diff options
-rw-r--r-- | include/clang/AST/ASTContext.h | 7 | ||||
-rw-r--r-- | lib/AST/ASTContext.cpp | 71 | ||||
-rw-r--r-- | lib/CodeGen/CGBlocks.cpp | 118 | ||||
-rw-r--r-- | lib/CodeGen/CGBlocks.h | 6 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 1 |
5 files changed, 119 insertions, 84 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 8507cd4175..3ab2a0b1ea 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -409,11 +409,10 @@ public: /// This gets the struct used to keep track of pointer to blocks, complete /// with captured variables. - QualType getBlockParmType(); + QualType getBlockParmType(llvm::SmallVector<const Expr *, 8> &BDRDs); - /// This completes a type created by getBlockParmType. - void completeBlockParmType(QualType Ty, - llvm::SmallVector<const Expr *, 8> &BlockDeclRefDecls); + /// This builds the struct used for __block variables. + QualType BuildByRefType(QualType Ty); /// getLValueReferenceType - Return the uniqued reference to the type for an /// lvalue reference to the specified type. diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 8855cba159..673229cd6b 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -2741,7 +2741,22 @@ void ASTContext::setBlockDescriptorType(QualType T) { BlockDescriptorType = Rec->getDecl(); } -QualType ASTContext::getBlockParmType() { +QualType ASTContext::BuildByRefType(QualType Ty) { + // type = struct __Block_byref_1_done { + // void *__isa; + // struct __Block_byref_1_done *__forwarding; + // unsigned int __flags; + // unsigned int __size; + // int done; + // } * + + // FIXME: Build up reference type. + return getPointerType(VoidPtrTy); +} + + +QualType ASTContext::getBlockParmType( + llvm::SmallVector<const Expr *, 8> &BlockDeclRefDecls) { // FIXME: Move up static int UniqueBlockParmTypeID = 0; char Name[36]; @@ -2749,30 +2764,6 @@ QualType ASTContext::getBlockParmType() { RecordDecl *T; T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(), &Idents.get(Name)); - -#define REV2 -#ifdef REV2 - cast<TagDecl>(T)->startDefinition(); -#endif - - return getPointerType(getTagDeclType(T)); -} - -void ASTContext::completeBlockParmType(QualType Ty, - llvm::SmallVector<const Expr *, 8> &BlockDeclRefDecls) { - RecordDecl *PT = Ty->getPointeeType()->getAs<RecordType>()->getDecl(); - llvm::StringRef Name = PT->getIdentifier()->getName(); - - RecordDecl *T; -#ifdef REV2 - T = PT; -#else - T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(), - &Idents.get(Name), SourceLocation(), PT); - - cast<TagDecl>(T)->startDefinition(); -#endif - QualType FieldTypes[] = { getPointerType(VoidPtrTy), IntTy, @@ -2790,19 +2781,35 @@ void ASTContext::completeBlockParmType(QualType Ty, }; for (size_t i = 0; i < 5; ++i) { - FieldDecl *Field = FieldDecl::Create(*this, - T, - SourceLocation(), + FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(), &Idents.get(FieldNames[i]), FieldTypes[i], /*DInfo=*/0, - /*BitWidth=*/0, - /*Mutable=*/false); - // FIXME: Do this instead or addDecl? - // PushOnScopeChains(FieldTypes, S); + /*BitWidth=*/0, /*Mutable=*/false); + T->addDecl(Field); + } + + for (size_t i = 0; i < BlockDeclRefDecls.size(); ++i) { + const Expr *E = BlockDeclRefDecls[i]; + const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E); + clang::IdentifierInfo *Name = 0; + if (BDRE) { + const ValueDecl *D = BDRE->getDecl(); + Name = &Idents.get(D->getName()); + } + QualType FieldType = E->getType(); + + if (BDRE && BDRE->isByRef()) + FieldType = BuildByRefType(FieldType); + + FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(), + Name, FieldType, /*DInfo=*/0, + /*BitWidth=*/0, /*Mutable=*/false); T->addDecl(Field); } T->completeDefinition(*this); + + return getPointerType(getTagDeclType(T)); } void ASTContext::setObjCFastEnumerationStateType(QualType T) { diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp index 8e020c80ea..692a7a6bc5 100644 --- a/lib/CodeGen/CGBlocks.cpp +++ b/lib/CodeGen/CGBlocks.cpp @@ -80,22 +80,48 @@ static void CollectBlockDeclRefInfo(const Stmt *S, if (*I) CollectBlockDeclRefInfo(*I, Info); + // We want to ensure we walk down into block literals so we can find + // all nested BlockDeclRefExprs. + if (const BlockExpr *BE = dyn_cast<BlockExpr>(S)) + CollectBlockDeclRefInfo(BE->getBody(), 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); + Info.DeclRefs.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(); + return Info.DeclRefs.empty(); +} + +/// AllocateAllBlockDeclRefs - Preallocate all nested BlockDeclRefExprs to +/// ensure we can generate the debug information for the parameter for the block +/// invoke function. +static void AllocateAllBlockDeclRefs(const CodeGenFunction::BlockInfo &Info, + CodeGenFunction *CGF) { + // Always allocate self, as it is often handy in the debugger, even if there + // is no codegen in the block that uses it. This is also useful to always do + // this as if we didn't, we'd have to figure out all code that uses a self + // pointer, including implicit uses. + if (const ObjCMethodDecl *OMD + = dyn_cast_or_null<ObjCMethodDecl>(CGF->CurFuncDecl)) { + ImplicitParamDecl *SelfDecl = OMD->getSelfDecl(); + BlockDeclRefExpr *BDRE = new (CGF->getContext()) + BlockDeclRefExpr(SelfDecl, + SelfDecl->getType(), SourceLocation(), false); + CGF->AllocateBlockDecl(BDRE); + } + + // FIXME: Also always forward the this pointer in C++ as well. + + for (size_t i = 0; i < Info.DeclRefs.size(); ++i) + CGF->AllocateBlockDecl(Info.DeclRefs[i]); } // FIXME: Push most into CGM, passing down a few bits, like current function @@ -159,7 +185,8 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { if (subBlockDeclRefDecls.size() == 0) { // __descriptor - Elts[4] = BuildDescriptorBlockDecl(subBlockHasCopyDispose, subBlockSize, 0, 0); + Elts[4] = BuildDescriptorBlockDecl(subBlockHasCopyDispose, subBlockSize, + 0, 0); // Optimize to being a global block. Elts[0] = CGM.getNSConcreteGlobalBlock(); @@ -269,7 +296,7 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) { llvm::Value *BlockLiteral = LoadBlockStruct(); Loc = Builder.CreateGEP(BlockLiteral, - llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), + llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), offset), "block.literal"); Ty = llvm::PointerType::get(Ty, 0); @@ -447,24 +474,32 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E) { return EmitCall(FnInfo, Func, Args); } -llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const BlockDeclRefExpr *E) { +uint64_t CodeGenFunction::AllocateBlockDecl(const BlockDeclRefExpr *E) { const ValueDecl *VD = E->getDecl(); - uint64_t &offset = BlockDecls[VD]; - // See if we have already allocated an offset for this variable. - if (offset == 0) { - // Don't run the expensive check, unless we have to. - if (!BlockHasCopyDispose && BlockRequiresCopying(E->getType())) - BlockHasCopyDispose = true; - // if not, allocate one now. - offset = getBlockOffset(E); - } + if (offset) + return offset; + + // Don't run the expensive check, unless we have to. + if (!BlockHasCopyDispose && BlockRequiresCopying(E->getType())) + BlockHasCopyDispose = true; + + // if not, allocate one now. + offset = getBlockOffset(E); + + return offset; +} + +llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const BlockDeclRefExpr *E) { + const ValueDecl *VD = E->getDecl(); + uint64_t offset = AllocateBlockDecl(E); + llvm::Value *BlockLiteral = LoadBlockStruct(); llvm::Value *V = Builder.CreateGEP(BlockLiteral, - llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), + llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), offset), "block.literal"); if (E->isByRef()) { @@ -633,12 +668,19 @@ CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr, FunctionArgList Args; + CurFuncDecl = OuterFuncDecl; + const BlockDecl *BD = BExpr->getBlockDecl(); - IdentifierInfo *II - = &CGM.getContext().Idents.get(".block_descriptor"); + IdentifierInfo *II = &CGM.getContext().Idents.get(".block_descriptor"); + + // Allocate all BlockDeclRefDecls, so we can calculate the the + // right ParmTy below. + // FIXME: Resolve testsuite problems, then enable. + if (0) + AllocateAllBlockDeclRefs(Info, this); - QualType ParmTy = getContext().getBlockParmType(); + QualType ParmTy = getContext().getBlockParmType(BlockDeclRefDecls); // FIXME: This leaks ImplicitParamDecl *SelfDecl = ImplicitParamDecl::Create(getContext(), 0, @@ -708,22 +750,6 @@ CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr, FinishFunction(cast<CompoundStmt>(BExpr->getBody())->getRBracLoc()); - // And now finish off the type for the parameter, since now we know - // BlockDeclRefDecls is complete. - getContext().completeBlockParmType(ParmTy, BlockDeclRefDecls); - -#define REV2 -#ifdef REV2 - TagDecl *TD = ParmTy->getPointeeType()->getAs<RecordType>()->getDecl(); - CGM.UpdateCompletedType(TD); -#else - TagDecl *TD = ParmTy->getPointeeType()->getAs<RecordType>()->getDecl(); - TagDecl::redecl_iterator rdi = TD->redecls_begin(); - ++rdi; - TD = *rdi; - CGM.UpdateCompletedType(TD); -#endif - // The runtime needs a minimum alignment of a void *. uint64_t MinAlign = getContext().getTypeAlign(getContext().VoidPtrTy) / 8; BlockOffset = llvm::RoundUpToAlignment(BlockOffset, MinAlign); @@ -781,11 +807,13 @@ GenerateCopyHelperFunction(bool BlockHasCopyDispose, const llvm::StructType *T, FunctionArgList Args; // FIXME: This leaks ImplicitParamDecl *Dst = - ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0, + 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, + ImplicitParamDecl::Create(getContext(), 0, + SourceLocation(), 0, getContext().getPointerType(getContext().VoidTy)); Args.push_back(std::make_pair(Src, Src->getType())); @@ -866,7 +894,8 @@ GenerateDestroyHelperFunction(bool BlockHasCopyDispose, FunctionArgList Args; // FIXME: This leaks ImplicitParamDecl *Src = - ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0, + ImplicitParamDecl::Create(getContext(), 0, + SourceLocation(), 0, getContext().getPointerType(getContext().VoidTy)); Args.push_back(std::make_pair(Src, Src->getType())); @@ -945,13 +974,15 @@ GeneratebyrefCopyHelperFunction(const llvm::Type *T, int flag) { FunctionArgList Args; // FIXME: This leaks ImplicitParamDecl *Dst = - ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0, + ImplicitParamDecl::Create(getContext(), 0, + SourceLocation(), 0, getContext().getPointerType(getContext().VoidTy)); Args.push_back(std::make_pair(Dst, Dst->getType())); // FIXME: This leaks ImplicitParamDecl *Src = - ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0, + ImplicitParamDecl::Create(getContext(), 0, + SourceLocation(), 0, getContext().getPointerType(getContext().VoidTy)); Args.push_back(std::make_pair(Src, Src->getType())); @@ -1014,7 +1045,8 @@ BlockFunction::GeneratebyrefDestroyHelperFunction(const llvm::Type *T, FunctionArgList Args; // FIXME: This leaks ImplicitParamDecl *Src = - ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0, + ImplicitParamDecl::Create(getContext(), 0, + SourceLocation(), 0, getContext().getPointerType(getContext().VoidTy)); Args.push_back(std::make_pair(Src, Src->getType())); diff --git a/lib/CodeGen/CGBlocks.h b/lib/CodeGen/CGBlocks.h index 3a860c0d3c..48807af209 100644 --- a/lib/CodeGen/CGBlocks.h +++ b/lib/CodeGen/CGBlocks.h @@ -165,11 +165,7 @@ public: /// 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; + llvm::SmallVector<const BlockDeclRefExpr *, 8> DeclRefs; BlockInfo(const llvm::Type *blt, const char *n) : BlockLiteralTy(blt), Name(n) { diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index a32a7eabad..00b07e4b68 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -356,6 +356,7 @@ public: void BlockForwardSelf(); llvm::Value *LoadBlockStruct(); + uint64_t AllocateBlockDecl(const BlockDeclRefExpr *E); llvm::Value *GetAddrOfBlockDecl(const BlockDeclRefExpr *E); const llvm::Type *BuildByRefType(const ValueDecl *D); |