summaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/CGBlocks.cpp
diff options
context:
space:
mode:
authorrdivacky <rdivacky@FreeBSD.org>2009-10-23 14:22:18 +0000
committerrdivacky <rdivacky@FreeBSD.org>2009-10-23 14:22:18 +0000
commit5563df30b9c8d1fe87a54baae0d6bd86642563f4 (patch)
tree3fdd91eae574e32453a4baf462961c742df2691a /lib/CodeGen/CGBlocks.cpp
parente5557c18e5d41b4b62f2af8a24af20eba40b0225 (diff)
downloadFreeBSD-src-5563df30b9c8d1fe87a54baae0d6bd86642563f4.zip
FreeBSD-src-5563df30b9c8d1fe87a54baae0d6bd86642563f4.tar.gz
Update clang to r84949.
Diffstat (limited to 'lib/CodeGen/CGBlocks.cpp')
-rw-r--r--lib/CodeGen/CGBlocks.cpp140
1 files changed, 96 insertions, 44 deletions
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp
index 736425e..682cf5d 100644
--- a/lib/CodeGen/CGBlocks.cpp
+++ b/lib/CodeGen/CGBlocks.cpp
@@ -73,29 +73,60 @@ llvm::Constant *BlockModule::getNSConcreteStackBlock() {
return NSConcreteStackBlock;
}
-static void CollectBlockDeclRefInfo(const Stmt *S,
- CodeGenFunction::BlockInfo &Info) {
+static void CollectBlockDeclRefInfo(
+ const Stmt *S, CodeGenFunction::BlockInfo &Info,
+ llvm::SmallSet<const DeclContext *, 16> &InnerContexts) {
for (Stmt::const_child_iterator I = S->child_begin(), E = S->child_end();
I != E; ++I)
if (*I)
- CollectBlockDeclRefInfo(*I, Info);
+ CollectBlockDeclRefInfo(*I, Info, InnerContexts);
- if (const BlockDeclRefExpr *DE = dyn_cast<BlockDeclRefExpr>(S)) {
+ // 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)) {
+ InnerContexts.insert(cast<DeclContext>(BE->getBlockDecl()));
+ CollectBlockDeclRefInfo(BE->getBody(), Info, InnerContexts);
+ }
+
+ if (const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(S)) {
// FIXME: Handle enums.
- if (isa<FunctionDecl>(DE->getDecl()))
+ if (isa<FunctionDecl>(BDRE->getDecl()))
return;
- if (DE->isByRef())
- Info.ByRefDeclRefs.push_back(DE);
- else
- Info.ByCopyDeclRefs.push_back(DE);
+ // Only Decls that escape are added.
+ if (!InnerContexts.count(BDRE->getDecl()->getDeclContext()))
+ Info.DeclRefs.push_back(BDRE);
}
}
/// 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
@@ -104,7 +135,9 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
std::string Name = CurFn->getName();
CodeGenFunction::BlockInfo Info(0, Name.c_str());
- CollectBlockDeclRefInfo(BE->getBody(), Info);
+ llvm::SmallSet<const DeclContext *, 16> InnerContexts;
+ InnerContexts.insert(BE->getBlockDecl());
+ CollectBlockDeclRefInfo(BE->getBody(), Info, InnerContexts);
// Check if the block can be global.
// FIXME: This test doesn't work for nested blocks yet. Longer term, I'd like
@@ -159,7 +192,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 +303,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);
@@ -391,10 +425,6 @@ const llvm::Type *BlockModule::getGenericExtendedBlockLiteralType() {
return GenericExtendedBlockLiteralType;
}
-bool BlockFunction::BlockRequiresCopying(QualType Ty) {
- return CGM.BlockRequiresCopying(Ty);
-}
-
RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E) {
const BlockPointerType *BPT =
E->getCallee()->getType()->getAs<BlockPointerType>();
@@ -447,24 +477,34 @@ 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()))
+ if (offset)
+ return offset;
+
+ // Don't run the expensive check, unless we have to.
+ if (!BlockHasCopyDispose)
+ if (E->isByRef()
+ || BlockRequiresCopying(E->getType()))
BlockHasCopyDispose = true;
- // if not, allocate one now.
- offset = getBlockOffset(E);
- }
+
+ // 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()) {
@@ -576,7 +616,10 @@ BlockModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) {
}
llvm::Value *CodeGenFunction::LoadBlockStruct() {
- return Builder.CreateLoad(LocalDeclMap[getBlockStructDecl()], "self");
+ llvm::Value *V = Builder.CreateLoad(LocalDeclMap[getBlockStructDecl()],
+ "self");
+ // For now, we codegen based upon byte offsets.
+ return Builder.CreateBitCast(V, PtrToInt8Ty);
}
llvm::Function *
@@ -605,14 +648,8 @@ CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr,
LocalDeclMap[VD] = i->second;
}
- // FIXME: We need to rearrange the code for copy/dispose so we have this
- // sooner, so we can calculate offsets correctly.
- if (!BlockHasCopyDispose)
- BlockOffset = CGM.getTargetData()
- .getTypeStoreSizeInBits(CGM.getGenericBlockLiteralType()) / 8;
- else
- BlockOffset = CGM.getTargetData()
- .getTypeStoreSizeInBits(CGM.getGenericExtendedBlockLiteralType()) / 8;
+ BlockOffset = CGM.getTargetData()
+ .getTypeStoreSizeInBits(CGM.getGenericBlockLiteralType()) / 8;
BlockAlign = getContext().getTypeAlign(getContext().VoidPtrTy) / 8;
const FunctionType *BlockFunctionType = BExpr->getFunctionType();
@@ -630,13 +667,22 @@ CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr,
FunctionArgList Args;
+ CurFuncDecl = OuterFuncDecl;
+
const BlockDecl *BD = BExpr->getBlockDecl();
+ IdentifierInfo *II = &CGM.getContext().Idents.get(".block_descriptor");
+
+ // Allocate all BlockDeclRefDecls, so we can calculate the right ParmTy below.
+ AllocateAllBlockDeclRefs(Info, this);
+
+ QualType ParmTy = getContext().getBlockParmType(BlockHasCopyDispose,
+ BlockDeclRefDecls);
// FIXME: This leaks
ImplicitParamDecl *SelfDecl =
ImplicitParamDecl::Create(getContext(), 0,
- SourceLocation(), 0,
- getContext().getPointerType(getContext().VoidTy));
+ SourceLocation(), II,
+ ParmTy);
Args.push_back(std::make_pair(SelfDecl, SelfDecl->getType()));
BlockStructDecl = SelfDecl;
@@ -758,11 +804,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()));
@@ -843,7 +891,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()));
@@ -922,13 +971,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()));
@@ -991,7 +1042,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()));
OpenPOWER on IntegriCloud