Add support for targets that want to do something with the llvm.used list,
authorChris Lattner <sabre@nondot.org>
Tue, 26 Sep 2006 03:38:18 +0000 (03:38 +0000)
committerChris Lattner <sabre@nondot.org>
Tue, 26 Sep 2006 03:38:18 +0000 (03:38 +0000)
because they have an aggressive linker that does dead code stripping.

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

include/llvm/CodeGen/AsmPrinter.h
include/llvm/Target/TargetAsmInfo.h
lib/CodeGen/AsmPrinter.cpp
lib/Target/TargetAsmInfo.cpp

index 52e47faca48114586a4c722f045269ddbf120aef..386a8d53fd60cb9113b6ce7f35057bc795e6e10e 100644 (file)
@@ -197,6 +197,7 @@ namespace llvm {
     void printDataDirective(const Type *type);
 
   private:
+    void EmitLLVMUsedList(Constant *List);
     void EmitXXStructorList(Constant *List);
     void EmitConstantPool(unsigned Alignment, const char *Section,
                 std::vector<std::pair<MachineConstantPoolEntry,unsigned> > &CP);
index 82132c01850e0447b613cf8854b0ee3b0932c454..9c3a5ab0f2c409bb0b95ad46e662ba8d17eb4639 100644 (file)
@@ -199,6 +199,11 @@ namespace llvm {
     /// directives, this is true for most ELF targets.
     bool HasDotTypeDotSizeDirective;      // Defaults to true.
     
+    /// UsedDirective - This directive, if non-null, is used to declare a global
+    /// as being used somehow that the assembler can't see.  This prevents dead
+    /// code elimination on some targets.
+    const char *UsedDirective;            // Defaults to null.
+    
     //===--- Dwarf Emission Directives -----------------------------------===//
 
     /// HasLEB128 - True if target asm supports leb128 directives.
@@ -387,6 +392,9 @@ namespace llvm {
     bool hasDotTypeDotSizeDirective() const {
       return HasDotTypeDotSizeDirective;
     }
+    const char *getUsedDirective() const {
+      return UsedDirective;
+    }
     bool hasLEB128() const {
       return HasLEB128;
     }
index bcdb393c239724e72c9a503e3f68eb54c9b54c0d..bfc0519806c3edf5a4425446c76ecd8ba312699b 100644 (file)
@@ -253,8 +253,11 @@ bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) {
 
   assert(GV->hasInitializer() && "Not a special LLVM global!");
   
-  if (GV->getName() == "llvm.used")
-    return true;  // No need to emit this at all.
+  if (GV->getName() == "llvm.used") {
+    if (TAI->getUsedDirective() != 0)    // No need to emit this at all.
+      EmitLLVMUsedList(GV->getInitializer());
+    return true;
+  }
 
   if (GV->getName() == "llvm.global_ctors" && GV->use_empty()) {
     SwitchToDataSection(TAI->getStaticCtorsSection(), 0);
@@ -273,6 +276,22 @@ bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) {
   return false;
 }
 
+/// EmitLLVMUsedList - For targets that define a TAI::UsedDirective, mark each
+/// global in the specified llvm.used list as being used with this directive.
+void AsmPrinter::EmitLLVMUsedList(Constant *List) {
+  const char *Directive = TAI->getUsedDirective();
+
+  // Should be an array of 'sbyte*'.
+  ConstantArray *InitList = dyn_cast<ConstantArray>(List);
+  if (InitList == 0) return;
+  
+  for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
+    O << Directive;
+    EmitConstantValueOnly(InitList->getOperand(i));
+    O << "\n";
+  }
+}
+
 /// EmitXXStructorList - Emit the ctor or dtor list.  This just prints out the 
 /// function pointers, ignoring the init priority.
 void AsmPrinter::EmitXXStructorList(Constant *List) {
index 6efcf4be2455242740ba020baf6c0b6d9fc1b005..c085eb4db02e4b2366d705f0ad1a86eaf3b8d605 100644 (file)
@@ -58,6 +58,7 @@ TargetAsmInfo::TargetAsmInfo() :
   COMMDirective("\t.comm\t"),
   COMMDirectiveTakesAlignment(true),
   HasDotTypeDotSizeDirective(true),
+  UsedDirective(0),
   HasLEB128(false),
   HasDotLoc(false),
   HasDotFile(false),