Ver Fonte

* further (final?) reworking of llvm external symbol handling:
o all external symbol definitions are now inserted in the llvmtype post pass
based on all declarations and types used in llvm instructions
o this means we don't have to use the workaround with the Pascal mangled
names anymore for all external names, as we now insert the external
references only once we know all type information

git-svn-id: trunk@31287 -

Jonas Maebe há 10 anos atrás
pai
commit
bfa94ae908
3 ficheiros alterados com 88 adições e 58 exclusões
  1. 0 28
      compiler/llvm/aasmllvm.pas
  2. 8 9
      compiler/llvm/hlcgllvm.pas
  3. 80 21
      compiler/llvm/llvmtype.pas

+ 0 - 28
compiler/llvm/aasmllvm.pas

@@ -35,9 +35,6 @@ interface
     type
       { taillvm }
       taillvm = class(tai_cpu_abstract_sym)
-       private
-        procedure maybe_declare(def: tdef; const ref: treference);
-       public
         llvmopcode: tllvmop;
 
         constructor create_llvm(op: tllvmop);
@@ -234,23 +231,6 @@ uses
                                  taicpu Constructors
 *****************************************************************************}
 
-    procedure taillvm.maybe_declare(def: tdef; const ref: treference);
-      begin
-        { add llvm declarations for imported symbols }
-        if not assigned(ref.symbol) or
-           (ref.symbol.declared) or
-           not(ref.symbol.bind in [AB_EXTERNAL,AB_WEAK_EXTERNAL]) then
-          exit;
-        if ref.refaddr<>addr_full then
-          begin
-            if def.typ<>pointerdef then
-              internalerror(2014020701);
-            def:=tpointerdef(def).pointeddef;
-          end;
-        current_asmdata.AsmLists[al_imports].concat(taillvmdecl.create(ref.symbol,def,nil,sec_none,def.alignment));
-      end;
-
-
     constructor taillvm.create_llvm(op: tllvmop);
       begin
         create(a_none);
@@ -731,7 +711,6 @@ uses
         create_llvm(op);
         ops:=4;
         loadreg(0,dst);
-        maybe_declare(fromsize,src);
         loaddef(1,fromsize);
         loadref(2,src);
         loaddef(3,tosize);
@@ -745,7 +724,6 @@ uses
         ops:=4;
         loaddef(0,fromsize);
         loadreg(1,src);
-        maybe_declare(ptrsize,toref);
         loaddef(2,ptrsize);
         loadref(3,toref);
       end;
@@ -755,10 +733,8 @@ uses
       begin
         create_llvm(op);
         ops:=4;
-        maybe_declare(fromsize,src);
         loaddef(0,fromsize);
         loadref(1,src);
-        maybe_declare(ptrsize,toref);
         loaddef(2,ptrsize);
         loadref(3,toref);
       end;
@@ -770,7 +746,6 @@ uses
         ops:=4;
         loaddef(0,fromsize);
         loadconst(1,src);
-        maybe_declare(ptrsize,toref);
         loaddef(2,ptrsize);
         loadref(3,toref);
       end;
@@ -781,7 +756,6 @@ uses
         create_llvm(op);
         ops:=3;
         loadreg(0,dst);
-        maybe_declare(fromsize,fromref);
         loaddef(1,fromsize);
         loadref(2,fromref);
       end;
@@ -859,7 +833,6 @@ uses
         else
           ops:=5;
         loadreg(0,dst);
-        maybe_declare(ptrsize,ref);
         loaddef(1,ptrsize);
         loadref(2,ref);
         if indirect then
@@ -885,7 +858,6 @@ uses
         else
           ops:=5;
         loadreg(0,dst);
-        maybe_declare(ptrsize,ref);
         loaddef(1,ptrsize);
         loadref(2,ref);
         if indirect then

+ 8 - 9
compiler/llvm/hlcgllvm.pas

@@ -319,7 +319,14 @@ implementation
     begin
       if (pd.typ=procdef) or
          not pd.is_addressonly then
-        result:=cprocvardef.getreusableprocaddr(pd)
+        { we get a pointerdef rather than a procvardef so that if we have to
+          insert an external declaration for this procdef in llvmtype, we don't
+          have to create another procdef from the procvardef we've just created.
+          With a pointerdef, we can just get the pointeddef again. A pointerdef
+          is also much cheaper to create, and in llvm a provardef is a "function
+          pointer", so a pointer to a procdef is the same as a procvar as far
+          as llvm is concerned }
+        result:=cpointerdef.getreusable(pd)
       else
         result:=pd
     end;
@@ -437,19 +444,11 @@ implementation
   function thlcgllvm.a_call_name(list: TAsmList; pd: tprocdef; const s: TSymStr; const paras: array of pcgpara; forceresdef: tdef; weak: boolean): tcgpara;
     var
       callparas: tfplist;
-      asmsym: tasmsymbol;
       llvmretdef,
       hlretdef,
       calldef: tdef;
       res: tregister;
     begin
