implement a new magic global "llvm.compiler.used" which is like llvm.used, but
authorChris Lattner <sabre@nondot.org>
Mon, 20 Jul 2009 06:14:25 +0000 (06:14 +0000)
committerChris Lattner <sabre@nondot.org>
Mon, 20 Jul 2009 06:14:25 +0000 (06:14 +0000)
doesn't cause ".no_dead_strip" to be emitted on darwin.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@76399 91177308-0d34-0410-b5e6-96231b3b80d8

docs/LangRef.html
include/llvm/CodeGen/MachineModuleInfo.h
lib/CodeGen/AsmPrinter/AsmPrinter.cpp
lib/CodeGen/AsmPrinter/DwarfException.cpp
lib/CodeGen/MachineModuleInfo.cpp
lib/Transforms/IPO/Internalize.cpp
lib/Transforms/IPO/StripSymbols.cpp
test/CodeGen/X86/compiler_used.ll [new file with mode: 0644]

index 910fc5c6514bfccf9f9d5a28477ed1863bccd993..dced11c44166905ee060d7c1ccc6657467fdb855 100644 (file)
@@ -94,6 +94,8 @@
   <li><a href="#intrinsic_globals">Intrinsic Global Variables</a>
     <ol>
       <li><a href="#intg_used">The '<tt>llvm.used</tt>' Global Variable</a></li>
+      <li><a href="#intg_compiler_used">The '<tt>llvm.compiler.used</tt>'
+          Global Variable</a></li>
       <li><a href="#intg_global_ctors">The '<tt>llvm.global_ctors</tt>'
          Global Variable</a></li>
       <li><a href="#intg_global_dtors">The '<tt>llvm.global_dtors</tt>'
@@ -2168,8 +2170,9 @@ call void asm sideeffect "eieio", ""()
 
 <p>LLVM has a number of "magic" global variables that contain data that affect
 code generation or other IR semantics.  These are documented here.  All globals
-of this sort should have a section specified as "llvm.metadata".  This section
-and all globals that start with "llvm." are reserved for LLVM.</p>
+of this sort should have a section specified as "<tt>llvm.metadata</tt>".  This
+section and all globals that start with "<tt>llvm.</tt>" are reserved for use
+by LLVM.</p>
 
 <!-- ======================================================================= -->
 <div class="doc_subsection">
@@ -2206,6 +2209,24 @@ object file to prevent the assembler and linker from molesting the symbol.</p>
 
 </div>
 
+<!-- ======================================================================= -->
+<div class="doc_subsection">
+<a name="intg_compiler_used">The '<tt>llvm.compiler.used</tt>' Global Variable</a>
+</div>
+
+<div class="doc_text">
+
+<p>The <tt>@llvm.compiler.used</tt> directive is the same as the
+<tt>@llvm.used</tt> directive, except that it only prevents the compiler from
+touching the symbol.  On targets that support it, this allows an intelligent
+linker to optimize references to the symbol without being impeded as it would be
+by <tt>@llvm.used</tt>.</p>
+
+<p>This is a rare construct that should only be used in rare circumstances, and
+should not be exposed to source languages.</p>
+
+</div>
+
 <!-- ======================================================================= -->
 <div class="doc_subsection">
 <a name="intg_global_ctors">The '<tt>llvm.global_ctors</tt>' Global Variable</a>
index 1872bd26d8aac5ed6b7e62d289f1d917252105cf..3618898a79da0791e49e78515751d88f985927eb 100644 (file)
@@ -112,8 +112,9 @@ private:
   // common EH frames.
   std::vector<Function *> Personalities;
 
-  // UsedFunctions - the functions in the llvm.used list in a more easily
-  // searchable format.
+  /// UsedFunctions - The functions in the @llvm.used list in a more easily
+  /// searchable format.  This does not include the functions in
+  /// llvm.compiler.used.
   SmallPtrSet<const Function *, 32> UsedFunctions;
 
   /// UsedDbgLabels - labels are used by debug info entries.
@@ -240,9 +241,11 @@ public:
     return Personalities;
   }
 
