aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGBlocks.cpp
diff options
context:
space:
mode:
authorMike Stump <mrs@apple.com>2009-02-25 23:33:13 +0000
committerMike Stump <mrs@apple.com>2009-02-25 23:33:13 +0000
commit8a2b4b1c5b960710db95e9b296d9a600aee37c00 (patch)
treee191004fda640e34ac654762007bd8dadda3deef /lib/CodeGen/CGBlocks.cpp
parentb293902c5cfa18365ffb0e00763849c9808a2ad1 (diff)
CodeGen support for copied BlockDeclRefExprs.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65487 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGBlocks.cpp')
-rw-r--r--lib/CodeGen/CGBlocks.cpp93
1 files changed, 75 insertions, 18 deletions
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp
index 163046ee58..65f6cb11e8 100644
--- a/lib/CodeGen/CGBlocks.cpp
+++ b/lib/CodeGen/CGBlocks.cpp
@@ -109,13 +109,14 @@ llvm::Constant *CodeGenModule::getNSConcreteStackBlock() {
// FIXME: Push most into CGM, passing down a few bits, like current
// function name.
-llvm::Constant *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
+llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
bool insideFunction = false;
bool BlockRefDeclList = false;
bool BlockByrefDeclList = false;
std::vector<llvm::Constant*> Elts;
llvm::Constant *C;
+ llvm::Value *V;
{
// C = BuildBlockStructInitlist();
@@ -152,32 +153,77 @@ llvm::Constant *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
if (ND->getIdentifier())
Name = ND->getNameAsCString();
BlockInfo Info(0, Name);
- uint64_t subBlockSize;
+ uint64_t subBlockSize, subBlockAlign;
+ llvm::SmallVector<ValueDecl *, 8> subBlockDeclRefDecls;
llvm::Function *Fn
- = CodeGenFunction(CGM).GenerateBlockFunction(BE, Info, subBlockSize);
+ = CodeGenFunction(CGM).GenerateBlockFunction(BE, Info, subBlockSize,
+ subBlockAlign, subBlockDeclRefDecls);
Elts.push_back(Fn);
// __descriptor
Elts.push_back(BuildDescriptorBlockDecl(subBlockSize));
- // FIXME: Add block_original_ref_decl_list and block_byref_decl_list.
+ // FIXME: Also check to make sure there are no byref variables
+ if (subBlockDeclRefDecls.size() == 0) {
+ C = llvm::ConstantStruct::get(Elts);
+
+ char Name[32];
+ sprintf(Name, "__block_holder_tmp_%d", CGM.getGlobalUniqueCount());
+ C = new llvm::GlobalVariable(C->getType(), true,
+ llvm::GlobalValue::InternalLinkage,
+ C, Name, &CGM.getModule());
+ QualType BPT = BE->getType();
+ 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();
+
+ for (unsigned i=0; i < subBlockDeclRefDecls.size(); ++i)
+ Types[i+5] = ConvertType(subBlockDeclRefDecls[i]->getType());
+
+ llvm::Type *Ty = llvm::StructType::get(Types, true);
+
+ llvm::AllocaInst *A = CreateTempAlloca(Ty);
+ A->setAlignment(subBlockAlign);
+ V = A;
+
+ 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)
+ {
+ ValueDecl *VD = subBlockDeclRefDecls[i];
+
+ if (VD->getIdentifier() == 0)
+ continue;
+ SourceLocation Loc = VD->getLocation();
+ DeclRefExpr D(VD, VD->getType(), Loc);
+ llvm::Value* Addr = Builder.CreateStructGEP(V, i+5, "tmp");
+ RValue r = EmitAnyExpr(&D, Addr, false);
+ if (r.isScalar())
+ Builder.CreateStore(r.getScalarVal(), Addr);
+ else if (r.isComplex())
+ // FIXME: implement
+ ErrorUnsupported(BE, "complex in block literal");
+ else if (r.isAggregate())
+ ; // Already created into the destination
+ else
+ assert (0 && "bad block variable");
+ // FIXME: Ensure that the offset created by the backend for
+ // the struct matches the previously computed offset in BlockDecls.
+ }
+
+ // FIXME: Add block_byref_decl_list.
}
- C = llvm::ConstantStruct::get(Elts);
-
- char Name[32];
- sprintf(Name, "__block_holder_tmp_%d", CGM.getGlobalUniqueCount());
- C = new llvm::GlobalVariable(C->getType(), true,
- llvm::GlobalValue::InternalLinkage,
- C, Name, &CGM.getModule());
QualType BPT = BE->getType();
- C = llvm::ConstantExpr::getBitCast(C, ConvertType(BPT));
- return C;
+ return Builder.CreateBitCast(V, ConvertType(BPT));
}
-
-
const llvm::Type *CodeGenModule::getBlockDescriptorType() {
if (BlockDescriptorType)
return BlockDescriptorType;
@@ -365,9 +411,12 @@ CodeGenModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) {
llvm::Constant *LiteralFields[5];
CodeGenFunction::BlockInfo Info(0, n);
- uint64_t subBlockSize;
+ uint64_t subBlockSize, subBlockAlign;
+ llvm::SmallVector<ValueDecl *, 8> subBlockDeclRefDecls;
llvm::Function *Fn
- = CodeGenFunction(*this).GenerateBlockFunction(BE, Info, subBlockSize);
+ = CodeGenFunction(*this).GenerateBlockFunction(BE, Info, subBlockSize,
+ subBlockAlign,
+ subBlockDeclRefDecls);
assert(subBlockSize == BlockLiteralSize
&& "no imports allowed for global block");
@@ -404,7 +453,9 @@ llvm::Value *CodeGenFunction::LoadBlockStruct() {
llvm::Function *CodeGenFunction::GenerateBlockFunction(const BlockExpr *Expr,
const BlockInfo& Info,
- uint64_t &Size) {
+ uint64_t &Size,
+ uint64_t &Align,
+ llvm::SmallVector<ValueDecl *, 8> &subBlockDeclRefDecls) {
const FunctionTypeProto *FTy =
cast<FunctionTypeProto>(Expr->getFunctionType());
@@ -442,7 +493,13 @@ llvm::Function *CodeGenFunction::GenerateBlockFunction(const BlockExpr *Expr,
EmitStmt(Expr->getBody());
FinishFunction(cast<CompoundStmt>(Expr->getBody())->getRBracLoc());
+ // The runtime needs a minimum alignment of a void *.
+ uint64_t MinAlign = getContext().getTypeAlign(getContext().VoidPtrTy) / 8;
+ BlockOffset = llvm::RoundUpToAlignment(BlockOffset, MinAlign);
+
Size = BlockOffset;
+ Align = BlockAlign;
+ subBlockDeclRefDecls = BlockDeclRefDecls;
return Fn;
}