diff --git a/clang/docs/ClangCommandLineReference.rst b/clang/docs/ClangCommandLineReference.rst --- a/clang/docs/ClangCommandLineReference.rst +++ b/clang/docs/ClangCommandLineReference.rst @@ -2617,6 +2617,10 @@ Link stack frames through backchain on System Z +.. option:: -mignore-xcoff-visibility + +Do not emit any visibility attribute for asm on AIX or give all symbols 'unspecified' visibility in xcoff object file (XCOFF only) + .. option:: -mbranches-within-32B-boundaries Align selected branches (fused, jcc, jmp) within 32-byte boundary 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(IgnoreXCOFFVisibility , 1, 0) ///< -mignore-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 @@ -2562,6 +2562,9 @@ def mzvector : Flag<["-"], "mzvector">, Alias; def mno_zvector : Flag<["-"], "mno-zvector">, Alias; +def mignore_xcoff_visibility : Flag<["-"], "mignore-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.IgnoreXCOFFVisibility = CodeGenOpts.IgnoreXCOFFVisibility; 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 @@ -5239,6 +5239,14 @@ } } + if (const Arg *A = Args.getLastArg(options::OPT_mignore_xcoff_visibility)) { + if (Triple.isOSAIX()) + CmdArgs.push_back("-mignore-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 @@ -1360,6 +1360,10 @@ } } + if (T.isOSAIX() && (Args.hasArg(OPT_mignore_xcoff_visibility) || + !Args.hasArg(OPT_fvisibility))) + Opts.IgnoreXCOFFVisibility = 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-ignore-xcoff-visibility.cpp b/clang/test/CodeGen/aix-ignore-xcoff-visibility.cpp new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/aix-ignore-xcoff-visibility.cpp @@ -0,0 +1,96 @@ +// RUN: %clang_cc1 -triple powerpc-unknown-aix -o - -x c++ -S %s |\ +// RUN: FileCheck --check-prefix=IGNOREVISIBILITY-ASM %s + +// RUN: %clang_cc1 -triple powerpc-unknown-aix -mignore-xcoff-visibility -o - -x c++ -S %s | \ +// RUN: FileCheck -check-prefix=IGNOREVISIBILITY-ASM %s + +// RUN: %clang_cc1 -triple powerpc-unknown-aix -mignore-xcoff-visibility -fvisibility default -o - -x c++ -S %s | \ +// RUN: FileCheck -check-prefix=IGNOREVISIBILITY-ASM %s + +// RUN: %clang_cc1 -triple powerpc-unknown-aix -fvisibility default -o - -x c++ -S %s | \ +// RUN: FileCheck -check-prefix=VISIBILITY-ASM %s + +// RUN: %clang_cc1 -triple powerpc-unknown-aix -mignore-xcoff-visibility -fvisibility default -o - -x c++ -S %s | \ +// RUN: FileCheck -check-prefix=IGNOREVISIBILITY-ASM %s + +// RUN: %clang_cc1 -triple powerpc-unknown-aix -fvisibility default -o - -x c++ -S %s | \ +// RUN: FileCheck -check-prefix=VISIBILITY-ASM %s + +// RUN: %clang_cc1 -triple powerpc-unknown-aix -mignore-xcoff-visibility -fvisibility default -emit-llvm -o - -x c++ %s | \ +// RUN: FileCheck -check-prefix=VISIBILITY-IR %s + +// RUN: %clang_cc1 -triple powerpc-unknown-aix -fvisibility default -emit-llvm -o - -x c++ %s | \ +// RUN: FileCheck -check-prefix=VISIBILITY-IR %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() + +// 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 + +// IGNOREVISIBILITY-ASM: .globl _Z5foo_hPi[DS] +// IGNOREVISIBILITY-ASM: .globl ._Z5foo_hPi +// IGNOREVISIBILITY-ASM: .globl _Z3barv[DS] +// IGNOREVISIBILITY-ASM: .globl ._Z3barv +// IGNOREVISIBILITY-ASM: .weak _ZNK9TestClass5valueEv[DS] +// IGNOREVISIBILITY-ASM: .weak ._ZNK9TestClass5valueEv +// IGNOREVISIBILITY-ASM: .weak _ZN5basicIiE7getdataEv[DS] +// IGNOREVISIBILITY-ASM: .weak ._ZN5basicIiE7getdataEv +// IGNOREVISIBILITY-ASM: .globl _Z7prambarv[DS] +// IGNOREVISIBILITY-ASM: .globl ._Z7prambarv +// IGNOREVISIBILITY-ASM: .globl b +// IGNOREVISIBILITY-ASM: .globl pramb diff --git a/clang/test/Driver/ignore-xcoff-visibility.cpp b/clang/test/Driver/ignore-xcoff-visibility.cpp new file mode 100644 --- /dev/null +++ b/clang/test/Driver/ignore-xcoff-visibility.cpp @@ -0,0 +1,9 @@ +// RUN: %clang -### -target powerpc-unknown-aix -mignore-xcoff-visibility -S %s 2> %t.log +// RUN: FileCheck -check-prefix=CHECK %s < %t.log + CHECK: {{.*}}clang{{.*}}" "-cc1" + CHECK: "-mignore-xcoff-visibility" + +// RUN: not %clang -mignore-xcoff-visibility -target powerpc-unknown-linux %s 2>&1 | \ +// RUN: FileCheck -check-prefix=ERROR %s + + ERROR: unsupported option '-mignore-xcoff-visibility' for target 'powerpc-unknown-linux' diff --git a/llvm/include/llvm/CodeGen/CommandFlags.h b/llvm/include/llvm/CodeGen/CommandFlags.h --- a/llvm/include/llvm/CodeGen/CommandFlags.h +++ b/llvm/include/llvm/CodeGen/CommandFlags.h @@ -94,6 +94,8 @@ bool getFunctionSections(); Optional getExplicitFunctionSections(); +bool getIgnoreXCOFFVisibility(); + std::string getBBSections(); unsigned getTLSSize(); 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 @@ -262,6 +262,12 @@ return Options.FunctionSections; } + /// Return true if visibility attribute should not be emitted in xcoff, + /// corresponding to -mignore-xcoff-visibility. + bool getIgnoreXCOFFVisibility() const { + return Options.IgnoreXCOFFVisibility; + } + /// 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), + IgnoreXCOFFVisibility(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 IgnoreXCOFFVisibility : 1; + unsigned UniqueSectionNames : 1; /// Use unique names for basic block sections. diff --git a/llvm/lib/CodeGen/CommandFlags.cpp b/llvm/lib/CodeGen/CommandFlags.cpp --- a/llvm/lib/CodeGen/CommandFlags.cpp +++ b/llvm/lib/CodeGen/CommandFlags.cpp @@ -74,6 +74,7 @@ CGOPT(bool, RelaxELFRelocations) CGOPT_EXP(bool, DataSections) CGOPT_EXP(bool, FunctionSections) +CGOPT(bool, IgnoreXCOFFVisibility) CGOPT(std::string, BBSections) CGOPT(unsigned, TLSSize) CGOPT(bool, EmulatedTLS) @@ -333,6 +334,13 @@ cl::init(false)); CGBINDOPT(FunctionSections); + static cl::opt IgnoreXCOFFVisibility( + "ignore-xcoff-visibility", + cl::desc("Not emit the visibility attribute for asm in AIX OS or give " + "all symbols 'unspecified' visibility in xcoff object file"), + cl::init(false)); + CGBINDOPT(IgnoreXCOFFVisibility); + static cl::opt BBSections( "basic-block-sections", cl::desc("Emit basic blocks into separate sections"), @@ -479,6 +487,7 @@ Options.RelaxELFRelocations = getRelaxELFRelocations(); Options.DataSections = getDataSections(); Options.FunctionSections = getFunctionSections(); + Options.IgnoreXCOFFVisibility = getIgnoreXCOFFVisibility(); Options.BBSections = getBBSectionsMode(Options); Options.UniqueSectionNames = getUniqueSectionNames(); Options.UniqueBasicBlockSectionNames = getUniqueBasicBlockSectionNames(); 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 @@ -1702,17 +1702,19 @@ assert(LinkageAttr != MCSA_Invalid && "LinkageAttr should not MCSA_Invalid."); MCSymbolAttr VisibilityAttr = MCSA_Invalid; - switch (GV->getVisibility()) { + if (!TM.getIgnoreXCOFFVisibility()) { + 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, diff --git a/llvm/test/CodeGen/PowerPC/aix-ignore-xcoff-visibility.ll b/llvm/test/CodeGen/PowerPC/aix-ignore-xcoff-visibility.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/aix-ignore-xcoff-visibility.ll @@ -0,0 +1,48 @@ +; RUN: llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff -mcpu=pwr4 \ +; RUN: -mattr=-altivec < %s | \ +; RUN: FileCheck --check-prefix=VISIBILITY-ASM %s +; RUN: llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff -mcpu=pwr4 \ +; RUN: -mattr=-altivec -ignore-xcoff-visibility < %s | \ +; RUN: FileCheck --check-prefix=IGNOREVISIBILITY-ASM %s +; RUN: llc -verify-machineinstrs -mtriple powerpc64-ibm-aix-xcoff -mcpu=pwr4 \ +; RUN: -mattr=-altivec < %s | \ +; RUN: FileCheck --check-prefix=VISIBILITY-ASM %s +; RUN: llc -verify-machineinstrs -mtriple powerpc64-ibm-aix-xcoff -mcpu=pwr4 \ +; RUN: -mattr=-altivec -ignore-xcoff-visibility < %s | \ +; RUN: FileCheck --check-prefix=IGNOREVISIBILITY-ASM %s + +@foo_p = global void ()* @zoo_extern_h, align 4 +@b = protected global i32 0, align 4 + +define hidden void @foo_h(i32* %p) { +entry: + %p.addr = alloca i32*, align 4 + store i32* %p, i32** %p.addr, align 4 + %0 = load i32*, i32** %p.addr, align 4 + %1 = load i32, i32* %0, align 4 + %inc = add nsw i32 %1, 1 + store i32 %inc, i32* %0, align 4 + ret void +} + +declare hidden void @zoo_extern_h() + +define protected void @bar() { +entry: + call void @foo_h(i32* @b) + %0 = load void ()*, void ()** @foo_p, align 4 + call void %0() + ret void +} + +; VISIBILITY-ASM: .globl foo_h[DS],hidden +; VISIBILITY-ASM: .globl .foo_h,hidden +; VISIBILITY-ASM: .globl bar[DS],protected +; VISIBILITY-ASM: .globl .bar,protected +; VISIBILITY-ASM: .globl b,protected + +; IGNOREVISIBILITY-ASM: .globl foo_h[DS] +; IGNOREVISIBILITY-ASM: .globl .foo_h +; IGNOREVISIBILITY-ASM: .globl bar[DS] +; IGNOREVISIBILITY-ASM: .globl .bar +; IGNOREVISIBILITY-ASM: .globl b