diff --git a/clang/docs/ClangCommandLineReference.rst b/clang/docs/ClangCommandLineReference.rst --- a/clang/docs/ClangCommandLineReference.rst +++ b/clang/docs/ClangCommandLineReference.rst @@ -2307,6 +2307,10 @@ Give inline C++ member functions hidden visibility by default +.. option:: -mno-xcoff-visibility + +Do not emit any visibility attribute for asm on AIX or give all symbols 'unspecified' visibility in xcoff object file. + .. option:: -fvisibility-ms-compat Give global types 'default' visibility and global functions and variables 'hidden' visibility by default diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -37,6 +37,7 @@ CODEGENOPT(Autolink , 1, 1) ///< -fno-autolink CODEGENOPT(ObjCAutoRefCountExceptions , 1, 0) ///< Whether ARC should be EH-safe. CODEGENOPT(Backchain , 1, 0) ///< -mbackchain +CODEGENOPT(NoXCOFFVisibility , 1, 0) ///< -mno-xcoff-visibility CODEGENOPT(ControlFlowGuardNoChecks , 1, 0) ///< -cfguard-no-checks CODEGENOPT(ControlFlowGuard , 1, 0) ///< -cfguard CODEGENOPT(CXAAtExit , 1, 1) ///< Use __cxa_atexit for calling destructors. diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2548,6 +2548,9 @@ def mzvector : Flag<["-"], "mzvector">, Alias; def mno_zvector : Flag<["-"], "mno-zvector">, Alias; +def mno_xcoff_visibility : Flag<["-"], "mno-xcoff-visibility">, Group, +HelpText<"Not emit the visibility attribute for asm in AIX OS or give all symbols 'unspecified' visibility in xcoff object file">, + Flags<[CC1Option]>; def mbackchain : Flag<["-"], "mbackchain">, Group, Flags<[DriverOption,CC1Option]>, HelpText<"Link stack frames through backchain on System Z">; def mno_backchain : Flag<["-"], "mno-backchain">, Group, Flags<[DriverOption,CC1Option]>; diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -517,6 +517,7 @@ Options.EnableMachineFunctionSplitter = CodeGenOpts.SplitMachineFunctions; Options.FunctionSections = CodeGenOpts.FunctionSections; Options.DataSections = CodeGenOpts.DataSections; + Options.NoXCOFFVisibility = CodeGenOpts.NoXCOFFVisibility; Options.UniqueSectionNames = CodeGenOpts.UniqueSectionNames; Options.UniqueBasicBlockSectionNames = CodeGenOpts.UniqueBasicBlockSectionNames; diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -5228,6 +5228,14 @@ } } + if (const Arg *A = Args.getLastArg(options::OPT_mno_xcoff_visibility)) { + if (Triple.isOSAIX()) + CmdArgs.push_back("-mno-xcoff-visibility"); + else + D.Diag(diag::err_drv_unsupported_opt_for_target) + << A->getAsString(Args) << TripleStr; + } + Args.AddLastArg(CmdArgs, options::OPT_fvisibility_inlines_hidden); Args.AddLastArg(CmdArgs, options::OPT_fvisibility_inlines_hidden_static_local_var, options::OPT_fno_visibility_inlines_hidden_static_local_var); diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1355,6 +1355,10 @@ } } + if (T.isOSAIX() && + (Args.hasArg(OPT_mno_xcoff_visibility) || !Args.hasArg(OPT_fvisibility))) + Opts.NoXCOFFVisibility = 1; + Opts.DependentLibraries = Args.getAllArgValues(OPT_dependent_lib); Opts.LinkerOptions = Args.getAllArgValues(OPT_linker_option); bool NeedLocTracking = false; diff --git a/clang/test/CodeGen/aix-no-xcoff-visibility.cpp b/clang/test/CodeGen/aix-no-xcoff-visibility.cpp new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/aix-no-xcoff-visibility.cpp @@ -0,0 +1,110 @@ +// RUN: %clang -target powerpc-unknown-aix -emit-llvm -o - -S %s |\ +// RUN: FileCheck --check-prefix=VISIBILITY-IR %s + +// RUN: %clang -target powerpc-unknown-aix -o - -S %s |\ +// RUN: FileCheck --check-prefix=NOVISIBILITY-ASM %s + +// RUN: %clang -target powerpc-unknown-linux -emit-llvm -o - -S %s | \ +// RUN: FileCheck -check-prefix=VISIBILITY-IR %s + +// RUN: %clang -mno-xcoff-visibility -target powerpc-unknown-aix -emit-llvm -o - -S %s | \ +// RUN: FileCheck -check-prefix=VISIBILITY-IR %s + +// RUN: %clang -mno-xcoff-visibility -target powerpc-unknown-aix -o - -S %s | \ +// RUN: FileCheck -check-prefix=NOVISIBILITY-ASM %s + +// RUN: not %clang -mno-xcoff-visibility -target powerpc-unknown-linux -emit-llvm -o - -S %s 2>&1 | \ +// RUN: FileCheck -check-prefix=ERROR %s + +// RUN: %clang -fvisibility=default -target powerpc-unknown-aix -emit-llvm -o - -S %s | \ +// RUN: FileCheck -check-prefix=VISIBILITY-IR %s + +// RUN: %clang -fvisibility=default -target powerpc-unknown-aix -o - -S %s | \ +// RUN: FileCheck -check-prefix=VISIBILITY-ASM %s + +// RUN: %clang -fvisibility=default -target powerpc-unknown-linux -emit-llvm -o - -S %s | \ +// RUN: FileCheck -check-prefix=VISIBILITY-IR %s + +// RUN: %clang -mno-xcoff-visibility -fvisibility=default -target powerpc-unknown-aix -emit-llvm -o - -S %s | \ +// RUN: FileCheck -check-prefix=VISIBILITY-IR %s + +// RUN: %clang -mno-xcoff-visibility -fvisibility=default -target powerpc-unknown-aix -o - -S %s | \ +// RUN: FileCheck -check-prefix=NOVISIBILITY-ASM %s + +// RUN: not %clang -mno-xcoff-visibility -fvisibility=default -target powerpc-unknown-linux -emit-llvm -o - -S %s 2>&1 | \ +// RUN: FileCheck -check-prefix=ERROR %s + +__attribute__((visibility("hidden"))) void foo_h(int *p) { + (*p)++; +} + +__attribute__((visibility("protected"))) int b; + +extern __attribute__((visibility("hidden"))) void zoo_extern_h(void); + +void (*foo_p)(void) = zoo_extern_h; + +__attribute__((visibility("protected"))) void bar() { + foo_h(&b); + foo_p(); +} + +class TestClass { +public: + __attribute__((__visibility__("hidden"))) int value() const noexcept { return 0; } +}; + +int main() { + TestClass TC; + return TC.value(); +} + +template +class basic { +public: + __attribute__((__visibility__("protected"))) int getdata() { return 1; } +}; + +template class basic; + +#pragma GCC visibility push(hidden) +int pramb; +void prambar() {} +#pragma GCC visibility pop + +// VISIBILITY-IR: @b = protected global i32 0 +// VISIBILITY-IR: @pramb = hidden global i32 0 +// VISIBILITY-IR: define hidden void @_Z5foo_hPi(i32* %p) +// VISIBILITY-IR: declare hidden void @_Z12zoo_extern_hv() +// VISIBILITY-IR: define protected void @_Z3barv() +// VISIBILITY-IR: define linkonce_odr hidden i32 @_ZNK9TestClass5valueEv(%class.TestClass* %this) +// VISIBILITY-IR: define weak_odr protected i32 @_ZN5basicIiE7getdataEv(%class.basic* %this) +// VISIBILITY-IR: define hidden void @_Z7prambarv() + +// ERROR: unsupported option '-mno-xcoff-visibility' for target 'powerpc-unknown-linux' + +// VISIBILITY-ASM: .globl _Z5foo_hPi[DS],hidden +// VISIBILITY-ASM: .globl ._Z5foo_hPi,hidden +// VISIBILITY-ASM: .globl _Z3barv[DS],protected +// VISIBILITY-ASM: .globl ._Z3barv,protected +// VISIBILITY-ASM: .weak _ZNK9TestClass5valueEv[DS],hidden +// VISIBILITY-ASM: .weak ._ZNK9TestClass5valueEv,hidden +// VISIBILITY-ASM: .weak _ZN5basicIiE7getdataEv[DS],protected +// VISIBILITY-ASM: .weak ._ZN5basicIiE7getdataEv,protected +// VISIBILITY-ASM: .globl _Z7prambarv[DS],hidden +// VISIBILITY-ASM: .globl ._Z7prambarv,hidden +// VISIBILITY-ASM: .globl b,protected +// VISIBILITY-ASM: .globl pramb,hidden + +// NOVISIBILITY-ASM: .globl _Z5foo_hPi[DS] +// NOVISIBILITY-ASM: .globl ._Z5foo_hPi +// NOVISIBILITY-ASM: .globl _Z3barv[DS] +// NOVISIBILITY-ASM: .globl ._Z3barv +// NOVISIBILITY-ASM: .weak _ZNK9TestClass5valueEv[DS] +// NOVISIBILITY-ASM: .weak ._ZNK9TestClass5valueEv +// NOVISIBILITY-ASM: .weak _ZN5basicIiE7getdataEv[DS] +// NOVISIBILITY-ASM: .weak ._ZN5basicIiE7getdataEv +// NOVISIBILITY-ASM: .globl _Z7prambarv[DS] +// NOVISIBILITY-ASM: .globl ._Z7prambarv +// NOVISIBILITY-ASM: .globl b +// NOVISIBILITY-ASM: .globl pramb diff --git a/llvm/include/llvm/Target/TargetMachine.h b/llvm/include/llvm/Target/TargetMachine.h --- a/llvm/include/llvm/Target/TargetMachine.h +++ b/llvm/include/llvm/Target/TargetMachine.h @@ -260,6 +260,10 @@ return Options.FunctionSections; } + /// Return true if visibility attribute should not be emitted in xcoff, + /// corresponding to -mno-xcoff-visibility. + bool getNoXCOFFVisibility() const { return Options.NoXCOFFVisibility; } + /// If basic blocks should be emitted into their own section, /// corresponding to -fbasic-block-sections. llvm::BasicBlockSection getBBSectionsType() const { diff --git a/llvm/include/llvm/Target/TargetOptions.h b/llvm/include/llvm/Target/TargetOptions.h --- a/llvm/include/llvm/Target/TargetOptions.h +++ b/llvm/include/llvm/Target/TargetOptions.h @@ -123,9 +123,10 @@ EnableFastISel(false), EnableGlobalISel(false), UseInitArray(false), DisableIntegratedAS(false), RelaxELFRelocations(false), FunctionSections(false), DataSections(false), - UniqueSectionNames(true), UniqueBasicBlockSectionNames(false), - TrapUnreachable(false), NoTrapAfterNoreturn(false), TLSSize(0), - EmulatedTLS(false), ExplicitEmulatedTLS(false), EnableIPRA(false), + NoXCOFFVisibility(false), UniqueSectionNames(true), + UniqueBasicBlockSectionNames(false), TrapUnreachable(false), + NoTrapAfterNoreturn(false), TLSSize(0), EmulatedTLS(false), + ExplicitEmulatedTLS(false), EnableIPRA(false), EmitStackSizeSection(false), EnableMachineOutliner(false), EnableMachineFunctionSplitter(false), SupportsDefaultOutlining(false), EmitAddrsig(false), EmitCallSiteInfo(false), @@ -230,6 +231,9 @@ /// Emit data into separate sections. unsigned DataSections : 1; + /// Do not emit visibility attribute for xcoff. + unsigned NoXCOFFVisibility : 1; + unsigned UniqueSectionNames : 1; /// Use unique names for basic block sections. diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -1686,17 +1686,19 @@ assert(LinkageAttr != MCSA_Invalid && "LinkageAttr should not MCSA_Invalid."); MCSymbolAttr VisibilityAttr = MCSA_Invalid; - switch (GV->getVisibility()) { + if (!TM.getNoXCOFFVisibility()) { + switch (GV->getVisibility()) { - // TODO: "exported" and "internal" Visibility needs to go here. - case GlobalValue::DefaultVisibility: - break; - case GlobalValue::HiddenVisibility: - VisibilityAttr = MAI->getHiddenVisibilityAttr(); - break; - case GlobalValue::ProtectedVisibility: - VisibilityAttr = MAI->getProtectedVisibilityAttr(); - break; + // TODO: "exported" and "internal" Visibility needs to go here. + case GlobalValue::DefaultVisibility: + break; + case GlobalValue::HiddenVisibility: + VisibilityAttr = MAI->getHiddenVisibilityAttr(); + break; + case GlobalValue::ProtectedVisibility: + VisibilityAttr = MAI->getProtectedVisibilityAttr(); + break; + } } OutStreamer->emitXCOFFSymbolLinkageWithVisibility(GVSym, LinkageAttr,