+ support for the gnu2 general-dynamic tls model on arm, use it instead of the gnu one as the gnu2 one can be relaxed (access optimizations by the linker)

+ support pic relocations in the internal assembler writer

git-svn-id: trunk@43128 -
This commit is contained in:
florian 2019-10-05 20:48:26 +00:00
parent abb9401011
commit 16163b74ec
10 changed files with 98 additions and 10 deletions

View File

@ -154,7 +154,8 @@ interface
{ ARM TLS code } { ARM TLS code }
aitconst_gottpoff, aitconst_gottpoff,
aitconst_tpoff, aitconst_tpoff,
aitconst_tlsgd aitconst_tlsgd,
aitconst_tlsdesc
); );
tairealconsttype = ( tairealconsttype = (
@ -2105,6 +2106,8 @@ implementation
result:=4; result:=4;
aitconst_tpoff: aitconst_tpoff:
result:=4; result:=4;
aitconst_tlsdesc:
result:=4;
else else
internalerror(200603253); internalerror(200603253);
end; end;

View File

@ -997,6 +997,11 @@ implementation
writer.AsmWrite(#9'.word'#9+tai_const(hp).sym.name+'(tlsgd)+(.-'+tai_const(hp).endsym.name+tostr_with_plus(tai_const(hp).symofs)+')'); writer.AsmWrite(#9'.word'#9+tai_const(hp).sym.name+'(tlsgd)+(.-'+tai_const(hp).endsym.name+tostr_with_plus(tai_const(hp).symofs)+')');
writer.Asmln; writer.Asmln;
end; end;
aitconst_tlsdesc:
begin
writer.AsmWrite(#9'.word'#9+tai_const(hp).sym.name+'(tlsdesc)+(.-'+tai_const(hp).endsym.name+tostr_with_plus(tai_const(hp).symofs)+')');
writer.Asmln;
end;
aitconst_tpoff: aitconst_tpoff:
begin begin
if assigned(tai_const(hp).endsym) or (tai_const(hp).symofs<>0) then if assigned(tai_const(hp).endsym) or (tai_const(hp).symofs<>0) then

View File

@ -1161,7 +1161,7 @@ implementation
if (hp2.typ=ait_const) and (tai_const(hp2).sym=tai_const(hp).sym) if (hp2.typ=ait_const) and (tai_const(hp2).sym=tai_const(hp).sym)
and (tai_const(hp2).value=tai_const(hp).value) and (tai(hp2.previous).typ=ait_label) and and (tai_const(hp2).value=tai_const(hp).value) and (tai(hp2.previous).typ=ait_label) and
{ gottpoff and tlsgd symbols are PC relative, so we cannot reuse them } { gottpoff and tlsgd symbols are PC relative, so we cannot reuse them }
(not(tai_const(hp2).consttype in [aitconst_gottpoff,aitconst_tlsgd])) then (not(tai_const(hp2).consttype in [aitconst_gottpoff,aitconst_tlsgd,aitconst_tlsdesc])) then
begin begin
with taicpu(curtai).oper[curop]^.ref^ do with taicpu(curtai).oper[curop]^.ref^ do
begin begin
@ -3051,13 +3051,23 @@ implementation
begin begin
currsym:=objdata.symbolref(oper[0]^.ref^.symbol); currsym:=objdata.symbolref(oper[0]^.ref^.symbol);
bytes:=bytes or (((oper[0]^.ref^.offset-8) shr 2) and $ffffff); { tlscall is not relative so ignore the offset }
if oper[0]^.ref^.refaddr<>addr_tlscall then
bytes:=bytes or (((oper[0]^.ref^.offset-8) shr 2) and $ffffff);
if (opcode<>A_BL) or (condition<>C_None) then if (opcode<>A_BL) or (condition<>C_None) then
objdata.writereloc(aint(bytes),4,currsym,RELOC_RELATIVE_24) objdata.writereloc(aint(bytes),4,currsym,RELOC_RELATIVE_24)
else else
objdata.writereloc(aint(bytes),4,currsym,RELOC_RELATIVE_CALL); case oper[0]^.ref^.refaddr of
addr_pic:
objdata.writereloc(aint(bytes),4,currsym,RELOC_ARM_CALL);
addr_full:
objdata.writereloc(aint(bytes),4,currsym,RELOC_RELATIVE_CALL);
addr_tlscall:
objdata.writereloc(aint(bytes),4,currsym,RELOC_TLS_CALL);
else
Internalerror(2019092903);
end;
exit; exit;
end; end;
end; end;

View File

@ -194,7 +194,9 @@ unit agarmgas;
if offset<>0 then if offset<>0 then
s:=s+tostr_with_plus(offset); s:=s+tostr_with_plus(offset);
if refaddr=addr_pic then if refaddr=addr_pic then
s:=s+'(PLT)'; s:=s+'(PLT)'
else if refaddr=addr_tlscall then
s:=s+'(tlscall)';
end end
else else
begin begin

View File

@ -2495,6 +2495,8 @@ unit cgcpu;
current_procinfo.aktlocaldata.concat(tai_const.Create_rel_sym_offset(aitconst_gottpoff,ref.symbol,ref.relsymbol,ref.offset)) current_procinfo.aktlocaldata.concat(tai_const.Create_rel_sym_offset(aitconst_gottpoff,ref.symbol,ref.relsymbol,ref.offset))
else if ref.refaddr=addr_tlsgd then else if ref.refaddr=addr_tlsgd then
current_procinfo.aktlocaldata.concat(tai_const.Create_rel_sym_offset(aitconst_tlsgd,ref.symbol,ref.relsymbol,ref.offset)) current_procinfo.aktlocaldata.concat(tai_const.Create_rel_sym_offset(aitconst_tlsgd,ref.symbol,ref.relsymbol,ref.offset))
else if ref.refaddr=addr_tlsdesc then
current_procinfo.aktlocaldata.concat(tai_const.Create_rel_sym_offset(aitconst_tlsdesc,ref.symbol,ref.relsymbol,ref.offset))
else if ref.refaddr=addr_tpoff then else if ref.refaddr=addr_tpoff then
begin begin
if assigned(ref.relsymbol) or (ref.offset<>0) then if assigned(ref.relsymbol) or (ref.offset<>0) then
@ -5140,6 +5142,8 @@ unit cgcpu;
current_procinfo.aktlocaldata.concat(tai_const.Create_rel_sym_offset(aitconst_gottpoff,ref.symbol,ref.relsymbol,ref.offset)) current_procinfo.aktlocaldata.concat(tai_const.Create_rel_sym_offset(aitconst_gottpoff,ref.symbol,ref.relsymbol,ref.offset))
else if ref.refaddr=addr_tlsgd then else if ref.refaddr=addr_tlsgd then
current_procinfo.aktlocaldata.concat(tai_const.Create_rel_sym_offset(aitconst_tlsgd,ref.symbol,ref.relsymbol,ref.offset)) current_procinfo.aktlocaldata.concat(tai_const.Create_rel_sym_offset(aitconst_tlsgd,ref.symbol,ref.relsymbol,ref.offset))
else if ref.refaddr=addr_tlsdesc then
current_procinfo.aktlocaldata.concat(tai_const.Create_rel_sym_offset(aitconst_tlsdesc,ref.symbol,ref.relsymbol,ref.offset))
else if ref.refaddr=addr_tpoff then else if ref.refaddr=addr_tpoff then
begin begin
if assigned(ref.relsymbol) or (ref.offset<>0) then if assigned(ref.relsymbol) or (ref.offset<>0) then

View File

@ -342,6 +342,14 @@ implementation
result:=R_ARM_TLS_LE32 result:=R_ARM_TLS_LE32
else else
Internalerror(2019092901); Internalerror(2019092901);
RELOC_TLSGD:
result:=R_ARM_TLS_GD32;
RELOC_TLSDESC:
result:=R_ARM_TLS_GOTDESC;
RELOC_TLS_CALL:
result:=R_ARM_TLS_CALL;
RELOC_ARM_CALL:
result:=R_ARM_CALL;
else else
InternalError(2012110602); InternalError(2012110602);
end; end;

View File

@ -41,7 +41,7 @@ implementation
uses uses
globals,verbose, globals,verbose,
cgbase,cgobj,cgutils, cgbase,cgobj,cgutils,
aasmdata, aasmdata,aasmcpu,
systems, systems,
symcpu,symdef, symcpu,symdef,
nld, nld,
@ -70,6 +70,7 @@ implementation
case current_settings.tlsmodel of case current_settings.tlsmodel of
tlsm_general_dynamic: tlsm_general_dynamic:
begin begin
{$ifdef use_tls_dialect_gnu}
current_asmdata.getjumplabel(l); current_asmdata.getjumplabel(l);
reference_reset_symbol(href,current_asmdata.RefAsmSymbol(gvs.mangledname,AT_TLS),-8,sizeof(AInt),[]); reference_reset_symbol(href,current_asmdata.RefAsmSymbol(gvs.mangledname,AT_TLS),-8,sizeof(AInt),[]);
href.refaddr:=addr_tlsgd; href.refaddr:=addr_tlsgd;
@ -79,12 +80,49 @@ implementation
cg.a_label(current_asmdata.CurrAsmList,l); cg.a_label(current_asmdata.CurrAsmList,l);
cg.getcpuregister(current_asmdata.CurrAsmList,NR_R0); cg.getcpuregister(current_asmdata.CurrAsmList,NR_R0);
cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_ADD,OS_ADDR,hregister,NR_PC,NR_R0); cg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_ADD,OS_ADDR,hregister,NR_PC,NR_R0);
cg.g_call(current_asmdata.CurrAsmList,'___tls_get_addr'); cg.g_call(current_asmdata.CurrAsmList,'__tls_get_addr');
cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_R0); cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_R0);
hregister:=cg.getaddressregister(current_asmdata.CurrAsmList); hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,NR_R0,hregister); cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,NR_R0,hregister);
reference_reset(location.reference,location.reference.alignment,location.reference.volatility); reference_reset(location.reference,location.reference.alignment,location.reference.volatility);
location.reference.base:=hregister; location.reference.base:=hregister;
{$else use_tls_dialect_gnu}
{ On arm, we use the gnu2 tls dialect. It has the advantage that it can be relaxed (optimized) by the linker,
this is not possible with the gnu tls dialect.
gnu2 is proposed and documented in
Glauber de Oliveira Costa, Alexandre Oliva: Speeding Up Thread-Local Storage Access in DynamicLibraries in the ARM platform, 2006.
Link: https://www.fsfla.org/~lxoliva/writeups/TLS/paper-lk2006.pdf
}
current_asmdata.getjumplabel(l);
reference_reset_symbol(href,current_asmdata.RefAsmSymbol(gvs.mangledname,AT_TLS),0,sizeof(AInt),[]);
href.refaddr:=addr_tlsdesc;
href.relsymbol:=l;
hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
cg.getcpuregister(current_asmdata.CurrAsmList,NR_R0);
cg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,href,NR_R0);
cg.a_label(current_asmdata.CurrAsmList,l);
{ we have to go the ugly way so we can set addr_tlscall }
cg.allocallcpuregisters(current_asmdata.CurrAsmList);
cg.a_call_name(current_asmdata.CurrAsmList,gvs.mangledname,false);
with taicpu(current_asmdata.CurrAsmList.Last) do
begin
if opcode<>A_BL then
Internalerror(2019092902);
oper[0]^.ref^.refaddr:=addr_tlscall;
end;
cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
cg.getcpuregister(current_asmdata.CurrAsmList,NR_R0);
cg.ungetcpuregister(current_asmdata.CurrAsmList,NR_R0);
hregister:=cg.getaddressregister(current_asmdata.CurrAsmList);
cg.a_load_reg_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,NR_R0,hregister);
reference_reset(location.reference,location.reference.alignment,location.reference.volatility);
location.reference.base:=current_procinfo.tlsoffset;
include(current_procinfo.flags,pi_needs_tls);
location.reference.index:=hregister;
{$endif use_tls_dialect_gnu}
handled:=true; handled:=true;
end; end;
tlsm_initial_exec: tlsm_initial_exec:

