From 46ff0c4fc4e3fe6fae897024f4fda675707aa992 Mon Sep 17 00:00:00 2001 From: Jonas Maebe Date: Wed, 26 May 2010 19:57:11 +0000 Subject: [PATCH] * extracted gen_load_cgpara_loc() * unified previously introduced helpers into a single gen_load_loc_cgpara() with the same interface as gen_load_cgpara_loc() git-svn-id: trunk@15327 - --- compiler/ncgcal.pas | 11 +- compiler/ncgutil.pas | 443 +++++++++++++++++++++++-------------------- 2 files changed, 240 insertions(+), 214 deletions(-) diff --git a/compiler/ncgcal.pas b/compiler/ncgcal.pas index 19893a4962..eecf684707 100644 --- a/compiler/ncgcal.pas +++ b/compiler/ncgcal.pas @@ -128,15 +128,8 @@ implementation if left.location.loc in [LOC_FLAGS,LOC_JUMP,LOC_SUBSETREG,LOC_CSUBSETREG,LOC_SUBSETREF,LOC_CSUBSETREF] then location_force_reg(current_asmdata.CurrAsmList,left.location,def_cgsize(left.resultdef),false); - { Handle Floating point types differently - - This doesn't depend on emulator settings, emulator settings should - be handled by cpupara } - - if left.resultdef.typ=floatdef then - gen_loadfpu_loc_cgpara(current_asmdata.CurrAsmList,left.location,tempcgpara,left.resultdef.size) - else - gen_load_locnonfpu_cgpara(current_asmdata.CurrAsmList,left.location,tempcgpara,is_64bit(left.resultdef)) + { load the parameter's tlocation into its cgpara } + gen_load_loc_cgpara(current_asmdata.CurrAsmList,left.resultdef,left.location,tempcgpara) end; diff --git a/compiler/ncgutil.pas b/compiler/ncgutil.pas index 9ec373a63f..f13b443d36 100644 --- a/compiler/ncgutil.pas +++ b/compiler/ncgutil.pas @@ -66,10 +66,15 @@ interface procedure location_force_mmregscalar(list:TAsmList;var l: tlocation;maybeconst:boolean); procedure location_force_mmreg(list:TAsmList;var l: tlocation;maybeconst:boolean); - { load a location of a floatdef into a cgpara } - procedure gen_loadfpu_loc_cgpara(list:TAsmList;const l: tlocation;const cgpara: tcgpara;locintsize: longint); - { load a location of a non-floatdef into a cgpara } - procedure gen_load_locnonfpu_cgpara(list:TAsmList;const l: tlocation;const cgpara: tcgpara; is64bitint: boolean); + { load a tlocation into a cgpara } + procedure gen_load_loc_cgpara(list: TAsmList; vardef: tdef; const l: tlocation; const cgpara: tcgpara); + { loads a cgpara into a tlocation; assumes that loc.loc is already + initialised } + procedure gen_load_cgpara_loc(list: TAsmList; vardef: tdef; const para: TCGPara; var destloc: tlocation); + + { allocate registers for a tlocation; assumes that loc.loc is already + set to LOC_CREGISTER/LOC_CFPUREGISTER/... } + procedure gen_alloc_regloc(list:TAsmList;var loc: tlocation); procedure register_maybe_adjust_setbase(list: TAsmList; var l: tlocation; setbase: aint); @@ -923,12 +928,22 @@ implementation end; - procedure gen_load_locnonfpu_cgpara(list: TAsmList; const l: tlocation;const cgpara: tcgpara; is64bitint: boolean); + procedure gen_load_loc_cgpara(list: TAsmList; vardef: tdef; const l: tlocation; const cgpara: tcgpara); {$ifndef cpu64bitalu} var tmploc: tlocation; {$endif not cpu64bitalu} begin + { Handle Floating point types differently + + This doesn't depend on emulator settings, emulator settings should + be handled by cpupara } + if vardef.typ=floatdef then + begin + gen_loadfpu_loc_cgpara(list,l,cgpara,vardef.size); + exit; + end; + case l.loc of LOC_CONSTANT, LOC_REGISTER, @@ -938,7 +953,7 @@ implementation begin {$ifndef cpu64bitalu} { use cg64 only for int64, not for 8 byte records } - if is64bitint then + if is_64bit(vardef) then cg64.a_load64_loc_cgpara(list,l,cgpara) else {$endif not cpu64bitalu} @@ -1794,31 +1809,37 @@ implementation end; - procedure gen_alloc_regvar(list:TAsmList;sym: tabstractnormalvarsym); + procedure gen_alloc_regloc(list:TAsmList;var loc: tlocation); begin - case sym.initialloc.loc of + case loc.loc of LOC_CREGISTER: begin {$ifndef cpu64bitalu} - if sym.initialloc.size in [OS_64,OS_S64] then + if loc.size in [OS_64,OS_S64] then begin - sym.initialloc.register64.reglo:=cg.getintregister(list,OS_32); - sym.initialloc.register64.reghi:=cg.getintregister(list,OS_32); + loc.register64.reglo:=cg.getintregister(list,OS_32); + loc.register64.reghi:=cg.getintregister(list,OS_32); end else {$endif cpu64bitalu} - sym.initialloc.register:=cg.getintregister(list,sym.initialloc.size); + loc.register:=cg.getintregister(list,loc.size); end; LOC_CFPUREGISTER: begin - sym.initialloc.register:=cg.getfpuregister(list,sym.initialloc.size); + loc.register:=cg.getfpuregister(list,loc.size); end; LOC_CMMREGISTER: begin - sym.initialloc.register:=cg.getmmregister(list,sym.initialloc.size); + loc.register:=cg.getmmregister(list,loc.size); end; end; + end; + + procedure gen_alloc_regvar(list:TAsmList;sym: tabstractnormalvarsym; allocreg: boolean); + begin + if allocreg then + gen_alloc_regloc(list,sym.initialloc); if (pi_has_goto in current_procinfo.flags) then begin { Allocate register already, to prevent first allocation to be @@ -1837,6 +1858,202 @@ implementation end; + procedure gen_load_cgpara_loc(list: TAsmList; vardef: tdef; const para: TCGPara; var destloc: tlocation); + + procedure unget_para(const paraloc:TCGParaLocation); + begin + case paraloc.loc of + LOC_REGISTER : + begin + if getsupreg(paraloc.register)LOC_REFERENCE) or + assigned(paraloc^.next) then + internalerror(2005013010); + cg.a_load_cgparaloc_ref(list,paraloc^,href,sizeleft,destloc.reference.alignment); + inc(href.offset,sizeleft); + sizeleft:=0; + end + else + begin + cg.a_load_cgparaloc_ref(list,paraloc^,href,tcgsize2size[paraloc^.size],destloc.reference.alignment); + inc(href.offset,TCGSize2Size[paraloc^.size]); + dec(sizeleft,TCGSize2Size[paraloc^.size]); + end; + unget_para(paraloc^); + paraloc:=paraloc^.next; + end; + end; + end; + LOC_CREGISTER : + begin +{$ifndef cpu64bitalu} + if (para.size in [OS_64,OS_S64]) and + is_64bit(vardef) then + begin + case paraloc^.loc of + LOC_REGISTER: + begin + if not assigned(paraloc^.next) then + internalerror(200410104); + if (target_info.endian=ENDIAN_BIG) then + begin + { paraloc^ -> high + paraloc^.next -> low } + unget_para(paraloc^); + gen_alloc_regloc(list,destloc); + { reg->reg, alignment is irrelevant } + cg.a_load_cgparaloc_anyreg(list,OS_32,paraloc^,destloc.register64.reghi,4); + unget_para(paraloc^.next^); + cg.a_load_cgparaloc_anyreg(list,OS_32,paraloc^.next^,destloc.register64.reglo,4); + end + else + begin + { paraloc^ -> low + paraloc^.next -> high } + unget_para(paraloc^); + gen_alloc_regloc(list,destloc); + cg.a_load_cgparaloc_anyreg(list,OS_32,paraloc^,destloc.register64.reglo,4); + unget_para(paraloc^.next^); + cg.a_load_cgparaloc_anyreg(list,OS_32,paraloc^.next^,destloc.register64.reghi,4); + end; + end; + LOC_REFERENCE: + begin + gen_alloc_regloc(list,destloc); + reference_reset_base(href,paraloc^.reference.index,paraloc^.reference.offset,para.alignment); + cg64.a_load64_ref_reg(list,href,destloc.register64); + unget_para(paraloc^); + end; + else + internalerror(2005101501); + end + end + else +{$endif not cpu64bitalu} + begin + if assigned(paraloc^.next) then + internalerror(200410105); + unget_para(paraloc^); + gen_alloc_regloc(list,destloc); + cg.a_load_cgparaloc_anyreg(list,destloc.size,paraloc^,destloc.register,sizeof(aint)); + end; + end; + LOC_CFPUREGISTER : + begin +{$if defined(sparc) or defined(arm)} + { Arm and Sparc passes floats in int registers, when loading to fpu register + we need a temp } + sizeleft := TCGSize2Size[destloc.size]; + tg.GetTemp(list,sizeleft,sizeleft,tt_normal,tempref); + href:=tempref; + while assigned(paraloc) do + begin + unget_para(paraloc^); + cg.a_load_cgparaloc_ref(list,paraloc^,href,sizeleft,destloc.reference.alignment); + inc(href.offset,TCGSize2Size[paraloc^.size]); + dec(sizeleft,TCGSize2Size[paraloc^.size]); + paraloc:=paraloc^.next; + end; + gen_alloc_regloc(list,destloc); + cg.a_loadfpu_ref_reg(list,destloc.size,destloc.size,tempref,destloc.register); + tg.UnGetTemp(list,tempref); +{$else sparc} + unget_para(paraloc^); + gen_alloc_regloc(list,destloc); + { from register to register -> alignment is irrelevant } + cg.a_load_cgparaloc_anyreg(list,destloc.size,paraloc^,destloc.register,0); + if assigned(paraloc^.next) then + internalerror(200410109); +{$endif sparc} + end; + LOC_CMMREGISTER : + begin +{$ifndef cpu64bitalu} + { ARM vfp floats are passed in integer registers } + if (para.size=OS_F64) and + (paraloc^.size in [OS_32,OS_S32]) and + use_vectorfpu(vardef) then + begin + { we need 2x32bit reg } + if not assigned(paraloc^.next) or + assigned(paraloc^.next^.next) then + internalerror(2009112421); + unget_para(paraloc^); + unget_para(paraloc^.next^); + gen_alloc_regloc(list,destloc); + if (target_info.endian=endian_big) then + { paraloc^ -> high + paraloc^.next -> low } + reg64:=joinreg64(paraloc^.next^.register,paraloc^.register) + else + reg64:=joinreg64(paraloc^.register,paraloc^.next^.register); + cg64.a_loadmm_intreg64_reg(list,OS_F64,reg64,destloc.register); + end + else +{$endif not cpu64bitalu} + begin + unget_para(paraloc^); + gen_alloc_regloc(list,destloc); + { from register to register -> alignment is irrelevant } + cg.a_load_cgparaloc_anyreg(list,destloc.size,paraloc^,destloc.register,0); + { data could come in two memory locations, for now + we simply ignore the sanity check (FK) + if assigned(paraloc^.next) then + internalerror(200410108); + } + end; + end; + end; + end; + + procedure gen_load_para_value(list:TAsmList); procedure get_para(const paraloc:TCGParaLocation); @@ -1861,40 +2078,10 @@ implementation end; - procedure unget_para(const paraloc:TCGParaLocation); - begin - case paraloc.loc of - LOC_REGISTER : - begin - if getsupreg(paraloc.register)LOC_REFERENCE) or - assigned(paraloc^.next) then - internalerror(2005013010); - cg.a_load_cgparaloc_ref(list,paraloc^,href,sizeleft,currpara.initialloc.reference.alignment); - inc(href.offset,sizeleft); - sizeleft:=0; - end - else - begin - cg.a_load_cgparaloc_ref(list,paraloc^,href,tcgsize2size[paraloc^.size],currpara.initialloc.reference.alignment); - inc(href.offset,TCGSize2Size[paraloc^.size]); - dec(sizeleft,TCGSize2Size[paraloc^.size]); - end; - unget_para(paraloc^); - paraloc:=paraloc^.next; - end; - end; - end; - LOC_CREGISTER : - begin -{$ifndef cpu64bitalu} - if (currpara.paraloc[calleeside].size in [OS_64,OS_S64]) and - is_64bit(currpara.vardef) then - begin - case paraloc^.loc of - LOC_REGISTER: - begin - if not assigned(paraloc^.next) then - internalerror(200410104); - if (target_info.endian=ENDIAN_BIG) then - begin - { paraloc^ -> high - paraloc^.next -> low } - unget_para(paraloc^); - gen_alloc_regvar(list,currpara); - { reg->reg, alignment is irrelevant } - cg.a_load_cgparaloc_anyreg(list,OS_32,paraloc^,currpara.initialloc.register64.reghi,4); - unget_para(paraloc^.next^); - cg.a_load_cgparaloc_anyreg(list,OS_32,paraloc^.next^,currpara.initialloc.register64.reglo,4); - end - else - begin - { paraloc^ -> low - paraloc^.next -> high } - unget_para(paraloc^); - gen_alloc_regvar(list,currpara); - cg.a_load_cgparaloc_anyreg(list,OS_32,paraloc^,currpara.initialloc.register64.reglo,4); - unget_para(paraloc^.next^); - cg.a_load_cgparaloc_anyreg(list,OS_32,paraloc^.next^,currpara.initialloc.register64.reghi,4); - end; - end; - LOC_REFERENCE: - begin - gen_alloc_regvar(list,currpara); - reference_reset_base(href,paraloc^.reference.index,paraloc^.reference.offset,currpara.paraloc[calleeside].alignment); - cg64.a_load64_ref_reg(list,href,currpara.initialloc.register64); - unget_para(paraloc^); - end; - else - internalerror(2005101501); - end - end - else -{$endif not cpu64bitalu} - begin - if assigned(paraloc^.next) then - internalerror(200410105); - unget_para(paraloc^); - gen_alloc_regvar(list,currpara); - cg.a_load_cgparaloc_anyreg(list,currpara.initialloc.size,paraloc^,currpara.initialloc.register,sizeof(aint)); - end; - end; - LOC_CFPUREGISTER : - begin -{$if defined(sparc) or defined(arm)} - { Arm and Sparc passes floats in int registers, when loading to fpu register - we need a temp } - sizeleft := TCGSize2Size[currpara.initialloc.size]; - tg.GetTemp(list,sizeleft,sizeleft,tt_normal,tempref); - href:=tempref; - while assigned(paraloc) do - begin - unget_para(paraloc^); - cg.a_load_cgparaloc_ref(list,paraloc^,href,sizeleft,currpara.initialloc.reference.alignment); - inc(href.offset,TCGSize2Size[paraloc^.size]); - dec(sizeleft,TCGSize2Size[paraloc^.size]); - paraloc:=paraloc^.next; - end; - gen_alloc_regvar(list,currpara); - cg.a_loadfpu_ref_reg(list,currpara.initialloc.size,currpara.initialloc.size,tempref,currpara.initialloc.register); - tg.UnGetTemp(list,tempref); -{$else sparc} - unget_para(paraloc^); - gen_alloc_regvar(list,currpara); - { from register to register -> alignment is irrelevant } - cg.a_load_cgparaloc_anyreg(list,currpara.initialloc.size,paraloc^,currpara.initialloc.register,0); - if assigned(paraloc^.next) then - internalerror(200410109); -{$endif sparc} - end; - LOC_CMMREGISTER : - begin -{$ifndef cpu64bitalu} - { ARM vfp floats are passed in integer registers } - if (currpara.paraloc[calleeside].size=OS_F64) and - (paraloc^.size in [OS_32,OS_S32]) and - use_vectorfpu(currpara.vardef) then - begin - { we need 2x32bit reg } - if not assigned(paraloc^.next) or - assigned(paraloc^.next^.next) then - internalerror(2009112421); - unget_para(paraloc^); - unget_para(paraloc^.next^); - gen_alloc_regvar(list,currpara); - if (target_info.endian=endian_big) then - { paraloc^ -> high - paraloc^.next -> low } - reg64:=joinreg64(paraloc^.next^.register,paraloc^.register) - else - reg64:=joinreg64(paraloc^.register,paraloc^.next^.register); - cg64.a_loadmm_intreg64_reg(list,OS_F64,reg64,currpara.initialloc.register); - end - else -{$endif not cpu64bitalu} - begin - unget_para(paraloc^); - gen_alloc_regvar(list,currpara); - { from register to register -> alignment is irrelevant } - cg.a_load_cgparaloc_anyreg(list,currpara.initialloc.size,paraloc^,currpara.initialloc.register,0); - { data could come in two memory locations, for now - we simply ignore the sanity check (FK) - if assigned(paraloc^.next) then - internalerror(200410108); - } - end; - end; - end; + gen_load_cgpara_loc(list,currpara.vardef,currpara.paraloc[calleeside],currpara.initialloc); + { gen_load_cgpara_loc() already allocated the initialloc + -> don't allocate again } + if currpara.initialloc.loc in [LOC_CREGISTER,LOC_CFPUREGISTER,LOC_CMMREGISTER] then + gen_alloc_regvar(list,currpara,false); end; { generate copies of call by value parameters, must be done before @@ -2548,7 +2581,7 @@ implementation begin vs.initialloc.loc:=tvarregable2tcgloc[vs.varregable]; vs.initialloc.size:=def_cgsize(vs.vardef); - gen_alloc_regvar(list,vs); + gen_alloc_regvar(list,vs,true); setlocalloc(vs); end; end; @@ -2607,7 +2640,7 @@ implementation else if vs.is_regvar(false) then begin vs.initialloc.loc:=tvarregable2tcgloc[vs.varregable]; - gen_alloc_regvar(list,vs); + gen_alloc_regvar(list,vs,true); end else begin