tmsriram updated this revision to Diff 255871.
tmsriram marked 4 inline comments as done.
tmsriram added a comment.

Change description and handle -ffile-prefix-map/-fmacro-prefix-map.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D73307/new/

https://reviews.llvm.org/D73307

Files:
  clang/docs/UsersManual.rst
  clang/include/clang/Basic/CodeGenOptions.def
  clang/include/clang/Driver/Options.td
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/CodeGen/CodeGenModule.h
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/test/CodeGen/unique-internal-linkage-names.cpp
  clang/test/CodeGen/unique-internal-linkage-names2.c
  clang/test/Driver/funique-internal-linkage-names.c

Index: clang/test/Driver/funique-internal-linkage-names.c
===================================================================
--- /dev/null
+++ clang/test/Driver/funique-internal-linkage-names.c
@@ -0,0 +1,4 @@
+// RUN: %clang -### -funique-internal-linkage-names %s -c 2>&1 | FileCheck -check-prefix=CHECK-OPT %s
+// RUN: %clang -### -funique-internal-linkage-names -fno-unique-internal-linkage-names %s -c 2>&1 | FileCheck -check-prefix=CHECK-NOOPT %s
+// CHECK-OPT: "-funique-internal-linkage-names"
+// CHECK-NOOPT-NOT: "-funique-internal-linkage-names"
Index: clang/test/CodeGen/unique-internal-linkage-names2.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/unique-internal-linkage-names2.c
@@ -0,0 +1,15 @@
+// This test checks if -funique-internal-linkage-names uses the right
+// path when -ffile-prefix-map= (-fmacro-prefix-map=) is enabled.
+// With -fmacro-prefix-map=%p=NEW, this file must be referenced as:
+// NEW/unique-internal-linkage-names2.c
+// MD5 hash of "NEW/unique-internal-linkage-names2.c" :
+// $ echo -n NEW/unique-internal-linkage-names2.c | md5sum
+// bd816b262f03c98ffb082cde0847804c
+// RUN: %clang_cc1 -triple x86_64 -funique-internal-linkage-names -fmacro-prefix-map=%p=NEW -x c -S -emit-llvm -o - %s | FileCheck %s
+static int glob;
+
+int getGlob() {
+  return glob;
+}
+
+// CHECK: glob.bd816b262f03c98ffb082cde0847804c = internal global
Index: clang/test/CodeGen/unique-internal-linkage-names.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGen/unique-internal-linkage-names.cpp
@@ -0,0 +1,68 @@
+// This test checks if internal linkage symbols get unique names with
+// -funique-internal-linkage-names option.
+// RUN: %clang_cc1 -triple x86_64 -x c++ -S -emit-llvm -o - < %s | FileCheck %s --check-prefix=PLAIN
+// RUN: %clang_cc1 -triple x86_64 -x c++ -S -emit-llvm -funique-internal-linkage-names -o - < %s | FileCheck %s --check-prefix=UNIQUE
+
+static int glob;
+static int foo() {
+  return 0;
+}
+
+int (*bar())() {
+  return foo;
+}
+
+int getGlob() {
+  return glob;
+}
+
+// Function local static variable and anonymous namespace namespace variable.
+namespace {
+int anon_m;
+int getM() {
+  return anon_m;
+}
+} // namespace
+
+int retAnonM() {
+  static int fGlob;
+  return getM() + fGlob;
+}
+
+// Multiversioning symbols
+__attribute__((target("default"))) static int mver() {
+  return 0;
+}
+
+__attribute__((target("sse4.2"))) static int mver() {
+  return 1;
+}
+
+int mver_call() {
+  return mver();
+}
+
+// PLAIN: @_ZL4glob = internal global
+// PLAIN: @_ZL3foov()
+// PLAIN: @_ZN12_GLOBAL__N_14getMEv
+// PLAIN: @_ZZ8retAnonMvE5fGlob
+// PLAIN: @_ZN12_GLOBAL__N_16anon_mE
+// PLAIN: @_ZL4mverv.resolver()
+// PLAIN: @_ZL4mverv()
+// PLAIN: @_ZL4mverv.sse4.2()
+// UNIQUE-NOT: @_ZL4glob = internal global
+// UNIQUE-NOT: @_ZL3foov()
+// UNIQUE-NOT: @_ZN12_GLOBAL__N_14getMEv
+// UNIQUE-NOT: @_ZZ8retAnonMvE5fGlob
+// UNIQUE-NOT: @_ZN12_GLOBAL__N_16anon_mE
+// UNIQUE-NOT: @_ZL4mverv.resolver()
+// UNIQUE-NOT: @_ZL4mverv()
+// UNIQUE-NOT: @_ZL4mverv.sse4.2()
+// UNIQUE: @_ZL4glob.{{[0-9a-f]+}} = internal global
+// UNIQUE: @_ZL3foov.{{[0-9a-f]+}}()
+// UNIQUE: @_ZN12_GLOBAL__N_14getMEv.{{[0-9a-f]+}}
+// UNIQUE: @_ZZ8retAnonMvE5fGlob.{{[0-9a-f]+}}
+// UNIQUE: @_ZN12_GLOBAL__N_16anon_mE.{{[0-9a-f]+}}
+// UNIQUE: @_ZL4mverv.{{[0-9a-f]+}}.resolver()
+// UNIQUE: @_ZL4mverv.{{[0-9a-f]+}}()
+// UNIQUE: @_ZL4mverv.{{[0-9a-f]+}}.sse4.2()
Index: clang/lib/Frontend/CompilerInvocation.cpp
===================================================================
--- clang/lib/Frontend/CompilerInvocation.cpp
+++ clang/lib/Frontend/CompilerInvocation.cpp
@@ -958,6 +958,8 @@
   Opts.DataSections = Args.hasArg(OPT_fdata_sections);
   Opts.StackSizeSection = Args.hasArg(OPT_fstack_size_section);
   Opts.UniqueSectionNames = !Args.hasArg(OPT_fno_unique_section_names);