-      if not pd.owner.iscurrentunit then
-        begin
-          asmsym:=current_asmdata.RefAsmSymbol(tprocdef(pd).mangledname);
-          if (not asmsym.declared) and
-             (asmsym.bind in [AB_EXTERNAL,AB_WEAK_EXTERNAL]) then
-            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(get_call_pd(pd),res,calldef,current_asmdata.RefAsmSymbol(pd.mangledname),callparas));
       result:=get_call_result_cgpara(pd,forceresdef);

+ 80 - 21
compiler/llvm/llvmtype.pas

@@ -82,10 +82,11 @@ interface
         procedure collect_tai_info(deftypelist: tasmlist; p: tai);
         procedure collect_asmlist_info(deftypelist, asmlist: tasmlist);
 
-        procedure insert_llvmins_typeconversions(p: taillvm);
-        procedure insert_typedconst_typeconversion(p: tai_abstracttypedconst);
-        procedure insert_tai_typeconversions(p: tai);
-        procedure insert_asmlist_typeconversions(list: tasmlist);
+        procedure insert_llvmins_typeconversions(toplevellist: tasmlist; p: taillvm);
+        procedure insert_typedconst_typeconversion(toplevellist: tasmlist; p: tai_abstracttypedconst);
+        procedure insert_tai_typeconversions(toplevellist: tasmlist; p: tai);
+        procedure insert_asmlist_typeconversions(toplevellist, list: tasmlist);
+        procedure maybe_insert_extern_sym_decl(toplevellist: tasmlist; sym: tasmsymbol; def: tdef);
         procedure update_asmlist_alias_types(list: tasmlist);
 
       public
@@ -169,6 +170,7 @@ implementation
         end;
       end;
 
+
     procedure TLLVMTypeInfo.collect_llvmins_info(deftypelist: tasmlist; p: taillvm);
       var
         opidx, paraidx: longint;
@@ -180,6 +182,20 @@ implementation
               appenddef(deftypelist,p.oper[opidx]^.def);
             top_tai:
               collect_tai_info(deftypelist,p.oper[opidx]^.ai);
+            top_ref:
+              begin
+                if (p.llvmopcode<>la_br) and
+                   assigned(p.oper[opidx]^.ref^.symbol) and
+                   (p.oper[opidx]^.ref^.symbol.bind<>AB_TEMP) then
+                  begin
+                    if (opidx=3) and
+                       (p.llvmopcode=la_call) then
+                      record_asmsym_def(p.oper[opidx]^.ref^.symbol,tpointerdef(p.oper[0]^.def).pointeddef,false)
+                    { not a named register }
+                    else if (p.oper[opidx]^.ref^.refaddr<>addr_full) then
+                      record_asmsym_def(p.oper[opidx]^.ref^.symbol,p.spilling_get_reg_type(opidx),false);
+                  end;
+              end;
             top_para:
               for paraidx:=0 to p.oper[opidx]^.paras.count-1 do
                 begin
@@ -245,10 +261,11 @@ implementation
       end;
 
 
-    procedure TLLVMTypeInfo.insert_llvmins_typeconversions(p: taillvm);
+    procedure TLLVMTypeInfo.insert_llvmins_typeconversions(toplevellist: tasmlist; p: taillvm);
       var
         symdef,
-        opdef: tdef;
+        opdef,
+        opcmpdef: tdef;
         cnv: taillvm;
         i: longint;
       begin
@@ -256,6 +273,7 @@ implementation
           la_call:
             if p.oper[3]^.typ=top_ref then
               begin
+                maybe_insert_extern_sym_decl(toplevellist,p.oper[3]^.ref^.symbol,tpointerdef(p.oper[0]^.def).pointeddef);
                 symdef:=get_asmsym_def(p.oper[3]^.ref^.symbol);
                 { the type used in the call is different from the type used to
                   declare the symbol -> insert a typecast }
@@ -278,26 +296,39 @@ implementation
               for i:=0 to p.ops-1 do
                 case p.oper[i]^.typ of
                   top_ref:
-                    if (p.oper[i]^.ref^.refaddr=addr_full) and
+                    if (p.oper[i]^.ref^.refaddr<>addr_full) and
+                       assigned(p.oper[i]^.ref^.symbol) and
                        (p.oper[i]^.ref^.symbol.bind<>AB_TEMP) then
                       begin
-                        symdef:=get_asmsym_def(p.oper[i]^.ref^.symbol);
                         opdef:=p.spilling_get_reg_type(i);
-                        if not equal_llvm_defs(symdef,opdef) then
+                        case opdef.typ of
+                          pointerdef:
+                            opcmpdef:=tpointerdef(opdef).pointeddef;
+                          procvardef,
+                          procdef:
+                            opcmpdef:=opdef;
+                          else
+                            internalerror(2015073101);
+                        end;
+                        maybe_insert_extern_sym_decl(toplevellist,p.oper[i]^.ref^.symbol,opcmpdef);
+                        symdef:=get_asmsym_def(p.oper[i]^.ref^.symbol);
+                        if not equal_llvm_defs(symdef,opcmpdef) then
                           begin
