Browse Source

+ support for handling the tcalo_no_dead_strip flag when targeting LLVM:
add such symbols to the pseudo-arrays llvm.compiler.used or llvm.used
depending on their nature (fixes compiling Objective-C programs with
optimization, and keeps the FPC ident in the linked binary)

git-svn-id: trunk@35041 -

Jonas Maebe 8 years ago
parent
commit
db40e1575d
3 changed files with 65 additions and 4 deletions
  1. 10 0
      compiler/fmodule.pas
  2. 13 2
      compiler/llvm/nllvmtcon.pas
  3. 42 2
      compiler/llvm/nllvmutil.pas

+ 10 - 0
compiler/fmodule.pas

@@ -147,6 +147,8 @@ interface
         procaddrdefs  : THashSet; { list of procvardefs created when getting the address of a procdef (not saved/restored) }
         procaddrdefs  : THashSet; { list of procvardefs created when getting the address of a procdef (not saved/restored) }
 {$ifdef llvm}
 {$ifdef llvm}
         llvmdefs      : THashSet; { defs added for llvm-specific reasons (not saved/restored) }
         llvmdefs      : THashSet; { defs added for llvm-specific reasons (not saved/restored) }
+        llvmusedsyms  : TFPObjectList; { a list of tllvmdecls of all symbols that need to be added to llvm.used (so they're not removed by llvm optimisation passes nor by the linker) }
+        llvmcompilerusedsyms : TFPObjectList; { a list of tllvmdecls of all symbols that need to be added to llvm.compiler.used (so they're not removed by llvm optimisation passes) }
 {$endif llvm}
 {$endif llvm}
         ansistrdef    : tobject; { an ansistring def redefined for the current module }
         ansistrdef    : tobject; { an ansistring def redefined for the current module }
         wpoinfo       : tunitwpoinfobase; { whole program optimization-related information that is generated during the current run for this unit }
         wpoinfo       : tunitwpoinfobase; { whole program optimization-related information that is generated during the current run for this unit }
@@ -588,6 +590,8 @@ implementation
         procaddrdefs:=THashSet.Create(64,true,false);
         procaddrdefs:=THashSet.Create(64,true,false);
 {$ifdef llvm}
 {$ifdef llvm}
         llvmdefs:=THashSet.Create(64,true,false);
         llvmdefs:=THashSet.Create(64,true,false);
+        llvmusedsyms:=TFPObjectList.Create(false);
+        llvmcompilerusedsyms:=TFPObjectList.Create(false);
 {$endif llvm}
 {$endif llvm}
         ansistrdef:=nil;
         ansistrdef:=nil;
         wpoinfo:=nil;
         wpoinfo:=nil;
@@ -714,6 +718,8 @@ implementation
         procaddrdefs.free;
         procaddrdefs.free;
 {$ifdef llvm}
 {$ifdef llvm}
         llvmdefs.free;
         llvmdefs.free;
+        llvmusedsyms.free;
+        llvmcompilerusedsyms.free;
 {$endif llvm}
 {$endif llvm}
         ansistrdef:=nil;
         ansistrdef:=nil;
         wpoinfo.free;
         wpoinfo.free;
@@ -784,6 +790,10 @@ implementation
 {$ifdef llvm}
 {$ifdef llvm}
         llvmdefs.free;
         llvmdefs.free;
         llvmdefs:=THashSet.Create(64,true,false);
         llvmdefs:=THashSet.Create(64,true,false);
+        llvmusedsyms.free;
+        llvmusedsyms:=TFPObjectList.Create(false);
+        llvmcompilerusedsyms.free;
+        llvmcompilerusedsyms:=TFPObjectList.Create(false);
 {$endif llvm}
 {$endif llvm}
         wpoinfo.free;
         wpoinfo.free;
         wpoinfo:=nil;
         wpoinfo:=nil;

+ 13 - 2
compiler/llvm/nllvmtcon.pas

@@ -124,7 +124,7 @@ interface
 implementation
 implementation
 
 
   uses
   uses
-    verbose,systems,
+    verbose,systems,fmodule,
     aasmdata,
     aasmdata,
     cpubase,cpuinfo,llvmbase,
     cpubase,cpuinfo,llvmbase,
     symtable,llvmdef,defutil,defcmp;
     symtable,llvmdef,defutil,defcmp;
@@ -202,7 +202,18 @@ implementation
         include(decl.flags,ldf_vectorized);
         include(decl.flags,ldf_vectorized);
       if tcalo_weak in options then
       if tcalo_weak in options then
         include(decl.flags,ldf_weak);
         include(decl.flags,ldf_weak);
-      { TODO: tcalo_no_dead_strip: add to @llvm.user meta-variable }
+      if tcalo_no_dead_strip in options then
+        { Objective-C section declarations already contain "no_dead_strip"
+          attributes if none of their symbols need to be stripped -> only
+          add the symbols to llvm.compiler.used (only affects compiler
+          optimisations) and not to llvm.used (also affects linker -- which in
+          this case is already taken care of by the section attribute; not sure
+          why it's done like this, but this is how Clang does it) }
+        if (target_info.system in systems_darwin) and
+           (section in [low(TObjCAsmSectionType)..high(TObjCAsmSectionType)]) then
+          current_module.llvmcompilerusedsyms.add(decl)
+        else
+          current_module.llvmusedsyms.add(decl);
       newasmlist.concat(decl);
       newasmlist.concat(decl);
       fasmlist:=newasmlist;
       fasmlist:=newasmlist;
     end;
     end;

+ 42 - 2
compiler/llvm/nllvmutil.pas

@@ -26,7 +26,7 @@ unit nllvmutil;
 interface
 interface
 
 
   uses
   uses
-    globtype,
+    globtype,cclasses,
     aasmdata,ngenutil,
     aasmdata,ngenutil,
     symtype,symconst,symsym,symdef;
     symtype,symconst,symsym,symdef;
 
 
@@ -35,6 +35,7 @@ interface
     tllvmnodeutils = class(tnodeutils)
     tllvmnodeutils = class(tnodeutils)
      strict protected
      strict protected
       class procedure insertbsssym(list: tasmlist; sym: tstaticvarsym; size: asizeint; varalign: shortint); override;
       class procedure insertbsssym(list: tasmlist; sym: tstaticvarsym; size: asizeint; varalign: shortint); override;
+      class procedure InsertUsedList(var usedsyms: tfpobjectlist; const usedsymsname: TSymstr);
      public
      public
       class procedure InsertObjectInfo; override;
       class procedure InsertObjectInfo; override;
     end;
     end;
@@ -45,7 +46,7 @@ implementation
     uses
     uses
       verbose,cutils,globals,fmodule,systems,
       verbose,cutils,globals,fmodule,systems,
       aasmbase,aasmtai,cpubase,llvmbase,aasmllvm,
       aasmbase,aasmtai,cpubase,llvmbase,aasmllvm,
-      aasmcnst,
+      aasmcnst,nllvmtcon,
       symbase,symtable,defutil,
       symbase,symtable,defutil,
       llvmtype;
       llvmtype;
 
 
@@ -70,10 +71,49 @@ implementation
     end;
     end;
 
 
 
 
+  class procedure tllvmnodeutils.InsertUsedList(var usedsyms: tfpobjectlist; const usedsymsname: TSymstr);
+    var
+      useddef: tdef;
+      tcb: ttai_typedconstbuilder;
+      decl: taillvmdecl;
+      i: longint;
+    begin
+      if usedsyms.count<>0 then
+        begin
+          tcb:=ctai_typedconstbuilder.create([tcalo_new_section]);
+          tllvmtai_typedconstbuilder(tcb).appendingdef:=true;
+          useddef:=carraydef.getreusable(voidpointertype,usedsyms.count);
+          tcb.maybe_begin_aggregate(useddef);
+          for i:=0 to usedsyms.count-1 do
+            begin
+              decl:=taillvmdecl(usedsyms[i]);
+              tcb.queue_init(voidpointertype);
+              tcb.queue_emit_asmsym(decl.namesym,decl.def);
+            end;
+          tcb.maybe_end_aggregate(useddef);
+          current_asmdata.AsmLists[al_globals].concatlist(
+            tcb.get_final_asmlist(
+              current_asmdata.DefineAsmSymbol(
+                usedsymsname,AB_GLOBAL,AT_DATA,useddef),useddef,sec_user,
+                'llvm.metadata',0
+            )
+          );
+          tcb.free;
+        end;
+      usedsyms.free;
+      usedsyms:=nil;
+    end;
+
+
   class procedure tllvmnodeutils.InsertObjectInfo;
   class procedure tllvmnodeutils.InsertObjectInfo;
     begin
     begin
       inherited;
       inherited;
 
 
+      { add the llvm.compiler.used array }
+      InsertUsedList(current_module.llvmcompilerusedsyms,'llvm.compiler.used');
+      { add the llvm.used array }
+      InsertUsedList(current_module.llvmusedsyms,'llvm.used');
+
       { add "type xx = .." statements for all used recorddefs }
       { add "type xx = .." statements for all used recorddefs }
       with TLLVMTypeInfo.Create do
       with TLLVMTypeInfo.Create do
         begin
         begin