+  Opts.UniqueInternalLinkageNames =
+      Args.hasArg(OPT_funique_internal_linkage_names);
 
   Opts.MergeFunctions = Args.hasArg(OPT_fmerge_functions);
 
Index: clang/docs/UsersManual.rst
===================================================================
--- clang/docs/UsersManual.rst
+++ clang/docs/UsersManual.rst
@@ -1677,6 +1677,27 @@
    on ELF targets when using the integrated assembler. This flag currently
    only has an effect on ELF targets.
 
+**-f[no]-unique-internal-linkage-names**
+
+   Controls whether Clang emits a unique (best-effort) symbol name for internal
+   linkage symbols.  When this option is set, compiler hashes the main source
+   file path from the command line and appends it to all internal symbols. If a
+   program contains multiple objects compiled with the same command-line source
+   file path, the symbols are not guaranteed to be unique.  This option is
+   particularly useful in attributing profile information to the correct
+   function when multiple functions with the same private linkage name exist
+   in the binary.
+
+   It should be noted that this option cannot guarantee uniqueness and the
+   following is an example where it is not unique when two modules contain
+   symbols with the same private linkage name:
+
+   .. code-block:: console
+
+     $ cd $P/foo && clang -c -funique-internal-linkage-names name_conflict.c
+     $ cd $P/bar && clang -c -funique-internal-linkage-names name_conflict.c
+     $ cd $P && clang foo/name_conflict.o && bar/name_conflict.o
+
 Profile Guided Optimization
 ---------------------------
 
Index: clang/lib/CodeGen/CodeGenModule.h
===================================================================
--- clang/lib/CodeGen/CodeGenModule.h
+++ clang/lib/CodeGen/CodeGenModule.h
@@ -28,6 +28,7 @@
 #include "clang/Basic/SanitizerBlacklist.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Basic/XRayLists.h"
+#include "clang/Lex/PreprocessorOptions.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SmallPtrSet.h"
@@ -72,7 +73,6 @@
 class LangOptions;
 class CodeGenOptions;
 class HeaderSearchOptions;
-class PreprocessorOptions;
 class DiagnosticsEngine;
 class AnnotateAttr;
 class CXXDestructorDecl;
@@ -307,6 +307,7 @@
   const TargetInfo &Target;
   std::unique_ptr<CGCXXABI> ABI;
   llvm::LLVMContext &VMContext;
+  std::string ModuleNameHash = "";
 
   std::unique_ptr<CodeGenTBAA> TBAA;
 
@@ -578,6 +579,8 @@
   /// Return true iff an Objective-C runtime has been configured.
   bool hasObjCRuntime() { return !!ObjCRuntime; }
 
+  const std::string &getModuleNameHash() const { return ModuleNameHash; }
+
   /// Return a reference to the configured OpenCL runtime.
   CGOpenCLRuntime &getOpenCLRuntime() {
     assert(OpenCLRuntime != nullptr);
Index: clang/lib/CodeGen/CodeGenModule.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -176,6 +176,25 @@
   // CoverageMappingModuleGen object.
   if (CodeGenOpts.CoverageMapping)
     CoverageMapping.reset(new CoverageMappingModuleGen(*this, *CoverageInfo));
+
+  // Generate the module name hash here if needed.
+  if (CodeGenOpts.UniqueInternalLinkageNames &&
+      !getModule().getSourceFileName().empty()) {
+    std::string Path = getModule().getSourceFileName();
+    // Check if a path substitution is needed from the MacroPrefixMap.
+    for (const auto &Entry : PPO.MacroPrefixMap)
+      if (Path.rfind(Entry.first, 0) != std::string::npos) {
+        Path = Entry.second + Path.substr(Entry.first.size());
+        break;
+      }
+    llvm::MD5 Md5;
+    Md5.update(Path);
+    llvm::MD5::MD5Result R;
+    Md5.final(R);
+    SmallString<32> Str;
+    llvm::MD5::stringifyResult(R, Str);
+    ModuleNameHash = ("." + Str).str();
+  }
 }
 
 CodeGenModule::~CodeGenModule() {}
