Переглянути джерело

* force complex procvars immediately to memory for llvm, so we don't have to
deal with the hacky register/registerhi complex locations

git-svn-id: trunk@32407 -

Jonas Maebe 9 роки тому
батько
коміт
bd4787c716
2 змінених файлів з 88 додано та 4 видалено
  1. 25 1
      compiler/llvm/nllvmcnv.pas
  2. 63 3
      compiler/llvm/nllvmld.pas

+ 25 - 1
compiler/llvm/nllvmcnv.pas

@@ -33,6 +33,7 @@ interface
          protected
           function first_int_to_real: tnode; override;
           function first_int_to_bool: tnode; override;
+          function first_nil_to_methodprocvar: tnode; override;
           procedure second_int_to_int;override;
          { procedure second_string_to_string;override; }
          { procedure second_cstring_to_pchar;override; }
@@ -45,6 +46,7 @@ interface
          { procedure second_real_to_real;override; }
          { procedure second_cord_to_pointer;override; }
          { procedure second_proc_to_procvar;override; }
+         procedure second_nil_to_methodprocvar; override;
          procedure second_bool_to_int;override;
          procedure second_int_to_bool;override;
          { procedure second_load_smallset;override;  }
@@ -63,7 +65,7 @@ uses
   llvmbase,aasmllvm,
   procinfo,
   symconst,symtype,symdef,defutil,
-  cgbase,cgutils,hlcgobj,pass_2;
+  cgbase,cgutils,tgobj,hlcgobj,pass_2;
 
 { tllvmtypeconvnode }
 
@@ -86,6 +88,15 @@ function tllvmtypeconvnode.first_int_to_bool: tnode;
   end;
 
 
+function tllvmtypeconvnode.first_nil_to_methodprocvar: tnode;
+  begin
+    result:=inherited;
+    if assigned(result) then
+      exit;
+    expectloc:=LOC_REFERENCE;
+  end;
+
+
 procedure tllvmtypeconvnode.second_int_to_int;
   var
     fromsize, tosize: tcgint;
@@ -138,6 +149,19 @@ procedure tllvmtypeconvnode.second_int_to_real;
   end;
 
 
+procedure tllvmtypeconvnode.second_nil_to_methodprocvar;
+  var
+    href: treference;
+  begin
+    tg.gethltemp(current_asmdata.CurrAsmList,resultdef,resultdef.size,tt_normal,href);
+    location_reset_ref(location,LOC_REFERENCE,def_cgsize(resultdef),href.alignment);
+    location.reference:=href;
+    hlcg.g_ptrtypecast_ref(current_asmdata.CurrAsmList,cpointerdef.getreusable(resultdef),cpointerdef.getreusable(methodpointertype),href);
+    hlcg.g_load_const_field_by_name(current_asmdata.CurrAsmList,trecorddef(methodpointertype),'proc',0,href);
+    hlcg.g_load_const_field_by_name(current_asmdata.CurrAsmList,trecorddef(methodpointertype),'self',0,href);
+  end;
+
+
 procedure tllvmtypeconvnode.second_bool_to_int;
   var
     pdef: tdef;

+ 63 - 3
compiler/llvm/nllvmld.pas

@@ -29,10 +29,12 @@ interface
       globtype,
       cgutils,
       symtype,
-      ncgld, ncgnstld;
+      node,ncgld,ncgnstld;
 
     type
       tllvmloadnode = class(tcgnestloadnode)
+        function pass_1: tnode; override;
+        procedure pass_generate_code; override;
       end;
 
       { tllvmarrayconstructornode }
@@ -46,10 +48,68 @@ interface
 implementation
 
      uses
+       systems,
        aasmdata,
        nld,
-       symdef,
-       hlcgobj;
+       symtable,symconst,symdef,symsym,
+       tgobj,cgbase,hlcgobj;
+
+function tllvmloadnode.pass_1: tnode;
+  begin
+    result:=inherited;
+    if assigned(result) then
+      exit;
+    case symtableentry.typ of
+      procsym:
+        begin
+          if assigned(left) then
+            expectloc:=LOC_REFERENCE;
+        end;
+    end;
+  end;
+
+procedure tllvmloadnode.pass_generate_code;
+  var
+    pvdef: tprocvardef;
+    href, mpref: treference;
+    field: tfieldvarsym;
+    procreg, selfreg: tregister;
+  begin
+    inherited;
+    case symtableentry.typ of
+      procsym:
+        begin
+          { if the result is returned in two registers, force it to memory into
+            a single memory location, as we don't use the registerhi/register
+            location hack for llvm (llvm will put it back into registers itself)
+          }
+          if assigned(left) then
+            begin
+              pvdef:=tprocvardef(procdef.getcopyas(procvardef,pc_normal));
+              { on little endian, location.register contains proc and
+                location.registerhi contains self; on big endian, it's the
+                other way around }
+              tg.gethltemp(current_asmdata.CurrAsmList,resultdef,resultdef.size,tt_normal,href);
+              if target_info.endian=endian_little then
+                begin
+                  procreg:=location.register;
+                  selfreg:=location.registerhi
+                end
+              else
+                begin
+                  procreg:=location.registerhi;
+                  selfreg:=location.register
+                end;
+              mpref:=href;
+              hlcg.g_ptrtypecast_ref(current_asmdata.CurrAsmList,cpointerdef.getreusable(resultdef),cpointerdef.getreusable(methodpointertype),mpref);
+              hlcg.g_load_reg_field_by_name(current_asmdata.CurrAsmList,cprocvardef.getreusableprocaddr(procdef),trecorddef(methodpointertype),procreg,'proc',mpref);
+              hlcg.g_load_reg_field_by_name(current_asmdata.CurrAsmList,left.resultdef,trecorddef(methodpointertype),selfreg,'self',mpref);
+              location_reset_ref(location,LOC_REFERENCE,location.size,href.alignment);
+              location.reference:=href;
+            end;
+        end;
+    end;
+  end;
 
 { tllvmarrayconstructornode }