diff --git a/compiler/cgbase.pas b/compiler/cgbase.pas index e95c4dcfbd..ada3e7bf48 100644 --- a/compiler/cgbase.pas +++ b/compiler/cgbase.pas @@ -77,7 +77,7 @@ unit cgbase; On the PowerPC, this is used to store the offset where the frame pointer from the outer procedure is stored. } - framepointer_offset : longint; + parent_framepointer_offset : longint; {# firsttemp position } firsttemp_offset : longint; @@ -114,23 +114,21 @@ unit cgbase; constructor create(aparent:tprocinfo);virtual; destructor destroy;override; - procedure allocate_interrupt_parameter;virtual; + procedure allocate_parent_framepointer_parameter;virtual; - procedure allocate_implicit_parameter;virtual; + procedure allocate_interrupt_parameter;virtual; { Allocate framepointer so it can not be used by the register allocator } - procedure allocate_framepointer;virtual; + procedure allocate_framepointer_reg;virtual; + + procedure allocate_push_parasize(size:longint);virtual; + + function calc_stackframe_size:longint;virtual; { Does the necessary stuff before a procedure body is compiled } procedure handle_body_start;virtual; - { This is called by parser, after the header of a subroutine is parsed. - If the local symtable offset depends on the para symtable size, the - necessary stuff must be done here. - } - procedure after_header;virtual; - { This procedure is called after the pass 1 of the subroutine body is done. Here the address fix ups to generate code for the body must be done. } @@ -319,7 +317,7 @@ implementation begin parent:=aparent; procdef:=nil; - framepointer_offset:=0; + parent_framepointer_offset:=0; firsttemp_offset:=0; flags:=[]; framepointer.enum:=R_INTREGISTER; @@ -340,16 +338,34 @@ implementation end; + procedure tprocinfo.allocate_parent_framepointer_parameter; + begin + parent_framepointer_offset:=procdef.parast.address_fixup; + inc(procdef.parast.address_fixup,POINTER_SIZE); + end; + + procedure tprocinfo.allocate_interrupt_parameter; begin end; - procedure tprocinfo.allocate_framepointer; + procedure tprocinfo.allocate_framepointer_reg; begin end; + procedure tprocinfo.allocate_push_parasize(size:longint); + begin + end; + + + function tprocinfo.calc_stackframe_size:longint; + begin + result:=procdef.localst.datasize+tg.gettempsize; + end; + + procedure tprocinfo.handle_body_start; var paramloc : tparalocation; @@ -395,22 +411,6 @@ implementation end; - procedure tprocinfo.allocate_implicit_parameter; - begin - { Insert implicit parameters, will be removed in the future } - if (procdef.parast.symtablelevel>normal_function_level) then - begin - framepointer_offset:=procdef.parast.address_fixup; - inc(procdef.parast.address_fixup,POINTER_SIZE); - end; - end; - - - procedure tprocinfo.after_header; - begin - end; - - procedure tprocinfo.after_pass1; begin end; @@ -571,7 +571,11 @@ implementation end. { $Log$ - Revision 1.56 2003-06-13 21:19:30 peter + Revision 1.57 2003-07-06 17:58:22 peter + * framepointer fixes for sparc + * parent framepointer code more generic + + Revision 1.56 2003/06/13 21:19:30 peter * current_procdef removed, use current_procinfo.procdef instead Revision 1.55 2003/06/12 16:43:07 peter diff --git a/compiler/cgobj.pas b/compiler/cgobj.pas index da2ecc5111..b548c7cbd5 100644 --- a/compiler/cgobj.pas +++ b/compiler/cgobj.pas @@ -311,6 +311,9 @@ unit cgobj; } procedure g_exception_reason_load(list : taasmoutput; const href : treference);virtual; + procedure g_load_parent_framepointer(list:taasmoutput;parentsymtable:tsymtable;reg:tregister); + procedure g_save_parent_framepointer_param(list:taasmoutput);virtual; + procedure g_maybe_testself(list : taasmoutput;reg:tregister); procedure g_maybe_testvmt(list : taasmoutput;reg:tregister;objdef:tobjectdef); {# This should emit the opcode to copy len bytes from the source @@ -1353,6 +1356,31 @@ unit cgobj; end; + procedure tcg.g_load_parent_framepointer(list:taasmoutput;parentsymtable:tsymtable;reg:tregister); + var + href : treference; + i : integer; + begin + { make a reference } + reference_reset_base(href,current_procinfo.framepointer,PARENT_FRAMEPOINTER_OFFSET); + cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,reg); + { walk parents } + i:=current_procinfo.procdef.parast.symtablelevel-1; + while (i>parentsymtable.symtablelevel) do + begin + { make a reference } + reference_reset_base(href,reg,PARENT_FRAMEPOINTER_OFFSET); + cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,reg); + dec(i); + end; + end; + + + procedure tcg.g_save_parent_framepointer_param(list:taasmoutput); + begin + end; + + procedure tcg.g_copyshortstring(list : taasmoutput;const source,dest : treference;len:byte;delsource,loadref : boolean); begin {$ifdef FPC} @@ -1767,7 +1795,11 @@ finalization end. { $Log$ - Revision 1.113 2003-07-02 22:18:04 peter + Revision 1.114 2003-07-06 17:58:22 peter + * framepointer fixes for sparc + * parent framepointer code more generic + + Revision 1.113 2003/07/02 22:18:04 peter * paraloc splitted in callerparaloc,calleeparaloc * sparc calling convention updates diff --git a/compiler/i386/cpubase.inc b/compiler/i386/cpubase.inc index 8b302d033b..f78290534e 100644 --- a/compiler/i386/cpubase.inc +++ b/compiler/i386/cpubase.inc @@ -181,6 +181,9 @@ fpu_result_reg = R_ST; mmresultreg = R_MM0; + { Offset where the parent framepointer is pushed } + PARENT_FRAMEPOINTER_OFFSET = 8; + {***************************************************************************** GCC /ABI linking information *****************************************************************************} @@ -205,7 +208,11 @@ { $Log$ - Revision 1.6 2003-06-03 13:01:59 daniel + Revision 1.7 2003-07-06 17:58:22 peter + * framepointer fixes for sparc + * parent framepointer code more generic + + Revision 1.6 2003/06/03 13:01:59 daniel * Register allocator finished Revision 1.5 2003/05/31 15:05:28 peter diff --git a/compiler/i386/cpupi.pas b/compiler/i386/cpupi.pas index 79e2064bb7..7177df9b6f 100644 --- a/compiler/i386/cpupi.pas +++ b/compiler/i386/cpupi.pas @@ -34,7 +34,7 @@ unit cpupi; type ti386procinfo = class(tcgprocinfo) procedure allocate_interrupt_parameter;override; - procedure allocate_framepointer;override; + procedure allocate_framepointer_reg;override; end; @@ -52,7 +52,7 @@ unit cpupi; end; - procedure ti386procinfo.allocate_framepointer; + procedure ti386procinfo.allocate_framepointer_reg; begin if framepointer.number=NR_EBP then begin @@ -69,7 +69,11 @@ begin end. { $Log$ - Revision 1.8 2003-06-13 21:19:31 peter + Revision 1.9 2003-07-06 17:58:22 peter + * framepointer fixes for sparc + * parent framepointer code more generic + + Revision 1.8 2003/06/13 21:19:31 peter * current_procdef removed, use current_procinfo.procdef instead Revision 1.7 2003/06/12 18:12:49 jonas diff --git a/compiler/ncgcal.pas b/compiler/ncgcal.pas index cd7cb9d06c..8e3f46c529 100644 --- a/compiler/ncgcal.pas +++ b/compiler/ncgcal.pas @@ -90,9 +90,6 @@ implementation {$else cpu64bit} cg64f32, {$endif cpu64bit} -{$ifdef powerpc} - cpupi, -{$endif powerpc} ncgutil,cgobj,tgobj,regvars,rgobj,rgcpu; @@ -370,12 +367,11 @@ implementation var href : treference; hregister : tregister; - i : integer; begin { this routine is itself not nested } if current_procinfo.procdef.parast.symtablelevel=(tprocdef(procdefinition).parast.symtablelevel) then begin - reference_reset_base(href,current_procinfo.framepointer,current_procinfo.framepointer_offset); + reference_reset_base(href,current_procinfo.framepointer,current_procinfo.parent_framepointer_offset); cg.a_param_ref(exprasmlist,OS_ADDR,href,paramanager.getintparaloc(exprasmlist,1)); end { one nesting level } @@ -384,18 +380,10 @@ implementation cg.a_param_reg(exprasmlist,OS_ADDR,current_procinfo.framepointer,paramanager.getintparaloc(exprasmlist,1)); end { very complex nesting level ... } - else if (current_procinfo.procdef.parast.symtablelevel>(tprocdef(procdefinition).parast.symtablelevel)) then + else if (current_procinfo.procdef.parast.symtablelevel>(tprocdef(procdefinition).parast.symtablelevel)) then begin hregister:=rg.getaddressregister(exprasmlist); - reference_reset_base(href,current_procinfo.framepointer,current_procinfo.framepointer_offset); - cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,hregister); - i:=current_procinfo.procdef.parast.symtablelevel; - while (i>tprocdef(procdefinition).parast.symtablelevel) do - begin - reference_reset_base(href,hregister,current_procinfo.framepointer_offset); - cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,hregister); - dec(i); - end; + cg.g_load_parent_framepointer(exprasmlist,tprocdef(procdefinition).parast,hregister); cg.a_param_reg(exprasmlist,OS_ADDR,hregister,paramanager.getintparaloc(exprasmlist,1)); rg.ungetaddressregister(exprasmlist,hregister); end; @@ -1050,11 +1038,8 @@ implementation if pop_size>0 then pop_parasize(pop_size); -{$ifdef powerpc} - { this calculation must be done in pass_1 anyway, so don't worry } - if tppcprocinfo(current_procinfo).maxpushedparasizesymtable.symtablelevel) then begin hregister:=rg.getaddressregister(exprasmlist); - { make a reference } - reference_reset_base(href,current_procinfo.framepointer,current_procinfo.framepointer_offset); - cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,hregister); - { walk parents } - i:=current_procinfo.procdef.parast.symtablelevel-1; - while (i>symtable.symtablelevel) do - begin - { make a reference } -{$ifdef powerpc} - reference_reset_base(href,hregister,current_procinfo.framepointer_offset); -{$else powerpc} - reference_reset_base(href,hregister,target_info.first_parm_offset); -{$endif powerpc} - cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,href,hregister); - dec(i); - end; + cg.g_load_parent_framepointer(exprasmlist,symtable,hregister); location.reference.base:=hregister; end; end; @@ -954,7 +939,11 @@ begin end. { $Log$ - Revision 1.73 2003-07-06 15:25:54 jonas + Revision 1.74 2003-07-06 17:58:22 peter + * framepointer fixes for sparc + * parent framepointer code more generic + + Revision 1.73 2003/07/06 15:25:54 jonas * newra fix for threadvars Revision 1.72 2003/06/15 15:13:12 jonas diff --git a/compiler/ncgutil.pas b/compiler/ncgutil.pas index aa59526fbb..b4fd86c1b3 100644 --- a/compiler/ncgutil.pas +++ b/compiler/ncgutil.pas @@ -68,7 +68,7 @@ interface procedure gen_finalize_code(list : TAAsmoutput;inlined:boolean); procedure gen_entry_code(list:TAAsmoutput;inlined:boolean); - procedure gen_stackalloc_code(list:Taasmoutput;stackframe:longint); + procedure gen_stackalloc_code(list:Taasmoutput); procedure gen_exit_code(list:Taasmoutput;inlined:boolean); (* @@ -1567,32 +1567,34 @@ implementation code, since temp. allocation might occur before - carl } - if assigned(current_procinfo.procdef.parast) then + if assigned(current_procinfo.procdef.parast) and + not (po_assembler in current_procinfo.procdef.procoptions) then begin - if not (po_assembler in current_procinfo.procdef.procoptions) then - begin - { move register parameters which aren't regable into memory } - { we do this before init_paras because that one calls routines which may overwrite these } - { registers and it also expects the values to be in memory } - hp:=tparaitem(current_procinfo.procdef.para.first); - while assigned(hp) do - begin - if Tvarsym(hp.parasym).reg.enum>R_INTREGISTER then - internalerror(200301081); - if (tvarsym(hp.parasym).reg.enum<>R_NO) then - begin - cg.a_load_param_reg(list,hp.calleeparaloc,tvarsym(hp.parasym).reg); - end - else if (hp.calleeparaloc.loc in [LOC_REGISTER,LOC_FPUREGISTER,LOC_MMREGISTER, - LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMREGISTER]) and - (tvarsym(hp.parasym).reg.enum=R_NO) then - begin - reference_reset_base(href,current_procinfo.framepointer,tvarsym(hp.parasym).adjusted_address); - cg.a_load_param_ref(list,hp.calleeparaloc,href); - end; - hp:=tparaitem(hp.next); - end; - end; + { save framepointer in memory } + if current_procinfo.procdef.parast.symtablelevel>normal_function_level then + cg.g_save_parent_framepointer_param(list); + + { move register parameters which aren't regable into memory } + { we do this before init_paras because that one calls routines which may overwrite these } + { registers and it also expects the values to be in memory } + hp:=tparaitem(current_procinfo.procdef.para.first); + while assigned(hp) do + begin + if Tvarsym(hp.parasym).reg.enum>R_INTREGISTER then + internalerror(200301081); + if (tvarsym(hp.parasym).reg.enum<>R_NO) then + begin + cg.a_load_param_reg(list,hp.calleeparaloc,tvarsym(hp.parasym).reg); + end + else if (hp.calleeparaloc.loc in [LOC_REGISTER,LOC_FPUREGISTER,LOC_MMREGISTER, + LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMREGISTER]) and + (tvarsym(hp.parasym).reg.enum=R_NO) then + begin + reference_reset_base(href,current_procinfo.framepointer,tvarsym(hp.parasym).adjusted_address); + cg.a_load_param_ref(list,hp.calleeparaloc,href); + end; + hp:=tparaitem(hp.next); + end; end; { for the save all registers we can simply use a pusha,popa which @@ -1618,76 +1620,73 @@ implementation end; - procedure gen_stackalloc_code(list:Taasmoutput;stackframe:longint); - - var hs:string; - - begin - {************************* Stack allocation **************************} - { and symbol entry point as well as debug information } - { will be inserted in front of the rest of this list. } - { Insert alignment and assembler names } - { Align, gprof uses 16 byte granularity } - if (cs_profile in aktmoduleswitches) then - list.concat(Tai_align.create(16)) - else - list.concat(Tai_align.create(aktalignment.procalign)); - -{$ifdef GDB} - if (cs_debuginfo in aktmoduleswitches) then - begin - if (po_public in current_procinfo.procdef.procoptions) then - Tprocsym(current_procinfo.procdef.procsym).is_global:=true; - current_procinfo.procdef.concatstabto(list); - Tprocsym(current_procinfo.procdef.procsym).isstabwritten:=true; - end; -{$endif GDB} - - repeat - hs:=current_procinfo.procdef.aliasnames.getfirst; - if hs='' then - break; -{$ifdef GDB} - if (cs_debuginfo in aktmoduleswitches) and - target_info.use_function_relative_addresses then - list.concat(Tai_stab_function_name.create(strpnew(hs))); -{$endif GDB} - if (cs_profile in aktmoduleswitches) or - (po_public in current_procinfo.procdef.procoptions) then - list.concat(Tai_symbol.createname_global(hs,0)) + procedure gen_stackalloc_code(list:Taasmoutput); + var + hs : string; + stackframe : longint; + begin + {************************* Stack allocation **************************} + { and symbol entry point as well as debug information } + { will be inserted in front of the rest of this list. } + { Insert alignment and assembler names } + { Align, gprof uses 16 byte granularity } + if (cs_profile in aktmoduleswitches) then + list.concat(Tai_align.create(16)) else - list.concat(Tai_symbol.createname(hs,0)); - until false; + list.concat(Tai_align.create(aktalignment.procalign)); + +{$ifdef GDB} + if (cs_debuginfo in aktmoduleswitches) then + begin + if (po_public in current_procinfo.procdef.procoptions) then + Tprocsym(current_procinfo.procdef.procsym).is_global:=true; + current_procinfo.procdef.concatstabto(list); + Tprocsym(current_procinfo.procdef.procsym).isstabwritten:=true; + end; +{$endif GDB} + + repeat + hs:=current_procinfo.procdef.aliasnames.getfirst; + if hs='' then + break; +{$ifdef GDB} + if (cs_debuginfo in aktmoduleswitches) and + target_info.use_function_relative_addresses then + list.concat(Tai_stab_function_name.create(strpnew(hs))); +{$endif GDB} + if (cs_profile in aktmoduleswitches) or + (po_public in current_procinfo.procdef.procoptions) then + list.concat(Tai_symbol.createname_global(hs,0)) + else + list.concat(Tai_symbol.createname(hs,0)); + until false; + + { Calculate size of stackframe } + stackframe:=current_procinfo.calc_stackframe_size; - stackframe:=stackframe+tg.gettempsize; -{$ifndef m68k} - { give a warning if the limit of local variables is reached } - if stackframe>maxlocalsize then - message(cg_w_localsize_too_big); -{$endif} {$ifndef powerpc} - { at least for the ppc this applies always, so this code isn't usable (FK) } - { omit stack frame ? } - if (current_procinfo.framepointer.number=NR_STACK_POINTER_REG) then - begin - CGmessage(cg_d_stackframe_omited); - if stackframe<>0 then - cg.g_stackpointer_alloc(list,stackframe); - end - else + { at least for the ppc this applies always, so this code isn't usable (FK) } + { omit stack frame ? } + if (current_procinfo.framepointer.number=NR_STACK_POINTER_REG) then + begin + CGmessage(cg_d_stackframe_omited); + if stackframe<>0 then + cg.g_stackpointer_alloc(list,stackframe); + end + else {$endif powerpc} - begin - if (po_interrupt in current_procinfo.procdef.procoptions) then - cg.g_interrupt_stackframe_entry(list); + begin + if (po_interrupt in current_procinfo.procdef.procoptions) then + cg.g_interrupt_stackframe_entry(list); - cg.g_stackframe_entry(list,stackframe); + cg.g_stackframe_entry(list,stackframe); - {Never call stack checking before the standard system unit - has been initialized.} - if (cs_check_stack in aktlocalswitches) and (current_procinfo.procdef.proctypeoption<>potype_proginit) then - cg.g_stackcheck(list,stackframe); - end; - end; + {Never call stack checking before the standard system unit + has been initialized.} + if (cs_check_stack in aktlocalswitches) and (current_procinfo.procdef.proctypeoption<>potype_proginit) then + cg.g_stackcheck(list,stackframe); + end; + end; procedure gen_exit_code(list : TAAsmoutput;inlined:boolean); @@ -1789,7 +1788,7 @@ implementation (current_procinfo.procdef.parast.symtablelevel>normal_function_level) then list.concat(Tai_stabs.Create(strpnew( '"parent_ebp:'+tstoreddef(voidpointertype.def).numberstring+'",'+ - tostr(N_LSYM)+',0,0,'+tostr(current_procinfo.framepointer_offset)))); + tostr(N_LSYM)+',0,0,'+tostr(current_procinfo.parent_framepointer_offset)))); if (not is_void(current_procinfo.procdef.rettype.def)) then begin @@ -1988,7 +1987,11 @@ implementation end. { $Log$ - Revision 1.129 2003-07-06 15:31:20 daniel + Revision 1.130 2003-07-06 17:58:22 peter + * framepointer fixes for sparc + * parent framepointer code more generic + + Revision 1.129 2003/07/06 15:31:20 daniel * Fixed register allocator. *Lots* of fixes. Revision 1.128 2003/07/02 22:18:04 peter diff --git a/compiler/pass_2.pas b/compiler/pass_2.pas index de0740f849..4a07f6dccc 100644 --- a/compiler/pass_2.pas +++ b/compiler/pass_2.pas @@ -302,7 +302,7 @@ implementation // cleanup_regvars(current_procinfo.aktexitcode); {$endif i386} - current_procinfo.allocate_framepointer; + current_procinfo.allocate_framepointer_reg; do_secondpass(p); @@ -316,7 +316,11 @@ implementation end. { $Log$ - Revision 1.60 2003-07-06 15:31:20 daniel + Revision 1.61 2003-07-06 17:58:22 peter + * framepointer fixes for sparc + * parent framepointer code more generic + + Revision 1.60 2003/07/06 15:31:20 daniel * Fixed register allocator. *Lots* of fixes. Revision 1.59 2003/07/06 10:18:47 jonas diff --git a/compiler/pmodules.pas b/compiler/pmodules.pas index ec30da9072..dc20fcdee8 100644 --- a/compiler/pmodules.pas +++ b/compiler/pmodules.pas @@ -768,7 +768,7 @@ implementation internalerror(200304253); end; include(current_procinfo.flags,pi_do_call); - gen_stackalloc_code(list,0); + gen_stackalloc_code(list); gen_entry_code(list,false); gen_initialize_code(list,false); gen_finalize_code(list,false); @@ -1312,12 +1312,6 @@ implementation pd:=create_main_proc('main',potype_proginit,st); pd.aliasnames.insert('PASCALMAIN'); end; -{$IFDEF SPARC} - current_procinfo.After_Header; -{main function is declared as - PROCEDURE main(ArgC:Integer;ArgV,EnvP:ARRAY OF PChar):Integer;CDECL; -So, all parameters are passerd into registers in sparc architecture.} -{$ENDIF SPARC} tcgprocinfo(current_procinfo).parse_body; tcgprocinfo(current_procinfo).generate_code; tcgprocinfo(current_procinfo).resetprocdef; @@ -1452,7 +1446,11 @@ So, all parameters are passerd into registers in sparc architecture.} end. { $Log$ - Revision 1.114 2003-06-13 21:19:31 peter + Revision 1.115 2003-07-06 17:58:22 peter + * framepointer fixes for sparc + * parent framepointer code more generic + + Revision 1.114 2003/06/13 21:19:31 peter * current_procdef removed, use current_procinfo.procdef instead Revision 1.113 2003/06/09 12:23:30 peter diff --git a/compiler/psub.pas b/compiler/psub.pas index 28e55c1831..c9760dc7b3 100644 --- a/compiler/psub.pas +++ b/compiler/psub.pas @@ -654,7 +654,7 @@ implementation end; stackalloccode:=Taasmoutput.create; - gen_stackalloc_code(stackalloccode,0); + gen_stackalloc_code(stackalloccode); stackalloccode.convert_registers; aktproccode.insertlist(stackalloccode); stackalloccode.destroy; @@ -1076,15 +1076,13 @@ implementation pd.parast.foreach_static({$ifdef FPCPROCVAR}@{$endif}check_init_paras,nil); { Update parameter information } - current_procinfo.allocate_implicit_parameter; + if (current_procinfo.procdef.parast.symtablelevel>normal_function_level) then + current_procinfo.allocate_parent_framepointer_parameter; { add implicit pushes for interrupt routines } if (po_interrupt in pd.procoptions) then current_procinfo.allocate_interrupt_parameter; - { Calculate offsets } - current_procinfo.after_header; - { set _FAIL as keyword if constructor } if (pd.proctypeoption=potype_constructor) then begin @@ -1254,7 +1252,11 @@ begin end. { $Log$ - Revision 1.131 2003-07-06 15:31:21 daniel + Revision 1.132 2003-07-06 17:58:22 peter + * framepointer fixes for sparc + * parent framepointer code more generic + + Revision 1.131 2003/07/06 15:31:21 daniel * Fixed register allocator. *Lots* of fixes. Revision 1.130 2003/07/05 20:15:24 jonas diff --git a/compiler/sparc/cgcpu.pas b/compiler/sparc/cgcpu.pas index ee82c22b2a..a4b55c598a 100644 --- a/compiler/sparc/cgcpu.pas +++ b/compiler/sparc/cgcpu.pas @@ -74,6 +74,7 @@ interface procedure a_jmp_flags(list:TAasmOutput;const f:TResFlags;l:tasmlabel);override; procedure g_flags2reg(list:TAasmOutput;Size:TCgSize;const f:tresflags;reg:TRegister);override; procedure g_overflowCheck(List:TAasmOutput;const Loc:TLocation;def:TDef);override; + procedure g_save_parent_framepointer_param(list:taasmoutput);override; procedure g_stackframe_entry(list:TAasmOutput;localsize:LongInt);override; procedure g_restore_all_registers(list:TAasmOutput;accused,acchiused:boolean);override; procedure g_restore_frame_pointer(list:TAasmOutput);override; @@ -637,10 +638,10 @@ implementation end; end else - list.concat(taicpu.op_reg_const_reg(A_ADD,ref.base,ref.offset,r)); + list.concat(taicpu.op_reg_const_reg(A_ADD,ref.base,aword(ref.offset),r)); end else - list.concat(taicpu.op_reg_const_reg(A_ADD,zeroreg,ref.offset,r)); + list.concat(taicpu.op_reg_const_reg(A_ADD,zeroreg,aword(ref.offset),r)); end else { Both base and index } @@ -868,6 +869,19 @@ implementation { *********** entry/exit code and address loading ************ } + procedure tcgsparc.g_save_parent_framepointer_param(list:taasmoutput); + var + hreg : tregister; + href : treference; + begin + reference_reset_base(href,current_procinfo.framepointer,PARENT_FRAMEPOINTER_OFFSET); + { Parent framepointer is always pushed in o0 } + hreg.enum:=R_INTREGISTER; + hreg.number:=NR_O0; + a_load_reg_ref(list,OS_ADDR,OS_ADDR,hreg,href); + end; + + procedure TCgSparc.g_stackframe_entry(list:TAasmOutput;LocalSize:LongInt); var r : tregister; @@ -1241,7 +1255,11 @@ begin end. { $Log$ - Revision 1.62 2003-07-03 21:09:53 peter + Revision 1.63 2003-07-06 17:58:22 peter + * framepointer fixes for sparc + * parent framepointer code more generic + + Revision 1.62 2003/07/03 21:09:53 peter * delay slot NOPs and comments added * a_loadaddr_ref_reg fixed and optimized to reuse passed register if it is not used by the ref diff --git a/compiler/sparc/cpubase.pas b/compiler/sparc/cpubase.pas index 83758c3a47..40b2f1a095 100644 --- a/compiler/sparc/cpubase.pas +++ b/compiler/sparc/cpubase.pas @@ -785,9 +785,10 @@ type usableregsaddr = []; c_countusableregsaddr = 0; - firstsaveintreg = RS_G0; { L0..L7 are already saved, I0..O7 are parameter } - lastsaveintreg = RS_G7; - firstsavefpureg = R_F0; +{$warning firstsaveintreg shall be RS_NO} + firstsaveintreg = RS_L0; { Temporary, having RS_NO is broken } + lastsaveintreg = RS_L0; { L0..L7 are already saved, I0..O7 are parameter } + firstsavefpureg = R_F2; { F0..F1 is used for return value } lastsavefpureg = R_F31; firstsavemmreg = R_NO; lastsavemmreg = R_NO; @@ -933,6 +934,8 @@ type FPU_RESULT_REG = R_F0; mmresultreg = R_NO; + PARENT_FRAMEPOINTER_OFFSET = 68; { o0 } + {***************************************************************************** GCC /ABI linking information *****************************************************************************} @@ -1051,7 +1054,11 @@ implementation end. { $Log$ - Revision 1.44 2003-07-02 22:18:04 peter + Revision 1.45 2003-07-06 17:58:22 peter + * framepointer fixes for sparc + * parent framepointer code more generic + + Revision 1.44 2003/07/02 22:18:04 peter * paraloc splitted in callerparaloc,calleeparaloc * sparc calling convention updates diff --git a/compiler/sparc/cpupara.pas b/compiler/sparc/cpupara.pas index c26a3b5e3f..2ad98d017b 100644 --- a/compiler/sparc/cpupara.pas +++ b/compiler/sparc/cpupara.pas @@ -122,14 +122,15 @@ implementation procedure TSparcParaManager.create_paraloc_info(p:TAbstractProcDef; side: tcallercallee); var nextintreg : tsuperregister; - nextfloatreg : toldregister; stack_offset : longint; hp : tparaitem; is_64bit : boolean; paraloc : tparalocation; begin nextintreg:=RS_O0; - nextfloatreg:=R_F0; + { Nested procedures have the parent framepoint in o0 } + if p.parast.symtablelevel>normal_function_level then + inc(NextIntReg); stack_offset:=92; hp:=TParaItem(p.para.First); while assigned(hp) do @@ -275,7 +276,11 @@ begin end. { $Log$ - Revision 1.23 2003-07-05 20:11:41 jonas + Revision 1.24 2003-07-06 17:58:22 peter + * framepointer fixes for sparc + * parent framepointer code more generic + + Revision 1.23 2003/07/05 20:11:41 jonas * create_paraloc_info() is now called separately for the caller and callee info * fixed ppc cycle diff --git a/compiler/sparc/cpupi.pas b/compiler/sparc/cpupi.pas index 6cb4cce0dc..b3d88b115a 100644 --- a/compiler/sparc/cpupi.pas +++ b/compiler/sparc/cpupi.pas @@ -1,4 +1,4 @@ -{***************************************************************************** +{ $Id$ Copyright (c) 2002 by Florian Klaempfl @@ -18,11 +18,11 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - ****************************************************************************} -{ This unit contains the CPU specific part of tprocinfo. } + **************************************************************************** +} unit cpupi; -{$I fpcdefs.inc} +{$i fpcdefs.inc} interface @@ -33,75 +33,64 @@ interface type TSparcProcInfo=class(tcgprocinfo) - { overall size of allocated stack space, currently this is used for the - PowerPC only } - LocalSize:aword; - {max of space need for parameters, currently used by the PowerPC port only} - maxpushedparasize:aword; + private + maxpushedparasize : longint; + public constructor create(aparent:tprocinfo);override; - { According the the SPARC ABI the standard stack frame must include : - * 16 word save for the in and local registers in case of overflow/underflow. - this save area always must exist at the %o6+0, - * software conventions requires space for the aggregate return value pointer, even if the word is not used, - * althogh the first six words of arguments reside in registers, the standard - stack frame reserves space for them. Arguments beond the sixth reside on the - stack as in the Intel architecture, - * other areas depend on the compiler and the code being compiled. The - standard calling sequence does not define a maximum stack frame size, nor does - it restrict how a language system uses the "unspecified" areas of the standard - stack frame.} - procedure after_header;override; - procedure after_pass1;override; + procedure allocate_push_parasize(size:longint);override; + function calc_stackframe_size:longint;override; end; implementation -uses - tgobj,paramgr,symsym,systems; -constructor TSparcprocinfo.create(aparent:tprocinfo); - begin - inherited create(aparent); - maxpushedparasize:=0; - LocalSize:=(16+1)*4; - {First 16 words are in the frame are used to save registers in case of a - register overflow/underflow.The 17th word is used to save the address of - the variable which will receive the return value of the called function} -// Return_Offset:=16*4; - end; + uses + globtype,systems, + tgobj,paramgr,symconst,symsym; - procedure TSparcprocinfo.after_header; + constructor tsparcprocinfo.create(aparent:tprocinfo); begin - { this value is necessary for nested procedures } - if assigned(procdef.localst) then - procdef.localst.address_fixup:=align(procdef.parast.address_fixup+procdef.parast.datasize,16); + inherited create(aparent); + maxpushedparasize:=0; end; -procedure TSparcProcInfo.after_pass1; - begin - with ProcDef do + + procedure tsparcprocinfo.allocate_push_parasize(size:longint); begin - {Reserve the stack for copying parameters passed into registers. By - default we reserve space for the 6 input registers if the function had - less parameters. Otherwise, we allocate data sizeof parameters} - if parast.datasize>6*4 - then - localst.address_fixup:=parast.address_fixup+parast.datasize - else - procdef.localst.address_fixup:=parast.address_fixup+6*4; - firsttemp_offset:=localst.address_fixup+localst.datasize; - with tg do - begin - SetFirstTemp(firsttemp_offset); - //LastTemp:=firsttemp_offset; - end; + if size>maxpushedparasize then + maxpushedparasize:=size; end; - end; + + + function TSparcProcInfo.calc_stackframe_size:longint; + var + savearea : longint; + begin + { ABI requires at least space to save 6 arguments } + savearea:=procdef.parast.address_fixup+max(maxpushedparasize,6*4); + { + Stackframe layout: + %fp + + + + + + %sp + } + result:=procdef.localst.datasize+tg.gettempsize+savearea; + end; + + begin cprocinfo:=TSparcProcInfo; end. { $Log$ - Revision 1.17 2003-06-13 21:19:32 peter + Revision 1.18 2003-07-06 17:58:22 peter + * framepointer fixes for sparc + * parent framepointer code more generic + + Revision 1.17 2003/06/13 21:19:32 peter * current_procdef removed, use current_procinfo.procdef instead Revision 1.16 2003/05/30 23:57:08 peter diff --git a/compiler/sparc/ncpucall.pas b/compiler/sparc/ncpucall.pas index f392cf120f..e29e591786 100644 --- a/compiler/sparc/ncpucall.pas +++ b/compiler/sparc/ncpucall.pas @@ -1,8 +1,8 @@ -{****************************************************************************** +{ $Id$ Copyright (c) 1998-2002 by Florian Klaempfl - Generate SPARC assembler for in call nodes + Generate sparc assembler for in call nodes This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,51 +18,37 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - ****************************************************************************} + **************************************************************************** +} unit ncpucall; -{$INCLUDE fpcdefs.inc} + +{$i fpcdefs.inc} + interface -uses - symdef,node,ncal,ncgcal; -type - TSparcCallNode=class(TCgCallNode) - function pass_1:TNode;override; -{Under SPARC, the frame pointer is automatically set by the SAVE instruction -which is part of the stardrad calling mechanism. This function will do nothing. -the frame pointer register is the stack pointer register of the caller, and is -set when generating function prologue in cgcpu.tcgSPARC.g_stackframe_entry} - procedure push_framepointer;override; - end; + + uses + ncgcal; + + type + tsparccallnode = class(tcgcallnode) + end; + + implementation -uses - systems, - cutils,verbose, - paramgr, - cgbase, - nmem,nld,ncnv, - cgobj,tgobj,rgobj,rgcpu,cgcpu,cpupi; -function TSparcCallNode.pass_1:TNode; - begin - result:=inherited pass_1; - if assigned(result) - then - exit; - if ProcDefinition is TProcDef - then - with TProcDef(procdefinition).parast do - if datasize>TSparcProcInfo(current_procinfo).maxpushedparasize - then - TSparcProcInfo(current_procinfo).maxpushedparasize:=datasize; - end; -procedure TSparcCallNode.push_framepointer; - begin - end; + + uses + ncal; + begin - ccallnode:=TSparcCallNode; + ccallnode:=TSparcCallNode; end. { $Log$ - Revision 1.12 2003-06-13 21:19:32 peter + Revision 1.13 2003-07-06 17:58:22 peter + * framepointer fixes for sparc + * parent framepointer code more generic + + Revision 1.12 2003/06/13 21:19:32 peter * current_procdef removed, use current_procinfo.procdef instead Revision 1.11 2003/04/28 09:49:58 mazen diff --git a/compiler/systems/i_linux.pas b/compiler/systems/i_linux.pas index 247c9bdb99..d0eb7639d3 100644 --- a/compiler/systems/i_linux.pas +++ b/compiler/systems/i_linux.pas @@ -403,8 +403,8 @@ unit i_linux; localalignmin : 0; localalignmax : 4; paraalign : 4; - recordalignmin : 0; - recordalignmax : 2; + recordalignmin : 4; + recordalignmax : 4; maxCrecordalign : 4 ); first_parm_offset : (16+1)*4; @@ -447,14 +447,18 @@ initialization {$endif CPUSPARC} {$ifdef CPUPOWERPC} {$ifdef linux} - set_source_info(system_powerpc_linux_info); + set_source_info(system_powerpc_linux_info); {$endif linux} {$endif CPUPOWERPC} end. { $Log$ - Revision 1.8 2003-05-31 18:14:06 jonas + Revision 1.9 2003-07-06 17:58:22 peter + * framepointer fixes for sparc + * parent framepointer code more generic + + Revision 1.8 2003/05/31 18:14:06 jonas * add default system for ppc Revision 1.7 2003/05/19 12:15:28 florian diff --git a/compiler/tgobj.pas b/compiler/tgobj.pas index 8886cb941b..ebd1aab7b6 100644 --- a/compiler/tgobj.pas +++ b/compiler/tgobj.pas @@ -157,9 +157,6 @@ unit tgobj; {$else powerpc} direction:=-1; {$endif powerpc} -{$IFDEF SPARC} - Direction:=1; -{$ENDIF SPARC} end; @@ -554,7 +551,11 @@ finalization end. { $Log$ - Revision 1.35 2003-06-03 13:01:59 daniel + Revision 1.36 2003-07-06 17:58:22 peter + * framepointer fixes for sparc + * parent framepointer code more generic + + Revision 1.35 2003/06/03 13:01:59 daniel * Register allocator finished Revision 1.34 2003/05/17 13:30:08 jonas