forked from OSchip/llvm-project
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:
parent
1596c4531b
commit
50198098b9
|
@ -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.
|
||||
///
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) &&
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue