[cfe-commits] r89134 - in /cfe/trunk: include/clang/AST/ASTContext.h include/clang/Basic/LangOptions.h include/clang/Driver/Options.def lib/AST/ASTContext.cpp lib/CodeGen/CGBlocks.cpp lib/CodeGen/CGBlocks.h lib/Driver/Tools.cpp test/CodeGen/blocks-2.c

David Chisnall csdavec at swan.ac.uk
Tue Nov 17 11:33:30 PST 2009


Author: theraven
Date: Tue Nov 17 13:33:30 2009
New Revision: 89134

URL: http://llvm.org/viewvc/llvm-project?rev=89134&view=rev
Log:
Added block type introspection support.

As per Fariborz's suggestion, committed now but can be reverted later if the used flag is problematic for Apple.


Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/Basic/LangOptions.h
    cfe/trunk/include/clang/Driver/Options.def
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/CodeGen/CGBlocks.cpp
    cfe/trunk/lib/CodeGen/CGBlocks.h
    cfe/trunk/lib/Driver/Tools.cpp
    cfe/trunk/test/CodeGen/blocks-2.c

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=89134&r1=89133&r2=89134&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Tue Nov 17 13:33:30 2009
@@ -37,6 +37,7 @@
 namespace clang {
   class FileManager;
   class ASTRecordLayout;
+  class BlockExpr;
   class Expr;
   class ExternalASTSource;
   class IdentifierTable;
@@ -672,6 +673,10 @@
   /// declaration.
   void getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, std::string &S);
 
+  /// getObjCEncodingForBlockDecl - Return the encoded type for this block
+  /// declaration.
+  void getObjCEncodingForBlock(const BlockExpr *Expr, std::string& S);
+  
   /// getObjCEncodingForPropertyDecl - Return the encoded type for
   /// this method declaration. If non-NULL, Container must be either
   /// an ObjCCategoryImplDecl or ObjCImplementationDecl; it should

Modified: cfe/trunk/include/clang/Basic/LangOptions.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/LangOptions.h?rev=89134&r1=89133&r2=89134&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/LangOptions.h (original)
+++ cfe/trunk/include/clang/Basic/LangOptions.h Tue Nov 17 13:33:30 2009
@@ -55,6 +55,7 @@
   unsigned POSIXThreads      : 1; // Compiling with POSIX thread support
                                   // (-pthread)
   unsigned Blocks            : 1; // block extension to C
+  unsigned BlockIntrospection: 1; // block have ObjC type encodings.
   unsigned EmitAllDecls      : 1; // Emit all declarations, even if
                                   // they are unused.
   unsigned MathErrno         : 1; // Math functions must respect errno
@@ -139,6 +140,7 @@
     ThreadsafeStatics = 0;
     POSIXThreads = 0;
     Blocks = 0;
+    BlockIntrospection = 0;
     EmitAllDecls = 0;
     MathErrno = 1;
 

Modified: cfe/trunk/include/clang/Driver/Options.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.def?rev=89134&r1=89133&r2=89134&view=diff

==============================================================================
--- cfe/trunk/include/clang/Driver/Options.def (original)
+++ cfe/trunk/include/clang/Driver/Options.def Tue Nov 17 13:33:30 2009
@@ -368,6 +368,7 @@
 OPTION("-fastf", fastf, Flag, f_Group, INVALID, "", 0, 0, 0)
 OPTION("-fast", fast, Flag, f_Group, INVALID, "", 0, 0, 0)
 OPTION("-fasynchronous-unwind-tables", fasynchronous_unwind_tables, Flag, f_Group, INVALID, "", 0, 0, 0)
+OPTION("-fblock-introspection", fblock_introspection, Flag, f_Group, INVALID, "", 0, 0, 0)
 OPTION("-fblocks", fblocks, Flag, f_Group, INVALID, "", 0, 0, 0)
 OPTION("-fbootclasspath=", fbootclasspath_EQ, Joined, f_Group, INVALID, "", 0, 0, 0)
 OPTION("-fbuiltin-strcat", fbuiltin_strcat, Flag, f_Group, INVALID, "", 0, 0, 0)

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=89134&r1=89133&r2=89134&view=diff

