* 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:
Jonas Maebe 2009-09-27 13:43:56 +00:00
parent 9c0e066d25
commit ec8fee45fe
5 changed files with 72 additions and 18 deletions

View File

@ -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;

View File

@ -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

View File

@ -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}

View File

@ -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

View File

@ -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;