From 9932561b4892b6e9bbb0c2369272dfff2305fdb9 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Fri, 18 Sep 2020 13:43:13 -0700 Subject: [PATCH] [COFF] Move per-global .drective emission from AsmPrinter to TLOFCOFF This changes the order of output sections and the output assembly, but is otherwise NFC. It simplifies the TLOF interface by removing two COFF-only methods. --- .../llvm/CodeGen/TargetLoweringObjectFileImpl.h | 9 +-- .../include/llvm/Target/TargetLoweringObjectFile.h | 6 -- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 45 ------------ llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp | 85 +++++++++++++++------- llvm/test/CodeGen/ARM/global-merge-dllexport.ll | 4 +- llvm/test/CodeGen/X86/dllexport-x86_64.ll | 72 +++++++++--------- llvm/test/CodeGen/X86/dllexport.ll | 36 ++++----- 7 files changed, 119 insertions(+), 138 deletions(-) diff --git a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h index bc2173e..4f3e1dd 100644 --- a/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ b/llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -167,12 +167,6 @@ public: 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; @@ -182,6 +176,9 @@ public: 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 { diff --git a/llvm/include/llvm/Target/TargetLoweringObjectFile.h b/llvm/include/llvm/Target/TargetLoweringObjectFile.h index 033b3c9..0c8f683 100644 --- a/llvm/include/llvm/Target/TargetLoweringObjectFile.h +++ b/llvm/include/llvm/Target/TargetLoweringObjectFile.h @@ -208,12 +208,6 @@ public: 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 { diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 7d8355c..bd304d7 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1720,51 +1720,6 @@ bool AsmPrinter::doFinalization(Module &M) { 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(LU->getValueType()) && - "expected llvm.used to be an array type"); - if (const auto *A = cast(LU->getInitializer())) { - for (const Value *Op : A->operands()) { - const auto *GV = cast(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(); diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp index 08dfbd1..0c43ec8 100644 --- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -1551,21 +1551,7 @@ MCSection *TargetLoweringObjectFileCOFF::getSectionForJumpTable( 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(Option)->operands()) { - // Lead with a space for consistency with our dllexport implementation. - std::string Directive(" "); - Directive.append(std::string(cast(Piece)->getString())); - Streamer.emitBytes(Directive); - } - } - } + emitLinkerDirectives(Streamer, M); unsigned Version = 0; unsigned Flags = 0; @@ -1588,6 +1574,65 @@ void TargetLoweringObjectFileCOFF::emitModuleMetadata(MCStreamer &Streamer, 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(Option)->operands()) { + // Lead with a space for consistency with our dllexport implementation. + std::string Directive(" "); + Directive.append(std::string(cast(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(LU->getValueType()) && + "expected llvm.used to be an array type"); + if (const auto *A = cast(LU->getInitializer())) { + for (const Value *Op : A->operands()) { + const auto *GV = cast(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); @@ -1665,16 +1710,6 @@ MCSection *TargetLoweringObjectFileCOFF::getStaticDtorSection( cast(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 { diff --git a/llvm/test/CodeGen/ARM/global-merge-dllexport.ll b/llvm/test/CodeGen/ARM/global-merge-dllexport.ll index d9bbaf9..98d7525 100644 --- a/llvm/test/CodeGen/ARM/global-merge-dllexport.ll +++ b/llvm/test/CodeGen/ARM/global-merge-dllexport.ll @@ -13,9 +13,9 @@ define void @f1(i32 %a1, i32 %a2) { } ; 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" diff --git a/llvm/test/CodeGen/X86/dllexport-x86_64.ll b/llvm/test/CodeGen/X86/dllexport-x86_64.ll index 9f427f6..6205cff 100644 --- a/llvm/test/CodeGen/X86/dllexport-x86_64.ll +++ b/llvm/test/CodeGen/X86/dllexport-x86_64.ll @@ -61,45 +61,13 @@ define weak_odr dllexport void @weak1() { @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" @@ -134,3 +102,35 @@ entry: ; 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 +} diff --git a/llvm/test/CodeGen/X86/dllexport.ll b/llvm/test/CodeGen/X86/dllexport.ll index f08395a..a54fea1 100644 --- a/llvm/test/CodeGen/X86/dllexport.ll +++ b/llvm/test/CodeGen/X86/dllexport.ll @@ -82,27 +82,11 @@ define weak_odr dllexport void @weak1() { @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" @@ -139,3 +123,19 @@ define weak_odr dllexport void @weak1() { ; 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 -- 2.7.4