-                            cnv:=taillvm.op_reg_size_sym_size(la_bitcast,NR_NO,symdef,p.oper[i]^.ref^.symbol,opdef);
+                            if symdef.typ=procdef then
+                              symdef:=cpointerdef.getreusable(symdef);
+                            cnv:=taillvm.op_reg_size_sym_size(la_bitcast,NR_NO,cpointerdef.getreusable(symdef),p.oper[i]^.ref^.symbol,opdef);
                             p.loadtai(i,cnv);
                           end;
                       end;
                   top_tai:
-                    insert_tai_typeconversions(p.oper[i]^.ai);
+                    insert_tai_typeconversions(toplevellist,p.oper[i]^.ai);
                 end;
             end;
         end;
       end;
 
 
-    procedure TLLVMTypeInfo.insert_typedconst_typeconversion(p: tai_abstracttypedconst);
+    procedure TLLVMTypeInfo.insert_typedconst_typeconversion(toplevellist: tasmlist; p: tai_abstracttypedconst);
       var
         symdef: tdef;
         cnv: taillvm;
@@ -311,6 +342,7 @@ implementation
                   if assigned(tai_const(tai_simpletypedconst(p).val).sym) and
                      not assigned(tai_const(tai_simpletypedconst(p).val).endsym) then
                     begin
+                      maybe_insert_extern_sym_decl(toplevellist,tai_const(tai_simpletypedconst(p).val).sym,p.def);
                       symdef:=get_asmsym_def(tai_const(tai_simpletypedconst(p).val).sym);
                       { all references to symbols in typed constants are
                         references to the address of a global symbol (you can't
@@ -325,36 +357,36 @@ implementation
                         end;
                     end;
                 else
-                  insert_tai_typeconversions(tai_simpletypedconst(p).val);
+                  insert_tai_typeconversions(toplevellist,tai_simpletypedconst(p).val);
               end;
             end;
           tck_array,
           tck_record:
             begin
               for elementp in tai_aggregatetypedconst(p) do
-                insert_typedconst_typeconversion(elementp);
+                insert_typedconst_typeconversion(toplevellist,elementp);
             end;
         end;
       end;
 
 
-    procedure TLLVMTypeInfo.insert_tai_typeconversions(p: tai);
+    procedure TLLVMTypeInfo.insert_tai_typeconversions(toplevellist: tasmlist; p: tai);
       begin
         case p.typ of
           ait_llvmins:
-            insert_llvmins_typeconversions(taillvm(p));
+            insert_llvmins_typeconversions(toplevellist,taillvm(p));
           { can also be necessary in case someone initialises a typed const with
             the address of an external symbol aliasing one declared with a
             different type in the same mmodule. }
           ait_typedconst:
-            insert_typedconst_typeconversion(tai_abstracttypedconst(p));
+            insert_typedconst_typeconversion(toplevellist,tai_abstracttypedconst(p));
           ait_llvmdecl:
-            insert_asmlist_typeconversions(taillvmdecl(p).initdata);
+            insert_asmlist_typeconversions(toplevellist,taillvmdecl(p).initdata);
         end;
       end;
 
 
-    procedure TLLVMTypeInfo.insert_asmlist_typeconversions(list: tasmlist);
+    procedure TLLVMTypeInfo.insert_asmlist_typeconversions(toplevellist, list: tasmlist);
       var
         hp: tai;
       begin
@@ -363,11 +395,36 @@ implementation
         hp:=tai(list.first);
         while assigned(hp) do
           begin
-            insert_tai_typeconversions(hp);
+            insert_tai_typeconversions(toplevellist,hp);
             hp:=tai(hp.next);
           end;
       end;
 
+
+    procedure TLLVMTypeInfo.maybe_insert_extern_sym_decl(toplevellist: tasmlist; sym: tasmsymbol; def: tdef);
+      var
+        sec: tasmsectiontype;
+      begin
+        { Necessery for "external" declarations for symbols not declared in the
+          current unit. We can't create these declarations when the alias is
+          initially generated, because the symbol may still be defined later at
+          that point.
+
+          We also do it for all other external symbol references (e.g.
+          references to symbols declared in other units), because then this
+          handling is centralised in one place. }
+        if not(sym.declared) then
+          begin
+            if def.typ=procdef then
+              sec:=sec_code
+            else
+              sec:=sec_data;
+            toplevellist.Concat(taillvmdecl.create(sym,def,nil,sec,def.alignment));
+            record_asmsym_def(sym,def,true);
+          end;
+      end;
+
+
     procedure TLLVMTypeInfo.update_asmlist_alias_types(list: tasmlist);
       var
         hp: tai;
@@ -580,7 +637,9 @@ implementation
         { and insert the necessary type conversions }
         for hal:=low(TasmlistType) to high(TasmlistType) do
           if hal<>al_start then
-            insert_asmlist_typeconversions(current_asmdata.asmlists[hal]);
+            insert_asmlist_typeconversions(
+              current_asmdata.asmlists[hal],
+              current_asmdata.asmlists[hal]);
 
         { write all used defs }
         write_defs_to_write;