Do some blocks cleanup and simplification. Fix a crash, and add a test case.

llvm-svn: 65746
This commit is contained in:
Anders Carlsson 2009-03-01 01:09:12 +00:00
parent e87da66562
commit ed5e69fe50
4 changed files with 50 additions and 16 deletions

View File

@ -107,13 +107,43 @@ llvm::Constant *CodeGenModule::getNSConcreteStackBlock() {
return NSConcreteStackBlock;
}
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)
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
Info.ByCopyDeclRefs.push_back(DE);
}
}
/// CanBlockBeGlobal - Given a BlockInfo struct, determines if a block
/// can be declared as a global variable instead of on the stack.
static bool CanBlockBeGlobal(const CodeGenFunction::BlockInfo &Info)
{
return Info.ByRefDeclRefs.empty() && Info.ByCopyDeclRefs.empty();
}
// FIXME: Push most into CGM, passing down a few bits, like current
// function name.
llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
bool insideFunction = false;
bool BlockRefDeclList = false;
bool BlockByrefDeclList = false;
std::string Name = CurFn->getName();
CodeGenFunction::BlockInfo Info(0, Name.c_str());
CollectBlockDeclRefInfo(BE->getBody(), Info);
// Check if the block can be global.
if (CanBlockBeGlobal(Info))
return CGM.GetAddrOfGlobalBlock(BE, Name.c_str());
std::vector<llvm::Constant*> Elts;
llvm::Constant *C;
llvm::Value *V;
@ -127,11 +157,6 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
// __isa
C = CGM.getNSConcreteStackBlock();
if (!insideFunction ||
(!BlockRefDeclList && !BlockByrefDeclList)) {
C = CGM.getNSConcreteGlobalBlock();
flags |= BLOCK_IS_GLOBAL;
}
const llvm::PointerType *PtrToInt8Ty
= llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
C = llvm::ConstantExpr::getBitCast(C, PtrToInt8Ty);
@ -148,11 +173,6 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
Elts.push_back(C);
// __invoke
const char *Name = "";
if (const NamedDecl *ND = dyn_cast<NamedDecl>(CurFuncDecl))
if (ND->getIdentifier())
Name = ND->getNameAsCString();
BlockInfo Info(0, Name);
uint64_t subBlockSize, subBlockAlign;
llvm::SmallVector<const Expr *, 8> subBlockDeclRefDecls;
llvm::Function *Fn

View File

@ -450,9 +450,13 @@ public:
return CGM.GetAddrOfConstantCFString(S);
}
case Expr::BlockExprClass: {
BlockExpr *B = cast<BlockExpr>(E);
if (!B->hasBlockDeclRefExprs())
return cast<llvm::Constant>(CGF->BuildBlockLiteralTmp(B));
std::string FunctionName;
if (CGF)
FunctionName = CGF->CurFn->getName();
else
FunctionName = "global";
return CGM.GetAddrOfGlobalBlock(cast<BlockExpr>(E), FunctionName.c_str());
}
}

View File

@ -275,6 +275,14 @@ public:
/// Name - the name of the function this block was created for, if any
const char *Name;
/// ByCopyDeclRefs - Variables from parent scopes that have been imported
/// into this block.
llvm::SmallVector<const BlockDeclRefExpr *, 8> ByCopyDeclRefs;
// ByRefDeclRefs - __block variables from parent scopes that have been
// imported into this block.
llvm::SmallVector<const BlockDeclRefExpr *, 8> ByRefDeclRefs;
BlockInfo(const llvm::Type *blt, const char *n)
: BlockLiteralTy(blt), Name(n) {}
};

View File

@ -0,0 +1,2 @@
// RUN: clang %s -emit-llvm -o %t -fblocks
void (^f)(void) = ^{};