IR Gen. part of API support for __block cxx

objects imported into blocks. //rdar://8594790.
Will have a test case coming (as well as one
sent to llvm test suite).

llvm-svn: 120713
This commit is contained in:
Fariborz Jahanian 2010-12-02 17:02:11 +00:00
parent 1596c4531b
commit 50198098b9
9 changed files with 83 additions and 78 deletions

View File

@ -130,7 +130,7 @@ class ASTContext {
llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*> ObjCImpls;
/// \brief Mapping from __block VarDecls to their copy initialization expr.
llvm::DenseMap<VarDecl*, Expr*> BlockVarCopyInits;
llvm::DenseMap<const VarDecl*, Expr*> BlockVarCopyInits;
/// \brief Representation of a "canonical" template template parameter that
/// is used in canonical template names.
@ -1366,7 +1366,7 @@ public:
void setBlockVarCopyInits(VarDecl*VD, Expr* Init);
/// \brief Get the copy initialization expression of VarDecl,or NULL if
/// none exists.
Expr *getBlockVarCopyInits(VarDecl*VD);
Expr *getBlockVarCopyInits(const VarDecl*VD);
/// \brief Allocate an uninitialized TypeSourceInfo.
///

View File

@ -1010,8 +1010,8 @@ void ASTContext::setObjCImplementation(ObjCCategoryDecl *CatD,
/// \brief Get the copy initialization expression of VarDecl,or NULL if
/// none exists.
Expr *ASTContext::getBlockVarCopyInits(VarDecl*VD) {
llvm::DenseMap<VarDecl*, Expr*>::iterator
Expr *ASTContext::getBlockVarCopyInits(const VarDecl*VD) {
llvm::DenseMap<const VarDecl*, Expr*>::iterator
I = BlockVarCopyInits.find(VD);
return (I != BlockVarCopyInits.end()) ? cast<Expr>(I->second) : 0;
}

View File

@ -1000,29 +1000,16 @@ GenerateCopyHelperFunction(const llvm::StructType *T,
llvm::Value *Srcv = SrcObj;
Srcv = Builder.CreateStructGEP(Srcv, index);
llvm::Value *Dstv;
if (NoteForHelper[i].cxxvar_import) {
if (NoteForHelper[i].flag & BLOCK_FIELD_IS_BYREF) {
const ValueDecl *VD = NoteForHelper[i].cxxvar_import->getDecl();
const llvm::Type *PtrStructTy
= llvm::PointerType::get(CGF.BuildByRefType(VD), 0);
Srcv = Builder.CreateLoad(Srcv);
Srcv = Builder.CreateBitCast(Srcv, PtrStructTy);
Srcv = Builder.CreateStructGEP(Srcv, CGF.getByRefValueLLVMField(VD),
VD->getNameAsString());
Dstv = Builder.CreateBitCast(DstObj, PtrStructTy);
Dstv = Builder.CreateStructGEP(Dstv, CGF.getByRefValueLLVMField(VD),
VD->getNameAsString());
CGF.EmitSynthesizedCXXCopyCtor(Dstv, Srcv,
NoteForHelper[i].cxxvar_import);
}
else {
Srcv = Builder.CreateBitCast(Srcv,
llvm::PointerType::get(PtrToInt8Ty, 0));
Dstv = Builder.CreateStructGEP(DstObj, index);
CGF.EmitSynthesizedCXXCopyCtor(Dstv, Srcv,
NoteForHelper[i].cxxvar_import);
}
if (NoteForHelper[i].cxxvar_import &&
(NoteForHelper[i].flag & BLOCK_FIELD_IS_BYREF) == 0) {
// Note that cxx objects declared as __block require a
// different API. They are copy constructed in their own copy
// helper functions (see GeneratebyrefCopyHelperFunction).
Srcv = Builder.CreateBitCast(Srcv,
llvm::PointerType::get(PtrToInt8Ty, 0));
Dstv = Builder.CreateStructGEP(DstObj, index);
CGF.EmitSynthesizedCXXCopyCtor(Dstv, Srcv,
NoteForHelper[i].cxxvar_import->getCopyConstructorExpr());
}
else {
Srcv = Builder.CreateBitCast(Srcv,
@ -1099,23 +1086,13 @@ GenerateDestroyHelperFunction(const llvm::StructType* T,
Srcv = Builder.CreateStructGEP(Srcv, index);
Srcv = Builder.CreateBitCast(Srcv,
llvm::PointerType::get(PtrToInt8Ty, 0));
if (NoteForHelper[i].cxxvar_import) {
if (NoteForHelper[i].cxxvar_import &&
(NoteForHelper[i].flag & BLOCK_FIELD_IS_BYREF) == 0) {
const BlockDeclRefExpr *BDRE = NoteForHelper[i].cxxvar_import;
const Expr *E = BDRE->getCopyConstructorExpr();
QualType ClassTy = E->getType();
QualType PtrClassTy = getContext().getPointerType(ClassTy);
const llvm::Type *t = CGM.getTypes().ConvertType(PtrClassTy);
if (NoteForHelper[i].flag & BLOCK_FIELD_IS_BYREF) {
const ValueDecl *VD = NoteForHelper[i].cxxvar_import->getDecl();
const llvm::Type *PtrStructTy
= llvm::PointerType::get(CGF.BuildByRefType(VD), 0);
Srcv = Builder.CreateLoad(Srcv);
Srcv = Builder.CreateBitCast(Srcv, PtrStructTy);
Srcv = Builder.CreateStructGEP(Srcv, CGF.getByRefValueLLVMField(VD),
VD->getNameAsString());
}
Srcv = Builder.CreateBitCast(Srcv, t);
CGF.PushDestructorCleanup(ClassTy, Srcv);
}
@ -1144,7 +1121,8 @@ llvm::Constant *BlockFunction::BuildDestroyHelper(const llvm::StructType *T,
}
llvm::Constant *BlockFunction::
GeneratebyrefCopyHelperFunction(const llvm::Type *T, int flag) {
GeneratebyrefCopyHelperFunction(const llvm::Type *T, int flag,
const VarDecl *BD) {
QualType R = getContext().VoidTy;
FunctionArgList Args;
@ -1172,10 +1150,10 @@ GeneratebyrefCopyHelperFunction(const llvm::Type *T, int flag) {
// internal linkage.
llvm::Function *Fn =
llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
"__Block_byref_id_object_copy_", &CGM.getModule());
"__Block_byref_object_copy_", &CGM.getModule());
IdentifierInfo *II
= &CGM.getContext().Idents.get("__Block_byref_id_object_copy_");
= &CGM.getContext().Idents.get("__Block_byref_object_copy_");
FunctionDecl *FD = FunctionDecl::Create(getContext(),
getContext().getTranslationUnitDecl(),
@ -1190,22 +1168,30 @@ GeneratebyrefCopyHelperFunction(const llvm::Type *T, int flag) {
V = Builder.CreateBitCast(V, llvm::PointerType::get(T, 0));
V = Builder.CreateLoad(V);
V = Builder.CreateStructGEP(V, 6, "x");
llvm::Value *DstObj = Builder.CreateBitCast(V, PtrToInt8Ty);
llvm::Value *DstObj = V;
// src->x
V = CGF.GetAddrOfLocalVar(Src);
V = Builder.CreateLoad(V);
V = Builder.CreateBitCast(V, T);
V = Builder.CreateStructGEP(V, 6, "x");
V = Builder.CreateBitCast(V, llvm::PointerType::get(PtrToInt8Ty, 0));
llvm::Value *SrcObj = Builder.CreateLoad(V);
flag |= BLOCK_BYREF_CALLER;
llvm::Value *N = llvm::ConstantInt::get(CGF.Int32Ty, flag);
llvm::Value *F = CGM.getBlockObjectAssign();
Builder.CreateCall3(F, DstObj, SrcObj, N);
if (flag & BLOCK_HAS_CXX_OBJ) {
assert (BD && "VarDecl is null - GeneratebyrefCopyHelperFunction");
llvm::Value *SrcObj = V;
CGF.EmitSynthesizedCXXCopyCtor(DstObj, SrcObj,
getContext().getBlockVarCopyInits(BD));
}
else {
DstObj = Builder.CreateBitCast(DstObj, PtrToInt8Ty);
V = Builder.CreateBitCast(V, llvm::PointerType::get(PtrToInt8Ty, 0));
llvm::Value *SrcObj = Builder.CreateLoad(V);
flag |= BLOCK_BYREF_CALLER;
llvm::Value *N = llvm::ConstantInt::get(CGF.Int32Ty, flag);
llvm::Value *F = CGM.getBlockObjectAssign();
Builder.CreateCall3(F, DstObj, SrcObj, N);
}
CGF.FinishFunction();
return llvm::ConstantExpr::getBitCast(Fn, PtrToInt8Ty);
@ -1213,7 +1199,8 @@ GeneratebyrefCopyHelperFunction(const llvm::Type *T, int flag) {
llvm::Constant *
BlockFunction::GeneratebyrefDestroyHelperFunction(const llvm::Type *T,
int flag) {
int flag,
const VarDecl *BD) {
QualType R = getContext().VoidTy;
FunctionArgList Args;
@ -1235,11 +1222,11 @@ BlockFunction::GeneratebyrefDestroyHelperFunction(const llvm::Type *T,
// internal linkage.
llvm::Function *Fn =
llvm::Function::Create(LTy, llvm::GlobalValue::InternalLinkage,
"__Block_byref_id_object_dispose_",
"__Block_byref_object_dispose_",
&CGM.getModule());
IdentifierInfo *II
= &CGM.getContext().Idents.get("__Block_byref_id_object_dispose_");
= &CGM.getContext().Idents.get("__Block_byref_object_dispose_");
FunctionDecl *FD = FunctionDecl::Create(getContext(),
getContext().getTranslationUnitDecl(),
@ -1253,18 +1240,28 @@ BlockFunction::GeneratebyrefDestroyHelperFunction(const llvm::Type *T,
V = Builder.CreateBitCast(V, llvm::PointerType::get(T, 0));
V = Builder.CreateLoad(V);
V = Builder.CreateStructGEP(V, 6, "x");
V = Builder.CreateBitCast(V, llvm::PointerType::get(PtrToInt8Ty, 0));
V = Builder.CreateLoad(V);
if (flag & BLOCK_HAS_CXX_OBJ) {
EHScopeStack::stable_iterator CleanupDepth = CGF.EHStack.stable_begin();
assert (BD && "VarDecl is null - GeneratebyrefDestroyHelperFunction");
QualType ClassTy = BD->getType();
CGF.PushDestructorCleanup(ClassTy, V);
CGF.PopCleanupBlocks(CleanupDepth);
}
else {
V = Builder.CreateBitCast(V, llvm::PointerType::get(PtrToInt8Ty, 0));
V = Builder.CreateLoad(V);
flag |= BLOCK_BYREF_CALLER;
BuildBlockRelease(V, flag);
flag |= BLOCK_BYREF_CALLER;
BuildBlockRelease(V, flag);
}
CGF.FinishFunction();
return llvm::ConstantExpr::getBitCast(Fn, PtrToInt8Ty);
}
llvm::Constant *BlockFunction::BuildbyrefCopyHelper(const llvm::Type *T,
int Flag, unsigned Align) {
int Flag, unsigned Align,
const VarDecl *BD) {
// All alignments below that of pointer alignment collapse down to just
// pointer alignment, as we always have at least that much alignment to begin
// with.
@ -1277,12 +1274,14 @@ llvm::Constant *BlockFunction::BuildbyrefCopyHelper(const llvm::Type *T,
llvm::Constant *&Entry = CGM.AssignCache[Kind];
if (Entry)
return Entry;
return Entry = CodeGenFunction(CGM).GeneratebyrefCopyHelperFunction(T, Flag);
return Entry =
CodeGenFunction(CGM).GeneratebyrefCopyHelperFunction(T, Flag, BD);
}
llvm::Constant *BlockFunction::BuildbyrefDestroyHelper(const llvm::Type *T,
int Flag,
unsigned Align) {
unsigned Align,
const VarDecl *BD) {
// All alignments below that of pointer alignment collpase down to just
// pointer alignment, as we always have at least that much alignment to begin
// with.
@ -1295,7 +1294,8 @@ llvm::Constant *BlockFunction::BuildbyrefDestroyHelper(const llvm::Type *T,
llvm::Constant *&Entry = CGM.DestroyCache[Kind];
if (Entry)
return Entry;
return Entry=CodeGenFunction(CGM).GeneratebyrefDestroyHelperFunction(T, Flag);
return Entry =
CodeGenFunction(CGM).GeneratebyrefDestroyHelperFunction(T, Flag, BD);
}
void BlockFunction::BuildBlockRelease(llvm::Value *V, int flag) {

View File

@ -189,13 +189,16 @@ public:
llvm::Constant *BuildDestroyHelper(const llvm::StructType *,
std::vector<HelperInfo> *);
llvm::Constant *GeneratebyrefCopyHelperFunction(const llvm::Type *, int flag);
llvm::Constant *GeneratebyrefDestroyHelperFunction(const llvm::Type *T, int);
llvm::Constant *GeneratebyrefCopyHelperFunction(const llvm::Type *, int flag,
const VarDecl *BD);
llvm::Constant *GeneratebyrefDestroyHelperFunction(const llvm::Type *T,
int flag,
const VarDecl *BD);
llvm::Constant *BuildbyrefCopyHelper(const llvm::Type *T, int flag,
unsigned Align);
unsigned Align, const VarDecl *BD);
llvm::Constant *BuildbyrefDestroyHelper(const llvm::Type *T, int flag,
unsigned Align);
unsigned Align, const VarDecl *BD);
void BuildBlockRelease(llvm::Value *DeclPtr, int flag = BLOCK_FIELD_IS_BYREF);

View File

@ -756,6 +756,9 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D,
Ty->isObjCObjectPointerType()) {
flag |= BLOCK_FIELD_IS_OBJECT;
flags |= BLOCK_HAS_COPY_DISPOSE;
} else if (getContext().getBlockVarCopyInits(&D)) {
flag |= BLOCK_HAS_CXX_OBJ;
flags |= BLOCK_HAS_COPY_DISPOSE;
}
// FIXME: Someone double check this.
@ -781,12 +784,12 @@ void CodeGenFunction::EmitAutoVarDecl(const VarDecl &D,
SynthesizeCopyDisposeHelpers = true;
llvm::Value *copy_helper = Builder.CreateStructGEP(DeclPtr, 4);
Builder.CreateStore(BuildbyrefCopyHelper(DeclPtr->getType(), flag,
Align.getQuantity()),
Align.getQuantity(), &D),
copy_helper);
llvm::Value *destroy_helper = Builder.CreateStructGEP(DeclPtr, 5);
Builder.CreateStore(BuildbyrefDestroyHelper(DeclPtr->getType(), flag,
Align.getQuantity()),
Align.getQuantity(), &D),
destroy_helper);
}
}

View File

@ -344,8 +344,7 @@ CodeGenFunction::EmitCXXConstructExpr(const CXXConstructExpr *E,
void
CodeGenFunction::EmitSynthesizedCXXCopyCtor(llvm::Value *Dest,
llvm::Value *Src,
const BlockDeclRefExpr *BDRE) {
const Expr *Exp = BDRE->getCopyConstructorExpr();
const Expr *Exp) {
if (const CXXExprWithTemporaries *E = dyn_cast<CXXExprWithTemporaries>(Exp))
Exp = E->getSubExpr();
assert(isa<CXXConstructExpr>(Exp) &&

View File

@ -1659,7 +1659,7 @@ public:
void EmitCXXConstructExpr(const CXXConstructExpr *E, AggValueSlot Dest);
void EmitSynthesizedCXXCopyCtor(llvm::Value *Dest, llvm::Value *Src,
const BlockDeclRefExpr *BDRE);
const Expr *Exp);
RValue EmitCXXExprWithTemporaries(const CXXExprWithTemporaries *E,
AggValueSlot Slot =AggValueSlot::ignored());

View File

@ -2,8 +2,8 @@
// RUN: grep "_Block_object_dispose" %t | count 17
// RUN: grep "__copy_helper_block_" %t | count 16
// RUN: grep "__destroy_helper_block_" %t | count 16
// RUN: grep "__Block_byref_id_object_copy_" %t | count 2
// RUN: grep "__Block_byref_id_object_dispose_" %t | count 2
// RUN: grep "__Block_byref_object_copy_" %t | count 2
// RUN: grep "__Block_byref_object_dispose_" %t | count 2
// RUN: grep "i32 135)" %t | count 2
// RUN: grep "_Block_object_assign" %t | count 10

View File

@ -2,8 +2,8 @@
// RUN: grep "_Block_object_dispose" %t | count 6
// RUN: grep "__copy_helper_block_" %t | count 4
// RUN: grep "__destroy_helper_block_" %t | count 4
// RUN: grep "__Block_byref_id_object_copy_" %t | count 2
// RUN: grep "__Block_byref_id_object_dispose_" %t | count 2
// RUN: grep "__Block_byref_object_copy_" %t | count 2
// RUN: grep "__Block_byref_object_dispose_" %t | count 2
// RUN: grep "i32 135)" %t | count 0
// RUN: grep "_Block_object_assign" %t | count 4
// RUN: grep "objc_read_weak" %t | count 2
@ -12,8 +12,8 @@
// RUN: grep "_Block_object_dispose" %t | count 6
// RUN: grep "__copy_helper_block_" %t | count 4
// RUN: grep "__destroy_helper_block_" %t | count 4
// RUN: grep "__Block_byref_id_object_copy_" %t | count 2
// RUN: grep "__Block_byref_id_object_dispose_" %t | count 2
// RUN: grep "__Block_byref_object_copy_" %t | count 2
// RUN: grep "__Block_byref_object_dispose_" %t | count 2
// RUN: grep "i32 135)" %t | count 0
// RUN: grep "_Block_object_assign" %t | count 4
// RUN: grep "objc_read_weak" %t | count 2