aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Stump <mrs@apple.com>2009-10-21 03:49:08 +0000
committerMike Stump <mrs@apple.com>2009-10-21 03:49:08 +0000
commitea26cb522e88fc86b0d1cae61dcefcfe4cc20231 (patch)
treea9afb8e3511ba7a61e2caf474ebe54b26c51f7bc
parent3c50bfe3d9d4bda4183a541d97ec5b32bbae7aab (diff)
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
-rw-r--r--include/clang/AST/ASTContext.h7
-rw-r--r--lib/AST/ASTContext.cpp71
-rw-r--r--lib/CodeGen/CGBlocks.cpp118
-rw-r--r--lib/CodeGen/CGBlocks.h6
-rw-r--r--lib/CodeGen/CodeGenFunction.h1
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);