serge-sans-paille created this revision.
serge-sans-paille added reviewers: MaskRay, hfinkel.
Herald added subscribers: llvm-commits, cfe-commits, haicheng, hiraditya, 
eraman.
Herald added projects: clang, LLVM.
serge-sans-paille added a comment.

@MaskRay no example yet, I'd like your opinion on the approach first. It has 
the advantage of being non intrusive to the code base...


First attempt at implementing -fsemantic-interposition.

Rely on `GlobalValue::isInterposable` that already captures most of the 
expected behavior.

Rely on a `ModuleFlag` to state whether we should respect SemanticInterposition 
or not. The default remains no.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D72829

Files:
  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
  llvm/include/llvm/IR/GlobalValue.h
  llvm/include/llvm/IR/Module.h
  llvm/lib/Analysis/InlineCost.cpp
  llvm/lib/IR/Globals.cpp
  llvm/lib/IR/Module.cpp

Index: llvm/lib/IR/Module.cpp
===================================================================
--- llvm/lib/IR/Module.cpp
+++ llvm/lib/IR/Module.cpp
@@ -559,6 +559,20 @@
                : getModuleFlag("ProfileSummary"));
 }
 
+bool Module::getSemanticInterposition() const {
+  auto *Val =
+      cast_or_null<ConstantAsMetadata>(getModuleFlag("SemanticInterposition"));
+
+  if (!Val)
+    return false;
+
+  return cast<ConstantInt>(Val->getValue())->getZExtValue();
+}
+
+void Module::setSemanticInterposition(bool SI) {
+  addModuleFlag(ModFlagBehavior::Error, "SemanticInterposition", SI);
+}
+
 void Module::setOwnedMemoryBuffer(std::unique_ptr<MemoryBuffer> MB) {
   OwnedMemoryBuffer = std::move(MB);
 }
Index: llvm/lib/IR/Globals.cpp
===================================================================
--- llvm/lib/IR/Globals.cpp
+++ llvm/lib/IR/Globals.cpp
@@ -94,6 +94,13 @@
   llvm_unreachable("not a global");
 }
 