==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Tue Nov 17 13:33:30 2009
@@ -3071,6 +3071,54 @@
   return sz / getTypeSize(CharTy);
 }
 
+/// getObjCEncodingForBlockDecl - Return the encoded type for this method
+/// declaration.
+void ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr, 
+                                             std::string& S) {
+  const BlockDecl *Decl = Expr->getBlockDecl();
+  QualType BlockTy =
+      Expr->getType()->getAs<BlockPointerType>()->getPointeeType();
+  // Encode result type.
+  getObjCEncodingForType(cast<FunctionType>(BlockTy)->getResultType(), S);
+  // Compute size of all parameters.
+  // Start with computing size of a pointer in number of bytes.
+  // FIXME: There might(should) be a better way of doing this computation!
+  SourceLocation Loc;
+  int PtrSize = getTypeSize(VoidPtrTy) / getTypeSize(CharTy);
+  int ParmOffset = PtrSize;
+  for (ObjCMethodDecl::param_iterator PI = Decl->param_begin(),
+       E = Decl->param_end(); PI != E; ++PI) {
+    QualType PType = (*PI)->getType();
+    int sz = getObjCEncodingTypeSize(PType);
+    assert (sz > 0 && "BlockExpr - Incomplete param type");
+    ParmOffset += sz;
+  }
+  // Size of the argument frame
+  S += llvm::utostr(ParmOffset);
+  // Block pointer and offset.
+  S += "@?0";
+  ParmOffset = PtrSize;
+  
+  // Argument types.
+  ParmOffset = PtrSize;
+  for (BlockDecl::param_const_iterator PI = Decl->param_begin(), E =
+       Decl->param_end(); PI != E; ++PI) {
+    ParmVarDecl *PVDecl = *PI;
+    QualType PType = PVDecl->getOriginalType(); 
+    if (const ArrayType *AT =
+          dyn_cast<ArrayType>(PType->getCanonicalTypeInternal())) {
+      // Use array's original type only if it has known number of
+      // elements.
+      if (!isa<ConstantArrayType>(AT))
+        PType = PVDecl->getType();
+    } else if (PType->isFunctionType())
+      PType = PVDecl->getType();
+    getObjCEncodingForType(PType, S);
+    S += llvm::utostr(ParmOffset);
+    ParmOffset += getObjCEncodingTypeSize(PType);
+  }
+}
+
 /// getObjCEncodingForMethodDecl - Return the encoded type for this method
 /// declaration.
 void ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl,

Modified: cfe/trunk/lib/CodeGen/CGBlocks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBlocks.cpp?rev=89134&r1=89133&r2=89134&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGBlocks.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBlocks.cpp Tue Nov 17 13:33:30 2009
@@ -146,7 +146,23 @@
   if (0 && CanBlockBeGlobal(Info))
     return CGM.GetAddrOfGlobalBlock(BE, Name.c_str());
 
-  std::vector<llvm::Constant*> Elts(5);
+  size_t BlockFields = 5;
+
+  bool hasIntrospection  = CGM.getContext().getLangOptions().BlockIntrospection;
+
+  if (hasIntrospection) {
+    BlockFields++;
+  }
+  std::vector<llvm::Constant*> Elts(BlockFields);
+
+  if (hasIntrospection) {
+    std::string BlockTypeEncoding;
+    CGM.getContext().getObjCEncodingForBlock(BE, BlockTypeEncoding);
+
+    Elts[5] = llvm::ConstantExpr::getBitCast(
+            CGM.GetAddrOfConstantCString(BlockTypeEncoding), PtrToInt8Ty);
+  }
+
   llvm::Constant *C;
   llvm::Value *V;
 
@@ -154,6 +170,9 @@
     // C = BuildBlockStructInitlist();
     unsigned int flags = BLOCK_HAS_DESCRIPTOR;
 
+    if (hasIntrospection)
+      flags |= BLOCK_HAS_OBJC_TYPE;
+
     // We run this first so that we set BlockHasCopyDispose from the entire
     // block literal.
     // __invoke
@@ -211,19 +230,21 @@
       return C;
     }
 
