浏览代码

* 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 -

Jonas Maebe 14 年之前
父节点
当前提交
8439e1472e
共有 3 个文件被更改,包括 111 次插入28 次删除
  1. 36 0
      compiler/defutil.pas
  2. 75 1
      compiler/hlcgobj.pas
  3. 0 27
      compiler/jvm/hlcgcpu.pas

+ 36 - 0
compiler/defutil.pas

@@ -101,6 +101,11 @@ interface
     {# Returns whether def is reference counted }
     {# Returns whether def is reference counted }
     function is_managed_type(def: tdef) : boolean;{$ifdef USEINLINE}inline;{$endif}
     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;}
 {    function is_in_limit_value(val_from:TConstExprInt;def_from,def_to : tdef) : boolean;}
 
 
@@ -541,6 +546,37 @@ implementation
         result:=def.needs_inittable;
         result:=def.needs_inittable;
       end;
       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 }
     { true, if p points to an open array def }
     function is_open_string(p : tdef) : boolean;
     function is_open_string(p : tdef) : boolean;

+ 75 - 1
compiler/hlcgobj.pas

@@ -71,6 +71,7 @@ unit hlcgobj;
 //        we don't have high level defs yet that translate into all mm cgsizes
 //        we don't have high level defs yet that translate into all mm cgsizes
 //          function getmmregister(list:TAsmList;size:tdef):Tregister;virtual;
 //          function getmmregister(list:TAsmList;size:tdef):Tregister;virtual;
           function getflagregister(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
           {Does the generic cg need SIMD registers, like getmmxregister? Or should
            the cpu specific child cg object have such a method?}
            the cpu specific child cg object have such a method?}
 
 
@@ -414,7 +415,7 @@ unit hlcgobj;
 
 
           { routines migrated from ncgutil }
           { 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_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_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;
 //          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));
       result:=cg.getflagregister(list,def_cgsize(size));
     end;
     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;
   function thlcgobj.uses_registers(rt: Tregistertype): boolean;
     begin
     begin
        result:=cg.uses_registers(rt);
        result:=cg.uses_registers(rt);
@@ -1552,6 +1571,61 @@ implementation
     begin
     begin
     end;
     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);
   procedure thlcgobj.gen_proc_symbol(list: TAsmList);
     var
     var
       item,
       item,

+ 0 - 27
compiler/jvm/hlcgcpu.pas

@@ -127,7 +127,6 @@ uses
         twice. Returns how many stack slots have been consumed, disregarding
         twice. Returns how many stack slots have been consumed, disregarding
         the "dup". }
         the "dup". }
       function prepare_stack_for_ref(list: TAsmList; const ref: treference; dup: boolean): longint;
       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
       { 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
         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) }
         is returned in finishandval (otherwise that value is set to -1) }
@@ -838,32 +837,6 @@ implementation
       incstack(1+ord(size.size>4)-extra_slots);
       incstack(1+ord(size.size>4)-extra_slots);
     end;
     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;
   function thlcgjvm.loadstoreopcref(def: tdef; isload: boolean; const ref: treference; out finishandval: aint): tasmop;
     const
     const
                      { isload  static }
                      { isload  static }