[cfe-commits] r96989 - in /cfe/trunk: include/clang/Basic/LangOptions.h include/clang/Driver/Options.td lib/CodeGen/CGBlocks.cpp lib/CodeGen/CGBlocks.h lib/CodeGen/CodeGenFunction.h lib/Driver/Tools.cpp test/CodeGen/blocksignature.c

Blaine Garst blaine at apple.com
Tue Feb 23 13:51:17 PST 2010


Author: blaine
Date: Tue Feb 23 15:51:17 2010
New Revision: 96989

URL: http://llvm.org/viewvc/llvm-project?rev=96989&view=rev
Log:
Unconditionally support block introspection data in a new field at the end
of the block descriptor field.  This field is the ObjC style @encode
signature of the implementation function, and was to this point
conditionally provided in the block literal data structure.  That
provisional support is removed.

Additionally, eliminate unused enumerations for the block literal flags field.
The first shipping ABI unconditionally set (1<<29) but this bit is unused
by the runtime, so the second ABI will unconditionally have (1<<30) set so
that the runtime can in fact distinguish whether the additional data is
present or not.


Added:
    cfe/trunk/test/CodeGen/blocksignature.c
Modified:
    cfe/trunk/include/clang/Basic/LangOptions.h
    cfe/trunk/include/clang/Driver/Options.td
    cfe/trunk/lib/CodeGen/CGBlocks.cpp
    cfe/trunk/lib/CodeGen/CGBlocks.h
    cfe/trunk/lib/CodeGen/CodeGenFunction.h
    cfe/trunk/lib/Driver/Tools.cpp

Modified: cfe/trunk/include/clang/Basic/LangOptions.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/LangOptions.h?rev=96989&r1=96988&r2=96989&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/LangOptions.h (original)
+++ cfe/trunk/include/clang/Basic/LangOptions.h Tue Feb 23 15:51:17 2010
@@ -59,7 +59,6 @@
   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
@@ -143,7 +142,6 @@
     ThreadsafeStatics = 1;
     POSIXThreads = 0;
     Blocks = 0;
-    BlockIntrospection = 0;
     EmitAllDecls = 0;
     MathErrno = 1;
 

Modified: cfe/trunk/include/clang/Driver/Options.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=96989&r1=96988&r2=96989&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/Options.td (original)
+++ cfe/trunk/include/clang/Driver/Options.td Tue Feb 23 15:51:17 2010
@@ -235,7 +235,6 @@
 def fastf : Flag<"-fastf">, Group<f_Group>;
 def fast : Flag<"-fast">, Group<f_Group>;
 def fasynchronous_unwind_tables : Flag<"-fasynchronous-unwind-tables">, Group<f_Group>;
-def fblock_introspection : Flag<"-fblock-introspection">, Group<f_Group>;
 def fblocks : Flag<"-fblocks">, Group<f_Group>;
 def fbootclasspath_EQ : Joined<"-fbootclasspath=">, Group<f_Group>;
 def fbuiltin_strcat : Flag<"-fbuiltin-strcat">, Group<f_Group>;

Modified: cfe/trunk/lib/CodeGen/CGBlocks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBlocks.cpp?rev=96989&r1=96988&r2=96989&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGBlocks.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBlocks.cpp Tue Feb 23 15:51:17 2010
@@ -24,7 +24,7 @@
 using namespace CodeGen;
 
 llvm::Constant *CodeGenFunction::
