diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index cc5eb939dbd294..963fde5f3ad4be 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -322,7 +322,8 @@ ENUM_LANGOPT(ExternDeclDLLImportVisibility, Visibility, 3, DefaultVisibility, ENUM_LANGOPT(ExternDeclNoDLLStorageClassVisibility, Visibility, 3, HiddenVisibility, "visibility for external declarations without an explicit DLL storage class [-fvisibility-from-dllstorageclass]") BENIGN_LANGOPT(SemanticInterposition , 1, 0, "semantic interposition") -BENIGN_LANGOPT(ExplicitNoSemanticInterposition, 1, 0, "explicitly no semantic interposition") +BENIGN_LANGOPT(HalfNoSemanticInterposition, 1, 0, + "Like -fno-semantic-interposition but don't use local aliases") ENUM_LANGOPT(StackProtector, StackProtectorMode, 2, SSPOff, "stack protector mode") ENUM_LANGOPT(TrivialAutoVarInit, TrivialAutoVarInitKind, 2, TrivialAutoVarInitKind::Uninitialized, diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index af209eb9089d7f..9a851f63a663c2 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -3793,7 +3793,7 @@ defm ipa_cp : BooleanFFlag<"ipa-cp">, Group; defm ivopts : BooleanFFlag<"ivopts">, Group; def fsemantic_interposition : Flag<["-"], "fsemantic-interposition">, Group, Flags<[CC1Option]>; -def fno_semantic_interposition: Flag<["-"], "fno-semantic-interposition">, Group, Flags<[CC1Option]>; +def fno_semantic_interposition: Flag<["-"], "fno-semantic-interposition">, Group; defm non_call_exceptions : BooleanFFlag<"non-call-exceptions">, Group; defm peel_loops : BooleanFFlag<"peel-loops">, Group; defm permissive : BooleanFFlag<"permissive">, Group; @@ -4722,6 +4722,8 @@ def pic_level : Separate<["-"], "pic-level">, HelpText<"Value for __PIC__">; def pic_is_pie : Flag<["-"], "pic-is-pie">, HelpText<"File is for a position independent executable">; +def fhalf_no_semantic_interposition : Flag<["-"], "fhalf-no-semantic-interposition">, + HelpText<"Like -fno-semantic-interposition but don't use local aliases">; def fno_validate_pch : Flag<["-"], "fno-validate-pch">, HelpText<"Disable validation of precompiled headers">, MarshallingInfoFlag<"PreprocessorOpts->DisablePCHValidation">; diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index bf0a38bf83ab19..cfc0f732748c14 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -534,9 +534,6 @@ void CodeGenModule::Release() { if (Context.getLangOpts().SemanticInterposition) // Require various optimization to respect semantic interposition. getModule().setSemanticInterposition(1); - else if (Context.getLangOpts().ExplicitNoSemanticInterposition) - // Allow dso_local on applicable targets. - getModule().setSemanticInterposition(0); if (CodeGenOpts.EmitCodeView) { // Indicate that we want CodeView in the metadata. @@ -961,15 +958,15 @@ static bool shouldAssumeDSOLocal(const CodeGenModule &CGM, return false; if (RM != llvm::Reloc::Static && !LOpts.PIE) { - // On ELF, if -fno-semantic-interposition is specified, we can set dso_local - // if using a local alias is preferable (can avoid GOT indirection). - // Currently only x86 supports local alias. - if (!TT.isOSBinFormatELF() || - !CGM.getLangOpts().ExplicitNoSemanticInterposition || - !GV->canBenefitFromLocalAlias()) + // On ELF, if -fno-semantic-interposition is specified and the target + // supports local aliases, there will be neither CC1 + // -fsemantic-interposition nor -fhalf-no-semantic-interposition. Set + // dso_local if using a local alias is preferable (can avoid GOT + // indirection). + if (!GV->canBenefitFromLocalAlias()) return false; - // The allowed targets need to match AsmPrinter::getSymbolPreferLocal. - return TT.isX86(); + return !(CGM.getLangOpts().SemanticInterposition || + CGM.getLangOpts().HalfNoSemanticInterposition); } // A definition cannot be preempted from an executable. diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 300ab6e815e233..5451244c43aef4 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4561,12 +4561,31 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(A->getValue()); } - // The default is -fno-semantic-interposition. We render it just because we - // require explicit -fno-semantic-interposition to infer dso_local. - if (Arg *A = Args.getLastArg(options::OPT_fsemantic_interposition, - options::OPT_fno_semantic_interposition)) - if (RelocationModel != llvm::Reloc::Static && !IsPIE) - A->render(Args, CmdArgs); + // -fsemantic-interposition is forwarded to CC1: set the + // "SemanticInterposition" metadata to 1 (make some linkages interposable) and + // make default visibility external linkage definitions dso_preemptable. + // + // -fno-semantic-interposition: if the target supports .Lfoo$local local + // aliases (make default visibility external linkage definitions dso_local). + // This is the CC1 default for ELF to match COFF/Mach-O. + // + // Otherwise use Clang's traditional behavior: like + // -fno-semantic-interposition but local aliases are not used. So references + // can be interposed if not optimized out. + if (Triple.isOSBinFormatELF()) { + Arg *A = Args.getLastArg(options::OPT_fsemantic_interposition, + options::OPT_fno_semantic_interposition); + if (RelocationModel != llvm::Reloc::Static && !IsPIE) { + // The supported targets need to call AsmPrinter::getSymbolPreferLocal. + bool SupportsLocalAlias = Triple.isX86(); + if (!A) + CmdArgs.push_back("-fhalf-no-semantic-interposition"); + else if (A->getOption().matches(options::OPT_fsemantic_interposition)) + A->render(Args, CmdArgs); + else if (!SupportsLocalAlias) + CmdArgs.push_back("-fhalf-no-semantic-interposition"); + } + } { std::string Model; diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 06d8d2e27c9b77..1d16312cf2d0bb 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -3197,9 +3197,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, } Opts.SemanticInterposition = Args.hasArg(OPT_fsemantic_interposition); - // An explicit -fno-semantic-interposition infers dso_local. - Opts.ExplicitNoSemanticInterposition = - Args.hasArg(OPT_fno_semantic_interposition); + Opts.HalfNoSemanticInterposition = + Args.hasArg(OPT_fhalf_no_semantic_interposition); // -mrtd option if (Arg *A = Args.getLastArg(OPT_mrtd)) { diff --git a/clang/test/CodeGen/attr-arm-sve-vector-bits-globals.c b/clang/test/CodeGen/attr-arm-sve-vector-bits-globals.c index cb1aa6e0cf7479..d81cd3627b2b0d 100644 --- a/clang/test/CodeGen/attr-arm-sve-vector-bits-globals.c +++ b/clang/test/CodeGen/attr-arm-sve-vector-bits-globals.c @@ -1,7 +1,7 @@ // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py // REQUIRES: aarch64-registered-target -// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +bf16 -msve-vector-bits=128 -fallow-half-arguments-and-returns -S -O1 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-128 -// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +bf16 -msve-vector-bits=512 -fallow-half-arguments-and-returns -S -O1 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-512 +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +bf16 -msve-vector-bits=128 -fallow-half-arguments-and-returns -S -O1 -emit-llvm -o - %s -fhalf-no-semantic-interposition | FileCheck %s --check-prefix=CHECK-128 +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +bf16 -msve-vector-bits=512 -fallow-half-arguments-and-returns -S -O1 -emit-llvm -o - %s -fhalf-no-semantic-interposition | FileCheck %s --check-prefix=CHECK-512 #include diff --git a/clang/test/CodeGen/semantic-interposition-no.c b/clang/test/CodeGen/semantic-interposition-no.c deleted file mode 100644 index cc53d1799f9d9a..00000000000000 --- a/clang/test/CodeGen/semantic-interposition-no.c +++ /dev/null @@ -1,23 +0,0 @@ -// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -mrelocation-model pic -pic-level 1 -fno-semantic-interposition %s -o - | FileCheck %s - -/// For ELF -fpic/-fPIC, if -fno-semantic-interposition is specified, mark -/// defined variables and functions dso_local. ifunc isn't marked. - -// CHECK: @var = dso_local global i32 0, align 4 -// CHECK: @ext_var = external global i32, align 4 -int var; -extern int ext_var; - -// CHECK: @ifunc = ifunc i32 (), bitcast (i8* ()* @ifunc_resolver to i32 ()*) -int ifunc(void) __attribute__((ifunc("ifunc_resolver"))); - -// CHECK: define dso_local i32 @func() -// CHECK: declare i32 @ext() -int func(void) { return 0; } -int ext(void); - -static void *ifunc_resolver() { return func; } - -int foo() { - return var + ext_var + ifunc() + func() + ext(); -} diff --git a/clang/test/CodeGen/semantic-interposition.c b/clang/test/CodeGen/semantic-interposition.c index 3d6c5f2872b576..6b402214df9cc6 100644 --- a/clang/test/CodeGen/semantic-interposition.c +++ b/clang/test/CodeGen/semantic-interposition.c @@ -1,9 +1,38 @@ -// RUN: %clang_cc1 -emit-llvm -fsemantic-interposition %s -o - | FileCheck --check-prefix=INTERPOSITION %s -// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck --check-prefix=NO %s -/// With explicit -fno-semantic-interposition, add a module flag to inform the -/// backend that dso_local can be inferred. -// RUN: %clang_cc1 -emit-llvm -fno-semantic-interposition %s -o - | FileCheck --check-prefix=EXPLICIT_NO %s - -// INTERPOSITION: !{{[0-9]+}} = !{i32 1, !"SemanticInterposition", i32 1} -// NO-NOT: "SemanticInterposition" -// EXPLICIT_NO: !{{[0-9]+}} = !{i32 1, !"SemanticInterposition", i32 0} +/// -fno-semantic-interposition is the default and local aliases (via dso_local) are allowed. +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -mrelocation-model pic -pic-level 1 %s -o - | FileCheck %s --check-prefixes=CHECK,NOMETADATA + +/// -fsemantic-interposition sets a module metadata. +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -mrelocation-model pic -pic-level 1 -fsemantic-interposition %s -o - | FileCheck %s --check-prefixes=PREEMPT,METADATA + +/// Traditional half-baked behavior: interprocedural optimizations are allowed +/// but local aliases are not used. +// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -mrelocation-model pic -pic-level 1 -fhalf-no-semantic-interposition %s -o - | FileCheck %s --check-prefixes=PREEMPT,NOMETADATA + +// CHECK: @var = dso_local global i32 0, align 4 +// CHECK: @ext_var = external global i32, align 4 +// CHECK: @ifunc = ifunc i32 (), bitcast (i8* ()* @ifunc_resolver to i32 ()*) +// CHECK: define dso_local i32 @func() +// CHECK: declare i32 @ext() + +// PREEMPT: @var = global i32 0, align 4 +// PREEMPT: @ext_var = external global i32, align 4 +// PREEMPT: @ifunc = ifunc i32 (), bitcast (i8* ()* @ifunc_resolver to i32 ()*) +// PREEMPT: define i32 @func() +// PREEMPT: declare i32 @ext() + +// METADATA: !{{[0-9]+}} = !{i32 1, !"SemanticInterposition", i32 1} +// NOMETADATA-NOT: "SemanticInterposition" + +int var; +extern int ext_var; + +int ifunc(void) __attribute__((ifunc("ifunc_resolver"))); + +int func(void) { return 0; } +int ext(void); + +static void *ifunc_resolver() { return func; } + +int foo() { + return var + ext_var + ifunc() + func() + ext(); +} diff --git a/clang/test/CodeGenCXX/RelativeVTablesABI/child-inheritted-from-parent-in-comdat.cpp b/clang/test/CodeGenCXX/RelativeVTablesABI/child-inheritted-from-parent-in-comdat.cpp index 631594c2897d34..9e9a35a4a60acc 100644 --- a/clang/test/CodeGenCXX/RelativeVTablesABI/child-inheritted-from-parent-in-comdat.cpp +++ b/clang/test/CodeGenCXX/RelativeVTablesABI/child-inheritted-from-parent-in-comdat.cpp @@ -1,7 +1,7 @@ // Cross comdat example // Parent VTable is in a comdat section. -// RUN: %clang_cc1 %s -triple=aarch64-unknown-fuchsia -O1 -S -o - -emit-llvm -fexperimental-relative-c++-abi-vtables | FileCheck %s +// RUN: %clang_cc1 %s -triple=aarch64-unknown-fuchsia -O1 -S -o - -emit-llvm -fexperimental-relative-c++-abi-vtables -fhalf-no-semantic-interposition | FileCheck %s // The inline function is emitted in each module with the same comdat // CHECK: $_ZTS1A = comdat any diff --git a/clang/test/CodeGenCXX/RelativeVTablesABI/cross-translation-unit-1.cpp b/clang/test/CodeGenCXX/RelativeVTablesABI/cross-translation-unit-1.cpp index 3a7f65a7265664..381eb246a3baec 100644 --- a/clang/test/CodeGenCXX/RelativeVTablesABI/cross-translation-unit-1.cpp +++ b/clang/test/CodeGenCXX/RelativeVTablesABI/cross-translation-unit-1.cpp @@ -1,7 +1,7 @@ // Check the vtable layout for classes with key functions defined in different // translation units. This TU only manifests the vtable for A. -// RUN: %clang_cc1 %s -triple=aarch64-unknown-fuchsia -O1 -S -o - -emit-llvm -fexperimental-relative-c++-abi-vtables | FileCheck %s +// RUN: %clang_cc1 %s -triple=aarch64-unknown-fuchsia -O1 -S -o - -emit-llvm -fexperimental-relative-c++-abi-vtables -fhalf-no-semantic-interposition | FileCheck %s #include "cross-tu-header.h" diff --git a/clang/test/CodeGenCXX/RelativeVTablesABI/cross-translation-unit-2.cpp b/clang/test/CodeGenCXX/RelativeVTablesABI/cross-translation-unit-2.cpp index 10c87ea1a672fe..dafe7d57dea044 100644 --- a/clang/test/CodeGenCXX/RelativeVTablesABI/cross-translation-unit-2.cpp +++ b/clang/test/CodeGenCXX/RelativeVTablesABI/cross-translation-unit-2.cpp @@ -1,7 +1,7 @@ // Check the vtable layout for classes with key functions defined in different // translation units. This TU manifests the vtable for B. -// RUN: %clang_cc1 %s -triple=aarch64-unknown-fuchsia -O1 -S -o - -emit-llvm -fexperimental-relative-c++-abi-vtables | FileCheck %s +// RUN: %clang_cc1 %s -triple=aarch64-unknown-fuchsia -O1 -S -o - -emit-llvm -fexperimental-relative-c++-abi-vtables -fhalf-no-semantic-interposition | FileCheck %s #include "cross-tu-header.h" diff --git a/clang/test/CodeGenCXX/RelativeVTablesABI/diamond-inheritance.cpp b/clang/test/CodeGenCXX/RelativeVTablesABI/diamond-inheritance.cpp index e42e402ec0a4a2..03165ddb02824b 100644 --- a/clang/test/CodeGenCXX/RelativeVTablesABI/diamond-inheritance.cpp +++ b/clang/test/CodeGenCXX/RelativeVTablesABI/diamond-inheritance.cpp @@ -1,7 +1,7 @@ // Diamond inheritance. // A more complicated multiple inheritance example that includes longer chain of inheritance and a common ancestor. -// RUN: %clang_cc1 %s -triple=aarch64-unknown-fuchsia -O1 -S -o - -emit-llvm -fexperimental-relative-c++-abi-vtables | FileCheck %s +// RUN: %clang_cc1 %s -triple=aarch64-unknown-fuchsia -O1 -S -o - -emit-llvm -fexperimental-relative-c++-abi-vtables -fhalf-no-semantic-interposition | FileCheck %s // CHECK-DAG: %class.B = type { %class.A } // CHECK-DAG: %class.A = type { i32 (...)** } diff --git a/clang/test/CodeGenCXX/RelativeVTablesABI/diamond-virtual-inheritance.cpp b/clang/test/CodeGenCXX/RelativeVTablesABI/diamond-virtual-inheritance.cpp index 0fff28ab8a0964..af6c3622253424 100644 --- a/clang/test/CodeGenCXX/RelativeVTablesABI/diamond-virtual-inheritance.cpp +++ b/clang/test/CodeGenCXX/RelativeVTablesABI/diamond-virtual-inheritance.cpp @@ -1,7 +1,7 @@ // Diamond virtual inheritance. // This should cover virtual inheritance, construction vtables, and VTTs. -// RUN: %clang_cc1 %s -triple=aarch64-unknown-fuchsia -O1 -S -o - -emit-llvm -fexperimental-relative-c++-abi-vtables | FileCheck %s +// RUN: %clang_cc1 %s -triple=aarch64-unknown-fuchsia -O1 -S -o - -emit-llvm -fexperimental-relative-c++-abi-vtables -fhalf-no-semantic-interposition | FileCheck %s // Class A contains a vtable ptr, then int, then padding // CHECK-DAG: %class.B = type { i32 (...)**, %class.A.base } diff --git a/clang/test/CodeGenCXX/RelativeVTablesABI/inheritted-virtual-function.cpp b/clang/test/CodeGenCXX/RelativeVTablesABI/inheritted-virtual-function.cpp index 4622970823f4ee..7c9da5d333cb2a 100644 --- a/clang/test/CodeGenCXX/RelativeVTablesABI/inheritted-virtual-function.cpp +++ b/clang/test/CodeGenCXX/RelativeVTablesABI/inheritted-virtual-function.cpp @@ -1,7 +1,7 @@ // Check the layout of the vtable for a child class that inherits a virtual // function but does not override it. -// RUN: %clang_cc1 %s -triple=aarch64-unknown-fuchsia -O1 -S -o - -emit-llvm -fexperimental-relative-c++-abi-vtables | FileCheck %s +// RUN: %clang_cc1 %s -triple=aarch64-unknown-fuchsia -O1 -S -o - -emit-llvm -fexperimental-relative-c++-abi-vtables -fhalf-no-semantic-interposition | FileCheck %s class A { public: diff --git a/clang/test/CodeGenCXX/RelativeVTablesABI/inline-virtual-function.cpp b/clang/test/CodeGenCXX/RelativeVTablesABI/inline-virtual-function.cpp index 900e9429bc7e7a..77f666dec1ee17 100644 --- a/clang/test/CodeGenCXX/RelativeVTablesABI/inline-virtual-function.cpp +++ b/clang/test/CodeGenCXX/RelativeVTablesABI/inline-virtual-function.cpp @@ -1,8 +1,8 @@ // The VTable is not in a comdat but the inline methods are. // This doesn’t affect the vtable or the stubs we emit. -// RUN: %clang_cc1 %s -triple=aarch64 -O1 -S -o - -emit-llvm -fexperimental-relative-c++-abi-vtables | FileCheck %s -// RUN: %clang_cc1 %s -triple=x86_64 -O1 -S -o - -emit-llvm -fexperimental-relative-c++-abi-vtables | FileCheck %s +// RUN: %clang_cc1 %s -triple=aarch64 -O1 -S -o - -emit-llvm -fexperimental-relative-c++-abi-vtables -fhalf-no-semantic-interposition | FileCheck %s +// RUN: %clang_cc1 %s -triple=x86_64 -O1 -S -o - -emit-llvm -fexperimental-relative-c++-abi-vtables -fhalf-no-semantic-interposition | FileCheck %s // CHECK: $_ZTI1A.rtti_proxy = comdat any diff --git a/clang/test/CodeGenCXX/RelativeVTablesABI/multiple-inheritance.cpp b/clang/test/CodeGenCXX/RelativeVTablesABI/multiple-inheritance.cpp index 8d888e69ed628c..547bac85dafeac 100644 --- a/clang/test/CodeGenCXX/RelativeVTablesABI/multiple-inheritance.cpp +++ b/clang/test/CodeGenCXX/RelativeVTablesABI/multiple-inheritance.cpp @@ -1,6 +1,6 @@ // Multiple inheritance. -// RUN: %clang_cc1 %s -triple=aarch64-unknown-fuchsia -O1 -S -o - -emit-llvm -fexperimental-relative-c++-abi-vtables | FileCheck %s +// RUN: %clang_cc1 %s -triple=aarch64-unknown-fuchsia -O1 -S -o - -emit-llvm -fexperimental-relative-c++-abi-vtables -fhalf-no-semantic-interposition | FileCheck %s // CHECK: %class.C = type { %class.A, %class.B } // CHECK: %class.A = type { i32 (...)** } diff --git a/clang/test/CodeGenCXX/RelativeVTablesABI/no-alias-when-dso-local.cpp b/clang/test/CodeGenCXX/RelativeVTablesABI/no-alias-when-dso-local.cpp index 8e04df39e64e49..89fe6da2a4e46e 100644 --- a/clang/test/CodeGenCXX/RelativeVTablesABI/no-alias-when-dso-local.cpp +++ b/clang/test/CodeGenCXX/RelativeVTablesABI/no-alias-when-dso-local.cpp @@ -1,7 +1,7 @@ // Check that no alias is emitted when the vtable is already dso_local. This can // happen if the class is hidden. -// RUN: %clang_cc1 %s -triple=aarch64-unknown-fuchsia -S -o - -emit-llvm -fexperimental-relative-c++-abi-vtables | FileCheck %s --check-prefix=DEFAULT-VIS +// RUN: %clang_cc1 %s -triple=aarch64-unknown-fuchsia -S -o - -emit-llvm -fexperimental-relative-c++-abi-vtables -fhalf-no-semantic-interposition | FileCheck %s --check-prefix=DEFAULT-VIS // RUN: %clang_cc1 %s -triple=aarch64-unknown-fuchsia -S -o - -emit-llvm -fexperimental-relative-c++-abi-vtables -fvisibility hidden | FileCheck %s --check-prefix=HIDDEN-VIS // DEFAULT-VIS: @_ZTV1A.local = private unnamed_addr constant diff --git a/clang/test/CodeGenCXX/RelativeVTablesABI/override-pure-virtual-method.cpp b/clang/test/CodeGenCXX/RelativeVTablesABI/override-pure-virtual-method.cpp index 0d894ac899ffdb..2a1ecf567d8692 100644 --- a/clang/test/CodeGenCXX/RelativeVTablesABI/override-pure-virtual-method.cpp +++ b/clang/test/CodeGenCXX/RelativeVTablesABI/override-pure-virtual-method.cpp @@ -2,7 +2,7 @@ // We instead emit zero for the pure virtual function component. See PR43094 for // details. -// RUN: %clang_cc1 %s -triple=aarch64-unknown-fuchsia -O1 -S -o - -emit-llvm -fexperimental-relative-c++-abi-vtables | FileCheck %s +// RUN: %clang_cc1 %s -triple=aarch64-unknown-fuchsia -O1 -S -o - -emit-llvm -fexperimental-relative-c++-abi-vtables -fhalf-no-semantic-interposition | FileCheck %s // CHECK: @_ZTV1A.local = private unnamed_addr constant { [4 x i32] } { [4 x i32] [i32 0, i32 trunc (i64 sub (i64 ptrtoint ({ i8*, i8* }** @_ZTI1A.rtti_proxy to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [4 x i32] }, { [4 x i32] }* @_ZTV1A.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 0, i32 trunc (i64 sub (i64 ptrtoint (void (%class.A*)* dso_local_equivalent @_ZN1A3barEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [4 x i32] }, { [4 x i32] }* @_ZTV1A.local, i32 0, i32 0, i32 2) to i64)) to i32)] }, align 4 diff --git a/clang/test/CodeGenCXX/RelativeVTablesABI/overriden-virtual-function.cpp b/clang/test/CodeGenCXX/RelativeVTablesABI/overriden-virtual-function.cpp index 95e9c44706d065..4ec08d7eee74d1 100644 --- a/clang/test/CodeGenCXX/RelativeVTablesABI/overriden-virtual-function.cpp +++ b/clang/test/CodeGenCXX/RelativeVTablesABI/overriden-virtual-function.cpp @@ -1,7 +1,7 @@ // Check the layout of the vtable for a child class that inherits a virtual // function but does override it. -// RUN: %clang_cc1 %s -triple=aarch64-unknown-fuchsia -O1 -S -o - -emit-llvm -fexperimental-relative-c++-abi-vtables | FileCheck %s +// RUN: %clang_cc1 %s -triple=aarch64-unknown-fuchsia -O1 -S -o - -emit-llvm -fexperimental-relative-c++-abi-vtables -fhalf-no-semantic-interposition | FileCheck %s // CHECK: @_ZTV1B.local = private unnamed_addr constant { [4 x i32] } { [4 x i32] [i32 0, i32 trunc (i64 sub (i64 ptrtoint ({ i8*, i8*, i8* }** @_ZTI1B.rtti_proxy to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [4 x i32] }, { [4 x i32] }* @_ZTV1B.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.B*)* dso_local_equivalent @_ZN1B3fooEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [4 x i32] }, { [4 x i32] }* @_ZTV1B.local, i32 0, i32 0, i32 2) to i64)) to i32), i32 trunc (i64 sub (i64 ptrtoint (void (%class.B*)* dso_local_equivalent @_ZN1B3barEv to i64), i64 ptrtoint (i32* getelementptr inbounds ({ [4 x i32] }, { [4 x i32] }* @_ZTV1B.local, i32 0, i32 0, i32 2) to i64)) to i32)] }, align 4 diff --git a/clang/test/CodeGenCXX/RelativeVTablesABI/relative-vtables-flag.cpp b/clang/test/CodeGenCXX/RelativeVTablesABI/relative-vtables-flag.cpp index 57ff203f16f478..b141b2faec4528 100644 --- a/clang/test/CodeGenCXX/RelativeVTablesABI/relative-vtables-flag.cpp +++ b/clang/test/CodeGenCXX/RelativeVTablesABI/relative-vtables-flag.cpp @@ -3,7 +3,7 @@ // of a soft incremental rollout. This ABI should only be used if the flag for // it is passed on Fuchsia. -// RUN: %clang_cc1 %s -triple=aarch64-unknown-fuchsia -S -o - -emit-llvm -fexperimental-relative-c++-abi-vtables | FileCheck --check-prefix=RELATIVE-ABI %s +// RUN: %clang_cc1 %s -triple=aarch64-unknown-fuchsia -S -o - -emit-llvm -fexperimental-relative-c++-abi-vtables -fhalf-no-semantic-interposition | FileCheck --check-prefix=RELATIVE-ABI %s // RUN: %clang_cc1 %s -triple=aarch64-unknown-fuchsia -S -o - -emit-llvm -fno-experimental-relative-c++-abi-vtables | FileCheck --check-prefix=DEFAULT-ABI %s // RUN: %clang_cc1 %s -triple=aarch64-unknown-fuchsia -S -o - -emit-llvm | FileCheck --check-prefix=DEFAULT-ABI %s diff --git a/clang/test/CodeGenCXX/RelativeVTablesABI/simple-vtable-definition.cpp b/clang/test/CodeGenCXX/RelativeVTablesABI/simple-vtable-definition.cpp index 29a02b57226bbc..c9dee26b77ce46 100644 --- a/clang/test/CodeGenCXX/RelativeVTablesABI/simple-vtable-definition.cpp +++ b/clang/test/CodeGenCXX/RelativeVTablesABI/simple-vtable-definition.cpp @@ -1,6 +1,6 @@ // Check the layout of the vtable for a normal class. -// RUN: %clang_cc1 %s -triple=aarch64-unknown-fuchsia -O1 -S -o - -emit-llvm -fexperimental-relative-c++-abi-vtables | FileCheck %s +// RUN: %clang_cc1 %s -triple=aarch64-unknown-fuchsia -O1 -S -o - -emit-llvm -fexperimental-relative-c++-abi-vtables -fhalf-no-semantic-interposition | FileCheck %s // We should be emitting comdats for each of the virtual function RTTI proxies // CHECK: $_ZTI1A.rtti_proxy = comdat any diff --git a/clang/test/Driver/fsemantic-interposition.c b/clang/test/Driver/fsemantic-interposition.c index af3e7575a79971..af76daf7e1be4e 100644 --- a/clang/test/Driver/fsemantic-interposition.c +++ b/clang/test/Driver/fsemantic-interposition.c @@ -2,12 +2,27 @@ // RUN: %clang -target x86_64 %s -Werror -fPIC -fsemantic-interposition -c -### 2>&1 | FileCheck %s // CHECK: "-fsemantic-interposition" -/// Require explicit -fno-semantic-interposition to infer dso_local. -// RUN: %clang -target x86_64 %s -Werror -fPIC -fsemantic-interposition -fno-semantic-interposition -c -### 2>&1 | FileCheck --check-prefix=EXPLICIT_NO %s -// EXPLICIT_NO: "-fno-semantic-interposition" +/// No-op for -fno-pic/-fpie. +// RUN: %clang -target x86_64 %s -Werror -fsemantic-interposition -c -### 2>&1 | FileCheck --check-prefix=NOOP %s +// RUN: %clang -target x86_64 %s -Werror -fPIE -fsemantic-interposition -c -### 2>&1 | FileCheck --check-prefix=NOOP %s +// NOOP-NOT: "-fsemantic-interposition" +// NOOP-NOT: "-fno-semantic-interposition" -// RUN: %clang -target x86_64 %s -Werror -fsemantic-interposition -c -### 2>&1 | FileCheck --check-prefix=NO %s -// RUN: %clang -target x86_64 %s -Werror -fPIC -c -### 2>&1 | FileCheck --check-prefix=NO %s -// RUN: %clang -target x86_64 %s -Werror -fPIE -fsemantic-interposition -c -### 2>&1 | FileCheck --check-prefix=NO %s +/// If -fno-semantic-interposition is specified and the target supports local +/// aliases, neither CC1 option is set. +// RUN: %clang -target i386 %s -Werror -fPIC -fno-semantic-interposition -c -### 2>&1 | FileCheck --check-prefix=NO %s +// RUN: %clang -target x86_64 %s -Werror -fPIC -fno-semantic-interposition -c -### 2>&1 | FileCheck --check-prefix=NO %s // NO-NOT: "-fsemantic-interposition" -// NO-NOT: "-fno-semantic-interposition" +// NO-NOT: "-fhalf-no-semantic-interposition" + +/// If neither -fsemantic-interposition or -fno-semantic-interposition is specified, +/// or -fno-semantic-interposition is specified but the target does not support +/// local aliases, use the traditional half-baked behavor: interprocedural +/// optimizations are allowed but local aliases are not used. If references are +/// not optimized out, semantic interposition at runtime is possible. +// RUN: %clang -target aarch64 %s -Werror -fPIC -fno-semantic-interposition -c -### 2>&1 | FileCheck --check-prefix=HALF %s +// RUN: %clang -target ppc64le %s -Werror -fPIC -fno-semantic-interposition -c -### 2>&1 | FileCheck --check-prefix=HALF %s + +// RUN: %clang -target x86_64 %s -Werror -fPIC -c -### 2>&1 | FileCheck --check-prefix=HALF %s +// +// HALF: "-fhalf-no-semantic-interposition" diff --git a/llvm/include/llvm/IR/Module.h b/llvm/include/llvm/IR/Module.h index 2ec6f962e44351..3664b275114d62 100644 --- a/llvm/include/llvm/IR/Module.h +++ b/llvm/include/llvm/IR/Module.h @@ -855,7 +855,6 @@ class Module { /// Returns whether semantic interposition is to be respected. bool getSemanticInterposition() const; - bool noSemanticInterposition() const; /// Set whether semantic interposition is to be respected. void setSemanticInterposition(bool); diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 7f7ea18e72b88c..6732c35e20942c 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -483,10 +483,8 @@ MCSymbol *AsmPrinter::getSymbolPreferLocal(const GlobalValue &GV) const { if (TM.getTargetTriple().isOSBinFormatELF() && GV.canBenefitFromLocalAlias()) { const Module &M = *GV.getParent(); if (TM.getRelocationModel() != Reloc::Static && - M.getPIELevel() == PIELevel::Default) - if (GV.isDSOLocal() || (TM.getTargetTriple().isX86() && - GV.getParent()->noSemanticInterposition())) - return getSymbolWithGlobalValueBase(&GV, "$local"); + M.getPIELevel() == PIELevel::Default && GV.isDSOLocal()) + return getSymbolWithGlobalValueBase(&GV, "$local"); } return TM.getSymbol(&GV); } diff --git a/llvm/lib/IR/Module.cpp b/llvm/lib/IR/Module.cpp index b6fde57c70d02f..b4f10e2e2d2397 100644 --- a/llvm/lib/IR/Module.cpp +++ b/llvm/lib/IR/Module.cpp @@ -601,13 +601,6 @@ void Module::setSemanticInterposition(bool SI) { addModuleFlag(ModFlagBehavior::Error, "SemanticInterposition", SI); } -bool Module::noSemanticInterposition() const { - // Conservatively require an explicit zero value for now. - Metadata *MF = getModuleFlag("SemanticInterposition"); - auto *Val = cast_or_null(MF); - return Val && cast(Val->getValue())->getZExtValue() == 0; -} - void Module::setOwnedMemoryBuffer(std::unique_ptr MB) { OwnedMemoryBuffer = std::move(MB); }