зеркало из https://github.com/microsoft/clang.git
Add codegen support for __block variables to call _Block_object_dispose as necessary.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66117 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
7833ed2a6e
Коммит
797b632757
|
@ -34,8 +34,6 @@ Enable__block("f__block",
|
|||
|
||||
|
||||
llvm::Constant *CodeGenFunction::BuildDescriptorBlockDecl(uint64_t Size) {
|
||||
const llvm::PointerType *PtrToInt8Ty
|
||||
= llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
|
||||
const llvm::Type *UnsignedLongTy
|
||||
= CGM.getTypes().ConvertType(getContext().UnsignedLongTy);
|
||||
llvm::Constant *C;
|
||||
|
@ -78,8 +76,6 @@ llvm::Constant *BlockModule::getNSConcreteGlobalBlock() {
|
|||
if (NSConcreteGlobalBlock)
|
||||
return NSConcreteGlobalBlock;
|
||||
|
||||
const llvm::PointerType *PtrToInt8Ty
|
||||
= llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
|
||||
// FIXME: We should have a CodeGenModule::AddRuntimeVariable that does the
|
||||
// same thing as CreateRuntimeFunction if there's already a variable with the
|
||||
// same name.
|
||||
|
@ -96,8 +92,6 @@ llvm::Constant *BlockModule::getNSConcreteStackBlock() {
|
|||
if (NSConcreteStackBlock)
|
||||
return NSConcreteStackBlock;
|
||||
|
||||
const llvm::PointerType *PtrToInt8Ty
|
||||
= llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
|
||||
// FIXME: We should have a CodeGenModule::AddRuntimeVariable that does the
|
||||
// same thing as CreateRuntimeFunction if there's already a variable with the
|
||||
// same name.
|
||||
|
@ -164,8 +158,6 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {
|
|||
|
||||
// __isa
|
||||
C = CGM.getNSConcreteStackBlock();
|
||||
const llvm::PointerType *PtrToInt8Ty
|
||||
= llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
|
||||
C = llvm::ConstantExpr::getBitCast(C, PtrToInt8Ty);
|
||||
Elts.push_back(C);
|
||||
|
||||
|
@ -335,9 +327,6 @@ const llvm::Type *BlockModule::getGenericBlockLiteralType() {
|
|||
if (GenericBlockLiteralType)
|
||||
return GenericBlockLiteralType;
|
||||
|
||||
const llvm::Type *Int8PtrTy =
|
||||
llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
|
||||
|
||||
const llvm::Type *BlockDescPtrTy =
|
||||
llvm::PointerType::getUnqual(getBlockDescriptorType());
|
||||
|
||||
|
@ -351,10 +340,10 @@ const llvm::Type *BlockModule::getGenericBlockLiteralType() {
|
|||
// void (*__invoke)(void *);
|
||||
// struct __block_descriptor *__descriptor;
|
||||
// };
|
||||
GenericBlockLiteralType = llvm::StructType::get(Int8PtrTy,
|
||||
GenericBlockLiteralType = llvm::StructType::get(PtrToInt8Ty,
|
||||
IntTy,
|
||||
IntTy,
|
||||
Int8PtrTy,
|
||||
PtrToInt8Ty,
|
||||
BlockDescPtrTy,
|
||||
NULL);
|
||||
|
||||
|
@ -368,9 +357,6 @@ const llvm::Type *BlockModule::getGenericExtendedBlockLiteralType() {
|
|||
if (GenericExtendedBlockLiteralType)
|
||||
return GenericExtendedBlockLiteralType;
|
||||
|
||||
const llvm::Type *Int8PtrTy =
|
||||
llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
|
||||
|
||||
const llvm::Type *BlockDescPtrTy =
|
||||
llvm::PointerType::getUnqual(getBlockDescriptorType());
|
||||
|
||||
|
@ -386,13 +372,13 @@ const llvm::Type *BlockModule::getGenericExtendedBlockLiteralType() {
|
|||
// void *__copy_func_helper_decl;
|
||||
// void *__destroy_func_decl;
|
||||
// };
|
||||
GenericExtendedBlockLiteralType = llvm::StructType::get(Int8PtrTy,
|
||||
GenericExtendedBlockLiteralType = llvm::StructType::get(PtrToInt8Ty,
|
||||
IntTy,
|
||||
IntTy,
|
||||
Int8PtrTy,
|
||||
PtrToInt8Ty,
|
||||
BlockDescPtrTy,
|
||||
Int8PtrTy,
|
||||
Int8PtrTy,
|
||||
PtrToInt8Ty,
|
||||
PtrToInt8Ty,
|
||||
NULL);
|
||||
|
||||
getModule().addTypeName("struct.__block_literal_extended_generic",
|
||||
|
@ -678,8 +664,6 @@ uint64_t CodeGenFunction::getBlockOffset(const BlockDeclRefExpr *BDRE) {
|
|||
}
|
||||
|
||||
llvm::Value *BlockFunction::BuildCopyHelper(int flag) {
|
||||
const llvm::PointerType *PtrToInt8Ty
|
||||
= llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
|
||||
// FIXME: implement
|
||||
llvm::Value *V = llvm::ConstantInt::get(llvm::Type::Int32Ty, 43);
|
||||
V = Builder.CreateIntToPtr(V, PtrToInt8Ty, "tmp");
|
||||
|
@ -688,11 +672,33 @@ llvm::Value *BlockFunction::BuildCopyHelper(int flag) {
|
|||
}
|
||||
|
||||
llvm::Value *BlockFunction::BuildDestroyHelper(int flag) {
|
||||
const llvm::PointerType *PtrToInt8Ty
|
||||
= llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
|
||||
// FIXME: implement
|
||||
llvm::Value *V = llvm::ConstantInt::get(llvm::Type::Int32Ty, 44);
|
||||
V = Builder.CreateIntToPtr(V, PtrToInt8Ty, "tmp");
|
||||
V = Builder.CreateBitCast(V, PtrToInt8Ty, "tmp");
|
||||
return V;
|
||||
}
|
||||
|
||||
llvm::Value *BlockFunction::getBlockObjectDispose() {
|
||||
if (CGM.BlockObjectDispose == 0) {
|
||||
const llvm::FunctionType *FTy;
|
||||
std::vector<const llvm::Type*> ArgTys;
|
||||
const llvm::Type *ResultType = llvm::Type::VoidTy;
|
||||
ArgTys.push_back(PtrToInt8Ty);
|
||||
ArgTys.push_back(llvm::Type::Int32Ty);
|
||||
FTy = llvm::FunctionType::get(ResultType, ArgTys, false);
|
||||
CGM.BlockObjectDispose
|
||||
= CGM.CreateRuntimeFunction(FTy, "_Block_object_dispose");
|
||||
}
|
||||
return CGM.BlockObjectDispose;
|
||||
}
|
||||
|
||||
void BlockFunction::BuildBlockRelease(const VarDecl &D, llvm::Value *DeclPtr) {
|
||||
llvm::Value *F = getBlockObjectDispose();
|
||||
llvm::Value *N, *V;
|
||||
V = Builder.CreateStructGEP(DeclPtr, 1, "forwarding");
|
||||
V = Builder.CreateLoad(V, false);
|
||||
V = Builder.CreateBitCast(V, PtrToInt8Ty);
|
||||
N = llvm::ConstantInt::get(llvm::Type::Int32Ty, BLOCK_FIELD_IS_BYREF);
|
||||
Builder.CreateCall2(F, V, N);
|
||||
}
|
||||
|
|
|
@ -94,19 +94,26 @@ public:
|
|||
int GlobalUniqueCount;
|
||||
} Block;
|
||||
|
||||
llvm::Value *BlockObjectDispose;
|
||||
const llvm::Type *PtrToInt8Ty;
|
||||
|
||||
BlockModule(ASTContext &C, llvm::Module &M, const llvm::TargetData &TD,
|
||||
CodeGenTypes &T, CodeGenModule &CodeGen)
|
||||
: Context(C), TheModule(M), TheTargetData(TD), Types(T),
|
||||
CGM(CodeGen),
|
||||
NSConcreteGlobalBlock(0), NSConcreteStackBlock(0), BlockDescriptorType(0),
|
||||
GenericBlockLiteralType(0) {
|
||||
GenericBlockLiteralType(0), BlockObjectDispose(0) {
|
||||
Block.GlobalUniqueCount = 0;
|
||||
PtrToInt8Ty = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
|
||||
}
|
||||
};
|
||||
|
||||
class BlockFunction : public BlockBase {
|
||||
CodeGenModule &CGM;
|
||||
|
||||
public:
|
||||
enum {
|
||||
const llvm::Type *PtrToInt8Ty;
|
||||
enum {
|
||||
BLOCK_FIELD_IS_OBJECT = 3, /* id, NSObject, __attribute__((NSObject)),
|
||||
block, ... */
|
||||
BLOCK_FIELD_IS_BLOCK = 7, /* a block variable */
|
||||
|
@ -140,7 +147,10 @@ public:
|
|||
|
||||
CGBuilderTy &Builder;
|
||||
|
||||
BlockFunction(CGBuilderTy &B) : Builder(B) { }
|
||||
BlockFunction(CodeGenModule &cgm, CGBuilderTy &B)
|
||||
: CGM(cgm), Builder(B) {
|
||||
PtrToInt8Ty = llvm::PointerType::getUnqual(llvm::Type::Int8Ty);
|
||||
}
|
||||
|
||||
ImplicitParamDecl *BlockStructDecl;
|
||||
ImplicitParamDecl *getBlockStructDecl() { return BlockStructDecl; }
|
||||
|
@ -148,6 +158,8 @@ public:
|
|||
llvm::Value *BuildCopyHelper(int flag);
|
||||
llvm::Value *BuildDestroyHelper(int flag);
|
||||
|
||||
llvm::Value *getBlockObjectDispose();
|
||||
void BuildBlockRelease(const VarDecl &D, llvm::Value *DeclPtr);
|
||||
};
|
||||
|
||||
} // end namespace CodeGen
|
||||
|
|
|
@ -227,6 +227,7 @@ const llvm::Type *CodeGenFunction::BuildByRefType(QualType Ty,
|
|||
void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
|
||||
QualType Ty = D.getType();
|
||||
bool isByRef = D.getAttr<BlocksAttr>();
|
||||
bool needsDispose = false;
|
||||
|
||||
llvm::Value *DeclPtr;
|
||||
if (Ty->isConstantSizeType()) {
|
||||
|
@ -371,6 +372,7 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
|
|||
|
||||
Builder.CreateStore(BuildDestroyHelper(flag), destroy_helper);
|
||||
}
|
||||
needsDispose = true;
|
||||
}
|
||||
|
||||
// Handle the cleanup attribute
|
||||
|
@ -388,6 +390,11 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
|
|||
|
||||
EmitCall(CGM.getTypes().getFunctionInfo(FD), F, Args);
|
||||
}
|
||||
|
||||
if (needsDispose) {
|
||||
CleanupScope scope(*this);
|
||||
BuildBlockRelease(D, DeclPtr);
|
||||
}
|
||||
}
|
||||
|
||||
/// Emit an alloca (or GlobalValue depending on target)
|
||||
|
|
|
@ -24,7 +24,7 @@ using namespace clang;
|
|||
using namespace CodeGen;
|
||||
|
||||
CodeGenFunction::CodeGenFunction(CodeGenModule &cgm)
|
||||
: BlockFunction(Builder), CGM(cgm), Target(CGM.getContext().Target),
|
||||
: BlockFunction(cgm, Builder), CGM(cgm), Target(CGM.getContext().Target),
|
||||
DebugInfo(0), SwitchInsn(0), CaseRangeBlock(0), InvokeDest(0) {
|
||||
LLVMIntTy = ConvertType(getContext().IntTy);
|
||||
LLVMPointerWidth = Target.getPointerWidth(0);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// RUN: clang %s -emit-llvm -o %t -fblocks -f__block
|
||||
// RUN: clang %s -emit-llvm -o %t -fblocks -f__block &&
|
||||
// RUN: grep "_Block_object_dispose" %t | count 3
|
||||
#include <stdio.h>
|
||||
|
||||
void test1() {
|
||||
|
|
Загрузка…
Ссылка в новой задаче