llvm-project/llvm/lib/CodeGen/TargetLoweringObjectFileImp...

897 lines
32 KiB
C++

//===-- llvm/CodeGen/TargetLoweringObjectFileImpl.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/CodeGen/TargetLoweringObjectFileImpl.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Triple.h"
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCSectionCOFF.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetMachine.h"
using namespace llvm;
using namespace dwarf;
//===----------------------------------------------------------------------===//
// ELF
//===----------------------------------------------------------------------===//
MCSymbol *TargetLoweringObjectFileELF::getCFIPersonalitySymbol(
const GlobalValue *GV, Mangler &Mang, const TargetMachine &TM,
MachineModuleInfo *MMI) const {
unsigned Encoding = getPersonalityEncoding();
switch (Encoding & 0x70) {
default:
report_fatal_error("We do not support this DWARF encoding yet!");
case dwarf::DW_EH_PE_absptr:
return TM.getSymbol(GV, Mang);
case dwarf::DW_EH_PE_pcrel: {
return getContext().GetOrCreateSymbol(StringRef("DW.ref.") +
TM.getSymbol(GV, Mang)->getName());
}
}
}
void TargetLoweringObjectFileELF::emitPersonalityValue(MCStreamer &Streamer,
const TargetMachine &TM,
const MCSymbol *Sym) const {
SmallString<64> NameData("DW.ref.");
NameData += Sym->getName();
MCSymbol *Label = getContext().GetOrCreateSymbol(NameData);
Streamer.EmitSymbolAttribute(Label, MCSA_Hidden);
Streamer.EmitSymbolAttribute(Label, MCSA_Weak);
StringRef Prefix = ".data.";
NameData.insert(NameData.begin(), Prefix.begin(), Prefix.end());
unsigned Flags = ELF::SHF_ALLOC | ELF::SHF_WRITE | ELF::SHF_GROUP;
const MCSection *Sec = getContext().getELFSection(NameData,
ELF::SHT_PROGBITS,
Flags,
SectionKind::getDataRel(),
0, Label->getName());
unsigned Size = TM.getDataLayout()->getPointerSize();
Streamer.SwitchSection(Sec);
Streamer.EmitValueToAlignment(TM.getDataLayout()->getPointerABIAlignment());
Streamer.EmitSymbolAttribute(Label, MCSA_ELF_TypeObject);
const MCExpr *E = MCConstantExpr::Create(Size, getContext());
Streamer.EmitELFSize(Label, E);
Streamer.EmitLabel(Label);
Streamer.EmitSymbolValue(Sym, Size);
}
const MCExpr *TargetLoweringObjectFileELF::getTTypeGlobalReference(
const GlobalValue *GV, unsigned Encoding, Mangler &Mang,
const TargetMachine &TM, MachineModuleInfo *MMI,
MCStreamer &Streamer) const {
if (Encoding & dwarf::DW_EH_PE_indirect) {
MachineModuleInfoELF &ELFMMI = MMI->getObjFileInfo<MachineModuleInfoELF>();
MCSymbol *SSym = getSymbolWithGlobalValueBase(GV, ".DW.stub", Mang, TM);
// Add information about the stub reference to ELFMMI so that the stub
// gets emitted by the asmprinter.
MachineModuleInfoImpl::StubValueTy &StubSym = ELFMMI.getGVStubEntry(SSym);
if (!StubSym.getPointer()) {
MCSymbol *Sym = TM.getSymbol(GV, Mang);
StubSym = MachineModuleInfoImpl::StubValueTy(Sym, !GV->hasLocalLinkage());
}
return TargetLoweringObjectFile::
getTTypeReference(MCSymbolRefExpr::Create(SSym, getContext()),
Encoding & ~dwarf::DW_EH_PE_indirect, Streamer);
}
return TargetLoweringObjectFile::
getTTypeGlobalReference(GV, Encoding, Mang, TM, MMI, Streamer);
}
static SectionKind
getELFKindForNamedSection(StringRef Name, SectionKind K) {
// N.B.: The defaults used in here are no the same ones used in MC.
// We follow gcc, MC follows gas. For example, given ".section .eh_frame",
// both gas and MC will produce a section with no flags. Given
// section(".eh_frame") gcc will produce:
//
// .section .eh_frame,"a",@progbits
if (Name.empty() || Name[0] != '.') return K;
// Some lame default implementation based on some magic section names.
if (Name == ".bss" ||
Name.startswith(".bss.") ||
Name.startswith(".gnu.linkonce.b.") ||
Name.startswith(".llvm.linkonce.b.") ||
Name == ".sbss" ||
Name.startswith(".sbss.") ||
Name.startswith(".gnu.linkonce.sb.") ||
Name.startswith(".llvm.linkonce.sb."))
return SectionKind::getBSS();
if (Name == ".tdata" ||
Name.startswith(".tdata.") ||
Name.startswith(".gnu.linkonce.td.") ||
Name.startswith(".llvm.linkonce.td."))
return SectionKind::getThreadData();
if (Name == ".tbss" ||
Name.startswith(".tbss.") ||
Name.startswith(".gnu.linkonce.tb.") ||
Name.startswith(".llvm.linkonce.tb."))
return SectionKind::getThreadBSS();
return K;
}
static unsigned getELFSectionType(StringRef Name, SectionKind K) {
if (Name == ".init_array")
return ELF::SHT_INIT_ARRAY;
if (Name == ".fini_array")
return ELF::SHT_FINI_ARRAY;
if (Name == ".preinit_array")
return ELF::SHT_PREINIT_ARRAY;
if (K.isBSS() || K.isThreadBSS())
return ELF::SHT_NOBITS;
return ELF::SHT_PROGBITS;
}
static unsigned
getELFSectionFlags(SectionKind K) {
unsigned Flags = 0;
if (!K.isMetadata())
Flags |= ELF::SHF_ALLOC;
if (K.isText())
Flags |= ELF::SHF_EXECINSTR;
if (K.isWriteable())
Flags |= ELF::SHF_WRITE;
if (K.isThreadLocal())
Flags |= ELF::SHF_TLS;
// K.isMergeableConst() is left out to honour PR4650
if (K.isMergeableCString() || K.isMergeableConst4() ||
K.isMergeableConst8() || K.isMergeableConst16())
Flags |= ELF::SHF_MERGE;
if (K.isMergeableCString())
Flags |= ELF::SHF_STRINGS;
return Flags;
}
const MCSection *TargetLoweringObjectFileELF::getExplicitSectionGlobal(
const GlobalValue *GV, SectionKind Kind, Mangler &Mang,
const TargetMachine &TM) const {
StringRef SectionName = GV->getSection();
// Infer section flags from the section name if we can.
Kind = getELFKindForNamedSection(SectionName, Kind);
return getContext().getELFSection(SectionName,
getELFSectionType(SectionName, Kind),
getELFSectionFlags(Kind), Kind);
}
/// getSectionPrefixForGlobal - Return the section prefix name used by options
/// FunctionsSections and DataSections.
static const char *getSectionPrefixForGlobal(SectionKind Kind) {
if (Kind.isText()) return ".text.";
if (Kind.isReadOnly()) return ".rodata.";
if (Kind.isBSS()) return ".bss.";
if (Kind.isThreadData()) return ".tdata.";
if (Kind.isThreadBSS()) return ".tbss.";
if (Kind.isDataNoRel()) return ".data.";
if (Kind.isDataRelLocal()) return ".data.rel.local.";
if (Kind.isDataRel()) return ".data.rel.";
if (Kind.isReadOnlyWithRelLocal()) return ".data.rel.ro.local.";
assert(Kind.isReadOnlyWithRel() && "Unknown section kind");
return ".data.rel.ro.";
}
const MCSection *TargetLoweringObjectFileELF::
SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
Mangler &Mang, const TargetMachine &TM) const {
// If we have -ffunction-section or -fdata-section then we should emit the
// global value to a uniqued section specifically for it.
bool EmitUniquedSection;
if (Kind.isText())
EmitUniquedSection = TM.getFunctionSections();
else
EmitUniquedSection = TM.getDataSections();
// 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() || EmitUniquedSection) &&
!Kind.isCommon()) {
const char *Prefix;
Prefix = getSectionPrefixForGlobal(Kind);
SmallString<128> Name(Prefix, Prefix+strlen(Prefix));
TM.getNameWithPrefix(Name, GV, Mang, true);
StringRef Group = "";
unsigned Flags = getELFSectionFlags(Kind);
if (GV->isWeakForLinker()) {
Group = Name.substr(strlen(Prefix));
Flags |= ELF::SHF_GROUP;
}
return getContext().getELFSection(Name.str(),
getELFSectionType(Name.str(), Kind),
Flags, Kind, 0, Group);
}
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.getDataLayout()->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 getContext().getELFSection(Name, ELF::SHT_PROGBITS,
ELF::SHF_ALLOC |
ELF::SHF_MERGE |
ELF::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;
// Note: we claim that common symbols are put in BSSSection, but they are
// really emitted with the magic .comm directive, which creates a symbol table
// entry but not a section.
if (Kind.isBSS() || Kind.isCommon()) 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;
}
const MCSection *TargetLoweringObjectFileELF::getStaticCtorSection(
unsigned Priority, const MCSymbol *KeySym, const MCSection *KeySec) const {
// The default scheme is .ctor / .dtor, so we have to invert the priority
// numbering.
if (Priority == 65535)
return StaticCtorSection;
if (UseInitArray) {
std::string Name = std::string(".init_array.") + utostr(Priority);
return getContext().getELFSection(Name, ELF::SHT_INIT_ARRAY,
ELF::SHF_ALLOC | ELF::SHF_WRITE,
SectionKind::getDataRel());
} else {
std::string Name = std::string(".ctors.") + utostr(65535 - Priority);
return getContext().getELFSection(Name, ELF::SHT_PROGBITS,
ELF::SHF_ALLOC |ELF::SHF_WRITE,
SectionKind::getDataRel());
}
}
const MCSection *TargetLoweringObjectFileELF::getStaticDtorSection(
unsigned Priority, const MCSymbol *KeySym, const MCSection *KeySec) const {
// The default scheme is .ctor / .dtor, so we have to invert the priority
// numbering.
if (Priority == 65535)
return StaticDtorSection;
if (UseInitArray) {
std::string Name = std::string(".fini_array.") + utostr(Priority);
return getContext().getELFSection(Name, ELF::SHT_FINI_ARRAY,
ELF::SHF_ALLOC | ELF::SHF_WRITE,
SectionKind::getDataRel());
} else {
std::string Name = std::string(".dtors.") + utostr(65535 - Priority);
return getContext().getELFSection(Name, ELF::SHT_PROGBITS,
ELF::SHF_ALLOC |ELF::SHF_WRITE,
SectionKind::getDataRel());
}
}
void
TargetLoweringObjectFileELF::InitializeELF(bool UseInitArray_) {
UseInitArray = UseInitArray_;
if (!UseInitArray)
return;
StaticCtorSection =
getContext().getELFSection(".init_array", ELF::SHT_INIT_ARRAY,
ELF::SHF_WRITE |
ELF::SHF_ALLOC,
SectionKind::getDataRel());
StaticDtorSection =
getContext().getELFSection(".fini_array", ELF::SHT_FINI_ARRAY,
ELF::SHF_WRITE |
ELF::SHF_ALLOC,
SectionKind::getDataRel());
}
//===----------------------------------------------------------------------===//
// MachO
//===----------------------------------------------------------------------===//
/// getDepLibFromLinkerOpt - Extract the dependent library name from a linker
/// option string. Returns StringRef() if the option does not specify a library.
StringRef TargetLoweringObjectFileMachO::
getDepLibFromLinkerOpt(StringRef LinkerOption) const {
const char *LibCmd = "-l";
if (LinkerOption.startswith(LibCmd))
return LinkerOption.substr(strlen(LibCmd));
return StringRef();
}
/// emitModuleFlags - Perform code emission for module flags.
void TargetLoweringObjectFileMachO::
emitModuleFlags(MCStreamer &Streamer,
ArrayRef<Module::ModuleFlagEntry> ModuleFlags,
Mangler &Mang, const TargetMachine &TM) const {
unsigned VersionVal = 0;
unsigned ImageInfoFlags = 0;
MDNode *LinkerOptions = nullptr;
StringRef SectionVal;
for (ArrayRef<Module::ModuleFlagEntry>::iterator
i = ModuleFlags.begin(), e = ModuleFlags.end(); i != e; ++i) {
const Module::ModuleFlagEntry &MFE = *i;
// Ignore flags with 'Require' behavior.
if (MFE.Behavior == Module::Require)
continue;
StringRef Key = MFE.Key->getString();
Value *Val = MFE.Val;
if (Key == "Objective-C Image Info Version") {
VersionVal = cast<ConstantInt>(Val)->getZExtValue();
} else if (Key == "Objective-C Garbage Collection" ||
Key == "Objective-C GC Only" ||
Key == "Objective-C Is Simulated") {
ImageInfoFlags |= cast<ConstantInt>(Val)->getZExtValue();
} else if (Key == "Objective-C Image Info Section") {
SectionVal = cast<MDString>(Val)->getString();
} else if (Key == "Linker Options") {
LinkerOptions = cast<MDNode>(Val);
}
}
// Emit the linker options if present.
if (LinkerOptions) {
for (unsigned i = 0, e = LinkerOptions->getNumOperands(); i != e; ++i) {
MDNode *MDOptions = cast<MDNode>(LinkerOptions->getOperand(i));
SmallVector<std::string, 4> StrOptions;
// Convert to strings.
for (unsigned ii = 0, ie = MDOptions->getNumOperands(); ii != ie; ++ii) {
MDString *MDOption = cast<MDString>(MDOptions->getOperand(ii));
StrOptions.push_back(MDOption->getString());
}
Streamer.EmitLinkerOptions(StrOptions);
}
}
// The section is mandatory. If we don't have it, then we don't have GC info.
if (SectionVal.empty()) return;
StringRef Segment, Section;
unsigned TAA = 0, StubSize = 0;
bool TAAParsed;
std::string ErrorCode =
MCSectionMachO::ParseSectionSpecifier(SectionVal, Segment, Section,
TAA, TAAParsed, StubSize);
if (!ErrorCode.empty())
// If invalid, report the error with report_fatal_error.
report_fatal_error("Invalid section specifier '" + Section + "': " +
ErrorCode + ".");
// Get the section.
const MCSectionMachO *S =
getContext().getMachOSection(Segment, Section, TAA, StubSize,
SectionKind::getDataNoRel());
Streamer.SwitchSection(S);
Streamer.EmitLabel(getContext().
GetOrCreateSymbol(StringRef("L_OBJC_IMAGE_INFO")));
Streamer.EmitIntValue(VersionVal, 4);
Streamer.EmitIntValue(ImageInfoFlags, 4);
Streamer.AddBlankLine();
}
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 = 0, StubSize = 0;
bool TAAParsed;
std::string ErrorCode =
MCSectionMachO::ParseSectionSpecifier(GV->getSection(), Segment, Section,
TAA, TAAParsed, StubSize);
if (!ErrorCode.empty()) {
// If invalid, report the error with report_fatal_error.
report_fatal_error("Global variable '" + GV->getName() +
"' has an invalid section specifier '" +
GV->getSection() + "': " + ErrorCode + ".");
}
// Get the section.
const MCSectionMachO *S =
getContext().getMachOSection(Segment, Section, TAA, StubSize, Kind);
// If TAA wasn't set by ParseSectionSpecifier() above,
// use the value returned by getMachOSection() as a default.
if (!TAAParsed)
TAA = S->getTypeAndAttributes();
// 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 report_fatal_error.
report_fatal_error("Global variable '" + GV->getName() +
"' section type or attributes does not match previous"
" section specifier");
}
return S;
}
bool TargetLoweringObjectFileMachO::isSectionAtomizableBySymbols(
const MCSection &Section) const {
const MCSectionMachO &SMO = static_cast<const MCSectionMachO&>(Section);
// Sections holding 1 byte strings are atomized based on the data
// they contain.
// Sections holding 2 byte strings require symbols in order to be
// atomized.
// There is no dedicated section for 4 byte strings.
if (SMO.getKind().isMergeable1ByteCString())
return false;
if (SMO.getSegmentName() == "__DATA" &&
SMO.getSectionName() == "__cfstring")
return false;
switch (SMO.getType()) {
default:
return true;
// These sections are atomized at the element boundaries without using
// symbols.
case MachO::S_4BYTE_LITERALS:
case MachO::S_8BYTE_LITERALS:
case MachO::S_16BYTE_LITERALS:
case MachO::S_LITERAL_POINTERS:
case MachO::S_NON_LAZY_SYMBOL_POINTERS:
case MachO::S_LAZY_SYMBOL_POINTERS:
case MachO::S_MOD_INIT_FUNC_POINTERS:
case MachO::S_MOD_TERM_FUNC_POINTERS:
case MachO::S_INTERPOSING:
return false;
}
}
const MCSection *TargetLoweringObjectFileMachO::
SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
Mangler &Mang, const TargetMachine &TM) const {
// Handle thread local data.
if (Kind.isThreadBSS()) return TLSBSSSection;
if (Kind.isThreadData()) return TLSDataSection;
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() &&
TM.getDataLayout()->getPreferredAlignment(cast<GlobalVariable>(GV)) < 32)
return CStringSection;
// Do not put 16-bit arrays in the UString section if they have an
// externally visible label, this runs into issues with certain linker
// versions.
if (Kind.isMergeable2ByteCString() && !GV->hasExternalLinkage() &&
TM.getDataLayout()->getPreferredAlignment(cast<GlobalVariable>(GV)) < 32)
return UStringSection;
if (Kind.isMergeableConst()) {
if (Kind.isMergeableConst4())
return FourByteConstantSection;
if (Kind.isMergeableConst8())
return EightByteConstantSection;
if (Kind.isMergeableConst16())
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;
// Put zero initialized globals with strong external linkage in the
// DATA, __common section with the .zerofill directive.
if (Kind.isBSSExtern())
return DataCommonSection;
// Put zero initialized globals with local linkage in __DATA,__bss directive
// with the .zerofill directive (aka .lcomm).
if (Kind.isBSSLocal())
return DataBSSSection;
// 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() || Kind.isReadOnlyWithRel())
return ConstDataSection;
if (Kind.isMergeableConst4())
return FourByteConstantSection;
if (Kind.isMergeableConst8())
return EightByteConstantSection;
if (Kind.isMergeableConst16())
return SixteenByteConstantSection;
return ReadOnlySection; // .const
}
const MCExpr *TargetLoweringObjectFileMachO::getTTypeGlobalReference(
const GlobalValue *GV, unsigned Encoding, Mangler &Mang,
const TargetMachine &TM, MachineModuleInfo *MMI,
MCStreamer &Streamer) const {
// The mach-o version of this method defaults to returning a stub reference.
if (Encoding & DW_EH_PE_indirect) {
MachineModuleInfoMachO &MachOMMI =
MMI->getObjFileInfo<MachineModuleInfoMachO>();
MCSymbol *SSym =
getSymbolWithGlobalValueBase(GV, "$non_lazy_ptr", Mang, TM);
// Add information about the stub reference to MachOMMI so that the stub
// gets emitted by the asmprinter.
MachineModuleInfoImpl::StubValueTy &StubSym =
GV->hasHiddenVisibility() ? MachOMMI.getHiddenGVStubEntry(SSym) :
MachOMMI.getGVStubEntry(SSym);
if (!StubSym.getPointer()) {
MCSymbol *Sym = TM.getSymbol(GV, Mang);
StubSym = MachineModuleInfoImpl::StubValueTy(Sym, !GV->hasLocalLinkage());
}
return TargetLoweringObjectFile::
getTTypeReference(MCSymbolRefExpr::Create(SSym, getContext()),
Encoding & ~dwarf::DW_EH_PE_indirect, Streamer);
}
return TargetLoweringObjectFile::getTTypeGlobalReference(GV, Encoding, Mang,
TM, MMI, Streamer);
}
MCSymbol *TargetLoweringObjectFileMachO::getCFIPersonalitySymbol(
const GlobalValue *GV, Mangler &Mang, const TargetMachine &TM,
MachineModuleInfo *MMI) const {
// The mach-o version of this method defaults to returning a stub reference.
MachineModuleInfoMachO &MachOMMI =
MMI->getObjFileInfo<MachineModuleInfoMachO>();
MCSymbol *SSym = getSymbolWithGlobalValueBase(GV, "$non_lazy_ptr", Mang, TM);
// Add information about the stub reference to MachOMMI so that the stub
// gets emitted by the asmprinter.
MachineModuleInfoImpl::StubValueTy &StubSym = MachOMMI.getGVStubEntry(SSym);
if (!StubSym.getPointer()) {
MCSymbol *Sym = TM.getSymbol(GV, Mang);
StubSym = MachineModuleInfoImpl::StubValueTy(Sym, !GV->hasLocalLinkage());
}
return SSym;
}
//===----------------------------------------------------------------------===//
// COFF
//===----------------------------------------------------------------------===//
static unsigned
getCOFFSectionFlags(SectionKind K) {
unsigned Flags = 0;
if (K.isMetadata())
Flags |=
COFF::IMAGE_SCN_MEM_DISCARDABLE;
else if (K.isText())
Flags |=
COFF::IMAGE_SCN_MEM_EXECUTE |
COFF::IMAGE_SCN_MEM_READ |
COFF::IMAGE_SCN_CNT_CODE;
else if (K.isBSS ())
Flags |=
COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA |
COFF::IMAGE_SCN_MEM_READ |
COFF::IMAGE_SCN_MEM_WRITE;
else if (K.isThreadLocal())
Flags |=
COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
COFF::IMAGE_SCN_MEM_READ |
COFF::IMAGE_SCN_MEM_WRITE;
else if (K.isReadOnly())
Flags |=
COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
COFF::IMAGE_SCN_MEM_READ;
else if (K.isWriteable())
Flags |=
COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
COFF::IMAGE_SCN_MEM_READ |
COFF::IMAGE_SCN_MEM_WRITE;
return Flags;
}
const MCSection *TargetLoweringObjectFileCOFF::getExplicitSectionGlobal(
const GlobalValue *GV, SectionKind Kind, Mangler &Mang,
const TargetMachine &TM) const {
int Selection = 0;
unsigned Characteristics = getCOFFSectionFlags(Kind);
StringRef Name = GV->getSection();
StringRef COMDATSymName = "";
if (GV->isWeakForLinker()) {
Selection = COFF::IMAGE_COMDAT_SELECT_ANY;
Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT;
MCSymbol *Sym = TM.getSymbol(GV, Mang);
COMDATSymName = Sym->getName();
}
return getContext().getCOFFSection(Name,
Characteristics,
Kind,
COMDATSymName,
Selection);
}
static const char *getCOFFSectionNameForUniqueGlobal(SectionKind Kind) {
if (Kind.isText())
return ".text";
if (Kind.isBSS())
return ".bss";
if (Kind.isThreadLocal())
return ".tls$";
if (Kind.isWriteable())
return ".data";
return ".rdata";
}
const MCSection *TargetLoweringObjectFileCOFF::
SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
Mangler &Mang, const TargetMachine &TM) const {
// If we have -ffunction-sections then we should emit the global value to a
// uniqued section specifically for it.
bool EmitUniquedSection;
if (Kind.isText())
EmitUniquedSection = TM.getFunctionSections();
else
EmitUniquedSection = TM.getDataSections();
// 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.
// Section names depend on the name of the symbol which is not feasible if the
// symbol has private linkage.
if ((GV->isWeakForLinker() || EmitUniquedSection) &&
!GV->hasPrivateLinkage() && !Kind.isCommon()) {
const char *Name = getCOFFSectionNameForUniqueGlobal(Kind);
unsigned Characteristics = getCOFFSectionFlags(Kind);
Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT;
MCSymbol *Sym = TM.getSymbol(GV, Mang);
return getContext().getCOFFSection(
Name, Characteristics, Kind, Sym->getName(),
GV->isWeakForLinker() ? COFF::IMAGE_COMDAT_SELECT_ANY
: COFF::IMAGE_COMDAT_SELECT_NODUPLICATES);
}
if (Kind.isText())
return TextSection;
if (Kind.isThreadLocal())
return TLSDataSection;
if (Kind.isReadOnly())
return ReadOnlySection;
// Note: we claim that common symbols are put in BSSSection, but they are
// really emitted with the magic .comm directive, which creates a symbol table
// entry but not a section.
if (Kind.isBSS() || Kind.isCommon())
return BSSSection;
return DataSection;
}
StringRef TargetLoweringObjectFileCOFF::
getDepLibFromLinkerOpt(StringRef LinkerOption) const {
const char *LibCmd = "/DEFAULTLIB:";
if (LinkerOption.startswith(LibCmd))
return LinkerOption.substr(strlen(LibCmd));
return StringRef();
}
void TargetLoweringObjectFileCOFF::
emitModuleFlags(MCStreamer &Streamer,
ArrayRef<Module::ModuleFlagEntry> ModuleFlags,
Mangler &Mang, const TargetMachine &TM) const {
MDNode *LinkerOptions = nullptr;
// Look for the "Linker Options" flag, since it's the only one we support.
for (ArrayRef<Module::ModuleFlagEntry>::iterator
i = ModuleFlags.begin(), e = ModuleFlags.end(); i != e; ++i) {
const Module::ModuleFlagEntry &MFE = *i;
StringRef Key = MFE.Key->getString();
Value *Val = MFE.Val;
if (Key == "Linker Options") {
LinkerOptions = cast<MDNode>(Val);
break;
}
}
if (!LinkerOptions)
return;
// Emit the linker options to the linker .drectve section. According to the
// spec, this section is a space-separated string containing flags for linker.
const MCSection *Sec = getDrectveSection();
Streamer.SwitchSection(Sec);
for (unsigned i = 0, e = LinkerOptions->getNumOperands(); i != e; ++i) {
MDNode *MDOptions = cast<MDNode>(LinkerOptions->getOperand(i));
for (unsigned ii = 0, ie = MDOptions->getNumOperands(); ii != ie; ++ii) {
MDString *MDOption = cast<MDString>(MDOptions->getOperand(ii));
StringRef Op = MDOption->getString();
// Lead with a space for consistency with our dllexport implementation.
std::string Escaped(" ");
if (Op.find(" ") != StringRef::npos) {
// The PE-COFF spec says args with spaces must be quoted. It doesn't say
// how to escape quotes, but it probably uses this algorithm:
// http://msdn.microsoft.com/en-us/library/17w5ykft(v=vs.85).aspx
// FIXME: Reuse escaping code from Support/Windows/Program.inc
Escaped.push_back('\"');
Escaped.append(Op);
Escaped.push_back('\"');
} else {
Escaped.append(Op);
}
Streamer.EmitBytes(Escaped);
}
}
}
static const MCSection *getAssociativeCOFFSection(MCContext &Ctx,
const MCSection *Sec,
const MCSymbol *KeySym,
const MCSection *KeySec) {
// Return the normal section if we don't have to be associative.
if (!KeySym)
return Sec;
// Make an associative section with the same name and kind as the normal
// section.
const MCSectionCOFF *SecCOFF = cast<MCSectionCOFF>(Sec);
const MCSectionCOFF *KeySecCOFF = cast<MCSectionCOFF>(KeySec);
unsigned Characteristics =
SecCOFF->getCharacteristics() | COFF::IMAGE_SCN_LNK_COMDAT;
return Ctx.getCOFFSection(SecCOFF->getSectionName(), Characteristics,
SecCOFF->getKind(), KeySym->getName(),
COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE, KeySecCOFF);
}
const MCSection *TargetLoweringObjectFileCOFF::getStaticCtorSection(
unsigned Priority, const MCSymbol *KeySym, const MCSection *KeySec) const {
return getAssociativeCOFFSection(getContext(), StaticCtorSection, KeySym, KeySec);
}
const MCSection *TargetLoweringObjectFileCOFF::getStaticDtorSection(
unsigned Priority, const MCSymbol *KeySym, const MCSection *KeySec) const {
return getAssociativeCOFFSection(getContext(), StaticDtorSection, KeySym, KeySec);
}