Index: llvm/docs/LangRef.rst =================================================================== --- llvm/docs/LangRef.rst +++ llvm/docs/LangRef.rst @@ -481,7 +481,10 @@ 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 @@ 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: Index: llvm/include/llvm/MC/MCAsmInfo.h =================================================================== --- llvm/include/llvm/MC/MCAsmInfo.h +++ llvm/include/llvm/MC/MCAsmInfo.h @@ -430,6 +430,10 @@ /// 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 @@ MCSymbolAttr getHiddenVisibilityAttr() const { return HiddenVisibilityAttr; } + MCSymbolAttr getExportedVisibilityAttr() const { return ExportedVisibilityAttr; } + MCSymbolAttr getHiddenDeclarationVisibilityAttr() const { return HiddenDeclarationVisibilityAttr; } Index: llvm/include/llvm/MC/MCDirectives.h =================================================================== --- llvm/include/llvm/MC/MCDirectives.h +++ llvm/include/llvm/MC/MCDirectives.h @@ -31,6 +31,7 @@ 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) Index: llvm/lib/MC/MCAsmStreamer.cpp =================================================================== --- llvm/lib/MC/MCAsmStreamer.cpp +++ llvm/lib/MC/MCAsmStreamer.cpp @@ -762,6 +762,8 @@ 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 @@ case MCSA_Protected: OS << ",protected"; break; + case MCSA_Exported: + OS << ",exported"; + break; default: report_fatal_error("unexpected value for Visibility type"); } Index: llvm/lib/MC/MCELFStreamer.cpp =================================================================== --- llvm/lib/MC/MCELFStreamer.cpp +++ llvm/lib/MC/MCELFStreamer.cpp @@ -215,6 +215,7 @@ case MCSA_WeakDefAutoPrivate: case MCSA_Invalid: case MCSA_IndirectSymbol: + case MCSA_Exported: return false; case MCSA_NoDeadStrip: Index: llvm/lib/MC/MCMachOStreamer.cpp =================================================================== --- llvm/lib/MC/MCMachOStreamer.cpp +++ llvm/lib/MC/MCMachOStreamer.cpp @@ -358,6 +358,7 @@ case MCSA_Weak: case MCSA_Local: case MCSA_LGlobal: + case MCSA_Exported: return false; case MCSA_Global: Index: llvm/lib/MC/MCWasmStreamer.cpp =================================================================== --- llvm/lib/MC/MCWasmStreamer.cpp +++ llvm/lib/MC/MCWasmStreamer.cpp @@ -121,6 +121,7 @@ case MCSA_Invalid: case MCSA_IndirectSymbol: case MCSA_Protected: + case MCSA_Exported: return false; case MCSA_Hidden: Index: llvm/lib/MC/MCXCOFFStreamer.cpp =================================================================== --- llvm/lib/MC/MCXCOFFStreamer.cpp +++ llvm/lib/MC/MCXCOFFStreamer.cpp @@ -56,6 +56,9 @@ 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."); } Index: llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp =================================================================== --- llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -1898,10 +1898,15 @@ 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(); Index: llvm/test/CodeGen/PowerPC/aix-xcoff-exported-nondefault.ll =================================================================== --- /dev/null +++ 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 +@b_e = hidden dllexport global i32 0, align 4 Index: llvm/test/CodeGen/PowerPC/aix-xcoff-visibility.ll =================================================================== --- llvm/test/CodeGen/PowerPC/aix-xcoff-visibility.ll +++ 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 +@b_e = dllexport global i32 0, align 4 define void @foo() { entry: @@ -28,6 +29,11 @@ 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 @@ 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 @@ } 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