Index: include/llvm/CodeGen/TargetLoweringObjectFileImpl.h =================================================================== --- include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -171,6 +171,9 @@ const GlobalValue *GV) const override; }; +void emitLinkerFlagsForGlobalCOFF(raw_ostream &OS, const GlobalValue *GV, + const Triple &TT, Mangler &Mangler); + } // end namespace llvm #endif Index: include/llvm/LTO/LTO.h =================================================================== --- include/llvm/LTO/LTO.h +++ include/llvm/LTO/LTO.h @@ -25,6 +25,7 @@ #include "llvm/LTO/Config.h" #include "llvm/Linker/IRMover.h" #include "llvm/Object/IRObjectFile.h" +#include "llvm/Support/Error.h" #include "llvm/Support/thread.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Transforms/IPO/FunctionImport.h" @@ -105,6 +106,7 @@ class Symbol { friend symbol_iterator; friend LTO; + friend InputFile; ArrayRef::iterator I; const ModuleSymbolTable &SymTab; @@ -220,6 +222,9 @@ symbol_iterator(SymTab.symbols().end(), SymTab, this)); } + /// Returns linker options specified in the input file. + Expected getLinkerOpts(); + /// Returns the path to the InputFile. StringRef getName() const; Index: lib/CodeGen/TargetLoweringObjectFileImpl.cpp =================================================================== --- lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -919,6 +919,37 @@ return 0; } +void llvm::emitLinkerFlagsForGlobalCOFF(raw_ostream &OS, const GlobalValue *GV, + const Triple &TT, Mangler &Mangler) { + if (!GV->hasDLLExportStorageClass() || GV->isDeclaration()) + return; + + if (TT.isKnownWindowsMSVCEnvironment()) + OS << " /EXPORT:"; + else + OS << " -export:"; + + if (TT.isWindowsGNUEnvironment() || TT.isWindowsCygwinEnvironment()) { + std::string Flag; + raw_string_ostream FlagOS(Flag); + Mangler.getNameWithPrefix(FlagOS, GV, false); + FlagOS.flush(); + if (Flag[0] == GV->getParent()->getDataLayout().getGlobalPrefix()) + OS << Flag.substr(1); + else + OS << Flag; + } else { + Mangler.getNameWithPrefix(OS, GV, false); + } + + if (!GV->getValueType()->isFunctionTy()) { + if (TT.isKnownWindowsMSVCEnvironment()) + OS << ",DATA"; + else + OS << ",data"; + } +} + MCSection *TargetLoweringObjectFileCOFF::getExplicitSectionGlobal( const GlobalObject *GO, SectionKind Kind, const TargetMachine &TM) const { int Selection = 0; @@ -1122,33 +1153,5 @@ void TargetLoweringObjectFileCOFF::emitLinkerFlagsForGlobal( raw_ostream &OS, const GlobalValue *GV) 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); - getMangler().getNameWithPrefix(FlagOS, GV, false); - FlagOS.flush(); - if (Flag[0] == GV->getParent()->getDataLayout().getGlobalPrefix()) - OS << Flag.substr(1); - else - OS << Flag; - } else { - getMangler().getNameWithPrefix(OS, GV, false); - } - - if (!GV->getValueType()->isFunctionTy()) { - if (TT.isKnownWindowsMSVCEnvironment()) - OS << ",DATA"; - else - OS << ",data"; - } + emitLinkerFlagsForGlobalCOFF(OS, GV, getTargetTriple(), getMangler()); } Index: lib/LTO/LTO.cpp =================================================================== --- lib/LTO/LTO.cpp +++ lib/LTO/LTO.cpp @@ -17,12 +17,16 @@ #include "llvm/Bitcode/BitcodeReader.h" #include "llvm/Bitcode/BitcodeWriter.h" #include "llvm/CodeGen/Analysis.h" +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" #include "llvm/IR/AutoUpgrade.h" #include "llvm/IR/DiagnosticPrinter.h" #include "llvm/IR/LegacyPassManager.h" +#include "llvm/IR/Mangler.h" +#include "llvm/IR/Metadata.h" #include "llvm/LTO/LTOBackend.h" #include "llvm/Linker/IRMover.h" #include "llvm/Object/ModuleSummaryIndexObjectFile.h" +#include "llvm/Support/Error.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" @@ -288,6 +292,37 @@ return -1; } +Expected InputFile::getLinkerOpts() { + std::string LinkerOpts; + raw_string_ostream LOS(LinkerOpts); + // Extract linker options from module metadata. + for (InputModule &Mod : Mods) { + std::unique_ptr &M = Mod.Mod; + if (auto E = M->materializeMetadata()) + return std::move(E); + if (Metadata *Val = M->getModuleFlag("Linker Options")) { + MDNode *LinkerOptions = cast(Val); + for (const MDOperand &MDOptions : LinkerOptions->operands()) { + for (const MDOperand &MDOption : cast(MDOptions)->operands()) { + LOS << " " << cast(MDOption)->getString(); + } + } + } + } + + // Synthesize export flags for symbols with dllexport storage. + std::string TTStr = Mods.empty() ? "" : Mods[0].Mod->getTargetTriple(); + if (TTStr.empty()) + TTStr = sys::getDefaultTargetTriple(); + const Triple TT(TTStr); + Mangler M; + for (auto &Sym : symbols()) + if (Sym.isGV()) + emitLinkerFlagsForGlobalCOFF(LOS, Sym.getGV(), TT, M); + LOS.flush(); + return LinkerOpts; +} + StringRef InputFile::getName() const { return Mods[0].BM.getModuleIdentifier(); }