diff --git a/compiler/arm/cpupara.pas b/compiler/arm/cpupara.pas index 52aea290cb..d8da268e33 100644 --- a/compiler/arm/cpupara.pas +++ b/compiler/arm/cpupara.pas @@ -29,7 +29,7 @@ unit cpupara; uses globtype,globals, aasmtai,aasmdata, - cpuinfo,cpubase,cgbase, + cpuinfo,cpubase,cgbase,cgutils, symconst,symbase,symtype,symdef,parabase,paramgr; type @@ -41,10 +41,12 @@ unit cpupara; procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);override; function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override; function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override; + function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation;override; private procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword); function create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist; var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword):longint; + procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee); end; implementation @@ -52,8 +54,7 @@ unit cpupara; uses verbose,systems, rgobj, - defutil,symsym, - cgutils; + defutil,symsym; function tarmparamanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset; @@ -428,40 +429,40 @@ unit cpupara; end; - function tarmparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint; + procedure tarmparamanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee); + begin + p.funcretloc[side]:=get_funcretloc(p,side,p.returndef); + end; + + + function tarmparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation; var - cur_stack_offset: aword; - curintreg, curfloatreg, curmmreg: tsuperregister; retcgsize : tcgsize; begin - init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset); - - result:=create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset); - { Constructors return self instead of a boolean } if (p.proctypeoption=potype_constructor) then retcgsize:=OS_ADDR else - retcgsize:=def_cgsize(p.returndef); + retcgsize:=def_cgsize(def); - location_reset(p.funcretloc[side],LOC_INVALID,OS_NO); - p.funcretloc[side].size:=retcgsize; + location_reset(result,LOC_INVALID,OS_NO); + result.size:=retcgsize; { void has no location } - if is_void(p.returndef) then + if is_void(def) then begin - location_reset(p.funcretloc[side],LOC_VOID,OS_NO); + location_reset(result,LOC_VOID,OS_NO); exit; end; { Return is passed as var parameter } - if ret_in_param(p.returndef,p.proccalloption) then + if ret_in_param(def,p.proccalloption) then begin - p.funcretloc[side].loc:=LOC_REFERENCE; - p.funcretloc[side].size:=retcgsize; + result.loc:=LOC_REFERENCE; + result.size:=retcgsize; exit; end; { Return in FPU register? } - if p.returndef.typ=floatdef then + if def.typ=floatdef then begin if (p.proccalloption in [pocall_softfloat]) or (cs_fp_emulation in current_settings.moduleswitches) then begin @@ -470,17 +471,17 @@ unit cpupara; OS_F64: begin { low } - p.funcretloc[side].loc:=LOC_REGISTER; - p.funcretloc[side].register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG; - p.funcretloc[side].register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG; - p.funcretloc[side].size:=OS_64; + result.loc:=LOC_REGISTER; + result.register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG; + result.register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG; + result.size:=OS_64; end; OS_32, OS_F32: begin - p.funcretloc[side].loc:=LOC_REGISTER; - p.funcretloc[side].register:=NR_FUNCTION_RETURN_REG; - p.funcretloc[side].size:=OS_32; + result.loc:=LOC_REGISTER; + result.register:=NR_FUNCTION_RETURN_REG; + result.size:=OS_32; end; else internalerror(2005082603); @@ -488,8 +489,8 @@ unit cpupara; end else begin - p.funcretloc[side].loc:=LOC_FPUREGISTER; - p.funcretloc[side].register:=NR_FPU_RESULT_REG; + result.loc:=LOC_FPUREGISTER; + result.register:=NR_FPU_RESULT_REG; end; end { Return in register } @@ -498,17 +499,29 @@ unit cpupara; if retcgsize in [OS_64,OS_S64] then begin { low } - p.funcretloc[side].loc:=LOC_REGISTER; - p.funcretloc[side].register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG; - p.funcretloc[side].register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG; + result.loc:=LOC_REGISTER; + result.register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG; + result.register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG; end else begin - p.funcretloc[side].loc:=LOC_REGISTER; - p.funcretloc[side].register:=NR_FUNCTION_RETURN_REG; + result.loc:=LOC_REGISTER; + result.register:=NR_FUNCTION_RETURN_REG; end; - end; + end; + + + function tarmparamanager.create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint; + var + cur_stack_offset: aword; + curintreg, curfloatreg, curmmreg: tsuperregister; + begin + init_values(curintreg,curfloatreg,curmmreg,cur_stack_offset); + + result:=create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset); + + create_funcretloc_info(p,side); end; diff --git a/compiler/avr/cpupara.pas b/compiler/avr/cpupara.pas index b56fc79db0..1332b67af9 100644 --- a/compiler/avr/cpupara.pas +++ b/compiler/avr/cpupara.pas @@ -29,7 +29,7 @@ unit cpupara; uses globtype,globals, aasmtai,aasmdata, - cpuinfo,cpubase,cgbase, + cpuinfo,cpubase,cgbase,cgutils, symconst,symbase,symtype,symdef,parabase,paramgr; type @@ -52,8 +52,7 @@ unit cpupara; uses verbose,systems, rgobj, - defutil,symsym, - cgutils; + defutil,symsym; function tavrparamanager.get_volatile_registers_int(calloption : tproccalloption):tcpuregisterset; @@ -396,30 +395,44 @@ unit cpupara; result:=create_paraloc_info_intern(p,side,p.paras,curintreg,curfloatreg,curmmreg,cur_stack_offset); + create_funcretloc_info(p,side); + end; + + + procedure tavrparamanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee); + begin + p.funcretloc[side]:=get_funcretloc(p,side,p.returndef); + end; + + + function tavrparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation; + var + retcgsize : tcgsize; + begin { Constructors return self instead of a boolean } if (p.proctypeoption=potype_constructor) then retcgsize:=OS_ADDR else - retcgsize:=def_cgsize(p.returndef); + retcgsize:=def_cgsize(def); - location_reset(p.funcretloc[side],LOC_INVALID,OS_NO); - p.funcretloc[side].size:=retcgsize; + location_reset(result,LOC_INVALID,OS_NO); + result.size:=retcgsize; { void has no location } - if is_void(p.returndef) then + if is_void(def) then begin - location_reset(p.funcretloc[side],LOC_VOID,OS_NO); + location_reset(result,LOC_VOID,OS_NO); exit; end; { Return is passed as var parameter } - if ret_in_param(p.returndef,p.proccalloption) then + if ret_in_param(def,p.proccalloption) then begin - p.funcretloc[side].loc:=LOC_REFERENCE; - p.funcretloc[side].size:=retcgsize; + result.loc:=LOC_REFERENCE; + result.size:=retcgsize; exit; end; { Return in FPU register? } - if p.returndef.typ=floatdef then + if def.typ=floatdef then begin if (p.proccalloption in [pocall_softfloat]) or (cs_fp_emulation in current_settings.moduleswitches) then begin @@ -428,17 +441,17 @@ unit cpupara; OS_F64: begin { low } - p.funcretloc[side].loc:=LOC_REGISTER; - p.funcretloc[side].register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG; - p.funcretloc[side].register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG; - p.funcretloc[side].size:=OS_64; + result.loc:=LOC_REGISTER; + result.register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG; + result.register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG; + result.size:=OS_64; end; OS_32, OS_F32: begin - p.funcretloc[side].loc:=LOC_REGISTER; - p.funcretloc[side].register:=NR_FUNCTION_RETURN_REG; - p.funcretloc[side].size:=OS_32; + result.loc:=LOC_REGISTER; + result.register:=NR_FUNCTION_RETURN_REG; + result.size:=OS_32; end; else internalerror(2005082603); @@ -446,8 +459,8 @@ unit cpupara; end else begin - p.funcretloc[side].loc:=LOC_FPUREGISTER; - p.funcretloc[side].register:=NR_FPU_RESULT_REG; + result.loc:=LOC_FPUREGISTER; + result.register:=NR_FPU_RESULT_REG; end; end { Return in register } @@ -456,18 +469,18 @@ unit cpupara; if retcgsize in [OS_64,OS_S64] then begin { low } - p.funcretloc[side].loc:=LOC_REGISTER; - p.funcretloc[side].register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG; - p.funcretloc[side].register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG; + result.loc:=LOC_REGISTER; + result.register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG; + result.register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG; end else begin - p.funcretloc[side].loc:=LOC_REGISTER; - p.funcretloc[side].register:=NR_FUNCTION_RETURN_REG; + result.loc:=LOC_REGISTER; + result.register:=NR_FUNCTION_RETURN_REG; end; end; - end; + end; function tavrparamanager.create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint; diff --git a/compiler/i386/cpupara.pas b/compiler/i386/cpupara.pas index fc40612108..8da91c4a64 100644 --- a/compiler/i386/cpupara.pas +++ b/compiler/i386/cpupara.pas @@ -27,7 +27,7 @@ unit cpupara; uses globtype, - aasmtai,aasmdata,cpubase,cgbase, + aasmtai,aasmdata,cpubase,cgbase,cgutils, symconst,symtype,symsym,symdef, parabase,paramgr; @@ -49,6 +49,7 @@ unit cpupara; function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override; function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override; procedure createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;var cgpara:TCGPara);override; + function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation;override; private procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee); procedure create_stdcall_paraloc_info(p : tabstractprocdef; side: tcallercallee;paras:tparalist;var parasize:longint); @@ -61,8 +62,7 @@ unit cpupara; uses cutils, systems,verbose, - defutil, - cgutils; + defutil; const parasupregs : array[0..2] of tsuperregister = (RS_EAX,RS_EDX,RS_ECX); @@ -307,6 +307,12 @@ unit cpupara; procedure ti386paramanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee); + begin + p.funcretloc[side]:=get_funcretloc(p,side,p.returndef); + end; + + + function ti386paramanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation; var retcgsize : tcgsize; begin @@ -314,28 +320,28 @@ unit cpupara; if (p.proctypeoption=potype_constructor) then retcgsize:=OS_ADDR else - retcgsize:=def_cgsize(p.returndef); + retcgsize:=def_cgsize(def); - location_reset(p.funcretloc[side],LOC_INVALID,OS_NO); + location_reset(result,LOC_INVALID,OS_NO); { void has no location } - if is_void(p.returndef) then + if is_void(def) then begin - location_reset(p.funcretloc[side],LOC_VOID,OS_NO); + location_reset(result,LOC_VOID,OS_NO); exit; end; { Return is passed as var parameter } - if ret_in_param(p.returndef,p.proccalloption) then + if ret_in_param(def,p.proccalloption) then begin - p.funcretloc[side].loc:=LOC_REFERENCE; - p.funcretloc[side].size:=retcgsize; + result.loc:=LOC_REFERENCE; + result.size:=retcgsize; exit; end; { Return in FPU register? } - if p.returndef.typ=floatdef then + if def.typ=floatdef then begin - p.funcretloc[side].loc:=LOC_FPUREGISTER; - p.funcretloc[side].register:=NR_FPU_RESULT_REG; - p.funcretloc[side].size:=retcgsize; + result.loc:=LOC_FPUREGISTER; + result.register:=NR_FPU_RESULT_REG; + result.size:=retcgsize; end else { Return in register } @@ -343,26 +349,26 @@ unit cpupara; if retcgsize in [OS_64,OS_S64] then begin { low 32bits } - p.funcretloc[side].loc:=LOC_REGISTER; - p.funcretloc[side].size:=OS_64; + result.loc:=LOC_REGISTER; + result.size:=OS_64; if side=callerside then - p.funcretloc[side].register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG + result.register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG else - p.funcretloc[side].register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG; + result.register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG; { high 32bits } if side=callerside then - p.funcretloc[side].register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG + result.register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG else - p.funcretloc[side].register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG; + result.register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG; end else begin - p.funcretloc[side].loc:=LOC_REGISTER; - p.funcretloc[side].size:=retcgsize; + result.loc:=LOC_REGISTER; + result.size:=retcgsize; if side=callerside then - p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize)) + result.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize)) else - p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize)); + result.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize)); end; end; end; diff --git a/compiler/ncgcal.pas b/compiler/ncgcal.pas index 8a05013254..12f55ddda8 100644 --- a/compiler/ncgcal.pas +++ b/compiler/ncgcal.pas @@ -45,6 +45,8 @@ interface tcgcallnode = class(tcallnode) private + retloc: tlocation; + procedure handle_return_value; procedure release_unused_return_value; procedure release_para_temps; @@ -510,7 +512,6 @@ implementation var tmpcgsize, cgsize : tcgsize; - retloc : tlocation; {$ifdef cpu64bitaddr} ref : treference; {$endif cpu64bitaddr} @@ -529,12 +530,12 @@ implementation end; { Load normal (ordinal,float,pointer) result value from accumulator } - cgsize:=procdefinition.funcretloc[callerside].size; - case procdefinition.funcretloc[callerside].loc of + cgsize:=retloc.size; + case retloc.loc of LOC_FPUREGISTER: begin location_reset(location,LOC_FPUREGISTER,cgsize); - location.register:=procdefinition.funcretloc[callerside].register; + location.register:=retloc.register; {$ifdef x86} tcgx86(cg).inc_fpu_stack; {$else x86} @@ -548,8 +549,8 @@ implementation (mantis #13536). } if (cnf_return_value_used in callnodeflags) then begin - if getsupreg(procdefinition.funcretloc[callerside].register)LOC_REGISTER then internalerror(2009042001); { See #13536 comment above. } @@ -591,7 +591,6 @@ implementation {$else cpu64bitaddr} if cgsize in [OS_64,OS_S64] then begin - retloc:=procdefinition.funcretloc[callerside]; if retloc.loc<>LOC_REGISTER then internalerror(200409141); { See #13536 comment above. } @@ -621,8 +620,8 @@ implementation { See #13536 comment above. } if (cnf_return_value_used in callnodeflags) then begin - if getsupreg(procdefinition.funcretloc[callerside].register)OS_NO then - location_free(current_asmdata.CurrAsmList,procdefinition.funcretloc[callerside]); + if retloc.size<>OS_NO then + location_free(current_asmdata.CurrAsmList,retloc); location_reset(location,LOC_VOID,OS_NO); end; end; @@ -944,16 +943,49 @@ implementation { Include Function result registers } if (not is_void(resultdef)) then begin - case procdefinition.funcretloc[callerside].loc of + { The forced returntype may have a different size than the one + declared for the procdef } + if not assigned(typedef) then + retloc:=procdefinition.funcretloc[callerside] + else + retloc:=paramanager.get_funcretloc(procdefinition,callerside,typedef); + case retloc.loc of LOC_REGISTER, LOC_CREGISTER: - include(regs_to_save_int,getsupreg(procdefinition.funcretloc[callerside].register)); + begin +{$ifdef cpu64bitaddr} + { x86-64 system v abi: + structs with up to 16 bytes are returned in registers } + if retloc.size in [OS_128,OS_S128] then + begin + include(regs_to_save_int,getsupreg(retloc.register)); + include(regs_to_save_int,getsupreg(retloc.registerhi)); + end + else +{$else cpu64bitaddr} + if retloc.size in [OS_64,OS_S64] then + begin + include(regs_to_save_int,getsupreg(retloc.register64.reglo)); + include(regs_to_save_int,getsupreg(retloc.register64.reghi)); + end + else +{$endif not cpu64bitaddr} + include(regs_to_save_int,getsupreg(retloc.register)); + end; LOC_FPUREGISTER, LOC_CFPUREGISTER: - include(regs_to_save_fpu,getsupreg(procdefinition.funcretloc[callerside].register)); + begin + include(regs_to_save_fpu,getsupreg(retloc.register)); +{$ifdef SPARC} + { SPARC uses two successive single precision fpu registers + for double-precision values } + if retloc.size=OS_F64 then + include(regs_to_save_fpu,succ(getsupreg(retloc.register))); +{$endif SPARC} + end; LOC_MMREGISTER, LOC_CMMREGISTER: - include(regs_to_save_mm,getsupreg(procdefinition.funcretloc[callerside].register)); + include(regs_to_save_mm,getsupreg(retloc.register)); LOC_REFERENCE, LOC_VOID: ; @@ -1145,26 +1177,32 @@ implementation function result } if (not is_void(resultdef)) then begin - case procdefinition.funcretloc[callerside].loc of + case retloc.loc of LOC_REGISTER, LOC_CREGISTER: begin {$ifndef cpu64bitalu} - if procdefinition.funcretloc[callerside].size in [OS_64,OS_S64] then + if retloc.size in [OS_64,OS_S64] then begin - exclude(regs_to_save_int,getsupreg(procdefinition.funcretloc[callerside].register64.reghi)); - exclude(regs_to_save_int,getsupreg(procdefinition.funcretloc[callerside].register64.reglo)); + exclude(regs_to_save_int,getsupreg(retloc.register64.reghi)); + exclude(regs_to_save_int,getsupreg(retloc.register64.reglo)); + end +{$else not cpu64bitalu} + if retloc.size in [OS_128,OS_S128] then + begin + exclude(regs_to_save_int,getsupreg(retloc.register)); + exclude(regs_to_save_int,getsupreg(retloc.registerhi)); end - else {$endif not cpu64bitalu} - exclude(regs_to_save_int,getsupreg(procdefinition.funcretloc[callerside].register)); + else + exclude(regs_to_save_int,getsupreg(retloc.register)); end; LOC_FPUREGISTER, LOC_CFPUREGISTER: - exclude(regs_to_save_fpu,getsupreg(procdefinition.funcretloc[callerside].register)); + exclude(regs_to_save_fpu,getsupreg(retloc.register)); LOC_MMREGISTER, LOC_CMMREGISTER: - exclude(regs_to_save_mm,getsupreg(procdefinition.funcretloc[callerside].register)); + exclude(regs_to_save_mm,getsupreg(retloc.register)); LOC_REFERENCE, LOC_VOID: ; diff --git a/compiler/paramgr.pas b/compiler/paramgr.pas index be91952a56..d5002783ea 100644 --- a/compiler/paramgr.pas +++ b/compiler/paramgr.pas @@ -29,7 +29,7 @@ unit paramgr; uses cclasses,globtype, - cpubase,cgbase, + cpubase,cgbase,cgutils, parabase, aasmtai,aasmdata, symconst,symtype,symsym,symdef; @@ -96,6 +96,12 @@ unit paramgr; } function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;virtual;abstract; + { Returns the location of the function result if p had def as + function result instead of its actual result. Used if the compiler + forces the function result to something different than the real + result. } + function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation;virtual;abstract; + { This is used to populate the location information on all parameters for the routine when it is being inlined. It returns the size allocated on the stack @@ -124,7 +130,7 @@ implementation uses systems, - cgobj,tgobj,cgutils, + cgobj,tgobj, defutil,verbose; { true if the location in paraloc can be reused as localloc } diff --git a/compiler/powerpc/cpupara.pas b/compiler/powerpc/cpupara.pas index f593d6e15b..f99ccc830d 100644 --- a/compiler/powerpc/cpupara.pas +++ b/compiler/powerpc/cpupara.pas @@ -29,7 +29,7 @@ unit cpupara; aasmtai,aasmdata, cpubase, symconst,symtype,symdef,symsym, - paramgr,parabase,cgbase; + paramgr,parabase,cgbase,cgutils; type tppcparamanager = class(tparamanager) @@ -40,6 +40,7 @@ unit cpupara; procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);override; function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override; function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override; + function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation;override; procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee); private procedure init_values(var curintreg, curfloatreg, curmmreg: tsuperregister; var cur_stack_offset: aword); @@ -53,7 +54,6 @@ unit cpupara; uses verbose,systems, defutil, - cgutils, procinfo,cpupi; @@ -245,6 +245,12 @@ unit cpupara; procedure tppcparamanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee); + begin + p.funcretloc[side]:=get_funcretloc(p,side,p.returndef); + end; + + + function tppcparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation; var retcgsize : tcgsize; begin @@ -252,29 +258,29 @@ unit cpupara; if (p.proctypeoption=potype_constructor) then retcgsize:=OS_ADDR else - retcgsize:=def_cgsize(p.returndef); + retcgsize:=def_cgsize(def); - location_reset(p.funcretloc[side],LOC_INVALID,OS_NO); - p.funcretloc[side].size:=retcgsize; + location_reset(result,LOC_INVALID,OS_NO); + result.size:=retcgsize; { void has no location } - if is_void(p.returndef) then + if is_void(def) then begin - p.funcretloc[side].loc:=LOC_VOID; + result.loc:=LOC_VOID; exit; end; { Return is passed as var parameter } - if ret_in_param(p.returndef,p.proccalloption) then + if ret_in_param(def,p.proccalloption) then begin - p.funcretloc[side].loc:=LOC_REFERENCE; - p.funcretloc[side].size:=retcgsize; + result.loc:=LOC_REFERENCE; + result.size:=retcgsize; exit; end; { Return in FPU register? } - if p.returndef.typ=floatdef then + if def.typ=floatdef then begin - p.funcretloc[side].loc:=LOC_FPUREGISTER; - p.funcretloc[side].register:=NR_FPU_RESULT_REG; - p.funcretloc[side].size:=retcgsize; + result.loc:=LOC_FPUREGISTER; + result.register:=NR_FPU_RESULT_REG; + result.size:=retcgsize; end else { Return in register } @@ -283,26 +289,26 @@ unit cpupara; if retcgsize in [OS_64,OS_S64] then begin { low 32bits } - p.funcretloc[side].loc:=LOC_REGISTER; + result.loc:=LOC_REGISTER; if side=callerside then - p.funcretloc[side].register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG + result.register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG else - p.funcretloc[side].register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG; + result.register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG; { high 32bits } if side=callerside then - p.funcretloc[side].register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG + result.register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG else - p.funcretloc[side].register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG; + result.register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG; end else {$endif cpu64bitaddr} begin - p.funcretloc[side].loc:=LOC_REGISTER; - p.funcretloc[side].size:=retcgsize; + result.loc:=LOC_REGISTER; + result.size:=retcgsize; if side=callerside then - p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize)) + result.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize)) else - p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize)); + result.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize)); end; end; end; diff --git a/compiler/powerpc64/cpupara.pas b/compiler/powerpc64/cpupara.pas index 448e01663a..b11202b264 100644 --- a/compiler/powerpc64/cpupara.pas +++ b/compiler/powerpc64/cpupara.pas @@ -29,7 +29,7 @@ uses aasmtai,aasmdata, cpubase, symconst, symtype, symdef, symsym, - paramgr, parabase, cgbase; + paramgr, parabase, cgbase, cgutils; type tppcparamanager = class(tparamanager) @@ -45,6 +45,7 @@ type function create_paraloc_info(p: tabstractprocdef; side: tcallercallee): longint; override; function create_varargs_paraloc_info(p: tabstractprocdef; varargspara: tvarargsparalist): longint; override; + function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation;override; procedure create_funcretloc_info(p: tabstractprocdef; side: tcallercallee); private @@ -62,7 +63,6 @@ implementation uses verbose, systems, defutil, - cgutils, procinfo, cpupi; function tppcparamanager.get_volatile_registers_int(calloption: @@ -204,6 +204,12 @@ end; procedure tppcparamanager.create_funcretloc_info(p: tabstractprocdef; side: tcallercallee); +begin + p.funcretloc[side]:=get_funcretloc(p,side,p.returndef); +end; + +function tppcparamanager.get_funcretloc(p : tabstractprocdef; side: + tcallercallee; def: tdef): tlocation; var retcgsize: tcgsize; begin @@ -211,37 +217,37 @@ begin if (p.proctypeoption = potype_constructor) then retcgsize := OS_ADDR else - retcgsize := def_cgsize(p.returndef); + retcgsize := def_cgsize(def); - location_reset(p.funcretloc[side], LOC_INVALID, OS_NO); - p.funcretloc[side].size := retcgsize; + location_reset(result, LOC_INVALID, OS_NO); + result.size := retcgsize; { void has no location } - if is_void(p.returndef) then begin - p.funcretloc[side].loc := LOC_VOID; + if is_void(def) then begin + result.loc := LOC_VOID; exit; end; { Return is passed as var parameter } - if ret_in_param(p.returndef, p.proccalloption) then + if ret_in_param(def, p.proccalloption) then begin - p.funcretloc[side].loc := LOC_REFERENCE; - p.funcretloc[side].size := retcgsize; + result.loc := LOC_REFERENCE; + result.size := retcgsize; exit; end; { Return in FPU register? } - if p.returndef.typ = floatdef then begin - p.funcretloc[side].loc := LOC_FPUREGISTER; - p.funcretloc[side].register := NR_FPU_RESULT_REG; - p.funcretloc[side].size := retcgsize; + if def.typ = floatdef then begin + result.loc := LOC_FPUREGISTER; + result.register := NR_FPU_RESULT_REG; + result.size := retcgsize; end else { Return in register } begin - p.funcretloc[side].loc := LOC_REGISTER; - p.funcretloc[side].size := retcgsize; + result.loc := LOC_REGISTER; + result.size := retcgsize; if side = callerside then - p.funcretloc[side].register := newreg(R_INTREGISTER, + result.register := newreg(R_INTREGISTER, RS_FUNCTION_RESULT_REG, cgsize2subreg(R_INTREGISTER, retcgsize)) else - p.funcretloc[side].register := newreg(R_INTREGISTER, + result.register := newreg(R_INTREGISTER, RS_FUNCTION_RETURN_REG, cgsize2subreg(R_INTREGISTER, retcgsize)); end; end; diff --git a/compiler/sparc/cpupara.pas b/compiler/sparc/cpupara.pas index 05cdb20d8b..c4e3efe460 100644 --- a/compiler/sparc/cpupara.pas +++ b/compiler/sparc/cpupara.pas @@ -28,7 +28,7 @@ interface cclasses, aasmtai,aasmdata, cpubase,cpuinfo, - symconst,symbase,symsym,symtype,symdef,paramgr,parabase,cgbase; + symconst,symbase,symsym,symtype,symdef,paramgr,parabase,cgbase,cgutils; type TSparcParaManager=class(TParaManager) @@ -41,6 +41,7 @@ interface procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara : TCGPara);override; function create_paraloc_info(p : TAbstractProcDef; side: tcallercallee):longint;override; function create_varargs_paraloc_info(p : TAbstractProcDef; varargspara:tvarargsparalist):longint;override; + function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation;override; private procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee); procedure create_paraloc_info_intern(p : tabstractprocdef; side: tcallercallee; paras: tparalist; @@ -52,7 +53,7 @@ implementation uses cutils,verbose,systems, defutil, - cgutils,cgobj; + cgobj; type tparasupregs = array[0..5] of tsuperregister; @@ -139,6 +140,12 @@ implementation procedure tsparcparamanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee); + begin + p.funcretloc[side]:=get_funcretloc(p,side,p.returndef); + end; + + + function tsparcparamanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation; var retcgsize : tcgsize; begin @@ -146,31 +153,31 @@ implementation if (p.proctypeoption=potype_constructor) then retcgsize:=OS_ADDR else - retcgsize:=def_cgsize(p.returndef); + retcgsize:=def_cgsize(def); - location_reset(p.funcretloc[side],LOC_INVALID,OS_NO); - p.funcretloc[side].size:=retcgsize; + location_reset(result,LOC_INVALID,OS_NO); + result.size:=retcgsize; { void has no location } - if is_void(p.returndef) then + if is_void(def) then begin - p.funcretloc[side].loc:=LOC_VOID; + result.loc:=LOC_VOID; exit; end; { Return is passed as var parameter } - if ret_in_param(p.returndef,p.proccalloption) then + if ret_in_param(def,p.proccalloption) then begin - p.funcretloc[side].loc:=LOC_REFERENCE; - p.funcretloc[side].size:=retcgsize; + result.loc:=LOC_REFERENCE; + result.size:=retcgsize; exit; end; { Return in FPU register? } - if p.returndef.typ=floatdef then + if def.typ=floatdef then begin - p.funcretloc[side].loc:=LOC_FPUREGISTER; - p.funcretloc[side].register:=NR_FPU_RESULT_REG; + result.loc:=LOC_FPUREGISTER; + result.register:=NR_FPU_RESULT_REG; if retcgsize=OS_F64 then - setsubreg(p.funcretloc[side].register,R_SUBFD); - p.funcretloc[side].size:=retcgsize; + setsubreg(result.register,R_SUBFD); + result.size:=retcgsize; end else { Return in register } @@ -178,27 +185,27 @@ implementation {$ifndef cpu64bitaddr} if retcgsize in [OS_64,OS_S64] then begin - p.funcretloc[side].loc:=LOC_REGISTER; + result.loc:=LOC_REGISTER; { high } if (side=callerside) or (po_inline in p.procoptions) then - p.funcretloc[side].register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG + result.register64.reghi:=NR_FUNCTION_RESULT64_HIGH_REG else - p.funcretloc[side].register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG; + result.register64.reghi:=NR_FUNCTION_RETURN64_HIGH_REG; { low } if (side=callerside) or (po_inline in p.procoptions) then - p.funcretloc[side].register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG + result.register64.reglo:=NR_FUNCTION_RESULT64_LOW_REG else - p.funcretloc[side].register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG; + result.register64.reglo:=NR_FUNCTION_RETURN64_LOW_REG; end else {$endif not cpu64bitaddr} begin - p.funcretloc[side].loc:=LOC_REGISTER; - p.funcretloc[side].size:=retcgsize; + result.loc:=LOC_REGISTER; + result.size:=retcgsize; if (side=callerside) then - p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize)) + result.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize)) else - p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize)); + result.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize)); end; end; end; diff --git a/compiler/x86_64/cpupara.pas b/compiler/x86_64/cpupara.pas index f3f40d723a..78f9f376e8 100644 --- a/compiler/x86_64/cpupara.pas +++ b/compiler/x86_64/cpupara.pas @@ -27,7 +27,7 @@ unit cpupara; uses globtype, - cpubase,cgbase, + cpubase,cgbase,cgutils, symconst,symtype,symsym,symdef, aasmtai,aasmdata, parabase,paramgr; @@ -48,6 +48,7 @@ unit cpupara; function get_volatile_registers_fpu(calloption : tproccalloption):tcpuregisterset;override; function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override; function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override; + function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation;override; end; implementation @@ -55,8 +56,7 @@ unit cpupara; uses cutils,verbose, systems, - defutil, - cgutils; + defutil; const paraintsupregs : array[0..5] of tsuperregister = (RS_RDI,RS_RSI,RS_RDX,RS_RCX,RS_R8,RS_R9); @@ -393,6 +393,12 @@ unit cpupara; procedure tx86_64paramanager.create_funcretloc_info(p : tabstractprocdef; side: tcallercallee); + begin + p.funcretloc[side]:=get_funcretloc(p,side,p.returndef); + end; + + + function tx86_64paramanager.get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tlocation; var retcgsize : tcgsize; begin @@ -400,38 +406,38 @@ unit cpupara; if (p.proctypeoption=potype_constructor) then retcgsize:=OS_ADDR else - retcgsize:=def_cgsize(p.returndef); - location_reset(p.funcretloc[side],LOC_INVALID,OS_NO); + retcgsize:=def_cgsize(def); + location_reset(result,LOC_INVALID,OS_NO); { void has no location } - if is_void(p.returndef) then + if is_void(def) then begin - location_reset(p.funcretloc[side],LOC_VOID,OS_NO); + location_reset(result,LOC_VOID,OS_NO); exit; end; { Return is passed as var parameter } - if ret_in_param(p.returndef,p.proccalloption) then + if ret_in_param(def,p.proccalloption) then begin - p.funcretloc[side].loc:=LOC_REFERENCE; - p.funcretloc[side].size:=retcgsize; + result.loc:=LOC_REFERENCE; + result.size:=retcgsize; exit; end; { Return in FPU register? } - if p.returndef.typ=floatdef then + if def.typ=floatdef then begin - case tfloatdef(p.returndef).floattype of + case tfloatdef(def).floattype of s32real,s64real: begin - p.funcretloc[side].loc:=LOC_MMREGISTER; - p.funcretloc[side].register:=NR_MM_RESULT_REG; - p.funcretloc[side].size:=retcgsize; + result.loc:=LOC_MMREGISTER; + result.register:=NR_MM_RESULT_REG; + result.size:=retcgsize; end; s64currency, s64comp, s80real: begin - p.funcretloc[side].loc:=LOC_FPUREGISTER; - p.funcretloc[side].register:=NR_FPU_RESULT_REG; - p.funcretloc[side].size:=retcgsize; + result.loc:=LOC_FPUREGISTER; + result.register:=NR_FPU_RESULT_REG; + result.size:=retcgsize; end; else internalerror(200405034); @@ -440,41 +446,41 @@ unit cpupara; else { Return in register } begin - p.funcretloc[side].loc:=LOC_REGISTER; + result.loc:=LOC_REGISTER; if retcgsize=OS_NO then begin - case p.returndef.size of + case def.size of 0..4: begin - p.funcretloc[side].size:=OS_32; - p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,R_SUBD); + result.size:=OS_32; + result.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,R_SUBD); end; 5..8: begin - p.funcretloc[side].size:=OS_64; - p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,R_SUBQ); + result.size:=OS_64; + result.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,R_SUBQ); end; 9..16: begin - p.funcretloc[side].size:=OS_128; - p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,R_SUBWHOLE); - p.funcretloc[side].registerhi:=newreg(R_INTREGISTER,RS_RDX,R_SUBWHOLE); + result.size:=OS_128; + result.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,R_SUBWHOLE); + result.registerhi:=newreg(R_INTREGISTER,RS_RDX,R_SUBWHOLE); end; end; end else if retcgsize in [OS_128,OS_S128] then begin - p.funcretloc[side].size:=retcgsize; - p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,R_SUBWHOLE); - p.funcretloc[side].registerhi:=newreg(R_INTREGISTER,RS_RDX,R_SUBWHOLE); + result.size:=retcgsize; + result.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,R_SUBWHOLE); + result.registerhi:=newreg(R_INTREGISTER,RS_RDX,R_SUBWHOLE); end else begin - p.funcretloc[side].size:=retcgsize; + result.size:=retcgsize; if side=callerside then - p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize)) + result.register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(R_INTREGISTER,retcgsize)) else - p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize)); + result.register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(R_INTREGISTER,retcgsize)); end; end; end;