Refactor how -fno-semantic-interposition sets dso_local on default visibility externa...
authorFangrui Song <i@maskray.me>
Thu, 31 Dec 2020 21:59:45 +0000 (13:59 -0800)
committerFangrui Song <i@maskray.me>
Thu, 31 Dec 2020 21:59:45 +0000 (13:59 -0800)
The idea is that the CC1 default for ELF should set dso_local on default
visibility external linkage definitions in the default -mrelocation-model pic
mode (-fpic/-fPIC) to match COFF/Mach-O and make output IR similar.

The refactoring is made available by 2820a2ca3a0e69c3f301845420e0067ffff2251b.

Currently only x86 supports local aliases. We move the decision to the driver.
There are three CC1 states:

* -fsemantic-interposition: make some linkages interposable and make default visibility external linkage definitions dso_preemptable.
* (default): selected if the target supports .Lfoo$local: make default visibility external linkage definitions dso_local
* -fhalf-no-semantic-interposition: if neither option is set or the target does not support .Lfoo$local: like -fno-semantic-interposition but local aliases are not used. So references can be interposed if not optimized out.

Add -fhalf-no-semantic-interposition to a few tests using the half-based semantic interposition behavior.

25 files changed:
clang/include/clang/Basic/LangOptions.def
clang/include/clang/Driver/Options.td
clang/lib/CodeGen/CodeGenModule.cpp
clang/lib/Driver/ToolChains/Clang.cpp
clang/lib/Frontend/CompilerInvocation.cpp
clang/test/CodeGen/attr-arm-sve-vector-bits-globals.c
clang/test/CodeGen/semantic-interposition-no.c [deleted file]
clang/test/CodeGen/semantic-interposition.c
clang/test/CodeGenCXX/RelativeVTablesABI/child-inheritted-from-parent-in-comdat.cpp
clang/test/CodeGenCXX/RelativeVTablesABI/cross-translation-unit-1.cpp
clang/test/CodeGenCXX/RelativeVTablesABI/cross-translation-unit-2.cpp
clang/test/CodeGenCXX/RelativeVTablesABI/diamond-inheritance.cpp
clang/test/CodeGenCXX/RelativeVTablesABI/diamond-virtual-inheritance.cpp
clang/test/CodeGenCXX/RelativeVTablesABI/inheritted-virtual-function.cpp
clang/test/CodeGenCXX/RelativeVTablesABI/inline-virtual-function.cpp
clang/test/CodeGenCXX/RelativeVTablesABI/multiple-inheritance.cpp
clang/test/CodeGenCXX/RelativeVTablesABI/no-alias-when-dso-local.cpp
clang/test/CodeGenCXX/RelativeVTablesABI/override-pure-virtual-method.cpp
clang/test/CodeGenCXX/RelativeVTablesABI/overriden-virtual-function.cpp
clang/test/CodeGenCXX/RelativeVTablesABI/relative-vtables-flag.cpp
clang/test/CodeGenCXX/RelativeVTablesABI/simple-vtable-definition.cpp
clang/test/Driver/fsemantic-interposition.c
llvm/include/llvm/IR/Module.h
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
llvm/lib/IR/Module.cpp

index cc5eb939dbd294bc528c47acfb284b99258c56eb..963fde5f3ad4be768b2ff9ea2c0580b4bd2d43ec 100644 (file)
@@ -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,
index af209eb9089d7f38b753ecd12d0720df890db4ec..9a851f63a663c2f765f3272e6262cc1376e13ac4 100644 (file)
@@ -3793,7 +3793,7 @@ defm ipa_cp : BooleanFFlag<"ipa-cp">,
     Group<clang_ignored_gcc_optimization_f_Group>;
 defm ivopts : BooleanFFlag<"ivopts">, Group<clang_ignored_gcc_optimization_f_Group>;
 def fsemantic_interposition : Flag<["-"], "fsemantic-interposition">, Group<f_Group>, Flags<[CC1Option]>;
-def fno_semantic_interposition: Flag<["-"], "fno-semantic-interposition">, Group<f_Group>, Flags<[CC1Option]>;
+def fno_semantic_interposition: Flag<["-"], "fno-semantic-interposition">, Group<f_Group>;
 defm non_call_exceptions : BooleanFFlag<"non-call-exceptions">, Group<clang_ignored_f_Group>;
 defm peel_loops : BooleanFFlag<"peel-loops">, Group<clang_ignored_gcc_optimization_f_Group>;
 defm permissive : BooleanFFlag<"permissive">, Group<clang_ignored_f_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">;