-    std::vector<const llvm::Type *> Types(5+subBlockDeclRefDecls.size());
+    std::vector<const llvm::Type *> Types(BlockFields+subBlockDeclRefDecls.size());
     for (int i=0; i<4; ++i)
       Types[i] = Elts[i]->getType();
     Types[4] = PtrToInt8Ty;
+    if (hasIntrospection)
+      Types[5] = PtrToInt8Ty;
 
     for (unsigned i=0; i < subBlockDeclRefDecls.size(); ++i) {
       const Expr *E = subBlockDeclRefDecls[i];
       const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E);
       QualType Ty = E->getType();
       if (BDRE && BDRE->isByRef()) {
-        Types[i+5] = llvm::PointerType::get(BuildByRefType(BDRE->getDecl()), 0);
+        Types[i+BlockFields] = llvm::PointerType::get(BuildByRefType(BDRE->getDecl()), 0);
       } else
-        Types[i+5] = ConvertType(Ty);
+        Types[i+BlockFields] = ConvertType(Ty);
     }
 
     llvm::StructType *Ty = llvm::StructType::get(VMContext, Types, true);
@@ -237,6 +258,8 @@
 
     for (unsigned i=0; i<4; ++i)
       Builder.CreateStore(Elts[i], Builder.CreateStructGEP(V, i, "block.tmp"));
+    if (hasIntrospection)
+      Builder.CreateStore(Elts[5], Builder.CreateStructGEP(V, 5, "block.tmp"));
 
     for (unsigned i=0; i < subBlockDeclRefDecls.size(); ++i)
       {
@@ -252,7 +275,7 @@
         BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E);
         VD = BDRE->getDecl();
 
-        llvm::Value* Addr = Builder.CreateStructGEP(V, i+5, "tmp");
+        llvm::Value* Addr = Builder.CreateStructGEP(V, i+BlockFields, "tmp");
         NoteForHelper[helpersize].index = i+5;
         NoteForHelper[helpersize].RequiresCopying
           = BlockRequiresCopying(VD->getType());
