/**
* Returns the number of dependent libraries in the object module.
*
+ * Deprecated. Now returns an empty list.
+ *
* \since LTO_API_VERSION=8
*/
extern unsigned int
/**
* Returns the ith dependent library in the module.
*
+ * Deprecated. Now always returns null.
+ *
* \since LTO_API_VERSION=8
*/
extern const char*
/**
* 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
/**
* 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*
~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<Module::ModuleFlagEntry> ModuleFlags,
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,
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
std::unique_ptr<LLVMContext> OwnedContext;
+ std::string LinkerOpts;
+
std::unique_ptr<object::IRObjectFile> IRFile;
std::unique_ptr<TargetMachine> _target;
- StringSet<> _linkeropt_strings;
- std::vector<const char *> _deplibs;
- std::vector<const char *> _linkeropts;
- std::vector<NameAndAttributes> _symbols;
+ std::vector<NameAndAttributes> _symbols;
// _defines and _undefines only needed to disambiguate tentative definitions
StringSet<> _defines;
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<const char*> &getAsmUndefinedRefs() {
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<Module::ModuleFlagEntry> Flags,
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,
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,
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,
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";
+ }
+}
#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"
/// 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);
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.
}
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();
}
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();
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
@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"
@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
}
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,