Fixed conversion from string to enum value for 64 bit platforms requiring proper alignment (e.g. ppc64/linux)

* start of data entries (Tsorted_array record in fpc_shortstr_enum_intern) in string-to-ordinal helper table must be aligned to the maximum alignment required by the members, otherwise the actual and the expected layout do not match
* do not use magic constants (+1) in the code for calculating the address of the first Tsorted_array in the string-to-ordinal helper table
* fix wrong calculation of the start offset to the Tsorted_array in the rtti writer (although it came to the same result)
* refactored rtti writing code for enums: removed duplicate code

git-svn-id: trunk@16211 -
This commit is contained in:
tom_at_work 2010-10-23 20:19:32 +00:00
parent 7f9dedec99
commit a380da6204
2 changed files with 72 additions and 113 deletions

View File

@ -960,70 +960,36 @@ implementation
end;
procedure TRTTIWriter.write_rtti_extrasyms(def:Tdef;rt:Trttitype;mainrtti:Tasmsymbol);
type Penumsym = ^Tenumsym;
procedure enumdef_rtti_ord2stringindex(def:Tenumdef);
function enumdef_rtti_calcstringtablestart(const def : Tenumdef) : integer;
begin
result:=1;
if assigned(def.typesym) then
inc(result,length(def.typesym.realname)+1)
else
inc(result);
if (tf_requires_proper_alignment in target_info.flags) then
result:=align(result,sizeof(Tconstptruint));
inc(result);
if (tf_requires_proper_alignment in target_info.flags) then
result:=align(result,longint(def.size));
inc(result, sizeof(longint) * 2);
if (tf_requires_proper_alignment in target_info.flags) then
result:=align(result,sizeof(Tconstptruint));
inc(result, sizeof(pint));
end;
procedure enumdef_rtti_ord2stringindex(const sym_count:longint; const offsets:plongint; const syms:Penumsym; const st:longint);
var rttilab:Tasmsymbol;
t:Tenumsym;
syms:^Tenumsym;
offsets:^longint;
sym_count,sym_alloc:longint;
h,i,p,o,st:longint;
h,i,o:longint;
mode:(lookup,search); {Modify with care, ordinal value of enum is written.}
r:single; {Must be real type because of integer overflow risk.}
begin
{Random access needed, put in array.}
getmem(syms,64*sizeof(Tenumsym));
getmem(offsets,64*sizeof(longint));
sym_count:=0;
sym_alloc:=64;
st:=0;
for i := 0 to def.symtable.SymList.Count - 1 do
begin
t:=tenumsym(def.symtable.SymList[i]);
if t.value<def.minval then
continue
else
if t.value>def.maxval then
break;
if sym_count>=sym_alloc then
begin
reallocmem(syms,2*sym_alloc*sizeof(Tenumsym));
reallocmem(offsets,2*sym_alloc*sizeof(longint));
sym_alloc:=sym_alloc*2;
end;
syms[sym_count]:=t;
offsets[sym_count]:=st;
inc(sym_count);
st:=st+length(t.realname)+1;
end;
{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];
o:=offsets[i];
repeat
if syms[i-p].value<=t.value then
break;
syms[i]:=syms[i-p];
offsets[i]:=offsets[i-p];
dec(i,p);
until i<p;
syms[i]:=t;
offsets[i]:=o;
end;
p:=p shr 1;
end;
end;
{Decide wether a lookup array is size efficient.}
mode:=lookup;
if sym_count>0 then
@ -1041,18 +1007,6 @@ implementation
if r>sym_count then
mode:=search; {Don't waste more than 50% space.}
end;
{Calculate start of string table.}
st:=1;
if assigned(def.typesym) then
inc(st,length(def.typesym.realname)+1)
else
inc(st);
if (tf_requires_proper_alignment in target_info.flags) then
st:=align(st,sizeof(Tconstptruint));
inc(st);
if (tf_requires_proper_alignment in target_info.flags) then
st:=align(st,sizeof(Tconstptruint));
inc(st,8+sizeof(pint));
{ write rtti data }
with current_asmdata do
begin
@ -1092,19 +1046,45 @@ implementation
end;
asmlists[al_rtti].concat(Tai_symbol_end.create(rttilab));
end;
freemem(syms);
freemem(offsets);
end;
procedure enumdef_rtti_string2ordindex(def:Tenumdef);
procedure enumdef_rtti_string2ordindex(const sym_count:longint; const offsets:plongint; const syms:Penumsym; const st:longint);
var rttilab:Tasmsymbol;
t:Tenumsym;
syms:^Tenumsym;
offsets:^longint;
sym_count,sym_alloc:longint;
h,i,p,o,st:longint;
i:longint;
begin
{ write rtti data }
with current_asmdata do
begin
rttilab:=defineasmsymbol(Tstoreddef(def).rtti_mangledname(rt)+'_s2o',AB_GLOBAL,AT_DATA);
maybe_new_object_file(asmlists[al_rtti]);
new_section(asmlists[al_rtti],sec_rodata,rttilab.name,const_align(sizeof(pint)));
asmlists[al_rtti].concat(Tai_symbol.create_global(rttilab,0));
asmlists[al_rtti].concat(Tai_const.create_32bit(sym_count));
{ need to align the entry record according to the largest member }
if (tf_requires_proper_alignment in target_info.flags) then
current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
for i:=0 to sym_count-1 do
begin
if (tf_requires_proper_alignment in target_info.flags) then
current_asmdata.asmlists[al_rtti].concat(cai_align.Create(4));
asmlists[al_rtti].concat(Tai_const.create_32bit(syms[i].value));
if (tf_requires_proper_alignment in target_info.flags) then
current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
asmlists[al_rtti].concat(Tai_const.create_sym_offset(mainrtti,st+offsets[i]));
end;
asmlists[al_rtti].concat(Tai_symbol_end.create(rttilab));
end;
end;
procedure enumdef_rtti_extrasyms(def:Tenumdef);
var
t:Tenumsym;
syms:Penumsym;
sym_count,sym_alloc:longint;
offsets:^longint;
h,i,p,o,st:longint;
begin
{Random access needed, put in array.}
getmem(syms,64*sizeof(Tenumsym));
@ -1157,48 +1137,20 @@ implementation
p:=p shr 1;
end;
end;
{Calculate start of string table.}
st:=1;
if assigned(def.typesym) then
inc(st,length(def.typesym.realname)+1)
else
inc(st);
if (tf_requires_proper_alignment in target_info.flags) then
st:=align(st,sizeof(Tconstptruint));
inc(st);
if (tf_requires_proper_alignment in target_info.flags) then
st:=align(st,sizeof(Tconstptruint));
inc(st,8+sizeof(pint));
{ write rtti data }
with current_asmdata do
begin
rttilab:=defineasmsymbol(Tstoreddef(def).rtti_mangledname(rt)+'_s2o',AB_GLOBAL,AT_DATA);
maybe_new_object_file(asmlists[al_rtti]);
new_section(asmlists[al_rtti],sec_rodata,rttilab.name,const_align(sizeof(pint)));
asmlists[al_rtti].concat(Tai_symbol.create_global(rttilab,0));
asmlists[al_rtti].concat(Tai_const.create_32bit(sym_count));
for i:=0 to sym_count-1 do
begin
if (tf_requires_proper_alignment in target_info.flags) then
current_asmdata.asmlists[al_rtti].concat(cai_align.Create(4));
asmlists[al_rtti].concat(Tai_const.create_32bit(syms[i].value));
if (tf_requires_proper_alignment in target_info.flags) then
current_asmdata.asmlists[al_rtti].concat(cai_align.Create(sizeof(TConstPtrUInt)));
asmlists[al_rtti].concat(Tai_const.create_sym_offset(mainrtti,st+offsets[i]));
end;
asmlists[al_rtti].concat(Tai_symbol_end.create(rttilab));
end;
st:=enumdef_rtti_calcstringtablestart(def);
enumdef_rtti_string2ordindex(sym_count,offsets,syms,st);
enumdef_rtti_ord2stringindex(sym_count,offsets,syms,st);
freemem(syms);
freemem(offsets);
end;
begin
case def.typ of
enumdef:
if rt=fullrtti then
begin
enumdef_rtti_ord2stringindex(Tenumdef(def));
enumdef_rtti_string2ordindex(Tenumdef(def));
enumdef_rtti_extrasyms(Tenumdef(def));
end;
end;
end;

View File

@ -1243,11 +1243,18 @@ function fpc_val_enum_shortstr(str2ordindex:pointer;const s:shortstring;out code
string_compare:=length(s1)-length(s2);
end;
type Tsorted_array={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
type Psorted_array=^Tsorted_array;
Tsorted_array={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
o:longint;
s:Pstring;
end;
Pstring_to_ord=^Tstring_to_ord;
Tstring_to_ord={$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}packed{$endif}record
count:longint;
data:array[0..0] of Tsorted_array;
end;
var l,h,m:cardinal;
c:sizeint;
sorted_array:^Tsorted_array;
@ -1264,10 +1271,10 @@ begin
while (spaces<=length(s)) and (s[spaces]=' ') do
inc(spaces);
t:=upcase(copy(s,spaces,255));
sorted_array:=pointer(Pcardinal(str2ordindex)+1);
sorted_array:=pointer(@Pstring_to_ord(str2ordindex)^.data);
{Use a binary search to get the string.}
l:=1;
h:=Pcardinal(str2ordindex)^;
h:=Pstring_to_ord(str2ordindex)^.count;
repeat
m:=(l+h) div 2;
c:=string_compare(t,upcase(sorted_array[m-1].s^));