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