aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/llvm/Target/TargetAsmInfo.h22
-rw-r--r--lib/Target/TargetAsmInfo.cpp49
2 files changed, 69 insertions, 2 deletions
diff --git a/include/llvm/Target/TargetAsmInfo.h b/include/llvm/Target/TargetAsmInfo.h
index 9b5ba48..3b16ef1 100644
--- a/include/llvm/Target/TargetAsmInfo.h
+++ b/include/llvm/Target/TargetAsmInfo.h
@@ -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;
}
diff --git a/lib/Target/TargetAsmInfo.cpp b/lib/Target/TargetAsmInfo.cpp
index 67f0cfa..2adad3d 100644
--- a/lib/Target/TargetAsmInfo.cpp
+++ b/lib/Target/TargetAsmInfo.cpp
@@ -12,7 +12,13 @@
//
//===----------------------------------------------------------------------===//
+#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);
+}