зеркало из https://github.com/microsoft/clang.git
Allocate space in a block record for implicit references to the Objective C
'self' variable arising from uses of the 'super' keyword. Also reorganize some code so that BlockInfo (now CGBlockInfo) can be opaque outside of CGBlocks.cpp. Fixes rdar://problem/8010633. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@104312 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
a9976d3b19
Коммит
ee5042903d
|
@ -24,6 +24,45 @@
|
||||||
using namespace clang;
|
using namespace clang;
|
||||||
using namespace CodeGen;
|
using namespace CodeGen;
|
||||||
|
|
||||||
|
/// CGBlockInfo - Information to generate a block literal.
|
||||||
|
class clang::CodeGen::CGBlockInfo {
|
||||||
|
public:
|
||||||
|
/// Name - The name of the block, kindof.
|
||||||
|
const char *Name;
|
||||||
|
|
||||||
|
/// DeclRefs - Variables from parent scopes that have been
|
||||||
|
/// imported into this block.
|
||||||
|
llvm::SmallVector<const BlockDeclRefExpr *, 8> DeclRefs;
|
||||||
|
|
||||||
|
/// InnerBlocks - This block and the blocks it encloses.
|
||||||
|
llvm::SmallPtrSet<const DeclContext *, 4> InnerBlocks;
|
||||||
|
|
||||||
|
/// CXXThisRef - Non-null if 'this' was required somewhere, in
|
||||||
|
/// which case this is that expression.
|
||||||
|
const CXXThisExpr *CXXThisRef;
|
||||||
|
|
||||||
|
/// NeedsObjCSelf - True if something in this block has an implicit
|
||||||
|
/// reference to 'self'.
|
||||||
|
bool NeedsObjCSelf;
|
||||||
|
|
||||||
|
/// These are initialized by GenerateBlockFunction.
|
||||||
|
bool BlockHasCopyDispose;
|
||||||
|
CharUnits BlockSize;
|
||||||
|
CharUnits BlockAlign;
|
||||||
|
llvm::SmallVector<const Expr*, 8> BlockLayout;
|
||||||
|
|
||||||
|
CGBlockInfo(const char *Name);
|
||||||
|
};
|
||||||
|
|
||||||
|
CGBlockInfo::CGBlockInfo(const char *N)
|
||||||
|
: Name(N), CXXThisRef(0), NeedsObjCSelf(false) {
|
||||||
|
|
||||||
|
// Skip asm prefix, if any.
|
||||||
|
if (Name && Name[0] == '\01')
|
||||||
|
++Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
llvm::Constant *CodeGenFunction::
|
llvm::Constant *CodeGenFunction::
|
||||||
BuildDescriptorBlockDecl(const BlockExpr *BE, bool BlockHasCopyDispose, CharUnits Size,
|
BuildDescriptorBlockDecl(const BlockExpr *BE, bool BlockHasCopyDispose, CharUnits Size,
|
||||||
const llvm::StructType* Ty,
|
const llvm::StructType* Ty,
|
||||||
|
@ -86,62 +125,85 @@ llvm::Constant *BlockModule::getNSConcreteStackBlock() {
|
||||||
return NSConcreteStackBlock;
|
return NSConcreteStackBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CollectBlockDeclRefInfo(
|
static void CollectBlockDeclRefInfo(const Stmt *S, CGBlockInfo &Info) {
|
||||||
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();
|
for (Stmt::const_child_iterator I = S->child_begin(), E = S->child_end();
|
||||||
I != E; ++I)
|
I != E; ++I)
|
||||||
if (*I)
|
if (*I)
|
||||||
CollectBlockDeclRefInfo(*I, Info, InnerContexts);
|
CollectBlockDeclRefInfo(*I, Info);
|
||||||
|
|
||||||
// We want to ensure we walk down into block literals so we can find
|
// We want to ensure we walk down into block literals so we can find
|
||||||
// all nested BlockDeclRefExprs.
|
// all nested BlockDeclRefExprs.
|
||||||
if (const BlockExpr *BE = dyn_cast<BlockExpr>(S)) {
|
if (const BlockExpr *BE = dyn_cast<BlockExpr>(S)) {
|
||||||
InnerContexts.insert(cast<DeclContext>(BE->getBlockDecl()));
|
Info.InnerBlocks.insert(BE->getBlockDecl());
|
||||||
CollectBlockDeclRefInfo(BE->getBody(), Info, InnerContexts);
|
CollectBlockDeclRefInfo(BE->getBody(), Info);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(S)) {
|
else if (const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(S)) {
|
||||||
|
const ValueDecl *D = BDRE->getDecl();
|
||||||
// FIXME: Handle enums.
|
// FIXME: Handle enums.
|
||||||
if (isa<FunctionDecl>(BDRE->getDecl()))
|
if (isa<FunctionDecl>(D))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (isa<ImplicitParamDecl>(D) &&
|
||||||
|
isa<ObjCMethodDecl>(D->getDeclContext()) &&
|
||||||
|
cast<ObjCMethodDecl>(D->getDeclContext())->getSelfDecl() == D) {
|
||||||
|
Info.NeedsObjCSelf = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Only Decls that escape are added.
|
// Only Decls that escape are added.
|
||||||
if (!InnerContexts.count(BDRE->getDecl()->getDeclContext()))
|
if (!Info.InnerBlocks.count(D->getDeclContext()))
|
||||||
Info.DeclRefs.push_back(BDRE);
|
Info.DeclRefs.push_back(BDRE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isa<CXXThisExpr>(S))
|
// Make sure to capture implicit 'self' references due to super calls.
|
||||||
|
else if (const ObjCMessageExpr *E = dyn_cast<ObjCMessageExpr>(S))
|
||||||
|
if (E->getReceiverKind() == ObjCMessageExpr::SuperClass ||
|
||||||
|
E->getReceiverKind() == ObjCMessageExpr::SuperInstance)
|
||||||
|
Info.NeedsObjCSelf = true;
|
||||||
|
|
||||||
|
// Getter/setter uses may also cause implicit super references,
|
||||||
|
// which we can check for with:
|
||||||
|
else if (isa<ObjCSuperExpr>(S))
|
||||||
|
Info.NeedsObjCSelf = true;
|
||||||
|
|
||||||
|
else if (isa<CXXThisExpr>(S))
|
||||||
Info.CXXThisRef = cast<CXXThisExpr>(S);
|
Info.CXXThisRef = cast<CXXThisExpr>(S);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// CanBlockBeGlobal - Given a BlockInfo struct, determines if a block can be
|
/// CanBlockBeGlobal - Given a CGBlockInfo struct, determines if a block can be
|
||||||
/// declared as a global variable instead of on the stack.
|
/// declared as a global variable instead of on the stack.
|
||||||
static bool CanBlockBeGlobal(const CodeGenFunction::BlockInfo &Info) {
|
static bool CanBlockBeGlobal(const CGBlockInfo &Info) {
|
||||||
return Info.DeclRefs.empty();
|
return Info.DeclRefs.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// AllocateAllBlockDeclRefs - Preallocate all nested BlockDeclRefExprs to
|
/// AllocateAllBlockDeclRefs - Preallocate all nested BlockDeclRefExprs to
|
||||||
/// ensure we can generate the debug information for the parameter for the block
|
/// ensure we can generate the debug information for the parameter for the block
|
||||||
/// invoke function.
|
/// invoke function.
|
||||||
static void AllocateAllBlockDeclRefs(const CodeGenFunction::BlockInfo &Info,
|
static void AllocateAllBlockDeclRefs(CodeGenFunction &CGF, CGBlockInfo &Info) {
|
||||||
CodeGenFunction *CGF) {
|
|
||||||
if (Info.CXXThisRef)
|
if (Info.CXXThisRef)
|
||||||
CGF->AllocateBlockCXXThisPointer(Info.CXXThisRef);
|
CGF.AllocateBlockCXXThisPointer(Info.CXXThisRef);
|
||||||
|
|
||||||
for (size_t i = 0; i < Info.DeclRefs.size(); ++i)
|
for (size_t i = 0; i < Info.DeclRefs.size(); ++i)
|
||||||
CGF->AllocateBlockDecl(Info.DeclRefs[i]);
|
CGF.AllocateBlockDecl(Info.DeclRefs[i]);
|
||||||
|
|
||||||
|
if (Info.NeedsObjCSelf) {
|
||||||
|
ValueDecl *Self = cast<ObjCMethodDecl>(CGF.CurFuncDecl)->getSelfDecl();
|
||||||
|
BlockDeclRefExpr *BDRE =
|
||||||
|
new (CGF.getContext()) BlockDeclRefExpr(Self, Self->getType(),
|
||||||
|
SourceLocation(), false);
|
||||||
|
Info.DeclRefs.push_back(BDRE);
|
||||||
|
CGF.AllocateBlockDecl(BDRE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Push most into CGM, passing down a few bits, like current function
|
// FIXME: Push most into CGM, passing down a few bits, like current function
|
||||||
// name.
|
// name.
|
||||||
llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
|
llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
|
||||||
|
|
||||||
std::string Name = CurFn->getName();
|
std::string Name = CurFn->getName();
|
||||||
CodeGenFunction::BlockInfo Info(0, Name.c_str());
|
CGBlockInfo Info(Name.c_str());
|
||||||
llvm::SmallSet<const DeclContext *, 16> InnerContexts;
|
Info.InnerBlocks.insert(BE->getBlockDecl());
|
||||||
InnerContexts.insert(BE->getBlockDecl());
|
CollectBlockDeclRefInfo(BE->getBody(), Info);
|
||||||
CollectBlockDeclRefInfo(BE->getBody(), Info, InnerContexts);
|
|
||||||
|
|
||||||
// Check if the block can be global.
|
// Check if the block can be global.
|
||||||
// FIXME: This test doesn't work for nested blocks yet. Longer term, I'd like
|
// FIXME: This test doesn't work for nested blocks yet. Longer term, I'd like
|
||||||
|
@ -164,23 +226,15 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
|
||||||
// We run this first so that we set BlockHasCopyDispose from the entire
|
// We run this first so that we set BlockHasCopyDispose from the entire
|
||||||
// block literal.
|
// block literal.
|
||||||
// __invoke
|
// __invoke
|
||||||
CharUnits subBlockSize;
|
|
||||||
CharUnits subBlockAlign;
|
|
||||||
llvm::SmallVector<const Expr *, 8> subBlockLayout;
|
|
||||||
bool subBlockHasCopyDispose = false;
|
|
||||||
llvm::Function *Fn
|
llvm::Function *Fn
|
||||||
= CodeGenFunction(CGM).GenerateBlockFunction(BE, Info, CurFuncDecl,
|
= CodeGenFunction(CGM).GenerateBlockFunction(BE, Info, CurFuncDecl,
|
||||||
LocalDeclMap,
|
LocalDeclMap);
|
||||||
subBlockSize,
|
BlockHasCopyDispose |= Info.BlockHasCopyDispose;
|
||||||
subBlockAlign,
|
|
||||||
subBlockLayout,
|
|
||||||
subBlockHasCopyDispose);
|
|
||||||
BlockHasCopyDispose |= subBlockHasCopyDispose;
|
|
||||||
Elts[3] = Fn;
|
Elts[3] = Fn;
|
||||||
|
|
||||||
// FIXME: Don't use BlockHasCopyDispose, it is set more often then
|
// FIXME: Don't use BlockHasCopyDispose, it is set more often then
|
||||||
// necessary, for example: { ^{ __block int i; ^{ i = 1; }(); }(); }
|
// necessary, for example: { ^{ __block int i; ^{ i = 1; }(); }(); }
|
||||||
if (subBlockHasCopyDispose)
|
if (Info.BlockHasCopyDispose)
|
||||||
flags |= BLOCK_HAS_COPY_DISPOSE;
|
flags |= BLOCK_HAS_COPY_DISPOSE;
|
||||||
|
|
||||||
// __isa
|
// __isa
|
||||||
|
@ -210,10 +264,10 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
|
||||||
C = llvm::ConstantInt::get(IntTy, 0);
|
C = llvm::ConstantInt::get(IntTy, 0);
|
||||||
Elts[2] = C;
|
Elts[2] = C;
|
||||||
|
|
||||||
if (subBlockLayout.empty()) {
|
if (Info.BlockLayout.empty()) {
|
||||||
// __descriptor
|
// __descriptor
|
||||||
Elts[4] = BuildDescriptorBlockDecl(BE, subBlockHasCopyDispose, subBlockSize,
|
Elts[4] = BuildDescriptorBlockDecl(BE, Info.BlockHasCopyDispose,
|
||||||
0, 0);
|
Info.BlockSize, 0, 0);
|
||||||
|
|
||||||
// Optimize to being a global block.
|
// Optimize to being a global block.
|
||||||
Elts[0] = CGM.getNSConcreteGlobalBlock();
|
Elts[0] = CGM.getNSConcreteGlobalBlock();
|
||||||
|
@ -231,13 +285,13 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
|
||||||
return C;
|
return C;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<const llvm::Type *> Types(BlockFields+subBlockLayout.size());
|
std::vector<const llvm::Type *> Types(BlockFields+Info.BlockLayout.size());
|
||||||
for (int i=0; i<4; ++i)
|
for (int i=0; i<4; ++i)
|
||||||
Types[i] = Elts[i]->getType();
|
Types[i] = Elts[i]->getType();
|
||||||
Types[4] = PtrToInt8Ty;
|
Types[4] = PtrToInt8Ty;
|
||||||
|
|
||||||
for (unsigned i = 0, n = subBlockLayout.size(); i != n; ++i) {
|
for (unsigned i = 0, n = Info.BlockLayout.size(); i != n; ++i) {
|
||||||
const Expr *E = subBlockLayout[i];
|
const Expr *E = Info.BlockLayout[i];
|
||||||
const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E);
|
const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E);
|
||||||
QualType Ty = E->getType();
|
QualType Ty = E->getType();
|
||||||
if (BDRE && BDRE->isByRef()) {
|
if (BDRE && BDRE->isByRef()) {
|
||||||
|
@ -249,19 +303,19 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
|
||||||
llvm::StructType *Ty = llvm::StructType::get(VMContext, Types, true);
|
llvm::StructType *Ty = llvm::StructType::get(VMContext, Types, true);
|
||||||
|
|
||||||
llvm::AllocaInst *A = CreateTempAlloca(Ty);
|
llvm::AllocaInst *A = CreateTempAlloca(Ty);
|
||||||
A->setAlignment(subBlockAlign.getQuantity());
|
A->setAlignment(Info.BlockAlign.getQuantity());
|
||||||
V = A;
|
V = A;
|
||||||
|
|
||||||
// Build layout / cleanup information for all the data entries in the
|
// Build layout / cleanup information for all the data entries in the
|
||||||
// layout, and write the enclosing fields into the type.
|
// layout, and write the enclosing fields into the type.
|
||||||
std::vector<HelperInfo> NoteForHelper(subBlockLayout.size());
|
std::vector<HelperInfo> NoteForHelper(Info.BlockLayout.size());
|
||||||
unsigned NumHelpers = 0;
|
unsigned NumHelpers = 0;
|
||||||
|
|
||||||
for (unsigned i=0; i<4; ++i)
|
for (unsigned i=0; i<4; ++i)
|
||||||
Builder.CreateStore(Elts[i], Builder.CreateStructGEP(V, i, "block.tmp"));
|
Builder.CreateStore(Elts[i], Builder.CreateStructGEP(V, i, "block.tmp"));
|
||||||
|
|
||||||
for (unsigned i=0; i < subBlockLayout.size(); ++i) {
|
for (unsigned i=0; i < Info.BlockLayout.size(); ++i) {
|
||||||
const Expr *E = subBlockLayout[i];
|
const Expr *E = Info.BlockLayout[i];
|
||||||
|
|
||||||
// Skip padding.
|
// Skip padding.
|
||||||
if (isa<DeclRefExpr>(E)) continue;
|
if (isa<DeclRefExpr>(E)) continue;
|
||||||
|
@ -354,8 +408,8 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
|
||||||
|
|
||||||
// __descriptor
|
// __descriptor
|
||||||
llvm::Value *Descriptor = BuildDescriptorBlockDecl(BE,
|
llvm::Value *Descriptor = BuildDescriptorBlockDecl(BE,
|
||||||
subBlockHasCopyDispose,
|
Info.BlockHasCopyDispose,
|
||||||
subBlockSize, Ty,
|
Info.BlockSize, Ty,
|
||||||
&NoteForHelper);
|
&NoteForHelper);
|
||||||
Descriptor = Builder.CreateBitCast(Descriptor, PtrToInt8Ty);
|
Descriptor = Builder.CreateBitCast(Descriptor, PtrToInt8Ty);
|
||||||
Builder.CreateStore(Descriptor, Builder.CreateStructGEP(V, 4, "block.tmp"));
|
Builder.CreateStore(Descriptor, Builder.CreateStructGEP(V, 4, "block.tmp"));
|
||||||
|
@ -542,8 +596,8 @@ void CodeGenFunction::AllocateBlockDecl(const BlockDeclRefExpr *E) {
|
||||||
BlockLayout.push_back(E);
|
BlockLayout.push_back(E);
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const BlockDeclRefExpr *E) {
|
llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const ValueDecl *VD,
|
||||||
const ValueDecl *VD = E->getDecl();
|
bool IsByRef) {
|
||||||
CharUnits offset = BlockDecls[VD];
|
CharUnits offset = BlockDecls[VD];
|
||||||
assert(!offset.isZero() && "getting address of unallocated decl");
|
assert(!offset.isZero() && "getting address of unallocated decl");
|
||||||
|
|
||||||
|
@ -552,7 +606,7 @@ llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const BlockDeclRefExpr *E) {
|
||||||
llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
|
llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),
|
||||||
offset.getQuantity()),
|
offset.getQuantity()),
|
||||||
"block.literal");
|
"block.literal");
|
||||||
if (E->isByRef()) {
|
if (IsByRef) {
|
||||||
const llvm::Type *PtrStructTy
|
const llvm::Type *PtrStructTy
|
||||||
= llvm::PointerType::get(BuildByRefType(VD), 0);
|
= llvm::PointerType::get(BuildByRefType(VD), 0);
|
||||||
// The block literal will need a copy/destroy helper.
|
// The block literal will need a copy/destroy helper.
|
||||||
|
@ -578,19 +632,6 @@ llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const BlockDeclRefExpr *E) {
|
||||||
return V;
|
return V;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeGenFunction::BlockForwardSelf() {
|
|
||||||
const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl);
|
|
||||||
ImplicitParamDecl *SelfDecl = OMD->getSelfDecl();
|
|
||||||
llvm::Value *&DMEntry = LocalDeclMap[SelfDecl];
|
|
||||||
if (DMEntry)
|
|
||||||
return;
|
|
||||||
// FIXME - Eliminate BlockDeclRefExprs, clients don't need/want to care
|
|
||||||
BlockDeclRefExpr *BDRE = new (getContext())
|
|
||||||
BlockDeclRefExpr(SelfDecl,
|
|
||||||
SelfDecl->getType(), SourceLocation(), false);
|
|
||||||
DMEntry = GetAddrOfBlockDecl(BDRE);
|
|
||||||
}
|
|
||||||
|
|
||||||
llvm::Constant *
|
llvm::Constant *
|
||||||
BlockModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) {
|
BlockModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) {
|
||||||
// Generate the block descriptor.
|
// Generate the block descriptor.
|
||||||
|
@ -635,19 +676,11 @@ BlockModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) {
|
||||||
|
|
||||||
std::vector<llvm::Constant*> LiteralFields(FieldCount);
|
std::vector<llvm::Constant*> LiteralFields(FieldCount);
|
||||||
|
|
||||||
CodeGenFunction::BlockInfo Info(0, n);
|
CGBlockInfo Info(n);
|
||||||
CharUnits subBlockSize;
|
|
||||||
CharUnits subBlockAlign;
|
|
||||||
llvm::SmallVector<const Expr *, 8> subBlockLayout;
|
|
||||||
bool subBlockHasCopyDispose = false;
|
|
||||||
llvm::DenseMap<const Decl*, llvm::Value*> LocalDeclMap;
|
llvm::DenseMap<const Decl*, llvm::Value*> LocalDeclMap;
|
||||||
llvm::Function *Fn
|
llvm::Function *Fn
|
||||||
= CodeGenFunction(CGM).GenerateBlockFunction(BE, Info, 0, LocalDeclMap,
|
= CodeGenFunction(CGM).GenerateBlockFunction(BE, Info, 0, LocalDeclMap);
|
||||||
subBlockSize,
|
assert(Info.BlockSize == BlockLiteralSize
|
||||||
subBlockAlign,
|
|
||||||
subBlockLayout,
|
|
||||||
subBlockHasCopyDispose);
|
|
||||||
assert(subBlockSize == BlockLiteralSize
|
|
||||||
&& "no imports allowed for global block");
|
&& "no imports allowed for global block");
|
||||||
|
|
||||||
// isa
|
// isa
|
||||||
|
@ -686,13 +719,9 @@ llvm::Value *CodeGenFunction::LoadBlockStruct() {
|
||||||
|
|
||||||
llvm::Function *
|
llvm::Function *
|
||||||
CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr,
|
CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr,
|
||||||
const BlockInfo& Info,
|
CGBlockInfo &Info,
|
||||||
const Decl *OuterFuncDecl,
|
const Decl *OuterFuncDecl,
|
||||||
llvm::DenseMap<const Decl*, llvm::Value*> ldm,
|
llvm::DenseMap<const Decl*, llvm::Value*> ldm) {
|
||||||
CharUnits &Size,
|
|
||||||
CharUnits &Align,
|
|
||||||
llvm::SmallVectorImpl<const Expr *> &subBlockLayout,
|
|
||||||
bool &subBlockHasCopyDispose) {
|
|
||||||
|
|
||||||
// Check if we should generate debug info for this block.
|
// Check if we should generate debug info for this block.
|
||||||
if (CGM.getDebugInfo())
|
if (CGM.getDebugInfo())
|
||||||
|
@ -737,7 +766,7 @@ CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr,
|
||||||
IdentifierInfo *II = &CGM.getContext().Idents.get(".block_descriptor");
|
IdentifierInfo *II = &CGM.getContext().Idents.get(".block_descriptor");
|
||||||
|
|
||||||
// Build the block struct now.
|
// Build the block struct now.
|
||||||
AllocateAllBlockDeclRefs(Info, this);
|
AllocateAllBlockDeclRefs(*this, Info);
|
||||||
|
|
||||||
QualType ParmTy = getContext().getBlockParmType(BlockHasCopyDispose,
|
QualType ParmTy = getContext().getBlockParmType(BlockHasCopyDispose,
|
||||||
BlockLayout);
|
BlockLayout);
|
||||||
|
@ -795,6 +824,13 @@ CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr,
|
||||||
CXXThisValue = Builder.CreateLoad(ThisPtr, "this");
|
CXXThisValue = Builder.CreateLoad(ThisPtr, "this");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we have an Objective C 'self' reference, go ahead and force it
|
||||||
|
// into existence now.
|
||||||
|
if (Info.NeedsObjCSelf) {
|
||||||
|
ValueDecl *Self = cast<ObjCMethodDecl>(CurFuncDecl)->getSelfDecl();
|
||||||
|
LocalDeclMap[Self] = GetAddrOfBlockDecl(Self, false);
|
||||||
|
}
|
||||||
|
|
||||||
// Save a spot to insert the debug information for all the BlockDeclRefDecls.
|
// Save a spot to insert the debug information for all the BlockDeclRefDecls.
|
||||||
llvm::BasicBlock *entry = Builder.GetInsertBlock();
|
llvm::BasicBlock *entry = Builder.GetInsertBlock();
|
||||||
llvm::BasicBlock::iterator entry_ptr = Builder.GetInsertPoint();
|
llvm::BasicBlock::iterator entry_ptr = Builder.GetInsertPoint();
|
||||||
|
@ -837,10 +873,10 @@ CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr,
|
||||||
llvm::RoundUpToAlignment(BlockOffset.getQuantity(),
|
llvm::RoundUpToAlignment(BlockOffset.getQuantity(),
|
||||||
MinAlign.getQuantity()));
|
MinAlign.getQuantity()));
|
||||||
|
|
||||||
Size = BlockOffset;
|
Info.BlockSize = BlockOffset;
|
||||||
Align = BlockAlign;
|
Info.BlockAlign = BlockAlign;
|
||||||
subBlockLayout = BlockLayout;
|
Info.BlockLayout = BlockLayout;
|
||||||
subBlockHasCopyDispose |= BlockHasCopyDispose;
|
Info.BlockHasCopyDispose = BlockHasCopyDispose;
|
||||||
return Fn;
|
return Fn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -148,30 +148,6 @@ public:
|
||||||
BLOCK_BYREF_CURRENT_MAX = 256
|
BLOCK_BYREF_CURRENT_MAX = 256
|
||||||
};
|
};
|
||||||
|
|
||||||
/// BlockInfo - Information to generate a block literal.
|
|
||||||
struct BlockInfo {
|
|
||||||
/// BlockLiteralTy - The type of the block literal.
|
|
||||||
const llvm::Type *BlockLiteralTy;
|
|
||||||
|
|
||||||
/// Name - the name of the function this block was created for, if any.
|
|
||||||
const char *Name;
|
|
||||||
|
|
||||||
/// ByCopyDeclRefs - Variables from parent scopes that have been imported
|
|
||||||
/// into this block.
|
|
||||||
llvm::SmallVector<const BlockDeclRefExpr *, 8> DeclRefs;
|
|
||||||
|
|
||||||
/// CXXThisRef - An expression referring to the required 'this'
|
|
||||||
/// expression.
|
|
||||||
const CXXThisExpr *CXXThisRef;
|
|
||||||
|
|
||||||
BlockInfo(const llvm::Type *blt, const char *n)
|
|
||||||
: BlockLiteralTy(blt), Name(n), CXXThisRef(0) {
|
|
||||||
// Skip asm prefix, if any.
|
|
||||||
if (Name && Name[0] == '\01')
|
|
||||||
++Name;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
CGBuilderTy &Builder;
|
CGBuilderTy &Builder;
|
||||||
|
|
||||||
BlockFunction(CodeGenModule &cgm, CodeGenFunction &cgf, CGBuilderTy &B);
|
BlockFunction(CodeGenModule &cgm, CodeGenFunction &cgf, CGBuilderTy &B);
|
||||||
|
|
|
@ -494,8 +494,6 @@ bool CodeGenFunction::IvarTypeWithAggrGCObjects(QualType Ty) {
|
||||||
|
|
||||||
llvm::Value *CodeGenFunction::LoadObjCSelf() {
|
llvm::Value *CodeGenFunction::LoadObjCSelf() {
|
||||||
const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl);
|
const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl);
|
||||||
// See if we need to lazily forward self inside a block literal.
|
|
||||||
BlockForwardSelf();
|
|
||||||
return Builder.CreateLoad(LocalDeclMap[OMD->getSelfDecl()], "self");
|
return Builder.CreateLoad(LocalDeclMap[OMD->getSelfDecl()], "self");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -67,6 +67,7 @@ namespace CodeGen {
|
||||||
class CGDebugInfo;
|
class CGDebugInfo;
|
||||||
class CGFunctionInfo;
|
class CGFunctionInfo;
|
||||||
class CGRecordLayout;
|
class CGRecordLayout;
|
||||||
|
class CGBlockInfo;
|
||||||
|
|
||||||
/// CodeGenFunction - This class organizes the per-function state that is used
|
/// CodeGenFunction - This class organizes the per-function state that is used
|
||||||
/// while generating LLVM code.
|
/// while generating LLVM code.
|
||||||
|
@ -501,19 +502,18 @@ public:
|
||||||
std::vector<HelperInfo> *);
|
std::vector<HelperInfo> *);
|
||||||
|
|
||||||
llvm::Function *GenerateBlockFunction(const BlockExpr *BExpr,
|
llvm::Function *GenerateBlockFunction(const BlockExpr *BExpr,
|
||||||
const BlockInfo& Info,
|
CGBlockInfo &Info,
|
||||||
const Decl *OuterFuncDecl,
|
const Decl *OuterFuncDecl,
|
||||||
llvm::DenseMap<const Decl*, llvm::Value*> ldm,
|
llvm::DenseMap<const Decl*, llvm::Value*> ldm);
|
||||||
CharUnits &Size, CharUnits &Align,
|
|
||||||
llvm::SmallVectorImpl<const Expr*> &subBlockDeclRefDecls,
|
|
||||||
bool &subBlockHasCopyDispose);
|
|
||||||
|
|
||||||
void BlockForwardSelf();
|
|
||||||
llvm::Value *LoadBlockStruct();
|
llvm::Value *LoadBlockStruct();
|
||||||
|
|
||||||
void AllocateBlockCXXThisPointer(const CXXThisExpr *E);
|
void AllocateBlockCXXThisPointer(const CXXThisExpr *E);
|
||||||
void AllocateBlockDecl(const BlockDeclRefExpr *E);
|
void AllocateBlockDecl(const BlockDeclRefExpr *E);
|
||||||
llvm::Value *GetAddrOfBlockDecl(const BlockDeclRefExpr *E);
|
llvm::Value *GetAddrOfBlockDecl(const BlockDeclRefExpr *E) {
|
||||||
|
return GetAddrOfBlockDecl(E->getDecl(), E->isByRef());
|
||||||
|
}
|
||||||
|
llvm::Value *GetAddrOfBlockDecl(const ValueDecl *D, bool ByRef);
|
||||||
const llvm::Type *BuildByRefType(const ValueDecl *D);
|
const llvm::Type *BuildByRefType(const ValueDecl *D);
|
||||||
|
|
||||||
void GenerateCode(GlobalDecl GD, llvm::Function *Fn);
|
void GenerateCode(GlobalDecl GD, llvm::Function *Fn);
|
||||||
|
|
|
@ -31,5 +31,11 @@ void foo(T *P) {
|
||||||
-(void) im1 {
|
-(void) im1 {
|
||||||
^(void) { [self im0]; }();
|
^(void) { [self im0]; }();
|
||||||
}
|
}
|
||||||
|
-(void) im2 {
|
||||||
|
^{ [super im0]; }();
|
||||||
|
}
|
||||||
|
-(void) im3 {
|
||||||
|
^{ ^{[super im0];}(); }();
|
||||||
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче