2
0
Эх сурвалжийг харах

* simplified enum lookup table management by using tfplist instead of
an ad hoc dynamic array implementation

git-svn-id: trunk@31295 -

Jonas Maebe 10 жил өмнө
parent
commit
4c0807c596
1 өөрчлөгдсөн 59 нэмэгдсэн , 76 устгасан
  1. 59 76
      compiler/ncgrtti.pas

+ 59 - 76
compiler/ncgrtti.pas

@@ -1156,6 +1156,36 @@ implementation
         end;
         end;
       end;
       end;
 
 
+
+    function enumsym_compare_name(item1, item2: pointer): Integer;
+      var
+        enum1: tenumsym absolute item1;
+        enum2: tenumsym absolute item2;
+      begin
+        if enum1=enum2 then
+          result:=0
+        else if enum1.name>enum2.name then
+          result:=1
+        else
+          { there can't be equal names, identifiers are unique }
+          result:=-1;
+      end;
+
+
+    function enumsym_compare_value(item1, item2: pointer): Integer;
+      var
+        enum1: tenumsym absolute item1;
+        enum2: tenumsym absolute item2;
+      begin
+        if enum1.value>enum2.value then
+          result:=1
+        else if enum1.value<enum2.value then
+          result:=-1
+        else
+          result:=0;
+      end;
+
+
     procedure TRTTIWriter.write_rtti_extrasyms(def:Tdef;rt:Trttitype;mainrtti:Tasmsymbol);
     procedure TRTTIWriter.write_rtti_extrasyms(def:Tdef;rt:Trttitype;mainrtti:Tasmsymbol);
 
 
         type Penumsym = ^Tenumsym;
         type Penumsym = ^Tenumsym;
@@ -1163,22 +1193,24 @@ implementation
         { Writes a helper table for accelerated conversion of ordinal enum values to strings.
         { Writes a helper table for accelerated conversion of ordinal enum values to strings.
           If you change something in this method, make sure to adapt the corresponding code
           If you change something in this method, make sure to adapt the corresponding code
           in sstrings.inc. }
           in sstrings.inc. }
-        procedure enumdef_rtti_ord2stringindex(rttidef: trecorddef; const sym_count:longint; {const offsets:plongint;} const syms:Penumsym{; const st:longint});
+        procedure enumdef_rtti_ord2stringindex(rttidef: trecorddef; const syms: tfplist);
 
 
         var rttilab:Tasmsymbol;
         var rttilab:Tasmsymbol;
             h,i,o,prev_value:longint;
             h,i,o,prev_value:longint;
             mode:(lookup,search); {Modify with care, ordinal value of enum is written.}
             mode:(lookup,search); {Modify with care, ordinal value of enum is written.}
             r:single;             {Must be real type because of integer overflow risk.}
             r:single;             {Must be real type because of integer overflow risk.}
             tcb: ttai_typedconstbuilder;
             tcb: ttai_typedconstbuilder;
+            sym_count: integer;
         begin
         begin
 
 
           {Decide wether a lookup array is size efficient.}
           {Decide wether a lookup array is size efficient.}
           mode:=lookup;
           mode:=lookup;
+          sym_count:=syms.count;
           if sym_count>0 then
           if sym_count>0 then
             begin
             begin
               i:=1;
               i:=1;
               r:=0;
               r:=0;
-              h:=syms[0].value; {Next expected enum value is min.}
+              h:=tenumsym(syms[0]).value; {Next expected enum value is min.}
               { set prev_value for the first iteration to a value that is
               { set prev_value for the first iteration to a value that is
                 different from the first one without risking overflow (it's used
                 different from the first one without risking overflow (it's used
                 to detect whether two enum values are the same) }
                 to detect whether two enum values are the same) }
@@ -1195,9 +1227,9 @@ implementation
                       break;
                       break;
                     end;
                     end;
                   {Calculate size of hole between values. Avoid integer overflows.}
                   {Calculate size of hole between values. Avoid integer overflows.}
-                  r:=r+(single(syms[i].value)-single(h))-1;
+                  r:=r+(single(tenumsym(syms[i]).value)-single(h))-1;
                   prev_value:=h;
                   prev_value:=h;
-                  h:=syms[i].value;
+                  h:=tenumsym(syms[i]).value;
                   inc(i);
                   inc(i);
                 end;
                 end;
               if r>sym_count then
               if r>sym_count then
@@ -1219,10 +1251,10 @@ implementation
             targetinfos[target_info.system]^.alignment.maxCrecordalign);
             targetinfos[target_info.system]^.alignment.maxCrecordalign);
           if mode=lookup then
           if mode=lookup then
             begin
             begin
