diff --git a/clang/include/clang/AST/Mangle.h b/clang/include/clang/AST/Mangle.h --- a/clang/include/clang/AST/Mangle.h +++ b/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; diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def --- a/clang/include/clang/Basic/LangOptions.def +++ b/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 " diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1349,6 +1349,8 @@ def fthin_link_bitcode_EQ : Joined<["-"], "fthin-link-bitcode=">, Flags<[CoreOption, CC1Option]>, Group, HelpText<"Write minimized bitcode to 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, + 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, Flags<[DriverOption, CoreOption]>; def fmerge_all_constants : Flag<["-"], "fmerge-all-constants">, Group, diff --git a/clang/lib/AST/Mangle.cpp b/clang/lib/AST/Mangle.cpp --- a/clang/lib/AST/Mangle.cpp +++ b/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(); diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/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