* 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 -
This commit is contained in:
Jonas Maebe 2011-08-20 07:38:06 +00:00
parent e4d322bcdb
commit 8439e1472e
3 changed files with 111 additions and 28 deletions

View File

@ -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;

View File

@ -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<src_size.size) then
begin
hregister2:=getregisterfordef(list,src_size);
{ prevent problems with memory locations -- at this high
level we cannot twiddle with the reference offset, since
that may not mean anything (e.g., it refers to fixed-sized
stack slots on Java) }
a_load_loc_reg(list,src_size,src_size,l,hregister2);
a_load_reg_reg(list,src_size,dst_size,hregister2,hregister);
end
else
a_load_loc_reg(list,src_size,dst_size,l,hregister);
end;
end;
if (l.loc <> 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,

View File

@ -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 }