aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Stump <mrs@apple.com>2009-03-06 01:33:24 +0000
committerMike Stump <mrs@apple.com>2009-03-06 01:33:24 +0000
commita4f668f3b7e03629066a01b04e415cb2b4655daf (patch)
treee22535785d1ecd2de960f56386df0fae16c12543
parentb67db99d58c0a09a5a0ec336be5854451df6df8c (diff)
Framework for codegen for copy/dispose helpers.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66231 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/CodeGen/CGBlocks.cpp96
-rw-r--r--lib/CodeGen/CGBlocks.h12
-rw-r--r--lib/CodeGen/CGDecl.cpp4
-rw-r--r--lib/CodeGen/CodeGenFunction.cpp3
-rw-r--r--test/CodeGen/blocks-1.c10
5 files changed, 103 insertions, 22 deletions
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp
index 82ac86aaa3..a792537ea9 100644
--- a/lib/CodeGen/CGBlocks.cpp
+++ b/lib/CodeGen/CGBlocks.cpp
@@ -465,13 +465,13 @@ llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const BlockDeclRefExpr *E) {
// FIXME: add support for copy/dispose helpers.
if (!Enable__block && E->isByRef())
ErrorUnsupported(E, "__block variable in block literal");
- else if (E->getType()->isBlockPointerType())
+ else if (!Enable__block && E->getType()->isBlockPointerType())
ErrorUnsupported(E, "block pointer in block literal");
else if (E->getDecl()->getAttr<ObjCNSObjectAttr>() ||
getContext().isObjCNSObjectType(E->getType()))
ErrorUnsupported(E, "__attribute__((NSObject)) variable in block "
"literal");
- else if (getContext().isObjCObjectPointerType(E->getType()))
+ else if (!Enable__block && getContext().isObjCObjectPointerType(E->getType()))
ErrorUnsupported(E, "Objective-C variable in block literal");
// See if we have already allocated an offset for this variable.
@@ -677,20 +677,88 @@ uint64_t CodeGenFunction::getBlockOffset(const BlockDeclRefExpr *BDRE) {
return BlockOffset-Size;
}
-llvm::Value *BlockFunction::BuildCopyHelper(int flag) {
- // FIXME: implement
- llvm::Value *V = llvm::ConstantInt::get(llvm::Type::Int32Ty, 43);
- V = Builder.CreateIntToPtr(V, PtrToInt8Ty, "tmp");
- V = Builder.CreateBitCast(V, PtrToInt8Ty, "tmp");
- return V;
+llvm::Constant *BlockFunction::GenerateCopyHelperFunction() {
+ QualType R = getContext().VoidTy;
+
+ FunctionArgList Args;
+ // FIXME: This leaks
+ ImplicitParamDecl *Src =
+ ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
+ getContext().getPointerType(getContext().VoidTy));
+
+ Args.push_back(std::make_pair(Src, Src->getType()));
+
+ const CGFunctionInfo &FI =
+ CGM.getTypes().getFunctionInfo(R, Args);
+
+ std::string Name = std::string("__copy_helper_block_");
+ CodeGenTypes &Types = CGM.getTypes();
+ const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false);
+
+ llvm::Function *Fn =
+ llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
+ Name,
+ &CGM.getModule());
+
+ IdentifierInfo *II
+ = &CGM.getContext().Idents.get("__copy_helper_block_");
+
+ FunctionDecl *FD = FunctionDecl::Create(getContext(),
+ getContext().getTranslationUnitDecl(),
+ SourceLocation(), II, R,
+ FunctionDecl::Static, false,
+ true);
+ CGF.StartFunction(FD, R, Fn, Args, SourceLocation());
+ // EmitStmt(BExpr->getBody());
+ CGF.FinishFunction();
+
+ return llvm::ConstantExpr::getBitCast(Fn, PtrToInt8Ty);
}
-llvm::Value *BlockFunction::BuildDestroyHelper(int flag) {
- // FIXME: implement
- llvm::Value *V = llvm::ConstantInt::get(llvm::Type::Int32Ty, 44);
- V = Builder.CreateIntToPtr(V, PtrToInt8Ty, "tmp");
- V = Builder.CreateBitCast(V, PtrToInt8Ty, "tmp");
- return V;
+llvm::Constant *BlockFunction::GenerateDestroyHelperFunction() {
+ QualType R = getContext().VoidTy;
+
+ FunctionArgList Args;
+ // FIXME: This leaks
+ ImplicitParamDecl *Src =
+ ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0,
+ getContext().getPointerType(getContext().VoidTy));
+
+ Args.push_back(std::make_pair(Src, Src->getType()));
+
+ const CGFunctionInfo &FI =
+ CGM.getTypes().getFunctionInfo(R, Args);
+
+ std::string Name = std::string("__destroy_helper_block_");
+ CodeGenTypes &Types = CGM.getTypes();
+ const llvm::FunctionType *LTy = Types.GetFunctionType(FI, false);
+
+ llvm::Function *Fn =
+ llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
+ Name,
+ &CGM.getModule());
+
+ IdentifierInfo *II
+ = &CGM.getContext().Idents.get("__destroy_helper_block_");
+
+ FunctionDecl *FD = FunctionDecl::Create(getContext(),
+ getContext().getTranslationUnitDecl(),
+ SourceLocation(), II, R,
+ FunctionDecl::Static, false,
+ true);
+ CGF.StartFunction(FD, R, Fn, Args, SourceLocation());
+ // EmitStmt(BExpr->getBody());
+ CGF.FinishFunction();
+
+ return llvm::ConstantExpr::getBitCast(Fn, PtrToInt8Ty);
+}
+
+llvm::Constant *BlockFunction::BuildCopyHelper(int flag) {
+ return CodeGenFunction(CGM).GenerateCopyHelperFunction();
+}
+
+llvm::Constant *BlockFunction::BuildDestroyHelper(int flag) {
+ return CodeGenFunction(CGM).GenerateDestroyHelperFunction();
}
llvm::Value *BlockFunction::getBlockObjectDispose() {
diff --git a/lib/CodeGen/CGBlocks.h b/lib/CodeGen/CGBlocks.h
index 24b0cc9e5b..84ad190d6f 100644
--- a/lib/CodeGen/CGBlocks.h
+++ b/lib/CodeGen/CGBlocks.h
@@ -110,6 +110,7 @@ public:
class BlockFunction : public BlockBase {
CodeGenModule &CGM;
+ CodeGenFunction &CGF;
ASTContext &getContext() const;
public:
@@ -148,16 +149,19 @@ public:
CGBuilderTy &Builder;
- BlockFunction(CodeGenModule &cgm, CGBuilderTy &B)
- : CGM(cgm), Builder(B) {
+ BlockFunction(CodeGenModule &cgm, CodeGenFunction &cgf, CGBuilderTy &B)
+ : CGM(cgm), CGF(cgf), Builder(B) {
PtrToInt8Ty = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
}
ImplicitParamDecl *BlockStructDecl;
ImplicitParamDecl *getBlockStructDecl() { return BlockStructDecl; }
- llvm::Value *BuildCopyHelper(int flag);
- llvm::Value *BuildDestroyHelper(int flag);
+ llvm::Constant *GenerateCopyHelperFunction();
+ llvm::Constant *GenerateDestroyHelperFunction();
+
+ llvm::Constant *BuildCopyHelper(int flag);
+ llvm::Constant *BuildDestroyHelper(int flag);
llvm::Value *getBlockObjectDispose();
void BuildBlockRelease(const VarDecl &D, llvm::Value *DeclPtr);
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index e750d8a8d5..2b995d150c 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -354,10 +354,10 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
if (flag&BLOCK_FIELD_IS_WEAK)
isa = 1;
V = llvm::ConstantInt::get(llvm::Type::Int32Ty, isa);
- V = Builder.CreateIntToPtr(V, PtrToInt8Ty, "tmp");
+ V = Builder.CreateIntToPtr(V, PtrToInt8Ty, "isa");
Builder.CreateStore(V, isa_field);
- V = Builder.CreateBitCast(DeclPtr, PtrToInt8Ty, "tmp");
+ V = Builder.CreateBitCast(DeclPtr, PtrToInt8Ty, "forwarding");
Builder.CreateStore(V, forwarding_field);
V = llvm::ConstantInt::get(llvm::Type::Int32Ty, flags);
diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp
index b8e01029f7..adeb4ebfd4 100644
--- a/lib/CodeGen/CodeGenFunction.cpp
+++ b/lib/CodeGen/CodeGenFunction.cpp
@@ -24,7 +24,8 @@ using namespace clang;
using namespace CodeGen;
CodeGenFunction::CodeGenFunction(CodeGenModule &cgm)
- : BlockFunction(cgm, Builder), CGM(cgm), Target(CGM.getContext().Target),
+ : BlockFunction(cgm, *this, Builder), CGM(cgm),
+ Target(CGM.getContext().Target),
DebugInfo(0), SwitchInsn(0), CaseRangeBlock(0), InvokeDest(0) {
LLVMIntTy = ConvertType(getContext().IntTy);
LLVMPointerWidth = Target.getPointerWidth(0);
diff --git a/test/CodeGen/blocks-1.c b/test/CodeGen/blocks-1.c
index c397185e88..4a602e27d3 100644
--- a/test/CodeGen/blocks-1.c
+++ b/test/CodeGen/blocks-1.c
@@ -1,5 +1,7 @@
// RUN: clang %s -emit-llvm -o %t -fblocks -f__block &&
-// RUN: grep "_Block_object_dispose" %t | count 3
+// RUN: grep "_Block_object_dispose" %t | count 4
+// RUN: grep "__copy_helper_block_" %t | count 2
+// RUN: grep "__destroy_helper_block_" %t | count 2
#include <stdio.h>
void test1() {
@@ -28,8 +30,14 @@ void test2() {
printf("a is %d\n", a);
}
+void test3() {
+ __block int (^j)(int);
+ ^{j=0;}();
+}
+
int main() {
test1();
test2();
+ test3();
return 0;
}