[COFF] Move per-global .drective emission from AsmPrinter to TLOFCOFF
authorReid Kleckner <rnk@google.com>
Fri, 18 Sep 2020 20:43:13 +0000 (13:43 -0700)
committerReid Kleckner <rnk@google.com>
Fri, 18 Sep 2020 21:31:01 +0000 (14:31 -0700)
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/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
llvm/include/llvm/Target/TargetLoweringObjectFile.h
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
llvm/test/CodeGen/ARM/global-merge-dllexport.ll
llvm/test/CodeGen/X86/dllexport-x86_64.ll
llvm/test/CodeGen/X86/dllexport.ll

index bc2173e..4f3e1dd 100644 (file)
@@ -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 {
index 033b3c9..0c8f683 100644 (file)
@@ -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 {
index 7d8355c..bd304d7 100644 (file)
@@ -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<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();
index 08dfbd1..0c43ec8 100644 (file)
@@ -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<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;
@@ -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<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);
@@ -1665,16 +1710,6 @@ MCSection *TargetLoweringObjectFileCOFF::getStaticDtorSection(
                                       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 {
index d9bbaf9..98d7525 100644 (file)
@@ -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"
index 9f427f6..6205cff 100644 (file)
@@ -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
+}
index f08395a..a54fea1 100644 (file)
@@ -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