MCSection *getStaticDtorSection(unsigned Priority,
const MCSymbol *KeySym) const override;
- void emitLinkerFlagsForGlobal(raw_ostream &OS,
- const GlobalValue *GV) const override;
-
- void emitLinkerFlagsForUsed(raw_ostream &OS,
- const GlobalValue *GV) const override;
-
const MCExpr *lowerRelativeReference(const GlobalValue *LHS,
const GlobalValue *RHS,
const TargetMachine &TM) const override;
MCSection *getSectionForConstant(const DataLayout &DL, SectionKind Kind,
const Constant *C,
Align &Alignment) const override;
+
+private:
+ void emitLinkerDirectives(MCStreamer &Streamer, Module &M) const;
};
class TargetLoweringObjectFileWasm : public TargetLoweringObjectFile {
return nullptr;
}
- virtual void emitLinkerFlagsForGlobal(raw_ostream &OS,
- const GlobalValue *GV) const {}
-
- virtual void emitLinkerFlagsForUsed(raw_ostream &OS,
- const GlobalValue *GV) const {}
-
/// If supported, return the section to use for the llvm.commandline
/// metadata. Otherwise, return nullptr.
virtual MCSection *getSectionForCommandLines() const {
if (MCSection *S = MAI->getNonexecutableStackSection(OutContext))
OutStreamer->SwitchSection(S);
- if (TM.getTargetTriple().isOSBinFormatCOFF()) {
- // Emit /EXPORT: flags for each exported global as necessary.
- const auto &TLOF = getObjFileLowering();
- std::string Flags;
-
- for (const GlobalValue &GV : M.global_values()) {
- raw_string_ostream OS(Flags);
- TLOF.emitLinkerFlagsForGlobal(OS, &GV);
- OS.flush();
- if (!Flags.empty()) {
- OutStreamer->SwitchSection(TLOF.getDrectveSection());
- OutStreamer->emitBytes(Flags);
- }
- Flags.clear();
- }
-
- // Emit /INCLUDE: flags for each used global as necessary.
- if (const auto *LU = M.getNamedGlobal("llvm.used")) {
- assert(LU->hasInitializer() &&
- "expected llvm.used to have an initializer");
- assert(isa<ArrayType>(LU->getValueType()) &&
- "expected llvm.used to be an array type");
- if (const auto *A = cast<ConstantArray>(LU->getInitializer())) {
- for (const Value *Op : A->operands()) {
- const auto *GV = cast<GlobalValue>(Op->stripPointerCasts());
- // Global symbols with internal or private linkage are not visible to
- // the linker, and thus would cause an error when the linker tried to
- // preserve the symbol due to the `/include:` directive.
- if (GV->hasLocalLinkage())
- continue;
-
- raw_string_ostream OS(Flags);
- TLOF.emitLinkerFlagsForUsed(OS, GV);
- OS.flush();
-
- if (!Flags.empty()) {
- OutStreamer->SwitchSection(TLOF.getDrectveSection());
- OutStreamer->emitBytes(Flags);
- }
- Flags.clear();
- }
- }
- }
- }
-
if (TM.Options.EmitAddrsig) {
// Emit address-significance attributes for all globals.
OutStreamer->emitAddrsig();
void TargetLoweringObjectFileCOFF::emitModuleMetadata(MCStreamer &Streamer,
Module &M) const {
- if (NamedMDNode *LinkerOptions = M.getNamedMetadata("llvm.linker.options")) {
- // Emit the linker options to the linker .drectve section. According to the
- // spec, this section is a space-separated string containing flags for
- // linker.
- MCSection *Sec = getDrectveSection();
- Streamer.SwitchSection(Sec);
- for (const auto *Option : LinkerOptions->operands()) {
- for (const auto &Piece : cast<MDNode>(Option)->operands()) {
- // Lead with a space for consistency with our dllexport implementation.
- std::string Directive(" ");
- Directive.append(std::string(cast<MDString>(Piece)->getString()));
- Streamer.emitBytes(Directive);
- }
- }
- }
+ emitLinkerDirectives(Streamer, M);
unsigned Version = 0;
unsigned Flags = 0;
emitCGProfile(Streamer, M);
}
+void TargetLoweringObjectFileCOFF::emitLinkerDirectives(
+ MCStreamer &Streamer, Module &M) const {
+ if (NamedMDNode *LinkerOptions = M.getNamedMetadata("llvm.linker.options")) {
+ // Emit the linker options to the linker .drectve section. According to the
+ // spec, this section is a space-separated string containing flags for
+ // linker.
+ MCSection *Sec = getDrectveSection();
+ Streamer.SwitchSection(Sec);
+ for (const auto *Option : LinkerOptions->operands()) {
+ for (const auto &Piece : cast<MDNode>(Option)->operands()) {
+ // Lead with a space for consistency with our dllexport implementation.
+ std::string Directive(" ");
+ Directive.append(std::string(cast<MDString>(Piece)->getString()));
+ Streamer.emitBytes(Directive);
+ }
+ }
+ }
+
+ // Emit /EXPORT: flags for each exported global as necessary.
+ std::string Flags;
+ for (const GlobalValue &GV : M.global_values()) {
+ raw_string_ostream OS(Flags);
+ emitLinkerFlagsForGlobalCOFF(OS, &GV, getTargetTriple(), getMangler());
+ OS.flush();
+ if (!Flags.empty()) {
+ Streamer.SwitchSection(getDrectveSection());
+ Streamer.emitBytes(Flags);
+ }
+ Flags.clear();
+ }
+
+ // Emit /INCLUDE: flags for each used global as necessary.
+ if (const auto *LU = M.getNamedGlobal("llvm.used")) {
+ assert(LU->hasInitializer() && "expected llvm.used to have an initializer");
+ assert(isa<ArrayType>(LU->getValueType()) &&
+ "expected llvm.used to be an array type");
+ if (const auto *A = cast<ConstantArray>(LU->getInitializer())) {
+ for (const Value *Op : A->operands()) {
+ const auto *GV = cast<GlobalValue>(Op->stripPointerCasts());
+ // Global symbols with internal or private linkage are not visible to
+ // the linker, and thus would cause an error when the linker tried to
+ // preserve the symbol due to the `/include:` directive.
+ if (GV->hasLocalLinkage())
+ continue;
+
+ raw_string_ostream OS(Flags);
+ emitLinkerFlagsForUsedCOFF(OS, GV, getTargetTriple(), getMangler());
+ OS.flush();
+
+ if (!Flags.empty()) {
+ Streamer.SwitchSection(getDrectveSection());
+ Streamer.emitBytes(Flags);
+ }
+ Flags.clear();
+ }
+ }
+ }
+}
+
void TargetLoweringObjectFileCOFF::Initialize(MCContext &Ctx,
const TargetMachine &TM) {
TargetLoweringObjectFile::Initialize(Ctx, TM);
cast<MCSectionCOFF>(StaticDtorSection));
}
-void TargetLoweringObjectFileCOFF::emitLinkerFlagsForGlobal(
- raw_ostream &OS, const GlobalValue *GV) const {
- emitLinkerFlagsForGlobalCOFF(OS, GV, getTargetTriple(), getMangler());
-}
-
-void TargetLoweringObjectFileCOFF::emitLinkerFlagsForUsed(
- raw_ostream &OS, const GlobalValue *GV) const {
- emitLinkerFlagsForUsedCOFF(OS, GV, getTargetTriple(), getMangler());
-}
-
const MCExpr *TargetLoweringObjectFileCOFF::lowerRelativeReference(
const GlobalValue *LHS, const GlobalValue *RHS,
const TargetMachine &TM) const {
}
; CHECK: .lcomm .L_MergedGlobals,8,4
+; CHECK: .section .drectve,"yn"
+; CHECK: .ascii " /EXPORT:y,DATA"
; CHECK: .globl x
; CHECK: .set x, .L_MergedGlobals
; CHECK: .globl y
; CHECK: .set y, .L_MergedGlobals+4
-; CHECK: .section .drectve,"yn"
-; CHECK: .ascii " /EXPORT:y,DATA"
@WeakVar3 = weak_odr dllexport global i32 0, align 4
-; CHECK: .globl alias
-; CHECK: .set alias, notExported
-@alias = dllexport alias void(), void()* @notExported
-
-; CHECK: .globl aliasNotExported
-; CHECK: .set aliasNotExported, f1
-@aliasNotExported = alias void(), void()* @f1
-
-; CHECK: .globl alias2
-; CHECK: .set alias2, f1
-@alias2 = dllexport alias void(), void()* @f1
-
-; CHECK: .globl alias3
-; CHECK: .set alias3, notExported
-@alias3 = dllexport alias void(), void()* @notExported
-
-; CHECK: .weak weak_alias
-; CHECK: .set weak_alias, f1
-@weak_alias = weak_odr dllexport alias void(), void()* @f1
-
-@blob = global [6 x i8] c"\B8*\00\00\00\C3", section ".text", align 16
-@blob_alias = dllexport alias i32 (), bitcast ([6 x i8]* @blob to i32 ()*)
-
-@exportedButNotDefinedVariable = external dllexport global i32
-declare dllexport void @exportedButNotDefinedFunction()
-define void @foo() {
-entry:
- store i32 4, i32* @exportedButNotDefinedVariable, align 4
- call void @exportedButNotDefinedFunction()
- ret void
-}
-
; Verify items that should not be exported do not appear in the export table.
; We use a separate check prefix to avoid confusion between -NOT and -SAME.
; NOTEXPORTED: .section .drectve
-; NOTEXPORTED-NOT: notExported
-; NOTEXPORTED-NOT: aliasNotExported
-; NOTEXPORTED-NOT: exportedButNotDefinedVariable
-; NOTEXPORTED-NOT: exportedButNotDefinedFunction
+; NOTEXPORTED-NOT: :notExported
+; NOTEXPORTED-NOT: :aliasNotExported
+; NOTEXPORTED-NOT: :exportedButNotDefinedVariable
+; NOTEXPORTED-NOT: :exportedButNotDefinedFunction
; CHECK: .section .drectve
; WIN32: .ascii " /EXPORT:f1"
; MINGW: .ascii " -export:alias3"
; MINGW: .ascii " -export:weak_alias"
; MINGW: .ascii " -export:blob_alias"
+
+; CHECK: .globl alias
+; CHECK: .set alias, notExported
+@alias = dllexport alias void(), void()* @notExported
+
+; CHECK: .globl aliasNotExported
+; CHECK: .set aliasNotExported, f1
+@aliasNotExported = alias void(), void()* @f1
+
+; CHECK: .globl alias2
+; CHECK: .set alias2, f1
+@alias2 = dllexport alias void(), void()* @f1
+
+; CHECK: .globl alias3
+; CHECK: .set alias3, notExported
+@alias3 = dllexport alias void(), void()* @notExported
+
+; CHECK: .weak weak_alias
+; CHECK: .set weak_alias, f1
+@weak_alias = weak_odr dllexport alias void(), void()* @f1
+
+@blob = global [6 x i8] c"\B8*\00\00\00\C3", section ".text", align 16
+@blob_alias = dllexport alias i32 (), bitcast ([6 x i8]* @blob to i32 ()*)
+
+@exportedButNotDefinedVariable = external dllexport global i32
+declare dllexport void @exportedButNotDefinedFunction()
+define void @foo() {
+entry:
+ store i32 4, i32* @exportedButNotDefinedVariable, align 4
+ call void @exportedButNotDefinedFunction()
+ ret void
+}
@WeakVar2 = weak_odr dllexport unnamed_addr constant i32 1
-; CHECK: .globl _alias
-; CHECK: .set _alias, _notExported
-@alias = dllexport alias void(), void()* @notExported
-
-; CHECK: .globl _alias2
-; CHECK: .set _alias2, _f1
-@alias2 = dllexport alias void(), void()* @f1
-
-; CHECK: .globl _alias3
-; CHECK: .set _alias3, _notExported
-@alias3 = dllexport alias void(), void()* @notExported
-
-; CHECK: .weak _weak_alias
-; CHECK: .set _weak_alias, _f1
-@weak_alias = weak_odr dllexport alias void(), void()* @f1
-
; Verify items that should not be exported do not appear in the export table.
; We use a separate check prefix to avoid confusion between -NOT and -SAME.
; NOTEXPORTED: .section .drectve
-; NOTEXPORTED-NOT: notExported
-; NOTEXPORTED-NOT: notDefined
+; NOTEXPORTED-NOT: :notExported
+; NOTEXPORTED-NOT: :notDefined
; CHECK: .section .drectve
; CHECK-CL: .ascii " /EXPORT:_f1"
; CHECK-GCC: .ascii " -export:alias2"
; CHECK-GCC: .ascii " -export:alias3"
; CHECK-GCC: .ascii " -export:weak_alias"
+
+; CHECK: .globl _alias
+; CHECK: .set _alias, _notExported
+@alias = dllexport alias void(), void()* @notExported
+
+; CHECK: .globl _alias2
+; CHECK: .set _alias2, _f1
+@alias2 = dllexport alias void(), void()* @f1
+
+; CHECK: .globl _alias3
+; CHECK: .set _alias3, _notExported
+@alias3 = dllexport alias void(), void()* @notExported
+
+; CHECK: .weak _weak_alias
+; CHECK: .set _weak_alias, _f1
+@weak_alias = weak_odr dllexport alias void(), void()* @f1