@@ -291,7 +314,7 @@
         RValue r = EmitAnyExpr(E, Addr, false);
         if (r.isScalar()) {
           llvm::Value *Loc = r.getScalarVal();
-          const llvm::Type *Ty = Types[i+5];
+          const llvm::Type *Ty = Types[i+BlockFields];
           if  (BDRE->isByRef()) {
             // E is now the address of the value field, instead, we want the
             // address of the actual ByRef struct.  We optimize this slightly
@@ -375,8 +398,20 @@
   //   int __reserved;
   //   void (*__invoke)(void *);
   //   struct __block_descriptor *__descriptor;
+  //   // GNU runtime only:
+  //   const char *types;
   // };
-  GenericBlockLiteralType = llvm::StructType::get(IntTy->getContext(),
+  if (CGM.getContext().getLangOptions().BlockIntrospection)
+    GenericBlockLiteralType = llvm::StructType::get(IntTy->getContext(),
+                                                  PtrToInt8Ty,
+                                                  IntTy,
+                                                  IntTy,
+                                                  PtrToInt8Ty,
+                                                  BlockDescPtrTy,
+                                                  PtrToInt8Ty,
+                                                  NULL);
+  else
+    GenericBlockLiteralType = llvm::StructType::get(IntTy->getContext(),
                                                   PtrToInt8Ty,
                                                   IntTy,
                                                   IntTy,
@@ -571,8 +606,12 @@
                              llvm::GlobalVariable::InternalLinkage,
                              DescriptorStruct, "__block_descriptor_global");
 
+  int FieldCount = 5;
   // Generate the constants for the block literal.
-  llvm::Constant *LiteralFields[5];
+  if (CGM.getContext().getLangOptions().BlockIntrospection)
+    FieldCount = 6;
+
+  std::vector<llvm::Constant*> LiteralFields(FieldCount);
 
   CodeGenFunction::BlockInfo Info(0, n);
   uint64_t subBlockSize, subBlockAlign;
@@ -592,7 +631,9 @@
   LiteralFields[0] = getNSConcreteGlobalBlock();
 
   // Flags
-  LiteralFields[1] =
+  LiteralFields[1] = CGM.getContext().getLangOptions().BlockIntrospection ?
+    llvm::ConstantInt::get(IntTy, BLOCK_IS_GLOBAL | BLOCK_HAS_DESCRIPTOR |
+            BLOCK_HAS_OBJC_TYPE) :
     llvm::ConstantInt::get(IntTy, BLOCK_IS_GLOBAL | BLOCK_HAS_DESCRIPTOR);
 
   // Reserved
@@ -603,9 +644,17 @@
 
   // Descriptor
   LiteralFields[4] = Descriptor;
+  
+  // Type encoding
+  if (CGM.getContext().getLangOptions().BlockIntrospection) {
+    std::string BlockTypeEncoding;
+    CGM.getContext().getObjCEncodingForBlock(BE, BlockTypeEncoding);
+
+    LiteralFields[5] = CGM.GetAddrOfConstantCString(BlockTypeEncoding);
+  }
 
   llvm::Constant *BlockLiteralStruct =
-    llvm::ConstantStruct::get(VMContext, &LiteralFields[0], 5, false);
+    llvm::ConstantStruct::get(VMContext, LiteralFields, false);
 
   llvm::GlobalVariable *BlockLiteral =
     new llvm::GlobalVariable(getModule(), BlockLiteralStruct->getType(), true,

Modified: cfe/trunk/lib/CodeGen/CGBlocks.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBlocks.h?rev=89134&r1=89133&r2=89134&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGBlocks.h (original)
+++ cfe/trunk/lib/CodeGen/CGBlocks.h Tue Nov 17 13:33:30 2009
@@ -55,7 +55,8 @@
         BLOCK_HAS_CXX_OBJ =       (1 << 26),
         BLOCK_IS_GC =             (1 << 27),
         BLOCK_IS_GLOBAL =         (1 << 28),
-        BLOCK_HAS_DESCRIPTOR =    (1 << 29)
+        BLOCK_HAS_DESCRIPTOR =    (1 << 29),
+        BLOCK_HAS_OBJC_TYPE  =    (1 << 30)
     };
 };
 

Modified: cfe/trunk/lib/Driver/Tools.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=89134&r1=89133&r2=89134&view=diff

==============================================================================
--- cfe/trunk/lib/Driver/Tools.cpp (original)
+++ cfe/trunk/lib/Driver/Tools.cpp Tue Nov 17 13:33:30 2009
@@ -926,8 +926,10 @@
 
   // -fblocks=0 is default.
   if (Args.hasFlag(options::OPT_fblocks, options::OPT_fno_blocks,
-                   getToolChain().IsBlocksDefault()))
+                   getToolChain().IsBlocksDefault())) {
+    Args.AddLastArg(CmdArgs, options::OPT_fblock_introspection);
     CmdArgs.push_back("-fblocks");
+  }
 
   if (needsExceptions(Args, InputType, getToolChain().getTriple()))
     CmdArgs.push_back("-fexceptions");

Modified: cfe/trunk/test/CodeGen/blocks-2.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/blocks-2.c?rev=89134&r1=89133&r2=89134&view=diff

==============================================================================
--- cfe/trunk/test/CodeGen/blocks-2.c (original)
+++ cfe/trunk/test/CodeGen/blocks-2.c Tue Nov 17 13:33:30 2009
@@ -1,5 +1,9 @@
 // RUN: clang-cc -g %s -emit-llvm -o %t -fblocks
-// RUN: grep "func.start" %t | count 4
+// RUN: grep "func.start" %t | count 4 &&
+// RUN: clang-cc -g %s -triple i386-unknown-unknown -emit-llvm -o %t -fblocks -fblock-introspection &&
+// RUN: grep "v8@?0i4" %t | count 1 &&
+// RUN: clang-cc -g %s -triple i386-unknown-unknown -emit-llvm -o %t -fblocks &&
+// RUN: grep "v8@?0i4" %t | count 0 &&
 // 1 declaration, 1 bar, 1 test_block_dbg and 1 for the block.
 // XFAIL: *
 





More information about the cfe-commits mailing list