Start refactoring of asmprinters: provide a TAI hook, which will select a 'section...
authorAnton Korobeynikov <asl@math.spbu.ru>
Sat, 28 Jun 2008 13:45:57 +0000 (13:45 +0000)
committerAnton Korobeynikov <asl@math.spbu.ru>
Sat, 28 Jun 2008 13:45:57 +0000 (13:45 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@52868 91177308-0d34-0410-b5e6-96231b3b80d8

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

index 9b5ba4819cb9408041fef3744aa9abd58734fe16..3b16ef1645f9320e608c5cc1b32770ee54bc200d 100644 (file)
@@ -29,8 +29,22 @@ namespace llvm {
     };
   }
 
+  namespace SectionKind {
+    enum Kind {
+      Text,             ///< Text section
+      Data,             ///< Data section
+      BSS,              ///< BSS section
+      ROData,           ///< Readonly data section
+      RODataMergeStr,   ///< Readonly data section (mergeable strings)
+      RODataMergeConst, ///< Readonly data section (mergeable constants)
+      ThreadData,       ///< Initialized TLS data objects
+      ThreadBSS         ///< Uninitialized TLS data objects
+    };
+  }
+
   class TargetMachine;
   class CallInst;
+  class GlobalValue;
 
   /// TargetAsmInfo - This class is intended to be used as a base class for asm
   /// properties and features specific to the target.
@@ -427,7 +441,11 @@ namespace llvm {
     /// if the symbol can be relocated.
     virtual unsigned PreferredEHDataFormat(DwarfEncoding::Target Reason,
                                            bool Global) const;
-    
+
+    /// SectionKindForGlobal - This hook allows the target to select proper
+    /// section kind used for global emission.
+    SectionKind::Kind SectionKindForGlobal(const GlobalValue *GV) const;
+
     // Accessors.
     //
     const char *getTextSection() const {
@@ -642,7 +660,7 @@ namespace llvm {
     }
     const char *getDwarfSectionOffsetDirective() const {
       return DwarfSectionOffsetDirective;
-    }    
+    }
     const char *getDwarfAbbrevSection() const {
       return DwarfAbbrevSection;
     }
index 67f0cfa5be88dcb6509e3dd683f795f4157ebc64..2adad3d7baa654f5e2fa81c735f5cf7ebbdd48b0 100644 (file)
 //
 //===----------------------------------------------------------------------===//
 
+#include "llvm/Constants.h"
+#include "llvm/GlobalVariable.h"
+#include "llvm/Function.h"
+#include "llvm/Module.h"
+#include "llvm/Type.h"
 #include "llvm/Target/TargetAsmInfo.h"
+#include "llvm/Target/TargetOptions.h"
 #include "llvm/Support/Dwarf.h"
 #include <cctype>
 #include <cstring>
@@ -142,3 +148,46 @@ unsigned TargetAsmInfo::PreferredEHDataFormat(DwarfEncoding::Target Reason,
   return dwarf::DW_EH_PE_absptr;
 }
 
+static bool isSuitableForBSS(const GlobalVariable *GV) {
+  if (!GV->hasInitializer())
+    return true;
+
+  // Leave constant zeros in readonly constant sections, so they can be shared
+  Constant *C = GV->getInitializer();
+  return (C->isNullValue() && !GV->isConstant() && !NoZerosInBSS);
+}
+
+SectionKind::Kind
+TargetAsmInfo::SectionKindForGlobal(const GlobalValue *GV) const {
+  // Early exit - functions should be always in text sections.
+  if (isa<Function>(GV))
+    return SectionKind::Text;
+
+  const GlobalVariable* GVar = dyn_cast<GlobalVariable>(GV);
+  bool isThreadLocal = GVar->isThreadLocal();
+  assert(GVar && "Invalid global value for section selection");
+
+  SectionKind::Kind kind;
+  if (isSuitableForBSS(GVar)) {
+    // Variable can be easily put to BSS section.
+    return (isThreadLocal ? SectionKind::ThreadBSS : SectionKind::BSS);
+  } else if (GVar->isConstant() && !isThreadLocal) {
+    // Now we know, that varible has initializer and it is constant. We need to
+    // check its initializer to decide, which section to output it into. Also
+    // note, there is no thread-local r/o section.
+    Constant *C = GVar->getInitializer();
+    if (C->ContainsRelocations())
+      kind = SectionKind::ROData;
+    else {
+      const ConstantArray *CVA = dyn_cast<ConstantArray>(C);
+      // Check, if initializer is a null-terminated string
+      if (CVA && CVA->isCString())
+        kind = SectionKind::RODataMergeStr;
+      else
+        kind = SectionKind::RODataMergeConst;
+    }
+  }
+
+  // Variable is not constant or thread-local - emit to generic data section.
+  return (isThreadLocal ? SectionKind::ThreadData : SectionKind::Data);
+}