-  // UsedFunctions - Return set of the functions in the llvm.used list.
-  const SmallPtrSet<const Function *, 32>& getUsedFunctions() const {
-    return UsedFunctions;
+  /// isUsedFunction - Return true if the functions in the llvm.used list.  This
+  /// does not return true for things in llvm.compiler.used unless they are also
+  /// in llvm.used.
+  bool isUsedFunction(const Function *F) {
+    return UsedFunctions.count(F);
   }
 
   /// addCatchTypeInfo - Provide the catch typeinfo for a landing pad.
index a2d154f1ee6324f98924259d79eb4d40113d4599..80bdf04e8e8b3c382c59b121afff387b33df539b 100644 (file)
@@ -466,13 +466,13 @@ void AsmPrinter::printPICJumpTableEntry(const MachineJumpTableInfo *MJTI,
 /// special global used by LLVM.  If so, emit it and return true, otherwise
 /// do nothing and return false.
 bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) {
-  if (GV->getName() == "llvm.used") {
+  if (GV->isName("llvm.used")) {
     if (TAI->getUsedDirective() != 0)    // No need to emit this at all.
       EmitLLVMUsedList(GV->getInitializer());
     return true;
   }
 
-  // Ignore debug and non-emitted data.
+  // Ignore debug and non-emitted data.  This handles llvm.compiler.used.
   if (GV->getSection() == "llvm.metadata" ||
       GV->hasAvailableExternallyLinkage())
     return true;
index 1af3b11846554ac997768cdb9d9283da811b624b..fdec97ac6ac765f529ab168ab82bcfcd66391630 100644 (file)
@@ -229,7 +229,7 @@ void DwarfException::EmitEHFrame(const FunctionEHFrameInfo &EHFrameInfo) {
     // retains the function in this case, and there is code around that depends
     // on unused functions (calling undefined externals) being dead-stripped to
     // link correctly.  Yes, there really is.
-    if (MMI->getUsedFunctions().count(EHFrameInfo.function))
+    if (MMI->isUsedFunction(EHFrameInfo.function))
       if (const char *UsedDirective = TAI->getUsedDirective())
         O << UsedDirective << EHFrameInfo.FnName << "\n\n";
   }
index 66dd8375eb509771e9c153b4ddf345977c71c649..20b819e8235105680c87668322f5f3b50111f02f 100644 (file)
@@ -88,7 +88,8 @@ void MachineModuleInfo::EndFunction() {
 /// AnalyzeModule - Scan the module for global debug information.
 ///
 void MachineModuleInfo::AnalyzeModule(Module &M) {
-  // Insert functions in the llvm.used array into UsedFunctions.
+  // Insert functions in the llvm.used array (but not llvm.compiler.used) into
+  // UsedFunctions.
   GlobalVariable *GV = M.getGlobalVariable("llvm.used");
   if (!GV || !GV->hasInitializer()) return;
 
index 9bc91725170ec641190b9a4d1af1659152fc0732..da92634abf77debddcf7ccb22ef08c73556bbbfa 100644 (file)
@@ -138,7 +138,9 @@ bool InternalizePass::runOnModule(Module &M) {
 
   // Never internalize the llvm.used symbol.  It is used to implement
   // attribute((used)).
+  // FIXME: Shouldn't this just filter on llvm.metadata section??
   ExternalNames.insert("llvm.used");
+  ExternalNames.insert("llvm.compiler.used");
 
   // Never internalize anchors used by the machine module info, else the info
   // won't find them.  (see MachineModuleInfo.)
index 82a0952aa205cadc40f59fd68c305f5ee20bda82..8f3a7f4a649a7ba17722e0432294272a6fe50691 100644 (file)
@@ -157,32 +157,26 @@ static void StripTypeSymtab(TypeSymbolTable &ST, bool PreserveDbgInfo) {
 }
 
 /// Find values that are marked as llvm.used.
-void findUsedValues(Module &M,
-                    SmallPtrSet<const GlobalValue*, 8>& llvmUsedValues) {
-  if (GlobalVariable *LLVMUsed = M.getGlobalVariable("llvm.used")) {
-    llvmUsedValues.insert(LLVMUsed);
-    // Collect values that are preserved as per explicit request.
-    // llvm.used is used to list these values.
-    if (ConstantArray *Inits = 
-        dyn_cast<ConstantArray>(LLVMUsed->getInitializer())) {
-      for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i) {
-        if (GlobalValue *GV = dyn_cast<GlobalValue>(Inits->getOperand(i)))
-          llvmUsedValues.insert(GV);
-        else if (ConstantExpr *CE =
-                 dyn_cast<ConstantExpr>(Inits->getOperand(i)))
-          if (CE->getOpcode() == Instruction::BitCast)
-            if (GlobalValue *GV = dyn_cast<GlobalValue>(CE->getOperand(0)))
-              llvmUsedValues.insert(GV);
-      }
-    }
-  }
+static void findUsedValues(GlobalVariable *LLVMUsed,
+                           SmallPtrSet<const GlobalValue*, 8> &UsedValues) {
+  if (LLVMUsed == 0) return;
+  UsedValues.insert(LLVMUsed);
+  
+  ConstantArray *Inits = dyn_cast<ConstantArray>(LLVMUsed->getInitializer());
+  if (Inits == 0) return;
+  
+  for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i)
+    if (GlobalValue *GV = 
+          dyn_cast<GlobalValue>(Inits->getOperand(i)->stripPointerCasts()))
+      UsedValues.insert(GV);
 }
 
 /// StripSymbolNames - Strip symbol names.
 bool StripSymbolNames(Module &M, bool PreserveDbgInfo) {
 
   SmallPtrSet<const GlobalValue*, 8> llvmUsedValues;
-  findUsedValues(M, llvmUsedValues);
+  findUsedValues(M.getGlobalVariable("llvm.used"), llvmUsedValues);
+  findUsedValues(M.getGlobalVariable("llvm.compiler.used"), llvmUsedValues);
 
   for (Module::global_iterator I = M.global_begin(), E = M.global_end();
        I != E; ++I) {
@@ -210,7 +204,8 @@ bool StripSymbolNames(Module &M, bool PreserveDbgInfo) {
 bool StripDebugInfo(Module &M) {
 
   SmallPtrSet<const GlobalValue*, 8> llvmUsedValues;
-  findUsedValues(M, llvmUsedValues);
+  findUsedValues(M.getGlobalVariable("llvm.used"), llvmUsedValues);
+  findUsedValues(M.getGlobalVariable("llvm.compiler.used"), llvmUsedValues);
 
   SmallVector<GlobalVariable *, 2> CUs;
   SmallVector<GlobalVariable *, 4> GVs;
diff --git a/test/CodeGen/X86/compiler_used.ll b/test/CodeGen/X86/compiler_used.ll
new file mode 100644 (file)
index 0000000..b67bc36
--- /dev/null
@@ -0,0 +1,9 @@
+; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin9 | grep no_dead_strip | count 1
+; We should have a .no_dead_strip directive for Z but not for X/Y.
+
+@X = internal global i8 4
+@Y = internal global i32 123
+@Z = internal global i8 4
+
+@llvm.used = appending global [1 x i8*] [ i8* @Z ], section "llvm.metadata"
+@llvm.compiler_used = appending global [2 x i8*] [ i8* @X, i8* bitcast (i32* @Y to i8*)], section "llvm.metadata"