mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-24 22:49:19 +02:00
Extend the x86 targets by the ability to handle indirect symbols.
x86/cgx86.pas, tcgx86: + new method make_direct_ref() which is used to convert an indirect reference into a direct one (uses the boolean field in_make_direct_ref to avoid recursive calls) * make_simple_ref: call make_direct_ref() before anything else * a_loadaddr_ref_ref: call make_direct_ref() (the loading could probably be folded into the loadaddr method, but for now that is sufficent) i386/cgcpu.pas, tcg386: * a_loadaddr_ref_cgpara: call make_direct_ref(); the same remark as for a_loadaddr_ref_ref() applies here git-svn-id: trunk@33280 -
This commit is contained in:
parent
6722c611cf
commit
f297b00f5b
@ -221,9 +221,15 @@ unit cgcpu;
|
||||
var
|
||||
tmpreg : tregister;
|
||||
opsize : topsize;
|
||||
tmpref : treference;
|
||||
tmpref,dirref : treference;
|
||||
begin
|
||||
with r do
|
||||
dirref:=r;
|
||||
|
||||
{ this could probably done in a more optimized way, but for now this
|
||||
is sufficent }
|
||||
make_direct_ref(list,dirref);
|
||||
|
||||
with dirref do
|
||||
begin
|
||||
if use_push(cgpara) then
|
||||
begin
|
||||
@ -234,11 +240,11 @@ unit cgcpu;
|
||||
if assigned(symbol) then
|
||||
begin
|
||||
if (target_info.system in [system_i386_darwin,system_i386_iphonesim]) and
|
||||
((r.symbol.bind in [AB_EXTERNAL,AB_WEAK_EXTERNAL]) or
|
||||
((dirref.symbol.bind in [AB_EXTERNAL,AB_WEAK_EXTERNAL]) or
|
||||
(cs_create_pic in current_settings.moduleswitches)) then
|
||||
begin
|
||||
tmpreg:=getaddressregister(list);
|
||||
a_loadaddr_ref_reg(list,r,tmpreg);
|
||||
a_loadaddr_ref_reg(list,dirref,tmpreg);
|
||||
list.concat(taicpu.op_reg(A_PUSH,opsize,tmpreg));
|
||||
end
|
||||
else if cs_create_pic in current_settings.moduleswitches then
|
||||
@ -246,12 +252,12 @@ unit cgcpu;
|
||||
if offset<>0 then
|
||||
begin
|
||||
tmpreg:=getaddressregister(list);
|
||||
a_loadaddr_ref_reg(list,r,tmpreg);
|
||||
a_loadaddr_ref_reg(list,dirref,tmpreg);
|
||||
list.concat(taicpu.op_reg(A_PUSH,opsize,tmpreg));
|
||||
end
|
||||
else
|
||||
begin
|
||||
reference_reset_symbol(tmpref,r.symbol,0,r.alignment);
|
||||
reference_reset_symbol(tmpref,dirref.symbol,0,dirref.alignment);
|
||||
tmpref.refaddr:=addr_pic;
|
||||
tmpref.base:=current_procinfo.got;
|
||||
{$ifdef EXTDEBUG}
|
||||
@ -277,12 +283,12 @@ unit cgcpu;
|
||||
else
|
||||
begin
|
||||
tmpreg:=getaddressregister(list);
|
||||
a_loadaddr_ref_reg(list,r,tmpreg);
|
||||
a_loadaddr_ref_reg(list,dirref,tmpreg);
|
||||
list.concat(taicpu.op_reg(A_PUSH,opsize,tmpreg));
|
||||
end;
|
||||
end
|
||||
else
|
||||
inherited a_loadaddr_ref_cgpara(list,r,cgpara);
|
||||
inherited a_loadaddr_ref_cgpara(list,dirref,cgpara);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -126,11 +126,14 @@ unit cgx86;
|
||||
procedure g_overflowcheck(list: TAsmList; const l:tlocation;def:tdef);override;
|
||||
|
||||
procedure make_simple_ref(list:TAsmList;var ref: treference);
|
||||
procedure make_direct_ref(list:TAsmList;var ref: treference);
|
||||
|
||||
function get_darwin_call_stub(const s: string; weak: boolean): tasmsymbol;
|
||||
|
||||
procedure generate_leave(list : TAsmList);
|
||||
protected
|
||||
in_make_direct_ref : boolean;
|
||||
|
||||
procedure a_jmp_cond(list : TAsmList;cond : TOpCmp;l: tasmlabel);
|
||||
procedure check_register_size(size:tcgsize;reg:tregister);
|
||||
|
||||
@ -424,6 +427,9 @@ unit cgx86;
|
||||
if (ref.refaddr in [addr_pic,addr_pic_no_got]) then
|
||||
exit;
|
||||
|
||||
{ handle indirect symbols first }
|
||||
make_direct_ref(list,ref);
|
||||
|
||||
{$if defined(x86_64)}
|
||||
{ Only 32bit is allowed }
|
||||
{ Note that this isn't entirely correct: for RIP-relative targets/memory models,
|
||||
@ -648,6 +654,28 @@ unit cgx86;
|
||||
end;
|
||||
|
||||
|
||||
procedure tcgx86.make_direct_ref(list:tasmlist;var ref:treference);
|
||||
var
|
||||
href : treference;
|
||||
hreg : tregister;
|
||||
begin
|
||||
if in_make_direct_ref then
|
||||
exit;
|
||||
in_make_direct_ref:=true;
|
||||
if assigned(ref.symbol) and (ref.symbol.bind in asmsymbindindirect) then
|
||||
begin
|
||||
hreg:=getaddressregister(list);
|
||||
reference_reset_symbol(href,ref.symbol,0,sizeof(pint));
|
||||
a_op_ref_reg(list,OP_MOVE,OS_ADDR,href,hreg);
|
||||
if ref.base<>NR_NO then
|
||||
a_op_reg_reg(list,OP_ADD,OS_ADDR,ref.base,hreg);
|
||||
ref.symbol:=nil;
|
||||
ref.base:=hreg;
|
||||
end;
|
||||
in_make_direct_ref:=false;
|
||||
end;
|
||||
|
||||
|
||||
procedure tcgx86.floatloadops(t : tcgsize;var op : tasmop;var s : topsize);
|
||||
begin
|
||||
case t of
|
||||
@ -1012,31 +1040,38 @@ unit cgx86;
|
||||
|
||||
procedure tcgx86.a_loadaddr_ref_reg(list : TAsmList;const ref : treference;r : tregister);
|
||||
var
|
||||
tmpref : treference;
|
||||
dirref,tmpref : treference;
|
||||
hreg : tregister;
|
||||
begin
|
||||
with ref do
|
||||
dirref:=ref;
|
||||
|
||||
{ this could probably done in a more optimized way, but for now this
|
||||
is sufficent }
|
||||
make_direct_ref(list,dirref);
|
||||
|
||||
with dirref do
|
||||
begin
|
||||
if (base=NR_NO) and (index=NR_NO) then
|
||||
begin
|
||||
if assigned(ref.symbol) then
|
||||
if assigned(dirref.symbol) then
|
||||
begin
|
||||
if (target_info.system in [system_i386_darwin,system_i386_iphonesim]) and
|
||||
((ref.symbol.bind in [AB_EXTERNAL,AB_WEAK_EXTERNAL]) or
|
||||
((dirref.symbol.bind in [AB_EXTERNAL,AB_WEAK_EXTERNAL]) or
|
||||
(cs_create_pic in current_settings.moduleswitches)) then
|
||||
begin
|
||||
if (ref.symbol.bind in [AB_EXTERNAL,AB_WEAK_EXTERNAL]) or
|
||||
if (dirref.symbol.bind in [AB_EXTERNAL,AB_WEAK_EXTERNAL]) or
|
||||
((cs_create_pic in current_settings.moduleswitches) and
|
||||
(ref.symbol.bind in [AB_COMMON,AB_GLOBAL,AB_PRIVATE_EXTERN])) then
|
||||
(dirref.symbol.bind in [AB_COMMON,AB_GLOBAL,AB_PRIVATE_EXTERN])) then
|
||||
begin
|
||||
reference_reset_base(tmpref,
|
||||
g_indirect_sym_load(list,ref.symbol.name,asmsym2indsymflags(ref.symbol)),
|
||||
g_indirect_sym_load(list,dirref.symbol.name,asmsym2indsymflags(dirref.symbol)),
|
||||
offset,sizeof(pint));
|
||||
a_loadaddr_ref_reg(list,tmpref,r);
|
||||
end
|
||||
else
|
||||
begin
|
||||
include(current_procinfo.flags,pi_needs_got);
|
||||
reference_reset_base(tmpref,current_procinfo.got,offset,ref.alignment);
|
||||
reference_reset_base(tmpref,current_procinfo.got,offset,dirref.alignment);
|
||||
tmpref.symbol:=symbol;
|
||||
tmpref.relsymbol:=current_procinfo.CurrGOTLabel;
|
||||
list.concat(Taicpu.op_ref_reg(A_LEA,tcgsize2opsize[OS_ADDR],tmpref,r));
|
||||
@ -1044,17 +1079,17 @@ unit cgx86;
|
||||
end
|
||||
else if (cs_create_pic in current_settings.moduleswitches)
|
||||
{$ifdef x86_64}
|
||||
and not(ref.symbol.bind=AB_LOCAL)
|
||||
and not(dirref.symbol.bind=AB_LOCAL)
|
||||
{$endif x86_64}
|
||||
then
|
||||
begin
|
||||
{$ifdef x86_64}
|
||||
reference_reset_symbol(tmpref,ref.symbol,0,ref.alignment);
|
||||
reference_reset_symbol(tmpref,dirref.symbol,0,dirref.alignment);
|
||||
tmpref.refaddr:=addr_pic;
|
||||
tmpref.base:=NR_RIP;
|
||||
list.concat(taicpu.op_ref_reg(A_MOV,S_Q,tmpref,r));
|
||||
{$else x86_64}
|
||||
reference_reset_symbol(tmpref,ref.symbol,0,ref.alignment);
|
||||
reference_reset_symbol(tmpref,dirref.symbol,0,dirref.alignment);
|
||||
tmpref.refaddr:=addr_pic;
|
||||
tmpref.base:=current_procinfo.got;
|
||||
include(current_procinfo.flags,pi_needs_got);
|
||||
@ -1069,7 +1104,7 @@ unit cgx86;
|
||||
then
|
||||
begin
|
||||
{ Win64 and Darwin/x86_64 always require RIP-relative addressing }
|
||||
tmpref:=ref;
|
||||
tmpref:=dirref;
|
||||
tmpref.base:=NR_RIP;
|
||||
tmpref.refaddr:=addr_pic_no_got;
|
||||
list.concat(Taicpu.op_ref_reg(A_LEA,S_Q,tmpref,r));
|
||||
@ -1077,7 +1112,7 @@ unit cgx86;
|
||||
{$endif x86_64}
|
||||
else
|
||||
begin
|
||||
tmpref:=ref;
|
||||
tmpref:=dirref;
|
||||
tmpref.refaddr:=ADDR_FULL;
|
||||
list.concat(Taicpu.op_ref_reg(A_MOV,tcgsize2opsize[OS_ADDR],tmpref,r));
|
||||
end
|
||||
@ -1093,7 +1128,7 @@ unit cgx86;
|
||||
a_load_reg_reg(list,OS_ADDR,OS_ADDR,base,r)
|
||||
else
|
||||
begin
|
||||
tmpref:=ref;
|
||||
tmpref:=dirref;
|
||||
make_simple_ref(list,tmpref);
|
||||
list.concat(Taicpu.op_ref_reg(A_LEA,tcgsize2opsize[OS_ADDR],tmpref,r));
|
||||
end;
|
||||
@ -1113,7 +1148,7 @@ unit cgx86;
|
||||
system_i386_linux,system_i386_android:
|
||||
if segment=NR_GS then
|
||||
begin
|
||||
reference_reset_symbol(tmpref,current_asmdata.RefAsmSymbol('___fpc_threadvar_offset'),0,ref.alignment);
|
||||
reference_reset_symbol(tmpref,current_asmdata.RefAsmSymbol('___fpc_threadvar_offset'),0,dirref.alignment);
|
||||
tmpref.segment:=NR_GS;
|
||||
list.concat(Taicpu.op_ref_reg(A_ADD,tcgsize2opsize[OS_ADDR],tmpref,r));
|
||||
end
|
||||
|
Loading…
Reference in New Issue
Block a user