//===-- llvm/Target/TargetLoweringObjectFile.cpp - Object File Info -------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file implements classes used to handle lowerings specific to common // object file formats. // //===----------------------------------------------------------------------===// #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/GlobalVariable.h" #include "llvm/Support/Mangler.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetOptions.h" #include "llvm/ADT/StringExtras.h" using namespace llvm; //===----------------------------------------------------------------------===// // Generic Code //===----------------------------------------------------------------------===// TargetLoweringObjectFile::TargetLoweringObjectFile() { TextSection = 0; DataSection = 0; BSSSection_ = 0; ReadOnlySection = 0; TLSDataSection = 0; TLSBSSSection = 0; CStringSection_ = 0; } TargetLoweringObjectFile::~TargetLoweringObjectFile() { } static bool isSuitableForBSS(const GlobalVariable *GV) { Constant *C = GV->getInitializer(); // Must have zero initializer. if (!C->isNullValue()) return false; // Leave constant zeros in readonly constant sections, so they can be shared. if (GV->isConstant()) return false; // If the global has an explicit section specified, don't put it in BSS. if (!GV->getSection().empty()) return false; // If -nozero-initialized-in-bss is specified, don't ever use BSS. if (NoZerosInBSS) return false; // Otherwise, put it in BSS! return true; } static bool isConstantString(const Constant *C) { // First check: is we have constant array of i8 terminated with zero const ConstantArray *CVA = dyn_cast(C); // Check, if initializer is a null-terminated string if (CVA && CVA->isCString()) return true; // Another possibility: [1 x i8] zeroinitializer if (isa(C)) if (const ArrayType *Ty = dyn_cast(C->getType())) return (Ty->getElementType() == Type::Int8Ty && Ty->getNumElements() == 1); return false; } static SectionKind::Kind SectionKindForGlobal(const GlobalValue *GV, const TargetMachine &TM) { Reloc::Model ReloModel = TM.getRelocationModel(); // Early exit - functions should be always in text sections. const GlobalVariable *GVar = dyn_cast(GV); if (GVar == 0) return SectionKind::Text; // Handle thread-local data first. if (GVar->isThreadLocal()) { if (isSuitableForBSS(GVar)) return SectionKind::ThreadBSS; return SectionKind::ThreadData; } // Variable can be easily put to BSS section. if (isSuitableForBSS(GVar)) return SectionKind::BSS; Constant *C = GVar->getInitializer(); // If the global is marked constant, we can put it into a mergable section, // a mergable string section, or general .data if it contains relocations. if (GVar->isConstant()) { // If the initializer for the global contains something that requires a // relocation, then we may have to drop this into a wriable data section // even though it is marked const. switch (C->getRelocationInfo()) { default: llvm_unreachable("unknown relocation info kind"); case Constant::NoRelocation: // If initializer is a null-terminated string, put it in a "cstring" // section if the target has it. if (isConstantString(C)) return SectionKind::MergeableCString; // Otherwise, just drop it into a mergable constant section. If we have // a section for this size, use it, otherwise use the arbitrary sized // mergable section. switch (TM.getTargetData()->getTypeAllocSize(C->getType())) { case 4: return SectionKind::MergeableConst4; case 8: return SectionKind::MergeableConst8; case 16: return SectionKind::MergeableConst16; default: return SectionKind::MergeableConst; } case Constant::LocalRelocation: // In static relocation model, the linker will resolve all addresses, so // the relocation entries will actually be constants by the time the app // starts up. However, we can't put this into a mergable section, because // the linker doesn't take relocations into consideration when it tries to // merge entries in the section. if (ReloModel == Reloc::Static) return SectionKind::ReadOnly; // Otherwise, the dynamic linker needs to fix it up, put it in the // writable data.rel.local section. return SectionKind::ReadOnlyWithRelLocal; case Constant::GlobalRelocations: // In static relocation model, the linker will resolve all addresses, so // the relocation entries will actually be constants by the time the app // starts up. However, we can't put this into a mergable section, because // the linker doesn't take relocations into consideration when it tries to // merge entries in the section. if (ReloModel == Reloc::Static) return SectionKind::ReadOnly; // Otherwise, the dynamic linker needs to fix it up, put it in the // writable data.rel section. return SectionKind::ReadOnlyWithRel; } } // Okay, this isn't a constant. If the initializer for the global is going // to require a runtime relocation by the dynamic linker, put it into a more // specific section to improve startup time of the app. This coalesces these // globals together onto fewer pages, improving the locality of the dynamic // linker. if (ReloModel == Reloc::Static) return SectionKind::DataNoRel; switch (C->getRelocationInfo()) { default: llvm_unreachable("unknown relocation info kind"); case Constant::NoRelocation: return SectionKind::DataNoRel; case Constant::LocalRelocation: return SectionKind::DataRelLocal; case Constant::GlobalRelocations: return SectionKind::DataRel; } } /// SectionForGlobal - This method computes the appropriate section to emit /// the specified global variable or function definition. This should not /// be passed external (or available externally) globals. const Section *TargetLoweringObjectFile:: SectionForGlobal(const GlobalValue *GV, Mangler *Mang, const TargetMachine &TM) const { assert(!GV->isDeclaration() && !GV->hasAvailableExternallyLinkage() && "Can only be used for global definitions"); SectionKind::Kind GVKind = SectionKindForGlobal(GV, TM); SectionKind Kind = SectionKind::get(GVKind, GV->isWeakForLinker(), GV->hasSection()); // Select section name. if (GV->hasSection()) { // If the target has special section hacks for specifically named globals, // return them now. if (const Section *TS = getSpecialCasedSectionGlobals(GV, Mang, Kind)) return TS; // If the target has magic semantics for certain section names, make sure to // pick up the flags. This allows the user to write things with attribute // section and still get the appropriate section flags printed. GVKind = getKindForNamedSection(GV->getSection().c_str(), GVKind); return getOrCreateSection(GV->getSection().c_str(), false, GVKind); } // Use default section depending on the 'type' of global return SelectSectionForGlobal(GV, Kind, Mang, TM); } // Lame default implementation. Calculate the section name for global. const Section* TargetLoweringObjectFile::SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, Mangler *Mang, const TargetMachine &TM) const{ assert(!Kind.isThreadLocal() && "Doesn't support TLS"); if (Kind.isText()) return getTextSection(); if (Kind.isBSS() && BSSSection_ != 0) return BSSSection_; if (Kind.isReadOnly() && ReadOnlySection != 0) return ReadOnlySection; return getDataSection(); } /// getSectionForMergableConstant - Given a mergable constant with the /// specified size and relocation information, return a section that it /// should be placed in. const Section * TargetLoweringObjectFile:: getSectionForMergeableConstant(SectionKind Kind) const { if (Kind.isReadOnly() && ReadOnlySection != 0) return ReadOnlySection; return DataSection; } const Section *TargetLoweringObjectFile:: getOrCreateSection(const char *Name, bool isDirective, SectionKind::Kind Kind) const { Section &S = Sections[Name]; // This is newly-created section, set it up properly. if (S.Name.empty()) { S.Kind = SectionKind::get(Kind, false /*weak*/, !isDirective); S.Name = Name; } return &S; } //===----------------------------------------------------------------------===// // ELF //===----------------------------------------------------------------------===// TargetLoweringObjectFileELF::TargetLoweringObjectFileELF(bool atIsCommentChar, bool HasCrazyBSS) : AtIsCommentChar(atIsCommentChar) { if (!HasCrazyBSS) BSSSection_ = getOrCreateSection("\t.bss", true, SectionKind::BSS); else // PPC/Linux doesn't support the .bss directive, it needs .section .bss. // FIXME: Does .section .bss work everywhere?? BSSSection_ = getOrCreateSection("\t.bss", false, SectionKind::BSS); TextSection = getOrCreateSection("\t.text", true, SectionKind::Text); DataSection = getOrCreateSection("\t.data", true, SectionKind::DataRel); ReadOnlySection = getOrCreateSection("\t.rodata", false, SectionKind::ReadOnly); TLSDataSection = getOrCreateSection("\t.tdata", false, SectionKind::ThreadData); CStringSection_ = getOrCreateSection("\t.rodata.str", true, SectionKind::MergeableCString); TLSBSSSection = getOrCreateSection("\t.tbss", false, SectionKind::ThreadBSS); DataRelSection = getOrCreateSection("\t.data.rel", false, SectionKind::DataRel); DataRelLocalSection = getOrCreateSection("\t.data.rel.local", false, SectionKind::DataRelLocal); DataRelROSection = getOrCreateSection("\t.data.rel.ro", false, SectionKind::ReadOnlyWithRel); DataRelROLocalSection = getOrCreateSection("\t.data.rel.ro.local", false, SectionKind::ReadOnlyWithRelLocal); MergeableConst4Section = getOrCreateSection(".rodata.cst4", false, SectionKind::MergeableConst4); MergeableConst8Section = getOrCreateSection(".rodata.cst8", false, SectionKind::MergeableConst8); MergeableConst16Section = getOrCreateSection(".rodata.cst16", false, SectionKind::MergeableConst16); } SectionKind::Kind TargetLoweringObjectFileELF:: getKindForNamedSection(const char *Name, SectionKind::Kind K) const { if (Name[0] != '.') return K; // 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 || strncmp(Name, ".gnu.linkonce.sb.", 17) == 0 || strncmp(Name, ".llvm.linkonce.sb.", 18) == 0) return SectionKind::BSS; if (strcmp(Name, ".tdata") == 0 || strncmp(Name, ".tdata.", 7) == 0 || strncmp(Name, ".gnu.linkonce.td.", 17) == 0 || strncmp(Name, ".llvm.linkonce.td.", 18) == 0) return SectionKind::ThreadData; if (strcmp(Name, ".tbss") == 0 || strncmp(Name, ".tbss.", 6) == 0 || strncmp(Name, ".gnu.linkonce.tb.", 17) == 0 || strncmp(Name, ".llvm.linkonce.tb.", 18) == 0) return SectionKind::ThreadBSS; return K; } void TargetLoweringObjectFileELF:: getSectionFlagsAsString(SectionKind Kind, SmallVectorImpl &Str) const { Str.push_back(','); Str.push_back('"'); if (!Kind.isMetadata()) Str.push_back('a'); if (Kind.isText()) Str.push_back('x'); if (Kind.isWriteable()) Str.push_back('w'); if (Kind.isMergeableConst() || Kind.isMergeableCString()) Str.push_back('M'); if (Kind.isMergeableCString()) Str.push_back('S'); if (Kind.isThreadLocal()) Str.push_back('T'); Str.push_back('"'); Str.push_back(','); // If comment string is '@', e.g. as on ARM - use '%' instead if (AtIsCommentChar) Str.push_back('%'); else Str.push_back('@'); const char *KindStr; if (Kind.isBSS() || Kind.isThreadBSS()) KindStr = "nobits"; else KindStr = "progbits"; Str.append(KindStr, KindStr+strlen(KindStr)); if (Kind.isMergeableCString()) { // TODO: Eventually handle multiple byte character strings. For now, all // mergable C strings are single byte. Str.push_back(','); Str.push_back('1'); } else if (Kind.isMergeableConst4()) { Str.push_back(','); Str.push_back('4'); } else if (Kind.isMergeableConst8()) { Str.push_back(','); Str.push_back('8'); } else if (Kind.isMergeableConst16()) { Str.push_back(','); Str.push_back('1'); Str.push_back('6'); } } static const char *getSectionPrefixForUniqueGlobal(SectionKind Kind) { if (Kind.isText()) return ".gnu.linkonce.t."; if (Kind.isReadOnly()) return ".gnu.linkonce.r."; if (Kind.isThreadData()) return ".gnu.linkonce.td."; if (Kind.isThreadBSS()) return ".gnu.linkonce.tb."; if (Kind.isBSS()) return ".gnu.linkonce.b."; if (Kind.isDataNoRel()) return ".gnu.linkonce.d."; if (Kind.isDataRelLocal()) return ".gnu.linkonce.d.rel.local."; if (Kind.isDataRel()) return ".gnu.linkonce.d.rel."; if (Kind.isReadOnlyWithRelLocal()) return ".gnu.linkonce.d.rel.ro.local."; assert(Kind.isReadOnlyWithRel() && "Unknown section kind"); return ".gnu.linkonce.d.rel.ro."; } const Section *TargetLoweringObjectFileELF:: SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, Mangler *Mang, const TargetMachine &TM) const { // If this global is linkonce/weak and the target handles this by emitting it // into a 'uniqued' section name, create and return the section now. if (Kind.isWeak()) { const char *Prefix = getSectionPrefixForUniqueGlobal(Kind); std::string Name = Mang->makeNameProper(GV->getNameStr()); return getOrCreateSection((Prefix+Name).c_str(), false, Kind.getKind()); } if (Kind.isText()) return TextSection; if (Kind.isMergeableCString()) { assert(CStringSection_ && "Should have string section prefix"); // We also need alignment here. // FIXME: this is getting the alignment of the character, not the // alignment of the global! unsigned Align = TM.getTargetData()->getPreferredAlignment(cast(GV)); std::string Name = CStringSection_->getName() + "1." + utostr(Align); return getOrCreateSection(Name.c_str(), false, SectionKind::MergeableCString); } if (Kind.isMergeableConst()) { if (Kind.isMergeableConst4()) return MergeableConst4Section; if (Kind.isMergeableConst8()) return MergeableConst8Section; if (Kind.isMergeableConst16()) return MergeableConst16Section; return ReadOnlySection; // .const } if (Kind.isReadOnly()) return ReadOnlySection; if (Kind.isThreadData()) return TLSDataSection; if (Kind.isThreadBSS()) return TLSBSSSection; if (Kind.isBSS()) return BSSSection_; if (Kind.isDataNoRel()) return DataSection; if (Kind.isDataRelLocal()) return DataRelLocalSection; if (Kind.isDataRel()) return DataRelSection; if (Kind.isReadOnlyWithRelLocal()) return DataRelROLocalSection; assert(Kind.isReadOnlyWithRel() && "Unknown section kind"); return DataRelROSection; } /// getSectionForMergeableConstant - Given a mergeable constant with the /// specified size and relocation information, return a section that it /// should be placed in. const Section *TargetLoweringObjectFileELF:: getSectionForMergeableConstant(SectionKind Kind) const { if (Kind.isMergeableConst4()) return MergeableConst4Section; if (Kind.isMergeableConst8()) return MergeableConst8Section; if (Kind.isMergeableConst16()) return MergeableConst16Section; if (Kind.isReadOnly()) return ReadOnlySection; if (Kind.isReadOnlyWithRelLocal()) return DataRelROLocalSection; assert(Kind.isReadOnlyWithRel() && "Unknown section kind"); return DataRelROSection; } //===----------------------------------------------------------------------===// // MachO //===----------------------------------------------------------------------===// TargetLoweringObjectFileMachO:: TargetLoweringObjectFileMachO(const TargetMachine &TM) { TextSection = getOrCreateSection("\t.text", true, SectionKind::Text); DataSection = getOrCreateSection("\t.data", true, SectionKind::DataRel); CStringSection_ = getOrCreateSection("\t.cstring", true, SectionKind::MergeableCString); FourByteConstantSection = getOrCreateSection("\t.literal4\n", true, SectionKind::MergeableConst4); EightByteConstantSection = getOrCreateSection("\t.literal8\n", true, SectionKind::MergeableConst8); // ld_classic doesn't support .literal16 in 32-bit mode, and ld64 falls back // to using it in -static mode. if (TM.getRelocationModel() != Reloc::Static && TM.getTargetData()->getPointerSize() == 32) SixteenByteConstantSection = getOrCreateSection("\t.literal16\n", true, SectionKind::MergeableConst16); else SixteenByteConstantSection = 0; ReadOnlySection = getOrCreateSection("\t.const", true, SectionKind::ReadOnly); TextCoalSection = getOrCreateSection("\t__TEXT,__textcoal_nt,coalesced,pure_instructions", false, SectionKind::Text); ConstTextCoalSection = getOrCreateSection("\t__TEXT,__const_coal,coalesced", false, SectionKind::Text); ConstDataCoalSection = getOrCreateSection("\t__DATA,__const_coal,coalesced", false, SectionKind::Text); ConstDataSection = getOrCreateSection("\t.const_data", true, SectionKind::ReadOnlyWithRel); DataCoalSection = getOrCreateSection("\t__DATA,__datacoal_nt,coalesced", false, SectionKind::DataRel); } const Section *TargetLoweringObjectFileMachO:: SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, Mangler *Mang, const TargetMachine &TM) const { assert(!Kind.isThreadLocal() && "Darwin doesn't support TLS"); if (Kind.isText()) return Kind.isWeak() ? TextCoalSection : TextSection; // If this is weak/linkonce, put this in a coalescable section, either in text // or data depending on if it is writable. if (Kind.isWeak()) { if (Kind.isReadOnly()) return ConstTextCoalSection; return DataCoalSection; } // FIXME: Alignment check should be handled by section classifier. if (Kind.isMergeableCString()) { Constant *C = cast(GV)->getInitializer(); const Type *Ty = cast(C->getType())->getElementType(); const TargetData &TD = *TM.getTargetData(); unsigned Size = TD.getTypeAllocSize(Ty); if (Size) { unsigned Align = TD.getPreferredAlignment(cast(GV)); if (Align <= 32) return CStringSection_; } return ReadOnlySection; } if (Kind.isMergeableConst()) { if (Kind.isMergeableConst4()) return FourByteConstantSection; if (Kind.isMergeableConst8()) return EightByteConstantSection; if (Kind.isMergeableConst16() && SixteenByteConstantSection) return SixteenByteConstantSection; return ReadOnlySection; // .const } // FIXME: ROData -> const in -static mode that is relocatable but they happen // by the static linker. Why not mergeable? if (Kind.isReadOnly()) return ReadOnlySection; // If this is marked const, put it into a const section. But if the dynamic // linker needs to write to it, put it in the data segment. if (Kind.isReadOnlyWithRel()) return ConstDataSection; // Otherwise, just drop the variable in the normal data section. return DataSection; } const Section * TargetLoweringObjectFileMachO:: getSectionForMergeableConstant(SectionKind Kind) const { // If this constant requires a relocation, we have to put it in the data // segment, not in the text segment. if (Kind.isDataRel()) return ConstDataSection; if (Kind.isMergeableConst4()) return FourByteConstantSection; if (Kind.isMergeableConst8()) return EightByteConstantSection; if (Kind.isMergeableConst16() && SixteenByteConstantSection) return SixteenByteConstantSection; return ReadOnlySection; // .const } //===----------------------------------------------------------------------===// // COFF //===----------------------------------------------------------------------===// TargetLoweringObjectFileCOFF::TargetLoweringObjectFileCOFF() { TextSection = getOrCreateSection("\t.text", true, SectionKind::Text); DataSection = getOrCreateSection("\t.data", true, SectionKind::DataRel); } void TargetLoweringObjectFileCOFF:: getSectionFlagsAsString(SectionKind Kind, SmallVectorImpl &Str) const { // FIXME: Inefficient. std::string Res = ",\""; if (Kind.isText()) Res += 'x'; if (Kind.isWriteable()) Res += 'w'; Res += "\""; Str.append(Res.begin(), Res.end()); } static const char *getCOFFSectionPrefixForUniqueGlobal(SectionKind Kind) { if (Kind.isText()) return ".text$linkonce"; if (Kind.isWriteable()) return ".data$linkonce"; return ".rdata$linkonce"; } const Section *TargetLoweringObjectFileCOFF:: SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, Mangler *Mang, const TargetMachine &TM) const { assert(!Kind.isThreadLocal() && "Doesn't support TLS"); // If this global is linkonce/weak and the target handles this by emitting it // into a 'uniqued' section name, create and return the section now. if (Kind.isWeak()) { const char *Prefix = getCOFFSectionPrefixForUniqueGlobal(Kind); // FIXME: Use mangler interface (PR4584). std::string Name = Prefix+GV->getNameStr(); return getOrCreateSection(Name.c_str(), false, Kind.getKind()); } if (Kind.isText()) return getTextSection(); if (Kind.isBSS()) if (const Section *S = BSSSection_) return S; if (Kind.isReadOnly() && ReadOnlySection != 0) return ReadOnlySection; return getDataSection(); }