Index: llvm/trunk/include/llvm-c/lto.h =================================================================== --- llvm/trunk/include/llvm-c/lto.h +++ llvm/trunk/include/llvm-c/lto.h @@ -282,6 +282,8 @@ /** * Returns the number of dependent libraries in the object module. * + * Deprecated. Now returns an empty list. + * * \since LTO_API_VERSION=8 */ extern unsigned int @@ -291,6 +293,8 @@ /** * Returns the ith dependent library in the module. * + * Deprecated. Now always returns null. + * * \since LTO_API_VERSION=8 */ extern const char* @@ -300,6 +304,9 @@ /** * Returns the number of linker options in the object module. * + * Each linker option may consist of multiple flags. It is the linker's + * responsibility to split the flags using a platform-specific mechanism. + * * \since LTO_API_VERSION=8 */ extern unsigned int @@ -309,6 +316,9 @@ /** * Returns the ith linker option in the module. * + * Each linker option may consist of multiple flags. It is the linker's + * responsibility to split the flags using a platform-specific mechanism. + * * \since LTO_API_VERSION=8 */ extern const char* Index: llvm/trunk/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h =================================================================== --- llvm/trunk/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ llvm/trunk/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -90,10 +90,6 @@ ~TargetLoweringObjectFileMachO() override {} TargetLoweringObjectFileMachO(); - /// Extract the dependent library name from a linker option string. Returns - /// StringRef() if the option does not specify a library. - StringRef getDepLibFromLinkerOpt(StringRef LinkerOption) const override; - /// Emit the module flags that specify the garbage collection information. void emitModuleFlags(MCStreamer &Streamer, ArrayRef ModuleFlags, @@ -150,10 +146,6 @@ MCSection *getSectionForJumpTable(const Function &F, Mangler &Mang, const TargetMachine &TM) const override; - /// Extract the dependent library name from a linker option string. Returns - /// StringRef() if the option does not specify a library. - StringRef getDepLibFromLinkerOpt(StringRef LinkerOption) const override; - /// Emit Obj-C garbage collection and linker options. Only linker option /// emission is implemented for COFF. void emitModuleFlags(MCStreamer &Streamer, @@ -164,6 +156,9 @@ const MCSymbol *KeySym) const override; MCSection *getStaticDtorSection(unsigned Priority, const MCSymbol *KeySym) const override; + + void emitLinkerFlagsForGlobal(raw_ostream &OS, const GlobalValue *GV, + const Mangler &Mang) const override; }; } // end namespace llvm Index: llvm/trunk/include/llvm/LTO/LTOModule.h =================================================================== --- llvm/trunk/include/llvm/LTO/LTOModule.h +++ llvm/trunk/include/llvm/LTO/LTOModule.h @@ -47,12 +47,11 @@ std::unique_ptr OwnedContext; + std::string LinkerOpts; + std::unique_ptr IRFile; std::unique_ptr _target; - StringSet<> _linkeropt_strings; - std::vector _deplibs; - std::vector _linkeropts; - std::vector _symbols; + std::vector _symbols; // _defines and _undefines only needed to disambiguate tentative definitions StringSet<> _defines; @@ -149,28 +148,8 @@ return nullptr; } - /// Get the number of dependent libraries - uint32_t getDependentLibraryCount() { - return _deplibs.size(); - } - - /// Get the dependent library at the specified index. - const char *getDependentLibrary(uint32_t index) { - if (index < _deplibs.size()) - return _deplibs[index]; - return nullptr; - } - - /// Get the number of linker options - uint32_t getLinkerOptCount() { - return _linkeropts.size(); - } - - /// Get the linker option at the specified index. - const char *getLinkerOpt(uint32_t index) { - if (index < _linkeropts.size()) - return _linkeropts[index]; - return nullptr; + const char *getLinkerOpts() { + return LinkerOpts.c_str(); } const std::vector &getAsmUndefinedRefs() { Index: llvm/trunk/include/llvm/Target/TargetLoweringObjectFile.h =================================================================== --- llvm/trunk/include/llvm/Target/TargetLoweringObjectFile.h +++ llvm/trunk/include/llvm/Target/TargetLoweringObjectFile.h @@ -64,12 +64,6 @@ const TargetMachine &TM, const MCSymbol *Sym) const; - /// Extract the dependent library name from a linker option string. Returns - /// StringRef() if the option does not specify a library. - virtual StringRef getDepLibFromLinkerOpt(StringRef LinkerOption) const { - return StringRef(); - } - /// Emit the module flags that the platform cares about. virtual void emitModuleFlags(MCStreamer &Streamer, ArrayRef Flags, @@ -188,6 +182,9 @@ return nullptr; } + virtual void emitLinkerFlagsForGlobal(raw_ostream &OS, const GlobalValue *GV, + const Mangler &Mang) const {} + protected: virtual MCSection *SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, Mangler &Mang, Index: llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp =================================================================== --- llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -440,16 +440,6 @@ 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 @@ 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 ModuleFlags, @@ -1045,3 +1027,36 @@ return getContext().getAssociativeCOFFSection( cast(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"; + } +} Index: llvm/trunk/lib/LTO/LTOModule.cpp =================================================================== --- llvm/trunk/lib/LTO/LTOModule.cpp +++ llvm/trunk/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 @@ /// 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(Val); @@ -649,20 +652,19 @@ MDNode *MDOptions = cast(LinkerOptions->getOperand(i)); for (unsigned ii = 0, ie = MDOptions->getNumOperands(); ii != ie; ++ii) { MDString *MDOption = cast(MDOptions->getOperand(ii)); - // FIXME: Make StringSet::insert match Self-Associative Container - // requirements, returning 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. } Index: llvm/trunk/lib/Target/X86/X86AsmPrinter.h =================================================================== --- llvm/trunk/lib/Target/X86/X86AsmPrinter.h +++ llvm/trunk/lib/Target/X86/X86AsmPrinter.h @@ -30,8 +30,6 @@ 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 Index: llvm/trunk/lib/Target/X86/X86AsmPrinter.cpp =================================================================== --- llvm/trunk/lib/Target/X86/X86AsmPrinter.cpp +++ llvm/trunk/lib/Target/X86/X86AsmPrinter.cpp @@ -581,34 +581,6 @@ 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 @@ } if (TT.isOSBinFormatCOFF()) { - // Necessary for dllexport support - std::vector DLLExportedFns, DLLExportedGlobals; + const TargetLoweringObjectFileCOFF &TLOFCOFF = + static_cast(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(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(); Index: llvm/trunk/test/CodeGen/X86/dllexport-x86_64.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/dllexport-x86_64.ll +++ llvm/trunk/test/CodeGen/X86/dllexport-x86_64.ll @@ -71,33 +71,33 @@ @blob_alias = dllexport alias bitcast ([6 x i8]* @blob to i32 ()*) ; CHECK: .section .drectve -; WIN32: " /EXPORT:Var1,DATA" -; WIN32: " /EXPORT:Var2,DATA" -; WIN32: " /EXPORT:Var3,DATA" -; WIN32: " /EXPORT:WeakVar1,DATA" -; WIN32: " /EXPORT:WeakVar2,DATA" -; WIN32: " /EXPORT:f1" -; WIN32: " /EXPORT:f2" -; WIN32: " /EXPORT:lnk1" -; WIN32: " /EXPORT:lnk2" -; WIN32: " /EXPORT:weak1" -; WIN32: " /EXPORT:alias" -; WIN32: " /EXPORT:alias2" -; WIN32: " /EXPORT:alias3" -; WIN32: " /EXPORT:weak_alias" -; WIN32: " /EXPORT:blob_alias" -; MINGW: " -export:Var1,data" -; MINGW: " -export:Var2,data" -; MINGW: " -export:Var3,data" -; MINGW: " -export:WeakVar1,data" -; MINGW: " -export:WeakVar2,data" -; MINGW: " -export:f1" -; MINGW: " -export:f2" -; MINGW: " -export:lnk1" -; MINGW: " -export:lnk2" -; MINGW: " -export:weak1" -; MINGW: " -export:alias" -; MINGW: " -export:alias2" -; MINGW: " -export:alias3" -; MINGW: " -export:weak_alias" -; MINGW: " -export:blob_alias" +; WIN32: /EXPORT:f1 +; WIN32-SAME: /EXPORT:f2 +; WIN32-SAME: /EXPORT:lnk1 +; WIN32-SAME: /EXPORT:lnk2 +; WIN32-SAME: /EXPORT:weak1 +; WIN32-SAME: /EXPORT:Var1,DATA +; WIN32-SAME: /EXPORT:Var2,DATA +; WIN32-SAME: /EXPORT:Var3,DATA +; WIN32-SAME: /EXPORT:WeakVar1,DATA +; WIN32-SAME: /EXPORT:WeakVar2,DATA +; WIN32-SAME: /EXPORT:alias +; WIN32-SAME: /EXPORT:alias2 +; WIN32-SAME: /EXPORT:alias3 +; WIN32-SAME: /EXPORT:weak_alias +; WIN32-SAME: /EXPORT:blob_alias +; MINGW: -export:f1 +; MINGW-SAME: -export:f2 +; MINGW-SAME: -export:lnk1 +; MINGW-SAME: -export:lnk2 +; MINGW-SAME: -export:weak1 +; MINGW-SAME: -export:Var1,data +; MINGW-SAME: -export:Var2,data +; MINGW-SAME: -export:Var3,data +; MINGW-SAME: -export:WeakVar1,data +; MINGW-SAME: -export:WeakVar2,data +; MINGW-SAME: -export:alias +; MINGW-SAME: -export:alias2 +; MINGW-SAME: -export:alias3 +; MINGW-SAME: -export:weak_alias +; MINGW-SAME: -export:blob_alias" Index: llvm/trunk/test/CodeGen/X86/dllexport.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/dllexport.ll +++ llvm/trunk/test/CodeGen/X86/dllexport.ll @@ -89,40 +89,41 @@ @weak_alias = weak_odr dllexport alias void()* @f1 ; CHECK: .section .drectve -; CHECK-CL: " /EXPORT:_Var1,DATA" -; CHECK-CL: " /EXPORT:_Var2,DATA" -; CHECK-CL: " /EXPORT:_Var3,DATA" -; CHECK-CL: " /EXPORT:_WeakVar1,DATA" -; CHECK-CL: " /EXPORT:_WeakVar2,DATA" -; CHECK-CL: " /EXPORT:_f1" -; CHECK-CL: " /EXPORT:_f2" ; CHECK-CL-NOT: not_exported -; CHECK-CL: " /EXPORT:_stdfun@0" -; CHECK-CL: " /EXPORT:@fastfun@0" -; CHECK-CL: " /EXPORT:_thisfun" -; CHECK-CL: " /EXPORT:_lnk1" -; CHECK-CL: " /EXPORT:_lnk2" -; CHECK-CL: " /EXPORT:_weak1" -; CHECK-CL: " /EXPORT:_alias" -; CHECK-CL: " /EXPORT:_alias2" -; CHECK-CL: " /EXPORT:_alias3" -; CHECK-CL: " /EXPORT:_weak_alias" -; CHECK-GCC: " -export:Var1,data" -; CHECK-GCC: " -export:Var2,data" -; CHECK-GCC: " -export:Var3,data" -; CHECK-GCC: " -export:WeakVar1,data" -; CHECK-GCC: " -export:WeakVar2,data" -; CHECK-GCC: " -export:f1" -; CHECK-GCC: " -export:f2" +; CHECK-CL: /EXPORT:_f1 +; CHECK-CL-SAME: /EXPORT:_f2 +; CHECK-CL-SAME: /EXPORT:_stdfun@0 +; CHECK-CL-SAME: /EXPORT:@fastfun@0 +; CHECK-CL-SAME: /EXPORT:_thisfun +; CHECK-CL-SAME: /EXPORT:_lnk1 +; CHECK-CL-SAME: /EXPORT:_lnk2 +; CHECK-CL-SAME: /EXPORT:_weak1 +; CHECK-CL-SAME: /EXPORT:_Var1,DATA +; CHECK-CL-SAME: /EXPORT:_Var2,DATA +; CHECK-CL-SAME: /EXPORT:_Var3,DATA +; CHECK-CL-SAME: /EXPORT:_WeakVar1,DATA +; CHECK-CL-SAME: /EXPORT:_WeakVar2,DATA +; CHECK-CL-SAME: /EXPORT:_alias +; CHECK-CL-SAME: /EXPORT:_alias2 +; CHECK-CL-SAME: /EXPORT:_alias3 +; CHECK-CL-SAME: /EXPORT:_weak_alias" ; CHECK-CL-NOT: not_exported -; CHECK-GCC: " -export:stdfun@0" -; CHECK-GCC: " -export:@fastfun@0" -; CHECK-GCC: " -export:thisfun" -; CHECK-GCC: " -export:lnk1" -; CHECK-GCC: " -export:lnk2" -; CHECK-GCC: " -export:weak1" -; CHECK-GCC: " -export:alias" -; CHECK-GCC: " -export:alias2" -; CHECK-GCC: " -export:alias3" -; CHECK-GCC: " -export:weak_alias" - +; CHECK-GCC-NOT: not_exported +; CHECK-GCC: -export:f1 +; CHECK-GCC-SAME: -export:f2 +; CHECK-GCC-SAME: -export:stdfun@0 +; CHECK-GCC-SAME: -export:@fastfun@0 +; CHECK-GCC-SAME: -export:thisfun +; CHECK-GCC-SAME: -export:lnk1 +; CHECK-GCC-SAME: -export:lnk2 +; CHECK-GCC-SAME: -export:weak1 +; CHECK-GCC-SAME: -export:Var1,data +; CHECK-GCC-SAME: -export:Var2,data +; CHECK-GCC-SAME: -export:Var3,data +; CHECK-GCC-SAME: -export:WeakVar1,data +; CHECK-GCC-SAME: -export:WeakVar2,data +; CHECK-GCC-SAME: -export:alias +; CHECK-GCC-SAME: -export:alias2 +; CHECK-GCC-SAME: -export:alias3 +; CHECK-GCC-SAME: -export:weak_alias" +; CHECK-GCC-NOT: not_exported Index: llvm/trunk/tools/lto/lto.cpp =================================================================== --- llvm/trunk/tools/lto/lto.cpp +++ llvm/trunk/tools/lto/lto.cpp @@ -224,19 +224,21 @@ } unsigned int lto_module_get_num_deplibs(lto_module_t mod) { - return unwrap(mod)->getDependentLibraryCount(); + return 0; } const char* lto_module_get_deplib(lto_module_t mod, unsigned int index) { - return unwrap(mod)->getDependentLibrary(index); + return nullptr; } unsigned int lto_module_get_num_linkeropts(lto_module_t mod) { - return unwrap(mod)->getLinkerOptCount(); + return 1; } const char* lto_module_get_linkeropt(lto_module_t mod, unsigned int index) { - return unwrap(mod)->getLinkerOpt(index); + if (index != 0) + return nullptr; + return unwrap(mod)->getLinkerOpts(); } void lto_codegen_set_diagnostic_handler(lto_code_gen_t cg,