alexbdv created this revision.
alexbdv added reviewers: MaskRay, vsk, JonasToth, ruiu.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Function blocks don't have a name specified in source code. Currently their 
symbol name is based on the parent function's name and an index. 
Ex: _ZN1Parent_Funciton_block_invoke_1
One issue that happens with the current naming scheme is that in subsequent 
builds, the name of the function block can change even if the function block or 
the parent function has changed. This presents issues for tools that use symbol 
names to identify changes in source code / tracking of binary metrics.

The proposed solution here is to add a flag (default=off) that enables adding a 
hash of the block contents to the block name. 
Ex: _ZN1Parent_Funciton_block_invoke_38172  (38172 is the hash)
Therefore, the function block name will only change if its content or the 
parent function name changes. And will now remain stable regardless if new 
function blocks are added.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D74813

Files:
  clang/include/clang/AST/Mangle.h
  clang/include/clang/Basic/LangOptions.def
  clang/include/clang/Driver/Options.td
  clang/lib/AST/Mangle.cpp
  clang/lib/Frontend/CompilerInvocation.cpp

Index: clang/lib/Frontend/CompilerInvocation.cpp
===================================================================
--- clang/lib/Frontend/CompilerInvocation.cpp
+++ clang/lib/Frontend/CompilerInvocation.cpp
@@ -2817,6 +2817,9 @@
   Opts.ExternCNoUnwind = Args.hasArg(OPT_fexternc_nounwind);
   Opts.TraditionalCPP = Args.hasArg(OPT_traditional_cpp);
 
+  Opts.ObjCEnableHashFuncBlockNames =
+      Args.hasArg(OPT_enable_hash_in_objc_func_block_names);
+
   Opts.RTTI = Opts.CPlusPlus && !Args.hasArg(OPT_fno_rtti);
   Opts.RTTIData = Opts.RTTI && !Args.hasArg(OPT_fno_rtti_data);
   Opts.Blocks = Args.hasArg(OPT_fblocks) || (Opts.OpenCL
Index: clang/lib/AST/Mangle.cpp
===================================================================
--- clang/lib/AST/Mangle.cpp
+++ clang/lib/AST/Mangle.cpp
@@ -24,11 +24,61 @@
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/Mangler.h"
-#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ErrorHandling.h"	
+#include "llvm/Support/MD5.h"
 #include "llvm/Support/raw_ostream.h"
 
 using namespace clang;
 
+static std::string getBlockIDByHash(const BlockDecl *BD,
+                                    unsigned discriminator) {
+  Stmt *stmt = BD ? BD->getBody() : nullptr;
+
+  std::string strOutBuff;
+  llvm::raw_string_ostream strOutStream(strOutBuff);
+
+  strOutStream << "_block_invoke";
+
+  if (!stmt) {
+    if (discriminator)
+      strOutStream << "_" << discriminator + 1;
+
+    return strOutBuff;
+  }
+
+  std::string strStmtBuff;
+  llvm::raw_string_ostream strStmtStream(strStmtBuff);
+
+  // Dump the statement IR to a text stream for hasing
+  stmt->dump(strStmtStream);
+  strStmtBuff = strStmtStream.str();
+
+  // Strip out addresses
+  char *ptr = &strStmtBuff[1];
+  while (*ptr) {
+    if (*ptr == 'x' && *(ptr - 1) == '0') {
+      ptr++;
+      while ((*ptr >= '0' && *ptr <= '9') || (*ptr >= 'a' && *ptr <= 'f')) {
+        *ptr = '_';
+        ptr++;
+      }
+      continue;
+    }
+    ptr++;
+  }
+
+  // Hash the statement string
+  llvm::MD5 Hash;
+  llvm::MD5::MD5Result Result;
+
+  Hash.update(strStmtBuff);
+  Hash.final(Result);
+
+  strOutStream << "_" << *(unsigned short *)&Result;
+  return strOutBuff;
+}
+
+
 // FIXME: For blocks we currently mimic GCC's mangling scheme, which leaves
 // much to be desired. Come up with a better mangling scheme.
 
@@ -37,6 +87,12 @@
                                 const BlockDecl *BD,
                                 raw_ostream &Out) {
   unsigned discriminator = Context.getBlockId(BD, true);
+  	
+  if (Context.shouldAddHashOfBlockToName()) {
+    Out << "__" << Outer << getBlockIDByHash(BD, discriminator);
+    return;
+  }
+
   if (discriminator == 0)
     Out << "__" << Outer << "_block_invoke";
   else
@@ -89,6 +145,10 @@
     return CCM_Vector;
   }
 }
+	
+bool MangleContext::shouldAddHashOfBlockToName() {
+  return getASTContext().getLangOpts().ObjCEnableHashFuncBlockNames;
+}
 
 bool MangleContext::shouldMangleDeclName(const NamedDecl *D) {
   const ASTContext &ASTContext = getASTContext();
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -1349,6 +1349,8 @@
 def fthin_link_bitcode_EQ : Joined<["-"], "fthin-link-bitcode=">,
   Flags<[CoreOption, CC1Option]>, Group<f_Group>,
   HelpText<"Write minimized bitcode to <file> for the ThinLTO thin link only">;
+def enable_hash_in_objc_func_block_names : Flag<["-"], "enable-hash-in-objc-func-block-names">, Flags<[CC1Option]>, Group<f_Group>,
+  HelpText<"For objc function blocks - enable adding a hash of the block in the blocks's name">;
 def fmacro_backtrace_limit_EQ : Joined<["-"], "fmacro-backtrace-limit=">,
                                 Group<f_Group>, Flags<[DriverOption, CoreOption]>;
 def fmerge_all_constants : Flag<["-"], "fmerge-all-constants">, Group<f_Group>,
Index: clang/include/clang/Basic/LangOptions.def
===================================================================
--- clang/include/clang/Basic/LangOptions.def
+++ clang/include/clang/Basic/LangOptions.def
@@ -273,6 +273,7 @@
 LANGOPT(DeclareOpenCLBuiltins, 1, 0, "Declare OpenCL builtin functions")
 BENIGN_LANGOPT(DelayedTemplateParsing , 1, 0, "delayed template parsing")
 LANGOPT(BlocksRuntimeOptional , 1, 0, "optional blocks runtime")
+LANGOPT(ObjCEnableHashFuncBlockNames, 1, 0, "For function blocks - enable adding hash of block at the end of block's name")
 LANGOPT(
     CompleteMemberPointers, 1, 0,
     "Require member pointer base types to be complete at the point where the "
Index: clang/include/clang/AST/Mangle.h
===================================================================
--- clang/include/clang/AST/Mangle.h
+++ clang/include/clang/AST/Mangle.h
@@ -92,6 +92,7 @@
   /// @{
 
   bool shouldMangleDeclName(const NamedDecl *D);
+  bool shouldAddHashOfBlockToName();
   virtual bool shouldMangleCXXName(const NamedDecl *D) = 0;
   virtual bool shouldMangleStringLiteral(const StringLiteral *SL) = 0;
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to