TargetLoweringObjectFileImpl.cpp [plain text]
#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/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/Mangler.h"
#include "llvm/Target/TargetMachine.h"
using namespace llvm;
using namespace dwarf;
MCSymbol *
TargetLoweringObjectFileELF::getCFIPersonalitySymbol(const GlobalValue *GV,
Mangler *Mang,
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 getSymbol(*Mang, GV);
case dwarf::DW_EH_PE_pcrel: {
return getContext().GetOrCreateSymbol(StringRef("DW.ref.") +
getSymbol(*Mang, GV)->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, Mangler *Mang,
MachineModuleInfo *MMI, unsigned Encoding,
MCStreamer &Streamer) const {
if (Encoding & dwarf::DW_EH_PE_indirect) {
MachineModuleInfoELF &ELFMMI = MMI->getObjFileInfo<MachineModuleInfoELF>();
SmallString<128> Name;
Mang->getNameWithPrefix(Name, GV, true);
Name += ".DW.stub";
MCSymbol *SSym = getContext().GetOrCreateSymbol(Name.str());
MachineModuleInfoImpl::StubValueTy &StubSym = ELFMMI.getGVStubEntry(SSym);
if (StubSym.getPointer() == 0) {
MCSymbol *Sym = getSymbol(*Mang, GV);
StubSym = MachineModuleInfoImpl::StubValueTy(Sym, !GV->hasLocalLinkage());
}
return TargetLoweringObjectFile::
getTTypeReference(MCSymbolRefExpr::Create(SSym, getContext()),
Encoding & ~dwarf::DW_EH_PE_indirect, Streamer);
}
return TargetLoweringObjectFile::
getTTypeGlobalReference(GV, Mang, MMI, Encoding, Streamer);
}
static SectionKind
getELFKindForNamedSection(StringRef Name, SectionKind K) {
if (Name.empty() || Name[0] != '.') return K;
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;
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();
Kind = getELFKindForNamedSection(SectionName, Kind);
return getContext().getELFSection(SectionName,
getELFSectionType(SectionName, Kind),
getELFSectionFlags(Kind), Kind);
}
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 {
bool EmitUniquedSection;
if (Kind.isText())
EmitUniquedSection = TM.getFunctionSections();
else
EmitUniquedSection = TM.getDataSections();
if ((GV->isWeakForLinker() || EmitUniquedSection) &&
!Kind.isCommon()) {
const char *Prefix;
Prefix = getSectionPrefixForGlobal(Kind);
SmallString<128> Name(Prefix, Prefix+strlen(Prefix));
MCSymbol *Sym = getSymbol(*Mang, GV);
Name.append(Sym->getName().begin(), Sym->getName().end());
StringRef Group = "";
unsigned Flags = getELFSectionFlags(Kind);
if (GV->isWeakForLinker()) {
Group = Sym->getName();
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()) {
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; }
if (Kind.isReadOnly()) return ReadOnlySection;
if (Kind.isThreadData()) return TLSDataSection;
if (Kind.isThreadBSS()) return TLSBSSSection;
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;
}
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 {
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 {
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());
}
void TargetLoweringObjectFileMachO::
emitModuleFlags(MCStreamer &Streamer,
ArrayRef<Module::ModuleFlagEntry> ModuleFlags,
Mangler *Mang, const TargetMachine &TM) const {
unsigned VersionVal = 0;
unsigned ImageInfoFlags = 0;
MDNode *LinkerOptions = 0;
StringRef SectionVal;
for (ArrayRef<Module::ModuleFlagEntry>::iterator
i = ModuleFlags.begin(), e = ModuleFlags.end(); i != e; ++i) {
const Module::ModuleFlagEntry &MFE = *i;
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);
}
}
if (LinkerOptions) {
for (unsigned i = 0, e = LinkerOptions->getNumOperands(); i != e; ++i) {
MDNode *MDOptions = cast<MDNode>(LinkerOptions->getOperand(i));
SmallVector<std::string, 4> StrOptions;
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);
}
}
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())
report_fatal_error("Invalid section specifier '" + Section + "': " +
ErrorCode + ".");
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 {
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()) {
report_fatal_error("Global variable '" + GV->getName() +
"' has an invalid section specifier '" +
GV->getSection() + "': " + ErrorCode + ".");
}
const MCSectionMachO *S =
getContext().getMachOSection(Segment, Section, TAA, StubSize, Kind);
if (!TAAParsed)
TAA = S->getTypeAndAttributes();
if (S->getTypeAndAttributes() != TAA || S->getStubSize() != StubSize) {
report_fatal_error("Global variable '" + GV->getName() +
"' 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 {
if (Kind.isThreadBSS()) return TLSBSSSection;
if (Kind.isThreadData()) return TLSDataSection;
if (Kind.isText())
return GV->isWeakForLinker() ? TextCoalSection : TextSection;
if (GV->isWeakForLinker()) {
if (Kind.isReadOnly())
return ConstTextCoalSection;
return DataCoalSection;
}
if (Kind.isMergeable1ByteCString() &&
TM.getDataLayout()->getPreferredAlignment(cast<GlobalVariable>(GV)) < 32)
return CStringSection;
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() && SixteenByteConstantSection)
return SixteenByteConstantSection;
}
if (Kind.isReadOnly())
return ReadOnlySection;
if (Kind.isReadOnlyWithRel())
return ConstDataSection;
if (Kind.isBSSExtern())
return DataCommonSection;
if (Kind.isBSSLocal())
return DataBSSSection;
return DataSection;
}
const MCSection *
TargetLoweringObjectFileMachO::getSectionForConstant(SectionKind Kind) const {
if (Kind.isDataRel() || Kind.isReadOnlyWithRel())
return ConstDataSection;
if (Kind.isMergeableConst4())
return FourByteConstantSection;
if (Kind.isMergeableConst8())
return EightByteConstantSection;
if (Kind.isMergeableConst16() && SixteenByteConstantSection)
return SixteenByteConstantSection;
return ReadOnlySection; }
bool TargetLoweringObjectFileMachO::
shouldEmitUsedDirectiveFor(const GlobalValue *GV, Mangler *Mang) const {
if (!GV) return false;
if (GV->hasLocalLinkage() && !isa<Function>(GV)) {
MCSymbol *Sym = getSymbol(*Mang, GV);
if (Sym->getName()[0] == 'L' || Sym->getName()[0] == 'l')
return false;
}
return true;
}
const MCExpr *TargetLoweringObjectFileMachO::
getTTypeGlobalReference(const GlobalValue *GV, Mangler *Mang,
MachineModuleInfo *MMI, unsigned Encoding,
MCStreamer &Streamer) const {
if (Encoding & DW_EH_PE_indirect) {
MachineModuleInfoMachO &MachOMMI =
MMI->getObjFileInfo<MachineModuleInfoMachO>();
SmallString<128> Name;
Mang->getNameWithPrefix(Name, GV, true);
Name += "$non_lazy_ptr";
MCSymbol *SSym = getContext().GetOrCreateSymbol(Name.str());
MachineModuleInfoImpl::StubValueTy &StubSym =
GV->hasHiddenVisibility() ? MachOMMI.getHiddenGVStubEntry(SSym) :
MachOMMI.getGVStubEntry(SSym);
if (StubSym.getPointer() == 0) {
MCSymbol *Sym = getSymbol(*Mang, GV);
StubSym = MachineModuleInfoImpl::StubValueTy(Sym, !GV->hasLocalLinkage());
}
return TargetLoweringObjectFile::
getTTypeReference(MCSymbolRefExpr::Create(SSym, getContext()),
Encoding & ~dwarf::DW_EH_PE_indirect, Streamer);
}
return TargetLoweringObjectFile::
getTTypeGlobalReference(GV, Mang, MMI, Encoding, Streamer);
}
MCSymbol *TargetLoweringObjectFileMachO::
getCFIPersonalitySymbol(const GlobalValue *GV, Mangler *Mang,
MachineModuleInfo *MMI) const {
MachineModuleInfoMachO &MachOMMI =
MMI->getObjFileInfo<MachineModuleInfoMachO>();
SmallString<128> Name;
Mang->getNameWithPrefix(Name, GV, true);
Name += "$non_lazy_ptr";
MCSymbol *SSym = getContext().GetOrCreateSymbol(Name.str());
MachineModuleInfoImpl::StubValueTy &StubSym = MachOMMI.getGVStubEntry(SSym);
if (StubSym.getPointer() == 0) {
MCSymbol *Sym = getSymbol(*Mang, GV);
StubSym = MachineModuleInfoImpl::StubValueTy(Sym, !GV->hasLocalLinkage());
}
return SSym;
}
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);
SmallString<128> Name(GV->getSection().c_str());
if (GV->isWeakForLinker()) {
Selection = COFF::IMAGE_COMDAT_SELECT_ANY;
Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT;
Name.append("$");
Mang->getNameWithPrefix(Name, GV, false, false);
}
return getContext().getCOFFSection(Name,
Characteristics,
Kind,
Selection);
}
static const char *getCOFFSectionPrefixForUniqueGlobal(SectionKind Kind) {
if (Kind.isText())
return ".text$";
if (Kind.isBSS ())
return ".bss$";
if (Kind.isThreadLocal()) {
return ".tls$LLVM";
}
if (Kind.isWriteable())
return ".data$";
return ".rdata$";
}
const MCSection *TargetLoweringObjectFileCOFF::
SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind,
Mangler *Mang, const TargetMachine &TM) const {
if (GV->isWeakForLinker()) {
const char *Prefix = getCOFFSectionPrefixForUniqueGlobal(Kind);
SmallString<128> Name(Prefix, Prefix+strlen(Prefix));
Mang->getNameWithPrefix(Name, GV, false, false);
unsigned Characteristics = getCOFFSectionFlags(Kind);
Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT;
return getContext().getCOFFSection(Name.str(), Characteristics,
Kind, COFF::IMAGE_COMDAT_SELECT_ANY);
}
if (Kind.isText())
return TextSection;
if (Kind.isThreadLocal())
return TLSDataSection;
if (Kind.isReadOnly())
return ReadOnlySection;
if (Kind.isBSS())
return BSSSection;
return DataSection;
}
void TargetLoweringObjectFileCOFF::
emitModuleFlags(MCStreamer &Streamer,
ArrayRef<Module::ModuleFlagEntry> ModuleFlags,
Mangler *Mang, const TargetMachine &TM) const {
MDNode *LinkerOptions = 0;
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;
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();
std::string Escaped(" ");
if (Op.find(" ") != StringRef::npos) {
Escaped.push_back('\"');
Escaped.append(Op);
Escaped.push_back('\"');
} else {
Escaped.append(Op);
}
Streamer.EmitBytes(Escaped);
}
}
}