summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Basic/LangOptions.h2
-rw-r--r--clang/include/clang/Driver/Options.td1
-rw-r--r--clang/lib/CodeGen/CGBlocks.cpp97
-rw-r--r--clang/lib/CodeGen/CGBlocks.h1
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h3
-rw-r--r--clang/lib/Driver/Tools.cpp1
-rw-r--r--clang/test/CodeGen/blocksignature.c94
7 files changed, 140 insertions, 59 deletions
diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h
index d909f83e74d..edff4847719 100644
--- a/clang/include/clang/Basic/LangOptions.h
+++ b/clang/include/clang/Basic/LangOptions.h
@@ -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;
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 4693e5c1433..1f5f154fb8f 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -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>;
diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp
index c6c5d5a230c..7076067e438 100644
--- a/clang/lib/CodeGen/CGBlocks.cpp
+++ b/clang/lib/CodeGen/CGBlocks.cpp
@@ -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);
diff --git a/clang/lib/CodeGen/CGBlocks.h b/clang/lib/CodeGen/CGBlocks.h
index fc18c7cc564..39f26f8b136 100644
--- a/clang/lib/CodeGen/CGBlocks.h
+++ b/clang/lib/CodeGen/CGBlocks.h
@@ -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)
};
};
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index c4f0a9fcfff..64d5cbdb01a 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -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> *);
diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp
index d2391b391cd..145e29e7979 100644
--- a/clang/lib/Driver/Tools.cpp
+++ b/clang/lib/Driver/Tools.cpp
@@ -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/clang/test/CodeGen/blocksignature.c b/clang/test/CodeGen/blocksignature.c
new file mode 100644
index 00000000000..141693f9e4d
--- /dev/null
+++ b/clang/test/CodeGen/blocksignature.c
@@ -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
OpenPOWER on IntegriCloud