+bool GlobalValue::isInterposable() const {
+  if (getParent() && getParent()->getSemanticInterposition() &&
+      isDSOPreemptable())
+    return true;
+  return isInterposableLinkage(getLinkage());
+}
+
 unsigned GlobalValue::getAlignment() const {
   if (auto *GA = dyn_cast<GlobalAlias>(this)) {
     // In general we cannot compute this at the IR level, but we try.
Index: llvm/lib/Analysis/InlineCost.cpp
===================================================================
--- llvm/lib/Analysis/InlineCost.cpp
+++ llvm/lib/Analysis/InlineCost.cpp
@@ -1842,7 +1842,7 @@
     } else if (Operator::getOpcode(V) == Instruction::BitCast) {
       V = cast<Operator>(V)->getOperand(0);
     } else if (GlobalAlias *GA = dyn_cast<GlobalAlias>(V)) {
-      if (GA->isInterposable())
+      if (GA->isInterposable() || GA->isDSOPreemptable())
         break;
       V = GA->getAliasee();
     } else {
Index: llvm/include/llvm/IR/Module.h
===================================================================
--- llvm/include/llvm/IR/Module.h
+++ llvm/include/llvm/IR/Module.h
@@ -846,6 +846,17 @@
   Metadata *getProfileSummary(bool IsCS);
   /// @}
 
+  /// @name Utility functions for querying and setting semantic interposition
+  /// @{
+
+  /// Returns whether semantic interposition is to be respected.
+  bool getSemanticInterposition() const;
+
+  /// Set whether semantic interposition is to be respected.
+  void setSemanticInterposition(bool);
+
+  /// @}
+
   /// Returns true if PLT should be avoided for RTLib calls.
   bool getRtLibUseGOT() const;
 
Index: llvm/include/llvm/IR/GlobalValue.h
===================================================================
--- llvm/include/llvm/IR/GlobalValue.h
+++ llvm/include/llvm/IR/GlobalValue.h
@@ -284,6 +284,8 @@
     return IsDSOLocal;
   }
 
+  bool isDSOPreemptable() const { return !IsDSOLocal; }
+
   bool hasPartition() const {
     return HasPartition;
   }
@@ -426,7 +428,7 @@
   /// *arbitrary* definition at link time.  We cannot do any IPO or inlinining
   /// across interposable call edges, since the callee can be replaced with
   /// something arbitrary at link time.
-  bool isInterposable() const { return isInterposableLinkage(getLinkage()); }
+  bool isInterposable() const;
 
   bool hasExternalLinkage() const { return isExternalLinkage(getLinkage()); }
   bool hasAvailableExternallyLinkage() const {
Index: clang/lib/Frontend/CompilerInvocation.cpp
===================================================================
--- clang/lib/Frontend/CompilerInvocation.cpp
+++ clang/lib/Frontend/CompilerInvocation.cpp
@@ -2679,6 +2679,13 @@
     Opts.setValueVisibilityMode(DefaultVisibility);
   }
 
+  // Semantic interposition mode defaults to "false".
+  if (Arg *siOpt = Args.getLastArg(OPT_fsemantic_interposition,
+                                   OPT_fno_semantic_interposition)) {
+    Opts.SemanticInterposition =
+        unsigned(siOpt->getOption().getID() == OPT_fsemantic_interposition);
+  }
+
   // The type-visibility mode defaults to the value-visibility mode.
   if (Arg *typeVisOpt = Args.getLastArg(OPT_ftype_visibility)) {
     Opts.setTypeVisibilityMode(parseVisibility(typeVisOpt, Args, Diags));
Index: clang/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -5002,6 +5002,8 @@
   Args.AddLastArg(CmdArgs, options::OPT_femulated_tls,
                   options::OPT_fno_emulated_tls);
   Args.AddLastArg(CmdArgs, options::OPT_fkeep_static_consts);
+  Args.AddLastArg(CmdArgs, options::OPT_fsemantic_interposition,
+                  options::OPT_fno_semantic_interposition);
 
   // AltiVec-like language extensions aren't relevant for assembling.
   if (!isa<PreprocessJobAction>(JA) || Output.getType() != types::TY_PP_Asm)
Index: clang/lib/CodeGen/CodeGenModule.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -483,6 +483,11 @@
     getModule().addModuleFlag(llvm::Module::Max, "Dwarf Version",
                               CodeGenOpts.DwarfVersion);
   }
+
+  if (Context.getLangOpts().SemanticInterposition)
+    // Require various optimization to respect semantic interposition.
+    getModule().setSemanticInterposition(1);
+
   if (CodeGenOpts.EmitCodeView) {
     // Indicate that we want CodeView in the metadata.
     getModule().addModuleFlag(llvm::Module::Warning, "CodeView", 1);
@@ -856,7 +861,7 @@
   if (isa<llvm::Function>(GV) && !CGOpts.NoPLT && RM == llvm::Reloc::Static)
     return true;
 
-  // Otherwise don't assue it is local.
+  // Otherwise don't assume it is local.
   return false;
 }
 
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -3262,7 +3262,8 @@
 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 : Flag<["-"], "fno-semantic-interposition">, Group<clang_ignored_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]>;
 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>;
Index: clang/include/clang/Basic/LangOptions.def
===================================================================
--- clang/include/clang/Basic/LangOptions.def
+++ clang/include/clang/Basic/LangOptions.def
@@ -284,6 +284,7 @@
              "default visibility for types [-ftype-visibility]")
 LANGOPT(SetVisibilityForExternDecls, 1, 0,
         "apply global symbol visibility to external declarations without an explicit visibility")
+BENIGN_LANGOPT(SemanticInterposition        , 1, 0, "semantic interposition")
 ENUM_LANGOPT(StackProtector, StackProtectorMode, 2, SSPOff,
              "stack protector mode")
 ENUM_LANGOPT(TrivialAutoVarInit, TrivialAutoVarInitKind, 2, TrivialAutoVarInitKind::Uninitialized,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to