Index: clang/include/clang/AST/Mangle.h =================================================================== --- clang/include/clang/AST/Mangle.h +++ clang/include/clang/AST/Mangle.h @@ -116,11 +116,14 @@ const NamedDecl *ID, raw_ostream &Out); void mangleCtorBlock(const CXXConstructorDecl *CD, CXXCtorType CT, - const BlockDecl *BD, raw_ostream &Out); + const BlockDecl *BD, raw_ostream &Out, + const StringRef *parentFuncName); void mangleDtorBlock(const CXXDestructorDecl *CD, CXXDtorType DT, - const BlockDecl *BD, raw_ostream &Out); + const BlockDecl *BD, raw_ostream &Out, + const StringRef *parentFuncName); void mangleBlock(const DeclContext *DC, const BlockDecl *BD, - raw_ostream &Out); + raw_ostream &Out, + const StringRef *parentFuncName); void mangleObjCMethodNameWithoutSize(const ObjCMethodDecl *MD, raw_ostream &); void mangleObjCMethodName(const ObjCMethodDecl *MD, raw_ostream &); Index: clang/lib/AST/Mangle.cpp =================================================================== --- clang/lib/AST/Mangle.cpp +++ clang/lib/AST/Mangle.cpp @@ -26,21 +26,70 @@ #include "llvm/IR/Mangler.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" +#include +#include +#include using namespace clang; +static std::string getBlockDeclHash(const BlockDecl *BD, + const StringRef *parentFuncName) { + std::vector hashItems; + + ArrayRef params = BD->parameters(); + std::string strTypeBuff; + llvm::raw_string_ostream osTypeStream(strTypeBuff); + + hashItems.push_back(params.size()); + for(unsigned i = 0; i < params.size(); i++) { + ParmVarDecl *param = params[i]; + + osTypeStream << param->getNameAsString(); + osTypeStream << " ["; + param->getType()->dump(osTypeStream); + osTypeStream << "] \n"; + } + + osTypeStream.flush(); + + // Remove (non-deterministic) pointers from the param string + char *ptr = &strTypeBuff[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 param string + llvm::MD5 Hash; + llvm::MD5::MD5Result Result; + + if(parentFuncName) { + Hash.update(*parentFuncName); + } + Hash.update(strTypeBuff); + Hash.final(Result); + + std::ostringstream osRet; + unsigned short hash = (*(unsigned short *)&Result); + + osRet << std::hex << std::setfill('0') << std::setw(4) << std::uppercase << hash; + return osRet.str(); +} + // FIXME: For blocks we currently mimic GCC's mangling scheme, which leaves // much to be desired. Come up with a better mangling scheme. - -static void mangleFunctionBlock(MangleContext &Context, - StringRef Outer, - const BlockDecl *BD, - raw_ostream &Out) { - unsigned discriminator = Context.getBlockId(BD, true); - if (discriminator == 0) - Out << "__" << Outer << "_block_invoke"; - else - Out << "__" << Outer << "_block_invoke_" << discriminator+1; +static void mangleFunctionBlock(MangleContext &Context, StringRef Outer, + const BlockDecl *BD, raw_ostream &Out, + const StringRef *parentFuncName) { + Out << "__" << Outer << "_block_invoke_" + << getBlockDeclHash(BD, parentFuncName); } void MangleContext::anchor() { } @@ -228,24 +277,27 @@ void MangleContext::mangleCtorBlock(const CXXConstructorDecl *CD, CXXCtorType CT, const BlockDecl *BD, - raw_ostream &ResStream) { + raw_ostream &ResStream, + const StringRef *parentFuncName) { SmallString<64> Buffer; llvm::raw_svector_ostream Out(Buffer); mangleName(GlobalDecl(CD, CT), Out); - mangleFunctionBlock(*this, Buffer, BD, ResStream); + mangleFunctionBlock(*this, Buffer, BD, ResStream, parentFuncName); } void MangleContext::mangleDtorBlock(const CXXDestructorDecl *DD, CXXDtorType DT, const BlockDecl *BD, - raw_ostream &ResStream) { + raw_ostream &ResStream, + const StringRef *parentFuncName) { SmallString<64> Buffer; llvm::raw_svector_ostream Out(Buffer); mangleName(GlobalDecl(DD, DT), Out); - mangleFunctionBlock(*this, Buffer, BD, ResStream); + mangleFunctionBlock(*this, Buffer, BD, ResStream, parentFuncName); } void MangleContext::mangleBlock(const DeclContext *DC, const BlockDecl *BD, - raw_ostream &Out) { + raw_ostream &Out, + const StringRef *parentFuncName) { assert(!isa(DC) && !isa(DC)); SmallString<64> Buffer; @@ -261,9 +313,9 @@ assert((isa(DC) || isa(DC)) && "expected a TranslationUnitDecl or a NamedDecl"); if (const auto *CD = dyn_cast(DC)) - mangleCtorBlock(CD, /*CT*/ Ctor_Complete, BD, Out); + mangleCtorBlock(CD, /*CT*/ Ctor_Complete, BD, Out, parentFuncName); else if (const auto *DD = dyn_cast(DC)) - mangleDtorBlock(DD, /*DT*/ Dtor_Complete, BD, Out); + mangleDtorBlock(DD, /*DT*/ Dtor_Complete, BD, Out, parentFuncName); else if (auto ND = dyn_cast(DC)) { if (!shouldMangleDeclName(ND) && ND->getIdentifier()) Stream << ND->getIdentifier()->getName(); @@ -277,7 +329,7 @@ } } } - mangleFunctionBlock(*this, Buffer, BD, Out); + mangleFunctionBlock(*this, Buffer, BD, Out, parentFuncName); } void MangleContext::mangleObjCMethodNameWithoutSize(const ObjCMethodDecl *MD, Index: clang/lib/CodeGen/CGBlocks.cpp =================================================================== --- clang/lib/CodeGen/CGBlocks.cpp +++ clang/lib/CodeGen/CGBlocks.cpp @@ -1571,7 +1571,7 @@ llvm::FunctionType *fnLLVMType = CGM.getTypes().GetFunctionType(fnInfo); - StringRef name = CGM.getBlockMangledName(GD, blockDecl); + StringRef name = CGM.getBlockMangledName(GD, blockDecl, &blockInfo.Name); llvm::Function *fn = llvm::Function::Create( fnLLVMType, llvm::GlobalValue::InternalLinkage, name, &CGM.getModule()); CGM.SetInternalFunctionAttributes(blockDecl, fn, fnInfo); Index: clang/lib/CodeGen/CGDecl.cpp =================================================================== --- clang/lib/CodeGen/CGDecl.cpp +++ clang/lib/CodeGen/CGDecl.cpp @@ -212,7 +212,8 @@ if (const auto *FD = dyn_cast(DC)) ContextName = std::string(CGM.getMangledName(FD)); else if (const auto *BD = dyn_cast(DC)) - ContextName = std::string(CGM.getBlockMangledName(GlobalDecl(), BD)); + ContextName = + std::string(CGM.getBlockMangledName(GlobalDecl(), BD, nullptr)); else if (const auto *OMD = dyn_cast(DC)) ContextName = OMD->getSelector().getAsString(); else Index: clang/lib/CodeGen/CodeGenModule.h =================================================================== --- clang/lib/CodeGen/CodeGenModule.h +++ clang/lib/CodeGen/CodeGenModule.h @@ -1173,7 +1173,8 @@ void AddDefaultFnAttrs(llvm::Function &F); StringRef getMangledName(GlobalDecl GD); - StringRef getBlockMangledName(GlobalDecl GD, const BlockDecl *BD); + StringRef getBlockMangledName(GlobalDecl GD, const BlockDecl *BD, + const StringRef *parentFuncName); void EmitTentativeDefinition(const VarDecl *D); Index: clang/lib/CodeGen/CodeGenModule.cpp =================================================================== --- clang/lib/CodeGen/CodeGenModule.cpp +++ clang/lib/CodeGen/CodeGenModule.cpp @@ -1177,7 +1177,8 @@ } StringRef CodeGenModule::getBlockMangledName(GlobalDecl GD, - const BlockDecl *BD) { + const BlockDecl *BD, + const StringRef *parentFuncName) { MangleContext &MangleCtx = getCXXABI().getMangleContext(); const Decl *D = GD.getDecl(); @@ -1187,11 +1188,11 @@ MangleCtx.mangleGlobalBlock(BD, dyn_cast_or_null(initializedGlobalDecl.getDecl()), Out); else if (const auto *CD = dyn_cast(D)) - MangleCtx.mangleCtorBlock(CD, GD.getCtorType(), BD, Out); + MangleCtx.mangleCtorBlock(CD, GD.getCtorType(), BD, Out, parentFuncName); else if (const auto *DD = dyn_cast(D)) - MangleCtx.mangleDtorBlock(DD, GD.getDtorType(), BD, Out); + MangleCtx.mangleDtorBlock(DD, GD.getDtorType(), BD, Out, parentFuncName); else - MangleCtx.mangleBlock(cast(D), BD, Out); + MangleCtx.mangleBlock(cast(D), BD, Out, parentFuncName); auto Result = Manglings.insert(std::make_pair(Out.str(), BD)); return Result.first->first();