mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-20 11:09:42 +02:00
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:
parent
7f9dedec99
commit
a380da6204
@ -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;
|
||||
|
@ -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^));
|
||||
|
Loading…
Reference in New Issue
Block a user