diff options
author | Peter Collingbourne <peter@pcc.me.uk> | 2015-06-29 22:04:09 +0000 |
---|---|---|
committer | Peter Collingbourne <peter@pcc.me.uk> | 2015-06-29 22:04:09 +0000 |
commit | aef3659e1888753ffe03510c513e1a2d9101a795 (patch) | |
tree | 90628139a0ed05a1976cc268cde21abd210acfc0 /llvm/lib | |
parent | 3c7828e36ebc615904627561eec6761cca2cbab2 (diff) | |
download | bcm5719-llvm-aef3659e1888753ffe03510c513e1a2d9101a795.tar.gz bcm5719-llvm-aef3659e1888753ffe03510c513e1a2d9101a795.zip |
Teach LTOModule to emit linker flags for dllexported symbols, plus interface cleanup.
This change unifies how LTOModule and the backend obtain linker flags
for globals: via a new TargetLoweringObjectFile member function named
emitLinkerFlagsForGlobal. A new function LTOModule::getLinkerOpts() returns
the list of linker flags as a single concatenated string.
This change affects the C libLTO API: the function lto_module_get_*deplibs now
exposes an empty list, and lto_module_get_*linkeropts exposes a single element
which combines the contents of all observed flags. libLTO should never have
tried to parse the linker flags; it is the linker's job to do so. Because
linkers will need to be able to parse flags in regular object files, it
makes little sense for libLTO to have a redundant mechanism for doing so.
The new API is compatible with the old one. It is valid for a user to specify
multiple linker flags in a single pragma directive like this:
#pragma comment(linker, "/defaultlib:foo /defaultlib:bar")
The previous implementation would not have exposed
either flag via lto_module_get_*deplibs (as the test in
TargetLoweringObjectFileCOFF::getDepLibFromLinkerOpt was case sensitive)
and would have exposed "/defaultlib:foo /defaultlib:bar" as a single flag via
lto_module_get_*linkeropts. This may have been a bug in the implementation,
but it does give us a chance to fix the interface.
Differential Revision: http://reviews.llvm.org/D10548
llvm-svn: 241010
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp | 51 | ||||
-rw-r--r-- | llvm/lib/LTO/LTOModule.cpp | 24 | ||||
-rw-r--r-- | llvm/lib/Target/X86/X86AsmPrinter.cpp | 67 | ||||
-rw-r--r-- | llvm/lib/Target/X86/X86AsmPrinter.h | 2 |
4 files changed, 59 insertions, 85 deletions
diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp index d7b043dac01..e1ac444d4a4 100644 --- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -440,16 +440,6 @@ TargetLoweringObjectFileMachO::TargetLoweringObjectFileMachO() SupportIndirectSymViaGOTPCRel = true; } -/// 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, @@ -990,14 +980,6 @@ MCSection *TargetLoweringObjectFileCOFF::getSectionForJumpTable( COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE); } -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, @@ -1045,3 +1027,36 @@ MCSection *TargetLoweringObjectFileCOFF::getStaticDtorSection( return getContext().getAssociativeCOFFSection( cast<MCSectionCOFF>(StaticDtorSection), KeySym); } + +void TargetLoweringObjectFileCOFF::emitLinkerFlagsForGlobal( + raw_ostream &OS, const GlobalValue *GV, const Mangler &Mang) const { + if (!GV->hasDLLExportStorageClass() || GV->isDeclaration()) + return; + + const Triple &TT = getTargetTriple(); + + if (TT.isKnownWindowsMSVCEnvironment()) + OS << " /EXPORT:"; + else + OS << " -export:"; + + if (TT.isWindowsGNUEnvironment() || TT.isWindowsCygwinEnvironment()) { + std::string Flag; + raw_string_ostream FlagOS(Flag); + Mang.getNameWithPrefix(FlagOS, GV, false); + FlagOS.flush(); + if (Flag[0] == DL->getGlobalPrefix()) + OS << Flag.substr(1); + else + OS << Flag; + } else { + Mang.getNameWithPrefix(OS, GV, false); + } + + if (!GV->getValueType()->isFunctionTy()) { + if (TT.isKnownWindowsMSVCEnvironment()) + OS << ",DATA"; + else + OS << ",data"; + } +} diff --git a/llvm/lib/LTO/LTOModule.cpp b/llvm/lib/LTO/LTOModule.cpp index bbb3b6df30c..6131c318024 100644 --- a/llvm/lib/LTO/LTOModule.cpp +++ b/llvm/lib/LTO/LTOModule.cpp @@ -19,6 +19,7 @@ #include "llvm/IR/Constants.h" #include "llvm/IR/DiagnosticPrinter.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Mangler.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" #include "llvm/MC/MCExpr.h" @@ -642,6 +643,8 @@ bool LTOModule::parseSymbols(std::string &errMsg) { /// parseMetadata - Parse metadata from the module void LTOModule::parseMetadata() { + raw_string_ostream OS(LinkerOpts); + // Linker Options if (Metadata *Val = getModule().getModuleFlag("Linker Options")) { MDNode *LinkerOptions = cast<MDNode>(Val); @@ -649,20 +652,19 @@ void LTOModule::parseMetadata() { MDNode *MDOptions = cast<MDNode>(LinkerOptions->getOperand(i)); for (unsigned ii = 0, ie = MDOptions->getNumOperands(); ii != ie; ++ii) { MDString *MDOption = cast<MDString>(MDOptions->getOperand(ii)); - // FIXME: Make StringSet::insert match Self-Associative Container - // requirements, returning <iter,bool> rather than bool, and use that - // here. - StringRef Op = - _linkeropt_strings.insert(MDOption->getString()).first->first(); - StringRef DepLibName = - _target->getObjFileLowering()->getDepLibFromLinkerOpt(Op); - if (!DepLibName.empty()) - _deplibs.push_back(DepLibName.data()); - else if (!Op.empty()) - _linkeropts.push_back(Op.data()); + OS << " " << MDOption->getString(); } } } + // Globals + Mangler Mang; + for (const NameAndAttributes &Sym : _symbols) { + if (!Sym.symbol) + continue; + _target->getObjFileLowering()->emitLinkerFlagsForGlobal(OS, Sym.symbol, + Mang); + } + // Add other interesting metadata here. } diff --git a/llvm/lib/Target/X86/X86AsmPrinter.cpp b/llvm/lib/Target/X86/X86AsmPrinter.cpp index 0557582b50d..ba33248d203 100644 --- a/llvm/lib/Target/X86/X86AsmPrinter.cpp +++ b/llvm/lib/Target/X86/X86AsmPrinter.cpp @@ -581,34 +581,6 @@ MCSymbol *X86AsmPrinter::GetCPISymbol(unsigned CPID) const { return AsmPrinter::GetCPISymbol(CPID); } -void X86AsmPrinter::GenerateExportDirective(const MCSymbol *Sym, bool IsData) { - SmallString<128> Directive; - raw_svector_ostream OS(Directive); - StringRef Name = Sym->getName(); - const Triple &TT = TM.getTargetTriple(); - - if (TT.isKnownWindowsMSVCEnvironment()) - OS << " /EXPORT:"; - else - OS << " -export:"; - - if ((TT.isWindowsGNUEnvironment() || TT.isWindowsCygwinEnvironment()) && - (Name[0] == getDataLayout().getGlobalPrefix())) - Name = Name.drop_front(); - - OS << Name; - - if (IsData) { - if (TT.isKnownWindowsMSVCEnvironment()) - OS << ",DATA"; - else - OS << ",data"; - } - - OS.flush(); - OutStreamer->EmitBytes(Directive); -} - void X86AsmPrinter::EmitEndOfAsmFile(Module &M) { const Triple &TT = TM.getTargetTriple(); @@ -692,38 +664,25 @@ void X86AsmPrinter::EmitEndOfAsmFile(Module &M) { } if (TT.isOSBinFormatCOFF()) { - // Necessary for dllexport support - std::vector<const MCSymbol*> DLLExportedFns, DLLExportedGlobals; + const TargetLoweringObjectFileCOFF &TLOFCOFF = + static_cast<const TargetLoweringObjectFileCOFF&>(getObjFileLowering()); - for (const auto &Function : M) - if (Function.hasDLLExportStorageClass() && !Function.isDeclaration()) - DLLExportedFns.push_back(getSymbol(&Function)); + std::string Flags; + raw_string_ostream FlagsOS(Flags); + for (const auto &Function : M) + TLOFCOFF.emitLinkerFlagsForGlobal(FlagsOS, &Function, *Mang); for (const auto &Global : M.globals()) - if (Global.hasDLLExportStorageClass() && !Global.isDeclaration()) - DLLExportedGlobals.push_back(getSymbol(&Global)); + TLOFCOFF.emitLinkerFlagsForGlobal(FlagsOS, &Global, *Mang); + for (const auto &Alias : M.aliases()) + TLOFCOFF.emitLinkerFlagsForGlobal(FlagsOS, &Alias, *Mang); - for (const auto &Alias : M.aliases()) { - if (!Alias.hasDLLExportStorageClass()) - continue; - - if (Alias.getType()->getElementType()->isFunctionTy()) - DLLExportedFns.push_back(getSymbol(&Alias)); - else - DLLExportedGlobals.push_back(getSymbol(&Alias)); - } - - // Output linker support code for dllexported globals on windows. - if (!DLLExportedGlobals.empty() || !DLLExportedFns.empty()) { - const TargetLoweringObjectFileCOFF &TLOFCOFF = - static_cast<const TargetLoweringObjectFileCOFF&>(getObjFileLowering()); + FlagsOS.flush(); + // Output collected flags. + if (!Flags.empty()) { OutStreamer->SwitchSection(TLOFCOFF.getDrectveSection()); - - for (auto & Symbol : DLLExportedGlobals) - GenerateExportDirective(Symbol, /*IsData=*/true); - for (auto & Symbol : DLLExportedFns) - GenerateExportDirective(Symbol, /*IsData=*/false); + OutStreamer->EmitBytes(Flags); } SM.serializeToStackMapSection(); diff --git a/llvm/lib/Target/X86/X86AsmPrinter.h b/llvm/lib/Target/X86/X86AsmPrinter.h index acba21169c9..7f5d127c68d 100644 --- a/llvm/lib/Target/X86/X86AsmPrinter.h +++ b/llvm/lib/Target/X86/X86AsmPrinter.h @@ -30,8 +30,6 @@ class LLVM_LIBRARY_VISIBILITY X86AsmPrinter : public AsmPrinter { StackMaps SM; FaultMaps FM; - void GenerateExportDirective(const MCSymbol *Sym, bool IsData); - // This utility class tracks the length of a stackmap instruction's 'shadow'. // It is used by the X86AsmPrinter to ensure that the stackmap shadow // invariants (i.e. no other stackmaps, patchpoints, or control flow within |