-              o:=syms[0].value;  {Start with min value.}
+              o:=tenumsym(syms[0]).value;  {Start with min value.}
               for i:=0 to sym_count-1 do
               for i:=0 to sym_count-1 do
                 begin
                 begin
-                  while o<syms[i].value do
+                  while o<tenumsym(syms[i]).value do
                     begin
                     begin
                       tcb.emit_tai(Tai_const.create_pint(0),ptruinttype);
                       tcb.emit_tai(Tai_const.create_pint(0),ptruinttype);
                       inc(o);
                       inc(o);
@@ -1233,7 +1265,7 @@ implementation
                     ['size_start_rec',
                     ['size_start_rec',
                       'min_max_rec',
                       'min_max_rec',
                       'basetype_array_rec',
                       'basetype_array_rec',
-                      'enumname'+tostr(syms[i].symid)]
+                      'enumname'+tostr(tenumsym(syms[i]).symid)]
                   );
                   );
                   tcb.queue_emit_asmsym(mainrtti,rttidef);
                   tcb.queue_emit_asmsym(mainrtti,rttidef);
                 end;
                 end;
@@ -1246,13 +1278,13 @@ implementation
                 targetinfos[target_info.system]^.alignment.maxCrecordalign);
                 targetinfos[target_info.system]^.alignment.maxCrecordalign);
               for i:=0 to sym_count-1 do
               for i:=0 to sym_count-1 do
                 begin
                 begin
-                  tcb.emit_ord_const(syms[i].value,s32inttype);
+                  tcb.emit_ord_const(tenumsym(syms[i]).value,s32inttype);
                   tcb.queue_init(voidpointertype);
                   tcb.queue_init(voidpointertype);
                   tcb.queue_subscriptn_multiple_by_name(rttidef,
                   tcb.queue_subscriptn_multiple_by_name(rttidef,
                     ['size_start_rec',
                     ['size_start_rec',
                       'min_max_rec',
                       'min_max_rec',
                       'basetype_array_rec',
                       'basetype_array_rec',
-                      'enumname'+tostr(syms[i].symid)]
+                      'enumname'+tostr(tenumsym(syms[i]).symid)]
                   );
                   );
                   tcb.queue_emit_asmsym(mainrtti,rttidef);
                   tcb.queue_emit_asmsym(mainrtti,rttidef);
                 end;
                 end;
@@ -1266,10 +1298,11 @@ implementation
             tcb.free;
             tcb.free;
         end;
         end;
 
 
+
         { Writes a helper table for accelerated conversion of string to ordinal enum values.
         { Writes a helper table for accelerated conversion of string to ordinal enum values.
           If you change something in this method, make sure to adapt the corresponding code
           If you change something in this method, make sure to adapt the corresponding code
           in sstrings.inc. }
           in sstrings.inc. }
-        procedure enumdef_rtti_string2ordindex(rttidef: trecorddef; const sym_count:longint; {const offsets:plongint; } const syms:Penumsym {; const st:longint});
+        procedure enumdef_rtti_string2ordindex(rttidef: trecorddef; const syms: tfplist);
 
 
         var
         var
           tcb: ttai_typedconstbuilder;
           tcb: ttai_typedconstbuilder;
@@ -1283,21 +1316,21 @@ implementation
           tcb.begin_anonymous_record('',defaultpacking,reqalign,
           tcb.begin_anonymous_record('',defaultpacking,reqalign,
             targetinfos[target_info.system]^.alignment.recordalignmin,
             targetinfos[target_info.system]^.alignment.recordalignmin,
             targetinfos[target_info.system]^.alignment.maxCrecordalign);
             targetinfos[target_info.system]^.alignment.maxCrecordalign);
-          tcb.emit_ord_const(sym_count,s32inttype);
+          tcb.emit_ord_const(syms.count,s32inttype);
           { begin of "data" array in Tstring_to_ord }
           { begin of "data" array in Tstring_to_ord }
           tcb.begin_anonymous_record('',defaultpacking,reqalign,
           tcb.begin_anonymous_record('',defaultpacking,reqalign,
             targetinfos[target_info.system]^.alignment.recordalignmin,
             targetinfos[target_info.system]^.alignment.recordalignmin,
             targetinfos[target_info.system]^.alignment.maxCrecordalign);
             targetinfos[target_info.system]^.alignment.maxCrecordalign);
-          for i:=0 to sym_count-1 do
+          for i:=0 to syms.count-1 do
             begin
             begin
