* simplified enum lookup table management by using tfplist instead of

an ad hoc dynamic array implementation

git-svn-id: trunk@31295 -
This commit is contained in:
Jonas Maebe 2015-08-06 18:34:31 +00:00
parent d9359ea4af
commit 4c0807c596

View File

@ -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; syms:tfplist;
sym_count,sym_alloc:sizeuint;
h,i,p:longint; h,i,p:longint;
rttitypesym: ttypesym; rttitypesym: ttypesym;
rttidef: trecorddef; rttidef: trecorddef;
begin begin
{Random access needed, put in array.} { collect enumsyms belonging to this enum type (could be a subsection
getmem(syms,64*sizeof(Tenumsym)); in case of a subrange type) }
sym_count:=0; syms:=tfplist.create;
sym_alloc:=64;
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 syms.add(t);
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;
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); enumdef_rtti_string2ordindex(rttidef,syms);
{ Sort the syms by enum value } { sort the syms by enum value }
if sym_count>=2 then syms.sort(@enumsym_compare_value);
begin enumdef_rtti_ord2stringindex(rttidef,syms);
p:=1; syms.free;
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);
end; end;