]> granicus.if.org Git - clang/commitdiff
Framework for codegen for copy/dispose helpers.
authorMike Stump <mrs@apple.com>
Fri, 6 Mar 2009 01:33:24 +0000 (01:33 +0000)
committerMike Stump <mrs@apple.com>
Fri, 6 Mar 2009 01:33:24 +0000 (01:33 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66231 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGBlocks.cpp
lib/CodeGen/CGBlocks.h
lib/CodeGen/CGDecl.cpp
lib/CodeGen/CodeGenFunction.cpp
test/CodeGen/blocks-1.c

index 82ac86aaa359e11bf0fa18e7b247550f97fa176b..a792537ea9feb22895e188812c342e74092de997 100644 (file)
@@ -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() {
index 24b0cc9e5b5673c017d064938405810313b3e6b4..84ad190d6ff8e3ab69e2d2a476bd0ed6611a6e94 100644 (file)
@@ -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);
index e750d8a8d5ba2eb22c8f72bbc859621268874d4e..2b995d150cb33f28aa510eac1c8c014034ca5c38 100644 (file)
@@ -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);
index b8e01029f7160e11cca4029519b8b096fbe62936..adeb4ebfd4a60aa5f995f5b36c835518a914b195 100644 (file)
@@ -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);
index c397185e8802c22c60c9884e164acf8108037be9..4a602e27d3cdebc8860bccc9105a00264018ca21 100644 (file)
@@ -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;
 }