mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-06 02:08:01 +02:00
* do not access local data via the GOT on x86_64, because
a) it's unnecessary b) it's slower than "direct" RIP-relative accessing c) it's not supported on darwin/x86_64 in certain cases * never use absolute addressing on darwin/x86_64 (like on win64) * when not generating PIC, make sure that a_loadaddr_ref_reg on x86_64 also uses RIP-relative addressing for darwin/x86_64 and win64 git-svn-id: trunk@13760 -
This commit is contained in:
parent
9c0e066d25
commit
ec8fee45fe
@ -354,11 +354,18 @@ implementation
|
|||||||
*****************************************************************************}
|
*****************************************************************************}
|
||||||
|
|
||||||
constructor TAsmLabel.Createlocal(AList:TFPHashObjectList;nr:longint;ltyp:TAsmLabelType);
|
constructor TAsmLabel.Createlocal(AList:TFPHashObjectList;nr:longint;ltyp:TAsmLabelType);
|
||||||
|
var
|
||||||
|
asmtyp: TAsmsymtype;
|
||||||
begin
|
begin
|
||||||
if ltyp=alt_addr then
|
case ltyp of
|
||||||
inherited Create(AList,target_asm.labelprefix+asmlabeltypeprefix[ltyp]+tostr(nr),AB_LOCAL,AT_ADDR)
|
alt_addr:
|
||||||
|
asmtyp:=AT_ADDR;
|
||||||
|
alt_data:
|
||||||
|
asmtyp:=AT_DATA;
|
||||||
else
|
else
|
||||||
inherited Create(AList,target_asm.labelprefix+asmlabeltypeprefix[ltyp]+tostr(nr),AB_LOCAL,AT_LABEL);
|
asmtyp:=AT_LABEL;
|
||||||
|
end;
|
||||||
|
inherited Create(AList,target_asm.labelprefix+asmlabeltypeprefix[ltyp]+tostr(nr),AB_LOCAL,asmtyp);
|
||||||
labelnr:=nr;
|
labelnr:=nr;
|
||||||
labeltype:=ltyp;
|
labeltype:=ltyp;
|
||||||
is_set:=false;
|
is_set:=false;
|
||||||
|
@ -68,7 +68,8 @@ interface
|
|||||||
trefaddr = (
|
trefaddr = (
|
||||||
addr_no,
|
addr_no,
|
||||||
addr_full,
|
addr_full,
|
||||||
addr_pic
|
addr_pic,
|
||||||
|
addr_pic_no_got
|
||||||
{$IF defined(POWERPC) or defined(POWERPC64) or defined(SPARC)}
|
{$IF defined(POWERPC) or defined(POWERPC64) or defined(SPARC)}
|
||||||
,
|
,
|
||||||
addr_low, // bits 48-63
|
addr_low, // bits 48-63
|
||||||
|
@ -931,7 +931,7 @@ implementation
|
|||||||
if (ref^.refaddr=addr_no)
|
if (ref^.refaddr=addr_no)
|
||||||
{$ifdef x86_64}
|
{$ifdef x86_64}
|
||||||
or (
|
or (
|
||||||
(ref^.refaddr=addr_pic) and
|
(ref^.refaddr in [addr_pic,addr_pic_no_got]) and
|
||||||
(ref^.base<>NR_NO)
|
(ref^.base<>NR_NO)
|
||||||
)
|
)
|
||||||
{$endif x86_64}
|
{$endif x86_64}
|
||||||
|
@ -162,7 +162,7 @@ interface
|
|||||||
top_reg :
|
top_reg :
|
||||||
owner.AsmWrite(gas_regname(o.reg));
|
owner.AsmWrite(gas_regname(o.reg));
|
||||||
top_ref :
|
top_ref :
|
||||||
if o.ref^.refaddr in [addr_no,addr_pic] then
|
if o.ref^.refaddr in [addr_no,addr_pic,addr_pic_no_got] then
|
||||||
WriteReference(o.ref^)
|
WriteReference(o.ref^)
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
|
@ -385,6 +385,33 @@ unit cgx86;
|
|||||||
if assigned(ref.symbol) and not((ref.symbol.bind=AB_LOCAL) and (ref.symbol.typ in [AT_LABEL,AT_FUNCTION])) then
|
if assigned(ref.symbol) and not((ref.symbol.bind=AB_LOCAL) and (ref.symbol.typ in [AT_LABEL,AT_FUNCTION])) then
|
||||||
begin
|
begin
|
||||||
if cs_create_pic in current_settings.moduleswitches then
|
if cs_create_pic in current_settings.moduleswitches then
|
||||||
|
begin
|
||||||
|
if (ref.symbol.bind=AB_LOCAL) and
|
||||||
|
(ref.symbol.typ=AT_DATA) then
|
||||||
|
begin
|
||||||
|
{ Local data symbols don't have to go via the GOT (and in
|
||||||
|
case of darwin must not in some cases), but they still
|
||||||
|
have to be addressed using PIC (RIP-relative).
|
||||||
|
}
|
||||||
|
{ unfortunately, RIP-based addresses don't support an index }
|
||||||
|
if (ref.base<>NR_NO) or
|
||||||
|
(ref.index<>NR_NO) then
|
||||||
|
begin
|
||||||
|
reference_reset_symbol(href,ref.symbol,0,sizeof(pint));
|
||||||
|
hreg:=getaddressregister(list);
|
||||||
|
href.refaddr:=addr_pic_no_got;
|
||||||
|
href.base:=NR_RIP;
|
||||||
|
list.concat(taicpu.op_ref_reg(A_LEA,S_Q,href,hreg));
|
||||||
|
ref.symbol:=nil;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
ref.refaddr:=addr_pic_no_got;
|
||||||
|
hreg:=NR_NO;
|
||||||
|
ref.base:=NR_RIP;
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
else
|
||||||
begin
|
begin
|
||||||
reference_reset_symbol(href,ref.symbol,0,sizeof(pint));
|
reference_reset_symbol(href,ref.symbol,0,sizeof(pint));
|
||||||
hreg:=getaddressregister(list);
|
hreg:=getaddressregister(list);
|
||||||
@ -393,6 +420,7 @@ unit cgx86;
|
|||||||
list.concat(taicpu.op_ref_reg(A_MOV,S_Q,href,hreg));
|
list.concat(taicpu.op_ref_reg(A_MOV,S_Q,href,hreg));
|
||||||
|
|
||||||
ref.symbol:=nil;
|
ref.symbol:=nil;
|
||||||
|
end;
|
||||||
|
|
||||||
if ref.base=NR_NO then
|
if ref.base=NR_NO then
|
||||||
ref.base:=hreg
|
ref.base:=hreg
|
||||||
@ -408,17 +436,21 @@ unit cgx86;
|
|||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
{ Always use RIP relative symbol addressing for Windows targets. }
|
{ Always use RIP relative symbol addressing for Windows and Darwin targets. }
|
||||||
if (target_info.system in system_all_windows) and (ref.base<>NR_RIP) then
|
if (target_info.system in (system_all_windows+[system_x86_64_darwin])) and (ref.base<>NR_RIP) then
|
||||||
begin
|
begin
|
||||||
if (ref.refaddr=addr_no) and (ref.base=NR_NO) and (ref.index=NR_NO) then
|
if (ref.refaddr=addr_no) and (ref.base=NR_NO) and (ref.index=NR_NO) then
|
||||||
|
begin
|
||||||
{ Set RIP relative addressing for simple symbol references }
|
{ Set RIP relative addressing for simple symbol references }
|
||||||
ref.base:=NR_RIP
|
ref.base:=NR_RIP;
|
||||||
|
ref.refaddr:=addr_pic_no_got
|
||||||
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
{ Use temp register to load calculated 64-bit symbol address for complex references }
|
{ Use temp register to load calculated 64-bit symbol address for complex references }
|
||||||
reference_reset_symbol(href,ref.symbol,0,sizeof(pint));
|
reference_reset_symbol(href,ref.symbol,0,sizeof(pint));
|
||||||
href.base:=NR_RIP;
|
href.base:=NR_RIP;
|
||||||
|
href.refaddr:=addr_pic_no_got;
|
||||||
hreg:=GetAddressRegister(list);
|
hreg:=GetAddressRegister(list);
|
||||||
list.concat(taicpu.op_ref_reg(A_LEA,S_Q,href,hreg));
|
list.concat(taicpu.op_ref_reg(A_LEA,S_Q,href,hreg));
|
||||||
ref.symbol:=nil;
|
ref.symbol:=nil;
|
||||||
@ -874,7 +906,11 @@ unit cgx86;
|
|||||||
list.concat(Taicpu.op_ref_reg(A_LEA,tcgsize2opsize[OS_ADDR],tmpref,r));
|
list.concat(Taicpu.op_ref_reg(A_LEA,tcgsize2opsize[OS_ADDR],tmpref,r));
|
||||||
end;
|
end;
|
||||||
end
|
end
|
||||||
else if (cs_create_pic in current_settings.moduleswitches) then
|
else if (cs_create_pic in current_settings.moduleswitches)
|
||||||
|
{$ifdef x86_64}
|
||||||
|
and not((ref.symbol.bind=AB_LOCAL) and (ref.symbol.typ=AT_DATA))
|
||||||
|
{$endif x86_64}
|
||||||
|
then
|
||||||
begin
|
begin
|
||||||
{$ifdef x86_64}
|
{$ifdef x86_64}
|
||||||
reference_reset_symbol(tmpref,ref.symbol,0,ref.alignment);
|
reference_reset_symbol(tmpref,ref.symbol,0,ref.alignment);
|
||||||
@ -891,6 +927,16 @@ unit cgx86;
|
|||||||
if offset<>0 then
|
if offset<>0 then
|
||||||
a_op_const_reg(list,OP_ADD,OS_ADDR,offset,r);
|
a_op_const_reg(list,OP_ADD,OS_ADDR,offset,r);
|
||||||
end
|
end
|
||||||
|
{$ifdef x86_64}
|
||||||
|
else if (target_info.system in (system_all_windows+[system_x86_64_darwin])) then
|
||||||
|
begin
|
||||||
|
{ Win64 and Darwin/x86_64 always require RIP-relative addressing }
|
||||||
|
tmpref:=ref;
|
||||||
|
tmpref.base:=NR_RIP;
|
||||||
|
tmpref.refaddr:=addr_pic_no_got;
|
||||||
|
list.concat(Taicpu.op_ref_reg(A_LEA,S_Q,tmpref,r));
|
||||||
|
end
|
||||||
|
{$endif x86_64}
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
tmpref:=ref;
|
tmpref:=ref;
|
||||||
|
Loading…
Reference in New Issue
Block a user