@@ -1046,7 +1065,7 @@
   }
 }
 
-static std::string getMangledNameImpl(const CodeGenModule &CGM, GlobalDecl GD,
+static std::string getMangledNameImpl(CodeGenModule &CGM, GlobalDecl GD,
                                       const NamedDecl *ND,
                                       bool OmitMultiVersionMangling = false) {
   SmallString<256> Buffer;
@@ -1070,6 +1089,19 @@
     }
   }
 
+  // Check if the module name hash should be appended for internal linkage
+  // symbols.
+  const Decl *D = GD.getDecl();
+  if (!CGM.getModuleNameHash().empty() &&
+      ((isa<FunctionDecl>(D) &&
+        CGM.getFunctionLinkage(GD) == llvm::GlobalValue::InternalLinkage) ||
+       (isa<VarDecl>(D) && CGM.getContext().GetGVALinkageForVariable(
+                               cast<VarDecl>(D)) == GVA_Internal))) {
+    assert(CGM.getCodeGenOpts().UniqueInternalLinkageNames &&
+           "Hash computed when not explicitly requested");
+    Out << CGM.getModuleNameHash();
+  }
+
   if (const auto *FD = dyn_cast<FunctionDecl>(ND))
     if (FD->isMultiVersion() && !OmitMultiVersionMangling) {
       switch (FD->getMultiVersionKind()) {
Index: clang/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -4254,6 +4254,8 @@
         options::OPT_fno_function_sections,
         options::OPT_fdata_sections,
         options::OPT_fno_data_sections,
+        options::OPT_funique_internal_linkage_names,
+        options::OPT_fno_unique_internal_linkage_names,
         options::OPT_funique_section_names,
         options::OPT_fno_unique_section_names,
         options::OPT_mrestrict_it,
@@ -4861,6 +4863,10 @@
                     options::OPT_fno_unique_section_names, true))
     CmdArgs.push_back("-fno-unique-section-names");
 
+  if (Args.hasFlag(options::OPT_funique_internal_linkage_names,
+                   options::OPT_fno_unique_internal_linkage_names, false))
+    CmdArgs.push_back("-funique-internal-linkage-names");
+
   Args.AddLastArg(CmdArgs, options::OPT_finstrument_functions,
                   options::OPT_finstrument_functions_after_inlining,
                   options::OPT_finstrument_function_entry_bare);
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -1985,6 +1985,12 @@
 def fno_unique_section_names : Flag <["-"], "fno-unique-section-names">,
   Group<f_Group>, Flags<[CC1Option]>;
 
+def funique_internal_linkage_names : Flag <["-"], "funique-internal-linkage-names">,
+  Group<f_Group>, Flags<[CC1Option]>,
+  HelpText<"Uniqueify Internal Linkage Symbol Names by appending the MD5 hash of the module path">;
+def fno_unique_internal_linkage_names : Flag <["-"], "fno-unique-internal-linkage-names">,
+  Group<f_Group>;
+
 def fstrict_return : Flag<["-"], "fstrict-return">, Group<f_Group>,
   Flags<[CC1Option]>,
   HelpText<"Always treat control flow paths that fall off the end of a "
Index: clang/include/clang/Basic/CodeGenOptions.def
===================================================================
--- clang/include/clang/Basic/CodeGenOptions.def
+++ clang/include/clang/Basic/CodeGenOptions.def
@@ -161,6 +161,7 @@
 CODEGENOPT(NoTrappingMath    , 1, 0) ///< Set when -fno-trapping-math is enabled.
 CODEGENOPT(NoNaNsFPMath      , 1, 0) ///< Assume FP arguments, results not NaN.
 CODEGENOPT(CorrectlyRoundedDivSqrt, 1, 0) ///< -cl-fp32-correctly-rounded-divide-sqrt
+CODEGENOPT(UniqueInternalLinkageNames, 1, 0) ///< Internal Linkage symbols get unique names.
 
 /// When false, this attempts to generate code as if the result of an
 /// overflowing conversion matches the overflowing behavior of a target's native
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to