./trunk/gcc121/vcs_diff_compiler.patch 2026-03-07-01:54
> uname -a Linux cfarm121 6.18.5+deb14-powerpc64 #1 SMP PREEMPT Debian 6.18.5-1 (2026-01-16) ppc64 GNU/Linux
diff --git a/compiler/cgobj.pas b/compiler/cgobj.pas
index 16c4a23e6a..6e58455553 100644
--- a/compiler/cgobj.pas
+++ b/compiler/cgobj.pas
@@ -415,6 +415,11 @@ tcg = class
@param(size Number of bytes to allocate)
}
procedure g_stackpointer_alloc(list : TAsmList;size : longint);virtual;
+ {# Emits instruction to load TOC into ABI specific register
+
+ @param(sym: assembler symbol used for computation of specific relocation)
+ }
+ procedure g_load_toc(list: TAsmList; sym : TAsmSymbol); virtual;
{# Emits instruction for allocating the locals in entry
code of a routine. This is one of the first
routine called in @var(genentrycode).
@@ -2884,6 +2889,11 @@ implementation
end;
+ procedure tcg.g_load_toc(list: TAsmList;sym : TAsmSymbol);
+ begin
+ end;
+
+
procedure tcg.g_adjust_self_value(list:TAsmList;procdef: tprocdef;ioffset: tcgint);
var
hsym : tsym;
diff --git a/compiler/hlcgobj.pas b/compiler/hlcgobj.pas
index df399ab0d0..13478a6073 100644
--- a/compiler/hlcgobj.pas
+++ b/compiler/hlcgobj.pas
@@ -4250,6 +4250,7 @@ implementation
sym:=current_asmdata.DefineAsmSymbol(wrappername,AB_PRIVATE_EXTERN,AT_FUNCTION,procdef);
list.concat(Tai_symbol.Create(sym,0));
end;
+ cg.g_load_toc(list,sym);
a_jmp_external_name(list,externalname);
list.concat(Tai_symbol_end.Create(sym));
end;
diff --git a/compiler/powerpc64/cgcpu.pas b/compiler/powerpc64/cgcpu.pas
index d3c663badd..a3890db769 100644
--- a/compiler/powerpc64/cgcpu.pas
+++ b/compiler/powerpc64/cgcpu.pas
@@ -79,6 +79,7 @@ tcgppc = class(tcgppcgen)
procedure g_adjust_self_value(list:TAsmList;procdef: tprocdef;ioffset: aint);override;
procedure g_profilecode(list: TAsmList); override;
+ procedure g_load_toc(list: TAsmList; sym : TAsmSymbol); override;
procedure g_proc_entry(list: TAsmList; localsize: longint; nostackframe:
boolean); override;
procedure g_proc_exit(list: TAsmList; parasize: longint; nostackframe:
@@ -1095,6 +1096,38 @@ procedure tcgppc.g_profilecode(list: TAsmList);
current_procinfo.procdef.paras.ForEachCall(TObjectListCallback(@profilecode_restorepara), list);
end;
+{ Default does nothing }
+procedure tcgppc.g_load_toc(list: TAsmList; sym: TAsmSymbol);
+var
+ href: treference;
+ lab: tasmlabel;
+begin
+ { In ELFv2 the function is required to initialise the TOC register itself
+ if necessary. Additionally, it has to mark the end of this TOC
+ initialisation code with a .localfunc directive, which will be used as
+ local entry code by the linker (when it knows the TOC value is the same
+ for the caller and callee). It must load the TOC in a PIC-way, which it
+ can do easily because R12 is guaranteed to hold the address of this function
+ on entry. }
+ if (target_info.abi=abi_powerpc_elfv2) then
+ begin
+ current_asmdata.getlabel(lab,alt_addr);
+ if assigned(current_procinfo) then
+ begin
+ getcpuregister(list,NR_R12);
+ getcpuregister(list,NR_R2);
+ end;
+ cg.a_label(list,lab);
+ reference_reset_symbol(href,current_asmdata.RefAsmSymbol('.TOC.',AT_DATA),0,sizeof(PInt),[]);
+ href.relsymbol:=lab;
+ href.refaddr:=addr_higha;
+ list.concat(taicpu.op_reg_reg_ref(a_addis,NR_R2,NR_R12,href));
+ href.refaddr:=addr_low;
+ list.concat(taicpu.op_reg_reg_ref(a_addi,NR_R2,NR_R2,href));
+ list.concat(tai_symbolpair.create(spk_localentry,sym.name,sym.name));
+ end;
+end;
+
{ Generates the entry code of a procedure/function.
This procedure may be called before, as well as after g_return_from_proc
@@ -1175,33 +1208,11 @@ procedure tcgppc.g_proc_entry(list: TAsmList; localsize: longint;
var
href: treference;
- lab: tasmlabel;
- procmangledname: TSymStr;
+ sym: TAsmSymbol;
begin
- { In ELFv2 the function is required to initialise the TOC register itself
- if necessary. Additionally, it has to mark the end of this TOC
- initialisation code with a .localfunc directive, which will be used as
- local entry code by the linker (when it knows the TOC value is the same
- for the caller and callee). It must load the TOC in a PIC-way, which it
- can do easily because R12 is guaranteed to hold the address of this function
- on entry. }
- if (target_info.abi=abi_powerpc_elfv2) and
- (pi_needs_got in current_procinfo.flags) and
- not nostackframe then
- begin
- current_asmdata.getlabel(lab,alt_addr);
- getcpuregister(list,NR_R12);
- getcpuregister(list,NR_R2);
- cg.a_label(list,lab);
- reference_reset_symbol(href,current_asmdata.RefAsmSymbol('.TOC.',AT_DATA),0,sizeof(PInt),[]);
- href.relsymbol:=lab;
- href.refaddr:=addr_higha;
- list.concat(taicpu.op_reg_reg_ref(a_addis,NR_R2,NR_R12,href));
- href.refaddr:=addr_low;
- list.concat(taicpu.op_reg_reg_ref(a_addi,NR_R2,NR_R2,href));
- procmangledname:=current_procinfo.procdef.mangledname;
- list.concat(tai_symbolpair.create(spk_localentry,procmangledname,procmangledname));
- end;
+ sym:=current_asmdata.RefAsmSymbol(current_procinfo.procdef.mangledname,AT_FUNCTION);
+ if (pi_needs_got in current_procinfo.flags) and not nostackframe then
+ g_load_toc(list,sym);
calcFirstUsedFPR(firstregfpu, fprcount);
calcFirstUsedGPR(firstreggpr, gprcount);
diff --git a/compiler/ppcgen/cgppc.pas b/compiler/ppcgen/cgppc.pas
index c09c961b76..d2777898a9 100644
--- a/compiler/ppcgen/cgppc.pas
+++ b/compiler/ppcgen/cgppc.pas
@@ -67,6 +67,10 @@ tcgppcgen = class(tcg)
procedure g_load_check_simple(list: TAsmList; const ref: treference; size: aint);
procedure g_flags2reg(list: TAsmList; size: TCgSize; const f: TResFlags; reg: TRegister); override;
+ function get_rtoc_offset: longint;
+
+ function load_got_symbol(list : TAsmList; const symbol : string; const flags: tindsymflags) : tregister;
+
{ returns true if the offset of the given reference can not be }
{ represented by a 16 bit immediate as required by some PowerPC }
{ instructions }
@@ -89,11 +93,7 @@ tcgppcgen = class(tcg)
procedure a_jmp(list: TAsmList; op: tasmop;
c: tasmcondflag; crval: longint; l: tasmlabel);
- function get_rtoc_offset: longint;
-
function save_lr_in_prologue: boolean;
-
- function load_got_symbol(list : TAsmList; const symbol : string; const flags: tindsymflags) : tregister;
end;
diff --git a/compiler/ppcgen/hlcgppc.pas b/compiler/ppcgen/hlcgppc.pas
index 1e7c84a6ec..3622099198 100644
--- a/compiler/ppcgen/hlcgppc.pas
+++ b/compiler/ppcgen/hlcgppc.pas
@@ -30,7 +30,7 @@ interface
uses
globtype,globals,
aasmdata,
- symtype,symdef,
+ symtype,symdef,parabase,
cgbase,cgutils,hlcgobj,hlcg2ll;
type
@@ -39,6 +39,7 @@ thlcgppcgen = class(thlcg2ll)
procedure a_load_subsetref_regs_noindex(list: TAsmList; subsetsize: tdef; loadbitsize: byte; const sref: tsubsetreference; valuereg, extra_value_reg: tregister); override;
public
procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);override;
+ function a_call_name(list: TAsmList; pd: tprocdef; const s: TSymStr; const paras: array of pcgpara; forceresdef: tdef; weak: boolean): tcgpara; override;
procedure a_jmp_external_name(list: TAsmList; const externalname: TSymStr); override;
procedure gen_load_para_value(list: TAsmList); override;
end;
@@ -197,6 +198,31 @@ implementation
List.concat(Tai_symbol_end.Createname(labelname));
end;
+ function thlcgppcgen.a_call_name(list: TAsmList; pd: tprocdef; const s: TSymStr; const paras: array of pcgpara; forceresdef: tdef; weak: boolean): tcgpara;
+ var
+ href : treference;
+ tmpreg : tregister;
+ sym : TAsmSymbol;
+ begin
+ { For external functions, we need to use R12 on ELFv2 ABI }
+ if (target_info.abi = abi_powerpc_elfv2) and ([po_external,po_has_importname]*pd.procoptions<>[]) then
+ begin
+ include(current_procinfo.flags,pi_needs_got);
+ sym:=current_asmdata.refasmsymbol(pd.mangledname,AT_FUNCTION);
+ tmpreg := tcgppcgen(cg).load_got_symbol(list, sym.name, asmsym2indsymflags(sym));
+ cg.a_load_reg_reg(list,OS_ADDR,OS_ADDR,tmpreg,NR_R12);
+ { move actual function pointer to CTR register }
+ list.concat(taicpu.op_reg(A_MTCTR, NR_R12));
+ { call function }
+ list.concat(taicpu.op_none(A_BCTR));
+ { we need to load the old RTOC from stackframe it might have changed }
+ reference_reset_base(href, voidpointertype, NR_STACK_POINTER_REG, tcgppcgen(cg).get_rtoc_offset, ctempposinvalid, sizeof(pint), []);
+ cg.a_load_ref_reg(list, OS_ADDR, OS_ADDR, href, NR_RTOC);
+ result:=get_call_result_cgpara(pd,forceresdef);
+ end
+ else
+ result:=inherited a_call_name(list,pd,s,paras,forceresdef,weak);
+ end;
procedure thlcgppcgen.a_jmp_external_name(list: TAsmList; const externalname: TSymStr);
var