TargetAsmInfo::TargetAsmInfo() :
TextSection("\t.text"),
+ TextSection_(0),
DataSection("\t.data"),
+ DataSection_(0),
BSSSection("\t.bss"),
+ BSSSection_(0),
+ ReadOnlySection(0),
+ ReadOnlySection_(0),
TLSDataSection("\t.section .tdata,\"awT\",@progbits"),
+ TLSDataSection_(0),
TLSBSSSection("\t.section .tbss,\"awT\",@nobits"),
+ TLSBSSSection_(0),
ZeroFillDirective(0),
NonexecutableStackDirective(0),
NeedsSet(false),
JumpTableDataSection("\t.section .rodata"),
JumpTableDirective(0),
CStringSection(0),
+ CStringSection_(0),
StaticCtorsSection("\t.section .ctors,\"aw\",@progbits"),
StaticDtorsSection("\t.section .dtors,\"aw\",@progbits"),
FourByteConstantSection(0),
+ FourByteConstantSection_(0),
EightByteConstantSection(0),
+ EightByteConstantSection_(0),
SixteenByteConstantSection(0),
- ReadOnlySection(0),
+ SixteenByteConstantSection_(0),
GlobalDirective("\t.globl\t"),
SetDirective(0),
LCOMMDirective(0),
DwarfEHFrameSection(".eh_frame"),
DwarfExceptionSection(".gcc_except_table"),
AsmTransCBE(0) {
+ TextSection_ = getUnnamedSection(TextSection);
+ DataSection_ = getUnnamedSection(DataSection);
}
TargetAsmInfo::~TargetAsmInfo() {
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);
// note, there is no thread-local r/o section.
Constant *C = GVar->getInitializer();
if (C->ContainsRelocations())
- kind = SectionKind::ROData;
+ return 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;
+ return SectionKind::RODataMergeStr;
else
- kind = SectionKind::RODataMergeConst;
+ return SectionKind::RODataMergeConst;
}
}
unsigned
TargetAsmInfo::SectionFlagsForGlobal(const GlobalValue *GV,
- const char* name) const {
- unsigned flags = SectionFlags::None;
+ const char* Name) const {
+ unsigned Flags = SectionFlags::None;
// Decode flags from global itself.
if (GV) {
- SectionKind::Kind kind = SectionKindForGlobal(GV);
- switch (kind) {
+ SectionKind::Kind Kind = SectionKindForGlobal(GV);
+ switch (Kind) {
case SectionKind::Text:
- flags |= SectionFlags::Code;
+ Flags |= SectionFlags::Code;
break;
case SectionKind::ThreadData:
- flags |= SectionFlags::TLS;
- // FALLS THROUGH
- case SectionKind::Data:
- flags |= SectionFlags::Writeable;
- break;
case SectionKind::ThreadBSS:
- flags |= SectionFlags::TLS;
+ Flags |= SectionFlags::TLS;
// FALLS THROUGH
+ case SectionKind::Data:
case SectionKind::BSS:
- flags |= SectionFlags::BSS;
+ Flags |= SectionFlags::Writeable;
break;
case SectionKind::ROData:
- // No additional flags here
- break;
case SectionKind::RODataMergeStr:
- flags |= SectionFlags::Strings;
- // FALLS THROUGH
case SectionKind::RODataMergeConst:
- flags |= SectionFlags::Mergeable;
+ // No additional flags here
break;
default:
assert(0 && "Unexpected section kind!");
}
- if (GV->hasLinkOnceLinkage() ||
- GV->hasWeakLinkage() ||
- GV->hasCommonLinkage())
- flags |= SectionFlags::Linkonce;
+ if (GV->isWeakForLinker())
+ Flags |= SectionFlags::Linkonce;
}
// Add flags from sections, if any.
- if (name) {
- // Some lame default implementation
- if (strcmp(name, ".bss") == 0 ||
- strncmp(name, ".bss.", 5) == 0 ||
- strncmp(name, ".gnu.linkonce.b.", 16) == 0)
- flags |= SectionFlags::BSS;
- else if (strcmp(name, ".tdata") == 0 ||
- strncmp(name, ".tdata.", 7) == 0 ||
- strncmp(name, ".gnu.linkonce.td.", 17) == 0)
- flags |= SectionFlags::TLS;
- else if (strcmp(name, ".tbss") == 0 ||
- strncmp(name, ".tbss.", 6) == 0 ||
- strncmp(name, ".gnu.linkonce.tb.", 17) == 0)
- flags |= SectionFlags::BSS | SectionFlags::TLS;
+ if (Name && *Name) {
+ Flags |= SectionFlags::Named;
+
+ // Some lame default implementation based on some magic section names.
+ if (strncmp(Name, ".gnu.linkonce.b.", 16) == 0 ||
+ strncmp(Name, ".llvm.linkonce.b.", 17) == 0)
+ Flags |= SectionFlags::BSS;
+ else if (strcmp(Name, ".tdata") == 0 ||
+ strncmp(Name, ".tdata.", 7) == 0 ||
+ strncmp(Name, ".gnu.linkonce.td.", 17) == 0 ||
+ strncmp(Name, ".llvm.linkonce.td.", 18) == 0)
+ Flags |= SectionFlags::TLS;
+ else if (strcmp(Name, ".tbss") == 0 ||
+ strncmp(Name, ".tbss.", 6) == 0 ||
+ strncmp(Name, ".gnu.linkonce.tb.", 17) == 0 ||
+ strncmp(Name, ".llvm.linkonce.tb.", 18) == 0)
+ Flags |= SectionFlags::BSS | SectionFlags::TLS;
}
- return flags;
+ return Flags;
}
-const char*
+std::string
TargetAsmInfo::SectionForGlobal(const GlobalValue *GV) const {
- SectionKind::Kind kind = SectionKindForGlobal(GV);
+ const Section* S;
+ // Select section name
+ if (GV->hasSection()) {
+ // Honour section already set, if any
+ unsigned Flags = SectionFlagsForGlobal(GV,
+ GV->getSection().c_str());
+ S = getNamedSection(GV->getSection().c_str(), Flags);
+ } else {
+ // Use default section depending on the 'type' of global
+ S = SelectSectionForGlobal(GV);
+ }
+
+ if (!S->isNamed())
+ return S->Name;
+
+ // If section is named we need to switch into it via special '.section'
+ // directive and also append funky flags. Otherwise - section name is just
+ // some magic assembler directive.
+ return getSwitchToSectionDirective() + S->Name + PrintSectionFlags(S->Flags);
+}
- if (kind == SectionKind::Text)
- return getTextSection();
- else if (kind == SectionKind::BSS && getBSSSection())
- return getBSSSection();
+// Lame default implementation. Calculate the section name for global.
+const Section*
+TargetAsmInfo::SelectSectionForGlobal(const GlobalValue *GV) const {
+ SectionKind::Kind Kind = SectionKindForGlobal(GV);
+
+ if (GV->isWeakForLinker()) {
+ std::string Name = UniqueSectionForGlobal(GV, Kind);
+ unsigned Flags = SectionFlagsForGlobal(GV, Name.c_str());
+ return getNamedSection(Name.c_str(), Flags);
+ } else {
+ if (Kind == SectionKind::Text)
+ return getTextSection_();
+ else if (Kind == SectionKind::BSS && getBSSSection_())
+ return getBSSSection_();
+ else if (getReadOnlySection_() &&
+ (Kind == SectionKind::ROData ||
+ Kind == SectionKind::RODataMergeConst ||
+ Kind == SectionKind::RODataMergeStr))
+ return getReadOnlySection_();
+ }
+
+ return getDataSection_();
+}
+
+std::string
+TargetAsmInfo::UniqueSectionForGlobal(const GlobalValue* GV,
+ SectionKind::Kind Kind) const {
+ switch (Kind) {
+ case SectionKind::Text:
+ return ".gnu.linkonce.t." + GV->getName();
+ case SectionKind::Data:
+ return ".gnu.linkonce.d." + GV->getName();
+ case SectionKind::BSS:
+ return ".gnu.linkonce.b." + GV->getName();
+ case SectionKind::ROData:
+ case SectionKind::RODataMergeConst:
+ case SectionKind::RODataMergeStr:
+ return ".gnu.linkonce.r." + GV->getName();
+ case SectionKind::ThreadData:
+ return ".gnu.linkonce.td." + GV->getName();
+ case SectionKind::ThreadBSS:
+ return ".gnu.linkonce.tb." + GV->getName();
+ default:
+ assert(0 && "Unknown section kind");
+ }
+}
+
+const Section*
+TargetAsmInfo::getNamedSection(const char *Name, unsigned Flags) const {
+ Section& S = Sections[Name];
+
+ // This is newly-created section, set it up properly.
+ if (S.Flags == SectionFlags::Invalid) {
+ S.Flags = Flags | SectionFlags::Named;
+ S.Name = Name;
+ }
+
+ return &S;
+}
+
+const Section*
+TargetAsmInfo::getUnnamedSection(const char *Directive, unsigned Flags) const {
+ Section& S = Sections[Directive];
+
+ // This is newly-created section, set it up properly.
+ if (S.Flags == SectionFlags::Invalid) {
+ S.Flags = Flags & ~SectionFlags::Named;
+ S.Name = Directive;
+ }
- return getDataSection();
+ return &S;
}