]> granicus.if.org Git - clang/commitdiff
Improve name mangling for blocks and support mangling of static local
authorDouglas Gregor <dgregor@apple.com>
Tue, 25 May 2010 17:04:15 +0000 (17:04 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 25 May 2010 17:04:15 +0000 (17:04 +0000)
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. <rdar://problem/8015719>.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@104610 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGBlocks.cpp
lib/CodeGen/CGCXX.cpp
lib/CodeGen/CodeGenFunction.cpp
lib/CodeGen/CodeGenModule.h
lib/CodeGen/Mangle.cpp
lib/CodeGen/Mangle.h

index f49b6ee18b8e3ab0bd8b03ac7e0c48be31bd4a34..dcae95f3de19546022eeed86c2c208411ab407e0 100644 (file)
@@ -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);
index 85222fe9dbace7fe42420004fa0675ae3f270546..be4256a691d28a7faaeef0f3a380707d22b6a749 100644 (file)
@@ -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) {
index 222dcc4b8f5e9d02f93e195662874d05b4e5997a..73de0fd77384d09f3ff8792301c4eac56e9b228f 100644 (file)
@@ -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 {
index e225462fac835322cfacd5ee30b3117fc4f828b1..b14c35f3845410c0e4ef0135e85d1eab835457ff 100644 (file)
@@ -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);
index 46a9f6ce82bd9ec5d7d472c66111a6d1d64da2eb..88e4c647c87df068a5efee568d2c20968ef66785 100644 (file)
@@ -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<BlockDecl>(DC) || isa<EnumDecl>(DC))
+    DC = DC->getParent();
+  if (DC->isFunctionOrMethod()) {
+    Out << "__";
+    if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC))
+      mangleObjCMethodName(Method);
+    else {
+      const NamedDecl *ND = cast<NamedDecl>(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) {
   //  <call-offset>  ::= h <nv-offset> _
   //                 ::= v <v-offset> _
@@ -752,6 +778,14 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) {
   if (DC->isTranslationUnit())
     return;
 
+  if (const BlockDecl *Block = dyn_cast<BlockDecl>(DC)) {
+    manglePrefix(DC->getParent(), NoFunction);    
+    llvm::SmallString<64> Name;
+    Context.mangleBlock(Block, Name);
+    Out << Name.size() << Name;
+    return;
+  }
+  
   if (mangleSubstitution(cast<NamedDecl>(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<FunctionDecl>(DC))
+  else if(NoFunction && (isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC)))
     return;
+  else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC))
+    mangleObjCMethodName(Method);
   else {
     manglePrefix(DC->getParent(), NoFunction);
     mangleUnqualifiedName(cast<NamedDecl>(DC));
@@ -2033,6 +2069,12 @@ void MangleContext::mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
   Mangler.mangle(D);
 }
 
+void MangleContext::mangleBlock(const BlockDecl *BD,
+                                llvm::SmallVectorImpl<char> &Res) {
+  CXXNameMangler Mangler(*this, Res);
+  Mangler.mangleBlock(BD);
+}
+
 void MangleContext::mangleThunk(const CXXMethodDecl *MD,
                                 const ThunkInfo &Thunk,
                                 llvm::SmallVectorImpl<char> &Res) {
index da3626fc5d37bfda2868593ab339bc1f438463a8..04f5dd6b21e089bf728495d1eac4310b9f7b07c6 100644 (file)
@@ -26,6 +26,7 @@
 
 namespace clang {
   class ASTContext;
+  class BlockDecl;
   class CXXConstructorDecl;
   class CXXDestructorDecl;
   class CXXMethodDecl;
@@ -73,6 +74,8 @@ class MangleContext {
   llvm::DenseMap<const TagDecl *, uint64_t> AnonStructIds;
   unsigned Discriminator;
   llvm::DenseMap<const NamedDecl*, unsigned> Uniquifier;
+  llvm::DenseMap<const BlockDecl*, unsigned> GlobalBlockIds;
+  llvm::DenseMap<const BlockDecl*, unsigned> 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<llvm::DenseMap<const TagDecl *,
       uint64_t>::iterator, bool> Result =
@@ -90,11 +95,18 @@ public:
     return Result.first->second;
   }
 
+  unsigned getBlockId(const BlockDecl *BD, bool Local) {
+    llvm::DenseMap<const BlockDecl *, unsigned> &BlockIds
+      = Local? LocalBlockIds : GlobalBlockIds;
+    std::pair<llvm::DenseMap<const BlockDecl *, unsigned>::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<char> &);
   void mangleThunk(const CXXMethodDecl *MD,
                    const ThunkInfo &Thunk,
@@ -114,7 +126,8 @@ public:
                      llvm::SmallVectorImpl<char> &);
   void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
                      llvm::SmallVectorImpl<char> &);
-  
+  void mangleBlock(const BlockDecl *BD, llvm::SmallVectorImpl<char> &);
+
   void mangleInitDiscriminator() {
     Discriminator = 0;
   }