[cfe-commits] r66159 - in /cfe/trunk: lib/CodeGen/CGBlocks.cpp lib/CodeGen/CGBlocks.h lib/CodeGen/CGDecl.cpp lib/CodeGen/CodeGenFunction.h test/CodeGenObjC/blocks-unsupported.m
Mike Stump
mrs at apple.com
Thu Mar 5 00:32:30 PST 2009
Author: mrs
Date: Thu Mar 5 02:32:30 2009
New Revision: 66159
URL: http://llvm.org/viewvc/llvm-project?rev=66159&view=rev
Log:
prep work for copy/destroy helpers for block literals.
Modified:
cfe/trunk/lib/CodeGen/CGBlocks.cpp
cfe/trunk/lib/CodeGen/CGBlocks.h
cfe/trunk/lib/CodeGen/CGDecl.cpp
cfe/trunk/lib/CodeGen/CodeGenFunction.h
cfe/trunk/test/CodeGenObjC/blocks-unsupported.m
Modified: cfe/trunk/lib/CodeGen/CGBlocks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBlocks.cpp?rev=66159&r1=66158&r2=66159&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGBlocks.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBlocks.cpp Thu Mar 5 02:32:30 2009
@@ -30,8 +30,8 @@
llvm::cl::desc("temporary option to turn on __block precessing "
"even though the code isn't done yet"),
llvm::cl::ValueDisallowed, llvm::cl::AllowInverse,
- llvm::cl::ZeroOrMore);
-
+ llvm::cl::ZeroOrMore,
+ llvm::cl::init(false));
llvm::Constant *CodeGenFunction::BuildDescriptorBlockDecl(uint64_t Size) {
const llvm::Type *UnsignedLongTy
@@ -53,13 +53,13 @@
if (BlockHasCopyDispose) {
// copy_func_helper_decl
// FIXME: implement
- C = llvm::ConstantInt::get(UnsignedLongTy, 0);
+ C = llvm::Constant::getNullValue(PtrToInt8Ty);
C = llvm::ConstantExpr::getBitCast(C, PtrToInt8Ty);
Elts.push_back(C);
// destroy_func_decl
// FIXME: implement
- C = llvm::ConstantInt::get(UnsignedLongTy, 0);
+ C = llvm::Constant::getNullValue(PtrToInt8Ty);
C = llvm::ConstantExpr::getBitCast(C, PtrToInt8Ty);
Elts.push_back(C);
}
@@ -80,7 +80,7 @@
// same thing as CreateRuntimeFunction if there's already a variable with the
// same name.
NSConcreteGlobalBlock
- = new llvm::GlobalVariable(PtrToInt8Ty, false,
+ = new llvm::GlobalVariable(PtrToInt8Ty, false,
llvm::GlobalValue::ExternalLinkage,
0, "_NSConcreteGlobalBlock",
&getModule());
@@ -96,7 +96,7 @@
// same thing as CreateRuntimeFunction if there's already a variable with the
// same name.
NSConcreteStackBlock
- = new llvm::GlobalVariable(PtrToInt8Ty, false,
+ = new llvm::GlobalVariable(PtrToInt8Ty, false,
llvm::GlobalValue::ExternalLinkage,
0, "_NSConcreteStackBlock",
&getModule());
@@ -104,18 +104,18 @@
return NSConcreteStackBlock;
}
-static void CollectBlockDeclRefInfo(const Stmt *S,
+static void CollectBlockDeclRefInfo(const Stmt *S,
CodeGenFunction::BlockInfo &Info) {
for (Stmt::const_child_iterator I = S->child_begin(), E = S->child_end();
I != E; ++I)
if (*I)
CollectBlockDeclRefInfo(*I, Info);
-
+
if (const BlockDeclRefExpr *DE = dyn_cast<BlockDeclRefExpr>(S)) {
// FIXME: Handle enums.
if (isa<FunctionDecl>(DE->getDecl()))
return;
-
+
if (DE->isByRef())
Info.ByRefDeclRefs.push_back(DE);
else
@@ -144,8 +144,8 @@
// CGF, then we can just check to see if CGF is 0.
if (0 && CanBlockBeGlobal(Info))
return CGM.GetAddrOfGlobalBlock(BE, Name.c_str());
-
- std::vector<llvm::Constant*> Elts;
+
+ std::vector<llvm::Constant*> Elts(5);
llvm::Constant *C;
llvm::Value *V;
@@ -153,34 +153,41 @@
// C = BuildBlockStructInitlist();
unsigned int flags = BLOCK_HAS_DESCRIPTOR;
+ // We run this first so that we set BlockHasCopyDispose from the entire
+ // block literal.
+ // __invoke
+ uint64_t subBlockSize, subBlockAlign;
+ llvm::SmallVector<const Expr *, 8> subBlockDeclRefDecls;
+ llvm::Function *Fn
+ = CodeGenFunction(CGM).GenerateBlockFunction(BE, Info, subBlockSize,
+ subBlockAlign,
+ subBlockDeclRefDecls,
+ BlockHasCopyDispose);
+ Elts[3] = Fn;
+
+ if (!Enable__block && BlockHasCopyDispose)
+ ErrorUnsupported(BE, "block literal that requires copy/dispose");
+
if (BlockHasCopyDispose)
flags |= BLOCK_HAS_COPY_DISPOSE;
// __isa
C = CGM.getNSConcreteStackBlock();
C = llvm::ConstantExpr::getBitCast(C, PtrToInt8Ty);
- Elts.push_back(C);
+ Elts[0] = C;
// __flags
const llvm::IntegerType *IntTy = cast<llvm::IntegerType>(
CGM.getTypes().ConvertType(CGM.getContext().IntTy));
C = llvm::ConstantInt::get(IntTy, flags);
- Elts.push_back(C);
+ Elts[1] = C;
// __reserved
C = llvm::ConstantInt::get(IntTy, 0);
- Elts.push_back(C);
-
- // __invoke
- uint64_t subBlockSize, subBlockAlign;
- llvm::SmallVector<const Expr *, 8> subBlockDeclRefDecls;
- llvm::Function *Fn
- = CodeGenFunction(CGM).GenerateBlockFunction(BE, Info, subBlockSize,
- subBlockAlign, subBlockDeclRefDecls);
- Elts.push_back(Fn);
+ Elts[2] = C;
// __descriptor
- Elts.push_back(BuildDescriptorBlockDecl(subBlockSize));
+ Elts[4] = BuildDescriptorBlockDecl(subBlockSize);
if (subBlockDeclRefDecls.size() == 0) {
// Optimize to being a global block.
@@ -198,7 +205,7 @@
C = llvm::ConstantExpr::getBitCast(C, ConvertType(BPT));
return C;
}
-
+
std::vector<const llvm::Type *> Types(5+subBlockDeclRefDecls.size());
for (int i=0; i<5; ++i)
Types[i] = Elts[i]->getType();
@@ -222,7 +229,7 @@
for (unsigned i=0; i<5; ++i)
Builder.CreateStore(Elts[i], Builder.CreateStructGEP(V, i, "block.tmp"));
-
+
for (unsigned i=0; i < subBlockDeclRefDecls.size(); ++i)
{
// FIXME: Push const down.
@@ -254,7 +261,6 @@
false, false);
}
if (BDRE->isByRef()) {
- // FIXME: __block in nested literals
E = new (getContext())
UnaryOperator(E, UnaryOperator::AddrOf,
getContext().getPointerType(E->getType()),
@@ -272,9 +278,9 @@
// be done during Block_copy for us, and we can postpone the work
// until then.
uint64_t offset = BlockDecls[BDRE->getDecl()];
-
+
llvm::Value *BlockLiteral = LoadBlockStruct();
-
+
Loc = Builder.CreateGEP(BlockLiteral,
llvm::ConstantInt::get(llvm::Type::Int64Ty,
offset),
@@ -296,7 +302,7 @@
// the struct matches the previously computed offset in BlockDecls.
}
}
-
+
QualType BPT = BE->getType();
return Builder.CreateBitCast(V, ConvertType(BPT));
}
@@ -461,7 +467,7 @@
ErrorUnsupported(E, "__block variable in block literal");
else if (E->getType()->isBlockPointerType())
ErrorUnsupported(E, "block pointer in block literal");
- else if (E->getDecl()->getAttr<ObjCNSObjectAttr>() ||
+ else if (E->getDecl()->getAttr<ObjCNSObjectAttr>() ||
getContext().isObjCNSObjectType(E->getType()))
ErrorUnsupported(E, "__attribute__((NSObject)) variable in block "
"literal");
@@ -470,6 +476,9 @@
// See if we have already allocated an offset for this variable.
if (offset == 0) {
+ // Don't run the expensive check, unless we have to.
+ if (!BlockHasCopyDispose && BlockRequiresCopying(E->getType()))
+ BlockHasCopyDispose = true;
// if not, allocate one now.
offset = getBlockOffset(E);
}
@@ -532,18 +541,21 @@
CodeGenFunction::BlockInfo Info(0, n);
uint64_t subBlockSize, subBlockAlign;
llvm::SmallVector<const Expr *, 8> subBlockDeclRefDecls;
+ bool subBlockHasCopyDispose;
llvm::Function *Fn
= CodeGenFunction(CGM).GenerateBlockFunction(BE, Info, subBlockSize,
subBlockAlign,
- subBlockDeclRefDecls);
+ subBlockDeclRefDecls,
+ subBlockHasCopyDispose);
assert(subBlockSize == BlockLiteralSize
&& "no imports allowed for global block");
+ assert(!subBlockHasCopyDispose && "no imports allowed for global block");
// isa
LiteralFields[0] = getNSConcreteGlobalBlock();
// Flags
- LiteralFields[1] =
+ LiteralFields[1] =
llvm::ConstantInt::get(IntTy, BLOCK_IS_GLOBAL | BLOCK_HAS_DESCRIPTOR);
// Reserved
@@ -571,11 +583,13 @@
return Builder.CreateLoad(LocalDeclMap[getBlockStructDecl()], "self");
}
-llvm::Function *CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr,
- const BlockInfo& Info,
- uint64_t &Size,
- uint64_t &Align,
- llvm::SmallVector<const Expr *, 8> &subBlockDeclRefDecls) {
+llvm::Function *
+CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr,
+ const BlockInfo& Info,
+ uint64_t &Size,
+ uint64_t &Align,
+ llvm::SmallVector<const Expr *, 8> &subBlockDeclRefDecls,
+ bool &subBlockHasCopyDispose) {
const FunctionProtoType *FTy =
cast<FunctionProtoType>(BExpr->getFunctionType());
@@ -620,7 +634,7 @@
Size = BlockOffset;
Align = BlockAlign;
subBlockDeclRefDecls = BlockDeclRefDecls;
-
+ subBlockHasCopyDispose |= BlockHasCopyDispose;
return Fn;
}
@@ -642,7 +656,7 @@
// Ensure proper alignment, even if it means we have to have a gap
BlockOffset = llvm::RoundUpToAlignment(BlockOffset, Align);
BlockAlign = std::max(Align, BlockAlign);
-
+
uint64_t Pad = BlockOffset - OldOffset;
if (Pad) {
llvm::ArrayType::get(llvm::Type::Int8Ty, Pad);
@@ -687,7 +701,7 @@
ArgTys.push_back(PtrToInt8Ty);
ArgTys.push_back(llvm::Type::Int32Ty);
FTy = llvm::FunctionType::get(ResultType, ArgTys, false);
- CGM.BlockObjectDispose
+ CGM.BlockObjectDispose
= CGM.CreateRuntimeFunction(FTy, "_Block_object_dispose");
}
return CGM.BlockObjectDispose;
@@ -702,3 +716,5 @@
N = llvm::ConstantInt::get(llvm::Type::Int32Ty, BLOCK_FIELD_IS_BYREF);
Builder.CreateCall2(F, V, N);
}
+
+ASTContext &BlockFunction::getContext() const { return CGM.getContext(); }
Modified: cfe/trunk/lib/CodeGen/CGBlocks.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBlocks.h?rev=66159&r1=66158&r2=66159&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGBlocks.h (original)
+++ cfe/trunk/lib/CodeGen/CGBlocks.h Thu Mar 5 02:32:30 2009
@@ -110,6 +110,7 @@
class BlockFunction : public BlockBase {
CodeGenModule &CGM;
+ ASTContext &getContext() const;
public:
const llvm::Type *PtrToInt8Ty;
@@ -160,6 +161,14 @@
llvm::Value *getBlockObjectDispose();
void BuildBlockRelease(const VarDecl &D, llvm::Value *DeclPtr);
+
+ bool BlockRequiresCopying(QualType Ty) {
+ if (Ty->isBlockPointerType())
+ return true;
+ if (getContext().isObjCNSObjectType(Ty))
+ return true;
+ return false;
+ }
};
} // end namespace CodeGen
Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=66159&r1=66158&r2=66159&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDecl.cpp Thu Mar 5 02:32:30 2009
@@ -338,6 +338,9 @@
int flag = 0;
int flags = 0;
+ // The block literal will need a copy/destroy helper.
+ BlockHasCopyDispose = true;
+
if (Ty->isBlockPointerType()) {
flag |= BLOCK_FIELD_IS_BLOCK;
flags |= BLOCK_HAS_COPY_DISPOSE;
@@ -360,11 +363,15 @@
V = llvm::ConstantInt::get(llvm::Type::Int32Ty, flags);
Builder.CreateStore(V, flags_field);
- const llvm::Type *V1 = cast<llvm::PointerType>(DeclPtr->getType())->getElementType();
- V = llvm::ConstantInt::get(llvm::Type::Int32Ty, CGM.getTargetData().getTypeStoreSizeInBits(V1) / 8);
+ const llvm::Type *V1;
+ V1 = cast<llvm::PointerType>(DeclPtr->getType())->getElementType();
+ V = llvm::ConstantInt::get(llvm::Type::Int32Ty,
+ (CGM.getTargetData().getTypeStoreSizeInBits(V1)
+ / 8));
Builder.CreateStore(V, size_field);
if (flags & BLOCK_HAS_COPY_DISPOSE) {
+ BlockHasCopyDispose = true;
llvm::Value *copy_helper = Builder.CreateStructGEP(DeclPtr, 4);
llvm::Value *destroy_helper = Builder.CreateStructGEP(DeclPtr, 5);
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=66159&r1=66158&r2=66159&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Thu Mar 5 02:32:30 2009
@@ -271,8 +271,8 @@
llvm::Function *GenerateBlockFunction(const BlockExpr *BExpr,
const BlockInfo& Info,
uint64_t &Size, uint64_t &Align,
- llvm::SmallVector<const Expr *, 8> &subBlockDeclRefDecls);
-
+ llvm::SmallVector<const Expr *, 8> &subBlockDeclRefDecls,
+ bool &subBlockHasCopyDispose);
llvm::Value *LoadBlockStruct();
@@ -288,6 +288,7 @@
uint64_t BlockOffset;
/// BlockAlign - Maximal alignment needed for the Block expressed in bytes.
uint64_t BlockAlign;
+
/// getBlockOffset - Allocate an offset for the ValueDecl from a
/// BlockDeclRefExpr in a block literal (BlockExpr).
uint64_t getBlockOffset(const BlockDeclRefExpr *E);
@@ -298,13 +299,6 @@
llvm::Value *GetAddrOfBlockDecl(const BlockDeclRefExpr *E);
const llvm::Type *BuildByRefType(QualType Ty, uint64_t Align);
- bool BlockRequiresCopying(QualType Ty) {
- if (Ty->isBlockPointerType())
- return true;
- if (getContext().isObjCNSObjectType(Ty))
- return true;
- return false;
- }
void GenerateCode(const FunctionDecl *FD,
llvm::Function *Fn);
Modified: cfe/trunk/test/CodeGenObjC/blocks-unsupported.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/blocks-unsupported.m?rev=66159&r1=66158&r2=66159&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjC/blocks-unsupported.m (original)
+++ cfe/trunk/test/CodeGenObjC/blocks-unsupported.m Thu Mar 5 02:32:30 2009
@@ -5,30 +5,28 @@
void t1()
{
- __block int a;
- ^{ a = 10; }(); // expected-error {{cannot compile this __block variable in block literal yet}}
-
- void (^block)(void);
- ^{ (void)block; }(); // expected-error {{}}
-
- struct Foo *__attribute__ ((NSObject)) foo;
- ^{ (void)foo; }(); // expected-error {{cannot compile this __attribute__((NSObject)) variable in block literal yet}}
-
- typedef struct CGColor * __attribute__ ((NSObject)) CGColorRef;
- CGColorRef color;
- ^{ (void)color; }(); // expected-error {{cannot compile this __attribute__((NSObject)) variable in block literal yet}}
-
- id a1;
- ^{ (void)a1; }(); // expected-error {{cannot compile this Objective-C variable in block literal yet}}
-
- Foo *a2;
- ^{ (void)a2; }(); // expected-error {{cannot compile this Objective-C variable in block literal yet}}
-
- id<P> a3;
- ^{ (void)a3; }(); // expected-error {{cannot compile this Objective-C variable in block literal yet}}
-
- Foo<P> *a4;
- ^{ (void)a4; }(); // expected-error {{cannot compile this Objective-C variable in block literal yet}}
-
-
+ __block int a;
+ ^{ a = 10; }(); // expected-error {{cannot compile this __block variable in block literal yet}} expected-error {{cannot compile this block literal that requires copy/dispose yet}}
+
+ void (^block)(void);
+ ^{ (void)block; }(); // expected-error {{cannot compile this block pointer in block literal yet}} expected-error {{cannot compile this block literal that requires copy/dispose yet}}
+
+ struct Foo *__attribute__ ((NSObject)) foo;
+ ^{ (void)foo; }(); // expected-error {{cannot compile this __attribute__((NSObject)) variable in block literal yet}} expected-error {{cannot compile this block literal that requires copy/dispose yet}}
+
+ typedef struct CGColor * __attribute__ ((NSObject)) CGColorRef;
+ CGColorRef color;
+ ^{ (void)color; }(); // expected-error {{cannot compile this __attribute__((NSObject)) variable in block literal yet}} expected-error {{cannot compile this block literal that requires copy/dispose yet}}
+
+ id a1;
+ ^{ (void)a1; }(); // expected-error {{cannot compile this Objective-C variable in block literal yet}} expected-error {{cannot compile this block literal that requires copy/dispose yet}}
+
+ Foo *a2;
+ ^{ (void)a2; }(); // expected-error {{cannot compile this Objective-C variable in block literal yet}} expected-error {{cannot compile this block literal that requires copy/dispose yet}}
+
+ id<P> a3;
+ ^{ (void)a3; }(); // expected-error {{cannot compile this Objective-C variable in block literal yet}} expected-error {{cannot compile this block literal that requires copy/dispose yet}}
+
+ Foo<P> *a4;
+ ^{ (void)a4; }(); // expected-error {{cannot compile this Objective-C variable in block literal yet}} expected-error {{cannot compile this block literal that requires copy/dispose yet}}
}
More information about the cfe-commits
mailing list