瀏覽代碼

* store the used tabstractprocdef when generating an llvm call instruction,
because due to aliasing symbols a single symbol may be called using
different procdefs (e.g. FPC_ANSISTR_UNIQUE in the system unit is defined
as an alias for a function and called as a procedure). This means we have
to insert extra type conversions for llvm, which requires both the source
and destination type

git-svn-id: trunk@30776 -

Jonas Maebe 10 年之前
父節點
當前提交
72277f5098
共有 3 個文件被更改,包括 37 次插入24 次删除
  1. 21 14
      compiler/llvm/aasmllvm.pas
  2. 3 3
      compiler/llvm/agllvm.pas
  3. 13 7
      compiler/llvm/hlcgllvm.pas

+ 21 - 14
compiler/llvm/aasmllvm.pas

@@ -105,9 +105,9 @@ interface
         constructor getelementptr_reg_tai_size_const(dst:tregister;const ai:tai;indextype:tdef;index1:ptrint;indirect:boolean);
 
         { e.g. dst = call retsize name (paras) }
-        constructor call_size_name_paras(dst: tregister;retsize: tdef;name:tasmsymbol;paras: tfplist);
+        constructor call_size_name_paras(callpd: tdef; dst: tregister;retsize: tdef;name:tasmsymbol;paras: tfplist);
         { e.g. dst = call retsize reg (paras) }
-        constructor call_size_reg_paras(dst: tregister;retsize: tdef;reg:tregister;paras: tfplist);
+        constructor call_size_reg_paras(callpd: tdef; dst: tregister;retsize: tdef;reg:tregister;paras: tfplist);
 
         procedure loadoper(opidx: longint; o: toper); override;
         procedure clearop(opidx: longint); override;
@@ -924,25 +924,32 @@ uses
       end;
 
 
-    constructor taillvm.call_size_name_paras(dst: tregister; retsize: tdef; name:tasmsymbol; paras: tfplist);
+    constructor taillvm.call_size_name_paras(callpd: tdef; dst: tregister; retsize: tdef; name:tasmsymbol; paras: tfplist);
       begin
         create_llvm(la_call);
-        ops:=4;
-        loadreg(0,dst);
-        loaddef(1,retsize);
-        loadsymbol(2,name,0);
-        loadparas(3,paras);
+        ops:=5;
+        { we need this in case the call symbol is an alias for a symbol with a
+          different def in the same module (via "external"), because then we
+          have to insert a type conversion later from the alias def to the
+          call def here; we can't always do that at the point the call itself
+          is generated, because the alias declaration may occur anywhere }
+        loaddef(0,callpd);
+        loadreg(1,dst);
+        loaddef(2,retsize);
+        loadsymbol(3,name,0);
+        loadparas(4,paras);
       end;
 
 
-    constructor taillvm.call_size_reg_paras(dst: tregister; retsize: tdef; reg: tregister; paras: tfplist);
+    constructor taillvm.call_size_reg_paras(callpd: tdef; dst: tregister; retsize: tdef; reg: tregister; paras: tfplist);
       begin
         create_llvm(la_call);
-        ops:=4;
-        loadreg(0,dst);
-        loaddef(1,retsize);
-        loadreg(2,reg);
-        loadparas(3,paras);
+        ops:=5;
+        loaddef(0,callpd);
+        loadreg(1,dst);
+        loaddef(2,retsize);
+        loadreg(3,reg);
+        loadparas(4,paras);
       end;
 
 end.

+ 3 - 3
compiler/llvm/agllvm.pas

@@ -374,10 +374,10 @@ implementation
           end;
         la_call:
           begin
-            if taillvm(hp).oper[0]^.reg<>NR_NO then
-              owner.AsmWrite(getregisterstring(taillvm(hp).oper[0]^.reg)+' = ');
+            if taillvm(hp).oper[1]^.reg<>NR_NO then
+              owner.AsmWrite(getregisterstring(taillvm(hp).oper[1]^.reg)+' = ');
             sep:=' ';
-            opstart:=1;
+            opstart:=2;
           end;
         la_alloca:
           begin

+ 13 - 7
compiler/llvm/hlcgllvm.pas

@@ -314,6 +314,16 @@ implementation
     end;
 
 
+  function get_call_pd(pd: tabstractprocdef): tdef;
+    begin
+      if (pd.typ=procdef) or
+         not pd.is_addressonly then
+        result:=pd.getcopyas(procvardef,pc_address_only)
+      else
+        result:=pd
+    end;
+
+
   procedure thlcgllvm.a_call_common(list: TAsmList; pd: tabstractprocdef; const paras: array of pcgpara; const forceresdef: tdef; out res: tregister; out calldef: tdef; out hlretdef: tdef; out llvmretdef: tdef; out callparas: tfplist);
 
     procedure load_ref_anyreg(def: tdef; const ref: treference; reg: tregister; var callpara: pllvmcallpara);
@@ -417,11 +427,7 @@ implementation
        ((pd.proccalloption in cdecl_pocalls) and
         (pd.paras.count>0) and
         is_array_of_const(tparavarsym(pd.paras[pd.paras.count-1]).vardef)) then
-      if (pd.typ=procdef) or
-         not pd.is_addressonly then
-        calldef:=pd.getcopyas(procvardef,pc_address_only)
-      else
-        calldef:=pd
+      calldef:=get_call_pd(pd)
     else
       calldef:=llvmretdef;
   end;
@@ -445,7 +451,7 @@ implementation
             current_asmdata.AsmLists[al_imports].Concat(taillvmdecl.create(asmsym,pd,nil,sec_code,pd.alignment));
         end;
       a_call_common(list,pd,paras,forceresdef,res,calldef,hlretdef,llvmretdef,callparas);
-      list.concat(taillvm.call_size_name_paras(res,calldef,current_asmdata.RefAsmSymbol(pd.mangledname),callparas));
+      list.concat(taillvm.call_size_name_paras(get_call_pd(pd),res,calldef,current_asmdata.RefAsmSymbol(pd.mangledname),callparas));
       result:=get_call_result_cgpara(pd,forceresdef);
       set_call_function_result(list,pd,llvmretdef,hlretdef,res,result);
     end;
@@ -460,7 +466,7 @@ implementation
       res: tregister;
     begin
       a_call_common(list,pd,paras,nil,res,calldef,hlretdef,llvmretdef,callparas);
-      list.concat(taillvm.call_size_reg_paras(res,calldef,reg,callparas));
+      list.concat(taillvm.call_size_reg_paras(get_call_pd(pd),res,calldef,reg,callparas));
       result:=get_call_result_cgpara(pd,nil);
       set_call_function_result(list,pd,llvmretdef,hlretdef,res,result);
     end;