View File

@ -1764,7 +1764,7 @@ Implementation
begin begin
objsym:=Objdata.SymbolRef(tai_const(hp).sym); objsym:=Objdata.SymbolRef(tai_const(hp).sym);
objsymend:=Objdata.SymbolRef(tai_const(hp).endsym); objsymend:=Objdata.SymbolRef(tai_const(hp).endsym);
if Tai_const(hp).consttype in [aitconst_gottpoff,aitconst_tlsgd] then if Tai_const(hp).consttype in [aitconst_gottpoff,aitconst_tlsgd,aitconst_tlsdesc] then
begin begin
if objsymend.objsection<>ObjData.CurrObjSec then if objsymend.objsection<>ObjData.CurrObjSec then
Internalerror(2019092801); Internalerror(2019092801);
@ -1991,12 +1991,18 @@ Implementation
objsym:=Objdata.SymbolRef(tai_const(hp).sym); objsym:=Objdata.SymbolRef(tai_const(hp).sym);
objsymend:=Objdata.SymbolRef(tai_const(hp).endsym); objsymend:=Objdata.SymbolRef(tai_const(hp).endsym);
relative_reloc:=(objsym.objsection<>objsymend.objsection); relative_reloc:=(objsym.objsection<>objsymend.objsection);
if Tai_const(hp).consttype in [aitconst_gottpoff,aitconst_tlsgd] then if Tai_const(hp).consttype in [aitconst_gottpoff] then
begin begin
if objsymend.objsection<>ObjData.CurrObjSec then if objsymend.objsection<>ObjData.CurrObjSec then
Internalerror(2019092802); Internalerror(2019092802);
Tai_const(hp).value:=objsymend.address-ObjData.CurrObjSec.Size+Tai_const(hp).symofs; Tai_const(hp).value:=objsymend.address-ObjData.CurrObjSec.Size+Tai_const(hp).symofs;
end end
else if Tai_const(hp).consttype in [aitconst_tlsgd,aitconst_tlsdesc] then
begin
if objsymend.objsection<>ObjData.CurrObjSec then
Internalerror(2019092802);
Tai_const(hp).value:=ObjData.CurrObjSec.Size-objsymend.address+Tai_const(hp).symofs;
end
else if objsymend.objsection<>objsym.objsection then else if objsymend.objsection<>objsym.objsection then
begin begin
if (Tai_const(hp).consttype in [aitconst_uleb128bit,aitconst_sleb128bit]) or if (Tai_const(hp).consttype in [aitconst_uleb128bit,aitconst_sleb128bit]) or
@ -2066,6 +2072,13 @@ Implementation
ObjData.writereloc(Tai_const(hp).symofs,sizeof(longint),Objdata.SymbolRef(tai_const(hp).sym),RELOC_TPOFF); ObjData.writereloc(Tai_const(hp).symofs,sizeof(longint),Objdata.SymbolRef(tai_const(hp).sym),RELOC_TPOFF);
aitconst_tlsgd: aitconst_tlsgd:
ObjData.writereloc(Tai_const(hp).symofs,sizeof(longint),Objdata.SymbolRef(tai_const(hp).sym),RELOC_TLSGD); ObjData.writereloc(Tai_const(hp).symofs,sizeof(longint),Objdata.SymbolRef(tai_const(hp).sym),RELOC_TLSGD);
aitconst_tlsdesc:
begin
{ must be a relative symbol, thus value being valid }
if not(assigned(tai_const(hp).sym)) or not(assigned(tai_const(hp).endsym)) then
Internalerror(2019092904);
ObjData.writereloc(Tai_const(hp).value,sizeof(longint),Objdata.SymbolRef(tai_const(hp).sym),RELOC_TLSDESC);
end;
{$endif arm} {$endif arm}
aitconst_gotoff_symbol: aitconst_gotoff_symbol:
ObjData.writereloc(Tai_const(hp).symofs,sizeof(longint),Objdata.SymbolRef(tai_const(hp).sym),RELOC_GOTOFF); ObjData.writereloc(Tai_const(hp).symofs,sizeof(longint),Objdata.SymbolRef(tai_const(hp).sym),RELOC_GOTOFF);

View File

@ -126,6 +126,8 @@ interface
,addr_gottpoff ,addr_gottpoff
,addr_tpoff ,addr_tpoff
,addr_tlsgd ,addr_tlsgd
,addr_tlsdesc
,addr_tlscall
{$ENDIF} {$ENDIF}
{$IFDEF i386} {$IFDEF i386}
,addr_ntpoff ,addr_ntpoff

View File

@ -93,6 +93,9 @@ interface
RELOC_GOT32, RELOC_GOT32,
RELOC_TPOFF, RELOC_TPOFF,
RELOC_TLSGD, RELOC_TLSGD,
RELOC_TLSDESC,
RELOC_TLS_CALL,
RELOC_ARM_CALL,
{$endif arm} {$endif arm}
{ Relative relocation } { Relative relocation }
RELOC_RELATIVE, RELOC_RELATIVE,