-              tcb.emit_ord_const(syms[i].value,s32inttype);
+              tcb.emit_ord_const(tenumsym(syms[i]).value,s32inttype);
               { alignment of pointer value handled by enclosing record already }
               { alignment of pointer value handled by enclosing record already }
               tcb.queue_init(voidpointertype);
               tcb.queue_init(voidpointertype);
               tcb.queue_subscriptn_multiple_by_name(rttidef,
               tcb.queue_subscriptn_multiple_by_name(rttidef,
                 ['size_start_rec',
                 ['size_start_rec',
                   'min_max_rec',
                   'min_max_rec',
                   'basetype_array_rec',
                   'basetype_array_rec',
-                  'enumname'+tostr(syms[i].SymId)]
+                  'enumname'+tostr(tenumsym(syms[i]).SymId)]
               );
               );
               tcb.queue_emit_asmsym(mainrtti,rttidef);
               tcb.queue_emit_asmsym(mainrtti,rttidef);
             end;
             end;
@@ -1311,16 +1344,14 @@ implementation
         procedure enumdef_rtti_extrasyms(def:Tenumdef);
         procedure enumdef_rtti_extrasyms(def:Tenumdef);
         var
         var
           t:Tenumsym;
           t:Tenumsym;
-          syms:Penumsym;
-          sym_count,sym_alloc:sizeuint;
+          syms:tfplist;
           h,i,p:longint;
           h,i,p:longint;
           rttitypesym: ttypesym;
           rttitypesym: ttypesym;
           rttidef: trecorddef;
           rttidef: trecorddef;
         begin
         begin
-          {Random access needed, put in array.}
-          getmem(syms,64*sizeof(Tenumsym));
-          sym_count:=0;
-          sym_alloc:=64;
+          { collect enumsyms belonging to this enum type (could be a subsection
+            in case of a subrange type) }
+          syms:=tfplist.create;
           for i := 0 to def.symtable.SymList.Count - 1 do
           for i := 0 to def.symtable.SymList.Count - 1 do
             begin
             begin
               t:=tenumsym(def.symtable.SymList[i]);
               t:=tenumsym(def.symtable.SymList[i]);
@@ -1329,68 +1360,20 @@ implementation
               else
               else
               if t.value>def.maxval then
               if t.value>def.maxval then
                 break;
                 break;
-              if sym_count>=sym_alloc then
-                begin
-                  reallocmem(syms,2*sym_alloc*sizeof(Tenumsym));
-                  sym_alloc:=sym_alloc*2;
-                end;
-              syms[sym_count]:=t;
-              inc(sym_count);
-            end;
-          {Sort the syms by enum name}
-          if sym_count>=2 then
-            begin
-              p:=1;
-              while 2*p<sym_count do
-                p:=2*p;
-              while p<>0 do
-                begin
-                  for h:=p to sym_count-1 do
-                    begin
-                      i:=h;
-                      t:=syms[i];
-                      repeat
-                        if syms[i-p].name<=t.name then
-                          break;
-                        syms[i]:=syms[i-p];
-                        dec(i,p);
-                      until i<p;
-                      syms[i]:=t;
-                    end;
-                  p:=p shr 1;
-                end;
+              syms.add(t);
             end;
             end;
+          { sort the syms by enum name }
+          syms.sort(@enumsym_compare_name);
           rttitypesym:=try_search_current_module_type(internaltypeprefixName[itp_rttidef]+def.rtti_mangledname(fullrtti));
           rttitypesym:=try_search_current_module_type(internaltypeprefixName[itp_rttidef]+def.rtti_mangledname(fullrtti));
           if not assigned(rttitypesym) or
           if not assigned(rttitypesym) or
              (ttypesym(rttitypesym).typedef.typ<>recorddef) then
              (ttypesym(rttitypesym).typedef.typ<>recorddef) then
             internalerror(2015071402);
             internalerror(2015071402);
           rttidef:=trecorddef(ttypesym(rttitypesym).typedef);
           rttidef:=trecorddef(ttypesym(rttitypesym).typedef);
-          enumdef_rtti_string2ordindex(rttidef,sym_count,syms);
-          { Sort the syms by enum value }
-          if sym_count>=2 then
-            begin
-              p:=1;
-              while 2*p<sym_count do
-                p:=2*p;
-              while p<>0 do
-                begin
-                  for h:=p to sym_count-1 do
-                    begin
-                      i:=h;
-                      t:=syms[i];
-                      repeat
-                        if syms[i-p].value<=t.value then
-                          break;
-                        syms[i]:=syms[i-p];
-                        dec(i,p);
-                      until i<p;
-                      syms[i]:=t;
-                    end;
-                  p:=p shr 1;
-                end;
-            end;
-          enumdef_rtti_ord2stringindex(rttidef,sym_count,syms);
-          freemem(syms);
+          enumdef_rtti_string2ordindex(rttidef,syms);
+          { sort the syms by enum value }
+          syms.sort(@enumsym_compare_value);
+          enumdef_rtti_ord2stringindex(rttidef,syms);
+          syms.free;
         end;
         end;