mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-15 02:30:48 +02:00
TOC handling: clean up
Also fix on 32 bits PowerPC
This commit is contained in:
parent
d42f577a3f
commit
629c1de460
@ -1234,7 +1234,7 @@ implementation
|
|||||||
between code fragments that use a different TOC (which has to be
|
between code fragments that use a different TOC (which has to be
|
||||||
executed when that "branch" returns). So we can't use tail call
|
executed when that "branch" returns). So we can't use tail call
|
||||||
branches to routines potentially using a different TOC there }
|
branches to routines potentially using a different TOC there }
|
||||||
if target_info.system in systems_ppc_toc then
|
if target_info.abi in abis_ppc_toc then
|
||||||
usehighlevelwrapper:=true
|
usehighlevelwrapper:=true
|
||||||
else
|
else
|
||||||
usehighlevelwrapper:=false;
|
usehighlevelwrapper:=false;
|
||||||
|
@ -911,9 +911,17 @@ const
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ save the CR if necessary ( !!! never done currently ) }
|
{ save current RTOC for restoration after calls if necessary }
|
||||||
{ still need to find out where this has to be done for SystemV
|
if (pi_do_call in current_procinfo.flags) and
|
||||||
a_reg_alloc(list,R_0);
|
(target_info.abi in abis_ppc_toc) then
|
||||||
|
begin
|
||||||
|
reference_reset_base(href,NR_STACK_POINTER_REG,get_rtoc_offset,ctempposinvalid,target_info.stackalign,[]);
|
||||||
|
a_load_reg_ref(list,OS_ADDR,OS_ADDR,NR_RTOC,href);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ save the CR if/when we ever start using caller-save portions of that
|
||||||
|
register}
|
||||||
|
{ a_reg_alloc(list,R_0);
|
||||||
list.concat(taicpu.op_reg_reg(A_MFSPR,R_0,R_CR);
|
list.concat(taicpu.op_reg_reg(A_MFSPR,R_0,R_CR);
|
||||||
list.concat(taicpu.op_reg_ref(A_STW,scratch_register,
|
list.concat(taicpu.op_reg_ref(A_STW,scratch_register,
|
||||||
new_reference(STACK_POINTER_REG,LA_CR)));
|
new_reference(STACK_POINTER_REG,LA_CR)));
|
||||||
@ -1306,6 +1314,14 @@ const
|
|||||||
a_reg_dealloc(list,href.index);
|
a_reg_dealloc(list,href.index);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ save current RTOC for restoration after calls if necessary }
|
||||||
|
if pi_do_call in current_procinfo.flags then
|
||||||
|
begin
|
||||||
|
reference_reset_base(href,NR_STACK_POINTER_REG,get_rtoc_offset,ctempposinvalid,target_info.stackalign,[]);
|
||||||
|
a_load_reg_ref(list,OS_ADDR,OS_ADDR,NR_RTOC,href);
|
||||||
|
end;
|
||||||
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure tcgppc.g_return_from_proc_mac(list : TAsmList;parasize : tcgint);
|
procedure tcgppc.g_return_from_proc_mac(list : TAsmList;parasize : tcgint);
|
||||||
|
@ -305,22 +305,6 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
function get_rtoc_offset: longint;
|
|
||||||
begin
|
|
||||||
result:=0;
|
|
||||||
case target_info.abi of
|
|
||||||
abi_powerpc_aix,
|
|
||||||
abi_powerpc_darwin:
|
|
||||||
result:=LA_RTOC_AIX;
|
|
||||||
abi_powerpc_elfv1:
|
|
||||||
result:=LA_RTOC_SYSV;
|
|
||||||
abi_powerpc_elfv2:
|
|
||||||
result:=LA_RTOC_ELFV2;
|
|
||||||
else
|
|
||||||
internalerror(2015021001);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ calling a procedure by address }
|
{ calling a procedure by address }
|
||||||
|
|
||||||
procedure tcgppc.a_call_reg(list: TAsmList; reg: tregister);
|
procedure tcgppc.a_call_reg(list: TAsmList; reg: tregister);
|
||||||
@ -330,40 +314,44 @@ var
|
|||||||
begin
|
begin
|
||||||
if (target_info.abi<>abi_powerpc_sysv) then
|
if (target_info.abi<>abi_powerpc_sysv) then
|
||||||
inherited a_call_reg(list,reg)
|
inherited a_call_reg(list,reg)
|
||||||
else if (not (cs_opt_size in current_settings.optimizerswitches)) then begin
|
else
|
||||||
tempreg := getintregister(list, OS_INT);
|
begin
|
||||||
{ load actual function entry (reg contains the reference to the function descriptor)
|
if (not (cs_opt_size in current_settings.optimizerswitches)) then
|
||||||
into tempreg }
|
begin
|
||||||
reference_reset_base(tmpref, reg, 0, ctempposinvalid, sizeof(pint), []);
|
tempreg := getintregister(list, OS_INT);
|
||||||
a_load_ref_reg(list, OS_ADDR, OS_ADDR, tmpref, tempreg);
|
{ load actual function entry (reg contains the reference to the function descriptor)
|
||||||
|
into tempreg }
|
||||||
|
reference_reset_base(tmpref, reg, 0, ctempposinvalid, sizeof(pint), []);
|
||||||
|
a_load_ref_reg(list, OS_ADDR, OS_ADDR, tmpref, tempreg);
|
||||||
|
|
||||||
{ move actual function pointer to CTR register }
|
{ move actual function pointer to CTR register }
|
||||||
list.concat(taicpu.op_reg(A_MTCTR, tempreg));
|
list.concat(taicpu.op_reg(A_MTCTR, tempreg));
|
||||||
|
|
||||||
{ load new TOC pointer from function descriptor into RTOC register }
|
{ load new TOC pointer from function descriptor into RTOC register }
|
||||||
reference_reset_base(tmpref, reg, tcgsize2size[OS_ADDR], ctempposinvalid, 8, []);
|
reference_reset_base(tmpref, reg, tcgsize2size[OS_ADDR], ctempposinvalid, 8, []);
|
||||||
|
a_load_ref_reg(list, OS_ADDR, OS_ADDR, tmpref, NR_RTOC);
|
||||||
|
|
||||||
|
{ load new environment pointer from function descriptor into R11 register }
|
||||||
|
reference_reset_base(tmpref, reg, 2*tcgsize2size[OS_ADDR], ctempposinvalid, 8, []);
|
||||||
|
a_reg_alloc(list, NR_R11);
|
||||||
|
a_load_ref_reg(list, OS_ADDR, OS_ADDR, tmpref, NR_R11);
|
||||||
|
{ call function }
|
||||||
|
list.concat(taicpu.op_none(A_BCTRL));
|
||||||
|
a_reg_dealloc(list, NR_R11);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
{ call ptrgl helper routine which expects the pointer to the function descriptor
|
||||||
|
in R11 }
|
||||||
|
a_reg_alloc(list, NR_R11);
|
||||||
|
a_load_reg_reg(list, OS_ADDR, OS_ADDR, reg, NR_R11);
|
||||||
|
a_call_name_direct(list, A_BL, '.ptrgl', false, false, false);
|
||||||
|
a_reg_dealloc(list, NR_R11);
|
||||||
|
end;
|
||||||
|
{ we need to load the old RTOC from stackframe because we changed it}
|
||||||
|
reference_reset_base(tmpref, NR_STACK_POINTER_REG, get_rtoc_offset, ctempposinvalid, 8, []);
|
||||||
a_load_ref_reg(list, OS_ADDR, OS_ADDR, tmpref, NR_RTOC);
|
a_load_ref_reg(list, OS_ADDR, OS_ADDR, tmpref, NR_RTOC);
|
||||||
|
|
||||||
{ load new environment pointer from function descriptor into R11 register }
|
|
||||||
reference_reset_base(tmpref, reg, 2*tcgsize2size[OS_ADDR], ctempposinvalid, 8, []);
|
|
||||||
a_reg_alloc(list, NR_R11);
|
|
||||||
a_load_ref_reg(list, OS_ADDR, OS_ADDR, tmpref, NR_R11);
|
|
||||||
{ call function }
|
|
||||||
list.concat(taicpu.op_none(A_BCTRL));
|
|
||||||
a_reg_dealloc(list, NR_R11);
|
|
||||||
end else begin
|
|
||||||
{ call ptrgl helper routine which expects the pointer to the function descriptor
|
|
||||||
in R11 }
|
|
||||||
a_reg_alloc(list, NR_R11);
|
|
||||||
a_load_reg_reg(list, OS_ADDR, OS_ADDR, reg, NR_R11);
|
|
||||||
a_call_name_direct(list, A_BL, '.ptrgl', false, false, false);
|
|
||||||
a_reg_dealloc(list, NR_R11);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ we need to load the old RTOC from stackframe because we changed it}
|
|
||||||
reference_reset_base(tmpref, NR_STACK_POINTER_REG, get_rtoc_offset, ctempposinvalid, 8, []);
|
|
||||||
a_load_ref_reg(list, OS_ADDR, OS_ADDR, tmpref, NR_RTOC);
|
|
||||||
|
|
||||||
include(current_procinfo.flags, pi_do_call);
|
include(current_procinfo.flags, pi_do_call);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -1270,7 +1258,8 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
{ save current RTOC for restoration after calls if necessary }
|
{ save current RTOC for restoration after calls if necessary }
|
||||||
if pi_do_call in current_procinfo.flags then
|
if (pi_do_call in current_procinfo.flags) and
|
||||||
|
(target_info.abi in abis_ppc_toc) then
|
||||||
begin
|
begin
|
||||||
reference_reset_base(href,NR_STACK_POINTER_REG,get_rtoc_offset,ctempposinvalid,target_info.stackalign,[]);
|
reference_reset_base(href,NR_STACK_POINTER_REG,get_rtoc_offset,ctempposinvalid,target_info.stackalign,[]);
|
||||||
a_load_reg_ref(list,OS_ADDR,OS_ADDR,NR_RTOC,href);
|
a_load_reg_ref(list,OS_ADDR,OS_ADDR,NR_RTOC,href);
|
||||||
|
@ -89,6 +89,8 @@ unit cgppc;
|
|||||||
procedure a_jmp(list: TAsmList; op: tasmop;
|
procedure a_jmp(list: TAsmList; op: tasmop;
|
||||||
c: tasmcondflag; crval: longint; l: tasmlabel);
|
c: tasmcondflag; crval: longint; l: tasmlabel);
|
||||||
|
|
||||||
|
function get_rtoc_offset: longint;
|
||||||
|
|
||||||
function save_lr_in_prologue: boolean;
|
function save_lr_in_prologue: boolean;
|
||||||
|
|
||||||
function load_got_symbol(list : TAsmList; const symbol : string; const flags: tindsymflags) : tregister;
|
function load_got_symbol(list : TAsmList; const symbol : string; const flags: tindsymflags) : tregister;
|
||||||
@ -123,7 +125,6 @@ unit cgppc;
|
|||||||
C_LT,C_GE,C_LE,C_NE,C_LE,C_LT,C_GE,C_GT);
|
C_LT,C_GE,C_LE,C_NE,C_LE,C_LT,C_GE,C_GT);
|
||||||
TocSecBaseName = 'toc_table';
|
TocSecBaseName = 'toc_table';
|
||||||
|
|
||||||
|
|
||||||
{$ifdef extdebug}
|
{$ifdef extdebug}
|
||||||
function ref2string(const ref : treference) : string;
|
function ref2string(const ref : treference) : string;
|
||||||
function cgop2string(const op : TOpCg) : String;
|
function cgop2string(const op : TOpCg) : String;
|
||||||
@ -473,9 +474,6 @@ unit cgppc;
|
|||||||
{ no need to allocate/free R0, is already allocated by call node
|
{ no need to allocate/free R0, is already allocated by call node
|
||||||
because it's a volatile register }
|
because it's a volatile register }
|
||||||
reg:=NR_R0;
|
reg:=NR_R0;
|
||||||
{ save current TOC }
|
|
||||||
reference_reset_base(tmpref,NR_STACK_POINTER_REG,LA_RTOC_AIX,ctempposinvalid,sizeof(pint),[]);
|
|
||||||
a_load_reg_ref(list,OS_ADDR,OS_ADDR,NR_RTOC,tmpref);
|
|
||||||
end;
|
end;
|
||||||
list.concat(taicpu.op_reg(A_MTCTR,reg));
|
list.concat(taicpu.op_reg(A_MTCTR,reg));
|
||||||
if target_info.system in systems_aix then
|
if target_info.system in systems_aix then
|
||||||
@ -488,9 +486,6 @@ unit cgppc;
|
|||||||
end
|
end
|
||||||
else if target_info.abi=abi_powerpc_elfv2 then
|
else if target_info.abi=abi_powerpc_elfv2 then
|
||||||
begin
|
begin
|
||||||
{ save current TOC }
|
|
||||||
reference_reset_base(tmpref,NR_STACK_POINTER_REG,LA_RTOC_ELFV2,ctempposinvalid,sizeof(pint),[]);
|
|
||||||
a_load_reg_ref(list,OS_ADDR,OS_ADDR,NR_RTOC,tmpref);
|
|
||||||
{ functions must be called via R12 for this ABI }
|
{ functions must be called via R12 for this ABI }
|
||||||
if reg<>NR_R12 then
|
if reg<>NR_R12 then
|
||||||
begin
|
begin
|
||||||
@ -499,17 +494,13 @@ unit cgppc;
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
list.concat(taicpu.op_none(A_BCTRL));
|
list.concat(taicpu.op_none(A_BCTRL));
|
||||||
if (target_info.system in systems_aix) or
|
if target_info.abi in abis_ppc_toc then
|
||||||
(target_info.abi=abi_powerpc_elfv2) then
|
|
||||||
begin
|
begin
|
||||||
if (target_info.abi=abi_powerpc_elfv2) and
|
if (target_info.abi=abi_powerpc_elfv2) and
|
||||||
(reg<>NR_R12) then
|
(reg<>NR_R12) then
|
||||||
ungetcpuregister(list,NR_R12);
|
ungetcpuregister(list,NR_R12);
|
||||||
{ restore our TOC }
|
{ restore our TOC }
|
||||||
if target_info.system in systems_aix then
|
toc_offset:=get_rtoc_offset;
|
||||||
toc_offset:=LA_RTOC_AIX
|
|
||||||
else
|
|
||||||
toc_offset:=LA_RTOC_ELFV2;
|
|
||||||
reference_reset_base(tmpref,NR_STACK_POINTER_REG,toc_offset,ctempposinvalid,sizeof(pint),[]);
|
reference_reset_base(tmpref,NR_STACK_POINTER_REG,toc_offset,ctempposinvalid,sizeof(pint),[]);
|
||||||
a_load_ref_reg(list,OS_ADDR,OS_ADDR,tmpref,NR_RTOC);
|
a_load_ref_reg(list,OS_ADDR,OS_ADDR,tmpref,NR_RTOC);
|
||||||
end;
|
end;
|
||||||
@ -743,6 +734,23 @@ unit cgppc;
|
|||||||
list.concat(p)
|
list.concat(p)
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function tcgppcgen.get_rtoc_offset: longint;
|
||||||
|
begin
|
||||||
|
case target_info.abi of
|
||||||
|
abi_powerpc_aix:
|
||||||
|
result:=LA_RTOC_AIX;
|
||||||
|
{$ifdef powerpc64}
|
||||||
|
{ no TOC on Linux/ppc32 }
|
||||||
|
abi_powerpc_elfv1:
|
||||||
|
result:=LA_RTOC_SYSV;
|
||||||
|
{$endif}
|
||||||
|
abi_powerpc_elfv2:
|
||||||
|
result:=LA_RTOC_ELFV2;
|
||||||
|
else
|
||||||
|
internalerror(2015021001);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function tcgppcgen.load_got_symbol(list: TAsmList; const symbol : string; const flags: tindsymflags) : tregister;
|
function tcgppcgen.load_got_symbol(list: TAsmList; const symbol : string; const flags: tindsymflags) : tregister;
|
||||||
|
@ -448,14 +448,9 @@ interface
|
|||||||
on the caller side rather than on the callee side }
|
on the caller side rather than on the callee side }
|
||||||
systems_caller_copy_addr_value_para = [system_aarch64_ios,system_aarch64_darwin,system_aarch64_linux,system_aarch64_win64,system_aarch64_freebsd];
|
systems_caller_copy_addr_value_para = [system_aarch64_ios,system_aarch64_darwin,system_aarch64_linux,system_aarch64_win64,system_aarch64_freebsd];
|
||||||
|
|
||||||
{ all PPC systems that use a TOC register to address globals }
|
{ all PPC ABIs that use a TOC register to address globals }
|
||||||
{ TODO: not used by Darwin, but don't know about others (JM) }
|
abis_ppc_toc = [
|
||||||
systems_ppc_toc = [
|
abi_powerpc_sysv,abi_powerpc_aix,abi_powerpc_elfv2
|
||||||
system_powerpc_linux,
|
|
||||||
system_powerpc64_linux,
|
|
||||||
system_powerpc_aix,
|
|
||||||
system_powerpc64_aix,
|
|
||||||
system_powerpc_macosclassic
|
|
||||||
];
|
];
|
||||||
|
|
||||||
{ pointer checking (requires special code in FPC_CHECKPOINTER,
|
{ pointer checking (requires special code in FPC_CHECKPOINTER,
|
||||||
|
Loading…
Reference in New Issue
Block a user