[llvm] 8042699 - [LLVM] Add exported visibility style for XCOFF

David Tenty via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 28 11:56:38 PDT 2022


Author: David Tenty
Date: 2022-04-28T14:56:00-04:00
New Revision: 8042699a3088280292066a2fb1869f372369301f

URL: https://github.com/llvm/llvm-project/commit/8042699a3088280292066a2fb1869f372369301f
DIFF: https://github.com/llvm/llvm-project/commit/8042699a3088280292066a2fb1869f372369301f.diff

LOG: [LLVM] Add exported visibility style for XCOFF

For the AIX linker, under default options, global or weak symbols which
have no visibility bits set to zero (i.e. no visibility, similar to ELF
default) are only exported if specified on an export list provided to
the linker. So AIX has an additional visibility style called
"exported" which indicates to the linker that the symbol should
be explicitly globally exported.

This change maps "dllexport" in the LLVM IR to correspond to XCOFF
exported as we feel this best models the intended semantic (discussion
on the discourse RFC thread: https://discourse.llvm.org/t/rfc-adding-exported-visibility-style-to-the-ir-to-model-xcoff-exported-visibility/61853)
and allows us to enable writing this visibility for the AIX target
in the assembly path.

Reviewed By: DiggerLin

Differential Revision: https://reviews.llvm.org/D123951

Added: 
    llvm/test/CodeGen/PowerPC/aix-xcoff-exported-nondefault.ll

Modified: 
    llvm/docs/LangRef.rst
    llvm/include/llvm/MC/MCAsmInfo.h
    llvm/include/llvm/MC/MCDirectives.h
    llvm/lib/MC/MCAsmStreamer.cpp
    llvm/lib/MC/MCELFStreamer.cpp
    llvm/lib/MC/MCMachOStreamer.cpp
    llvm/lib/MC/MCWasmStreamer.cpp
    llvm/lib/MC/MCXCOFFStreamer.cpp
    llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
    llvm/test/CodeGen/PowerPC/aix-xcoff-visibility.ll

Removed: 
    


################################################################################
diff  --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 041b51418eb89..9812ce3da6b69 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -481,7 +481,10 @@ styles:
     means that the declaration is visible to other modules and, in
     shared libraries, means that the declared entity may be overridden.
     On Darwin, default visibility means that the declaration is visible
-    to other modules. Default visibility corresponds to "external
+    to other modules. On XCOFF, default visibility means no explicit
+    visibility bit will be set and whether the symbol is visible
+    (i.e "exported") to other modules depends primarily on export lists
+    provided to the linker. Default visibility corresponds to "external
     linkage" in the language.
 "``hidden``" - Hidden style
     Two declarations of an object with hidden visibility refer to the
@@ -512,12 +515,15 @@ DLL storage class:
     symbol. On Microsoft Windows targets, the pointer name is formed by
     combining ``__imp_`` and the function or variable name.
 ``dllexport``
-    "``dllexport``" causes the compiler to provide a global pointer to a pointer
-    in a DLL, so that it can be referenced with the ``dllimport`` attribute. On
-    Microsoft Windows targets, the pointer name is formed by combining
-    ``__imp_`` and the function or variable name. Since this storage class
-    exists for defining a dll interface, the compiler, assembler and linker know
-    it is externally referenced and must refrain from deleting the symbol.
+    On Microsoft Windows targets, "``dllexport``" causes the compiler to provide
+    a global pointer to a pointer in a DLL, so that it can be referenced with the
+    ``dllimport`` attribute. the pointer name is formed by combining ``__imp_``
+    and the function or variable name. On XCOFF targets, ``dllexport`` indicates
+    that the symbol will be made visible to other modules using "exported"
+    visibility and thus placed by the linker in the loader section symbol table.
+    Since this storage class exists for defining a dll interface, the compiler,
+    assembler and linker know it is externally referenced and must refrain from
+    deleting the symbol.
 
 .. _tls_model:
 

diff  --git a/llvm/include/llvm/MC/MCAsmInfo.h b/llvm/include/llvm/MC/MCAsmInfo.h
index 08b5b3ebd355f..ec17131e17e81 100644
--- a/llvm/include/llvm/MC/MCAsmInfo.h
+++ b/llvm/include/llvm/MC/MCAsmInfo.h
@@ -430,6 +430,10 @@ class MCAsmInfo {
   /// hidden visibility.  Defaults to MCSA_Hidden.
   MCSymbolAttr HiddenVisibilityAttr = MCSA_Hidden;
 
+  /// This attribute, if not MCSA_Invalid, is used to declare a symbol as having
+  /// exported visibility.  Defaults to MCSA_Exported.
+  MCSymbolAttr ExportedVisibilityAttr = MCSA_Exported;
+
   /// This attribute, if not MCSA_Invalid, is used to declare an undefined
   /// symbol as having hidden visibility. Defaults to MCSA_Hidden.
   MCSymbolAttr HiddenDeclarationVisibilityAttr = MCSA_Hidden;
@@ -758,6 +762,8 @@ class MCAsmInfo {
 
   MCSymbolAttr getHiddenVisibilityAttr() const { return HiddenVisibilityAttr; }
 
+  MCSymbolAttr getExportedVisibilityAttr() const { return ExportedVisibilityAttr; }
+
   MCSymbolAttr getHiddenDeclarationVisibilityAttr() const {
     return HiddenDeclarationVisibilityAttr;
   }

diff  --git a/llvm/include/llvm/MC/MCDirectives.h b/llvm/include/llvm/MC/MCDirectives.h
index 51e57ad370215..d6ab29febeeb6 100644
--- a/llvm/include/llvm/MC/MCDirectives.h
+++ b/llvm/include/llvm/MC/MCDirectives.h
@@ -31,6 +31,7 @@ enum MCSymbolAttr {
   MCSA_LGlobal,                 ///< .lglobl (XCOFF)
   MCSA_Extern,                  ///< .extern (XCOFF)
   MCSA_Hidden,                  ///< .hidden (ELF)
+  MCSA_Exported,                ///< .globl _foo, exported (XCOFF)
   MCSA_IndirectSymbol,          ///< .indirect_symbol (MachO)
   MCSA_Internal,                ///< .internal (ELF)
   MCSA_LazyReference,           ///< .lazy_reference (MachO)

diff  --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp
index d73025d2d26cc..0f320bd07a751 100644
--- a/llvm/lib/MC/MCAsmStreamer.cpp
+++ b/llvm/lib/MC/MCAsmStreamer.cpp
@@ -762,6 +762,8 @@ bool MCAsmStreamer::emitSymbolAttribute(MCSymbol *Symbol,
   case MCSA_WeakDefAutoPrivate: OS << "\t.weak_def_can_be_hidden\t"; break;
   case MCSA_Cold:
     // Assemblers currently do not support a .cold directive.
+  case MCSA_Exported:
+    // Non-AIX assemblers currently do not support exported visibility.
     return false;
   }
 
@@ -904,6 +906,9 @@ void MCAsmStreamer::emitXCOFFSymbolLinkageWithVisibility(
   case MCSA_Protected:
     OS << ",protected";
     break;
+  case MCSA_Exported:
+    OS << ",exported";
+    break;
   default:
     report_fatal_error("unexpected value for Visibility type");
   }

diff  --git a/llvm/lib/MC/MCELFStreamer.cpp b/llvm/lib/MC/MCELFStreamer.cpp
index fbf3c860368a3..e287f8f51abbd 100644
--- a/llvm/lib/MC/MCELFStreamer.cpp
+++ b/llvm/lib/MC/MCELFStreamer.cpp
@@ -215,6 +215,7 @@ bool MCELFStreamer::emitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {
   case MCSA_WeakDefAutoPrivate:
   case MCSA_Invalid:
   case MCSA_IndirectSymbol:
+  case MCSA_Exported:
     return false;
 
   case MCSA_NoDeadStrip:

diff  --git a/llvm/lib/MC/MCMachOStreamer.cpp b/llvm/lib/MC/MCMachOStreamer.cpp
index 52e88b1007fc6..f5c40fa0cdfb3 100644
--- a/llvm/lib/MC/MCMachOStreamer.cpp
+++ b/llvm/lib/MC/MCMachOStreamer.cpp
@@ -358,6 +358,7 @@ bool MCMachOStreamer::emitSymbolAttribute(MCSymbol *Sym,
   case MCSA_Weak:
   case MCSA_Local:
   case MCSA_LGlobal:
+  case MCSA_Exported:
     return false;
 
   case MCSA_Global:

diff  --git a/llvm/lib/MC/MCWasmStreamer.cpp b/llvm/lib/MC/MCWasmStreamer.cpp
index 9029ab86a7ffa..ce948c7435f58 100644
--- a/llvm/lib/MC/MCWasmStreamer.cpp
+++ b/llvm/lib/MC/MCWasmStreamer.cpp
@@ -121,6 +121,7 @@ bool MCWasmStreamer::emitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {
   case MCSA_Invalid:
   case MCSA_IndirectSymbol:
   case MCSA_Protected:
+  case MCSA_Exported:
     return false;
 
   case MCSA_Hidden:

diff  --git a/llvm/lib/MC/MCXCOFFStreamer.cpp b/llvm/lib/MC/MCXCOFFStreamer.cpp
index 6f7dd47eb46ba..a4a42279d6e23 100644
--- a/llvm/lib/MC/MCXCOFFStreamer.cpp
+++ b/llvm/lib/MC/MCXCOFFStreamer.cpp
@@ -56,6 +56,9 @@ bool MCXCOFFStreamer::emitSymbolAttribute(MCSymbol *Sym,
   case llvm::MCSA_Protected:
     Symbol->setVisibilityType(XCOFF::SYM_V_PROTECTED);
     break;
+  case llvm::MCSA_Exported:
+    Symbol->setVisibilityType(XCOFF::SYM_V_EXPORTED);
+    break;
   default:
     report_fatal_error("Not implemented yet.");
   }

diff  --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
index 426caba3f99ea..eb8ec62576158 100644
--- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -1898,10 +1898,15 @@ void PPCAIXAsmPrinter::emitLinkage(const GlobalValue *GV,
 
   MCSymbolAttr VisibilityAttr = MCSA_Invalid;
   if (!TM.getIgnoreXCOFFVisibility()) {
+    if (GV->hasDLLExportStorageClass() && !GV->hasDefaultVisibility())
+      report_fatal_error(
+          "Cannot not be both dllexport and non-default visibility");
     switch (GV->getVisibility()) {
 
-    // TODO: "exported" and "internal" Visibility needs to go here.
+    // TODO: "internal" Visibility needs to go here.
     case GlobalValue::DefaultVisibility:
+      if (GV->hasDLLExportStorageClass())
+        VisibilityAttr = MAI->getExportedVisibilityAttr();
       break;
     case GlobalValue::HiddenVisibility:
       VisibilityAttr = MAI->getHiddenVisibilityAttr();

diff  --git a/llvm/test/CodeGen/PowerPC/aix-xcoff-exported-nondefault.ll b/llvm/test/CodeGen/PowerPC/aix-xcoff-exported-nondefault.ll
new file mode 100644
index 0000000000000..7b1dc5c2500a4
--- /dev/null
+++ b/llvm/test/CodeGen/PowerPC/aix-xcoff-exported-nondefault.ll
@@ -0,0 +1,15 @@
+; RUN: not --crash llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff 2>&1 < %s | \
+; RUN:   FileCheck %s
+; RUN: not --crash llc -verify-machineinstrs -mtriple powerpc64-ibm-aix-xcoff 2>&1 < %s |\
+; RUN:   FileCheck %s
+
+; RUN: not --crash llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff \
+; RUN:     -filetype=obj -o %t.o < %s 2>&1 | \
+; RUN:   FileCheck %s
+
+; RUN: not --crash llc -verify-machineinstrs -mtriple powerpc64-ibm-aix-xcoff \
+; RUN:     -filetype=obj -o %t.o 2>&1 < %s 2>&1 | \
+; RUN:   FileCheck %s
+
+; CHECK: LLVM ERROR: Cannot not be both dllexport and non-default visibility
+ at b_e = hidden dllexport global i32 0, align 4

diff  --git a/llvm/test/CodeGen/PowerPC/aix-xcoff-visibility.ll b/llvm/test/CodeGen/PowerPC/aix-xcoff-visibility.ll
index 77e76040b08d3..f5584d324e3ea 100644
--- a/llvm/test/CodeGen/PowerPC/aix-xcoff-visibility.ll
+++ b/llvm/test/CodeGen/PowerPC/aix-xcoff-visibility.ll
@@ -17,6 +17,7 @@
 
 @b =  global i32 0, align 4
 @b_h = hidden global i32 0, align 4
+ at b_e = dllexport global i32 0, align 4
 
 define void @foo() {
 entry:
@@ -28,6 +29,11 @@ entry:
   ret void
 }
 
+define dllexport void @foo_e(i32* %ip) {
+entry:
+  ret void
+}
+
 define protected void @foo_protected(i32* %ip) {
 entry:
   ret void
@@ -38,8 +44,14 @@ entry:
   ret void
 }
 
+define weak dllexport void @foo_weak_e() {
+entry:
+  ret void
+}
+
 @foo_p = global void ()* @zoo_weak_extern_h, align 4
 declare extern_weak hidden void @zoo_weak_extern_h()
+declare extern_weak dllexport void @zoo_weak_extern_e()
 
 define i32 @main() {
 entry:
@@ -51,20 +63,30 @@ entry:
 }
 
 declare hidden i32 @bar_h(i32*)
+declare dllexport i32 @bar_e(i32*)
 
 ; CHECK:        .globl  foo[DS]{{[[:space:]]*([#].*)?$}}
 ; CHECK:        .globl  .foo{{[[:space:]]*([#].*)?$}}
 ; CHECK:        .globl  foo_h[DS],hidden
 ; CHECK:        .globl  .foo_h,hidden
+; CHECK:        .globl  foo_e[DS],exported
+; CHECK:        .globl  .foo_e,exported
 ; CHECK:        .globl  foo_protected[DS],protected
 ; CHECK:        .globl  .foo_protected,protected
 ; CHECK:        .weak   foo_weak_h[DS],hidden
 ; CHECK:        .weak   .foo_weak_h,hidden
+; CHECK:        .weak   foo_weak_e[DS],exported
+; CHECK:        .weak   .foo_weak_e,exported
 
 ; CHECK:        .globl  b{{[[:space:]]*([#].*)?$}}
 ; CHECK:        .globl  b_h,hidden
+; CHECK:        .globl  b_e,exported
 
 ; CHECK:        .weak   .zoo_weak_extern_h[PR],hidden
 ; CHECK:        .weak   zoo_weak_extern_h[DS],hidden
+; CHECK:        .weak   .zoo_weak_extern_e[PR],exported
+; CHECK:        .weak   zoo_weak_extern_e[DS],exported
 ; CHECK:        .extern .bar_h[PR],hidden
 ; CHECK:        .extern bar_h[DS],hidden
+; CHECK:        .extern .bar_e[PR],exported
+; CHECK:        .extern bar_e[DS],exported


        


More information about the llvm-commits mailing list