浏览代码

* fixed handling of fpu/mm loads from "named registers" in case they involve
a typecast from a struct to a scalar type (webtbs/tw26993)

git-svn-id: trunk@34027 -

Jonas Maebe 9 年之前
父节点
当前提交
c421171461
共有 1 个文件被更改,包括 58 次插入24 次删除
  1. 58 24
      compiler/llvm/hlcgllvm.pas

+ 58 - 24
compiler/llvm/hlcgllvm.pas

@@ -61,6 +61,10 @@ uses
       procedure a_load_const_ref(list: TAsmList; tosize: tdef; a: tcgint; const ref: treference);override;
       procedure a_load_reg_ref(list : TAsmList;fromsize, tosize : tdef;register : tregister;const ref : treference);override;
       procedure a_load_reg_reg(list : TAsmList;fromsize, tosize : tdef;reg1,reg2 : tregister);override;
+
+     protected
+      procedure gen_load_refaddrfull_anyreg(list: TAsmList; fromsize, tosize : tdef; const simpleref: treference; register: tregister; shuffle: pmmshuffle);
+     public
       procedure a_load_ref_reg(list : TAsmList;fromsize, tosize : tdef;const ref : treference;register : tregister);override;
       procedure a_load_ref_ref(list: TAsmList; fromsize, tosize: tdef; const sref: treference; const dref: treference); override;
      protected
@@ -636,6 +640,47 @@ implementation
     end;
 
 
+  procedure thlcgllvm.gen_load_refaddrfull_anyreg(list: TAsmList; fromsize, tosize: tdef; const simpleref: treference; register: tregister; shuffle: pmmshuffle);
+    var
+      tmpref,
+      tmpref2: treference;
+    begin
+      { can't bitcast records/arrays }
+      if (llvmaggregatetype(fromsize) or
+          llvmaggregatetype(tosize)) and
+         (fromsize<>tosize) then
+        begin
+          if fromsize.size>tosize.size then
+            begin
+              tg.gethltemp(list,fromsize,fromsize.size,tt_normal,tmpref);
+              tmpref2:=tmpref;
+              g_ptrtypecast_ref(list,cpointerdef.getreusable(fromsize),cpointerdef.getreusable(tosize),tmpref2);
+            end
+          else
+            begin
+              tg.gethltemp(list,tosize,tosize.size,tt_normal,tmpref);
+              tmpref2:=tmpref;
+              g_ptrtypecast_ref(list,cpointerdef.getreusable(tosize),cpointerdef.getreusable(fromsize),tmpref);
+            end;
+          list.concat(taillvm.op_size_ref_size_ref(la_store,fromsize,simpleref,cpointerdef.getreusable(fromsize),tmpref));
+          case getregtype(register) of
+            R_INTREGISTER,
+            R_ADDRESSREGISTER:
+              a_load_ref_reg(list,tosize,tosize,tmpref2,register);
+            R_FPUREGISTER:
+              a_loadfpu_ref_reg(list,tosize,tosize,tmpref2,register);
+            R_MMREGISTER:
+              a_loadmm_ref_reg(list,tosize,tosize,tmpref2,register,shuffle);
+            else
+              internalerror(2016061901);
+          end;
+          tg.ungettemp(list,tmpref);
+        end
+      else
+        list.concat(taillvm.op_reg_size_ref_size(llvmconvop(fromsize,tosize,false),register,fromsize,simpleref,tosize))
+    end;
+
+
   procedure thlcgllvm.a_load_ref_reg(list: TAsmList; fromsize, tosize: tdef; const ref: treference; register: tregister);
     var
       tmpref,
@@ -646,20 +691,7 @@ implementation
       sref:=make_simple_ref(list,ref,fromsize);
       { "named register"? }
       if sref.refaddr=addr_full then
-        begin
-          { can't bitcast records/arrays }
-          if (llvmaggregatetype(fromsize) or
-              llvmaggregatetype(tosize)) and
-             (fromsize<>tosize) then
-            begin
-              tg.gethltemp(list,fromsize,fromsize.size,tt_normal,tmpref);
-              list.concat(taillvm.op_size_ref_size_ref(la_store,fromsize,sref,cpointerdef.getreusable(fromsize),tmpref));
-              a_load_ref_reg(list,fromsize,tosize,tmpref,register);
-              tg.ungettemp(list,tmpref);
-            end
-          else
-            list.concat(taillvm.op_reg_size_ref_size(llvmconvop(fromsize,tosize,false),register,fromsize,sref,tosize))
-        end
+        gen_load_refaddrfull_anyreg(list,fromsize,tosize,sref,register,nil)
       else
         begin
           if ((fromsize.typ in [arraydef,recorddef]) or
@@ -1059,10 +1091,11 @@ implementation
        fromcompcurr,
        tocompcurr: boolean;
      begin
+       href:=make_simple_ref(list,ref,fromsize);
        { named register -> use generic code }
        if ref.refaddr=addr_full then
          begin
-           a_load_ref_reg(list,fromsize,tosize,ref,reg);
+           gen_load_refaddrfull_anyreg(list,fromsize,tosize,href,reg,mms_movescalar);
            exit
          end;
        { comp and currency are handled by the x87 in this case. They cannot
@@ -1074,7 +1107,6 @@ implementation
        tocompcurr:=tfloatdef(tosize).floattype in [s64comp,s64currency];
        if tocompcurr then
          tosize:=s80floattype;
-       href:=make_simple_ref(list,ref,fromsize);
        { don't generate different code for loading e.g. extended into cextended,
          but to take care of loading e.g. comp (=int64) into double }
        if (fromsize.size<>tosize.size) then
@@ -1375,18 +1407,20 @@ implementation
     var
       href: treference;
     begin
-      { named register -> use generic code }
-      if ref.refaddr=addr_full then
-        a_load_ref_reg(list,fromsize,tosize,ref,reg)
-      else if shuffle=mms_movescalar then
+      if shuffle=mms_movescalar then
         a_loadfpu_ref_reg(list,fromsize,tosize,ref,reg)
       else
         begin
           href:=make_simple_ref(list,ref,fromsize);
-          if fromsize<>tosize then
-            g_ptrtypecast_ref(list,cpointerdef.create(fromsize),cpointerdef.create(tosize),href);
-          { %reg = load size* %ref }
-          list.concat(taillvm.op_reg_size_ref(la_load,reg,cpointerdef.getreusable(tosize),href));
+          if ref.refaddr=addr_full then
+            gen_load_refaddrfull_anyreg(list,fromsize,tosize,href,reg,shuffle)
+          else
+            begin
+              if fromsize<>tosize then
+                g_ptrtypecast_ref(list,cpointerdef.create(fromsize),cpointerdef.create(tosize),href);
+              { %reg = load size* %ref }
+              list.concat(taillvm.op_reg_size_ref(la_load,reg,cpointerdef.getreusable(tosize),href));
+            end;
         end;
     end;