From 354ebb822abe3032c5ac326b71227b2c4ee12bc1 Mon Sep 17 00:00:00 2001 From: sergei Date: Thu, 21 Feb 2013 20:57:38 +0000 Subject: [PATCH] * MIPS: fixed layout of stack frame in case procedure does only low-level calls (via a_call_name, etc.). A 16-byte outgoing parameter area must be allocated regardless of actual parameter count. * Abort if attempting to emit a call without pi_do_call flag set, because the outgoing parameter area determines layout of temps and therefore cannot be created/changed during pass 2. * Bypass g_concatcopy_move if procedure is a leaf one, due to the restriction mentioned above. git-svn-id: trunk@23644 - --- compiler/mips/cgcpu.pas | 22 ++++++++++++++++++++-- compiler/mips/cpupara.pas | 4 ---- compiler/mips/cpupi.pas | 11 ++++++++--- 3 files changed, 28 insertions(+), 9 deletions(-) diff --git a/compiler/mips/cgcpu.pas b/compiler/mips/cgcpu.pas index b9bebd7e5e..d063fcd9aa 100644 --- a/compiler/mips/cgcpu.pas +++ b/compiler/mips/cgcpu.pas @@ -611,6 +611,10 @@ procedure TCGMIPS.a_call_name(list: tasmlist; const s: string; weak: boolean); var href: treference; begin + if assigned(current_procinfo) and + not (pi_do_call in current_procinfo.flags) then + InternalError(2013022101); + if (cs_create_pic in current_settings.moduleswitches) then begin reference_reset(href,sizeof(aint)); @@ -643,6 +647,9 @@ end; procedure TCGMIPS.a_call_reg(list: tasmlist; Reg: TRegister); begin + if assigned(current_procinfo) and + not (pi_do_call in current_procinfo.flags) then + InternalError(2013022102); if (cs_create_pic in current_settings.moduleswitches) then begin if (Reg <> NR_PIC_FUNC) then @@ -1690,8 +1697,16 @@ var begin if len > high(longint) then internalerror(2002072704); + { A call (to FPC_MOVE) requires the outgoing parameter area to be properly + allocated on stack. This can only be done before tmipsprocinfo.set_first_temp_offset, + i.e. before secondpass. Other internal procedures request correct stack frame + by setting pi_do_call during firstpass, but for this particular one it is impossible. + Therefore, if the current procedure is a leaf one, we have to leave it that way. } + { anybody wants to determine a good value here :)? } - if len > 100 then + if (len > 100) and + assigned(current_procinfo) and + (pi_do_call in current_procinfo.flags) then g_concatcopy_move(list, Source, dest, len) else begin @@ -1789,7 +1804,10 @@ var lab: tasmlabel; ai : TaiCpu; begin - if len > 31 then + if (len > 31) and + { see comment in g_concatcopy } + assigned(current_procinfo) and + (pi_do_call in current_procinfo.flags) then g_concatcopy_move(list, Source, dest, len) else begin diff --git a/compiler/mips/cpupara.pas b/compiler/mips/cpupara.pas index a40d5ef768..3f619cf4f0 100644 --- a/compiler/mips/cpupara.pas +++ b/compiler/mips/cpupara.pas @@ -155,10 +155,6 @@ implementation reference.offset:=nr*mips_sizeof_register_param; end; size:=OS_INT; - { Be sure to reserve enough stack space tp cope with - that parameter } - if assigned(current_procinfo) then - TMIPSProcinfo(current_procinfo).allocate_push_parasize((nr+1)*mips_sizeof_register_param); end; end; diff --git a/compiler/mips/cpupi.pas b/compiler/mips/cpupi.pas index e35dbacfa1..3136006cdd 100644 --- a/compiler/mips/cpupi.pas +++ b/compiler/mips/cpupi.pas @@ -69,6 +69,9 @@ implementation i : longint; begin inherited create(aparent); + { will call _mcount if profiling } + if cs_profile in current_settings.moduleswitches then + include(flags,pi_do_call); for i:=low(tparasupregs) to high(tparasupregs) do begin register_used[i]:=false; @@ -102,6 +105,11 @@ implementation tg.setfirsttemp(0) else begin + { Fixes the case when there are calls done by low-level means + (cg.a_call_name) but no child callnode } + if (pi_do_call in flags) then + allocate_push_parasize(mips_nb_used_registers*sizeof(aint)); + if not (po_nostackframe in procdef.procoptions) then tg.setfirsttemp(Align(maxpushedparasize+ floatregssave*sizeof(aint)+intregssave*sizeof(aint) @@ -113,9 +121,6 @@ implementation function TMIPSProcInfo.calc_stackframe_size:longint; - var - r : byte; - regs: tcpuregisterset; begin result:=maxpushedparasize; floatregstart:=result;