From 35415f5132f70ad5097a3514ab84251e10db3664 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 25 May 2010 17:04:15 +0000 Subject: [PATCH] Improve name mangling for blocks and support mangling of static local variables within blocks. We loosely follow GCC's mangling, but since these are always internal symbols the names don't really matter. I intend to revisit block mangling later, because GCC's mangling is rather verbose. . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@104610 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGBlocks.cpp | 5 ++-- lib/CodeGen/CGCXX.cpp | 4 +++ lib/CodeGen/CodeGenFunction.cpp | 1 + lib/CodeGen/CodeGenModule.h | 1 + lib/CodeGen/Mangle.cpp | 44 ++++++++++++++++++++++++++++++++- lib/CodeGen/Mangle.h | 17 +++++++++++-- 6 files changed, 67 insertions(+), 5 deletions(-) diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp index f49b6ee18b..dcae95f3de 100644 --- a/lib/CodeGen/CGBlocks.cpp +++ b/lib/CodeGen/CGBlocks.cpp @@ -791,9 +791,10 @@ CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr, CodeGenTypes &Types = CGM.getTypes(); const llvm::FunctionType *LTy = Types.GetFunctionType(FI, IsVariadic); + MangleBuffer Name; + CGM.getMangledName(Name, BD); llvm::Function *Fn = - llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, - llvm::Twine("__") + Info.Name + "_block_invoke_", + llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); CGM.SetInternalFunctionAttributes(BD, Fn, FI); diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index 85222fe9db..be4256a691 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -230,6 +230,10 @@ CodeGenModule::GetAddrOfCXXConstructor(const CXXConstructorDecl *D, GetOrCreateLLVMFunction(Name, FTy, GlobalDecl(D, Type))); } +void CodeGenModule::getMangledName(MangleBuffer &Buffer, const BlockDecl *BD) { + getMangleContext().mangleBlock(BD, Buffer.getBuffer()); +} + void CodeGenModule::getMangledCXXCtorName(MangleBuffer &Name, const CXXConstructorDecl *D, CXXCtorType Type) { diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 222dcc4b8f..73de0fd773 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -37,6 +37,7 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm) LLVMPointerWidth = Target.getPointerWidth(0); Exceptions = getContext().getLangOptions().Exceptions; CatchUndefined = getContext().getLangOptions().CatchUndefined; + CGM.getMangleContext().startNewFunction(); } ASTContext &CodeGenFunction::getContext() const { diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index e225462fac..b14c35f384 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -413,6 +413,7 @@ public: void getMangledName(MangleBuffer &Buffer, GlobalDecl D); void getMangledName(MangleBuffer &Buffer, const NamedDecl *ND); + void getMangledName(MangleBuffer &Buffer, const BlockDecl *BD); void getMangledCXXCtorName(MangleBuffer &Buffer, const CXXConstructorDecl *D, CXXCtorType Type); diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp index 46a9f6ce82..88e4c647c8 100644 --- a/lib/CodeGen/Mangle.cpp +++ b/lib/CodeGen/Mangle.cpp @@ -102,6 +102,7 @@ public: llvm::raw_svector_ostream &getStream() { return Out; } void mangle(const NamedDecl *D, llvm::StringRef Prefix = "_Z"); + void mangleBlock(const BlockDecl *BD); void mangleCallOffset(int64_t NonVirtual, int64_t Virtual); void mangleNumber(int64_t Number); void mangleFunctionEncoding(const FunctionDecl *FD); @@ -469,6 +470,31 @@ void CXXNameMangler::mangleNumber(int64_t Number) { Out << Number; } +void CXXNameMangler::mangleBlock(const BlockDecl *BD) { + // Mangle the context of the block. + // FIXME: We currently mimic GCC's mangling scheme, which leaves much to be + // desired. Come up with a better mangling scheme. + const DeclContext *DC = BD->getDeclContext(); + while (isa(DC) || isa(DC)) + DC = DC->getParent(); + if (DC->isFunctionOrMethod()) { + Out << "__"; + if (const ObjCMethodDecl *Method = dyn_cast(DC)) + mangleObjCMethodName(Method); + else { + const NamedDecl *ND = cast(DC); + if (IdentifierInfo *II = ND->getIdentifier()) + Out << II->getName(); + else { + mangleUnqualifiedName(ND); + } + } + Out << "_block_invoke_" << Context.getBlockId(BD, true); + } else { + Out << "__block_global_" << Context.getBlockId(BD, false); + } +} + void CXXNameMangler::mangleCallOffset(int64_t NonVirtual, int64_t Virtual) { // ::= h _ // ::= v _ @@ -752,6 +778,14 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) { if (DC->isTranslationUnit()) return; + if (const BlockDecl *Block = dyn_cast(DC)) { + manglePrefix(DC->getParent(), NoFunction); + llvm::SmallString<64> Name; + Context.mangleBlock(Block, Name); + Out << Name.size() << Name; + return; + } + if (mangleSubstitution(cast(DC))) return; @@ -762,8 +796,10 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) { TemplateParameterList *TemplateParameters = TD->getTemplateParameters(); mangleTemplateArgs(*TemplateParameters, *TemplateArgs); } - else if(NoFunction && isa(DC)) + else if(NoFunction && (isa(DC) || isa(DC))) return; + else if (const ObjCMethodDecl *Method = dyn_cast(DC)) + mangleObjCMethodName(Method); else { manglePrefix(DC->getParent(), NoFunction); mangleUnqualifiedName(cast(DC)); @@ -2033,6 +2069,12 @@ void MangleContext::mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type, Mangler.mangle(D); } +void MangleContext::mangleBlock(const BlockDecl *BD, + llvm::SmallVectorImpl &Res) { + CXXNameMangler Mangler(*this, Res); + Mangler.mangleBlock(BD); +} + void MangleContext::mangleThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk, llvm::SmallVectorImpl &Res) { diff --git a/lib/CodeGen/Mangle.h b/lib/CodeGen/Mangle.h index da3626fc5d..04f5dd6b21 100644 --- a/lib/CodeGen/Mangle.h +++ b/lib/CodeGen/Mangle.h @@ -26,6 +26,7 @@ namespace clang { class ASTContext; + class BlockDecl; class CXXConstructorDecl; class CXXDestructorDecl; class CXXMethodDecl; @@ -73,6 +74,8 @@ class MangleContext { llvm::DenseMap AnonStructIds; unsigned Discriminator; llvm::DenseMap Uniquifier; + llvm::DenseMap GlobalBlockIds; + llvm::DenseMap LocalBlockIds; public: explicit MangleContext(ASTContext &Context, @@ -83,6 +86,8 @@ public: Diagnostic &getDiags() const { return Diags; } + void startNewFunction() { LocalBlockIds.clear(); } + uint64_t getAnonymousStructId(const TagDecl *TD) { std::pair::iterator, bool> Result = @@ -90,11 +95,18 @@ public: return Result.first->second; } + unsigned getBlockId(const BlockDecl *BD, bool Local) { + llvm::DenseMap &BlockIds + = Local? LocalBlockIds : GlobalBlockIds; + std::pair::iterator, bool> + Result = BlockIds.insert(std::make_pair(BD, BlockIds.size())); + return Result.first->second; + } + /// @name Mangler Entry Points /// @{ bool shouldMangleDeclName(const NamedDecl *D); - void mangleName(const NamedDecl *D, llvm::SmallVectorImpl &); void mangleThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk, @@ -114,7 +126,8 @@ public: llvm::SmallVectorImpl &); void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type, llvm::SmallVectorImpl &); - + void mangleBlock(const BlockDecl *BD, llvm::SmallVectorImpl &); + void mangleInitDiscriminator() { Discriminator = 0; } -- 2.40.0