From fc21845686f13633f5c73c17ea5a53651cf3c893 Mon Sep 17 00:00:00 2001 From: Jonas Maebe <jonas@freepascal.org> Date: Wed, 11 Mar 2015 17:49:44 +0000 Subject: [PATCH] * fixed the allocation of R12 on ppc32/ppc64 when used to hold the value of the stack pointer during the prolog. This was done previously in tcg.g_proc_entry(), but that routine is called after register allocation and hence has no influence. Also cleaned up the deallocation of that register by moving the previously ifdef'd code to thlcgppcgen (mantis #27634) git-svn-id: trunk@30164 - --- .gitattributes | 1 + compiler/ncgutil.pas | 12 ------- compiler/powerpc/cgcpu.pas | 7 ++-- compiler/powerpc/cpubase.pas | 4 +++ compiler/powerpc64/cgcpu.pas | 4 +-- compiler/ppcgen/hlcgppc.pas | 17 ++++++++++ tests/webtbs/tw27634.pp | 66 ++++++++++++++++++++++++++++++++++++ 7 files changed, 91 insertions(+), 20 deletions(-) create mode 100644 tests/webtbs/tw27634.pp diff --git a/.gitattributes b/.gitattributes index 89487ca324..494060306a 100644 --- a/.gitattributes +++ b/.gitattributes @@ -14319,6 +14319,7 @@ tests/webtbs/tw27424.pp svneol=native#text/pascal tests/webtbs/tw27515.pp svneol=native#text/pascal tests/webtbs/tw2758.pp svneol=native#text/plain tests/webtbs/tw2763.pp svneol=native#text/plain +tests/webtbs/tw27634.pp svneol=native#text/plain tests/webtbs/tw2765.pp svneol=native#text/plain tests/webtbs/tw2767.pp svneol=native#text/plain tests/webtbs/tw2771.pp svneol=native#text/plain diff --git a/compiler/ncgutil.pas b/compiler/ncgutil.pas index 67c5df1dd0..46c7809431 100644 --- a/compiler/ncgutil.pas +++ b/compiler/ncgutil.pas @@ -1259,18 +1259,6 @@ implementation the initialization and body is parsed because the refcounts are incremented using the local copies } current_procinfo.procdef.parast.SymList.ForEachCall(@hlcg.g_copyvalueparas,list); -{$ifdef powerpc} - { unget the register that contains the stack pointer before the procedure entry, } - { which is used to access the parameters in their original callee-side location } - if (tppcprocinfo(current_procinfo).needs_frame_pointer) then - cg.a_reg_dealloc(list,NR_R12); -{$endif powerpc} -{$ifdef powerpc64} - { unget the register that contains the stack pointer before the procedure entry, } - { which is used to access the parameters in their original callee-side location } - if (tppcprocinfo(current_procinfo).needs_frame_pointer) then - cg.a_reg_dealloc(list, NR_OLD_STACK_POINTER_REG); -{$endif powerpc64} if not(po_assembler in current_procinfo.procdef.procoptions) then begin { initialize refcounted paras, and trash others. Needed here diff --git a/compiler/powerpc/cgcpu.pas b/compiler/powerpc/cgcpu.pas index 79aa42f926..a6b55c92e1 100644 --- a/compiler/powerpc/cgcpu.pas +++ b/compiler/powerpc/cgcpu.pas @@ -830,11 +830,8 @@ const usesgpr := firstregint <> 32; usesfpr := firstregfpu <> 32; - if (tppcprocinfo(current_procinfo).needs_frame_pointer) then - begin - a_reg_alloc(list,NR_R12); - list.concat(taicpu.op_reg_reg(A_MR,NR_R12,NR_STACK_POINTER_REG)); - end; + if tppcprocinfo(current_procinfo).needs_frame_pointer then + list.concat(taicpu.op_reg_reg(A_MR,NR_OLD_STACK_POINTER_REG,NR_STACK_POINTER_REG)); end; if usesfpr then diff --git a/compiler/powerpc/cpubase.pas b/compiler/powerpc/cpubase.pas index fe1ed96e5f..4fcbf00f22 100644 --- a/compiler/powerpc/cpubase.pas +++ b/compiler/powerpc/cpubase.pas @@ -291,6 +291,10 @@ uses {# Stack pointer register } NR_STACK_POINTER_REG = NR_R1; RS_STACK_POINTER_REG = RS_R1; + { old stack pointer register used during copying variables from the caller + stack frame + } + NR_OLD_STACK_POINTER_REG = NR_R12; {# Frame pointer register } NR_FRAME_POINTER_REG = NR_STACK_POINTER_REG; RS_FRAME_POINTER_REG = RS_STACK_POINTER_REG; diff --git a/compiler/powerpc64/cgcpu.pas b/compiler/powerpc64/cgcpu.pas index 7c953471b0..524936f6c9 100644 --- a/compiler/powerpc64/cgcpu.pas +++ b/compiler/powerpc64/cgcpu.pas @@ -1193,10 +1193,8 @@ begin save_standard_registers; { save old stack frame pointer } - if (tppcprocinfo(current_procinfo).needs_frame_pointer) then begin - a_reg_alloc(list, NR_OLD_STACK_POINTER_REG); + if (tppcprocinfo(current_procinfo).needs_frame_pointer) then list.concat(taicpu.op_reg_reg(A_MR, NR_OLD_STACK_POINTER_REG, NR_STACK_POINTER_REG)); - end; { create stack frame } if (not nostackframe) and (localsize > 0) and diff --git a/compiler/ppcgen/hlcgppc.pas b/compiler/ppcgen/hlcgppc.pas index f41c9ac5f2..3eee7122f6 100644 --- a/compiler/ppcgen/hlcgppc.pas +++ b/compiler/ppcgen/hlcgppc.pas @@ -36,12 +36,15 @@ type thlcgppcgen = class(thlcg2ll) protected procedure a_load_subsetref_regs_noindex(list: TAsmList; subsetsize: tdef; loadbitsize: byte; const sref: tsubsetreference; valuereg, extra_value_reg: tregister); override; + public + procedure gen_load_para_value(list: TAsmList); override; end; implementation uses cpubase,globtype, + procinfo,cpupi, symdef,defutil; { thlcgppc } @@ -80,5 +83,19 @@ implementation a_load_subsetreg_subsetreg(list,subsetsize,subsetsize,fromsreg,tosreg); end; + + procedure thlcgppcgen.gen_load_para_value(list: TAsmList); + begin + { get the register that contains the stack pointer before the procedure + entry, which is used to access the parameters in their original + callee-side location } + if (tppcprocinfo(current_procinfo).needs_frame_pointer) then + getcpuregister(list,NR_OLD_STACK_POINTER_REG); + inherited; + { free it again } + if (tppcprocinfo(current_procinfo).needs_frame_pointer) then + ungetcpuregister(list,NR_OLD_STACK_POINTER_REG); + end; + end. diff --git a/tests/webtbs/tw27634.pp b/tests/webtbs/tw27634.pp new file mode 100644 index 0000000000..b33dd096df --- /dev/null +++ b/tests/webtbs/tw27634.pp @@ -0,0 +1,66 @@ +type + MBHelpPtr = pointer; + MenuRecord = record end; + MenuItemsPtr = pointer; + MenuIconHandle = pointer; + MenuRef = pointer; + int16 = word; + int32 = longint; + OSStatus = int32; + Str255 = ShortString; + + function MacMenuAddItemInternal + ( var theMenuRecord : MenuRecord; + theMenuOrSubMenuID : Int32; + theOptBeforeItemIndex : Int32; + var theMenuRef : MenuRef; + var theItemsPtr : MenuItemsPtr; + const theItemStr : Str255; + theItemIconHandle : MenuIconHandle; + theEnableFlag : boolean; + theCheckFlag : boolean; + theCommandChar : char; + theCommandModifiers : Int16; + theItemCmdID : Int32; + const theItemAppStr : AnsiString; + var theNewItemIndex : Int32): OSStatus; +begin +end; + + function MBMenuAddItemInternal + ( var theMenuRecord : MenuRecord; + theMenuOrSubMenuID : Int32; + theOptBeforeItemIndex : Int32; + var theMenuRef : MenuRef; + var theItemsPtr : MenuItemsPtr; + const theItemStr : Str255; + theItemIconHandle : MenuIconHandle; + theEnableFlag : boolean; + theCheckFlag : boolean; + theCommandChar : char; + theCommandGlyph : Int16; { unused here } + theCommandModifiers : Int16; + theItemCmdID : Int32; + const theItemAppStr : AnsiString; + theItemHelpPtr : MBHelpPtr; { unused here } + var theNewItemIndex : Int32): OSStatus; + var + theErr : OSStatus; + begin + theItemsPtr := nil; + theNewItemIndex := 0; + theErr := MacMenuAddItemInternal + ( theMenuRecord, theMenuOrSubMenuID, theOptBeforeItemIndex, theMenuRef, theItemsPtr, + theItemStr, theItemIconHandle, theEnableFlag, theCheckFlag, theCommandChar, + theCommandModifiers, theItemCmdID, theItemAppStr, theNewItemIndex); + MBMenuAddItemInternal := theErr + end; + +var + theMenuRecord: MenuRecord; + theMenuRef: MenuRef; + theItemsPtr: MenuItemsPtr; + theNewItemIndex: Int32; +begin + MBMenuAddItemInternal(theMenuRecord,1,2,theMenuRef,theItemsPtr,'abc',nil,true,false,'b',3,4,5,'def',nil,theNewItemIndex); +end.