mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-13 00:09:32 +02:00
* do not create a global symbol in the middle of ansi/unicodestring
constants on Darwin, because its linker uses global symbols as delimiters of subsections for dead code stripping. This was previously solved by never making any ansistring constants smart linkable, which is now solved git-svn-id: trunk@21328 -
This commit is contained in:
parent
7ae1db2e01
commit
8282d6e37a
@ -28,11 +28,19 @@ interface
|
||||
uses
|
||||
globtype,
|
||||
aasmbase,
|
||||
aasmdata;
|
||||
aasmdata,
|
||||
symconst;
|
||||
|
||||
type
|
||||
tasmlabofs = record
|
||||
lab: tasmlabel;
|
||||
ofs: pint;
|
||||
end;
|
||||
|
||||
function emit_ansistring_const(list:TAsmList;data:PChar;len:LongInt;encoding:tstringencoding;NewSection:Boolean=True):TAsmLabel;
|
||||
function emit_unicodestring_const(list:TAsmList;data:Pointer;encoding:tstringencoding;Winlike:Boolean):TAsmLabel;
|
||||
function emit_ansistring_const(list:TAsmList;data:PChar;len:LongInt;encoding:tstringencoding;NewSection:Boolean=True):tasmlabofs;
|
||||
function emit_unicodestring_const(list:TAsmList;data:Pointer;encoding:tstringencoding;Winlike:Boolean):tasmlabofs;
|
||||
|
||||
function get_string_symofs(typ: tstringtype; winlikewidestring: boolean): pint;
|
||||
|
||||
|
||||
implementation
|
||||
@ -45,35 +53,40 @@ uses
|
||||
widestr,
|
||||
symdef;
|
||||
|
||||
function emit_ansistring_const(list:TAsmList;data:PChar;len:LongInt;encoding:tstringencoding;NewSection:Boolean): TAsmLabel;
|
||||
function emit_ansistring_const(list:TAsmList;data:PChar;len:LongInt;encoding:tstringencoding;NewSection:Boolean): tasmlabofs;
|
||||
var
|
||||
referencelab: TAsmLabel;
|
||||
s: PChar;
|
||||
begin
|
||||
current_asmdata.getdatalabel(result);
|
||||
current_asmdata.getdatalabel(result.lab);
|
||||
result.ofs:=0;
|
||||
if NewSection then
|
||||
new_section(list,sec_rodata,result.name,const_align(sizeof(pint)));
|
||||
referencelab := nil;
|
||||
new_section(list,sec_rodata,result.lab.name,const_align(sizeof(pint)));
|
||||
{ put label before header on Darwin, because there the linker considers
|
||||
a global symbol to be the start of a new subsection }
|
||||
if target_info.system in systems_darwin then
|
||||
begin
|
||||
current_asmdata.getdatalabel(referencelab);
|
||||
list.concat(tai_label.create(referencelab));
|
||||
end;
|
||||
list.concat(tai_label.create(result.lab));
|
||||
list.concat(tai_const.create_16bit(encoding));
|
||||
inc(result.ofs,2);
|
||||
list.concat(tai_const.create_16bit(1));
|
||||
inc(result.ofs,2);
|
||||
{$ifdef cpu64bitaddr}
|
||||
{ dummy for alignment }
|
||||
list.concat(tai_const.create_32bit(0));
|
||||
inc(result.ofs,4);
|
||||
{$endif cpu64bitaddr}
|
||||
list.concat(tai_const.create_pint(-1));
|
||||
inc(result.ofs,sizeof(pint));
|
||||
list.concat(tai_const.create_pint(len));
|
||||
{ make sure the string doesn't get dead stripped if the header is referenced }
|
||||
if target_info.system in systems_darwin then
|
||||
list.concat(tai_directive.create(asd_reference,result.name));
|
||||
list.concat(tai_label.create(result));
|
||||
{ and vice versa }
|
||||
if target_info.system in systems_darwin then
|
||||
list.concat(tai_directive.create(asd_reference,referencelab.name));
|
||||
inc(result.ofs,sizeof(pint));
|
||||
if not(target_info.system in systems_darwin) then
|
||||
begin
|
||||
{ results in slightly more efficient code }
|
||||
list.concat(tai_label.create(result.lab));
|
||||
result.ofs:=0;
|
||||
end;
|
||||
{ sanity check }
|
||||
if result.ofs<>get_string_symofs(st_ansistring,false) then
|
||||
internalerror(2012051701);
|
||||
|
||||
getmem(s,len+1);
|
||||
move(data^,s^,len);
|
||||
@ -82,40 +95,51 @@ uses
|
||||
end;
|
||||
|
||||
|
||||
function emit_unicodestring_const(list:TAsmList;data:Pointer;encoding:tstringencoding;Winlike:Boolean):TAsmLabel;
|
||||
function emit_unicodestring_const(list:TAsmList;data:Pointer;encoding:tstringencoding;Winlike:Boolean):tasmlabofs;
|
||||
var
|
||||
referencelab: TAsmLabel;
|
||||
i, strlength: SizeInt;
|
||||
begin
|
||||
current_asmdata.getdatalabel(result);
|
||||
new_section(list,sec_rodata,result.name,const_align(sizeof(pint)));
|
||||
referencelab := nil;
|
||||
if target_info.system in systems_darwin then
|
||||
begin
|
||||
current_asmdata.getdatalabel(referencelab);
|
||||
list.concat(tai_label.create(referencelab));
|
||||
end;
|
||||
current_asmdata.getdatalabel(result.lab);
|
||||
result.ofs:=0;
|
||||
new_section(list,sec_rodata,result.lab.name,const_align(sizeof(pint)));
|
||||
strlength := getlengthwidestring(pcompilerwidestring(data));
|
||||
if Winlike then
|
||||
list.concat(Tai_const.Create_32bit(strlength*cwidechartype.size))
|
||||
begin
|
||||
list.concat(Tai_const.Create_32bit(strlength*cwidechartype.size));
|
||||
{ don't increase result.ofs, this is how Windows widestrings are
|
||||
defined by the OS: a pointer 4 bytes past the length of the
|
||||
string }
|
||||
list.concat(Tai_label.Create(result.lab));
|
||||
end
|
||||
else
|
||||
begin
|
||||
{ put label before header on Darwin, because there the linker considers
|
||||
a global symbol to be the start of a new subsection }
|
||||
if target_info.system in systems_darwin then
|
||||
list.concat(Tai_label.Create(result.lab));
|
||||
list.concat(tai_const.create_16bit(encoding));
|
||||
inc(result.ofs,2);
|
||||
list.concat(tai_const.create_16bit(2));
|
||||
inc(result.ofs,2);
|
||||
{$ifdef cpu64bitaddr}
|
||||
{ dummy for alignment }
|
||||
list.concat(Tai_const.Create_32bit(0));
|
||||
inc(result.ofs,4);
|
||||
{$endif cpu64bitaddr}
|
||||
list.concat(Tai_const.Create_pint(-1));
|
||||
inc(result.ofs,sizeof(pint));
|
||||
list.concat(Tai_const.Create_pint(strlength));
|
||||
inc(result.ofs,sizeof(pint));
|
||||
if not(target_info.system in systems_darwin) then
|
||||
begin
|
||||
{ results in slightly more efficient code }
|
||||
list.concat(tai_label.create(result.lab));
|
||||
result.ofs:=0;
|
||||
end;
|
||||
{ sanity check }
|
||||
if result.ofs<>get_string_symofs(st_unicodestring,false) then
|
||||
internalerror(2012051702);
|
||||
end;
|
||||
{ make sure the string doesn't get dead stripped if the header is referenced }
|
||||
if (target_info.system in systems_darwin) then
|
||||
list.concat(tai_directive.create(asd_reference,result.name));
|
||||
list.concat(Tai_label.Create(result));
|
||||
{ ... and vice versa }
|
||||
if (target_info.system in systems_darwin) then
|
||||
list.concat(tai_directive.create(asd_reference,referencelab.name));
|
||||
if cwidechartype.size = 2 then
|
||||
begin
|
||||
for i:=0 to strlength-1 do
|
||||
@ -128,4 +152,39 @@ uses
|
||||
end;
|
||||
|
||||
|
||||
function get_string_symofs(typ: tstringtype; winlikewidestring: boolean): pint;
|
||||
const
|
||||
ansistring_header_size =
|
||||
{ encoding }
|
||||
2 +
|
||||
{ elesize }
|
||||
2 +
|
||||
{$ifdef cpu64bitaddr}
|
||||
{ alignment }
|
||||
4 +
|
||||
{$endif cpu64bitaddr}
|
||||
{ reference count }
|
||||
sizeof(pint) +
|
||||
{ length }
|
||||
sizeof(pint);
|
||||
unicodestring_header_size = ansistring_header_size;
|
||||
begin
|
||||
if not(target_info.system in systems_darwin) then
|
||||
result:=0
|
||||
else case typ of
|
||||
st_ansistring:
|
||||
result:=ansistring_header_size;
|
||||
st_unicodestring:
|
||||
result:=unicodestring_header_size;
|
||||
st_widestring:
|
||||
if winlikewidestring then
|
||||
result:=0
|
||||
else
|
||||
result:=unicodestring_header_size;
|
||||
else
|
||||
result:=0;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
end.
|
||||
|
@ -133,7 +133,7 @@ uses
|
||||
procedure Tresourcestrings.CreateResourceStringData;
|
||||
Var
|
||||
namelab,
|
||||
valuelab : tasmlabel;
|
||||
valuelab : tasmlabofs;
|
||||
resstrlab : tasmsymbol;
|
||||
endsymlab : tasmsymbol;
|
||||
R : TResourceStringItem;
|
||||
@ -151,7 +151,7 @@ uses
|
||||
|
||||
{ Write unitname entry }
|
||||
namelab:=emit_ansistring_const(current_asmdata.asmlists[al_const],@current_module.localsymtable.name^[1],length(current_module.localsymtable.name^),getansistringcodepage,False);
|
||||
current_asmdata.asmlists[al_resourcestrings].concat(tai_const.create_sym(namelab));
|
||||
current_asmdata.asmlists[al_resourcestrings].concat(tai_const.Create_sym_offset(namelab.lab,namelab.ofs));
|
||||
current_asmdata.asmlists[al_resourcestrings].concat(tai_const.create_sym(nil));
|
||||
current_asmdata.asmlists[al_resourcestrings].concat(tai_const.create_sym(nil));
|
||||
current_asmdata.asmlists[al_resourcestrings].concat(tai_const.create_32bit(0));
|
||||
@ -168,7 +168,10 @@ uses
|
||||
if assigned(R.value) and (R.len<>0) then
|
||||
valuelab:=emit_ansistring_const(current_asmdata.asmlists[al_const],R.Value,R.Len,getansistringcodepage,False)
|
||||
else
|
||||
valuelab:=nil;
|
||||
begin
|
||||
valuelab.lab:=nil;
|
||||
valuelab.ofs:=0;
|
||||
end;
|
||||
{ Append the name as a ansistring. }
|
||||
current_asmdata.asmlists[al_const].concat(cai_align.Create(const_align(sizeof(pint))));
|
||||
namelab:=emit_ansistring_const(current_asmdata.asmlists[al_const],@R.Name[1],length(R.name),getansistringcodepage,False);
|
||||
@ -185,9 +188,9 @@ uses
|
||||
new_section(current_asmdata.asmlists[al_resourcestrings],sec_data,make_mangledname('RESSTR',current_module.localsymtable,'2_'+r.name),sizeof(pint));
|
||||
resstrlab:=current_asmdata.DefineAsmSymbol(make_mangledname('RESSTR',R.Sym.owner,R.Sym.name),AB_GLOBAL,AT_DATA);
|
||||
current_asmdata.asmlists[al_resourcestrings].concat(tai_symbol.Create_global(resstrlab,0));
|
||||
current_asmdata.asmlists[al_resourcestrings].concat(tai_const.create_sym(namelab));
|
||||
current_asmdata.asmlists[al_resourcestrings].concat(tai_const.create_sym(valuelab));
|
||||
current_asmdata.asmlists[al_resourcestrings].concat(tai_const.create_sym(valuelab));
|
||||
current_asmdata.asmlists[al_resourcestrings].concat(tai_const.Create_sym_offset(namelab.lab,namelab.ofs));
|
||||
current_asmdata.asmlists[al_resourcestrings].concat(tai_const.Create_sym_offset(valuelab.lab,valuelab.ofs));
|
||||
current_asmdata.asmlists[al_resourcestrings].concat(tai_const.Create_sym_offset(valuelab.lab,valuelab.ofs));
|
||||
current_asmdata.asmlists[al_resourcestrings].concat(tai_const.create_32bit(longint(R.Hash)));
|
||||
{$ifdef cpu64bitaddr}
|
||||
current_asmdata.asmlists[al_resourcestrings].concat(tai_const.create_32bit(0));
|
||||
|
@ -257,12 +257,13 @@ implementation
|
||||
|
||||
procedure tcgstringconstnode.pass_generate_code;
|
||||
var
|
||||
lastlabel: tasmlabel;
|
||||
lastlabel: tasmlabofs;
|
||||
pc: pchar;
|
||||
l: longint;
|
||||
href: treference;
|
||||
pool: THashSet;
|
||||
entry: PHashSetItem;
|
||||
winlikewidestring: boolean;
|
||||
|
||||
const
|
||||
PoolMap: array[tconststringtype] of TConstPoolType = (
|
||||
@ -281,6 +282,7 @@ implementation
|
||||
location.value:=0;
|
||||
exit;
|
||||
end;
|
||||
winlikewidestring:=(cst_type=cst_widestring) and (tf_winlikewidestring in target_info.flags);
|
||||
{ const already used ? }
|
||||
if not assigned(lab_str) then
|
||||
begin
|
||||
@ -305,7 +307,13 @@ implementation
|
||||
if len=0 then
|
||||
InternalError(2008032301) { empty string should be handled above }
|
||||
else
|
||||
lastlabel:=emit_ansistring_const(current_asmdata.AsmLists[al_typedconsts],value_str,len,tstringdef(resultdef).encoding);
|
||||
begin
|
||||
lastlabel:=emit_ansistring_const(current_asmdata.AsmLists[al_typedconsts],value_str,len,tstringdef(resultdef).encoding);
|
||||
{ because we hardcode the offset below due to it
|
||||
not being stored in the hashset, check here }
|
||||
if lastlabel.ofs<>get_string_symofs(st_ansistring,false) then
|
||||
internalerror(2012051703);
|
||||
end;
|
||||
end;
|
||||
cst_unicodestring,
|
||||
cst_widestring:
|
||||
@ -313,18 +321,24 @@ implementation
|
||||
if len=0 then
|
||||
InternalError(2008032302) { empty string should be handled above }
|
||||
else
|
||||
lastlabel := emit_unicodestring_const(current_asmdata.AsmLists[al_typedconsts],
|
||||
value_str,
|
||||
tstringdef(resultdef).encoding,
|
||||
(cst_type=cst_widestring) and (tf_winlikewidestring in target_info.flags));
|
||||
begin
|
||||
lastlabel := emit_unicodestring_const(current_asmdata.AsmLists[al_typedconsts],
|
||||
value_str,
|
||||
tstringdef(resultdef).encoding,
|
||||
winlikewidestring);
|
||||
{ because we hardcode the offset below due to it
|
||||
not being stored in the hashset, check here }
|
||||
if lastlabel.ofs<>get_string_symofs(tstringdef(resultdef).stringtype,winlikewidestring) then
|
||||
internalerror(2012051704);
|
||||
end;
|
||||
end;
|
||||
cst_shortstring:
|
||||
begin
|
||||
current_asmdata.getdatalabel(lastlabel);
|
||||
current_asmdata.getdatalabel(lastlabel.lab);
|
||||
maybe_new_object_file(current_asmdata.asmlists[al_typedconsts]);
|
||||
new_section(current_asmdata.asmlists[al_typedconsts],sec_rodata_norel,lastlabel.name,const_align(sizeof(pint)));
|
||||
new_section(current_asmdata.asmlists[al_typedconsts],sec_rodata_norel,lastlabel.lab.name,const_align(sizeof(pint)));
|
||||
|
||||
current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(lastlabel));
|
||||
current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(lastlabel.lab));
|
||||
{ truncate strings larger than 255 chars }
|
||||
if len>255 then
|
||||
l:=255
|
||||
@ -339,11 +353,11 @@ implementation
|
||||
end;
|
||||
cst_conststring:
|
||||
begin
|
||||
current_asmdata.getdatalabel(lastlabel);
|
||||
current_asmdata.getdatalabel(lastlabel.lab);
|
||||
maybe_new_object_file(current_asmdata.asmlists[al_typedconsts]);
|
||||
new_section(current_asmdata.asmlists[al_typedconsts],sec_rodata_norel,lastlabel.name,const_align(sizeof(pint)));
|
||||
new_section(current_asmdata.asmlists[al_typedconsts],sec_rodata_norel,lastlabel.lab.name,const_align(sizeof(pint)));
|
||||
|
||||
current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(lastlabel));
|
||||
current_asmdata.asmlists[al_typedconsts].concat(Tai_label.Create(lastlabel.lab));
|
||||
{ include terminating zero }
|
||||
getmem(pc,len+1);
|
||||
move(value_str^,pc[0],len);
|
||||
@ -351,14 +365,16 @@ implementation
|
||||
current_asmdata.asmlists[al_typedconsts].concat(Tai_string.Create_pchar(pc,len+1));
|
||||
end;
|
||||
end;
|
||||
lab_str:=lastlabel;
|
||||
entry^.Data:=lastlabel;
|
||||
lab_str:=lastlabel.lab;
|
||||
entry^.Data:=lastlabel.lab;
|
||||
end;
|
||||
end;
|
||||
if cst_type in [cst_ansistring, cst_widestring, cst_unicodestring] then
|
||||
begin
|
||||
location_reset(location, LOC_REGISTER, OS_ADDR);
|
||||
reference_reset_symbol(href, lab_str, 0, const_align(sizeof(pint)));
|
||||
reference_reset_symbol(href, lab_str,
|
||||
get_string_symofs(tstringdef(resultdef).stringtype,winlikewidestring),
|
||||
const_align(sizeof(pint)));
|
||||
location.register:=cg.getaddressregister(current_asmdata.CurrAsmList);
|
||||
cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,location.register);
|
||||
end
|
||||
|
@ -437,7 +437,7 @@ function get_next_varsym(def: tabstractrecorddef; const SymList:TFPHashObjectLis
|
||||
strlength : aint;
|
||||
strval : pchar;
|
||||
strch : char;
|
||||
ll : tasmlabel;
|
||||
ll : tasmlabofs;
|
||||
ca : pchar;
|
||||
winlike : boolean;
|
||||
hsym : tconstsym;
|
||||
@ -533,21 +533,27 @@ function get_next_varsym(def: tabstractrecorddef; const SymList:TFPHashObjectLis
|
||||
begin
|
||||
{ an empty ansi string is nil! }
|
||||
if (strlength=0) then
|
||||
ll := nil
|
||||
begin
|
||||
ll.lab:=nil;
|
||||
ll.ofs:=0;
|
||||
end
|
||||
else
|
||||
ll := emit_ansistring_const(current_asmdata.asmlists[al_const],strval,strlength,def.encoding);
|
||||
list.concat(Tai_const.Create_sym(ll));
|
||||
ll:=emit_ansistring_const(current_asmdata.asmlists[al_const],strval,strlength,def.encoding);
|
||||
list.concat(Tai_const.Create_sym_offset(ll.lab,ll.ofs));
|
||||
end;
|
||||
st_unicodestring,
|
||||
st_widestring:
|
||||
begin
|
||||
{ an empty wide/unicode string is nil! }
|
||||
if (strlength=0) then
|
||||
ll := nil
|
||||
begin
|
||||
ll.lab:=nil;
|
||||
ll.ofs:=0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
winlike := (def.stringtype=st_widestring) and (tf_winlikewidestring in target_info.flags);
|
||||
ll := emit_unicodestring_const(current_asmdata.asmlists[al_const],
|
||||
winlike:=(def.stringtype=st_widestring) and (tf_winlikewidestring in target_info.flags);
|
||||
ll:=emit_unicodestring_const(current_asmdata.asmlists[al_const],
|
||||
strval,
|
||||
def.encoding,
|
||||
winlike);
|
||||
@ -556,17 +562,20 @@ function get_next_varsym(def: tabstractrecorddef; const SymList:TFPHashObjectLis
|
||||
Local initialized vars are excluded because they are initialized
|
||||
at function entry instead. }
|
||||
if winlike and
|
||||
((tcsym.owner.symtablelevel <= main_program_level) or
|
||||
((tcsym.owner.symtablelevel<=main_program_level) or
|
||||
(current_old_block_type=bt_const)) then
|
||||
begin
|
||||
if ll.ofs<>0 then
|
||||
internalerror(2012051704);
|
||||
current_asmdata.WideInits.Concat(
|
||||
TTCInitItem.Create(tcsym, curoffset, ll)
|
||||
TTCInitItem.Create(tcsym,curoffset,ll.lab)
|
||||
);
|
||||
ll := nil;
|
||||
Include(tcsym.varoptions, vo_force_finalize);
|
||||
ll.lab:=nil;
|
||||
ll.ofs:=0;
|
||||
Include(tcsym.varoptions,vo_force_finalize);
|
||||
end;
|
||||
end;
|
||||
list.concat(Tai_const.Create_sym(ll));
|
||||
list.concat(Tai_const.Create_sym_offset(ll.lab,ll.ofs));
|
||||
end;
|
||||
else
|
||||
internalerror(200107081);
|
||||
|
Loading…
Reference in New Issue
Block a user