llvm-6502/lib/Target/TargetLoweringObjectFile.cpp
Bill Wendling 5511ffd763 Here's fun! It turns out that these filter functions can be internal. If they're
internal, they shouldn't use the indirect pointer stuff. In the case of
throw_rethrow_test, it was marked as 'internal' and calculated its own offset to
its contents.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@82354 91177308-0d34-0410-b5e6-96231b3b80d8
2009-09-20 02:19:49 +00:00

1090 lines
41 KiB
C++

//===-- 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/Function.h"
#include "llvm/GlobalVariable.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Support/Mangler.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
using namespace llvm;
//===----------------------------------------------------------------------===//
// Generic Code
//===----------------------------------------------------------------------===//
TargetLoweringObjectFile::TargetLoweringObjectFile() : Ctx(0) {
TextSection = 0;
DataSection = 0;
BSSSection = 0;
ReadOnlySection = 0;
StaticCtorSection = 0;
StaticDtorSection = 0;
LSDASection = 0;
EHFrameSection = 0;
DwarfAbbrevSection = 0;
DwarfInfoSection = 0;
DwarfLineSection = 0;
DwarfFrameSection = 0;
DwarfPubNamesSection = 0;
DwarfPubTypesSection = 0;
DwarfDebugInlineSection = 0;
DwarfStrSection = 0;
DwarfLocSection = 0;
DwarfARangesSection = 0;
DwarfRangesSection = 0;
DwarfMacroInfoSection = 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;
}
/// IsNullTerminatedString - Return true if the specified constant (which is
/// known to have a type that is an array of 1/2/4 byte elements) ends with a
/// nul value and contains no other nuls in it.
static bool IsNullTerminatedString(const Constant *C) {
const ArrayType *ATy = cast<ArrayType>(C->getType());
// First check: is we have constant array of i8 terminated with zero
if (const ConstantArray *CVA = dyn_cast<ConstantArray>(C)) {
if (ATy->getNumElements() == 0) return false;
ConstantInt *Null =
dyn_cast<ConstantInt>(CVA->getOperand(ATy->getNumElements()-1));
if (Null == 0 || Null->getZExtValue() != 0)
return false; // Not null terminated.
// Verify that the null doesn't occur anywhere else in the string.
for (unsigned i = 0, e = ATy->getNumElements()-1; i != e; ++i)
// Reject constantexpr elements etc.
if (!isa<ConstantInt>(CVA->getOperand(i)) ||
CVA->getOperand(i) == Null)
return false;
return true;
}
// Another possibility: [1 x i8] zeroinitializer
if (isa<ConstantAggregateZero>(C))
return ATy->getNumElements() == 1;
return false;
}
/// getKindForGlobal - This is a top-level target-independent classifier for
/// a global variable. Given an global variable and information from TM, it
/// classifies the global in a variety of ways that make various target
/// implementations simpler. The target implementation is free to ignore this
/// extra info of course.
SectionKind TargetLoweringObjectFile::getKindForGlobal(const GlobalValue *GV,
const TargetMachine &TM){
assert(!GV->isDeclaration() && !GV->hasAvailableExternallyLinkage() &&
"Can only be used for global definitions");
Reloc::Model ReloModel = TM.getRelocationModel();
// Early exit - functions should be always in text sections.
const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
if (GVar == 0)
return SectionKind::getText();
// Handle thread-local data first.
if (GVar->isThreadLocal()) {
if (isSuitableForBSS(GVar))
return SectionKind::getThreadBSS();
return SectionKind::getThreadData();
}
// Variable can be easily put to BSS section.
if (isSuitableForBSS(GVar))
return SectionKind::getBSS();
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 of the right width.
if (const ArrayType *ATy = dyn_cast<ArrayType>(C->getType())) {
if (const IntegerType *ITy =
dyn_cast<IntegerType>(ATy->getElementType())) {
if ((ITy->getBitWidth() == 8 || ITy->getBitWidth() == 16 ||
ITy->getBitWidth() == 32) &&
IsNullTerminatedString(C)) {
if (ITy->getBitWidth() == 8)
return SectionKind::getMergeable1ByteCString();
if (ITy->getBitWidth() == 16)
return SectionKind::getMergeable2ByteCString();
assert(ITy->getBitWidth() == 32 && "Unknown width");
return SectionKind::getMergeable4ByteCString();
}
}
}
// 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::getMergeableConst4();
case 8: return SectionKind::getMergeableConst8();
case 16: return SectionKind::getMergeableConst16();
default: return SectionKind::getMergeableConst();
}
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::getReadOnly();
// Otherwise, the dynamic linker needs to fix it up, put it in the
// writable data.rel.local section.
return SectionKind::getReadOnlyWithRelLocal();
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::getReadOnly();
// Otherwise, the dynamic linker needs to fix it up, put it in the
// writable data.rel section.
return SectionKind::getReadOnlyWithRel();
}
}
// 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::getDataNoRel();
switch (C->getRelocationInfo()) {
default: llvm_unreachable("unknown relocation info kind");
case Constant::NoRelocation:
return SectionKind::getDataNoRel();
case Constant::LocalRelocation:
return SectionKind::getDataRelLocal();
case Constant::GlobalRelocations:
return SectionKind::getDataRel();
}
}
/// 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 MCSection *TargetLoweringObjectFile::
SectionForGlobal(const GlobalValue *GV, SectionKind Kind, Mangler *Mang,
const TargetMachine &TM) const {
// Select section name.
if (GV->hasSection())
return getExplicitSectionGlobal(GV, Kind, Mang, TM);
// 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 MCSection *
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();
}
/// getSectionForConstant - Given a mergable constant with the
/// specified size and relocation information, return a section that it
/// should be placed in.
const MCSection *
TargetLoweringObjectFile::getSectionForConstant(SectionKind Kind) const {
if (Kind.isReadOnly() && ReadOnlySection != 0)
return ReadOnlySection;
return DataSection;
}
/// getSymbolForDwarfGlobalReference - Return an MCExpr to use for a
/// pc-relative reference to the specified global variable from exception
/// handling information. In addition to the symbol, this returns
/// by-reference:
///
/// IsIndirect - True if the returned symbol is actually a stub that contains
/// the address of the symbol, false if the symbol is the global itself.
///
/// IsPCRel - True if the symbol reference is already pc-relative, false if
/// the caller needs to subtract off the address of the reference from the
/// symbol.
///
const MCExpr *TargetLoweringObjectFile::
getSymbolForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang,
MachineModuleInfo *MMI,
bool &IsIndirect, bool &IsPCRel) const {
// The generic implementation of this just returns a direct reference to the
// symbol.
IsIndirect = false;
IsPCRel = false;
SmallString<128> Name;
Mang->getNameWithPrefix(Name, GV, false);
return MCSymbolRefExpr::Create(Name.str(), getContext());
}
//===----------------------------------------------------------------------===//
// ELF
//===----------------------------------------------------------------------===//
typedef StringMap<const MCSectionELF*> ELFUniqueMapTy;
TargetLoweringObjectFileELF::~TargetLoweringObjectFileELF() {
// If we have the section uniquing map, free it.
delete (ELFUniqueMapTy*)UniquingMap;
}
const MCSection *TargetLoweringObjectFileELF::
getELFSection(StringRef Section, unsigned Type, unsigned Flags,
SectionKind Kind, bool IsExplicit) const {
if (UniquingMap == 0)
UniquingMap = new ELFUniqueMapTy();
ELFUniqueMapTy &Map = *(ELFUniqueMapTy*)UniquingMap;
// Do the lookup, if we have a hit, return it.
const MCSectionELF *&Entry = Map[Section];
if (Entry) return Entry;
return Entry = MCSectionELF::Create(Section, Type, Flags, Kind, IsExplicit,
getContext());
}
void TargetLoweringObjectFileELF::Initialize(MCContext &Ctx,
const TargetMachine &TM) {
if (UniquingMap != 0)
((ELFUniqueMapTy*)UniquingMap)->clear();
TargetLoweringObjectFile::Initialize(Ctx, TM);
BSSSection =
getELFSection(".bss", MCSectionELF::SHT_NOBITS,
MCSectionELF::SHF_WRITE | MCSectionELF::SHF_ALLOC,
SectionKind::getBSS());
TextSection =
getELFSection(".text", MCSectionELF::SHT_PROGBITS,
MCSectionELF::SHF_EXECINSTR | MCSectionELF::SHF_ALLOC,
SectionKind::getText());
DataSection =
getELFSection(".data", MCSectionELF::SHT_PROGBITS,
MCSectionELF::SHF_WRITE | MCSectionELF::SHF_ALLOC,
SectionKind::getDataRel());
ReadOnlySection =
getELFSection(".rodata", MCSectionELF::SHT_PROGBITS,
MCSectionELF::SHF_ALLOC,
SectionKind::getReadOnly());
TLSDataSection =
getELFSection(".tdata", MCSectionELF::SHT_PROGBITS,
MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_TLS |
MCSectionELF::SHF_WRITE, SectionKind::getThreadData());
TLSBSSSection =
getELFSection(".tbss", MCSectionELF::SHT_NOBITS,
MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_TLS |
MCSectionELF::SHF_WRITE, SectionKind::getThreadBSS());
DataRelSection =
getELFSection(".data.rel", MCSectionELF::SHT_PROGBITS,
MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE,
SectionKind::getDataRel());
DataRelLocalSection =
getELFSection(".data.rel.local", MCSectionELF::SHT_PROGBITS,
MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE,
SectionKind::getDataRelLocal());
DataRelROSection =
getELFSection(".data.rel.ro", MCSectionELF::SHT_PROGBITS,
MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE,
SectionKind::getReadOnlyWithRel());
DataRelROLocalSection =
getELFSection(".data.rel.ro.local", MCSectionELF::SHT_PROGBITS,
MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE,
SectionKind::getReadOnlyWithRelLocal());
MergeableConst4Section =
getELFSection(".rodata.cst4", MCSectionELF::SHT_PROGBITS,
MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_MERGE,
SectionKind::getMergeableConst4());
MergeableConst8Section =
getELFSection(".rodata.cst8", MCSectionELF::SHT_PROGBITS,
MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_MERGE,
SectionKind::getMergeableConst8());
MergeableConst16Section =
getELFSection(".rodata.cst16", MCSectionELF::SHT_PROGBITS,
MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_MERGE,
SectionKind::getMergeableConst16());
StaticCtorSection =
getELFSection(".ctors", MCSectionELF::SHT_PROGBITS,
MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE,
SectionKind::getDataRel());
StaticDtorSection =
getELFSection(".dtors", MCSectionELF::SHT_PROGBITS,
MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE,
SectionKind::getDataRel());
// Exception Handling Sections.
// FIXME: We're emitting LSDA info into a readonly section on ELF, even though
// it contains relocatable pointers. In PIC mode, this is probably a big
// runtime hit for C++ apps. Either the contents of the LSDA need to be
// adjusted or this should be a data section.
LSDASection =
getELFSection(".gcc_except_table", MCSectionELF::SHT_PROGBITS,
MCSectionELF::SHF_ALLOC, SectionKind::getReadOnly());
EHFrameSection =
getELFSection(".eh_frame", MCSectionELF::SHT_PROGBITS,
MCSectionELF::SHF_ALLOC | MCSectionELF::SHF_WRITE,
SectionKind::getDataRel());
// Debug Info Sections.
DwarfAbbrevSection =
getELFSection(".debug_abbrev", MCSectionELF::SHT_PROGBITS, 0,
SectionKind::getMetadata());
DwarfInfoSection =
getELFSection(".debug_info", MCSectionELF::SHT_PROGBITS, 0,
SectionKind::getMetadata());
DwarfLineSection =
getELFSection(".debug_line", MCSectionELF::SHT_PROGBITS, 0,
SectionKind::getMetadata());
DwarfFrameSection =
getELFSection(".debug_frame", MCSectionELF::SHT_PROGBITS, 0,
SectionKind::getMetadata());
DwarfPubNamesSection =
getELFSection(".debug_pubnames", MCSectionELF::SHT_PROGBITS, 0,
SectionKind::getMetadata());
DwarfPubTypesSection =
getELFSection(".debug_pubtypes", MCSectionELF::SHT_PROGBITS, 0,
SectionKind::getMetadata());
DwarfStrSection =
getELFSection(".debug_str", MCSectionELF::SHT_PROGBITS, 0,
SectionKind::getMetadata());
DwarfLocSection =
getELFSection(".debug_loc", MCSectionELF::SHT_PROGBITS, 0,
SectionKind::getMetadata());
DwarfARangesSection =
getELFSection(".debug_aranges", MCSectionELF::SHT_PROGBITS, 0,
SectionKind::getMetadata());
DwarfRangesSection =
getELFSection(".debug_ranges", MCSectionELF::SHT_PROGBITS, 0,
SectionKind::getMetadata());
DwarfMacroInfoSection =
getELFSection(".debug_macinfo", MCSectionELF::SHT_PROGBITS, 0,
SectionKind::getMetadata());
}
static SectionKind
getELFKindForNamedSection(const char *Name, SectionKind K) {
if (Name[0] != '.') return K;
// Some lame default implementation based on some magic section names.
if (strcmp(Name, ".bss") == 0 ||
strncmp(Name, ".bss.", 5) == 0 ||
strncmp(Name, ".gnu.linkonce.b.", 16) == 0 ||
strncmp(Name, ".llvm.linkonce.b.", 17) == 0 ||
strcmp(Name, ".sbss") == 0 ||
strncmp(Name, ".sbss.", 6) == 0 ||
strncmp(Name, ".gnu.linkonce.sb.", 17) == 0 ||
strncmp(Name, ".llvm.linkonce.sb.", 18) == 0)
return SectionKind::getBSS();
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::getThreadData();
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::getThreadBSS();
return K;
}
static unsigned
getELFSectionType(const char *Name, SectionKind K) {
if (strcmp(Name, ".init_array") == 0)
return MCSectionELF::SHT_INIT_ARRAY;
if (strcmp(Name, ".fini_array") == 0)
return MCSectionELF::SHT_FINI_ARRAY;
if (strcmp(Name, ".preinit_array") == 0)
return MCSectionELF::SHT_PREINIT_ARRAY;
if (K.isBSS() || K.isThreadBSS())
return MCSectionELF::SHT_NOBITS;
return MCSectionELF::SHT_PROGBITS;
}
static unsigned
getELFSectionFlags(SectionKind K) {
unsigned Flags = 0;
if (!K.isMetadata())
Flags |= MCSectionELF::SHF_ALLOC;
if (K.isText())
Flags |= MCSectionELF::SHF_EXECINSTR;
if (K.isWriteable())
Flags |= MCSectionELF::SHF_WRITE;
if (K.isThreadLocal())
Flags |= MCSectionELF::SHF_TLS;
// K.isMergeableConst() is left out to honour PR4650
if (K.isMergeableCString() || K.isMergeableConst4() ||
K.isMergeableConst8() || K.isMergeableConst16())
Flags |= MCSectionELF::SHF_MERGE;
if (K.isMergeableCString())
Flags |= MCSectionELF::SHF_STRINGS;
return Flags;
}
const MCSection *TargetLoweringObjectFileELF::
getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind,
Mangler *Mang, const TargetMachine &TM) const {
const char *SectionName = GV->getSection().c_str();
// Infer section flags from the section name if we can.
Kind = getELFKindForNamedSection(SectionName, Kind);
return getELFSection(SectionName,
getELFSectionType(SectionName, Kind),
getELFSectionFlags(Kind), Kind, true);
}
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 MCSection *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 (GV->isWeakForLinker()) {
const char *Prefix = getSectionPrefixForUniqueGlobal(Kind);
std::string Name = Mang->makeNameProper(GV->getNameStr());
return getELFSection((Prefix+Name).c_str(),
getELFSectionType((Prefix+Name).c_str(), Kind),
getELFSectionFlags(Kind),
Kind);
}
if (Kind.isText()) return TextSection;
if (Kind.isMergeable1ByteCString() ||
Kind.isMergeable2ByteCString() ||
Kind.isMergeable4ByteCString()) {
// 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<GlobalVariable>(GV));
const char *SizeSpec = ".rodata.str1.";
if (Kind.isMergeable2ByteCString())
SizeSpec = ".rodata.str2.";
else if (Kind.isMergeable4ByteCString())
SizeSpec = ".rodata.str4.";
else
assert(Kind.isMergeable1ByteCString() && "unknown string width");
std::string Name = SizeSpec + utostr(Align);
return getELFSection(Name.c_str(), MCSectionELF::SHT_PROGBITS,
MCSectionELF::SHF_ALLOC |
MCSectionELF::SHF_MERGE |
MCSectionELF::SHF_STRINGS,
Kind);
}
if (Kind.isMergeableConst()) {
if (Kind.isMergeableConst4() && MergeableConst4Section)
return MergeableConst4Section;
if (Kind.isMergeableConst8() && MergeableConst8Section)
return MergeableConst8Section;
if (Kind.isMergeableConst16() && MergeableConst16Section)
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;
}
/// getSectionForConstant - Given a mergeable constant with the
/// specified size and relocation information, return a section that it
/// should be placed in.
const MCSection *TargetLoweringObjectFileELF::
getSectionForConstant(SectionKind Kind) const {
if (Kind.isMergeableConst4() && MergeableConst4Section)
return MergeableConst4Section;
if (Kind.isMergeableConst8() && MergeableConst8Section)
return MergeableConst8Section;
if (Kind.isMergeableConst16() && MergeableConst16Section)
return MergeableConst16Section;
if (Kind.isReadOnly())
return ReadOnlySection;
if (Kind.isReadOnlyWithRelLocal()) return DataRelROLocalSection;
assert(Kind.isReadOnlyWithRel() && "Unknown section kind");
return DataRelROSection;
}
//===----------------------------------------------------------------------===//
// MachO
//===----------------------------------------------------------------------===//
typedef StringMap<const MCSectionMachO*> MachOUniqueMapTy;
TargetLoweringObjectFileMachO::~TargetLoweringObjectFileMachO() {
// If we have the MachO uniquing map, free it.
delete (MachOUniqueMapTy*)UniquingMap;
}
const MCSectionMachO *TargetLoweringObjectFileMachO::
getMachOSection(const StringRef &Segment, const StringRef &Section,
unsigned TypeAndAttributes,
unsigned Reserved2, SectionKind Kind) const {
// We unique sections by their segment/section pair. The returned section
// may not have the same flags as the requested section, if so this should be
// diagnosed by the client as an error.
// Create the map if it doesn't already exist.
if (UniquingMap == 0)
UniquingMap = new MachOUniqueMapTy();
MachOUniqueMapTy &Map = *(MachOUniqueMapTy*)UniquingMap;
// Form the name to look up.
SmallString<64> Name;
Name += Segment;
Name.push_back(',');
Name += Section;
// Do the lookup, if we have a hit, return it.
const MCSectionMachO *&Entry = Map[Name.str()];
if (Entry) return Entry;
// Otherwise, return a new section.
return Entry = MCSectionMachO::Create(Segment, Section, TypeAndAttributes,
Reserved2, Kind, getContext());
}
void TargetLoweringObjectFileMachO::Initialize(MCContext &Ctx,
const TargetMachine &TM) {
if (UniquingMap != 0)
((MachOUniqueMapTy*)UniquingMap)->clear();
TargetLoweringObjectFile::Initialize(Ctx, TM);
TextSection // .text
= getMachOSection("__TEXT", "__text",
MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
SectionKind::getText());
DataSection // .data
= getMachOSection("__DATA", "__data", 0, SectionKind::getDataRel());
CStringSection // .cstring
= getMachOSection("__TEXT", "__cstring", MCSectionMachO::S_CSTRING_LITERALS,
SectionKind::getMergeable1ByteCString());
UStringSection
= getMachOSection("__TEXT","__ustring", 0,
SectionKind::getMergeable2ByteCString());
FourByteConstantSection // .literal4
= getMachOSection("__TEXT", "__literal4", MCSectionMachO::S_4BYTE_LITERALS,
SectionKind::getMergeableConst4());
EightByteConstantSection // .literal8
= getMachOSection("__TEXT", "__literal8", MCSectionMachO::S_8BYTE_LITERALS,
SectionKind::getMergeableConst8());
// ld_classic doesn't support .literal16 in 32-bit mode, and ld64 falls back
// to using it in -static mode.
SixteenByteConstantSection = 0;
if (TM.getRelocationModel() != Reloc::Static &&
TM.getTargetData()->getPointerSize() == 32)
SixteenByteConstantSection = // .literal16
getMachOSection("__TEXT", "__literal16",MCSectionMachO::S_16BYTE_LITERALS,
SectionKind::getMergeableConst16());
ReadOnlySection // .const
= getMachOSection("__TEXT", "__const", 0, SectionKind::getReadOnly());
TextCoalSection
= getMachOSection("__TEXT", "__textcoal_nt",
MCSectionMachO::S_COALESCED |
MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS,
SectionKind::getText());
ConstTextCoalSection
= getMachOSection("__TEXT", "__const_coal", MCSectionMachO::S_COALESCED,
SectionKind::getText());
ConstDataCoalSection
= getMachOSection("__DATA","__const_coal", MCSectionMachO::S_COALESCED,
SectionKind::getText());
ConstDataSection // .const_data
= getMachOSection("__DATA", "__const", 0,
SectionKind::getReadOnlyWithRel());
DataCoalSection
= getMachOSection("__DATA","__datacoal_nt", MCSectionMachO::S_COALESCED,
SectionKind::getDataRel());
LazySymbolPointerSection
= getMachOSection("__DATA", "__la_symbol_ptr",
MCSectionMachO::S_LAZY_SYMBOL_POINTERS,
SectionKind::getMetadata());
NonLazySymbolPointerSection
= getMachOSection("__DATA", "__nl_symbol_ptr",
MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS,
SectionKind::getMetadata());
if (TM.getRelocationModel() == Reloc::Static) {
StaticCtorSection
= getMachOSection("__TEXT", "__constructor", 0,SectionKind::getDataRel());
StaticDtorSection
= getMachOSection("__TEXT", "__destructor", 0, SectionKind::getDataRel());
} else {
StaticCtorSection
= getMachOSection("__DATA", "__mod_init_func",
MCSectionMachO::S_MOD_INIT_FUNC_POINTERS,
SectionKind::getDataRel());
StaticDtorSection
= getMachOSection("__DATA", "__mod_term_func",
MCSectionMachO::S_MOD_TERM_FUNC_POINTERS,
SectionKind::getDataRel());
}
// Exception Handling.
LSDASection = getMachOSection("__TEXT", "__gcc_except_tab", 0,
SectionKind::getReadOnly());
EHFrameSection =
getMachOSection("__TEXT", "__eh_frame",
MCSectionMachO::S_COALESCED |
MCSectionMachO::S_ATTR_NO_TOC |
MCSectionMachO::S_ATTR_STRIP_STATIC_SYMS |
MCSectionMachO::S_ATTR_LIVE_SUPPORT,
SectionKind::getReadOnly());
// Debug Information.
DwarfAbbrevSection =
getMachOSection("__DWARF", "__debug_abbrev", MCSectionMachO::S_ATTR_DEBUG,
SectionKind::getMetadata());
DwarfInfoSection =
getMachOSection("__DWARF", "__debug_info", MCSectionMachO::S_ATTR_DEBUG,
SectionKind::getMetadata());
DwarfLineSection =
getMachOSection("__DWARF", "__debug_line", MCSectionMachO::S_ATTR_DEBUG,
SectionKind::getMetadata());
DwarfFrameSection =
getMachOSection("__DWARF", "__debug_frame", MCSectionMachO::S_ATTR_DEBUG,
SectionKind::getMetadata());
DwarfPubNamesSection =
getMachOSection("__DWARF", "__debug_pubnames", MCSectionMachO::S_ATTR_DEBUG,
SectionKind::getMetadata());
DwarfPubTypesSection =
getMachOSection("__DWARF", "__debug_pubtypes", MCSectionMachO::S_ATTR_DEBUG,
SectionKind::getMetadata());
DwarfStrSection =
getMachOSection("__DWARF", "__debug_str", MCSectionMachO::S_ATTR_DEBUG,
SectionKind::getMetadata());
DwarfLocSection =
getMachOSection("__DWARF", "__debug_loc", MCSectionMachO::S_ATTR_DEBUG,
SectionKind::getMetadata());
DwarfARangesSection =
getMachOSection("__DWARF", "__debug_aranges", MCSectionMachO::S_ATTR_DEBUG,
SectionKind::getMetadata());
DwarfRangesSection =
getMachOSection("__DWARF", "__debug_ranges", MCSectionMachO::S_ATTR_DEBUG,
SectionKind::getMetadata());
DwarfMacroInfoSection =
getMachOSection("__DWARF", "__debug_macinfo", MCSectionMachO::S_ATTR_DEBUG,
SectionKind::getMetadata());
DwarfDebugInlineSection =
getMachOSection("__DWARF", "__debug_inlined", MCSectionMachO::S_ATTR_DEBUG,
SectionKind::getMetadata());
}
const MCSection *TargetLoweringObjectFileMachO::
getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind,
Mangler *Mang, const TargetMachine &TM) const {
// Parse the section specifier and create it if valid.
StringRef Segment, Section;
unsigned TAA, StubSize;
std::string ErrorCode =
MCSectionMachO::ParseSectionSpecifier(GV->getSection(), Segment, Section,
TAA, StubSize);
if (!ErrorCode.empty()) {
// If invalid, report the error with llvm_report_error.
llvm_report_error("Global variable '" + GV->getNameStr() +
"' has an invalid section specifier '" + GV->getSection()+
"': " + ErrorCode + ".");
// Fall back to dropping it into the data section.
return DataSection;
}
// Get the section.
const MCSectionMachO *S =
getMachOSection(Segment, Section, TAA, StubSize, Kind);
// Okay, now that we got the section, verify that the TAA & StubSize agree.
// If the user declared multiple globals with different section flags, we need
// to reject it here.
if (S->getTypeAndAttributes() != TAA || S->getStubSize() != StubSize) {
// If invalid, report the error with llvm_report_error.
llvm_report_error("Global variable '" + GV->getNameStr() +
"' section type or attributes does not match previous"
" section specifier");
}
return S;
}
const MCSection *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 GV->isWeakForLinker() ? 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 (GV->isWeakForLinker()) {
if (Kind.isReadOnly())
return ConstTextCoalSection;
return DataCoalSection;
}
// FIXME: Alignment check should be handled by section classifier.
if (Kind.isMergeable1ByteCString() ||
Kind.isMergeable2ByteCString()) {
if (TM.getTargetData()->getPreferredAlignment(
cast<GlobalVariable>(GV)) < 32) {
if (Kind.isMergeable1ByteCString())
return CStringSection;
assert(Kind.isMergeable2ByteCString());
return UStringSection;
}
}
if (Kind.isMergeableConst()) {
if (Kind.isMergeableConst4())
return FourByteConstantSection;
if (Kind.isMergeableConst8())
return EightByteConstantSection;
if (Kind.isMergeableConst16() && SixteenByteConstantSection)
return SixteenByteConstantSection;
}
// Otherwise, if it is readonly, but not something we can specially optimize,
// just drop it in .const.
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 MCSection *
TargetLoweringObjectFileMachO::getSectionForConstant(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
}
/// shouldEmitUsedDirectiveFor - This hook allows targets to selectively decide
/// not to emit the UsedDirective for some symbols in llvm.used.
// FIXME: REMOVE this (rdar://7071300)
bool TargetLoweringObjectFileMachO::
shouldEmitUsedDirectiveFor(const GlobalValue *GV, Mangler *Mang) const {
/// On Darwin, internally linked data beginning with "L" or "l" does not have
/// the directive emitted (this occurs in ObjC metadata).
if (!GV) return false;
// Check whether the mangled name has the "Private" or "LinkerPrivate" prefix.
if (GV->hasLocalLinkage() && !isa<Function>(GV)) {
// FIXME: ObjC metadata is currently emitted as internal symbols that have
// \1L and \0l prefixes on them. Fix them to be Private/LinkerPrivate and
// this horrible hack can go away.
const std::string &Name = Mang->getMangledName(GV);
if (Name[0] == 'L' || Name[0] == 'l')
return false;
}
return true;
}
const MCExpr *TargetLoweringObjectFileMachO::
getSymbolForDwarfGlobalReference(const GlobalValue *GV, Mangler *Mang,
MachineModuleInfo *MMI,
bool &IsIndirect, bool &IsPCRel) const {
// The mach-o version of this method defaults to returning a stub reference.
IsIndirect = true;
IsPCRel = false;
SmallString<128> Name;
Mang->getNameWithPrefix(Name, GV, true);
Name += "$non_lazy_ptr";
return MCSymbolRefExpr::Create(Name.str(), getContext());
}
//===----------------------------------------------------------------------===//
// COFF
//===----------------------------------------------------------------------===//
typedef StringMap<const MCSectionCOFF*> COFFUniqueMapTy;
TargetLoweringObjectFileCOFF::~TargetLoweringObjectFileCOFF() {
delete (COFFUniqueMapTy*)UniquingMap;
}
const MCSection *TargetLoweringObjectFileCOFF::
getCOFFSection(const char *Name, bool isDirective, SectionKind Kind) const {
// Create the map if it doesn't already exist.
if (UniquingMap == 0)
UniquingMap = new MachOUniqueMapTy();
COFFUniqueMapTy &Map = *(COFFUniqueMapTy*)UniquingMap;
// Do the lookup, if we have a hit, return it.
const MCSectionCOFF *&Entry = Map[Name];
if (Entry) return Entry;
return Entry = MCSectionCOFF::Create(Name, isDirective, Kind, getContext());
}
void TargetLoweringObjectFileCOFF::Initialize(MCContext &Ctx,
const TargetMachine &TM) {
if (UniquingMap != 0)
((COFFUniqueMapTy*)UniquingMap)->clear();
TargetLoweringObjectFile::Initialize(Ctx, TM);
TextSection = getCOFFSection("\t.text", true, SectionKind::getText());
DataSection = getCOFFSection("\t.data", true, SectionKind::getDataRel());
StaticCtorSection =
getCOFFSection(".ctors", false, SectionKind::getDataRel());
StaticDtorSection =
getCOFFSection(".dtors", false, SectionKind::getDataRel());
// FIXME: We're emitting LSDA info into a readonly section on COFF, even
// though it contains relocatable pointers. In PIC mode, this is probably a
// big runtime hit for C++ apps. Either the contents of the LSDA need to be
// adjusted or this should be a data section.
LSDASection =
getCOFFSection(".gcc_except_table", false, SectionKind::getReadOnly());
EHFrameSection =
getCOFFSection(".eh_frame", false, SectionKind::getDataRel());
// Debug info.
// FIXME: Don't use 'directive' mode here.
DwarfAbbrevSection =
getCOFFSection("\t.section\t.debug_abbrev,\"dr\"",
true, SectionKind::getMetadata());
DwarfInfoSection =
getCOFFSection("\t.section\t.debug_info,\"dr\"",
true, SectionKind::getMetadata());
DwarfLineSection =
getCOFFSection("\t.section\t.debug_line,\"dr\"",
true, SectionKind::getMetadata());
DwarfFrameSection =
getCOFFSection("\t.section\t.debug_frame,\"dr\"",
true, SectionKind::getMetadata());
DwarfPubNamesSection =
getCOFFSection("\t.section\t.debug_pubnames,\"dr\"",
true, SectionKind::getMetadata());
DwarfPubTypesSection =
getCOFFSection("\t.section\t.debug_pubtypes,\"dr\"",
true, SectionKind::getMetadata());
DwarfStrSection =
getCOFFSection("\t.section\t.debug_str,\"dr\"",
true, SectionKind::getMetadata());
DwarfLocSection =
getCOFFSection("\t.section\t.debug_loc,\"dr\"",
true, SectionKind::getMetadata());
DwarfARangesSection =
getCOFFSection("\t.section\t.debug_aranges,\"dr\"",
true, SectionKind::getMetadata());
DwarfRangesSection =
getCOFFSection("\t.section\t.debug_ranges,\"dr\"",
true, SectionKind::getMetadata());
DwarfMacroInfoSection =
getCOFFSection("\t.section\t.debug_macinfo,\"dr\"",
true, SectionKind::getMetadata());
}
const MCSection *TargetLoweringObjectFileCOFF::
getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind,
Mangler *Mang, const TargetMachine &TM) const {
return getCOFFSection(GV->getSection().c_str(), false, Kind);
}
static const char *getCOFFSectionPrefixForUniqueGlobal(SectionKind Kind) {
if (Kind.isText())
return ".text$linkonce";
if (Kind.isWriteable())
return ".data$linkonce";
return ".rdata$linkonce";
}
const MCSection *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 (GV->isWeakForLinker()) {
const char *Prefix = getCOFFSectionPrefixForUniqueGlobal(Kind);
std::string Name = Mang->makeNameProper(GV->getNameStr());
return getCOFFSection((Prefix+Name).c_str(), false, Kind);
}
if (Kind.isText())
return getTextSection();
return getDataSection();
}