From 8439e1472edbf6e8587ca229762d43f7fe771851 Mon Sep 17 00:00:00 2001 From: Jonas Maebe Date: Sat, 20 Aug 2011 07:38:06 +0000 Subject: [PATCH] * moved def2regtyp() from jvm/hlcgcpu to defutil, and extended it to handle vectorfpu (floatdef->MMREG) and softfloat (floatdef->INTREG) + thlcg.getregisterfordef(), which uses def2regtyp() to allocate a register appropriate to hold values of that tdef type + generic thlcg.location_force_reg() implementation. Note that for low-level code generator targets it may be slightly less efficient than the implementation in hlcg2ll (from ncgutil) because it does not play any tricks with the register or location size, or with reference offsets, to truncate values git-svn-id: branches/jvmbackend@18315 - --- compiler/defutil.pas | 36 +++++++++++++++++++ compiler/hlcgobj.pas | 76 +++++++++++++++++++++++++++++++++++++++- compiler/jvm/hlcgcpu.pas | 27 -------------- 3 files changed, 111 insertions(+), 28 deletions(-) diff --git a/compiler/defutil.pas b/compiler/defutil.pas index fa0b447624..be23dbc023 100644 --- a/compiler/defutil.pas +++ b/compiler/defutil.pas @@ -101,6 +101,11 @@ interface {# Returns whether def is reference counted } function is_managed_type(def: tdef) : boolean;{$ifdef USEINLINE}inline;{$endif} + {# Returns the kind of register this type should be loaded in (it does not + check whether this is actually possible, but if it's loaded in a register + by the compiler for any purpose other than parameter passing/function + result loading, this is the register type used } + function def2regtyp(def: tdef): tregistertype; { function is_in_limit_value(val_from:TConstExprInt;def_from,def_to : tdef) : boolean;} @@ -541,6 +546,37 @@ implementation result:=def.needs_inittable; end; + function def2regtyp(def: tdef): tregistertype; + begin + case def.typ of + enumdef, + orddef, + recorddef, + setdef: + result:=R_INTREGISTER; + stringdef, + pointerdef, + classrefdef, + objectdef, + procvardef, + procdef, + arraydef : + result:=R_ADDRESSREGISTER; + floatdef: + if use_vectorfpu(def) then + result:=R_MMREGISTER + else if cs_fp_emulation in current_settings.moduleswitches then + result:=R_INTREGISTER + else + result:=R_FPUREGISTER; + filedef, + variantdef: + internalerror(2010120507); + else + internalerror(2010120506); + end; + end; + { true, if p points to an open array def } function is_open_string(p : tdef) : boolean; diff --git a/compiler/hlcgobj.pas b/compiler/hlcgobj.pas index 43c6fa42bf..0933f88302 100644 --- a/compiler/hlcgobj.pas +++ b/compiler/hlcgobj.pas @@ -71,6 +71,7 @@ unit hlcgobj; // we don't have high level defs yet that translate into all mm cgsizes // function getmmregister(list:TAsmList;size:tdef):Tregister;virtual; function getflagregister(list:TAsmList;size:tdef):Tregister;virtual; + function getregisterfordef(list: TAsmList;size:tdef):Tregister;virtual; {Does the generic cg need SIMD registers, like getmmxregister? Or should the cpu specific child cg object have such a method?} @@ -414,7 +415,7 @@ unit hlcgobj; { routines migrated from ncgutil } - procedure location_force_reg(list:TAsmList;var l:tlocation;src_size,dst_size:tdef;maybeconst:boolean);virtual;abstract; + procedure location_force_reg(list:TAsmList;var l:tlocation;src_size,dst_size:tdef;maybeconst:boolean);virtual; procedure location_force_fpureg(list:TAsmList;var l: tlocation;size: tdef;maybeconst:boolean);virtual;abstract; procedure location_force_mem(list:TAsmList;var l:tlocation;size:tdef);virtual;abstract; // procedure location_force_mmregscalar(list:TAsmList;var l: tlocation;size:tdef;maybeconst:boolean);virtual;abstract; @@ -501,6 +502,24 @@ implementation result:=cg.getflagregister(list,def_cgsize(size)); end; + function thlcgobj.getregisterfordef(list: TAsmList; size: tdef): Tregister; + begin + case def2regtyp(size) of + R_INTREGISTER: + result:=getintregister(list,size); + R_ADDRESSREGISTER: + result:=getaddressregister(list,size); + R_FPUREGISTER: + result:=getfpuregister(list,size); +(* + R_MMREGISTER: + result:=getmmregister(list,size); +*) + else + internalerror(2010122901); + end; + end; + function thlcgobj.uses_registers(rt: Tregistertype): boolean; begin result:=cg.uses_registers(rt); @@ -1552,6 +1571,61 @@ implementation begin end; + procedure thlcgobj.location_force_reg(list: TAsmList; var l: tlocation; src_size, dst_size: tdef; maybeconst: boolean); + var + hregister, + hregister2: tregister; + hl : tasmlabel; + oldloc : tlocation; + begin + oldloc:=l; + hregister:=getregisterfordef(list,dst_size); + { load value in new register } + case l.loc of +{$ifdef cpuflags} + LOC_FLAGS : + cg.g_flags2reg(list,def_cgsize(dst_size),l.resflags,hregister); +{$endif cpuflags} + LOC_JUMP : + begin + a_label(list,current_procinfo.CurrTrueLabel); + a_load_const_reg(list,dst_size,1,hregister); + current_asmdata.getjumplabel(hl); + a_jmp_always(list,hl); + a_label(list,current_procinfo.CurrFalseLabel); + a_load_const_reg(list,dst_size,0,hregister); + a_label(list,hl); + end; + else + begin + { load_loc_reg can only handle size >= l.size, when the + new size is smaller then we need to adjust the size + of the orignal and maybe recalculate l.register for i386 } + if (dst_size.size LOC_CREGISTER) or + not maybeconst then + location_reset(l,LOC_REGISTER,def_cgsize(dst_size)) + else + location_reset(l,LOC_CREGISTER,def_cgsize(dst_size)); + l.register:=hregister; + { Release temp if it was a reference } + if oldloc.loc=LOC_REFERENCE then + location_freetemp(list,oldloc); + end; + procedure thlcgobj.gen_proc_symbol(list: TAsmList); var item, diff --git a/compiler/jvm/hlcgcpu.pas b/compiler/jvm/hlcgcpu.pas index 402e5c84a6..a2468071f4 100644 --- a/compiler/jvm/hlcgcpu.pas +++ b/compiler/jvm/hlcgcpu.pas @@ -127,7 +127,6 @@ uses twice. Returns how many stack slots have been consumed, disregarding the "dup". } function prepare_stack_for_ref(list: TAsmList; const ref: treference; dup: boolean): longint; - function def2regtyp(def: tdef): tregistertype; { return the load/store opcode to load/store from/to ref; if the result has to be and'ed after a load to get the final value, that constant is returned in finishandval (otherwise that value is set to -1) } @@ -838,32 +837,6 @@ implementation incstack(1+ord(size.size>4)-extra_slots); end; - function thlcgjvm.def2regtyp(def: tdef): tregistertype; - begin - case def.typ of - enumdef, - orddef, - setdef: - result:=R_INTREGISTER; - stringdef, - pointerdef, - classrefdef, - objectdef, - procvardef, - procdef, - arraydef : - result:=R_ADDRESSREGISTER; - floatdef: - result:=R_FPUREGISTER; - filedef, - recorddef, - variantdef: - internalerror(2010120507); - else - internalerror(2010120506); - end; - end; - function thlcgjvm.loadstoreopcref(def: tdef; isload: boolean; const ref: treference; out finishandval: aint): tasmop; const { isload static }