-BuildDescriptorBlockDecl(bool BlockHasCopyDispose, CharUnits Size,
+BuildDescriptorBlockDecl(const BlockExpr *BE, bool BlockHasCopyDispose, CharUnits Size,
                          const llvm::StructType* Ty,
                          std::vector<HelperInfo> *NoteForHelper) {
   const llvm::Type *UnsignedLongTy
@@ -43,6 +43,7 @@
   C = llvm::ConstantInt::get(UnsignedLongTy, Size.getQuantity());
   Elts.push_back(C);
 
+  // optional copy/dispose helpers
   if (BlockHasCopyDispose) {
     // copy_func_helper_decl
     Elts.push_back(BuildCopyHelper(Ty, NoteForHelper));
@@ -51,6 +52,17 @@
     Elts.push_back(BuildDestroyHelper(Ty, NoteForHelper));
   }
 
+  // Signature.  non-optional ObjC-style method descriptor @encode sequence
+  std::string BlockTypeEncoding;
+  CGM.getContext().getObjCEncodingForBlock(BE, BlockTypeEncoding);
+
+  Elts.push_back(llvm::ConstantExpr::getBitCast(
+          CGM.GetAddrOfConstantCString(BlockTypeEncoding), PtrToInt8Ty));
+  
+  // Layout.
+  C = llvm::ConstantInt::get(UnsignedLongTy, 0);
+  Elts.push_back(C);
+
   C = llvm::ConstantStruct::get(VMContext, Elts, false);
 
   C = new llvm::GlobalVariable(CGM.getModule(), C->getType(), true,
@@ -135,30 +147,14 @@
 
   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;
 
   {
     // C = BuildBlockStructInitlist();
-    unsigned int flags = BLOCK_HAS_DESCRIPTOR;
-
-    if (hasIntrospection)
-      flags |= BLOCK_HAS_OBJC_TYPE;
+    unsigned int flags = BLOCK_HAS_OBJC_TYPE;
 
     // We run this first so that we set BlockHasCopyDispose from the entire
     // block literal.
@@ -199,7 +195,7 @@
 
     if (subBlockDeclRefDecls.size() == 0) {
       // __descriptor
-      Elts[4] = BuildDescriptorBlockDecl(subBlockHasCopyDispose, subBlockSize,
+      Elts[4] = BuildDescriptorBlockDecl(BE, subBlockHasCopyDispose, subBlockSize,
                                          0, 0);
 
       // Optimize to being a global block.
@@ -221,8 +217,6 @@
     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];
@@ -245,8 +239,6 @@
 
     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)
       {
@@ -335,7 +327,8 @@
     NoteForHelper.resize(helpersize);
 
     // __descriptor
-    llvm::Value *Descriptor = BuildDescriptorBlockDecl(subBlockHasCopyDispose,
+    llvm::Value *Descriptor = BuildDescriptorBlockDecl(BE,
+                                                       subBlockHasCopyDispose,
                                                        subBlockSize, Ty,
                                                        &NoteForHelper);
     Descriptor = Builder.CreateBitCast(Descriptor, PtrToInt8Ty);
@@ -371,6 +364,16 @@
   // struct __block_descriptor {
   //   unsigned long reserved;
   //   unsigned long block_size;
+  //
+  //   // later, the following will be added
+  //
+  //   struct {
+  //     void (*copyHelper)();
+  //     void (*copyHelper)();
+  //   } helpers;                // !!! optional
+  //
+  //   const char *signature;   // the block signature
+  //   const char *layout;      // reserved
   // };
   BlockDescriptorType = llvm::StructType::get(UnsignedLongTy->getContext(),
                                               UnsignedLongTy,
@@ -399,20 +402,8 @@
   //   int __reserved;
   //   void (*__invoke)(void *);
   //   struct __block_descriptor *__descriptor;
-  //   // GNU runtime only:
-  //   const char *types;
   // };
-  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(),
+  GenericBlockLiteralType = llvm::StructType::get(IntTy->getContext(),
                                                   PtrToInt8Ty,
                                                   IntTy,
                                                   IntTy,
@@ -556,7 +547,7 @@
   const llvm::IntegerType *IntTy = cast<llvm::IntegerType>(
     getTypes().ConvertType(getContext().IntTy));
 
-  llvm::Constant *DescriptorFields[2];
+  llvm::Constant *DescriptorFields[4];
 
   // Reserved
   DescriptorFields[0] = llvm::Constant::getNullValue(UnsignedLongTy);
@@ -567,9 +558,21 @@
     CGM.GetTargetTypeStoreSize(getGenericBlockLiteralType());
   DescriptorFields[1] =
     llvm::ConstantInt::get(UnsignedLongTy,BlockLiteralSize.getQuantity());
+  
+  // signature.  non-optional ObjC-style method descriptor @encode sequence
+  std::string BlockTypeEncoding;
+  CGM.getContext().getObjCEncodingForBlock(BE, BlockTypeEncoding);
+
+  DescriptorFields[2] = llvm::ConstantExpr::getBitCast(
+          CGM.GetAddrOfConstantCString(BlockTypeEncoding), PtrToInt8Ty);
+  
+  // layout
+  DescriptorFields[3] =
+    llvm::ConstantInt::get(UnsignedLongTy,0);
 
+  // build the structure from the 4 elements
   llvm::Constant *DescriptorStruct =
-    llvm::ConstantStruct::get(VMContext, &DescriptorFields[0], 2, false);
+    llvm::ConstantStruct::get(VMContext, &DescriptorFields[0], 4, false);
 
   llvm::GlobalVariable *Descriptor =
     new llvm::GlobalVariable(getModule(), DescriptorStruct->getType(), true,
@@ -578,8 +581,6 @@
 
   int FieldCount = 5;
   // Generate the constants for the block literal.
-  if (CGM.getContext().getLangOptions().BlockIntrospection)
-    FieldCount = 6;
 
   std::vector<llvm::Constant*> LiteralFields(FieldCount);
 
@@ -602,10 +603,8 @@
   LiteralFields[0] = getNSConcreteGlobalBlock();
 
   // Flags
-  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);
+  LiteralFields[1] =
+    llvm::ConstantInt::get(IntTy, BLOCK_IS_GLOBAL | BLOCK_HAS_OBJC_TYPE);
 
   // Reserved
   LiteralFields[2] = llvm::Constant::getNullValue(IntTy);
@@ -616,14 +615,6 @@
   // 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, false);
 

Modified: cfe/trunk/lib/CodeGen/CGBlocks.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBlocks.h?rev=96989&r1=96988&r2=96989&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGBlocks.h (original)
+++ cfe/trunk/lib/CodeGen/CGBlocks.h Tue Feb 23 15:51:17 2010
@@ -54,7 +54,6 @@
         BLOCK_HAS_COPY_DISPOSE =  (1 << 25),
         BLOCK_HAS_CXX_OBJ =       (1 << 26),
         BLOCK_IS_GLOBAL =         (1 << 28),
-        BLOCK_HAS_DESCRIPTOR =    (1 << 29),
         BLOCK_HAS_OBJC_TYPE  =    (1 << 30)
     };
 };

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=96989&r1=96988&r2=96989&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Tue Feb 23 15:51:17 2010
@@ -465,7 +465,8 @@
   //===--------------------------------------------------------------------===//
 
   llvm::Value *BuildBlockLiteralTmp(const BlockExpr *);
-  llvm::Constant *BuildDescriptorBlockDecl(bool BlockHasCopyDispose,
+  llvm::Constant *BuildDescriptorBlockDecl(const BlockExpr *,
+                                           bool BlockHasCopyDispose,
                                            CharUnits Size,
                                            const llvm::StructType *,
                                            std::vector<HelperInfo> *);

Modified: cfe/trunk/lib/Driver/Tools.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=96989&r1=96988&r2=96989&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/Tools.cpp (original)
+++ cfe/trunk/lib/Driver/Tools.cpp Tue Feb 23 15:51:17 2010
@@ -1011,7 +1011,6 @@
   // -fblocks=0 is default.
   if (Args.hasFlag(options::OPT_fblocks, options::OPT_fno_blocks,
                    getToolChain().IsBlocksDefault())) {
-    Args.AddLastArg(CmdArgs, options::OPT_fblock_introspection);
     CmdArgs.push_back("-fblocks");
   }
 

Added: cfe/trunk/test/CodeGen/blocksignature.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/blocksignature.c?rev=96989&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/blocksignature.c (added)
+++ cfe/trunk/test/CodeGen/blocksignature.c Tue Feb 23 15:51:17 2010
@@ -0,0 +1,94 @@
+// RUN: %clang_cc1 -fblocks -triple x86_64-apple-darwin9 %s -emit-llvm -o - | FileCheck %s -check-prefix=X64
+// RUN: %clang_cc1 -fblocks -triple i686-apple-darwin9 %s -emit-llvm -o - | FileCheck %s -check-prefix=X32
+
+// X64: @.str = private constant [6 x i8] c"v8@?0\00" 
+// X64: @__block_literal_global = internal constant %1 { i8** @_NSConcreteGlobalBlock, i32 1342177280,
+// X64: @.str1 = private constant [12 x i8] c"i16@?0c8f12\00"
+// X64:   store i32 1073741824, i32* %block.tmp2
+
+// X32: @.str = private constant [6 x i8] c"v4@?0\00" 
+// X32: @__block_literal_global = internal constant %1 { i8** @_NSConcreteGlobalBlock, i32 1342177280,
+// X32: @.str1 = private constant [11 x i8] c"i12@?0c4f8\00"
+// X32:   store i32 1073741824, i32* %block.tmp2
+
+// rdar://7635294
+
+
+int globalInt;
+void (^global)(void) = ^{ ++globalInt; };
+
+    
+void foo(int param) {
+   extern int rand(void);
+   extern void rand_r(int (^b)(char x, float y));   // name a function present at runtime
+   while (param--)
+      rand_r(^(char x, float y){ return x + (int)y + param + rand(); });  // generate a local block binding param
+}
+
+#if 0
+#include <stdio.h>
+enum {
+    BLOCK_HAS_COPY_DISPOSE =  (1 << 25),
+    BLOCK_HAS_CXX_OBJ =       (1 << 26),
+    BLOCK_IS_GLOBAL =         (1 << 28),
+    BLOCK_HAS_DESCRIPTOR =    (1 << 29),
+    BLOCK_HAS_OBJC_TYPE  =    (1 << 30)
+};
+
+struct block_descriptor_big {
+    unsigned long int reserved;
+    unsigned long int size;
+    void (*copy)(void *dst, void *src); // conditional on BLOCK_HAS_COPY_DISPOSE
+    void (*dispose)(void *);            // conditional on BLOCK_HAS_COPY_DISPOSE
+    const char *signature;                  // conditional on BLOCK_HAS_OBJC
+    const char *layout;                 // conditional on BLOCK_HAS_OBJC
+};
+struct block_descriptor_small {
+    unsigned long int reserved;
+    unsigned long int size;
+    const char *signature;              // conditional on BLOCK_HAS_OBJC
+    const char *layout;                 // conditional on BLOCK_HAS_OBJC
+};
+
+struct block_layout_abi { // can't change
+  void *isa;
+  int flags;
+  int reserved; 
+  void (*invoke)(void *, ...);
+  struct block_descriptor_big *descriptor;
+};
+
+const char *getBlockSignature(void *block) {
+   struct block_layout_abi *layout = (struct block_layout_abi *)block;
+   if ((layout->flags & BLOCK_HAS_OBJC_TYPE) != BLOCK_HAS_OBJC_TYPE) return NULL;
+   if (layout->flags & BLOCK_HAS_COPY_DISPOSE) 
+      return layout->descriptor->signature;
+   else
+      return ((struct block_descriptor_small *)layout->descriptor)->signature;
+}
+  
+    
+   
+int main(int argc, char *argv[]) {
+   printf("desired global flags: %d\n", BLOCK_IS_GLOBAL  | BLOCK_HAS_OBJC_TYPE);
+   printf("desired stack flags: %d\n",  BLOCK_HAS_OBJC_TYPE);
+   
+   printf("types for global: %s\n", getBlockSignature(global));
+   printf("types for local: %s\n", getBlockSignature(^int(char x, float y) { return (int)(y + x); }));
+   return 0;
+}
+
+/*
+x86_64
+desired global flags: 1342177280
+desired stack flags: 1073741824
+types for global: v8@?0
+types for local: i16@?0c8f12
+
+i386
+desired global flags: 1342177280
+desired stack flags: 1073741824
+types for global: v4@?0
+types for local: i12@?0c4f8
+*/
+#endif





More information about the cfe-commits mailing list