aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/CodeGen/CGBlocks.cpp104
-rw-r--r--lib/CodeGen/CGBlocks.h46
-rw-r--r--lib/CodeGen/CGExprScalar.cpp3
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp1
-rw-r--r--lib/CodeGen/CodeGenFunction.h24
-rw-r--r--test/CodeGen/blocks-1.c2
6 files changed, 128 insertions, 52 deletions
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp
index 3b602a0a1b..8020a8b26f 100644
--- a/lib/CodeGen/CGBlocks.cpp
+++ b/lib/CodeGen/CGBlocks.cpp
@@ -34,7 +34,8 @@ Enable__block("f__block",
llvm::cl::init(false));
llvm::Constant *CodeGenFunction::
-BuildDescriptorBlockDecl(uint64_t Size, const llvm::Type* Ty) {
+BuildDescriptorBlockDecl(uint64_t Size, const llvm::StructType* Ty,
+ std::vector<HelperInfo> *NoteForHelper) {
const llvm::Type *UnsignedLongTy
= CGM.getTypes().ConvertType(getContext().UnsignedLongTy);
llvm::Constant *C;
@@ -53,10 +54,10 @@ BuildDescriptorBlockDecl(uint64_t Size, const llvm::Type* Ty) {
if (BlockHasCopyDispose) {
// copy_func_helper_decl
- Elts.push_back(BuildCopyHelper(Ty));
+ Elts.push_back(BuildCopyHelper(Ty, *NoteForHelper));
// destroy_func_decl
- Elts.push_back(BuildDestroyHelper(Ty));
+ Elts.push_back(BuildDestroyHelper(Ty, *NoteForHelper));
}
C = llvm::ConstantStruct::get(Elts);
@@ -183,7 +184,7 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
if (subBlockDeclRefDecls.size() == 0) {
// __descriptor
- Elts[4] = BuildDescriptorBlockDecl(subBlockSize, 0);
+ Elts[4] = BuildDescriptorBlockDecl(subBlockSize, 0, 0);
// Optimize to being a global block.
Elts[0] = CGM.getNSConcreteGlobalBlock();
@@ -202,8 +203,9 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
}
std::vector<const llvm::Type *> Types(5+subBlockDeclRefDecls.size());
- for (int i=0; i<5; ++i)
+ for (int i=0; i<4; ++i)
Types[i] = Elts[i]->getType();
+ Types[4] = PtrToInt8Ty;
for (unsigned i=0; i < subBlockDeclRefDecls.size(); ++i) {
const Expr *E = subBlockDeclRefDecls[i];
@@ -216,13 +218,16 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
Types[i+5] = ConvertType(Ty);
}
- llvm::Type *Ty = llvm::StructType::get(Types, true);
+ llvm::StructType *Ty = llvm::StructType::get(Types, true);
llvm::AllocaInst *A = CreateTempAlloca(Ty);
A->setAlignment(subBlockAlign);
V = A;
- for (unsigned i=0; i<5; ++i)
+ std::vector<HelperInfo> NoteForHelper(subBlockDeclRefDecls.size());
+ int helpersize = 0;
+
+ for (unsigned i=0; i<4; ++i)
Builder.CreateStore(Elts[i], Builder.CreateStructGEP(V, i, "block.tmp"));
for (unsigned i=0; i < subBlockDeclRefDecls.size(); ++i)
@@ -240,15 +245,24 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
VD = BDRE->getDecl();
llvm::Value* Addr = Builder.CreateStructGEP(V, i+5, "tmp");
- // FIXME: I want a better way to do this.
+ NoteForHelper[helpersize].index = i+5;
+ NoteForHelper[helpersize].RequiresCopying = BlockRequiresCopying(VD->getType());
+ NoteForHelper[helpersize].flag
+ = VD->getType()->isBlockPointerType() ? BLOCK_FIELD_IS_BLOCK : BLOCK_FIELD_IS_OBJECT;
+
if (LocalDeclMap[VD]) {
if (BDRE->isByRef()) {
+ // FIXME: For only local, or all byrefs?
+ NoteForHelper[helpersize].flag = BLOCK_FIELD_IS_BYREF |
+ (0?BLOCK_FIELD_IS_WEAK : 0);
+ // FIXME: Add weak support
const llvm::Type *Ty = Types[i+5];
llvm::Value *Loc = LocalDeclMap[VD];
Loc = Builder.CreateStructGEP(Loc, 1, "forwarding");
Loc = Builder.CreateLoad(Loc, false);
Loc = Builder.CreateBitCast(Loc, Ty);
Builder.CreateStore(Loc, Addr);
+ ++helpersize;
continue;
} else
E = new (getContext()) DeclRefExpr (cast<NamedDecl>(VD),
@@ -261,6 +275,7 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
getContext().getPointerType(E->getType()),
SourceLocation());
}
+ ++helpersize;
RValue r = EmitAnyExpr(E, Addr, false);
if (r.isScalar()) {
@@ -296,9 +311,13 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
// FIXME: Ensure that the offset created by the backend for
// the struct matches the previously computed offset in BlockDecls.
}
+ NoteForHelper.resize(helpersize);
// __descriptor
- Elts[4] = BuildDescriptorBlockDecl(subBlockSize, Ty);
+ llvm::Value *Descriptor = BuildDescriptorBlockDecl(subBlockSize, Ty,
+ &NoteForHelper);
+ Descriptor = Builder.CreateBitCast(Descriptor, PtrToInt8Ty);
+ Builder.CreateStore(Descriptor, Builder.CreateStructGEP(V, 4, "block.tmp"));
}
QualType BPT = BE->getType();
@@ -636,7 +655,7 @@ CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr,
return Fn;
}
-uint64_t CodeGenFunction::getBlockOffset(const BlockDeclRefExpr *BDRE) {
+uint64_t BlockFunction::getBlockOffset(const BlockDeclRefExpr *BDRE) {
const ValueDecl *D = dyn_cast<ValueDecl>(BDRE->getDecl());
uint64_t Size = getContext().getTypeSize(D->getType()) / 8;
@@ -675,15 +694,20 @@ uint64_t CodeGenFunction::getBlockOffset(const BlockDeclRefExpr *BDRE) {
return BlockOffset-Size;
}
-llvm::Constant *BlockFunction::GenerateCopyHelperFunction(const llvm::Type *Ty) {
+llvm::Constant *BlockFunction::
+GenerateCopyHelperFunction(bool BlockHasCopyDispose, const llvm::StructType *T,
+ std::vector<HelperInfo> &NoteForHelper) {
QualType R = getContext().VoidTy;
FunctionArgList Args;
// FIXME: This leaks
+ ImplicitParamDecl *Dst =
+ ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
+ getContext().getPointerType(getContext().VoidTy));
+ Args.push_back(std::make_pair(Dst, Dst->getType()));
ImplicitParamDecl *Src =
ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
getContext().getPointerType(getContext().VoidTy));
-
Args.push_back(std::make_pair(Src, Src->getType()));
const CGFunctionInfo &FI =
@@ -707,14 +731,46 @@ llvm::Constant *BlockFunction::GenerateCopyHelperFunction(const llvm::Type *Ty)
FunctionDecl::Static, false,
true);
CGF.StartFunction(FD, R, Fn, Args, SourceLocation());
- // EmitStmt(BExpr->getBody());
+
+ llvm::Value *SrcObj = CGF.GetAddrOfLocalVar(Src);
+ llvm::Type *PtrPtrT;
+ PtrPtrT = llvm::PointerType::get(llvm::PointerType::get(T, 0), 0);
+ SrcObj = Builder.CreateBitCast(SrcObj, PtrPtrT);
+ SrcObj = Builder.CreateLoad(SrcObj);
+
+ llvm::Value *DstObj = CGF.GetAddrOfLocalVar(Dst);
+ DstObj = Builder.CreateBitCast(DstObj, llvm::PointerType::get(T, 0));
+
+ for (unsigned i=0; i < NoteForHelper.size(); ++i) {
+ int flag = NoteForHelper[i].flag;
+ int index = NoteForHelper[i].index;
+
+ if ((NoteForHelper[i].flag & BLOCK_FIELD_IS_BYREF)
+ || NoteForHelper[i].RequiresCopying) {
+ llvm::Value *Srcv = SrcObj;
+ Srcv = Builder.CreateStructGEP(Srcv, index);
+ Srcv = Builder.CreateBitCast(Srcv,
+ llvm::PointerType::get(PtrToInt8Ty, 0));
+ Srcv = Builder.CreateLoad(Srcv);
+
+ llvm::Value *Dstv = Builder.CreateStructGEP(DstObj, index);
+ Dstv = Builder.CreateBitCast(Dstv, PtrToInt8Ty);
+
+ llvm::Value *N = llvm::ConstantInt::get(llvm::Type::Int32Ty, flag);
+ llvm::Value *F = getBlockObjectAssign();
+ Builder.CreateCall3(F, Dstv, Srcv, N);
+ }
+ }
+
CGF.FinishFunction();
return llvm::ConstantExpr::getBitCast(Fn, PtrToInt8Ty);
}
llvm::Constant *BlockFunction::
-GenerateDestroyHelperFunction(const llvm::Type* Ty) {
+GenerateDestroyHelperFunction(bool BlockHasCopyDispose,
+ const llvm::StructType* T,
+ std::vector<HelperInfo> &NoteForHelper) {
QualType R = getContext().VoidTy;
FunctionArgList Args;
@@ -752,12 +808,16 @@ GenerateDestroyHelperFunction(const llvm::Type* Ty) {
return llvm::ConstantExpr::getBitCast(Fn, PtrToInt8Ty);
}
-llvm::Constant *BlockFunction::BuildCopyHelper(const llvm::Type *Ty) {
- return CodeGenFunction(CGM).GenerateCopyHelperFunction(Ty);
+llvm::Constant *BlockFunction::BuildCopyHelper(const llvm::StructType *T,
+ std::vector<HelperInfo> &NoteForHelper) {
+ return CodeGenFunction(CGM).GenerateCopyHelperFunction(BlockHasCopyDispose,
+ T, NoteForHelper);
}
-llvm::Constant *BlockFunction::BuildDestroyHelper(const llvm::Type *Ty) {
- return CodeGenFunction(CGM).GenerateDestroyHelperFunction(Ty);
+llvm::Constant *BlockFunction::BuildDestroyHelper(const llvm::StructType *T,
+ std::vector<HelperInfo> &NoteForHelper) {
+ return CodeGenFunction(CGM).GenerateDestroyHelperFunction(BlockHasCopyDispose,
+ T, NoteForHelper);
}
llvm::Constant *BlockFunction::
@@ -924,3 +984,11 @@ void BlockFunction::BuildBlockRelease(llvm::Value *V, int flag) {
}
ASTContext &BlockFunction::getContext() const { return CGM.getContext(); }
+
+BlockFunction::BlockFunction(CodeGenModule &cgm, CodeGenFunction &cgf,
+ CGBuilderTy &B)
+ : CGM(cgm), CGF(cgf), Builder(B) {
+ PtrToInt8Ty = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
+
+ BlockHasCopyDispose = false;
+}
diff --git a/lib/CodeGen/CGBlocks.h b/lib/CodeGen/CGBlocks.h
index 5d6c089923..3eca891289 100644
--- a/lib/CodeGen/CGBlocks.h
+++ b/lib/CodeGen/CGBlocks.h
@@ -103,7 +103,8 @@ public:
: Context(C), TheModule(M), TheTargetData(TD), Types(T),
CGM(CodeGen),
NSConcreteGlobalBlock(0), NSConcreteStackBlock(0), BlockDescriptorType(0),
- GenericBlockLiteralType(0), BlockObjectAssign(0), BlockObjectDispose(0) {
+ GenericBlockLiteralType(0), GenericExtendedBlockLiteralType(0),
+ BlockObjectAssign(0), BlockObjectDispose(0) {
Block.GlobalUniqueCount = 0;
PtrToInt8Ty = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
}
@@ -116,6 +117,12 @@ class BlockFunction : public BlockBase {
public:
const llvm::Type *PtrToInt8Ty;
+ struct HelperInfo {
+ int index;
+ int flag;
+ bool RequiresCopying;
+ };
+
enum {
BLOCK_FIELD_IS_OBJECT = 3, /* id, NSObject, __attribute__((NSObject)),
block, ... */
@@ -150,19 +157,40 @@ public:
CGBuilderTy &Builder;
- BlockFunction(CodeGenModule &cgm, CodeGenFunction &cgf, CGBuilderTy &B)
- : CGM(cgm), CGF(cgf), Builder(B) {
- PtrToInt8Ty = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
- }
+ BlockFunction(CodeGenModule &cgm, CodeGenFunction &cgf, CGBuilderTy &B);
+
+ /// BlockOffset - The offset in bytes for the next allocation of an
+ /// imported block variable.
+ 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);
+
+ /// BlockHasCopyDispose - True iff the block uses copy/dispose.
+ bool BlockHasCopyDispose;
+
+ /// BlockDeclRefDecls - Decls from BlockDeclRefExprs in apperance order
+ /// in a block literal. Decls without names are used for padding.
+ llvm::SmallVector<const Expr *, 8> BlockDeclRefDecls;
+
+ /// BlockDecls - Offsets for all Decls in BlockDeclRefExprs.
+ std::map<const Decl*, uint64_t> BlockDecls;
ImplicitParamDecl *BlockStructDecl;
ImplicitParamDecl *getBlockStructDecl() { return BlockStructDecl; }
- llvm::Constant *GenerateCopyHelperFunction(const llvm::Type *);
- llvm::Constant *GenerateDestroyHelperFunction(const llvm::Type *);
+ llvm::Constant *GenerateCopyHelperFunction(bool, const llvm::StructType *,
+ std::vector<HelperInfo> &);
+ llvm::Constant *GenerateDestroyHelperFunction(bool, const llvm::StructType *,
+ std::vector<HelperInfo> &);
- llvm::Constant *BuildCopyHelper(const llvm::Type *);
- llvm::Constant *BuildDestroyHelper(const llvm::Type *);
+ llvm::Constant *BuildCopyHelper(const llvm::StructType *,
+ std::vector<HelperInfo> &);
+ llvm::Constant *BuildDestroyHelper(const llvm::StructType *,
+ std::vector<HelperInfo> &);
llvm::Constant *GeneratebyrefCopyHelperFunction(const llvm::Type *, int flag);
llvm::Constant *GeneratebyrefDestroyHelperFunction(const llvm::Type *T, int);
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index 70373031bb..9afe450c58 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -1326,8 +1326,7 @@ Value *ScalarExprEmitter::VisitVAArgExpr(VAArgExpr *VE) {
}
Value *ScalarExprEmitter::VisitBlockExpr(const BlockExpr *BE) {
- llvm::Value *V = CGF.BuildBlockLiteralTmp(BE);
- return V;
+ return CGF.BuildBlockLiteralTmp(BE);
}
//===----------------------------------------------------------------------===//
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index adeb4ebfd4..a54f9bd235 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -32,7 +32,6 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm)
// FIXME: We need to rearrange the code for copy/dispose so we have this
// sooner, so we can calculate offsets correctly.
- BlockHasCopyDispose = false;
if (!BlockHasCopyDispose)
BlockOffset = CGM.getTargetData()
.getTypeStoreSizeInBits(CGM.getGenericBlockLiteralType()) / 8;
diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h
index 2ac886d840..0b34d7a92d 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -266,7 +266,9 @@ public:
//===--------------------------------------------------------------------===//
llvm::Value *BuildBlockLiteralTmp(const BlockExpr *);
- llvm::Constant *BuildDescriptorBlockDecl(uint64_t Size, const llvm::Type *);
+ llvm::Constant *BuildDescriptorBlockDecl(uint64_t Size,
+ const llvm::StructType *,
+ std::vector<HelperInfo> *);
llvm::Function *GenerateBlockFunction(const BlockExpr *BExpr,
const BlockInfo& Info,
@@ -276,26 +278,6 @@ public:
llvm::Value *LoadBlockStruct();
- /// BlockHasCopyDispose - True iff the block uses copy/dispose.
- bool BlockHasCopyDispose;
-
- /// BlockDeclRefDecls - Decls from BlockDeclRefExprs in apperance order
- /// in a block literal. Decls without names are used for padding.
- llvm::SmallVector<const Expr *, 8> BlockDeclRefDecls;
-
- /// BlockOffset - The offset in bytes for the next allocation of an
- /// imported block variable.
- 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);
-
- /// BlockDecls - Offsets for all Decls in BlockDeclRefExprs.
- std::map<const Decl*, uint64_t> BlockDecls;
-
llvm::Value *GetAddrOfBlockDecl(const BlockDeclRefExpr *E);
const llvm::Type *BuildByRefType(QualType Ty, uint64_t Align);
diff --git a/test/CodeGen/blocks-1.c b/test/CodeGen/blocks-1.c
index b1f9d9bcdf..8b5de629e8 100644
--- a/test/CodeGen/blocks-1.c
+++ b/test/CodeGen/blocks-1.c
@@ -5,7 +5,7 @@
// RUN: grep "__Block_byref_id_object_copy_" %t | count 2 &&
// RUN: grep "__Block_byref_id_object_dispose_" %t | count 2 &&
// RUN: grep "i32 135)" %t | count 2 &&
-// RUN: grep "_Block_object_assign" %t | count 2
+// RUN: grep "_Block_object_assign" %t | count 6
#include <stdio.h>