index bf0a38bf83ab19b914e748b1b3a1fc204e2baaf1..cfc0f732748c145693e03547abc18f7d24fef935 100644 (file)
@@ -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.
index 300ab6e815e2335047cc6ed06caaac632044e7b3..5451244c43aef452e20267cbdc49799c3beb3ab3 100644 (file)
@@ -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;
index 06d8d2e27c9b77375d5aae1bdd5b428da21c4335..1d16312cf2d0bbf7cc4ea77ce968dd885fb95f38 100644 (file)
@@ -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)) {
index cb1aa6e0cf7479a5da0e8c6b315d138bc5c6702d..d81cd3627b2b0d4a29ccbe0b0246219ce9d3934a 100644 (file)
@@ -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 <arm_sve.h>
 
diff --git a/clang/test/CodeGen/semantic-interposition-no.c b/clang/test/CodeGen/semantic-interposition-no.c
deleted file mode 100644 (file)
index cc53d17..0000000
+++ /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();
-}
index 3d6c5f2872b576e6c4e86f42d249407bcca5da7e..6b402214df9cc68227ee684552deeefaa50b9f59 100644 (file)
@@ -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();
+}
index 631594c2897d34f82fb30488d21db8c75cfc1f4c..9e9a35a4a60accb1979b48483c6d7a9765c6f84b 100644 (file)
@@ -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
index 3a7f65a72656643898b3862c6d39bcf4c6027986..381eb246a3baec74fed90591c0f1c88bf8091c86 100644 (file)
@@ -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"
 
index 10c87ea1a672fe59fbc9ac46e665d0a7d43e2a19..dafe7d57dea044d14b7b97c6f297ea8aed35cc14 100644 (file)
@@ -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"
 
index e42e402ec0a4a2c0e7e6dbb952ea5d17f5d8104a..03165ddb02824bd4a39aa692f9634fefd6052d86 100644 (file)
@@ -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 (...)** }
index 0fff28ab8a0964a6f4ad882a5f1d521d7c55d1fc..af6c3622253424fbca0c66fe0a553e9ea4a382d8 100644 (file)
@@ -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 }
index 4622970823f4eee5760a04c776a012ddae9d9af0..7c9da5d333cb2a008c7731bfa387486c64c24aa6 100644 (file)
@@ -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:
index 900e9429bc7e7affd372cf662287225504e90b31..77f666dec1ee17dc4d8877cf6a9b7adb76558bea 100644 (file)
@@ -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
 
index 8d888e69ed628c9a9a95ce02362152671255c4aa..547bac85dafeaccb5d2fc68dd430fa0c3f69d13e 100644 (file)
@@ -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 (...)** }
index 8e04df39e64e49afe4e12fbd6a3683387f491cbd..89fe6da2a4e46e9f188c49ca83446de1a2c23627 100644 (file)
@@ -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
index 0d894ac899ffdb9c2bc89100e924ca7c7ea22097..2a1ecf567d8692f1fe81267c26fcccdc72fc5a1e 100644 (file)
@@ -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
 
index 95e9c44706d06597150acb6833070fbd944f9ff2..4ec08d7eee74d1864186bda995c80dffb5b5b1bf 100644 (file)
@@ -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
 
index 57ff203f16f47869cf31d7200d7e04eaac975ad1..b141b2faec4528fd807d1894e8a57b570e32a68e 100644 (file)
@@ -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
 
index 29a02b57226bbc278233cebe01a6975087efefb9..c9dee26b77ce46cdf61a6d172830f3808e08619e 100644 (file)
@@ -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
index af3e7575a799711c1078134673c20f2b0c926f3c..af76daf7e1be4ed6900079536e2fc31e5ac94eb6 100644 (file)
@@ -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"
index 2ec6f962e44351814a2b47cfb2698b8430d3886b..3664b275114d62ec0b44cdbcf26ce4dd6558e5f4 100644 (file)
@@ -855,7 +855,6 @@ public:
 
   /// 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);
index 7f7ea18e72b88c841b346eb5f32b2d6575df3e12..6732c35e20942c61294e4349342107ad3f98463c 100644 (file)
@@ -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);
 }
index b6fde57c70d02f4b1d059f9153a9af29722f801b..b4f10e2e2d23974f78998fd0e652a756108ed6ca 100644 (file)
@@ -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<ConstantAsMetadata>(MF);
-  return Val && cast<ConstantInt>(Val->getValue())->getZExtValue() == 0;
-}
-
 void Module::setOwnedMemoryBuffer(std::unique_ptr<MemoryBuffer> MB) {
   OwnedMemoryBuffer = std::move(MB);
 }