]> granicus.if.org Git - clang/commitdiff
Unconditionally support block introspection data in a new field at the end
authorBlaine Garst <blaine@apple.com>
Tue, 23 Feb 2010 21:51:17 +0000 (21:51 +0000)
committerBlaine Garst <blaine@apple.com>
Tue, 23 Feb 2010 21:51:17 +0000 (21:51 +0000)
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.

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

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 [new file with mode: 0644]

index d909f83e74d5e8bdad8341faa6bc3b9aaa7546cd..edff484771971293075c9b7e7b16e2b8eac136f4 100644 (file)
@@ -59,7 +59,6 @@ public:
   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 @@ public:
     ThreadsafeStatics = 1;
     POSIXThreads = 0;
     Blocks = 0;
-    BlockIntrospection = 0;
     EmitAllDecls = 0;
     MathErrno = 1;
 
index 4693e5c1433c4d51c733638bac76e38c86e0180c..1f5f154fb8f9552b7b55a77a6405f06942bc5e7e 100644 (file)
@@ -235,7 +235,6 @@ def fastcp : Flag<"-fastcp">, Group<f_Group>;
 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>;
index c6c5d5a230c6b59fe3751fa92f71ea02b1b468ff..7076067e4381b2b050bf19cc841b3cb6236f9e91 100644 (file)
@@ -24,7 +24,7 @@ using namespace clang;
 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 @@ BuildDescriptorBlockDecl(bool BlockHasCopyDispose, CharUnits Size,
   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 @@ BuildDescriptorBlockDecl(bool BlockHasCopyDispose, CharUnits Size,
     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 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
 
   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 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
 
     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 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
     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 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
 
     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 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
     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 @@ const llvm::Type *BlockModule::getBlockDescriptorType() {
   // 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 @@ const llvm::Type *BlockModule::getGenericBlockLiteralType() {
   //   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 @@ BlockModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) {
   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 @@ BlockModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) {
     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 @@ BlockModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) {
 
   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 @@ BlockModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) {
   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 @@ BlockModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) {
   // 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);
 
index fc18c7cc5647c8f500ee0c3cbfd6f2be96b4531c..39f26f8b1363e66522db2072a98d99b1731ba50b 100644 (file)
@@ -54,7 +54,6 @@ public:
         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)
     };
 };
index c4f0a9fcfffa2f95a87dd0c18d1086efa5952567..64d5cbdb01ac3c103e760b2520bafa32e768bf79 100644 (file)
@@ -465,7 +465,8 @@ public:
   //===--------------------------------------------------------------------===//
 
   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> *);
index d2391b391cd1375616511b47fd877a143c693a68..145e29e797966fa00c2ddb45fdf89afcf7a53943 100644 (file)
@@ -1011,7 +1011,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
   // -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");
   }
 
diff --git a/test/CodeGen/blocksignature.c b/test/CodeGen/blocksignature.c
new file mode 100644 (file)
index 0000000..141693f
--- /dev/null
@@ -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