Prep work to always preallocate BlockDeclRefExprs so that we can
generate the debug information for the first parameter to the block
invoke functions. WIP.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@84737 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index 8507cd4..3ab2a0b 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -409,11 +409,10 @@
/// 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 8855cba..673229c 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -2741,7 +2741,22 @@
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 @@
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 @@
};
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 8e020c8..692a7a6 100644
--- a/lib/CodeGen/CGBlocks.cpp
+++ b/lib/CodeGen/CGBlocks.cpp
@@ -80,22 +80,48 @@
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 @@
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 *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 @@
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 @@
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");
- QualType ParmTy = getContext().getBlockParmType();
+ // 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(BlockDeclRefDecls);
// FIXME: This leaks
ImplicitParamDecl *SelfDecl =
ImplicitParamDecl::Create(getContext(), 0,
@@ -708,22 +750,6 @@
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 @@
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 @@
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 @@
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 @@
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 3a860c0..48807af 100644
--- a/lib/CodeGen/CGBlocks.h
+++ b/lib/CodeGen/CGBlocks.h
@@ -165,11 +165,7 @@
/// 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 a32a7ea..00b07e4 100644
--- a/lib/CodeGen/CodeGenFunction.h
+++ b/lib/CodeGen/CodeGenFunction.h
@@ -356,6 +356,7 @@
void BlockForwardSelf();
llvm::Value *LoadBlockStruct();
+ uint64_t AllocateBlockDecl(const BlockDeclRefExpr *E);
llvm::Value *GetAddrOfBlockDecl(const BlockDeclRefExpr *E);
const llvm::Type *BuildByRefType(const ValueDecl *D);