diff options
-rw-r--r-- | lib/CodeGen/CGBlocks.cpp | 251 | ||||
-rw-r--r-- | lib/CodeGen/CGBlocks.h | 219 | ||||
-rw-r--r-- | lib/CodeGen/CGBuiltin.cpp | 93 | ||||
-rw-r--r-- | lib/CodeGen/CGCXX.cpp | 8 | ||||
-rw-r--r-- | lib/CodeGen/CGCall.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CGClass.cpp | 3 | ||||
-rw-r--r-- | lib/CodeGen/CGCleanup.cpp | 4 | ||||
-rw-r--r-- | lib/CodeGen/CGDebugInfo.cpp | 1 | ||||
-rw-r--r-- | lib/CodeGen/CGDecl.cpp | 63 | ||||
-rw-r--r-- | lib/CodeGen/CGDeclCXX.cpp | 6 | ||||
-rw-r--r-- | lib/CodeGen/CGException.cpp | 23 | ||||
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 69 | ||||
-rw-r--r-- | lib/CodeGen/CGExprAgg.cpp | 4 | ||||
-rw-r--r-- | lib/CodeGen/CGExprCXX.cpp | 28 | ||||
-rw-r--r-- | lib/CodeGen/CGObjCMac.cpp | 1 | ||||
-rw-r--r-- | lib/CodeGen/CGStmt.cpp | 43 | ||||
-rw-r--r-- | lib/CodeGen/CGVTables.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.cpp | 14 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 112 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 24 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.h | 40 |
21 files changed, 511 insertions, 499 deletions
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp index e78e175a5a..76a68b1526 100644 --- a/lib/CodeGen/CGBlocks.cpp +++ b/lib/CodeGen/CGBlocks.cpp @@ -15,6 +15,7 @@ #include "CodeGenFunction.h" #include "CGObjCRuntime.h" #include "CodeGenModule.h" +#include "CGBlocks.h" #include "clang/AST/DeclObjC.h" #include "llvm/Module.h" #include "llvm/ADT/SmallSet.h" @@ -104,18 +105,20 @@ static llvm::Constant *buildBlockDescriptor(CodeGenModule &CGM, return llvm::ConstantExpr::getBitCast(global, CGM.getBlockDescriptorType()); } -static unsigned computeBlockFlag(CodeGenModule &CGM, - const BlockExpr *BE, unsigned flags) { - QualType BPT = BE->getType(); - const FunctionType *ftype = BPT->getPointeeType()->getAs<FunctionType>(); - QualType ResultType = ftype->getResultType(); +static BlockFlags computeBlockFlag(CodeGenModule &CGM, + const BlockExpr *BE, + BlockFlags flags) { + const FunctionType *ftype = BE->getFunctionType(); - CallArgList Args; - CodeGenTypes &Types = CGM.getTypes(); - const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, Args, - FunctionType::ExtInfo()); - if (CGM.ReturnTypeUsesSRet(FnInfo)) - flags |= CodeGenFunction::BLOCK_USE_STRET; + // This is a bit overboard. + CallArgList args; + const CGFunctionInfo &fnInfo = + CGM.getTypes().getFunctionInfo(ftype->getResultType(), args, + ftype->getExtInfo()); + + if (CGM.ReturnTypeUsesSRet(fnInfo)) + flags |= BLOCK_USE_STRET; + return flags; } @@ -514,7 +517,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) { llvm::Constant *blockFn = CodeGenFunction(CGM).GenerateBlockFunction(CurGD, blockInfo, CurFuncDecl, LocalDeclMap); - blockFn = llvm::ConstantExpr::getBitCast(blockFn, PtrToInt8Ty); + blockFn = llvm::ConstantExpr::getBitCast(blockFn, Int8PtrTy); // If there is nothing to capture, we can emit this as a global block. if (blockInfo.CanBeGlobal) @@ -523,7 +526,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) { // Otherwise, we have to emit this as a local block. llvm::Constant *isa = CGM.getNSConcreteStackBlock(); - isa = llvm::ConstantExpr::getBitCast(isa, PtrToInt8Ty); + isa = llvm::ConstantExpr::getBitCast(isa, Int8PtrTy); // Build the block descriptor. llvm::Constant *descriptor = buildBlockDescriptor(CGM, blockInfo); @@ -535,14 +538,14 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) { blockAddr->setAlignment(blockInfo.BlockAlign.getQuantity()); // Compute the initial on-stack block flags. - unsigned int flags = BLOCK_HAS_SIGNATURE; + BlockFlags flags = BLOCK_HAS_SIGNATURE; if (blockInfo.NeedsCopyDispose) flags |= BLOCK_HAS_COPY_DISPOSE; if (blockInfo.HasCXXObject) flags |= BLOCK_HAS_CXX_OBJ; flags = computeBlockFlag(CGM, blockInfo.getBlockExpr(), flags); // Initialize the block literal. Builder.CreateStore(isa, Builder.CreateStructGEP(blockAddr, 0, "block.isa")); - Builder.CreateStore(llvm::ConstantInt::get(intTy, flags), + Builder.CreateStore(llvm::ConstantInt::get(intTy, flags.getBitMask()), Builder.CreateStructGEP(blockAddr, 1, "block.flags")); Builder.CreateStore(llvm::ConstantInt::get(intTy, 0), Builder.CreateStructGEP(blockAddr, 2, "block.reserved")); @@ -605,7 +608,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) { if (ci->isNested()) src = Builder.CreateLoad(src, "byref.capture"); else - src = Builder.CreateBitCast(src, PtrToInt8Ty); + src = Builder.CreateBitCast(src, Int8PtrTy); // Write that i8* into the capture field. Builder.CreateStore(src, blockField); @@ -667,7 +670,7 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) { } -const llvm::Type *BlockModule::getBlockDescriptorType() { +const llvm::Type *CodeGenModule::getBlockDescriptorType() { if (BlockDescriptorType) return BlockDescriptorType; @@ -701,7 +704,7 @@ const llvm::Type *BlockModule::getBlockDescriptorType() { return BlockDescriptorType; } -const llvm::Type *BlockModule::getGenericBlockLiteralType() { +const llvm::Type *CodeGenModule::getGenericBlockLiteralType() { if (GenericBlockLiteralType) return GenericBlockLiteralType; @@ -718,10 +721,10 @@ const llvm::Type *BlockModule::getGenericBlockLiteralType() { // struct __block_descriptor *__descriptor; // }; GenericBlockLiteralType = llvm::StructType::get(IntTy->getContext(), - PtrToInt8Ty, + Int8PtrTy, IntTy, IntTy, - PtrToInt8Ty, + Int8PtrTy, BlockDescPtrTy, NULL); @@ -750,10 +753,7 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E, // Get the function pointer from the literal. llvm::Value *FuncPtr = Builder.CreateStructGEP(BlockLiteral, 3, "tmp"); - BlockLiteral = - Builder.CreateBitCast(BlockLiteral, - llvm::Type::getInt8PtrTy(VMContext), - "tmp"); + BlockLiteral = Builder.CreateBitCast(BlockLiteral, Int8PtrTy, "tmp"); // Add the block literal. QualType VoidPtrTy = getContext().getPointerType(getContext().VoidTy); @@ -826,24 +826,24 @@ llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const VarDecl *variable, } llvm::Constant * -BlockModule::GetAddrOfGlobalBlock(const BlockExpr *blockExpr, +CodeGenModule::GetAddrOfGlobalBlock(const BlockExpr *blockExpr, const char *name) { CGBlockInfo blockInfo(blockExpr, name); // Compute information about the layout, etc., of this block. - computeBlockInfo(CGM, blockInfo); + computeBlockInfo(*this, blockInfo); // Using that metadata, generate the actual block function. llvm::Constant *blockFn; { llvm::DenseMap<const Decl*, llvm::Value*> LocalDeclMap; - blockFn = CodeGenFunction(CGM).GenerateBlockFunction(GlobalDecl(), - blockInfo, - 0, LocalDeclMap); + blockFn = CodeGenFunction(*this).GenerateBlockFunction(GlobalDecl(), + blockInfo, + 0, LocalDeclMap); } - blockFn = llvm::ConstantExpr::getBitCast(blockFn, PtrToInt8Ty); + blockFn = llvm::ConstantExpr::getBitCast(blockFn, Int8PtrTy); - return buildGlobalBlock(CGM, blockInfo, blockFn); + return buildGlobalBlock(*this, blockInfo, blockFn); } static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM, @@ -858,11 +858,10 @@ static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM, fields[0] = CGM.getNSConcreteGlobalBlock(); // __flags - unsigned flags = computeBlockFlag(CGM, blockInfo.getBlockExpr(), - BlockBase::BLOCK_IS_GLOBAL | - BlockBase::BLOCK_HAS_SIGNATURE); + BlockFlags flags = computeBlockFlag(CGM, blockInfo.getBlockExpr(), + BLOCK_IS_GLOBAL | BLOCK_HAS_SIGNATURE); const llvm::Type *intTy = CGM.getTypes().ConvertType(CGM.getContext().IntTy); - fields[1] = llvm::ConstantInt::get(intTy, flags); + fields[1] = llvm::ConstantInt::get(intTy, flags.getBitMask()); // Reserved fields[2] = llvm::Constant::getNullValue(intTy); @@ -1075,7 +1074,7 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD, llvm::Constant * -BlockFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) { +CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) { ASTContext &C = getContext(); FunctionArgList args; @@ -1108,17 +1107,17 @@ BlockFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) { SC_None, false, true); - CGF.StartFunction(FD, C.VoidTy, Fn, args, SourceLocation()); + StartFunction(FD, C.VoidTy, Fn, args, SourceLocation()); const llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo(); - llvm::Value *src = CGF.GetAddrOfLocalVar(srcDecl); - src = CGF.Builder.CreateLoad(src); - src = CGF.Builder.CreateBitCast(src, structPtrTy, "block.source"); + llvm::Value *src = GetAddrOfLocalVar(srcDecl); + src = Builder.CreateLoad(src); + src = Builder.CreateBitCast(src, structPtrTy, "block.source"); - llvm::Value *dst = CGF.GetAddrOfLocalVar(dstDecl); - dst = CGF.Builder.CreateLoad(dst); - dst = CGF.Builder.CreateBitCast(dst, structPtrTy, "block.dest"); + llvm::Value *dst = GetAddrOfLocalVar(dstDecl); + dst = Builder.CreateLoad(dst); + dst = Builder.CreateBitCast(dst, structPtrTy, "block.dest"); const BlockDecl *blockDecl = blockInfo.getBlockDecl(); @@ -1148,28 +1147,28 @@ BlockFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) { if (!copyExpr && !flags) continue; unsigned index = capture.getIndex(); - llvm::Value *srcField = CGF.Builder.CreateStructGEP(src, index); - llvm::Value *dstField = CGF.Builder.CreateStructGEP(dst, index); + llvm::Value *srcField = Builder.CreateStructGEP(src, index); + llvm::Value *dstField = Builder.CreateStructGEP(dst, index); // If there's an explicit copy expression, we do that. if (copyExpr) { - CGF.EmitSynthesizedCXXCopyCtor(dstField, srcField, copyExpr); + EmitSynthesizedCXXCopyCtor(dstField, srcField, copyExpr); } else { llvm::Value *srcValue = Builder.CreateLoad(srcField, "blockcopy.src"); - srcValue = Builder.CreateBitCast(srcValue, PtrToInt8Ty); - llvm::Value *dstAddr = Builder.CreateBitCast(dstField, PtrToInt8Ty); + srcValue = Builder.CreateBitCast(srcValue, Int8PtrTy); + llvm::Value *dstAddr = Builder.CreateBitCast(dstField, Int8PtrTy); Builder.CreateCall3(CGM.getBlockObjectAssign(), dstAddr, srcValue, - llvm::ConstantInt::get(CGF.Int32Ty, flags)); + llvm::ConstantInt::get(Int32Ty, flags)); } } - CGF.FinishFunction(); + FinishFunction(); - return llvm::ConstantExpr::getBitCast(Fn, PtrToInt8Ty); + return llvm::ConstantExpr::getBitCast(Fn, Int8PtrTy); } llvm::Constant * -BlockFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) { +CodeGenFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) { ASTContext &C = getContext(); FunctionArgList args; @@ -1197,17 +1196,17 @@ BlockFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) { SC_Static, SC_None, false, true); - CGF.StartFunction(FD, C.VoidTy, Fn, args, SourceLocation()); + StartFunction(FD, C.VoidTy, Fn, args, SourceLocation()); const llvm::Type *structPtrTy = blockInfo.StructureType->getPointerTo(); - llvm::Value *src = CGF.GetAddrOfLocalVar(srcDecl); - src = CGF.Builder.CreateLoad(src); - src = CGF.Builder.CreateBitCast(src, structPtrTy, "block"); + llvm::Value *src = GetAddrOfLocalVar(srcDecl); + src = Builder.CreateLoad(src); + src = Builder.CreateBitCast(src, structPtrTy, "block"); const BlockDecl *blockDecl = blockInfo.getBlockDecl(); - CodeGenFunction::RunCleanupsScope cleanups(CGF); + CodeGenFunction::RunCleanupsScope cleanups(*this); for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(), ce = blockDecl->capture_end(); ci != ce; ++ci) { @@ -1217,7 +1216,7 @@ BlockFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) { const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); if (capture.isConstant()) continue; - unsigned flags = 0; + BlockFieldFlags flags; const CXXDestructorDecl *dtor = 0; if (ci->isByRef()) { @@ -1233,35 +1232,35 @@ BlockFunction::GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo) { dtor = record->getDestructor(); } - if (!dtor && !flags) continue; + if (!dtor && flags.empty()) continue; unsigned index = capture.getIndex(); - llvm::Value *srcField = CGF.Builder.CreateStructGEP(src, index); + llvm::Value *srcField = Builder.CreateStructGEP(src, index); // If there's an explicit copy expression, we do that. if (dtor) { - CGF.PushDestructorCleanup(dtor, srcField); + PushDestructorCleanup(dtor, srcField); // Otherwise we call _Block_object_dispose. It wouldn't be too // hard to just emit this as a cleanup if we wanted to make sure // that things were done in reverse. } else { llvm::Value *value = Builder.CreateLoad(srcField); - value = Builder.CreateBitCast(value, PtrToInt8Ty); + value = Builder.CreateBitCast(value, Int8PtrTy); BuildBlockRelease(value, flags); } } cleanups.ForceCleanup(); - CGF.FinishFunction(); + FinishFunction(); - return llvm::ConstantExpr::getBitCast(Fn, PtrToInt8Ty); + return llvm::ConstantExpr::getBitCast(Fn, Int8PtrTy); } -llvm::Constant *BlockFunction:: -GeneratebyrefCopyHelperFunction(const llvm::Type *T, int flag, - const VarDecl *BD) { +llvm::Constant *CodeGenFunction:: +GeneratebyrefCopyHelperFunction(const llvm::Type *T, BlockFieldFlags flags, + const VarDecl *variable) { QualType R = getContext().VoidTy; FunctionArgList Args; @@ -1300,46 +1299,43 @@ GeneratebyrefCopyHelperFunction(const llvm::Type *T, int flag, SC_Static, SC_None, false, true); - CGF.StartFunction(FD, R, Fn, Args, SourceLocation()); + StartFunction(FD, R, Fn, Args, SourceLocation()); // dst->x - llvm::Value *V = CGF.GetAddrOfLocalVar(Dst); + llvm::Value *V = GetAddrOfLocalVar(Dst); V = Builder.CreateBitCast(V, llvm::PointerType::get(T, 0)); V = Builder.CreateLoad(V); V = Builder.CreateStructGEP(V, 6, "x"); llvm::Value *DstObj = V; // src->x - V = CGF.GetAddrOfLocalVar(Src); + V = GetAddrOfLocalVar(Src); V = Builder.CreateLoad(V); V = Builder.CreateBitCast(V, T); V = Builder.CreateStructGEP(V, 6, "x"); - if (flag & BLOCK_HAS_CXX_OBJ) { - assert (BD && "VarDecl is null - GeneratebyrefCopyHelperFunction"); + if (Expr *copyExpr = getContext().getBlockVarCopyInits(variable)) { 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)); + EmitSynthesizedCXXCopyCtor(DstObj, SrcObj, copyExpr); + } else { + DstObj = Builder.CreateBitCast(DstObj, Int8PtrTy); + V = Builder.CreateBitCast(V, llvm::PointerType::get(Int8PtrTy, 0)); llvm::Value *SrcObj = Builder.CreateLoad(V); - flag |= BLOCK_BYREF_CALLER; - llvm::Value *N = llvm::ConstantInt::get(CGF.Int32Ty, flag); + flags |= BLOCK_BYREF_CALLER; + llvm::Value *N = llvm::ConstantInt::get(Int32Ty, flags.getBitMask()); llvm::Value *F = CGM.getBlockObjectAssign(); Builder.CreateCall3(F, DstObj, SrcObj, N); } - CGF.FinishFunction(); + FinishFunction(); - return llvm::ConstantExpr::getBitCast(Fn, PtrToInt8Ty); + return llvm::ConstantExpr::getBitCast(Fn, Int8PtrTy); } llvm::Constant * -BlockFunction::GeneratebyrefDestroyHelperFunction(const llvm::Type *T, - int flag, - const VarDecl *BD) { +CodeGenFunction::GeneratebyrefDestroyHelperFunction(const llvm::Type *T, + BlockFieldFlags flags, + const VarDecl *variable) { QualType R = getContext().VoidTy; FunctionArgList Args; @@ -1373,85 +1369,78 @@ BlockFunction::GeneratebyrefDestroyHelperFunction(const llvm::Type *T, SC_Static, SC_None, false, true); - CGF.StartFunction(FD, R, Fn, Args, SourceLocation()); + StartFunction(FD, R, Fn, Args, SourceLocation()); - llvm::Value *V = CGF.GetAddrOfLocalVar(Src); + llvm::Value *V = GetAddrOfLocalVar(Src); V = Builder.CreateBitCast(V, llvm::PointerType::get(T, 0)); V = Builder.CreateLoad(V); V = Builder.CreateStructGEP(V, 6, "x"); - 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)); + + // If it's not any kind of special object, it must have a destructor + // or something. + if (!flags.isSpecialPointer()) { + EHScopeStack::stable_iterator CleanupDepth = EHStack.stable_begin(); + PushDestructorCleanup(variable->getType(), V); + PopCleanupBlocks(CleanupDepth); + + // Otherwise, call _Block_object_dispose. + } else { + V = Builder.CreateBitCast(V, llvm::PointerType::get(Int8PtrTy, 0)); V = Builder.CreateLoad(V); - flag |= BLOCK_BYREF_CALLER; - BuildBlockRelease(V, flag); + flags |= BLOCK_BYREF_CALLER; + BuildBlockRelease(V, flags); } - CGF.FinishFunction(); - return llvm::ConstantExpr::getBitCast(Fn, PtrToInt8Ty); + FinishFunction(); + + return llvm::ConstantExpr::getBitCast(Fn, Int8PtrTy); } -llvm::Constant *BlockFunction::BuildbyrefCopyHelper(const llvm::Type *T, - uint32_t flags, +llvm::Constant *CodeGenModule::BuildbyrefCopyHelper(const llvm::Type *T, + BlockFieldFlags flags, unsigned align, const VarDecl *var) { // 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. - align /= unsigned(CGF.Target.getPointerAlign(0)/8); + align /= unsigned(getTarget().getPointerAlign(0) / 8); // As an optimization, we only generate a single function of each kind we // might need. We need a different one for each alignment and for each // setting of flags. We mix Align and flag to get the kind. - uint64_t Kind = (uint64_t)align*BLOCK_BYREF_CURRENT_MAX + flags; - llvm::Constant *&Entry = CGM.AssignCache[Kind]; - if (Entry) - return Entry; - return Entry = - CodeGenFunction(CGM).GeneratebyrefCopyHelperFunction(T, flags, var); + uint64_t Kind = (uint64_t)align*BLOCK_BYREF_CURRENT_MAX + flags.getBitMask(); + llvm::Constant *&Entry = AssignCache[Kind]; + if (!Entry) + Entry = CodeGenFunction(*this). + GeneratebyrefCopyHelperFunction(T, flags, var); + return Entry; } -llvm::Constant *BlockFunction::BuildbyrefDestroyHelper(const llvm::Type *T, - uint32_t flags, +llvm::Constant *CodeGenModule::BuildbyrefDestroyHelper(const llvm::Type *T, + BlockFieldFlags flags, unsigned align, const VarDecl *var) { // 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. - align /= unsigned(CGF.Target.getPointerAlign(0)/8); + align /= unsigned(getTarget().getPointerAlign(0) / 8); // As an optimization, we only generate a single function of each kind we // might need. We need a different one for each alignment and for each // setting of flags. We mix Align and flag to get the kind. - uint64_t Kind = (uint64_t)align*BLOCK_BYREF_CURRENT_MAX + flags; - llvm::Constant *&Entry = CGM.DestroyCache[Kind]; - if (Entry) - return Entry; - return Entry = - CodeGenFunction(CGM).GeneratebyrefDestroyHelperFunction(T, flags, var); + uint64_t Kind = (uint64_t)align*BLOCK_BYREF_CURRENT_MAX + flags.getBitMask(); + llvm::Constant *&Entry = DestroyCache[Kind]; + if (!Entry) + Entry = CodeGenFunction(*this). + GeneratebyrefDestroyHelperFunction(T, flags, var); + return Entry; } -void BlockFunction::BuildBlockRelease(llvm::Value *V, uint32_t flags) { +void CodeGenFunction::BuildBlockRelease(llvm::Value *V, BlockFieldFlags flags) { llvm::Value *F = CGM.getBlockObjectDispose(); llvm::Value *N; - V = Builder.CreateBitCast(V, PtrToInt8Ty); - N = llvm::ConstantInt::get(CGF.Int32Ty, flags); + V = Builder.CreateBitCast(V, Int8PtrTy); + N = llvm::ConstantInt::get(Int32Ty, flags.getBitMask()); Builder.CreateCall2(F, V, N); } - -ASTContext &BlockFunction::getContext() const { return CGM.getContext(); } - -BlockFunction::BlockFunction(CodeGenModule &cgm, CodeGenFunction &cgf, - CGBuilderTy &B) - : CGM(cgm), VMContext(cgm.getLLVMContext()), CGF(cgf), - BlockInfo(0), BlockPointer(0), Builder(B) { - PtrToInt8Ty = llvm::PointerType::getUnqual( - llvm::Type::getInt8Ty(VMContext)); -} diff --git a/lib/CodeGen/CGBlocks.h b/lib/CodeGen/CGBlocks.h index 888fdb6a40..a2a1cdfdf6 100644 --- a/lib/CodeGen/CGBlocks.h +++ b/lib/CodeGen/CGBlocks.h @@ -24,9 +24,6 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" -#include <vector> -#include <map> - #include "CGBuilder.h" #include "CGCall.h" #include "CGValue.h" @@ -46,116 +43,156 @@ namespace llvm { namespace clang { namespace CodeGen { + class CodeGenModule; class CGBlockInfo; -class BlockBase { -public: - enum { - BLOCK_HAS_COPY_DISPOSE = (1 << 25), - BLOCK_HAS_CXX_OBJ = (1 << 26), - BLOCK_IS_GLOBAL = (1 << 28), - BLOCK_USE_STRET = (1 << 29), - BLOCK_HAS_SIGNATURE = (1 << 30) - }; +enum BlockFlag_t { + BLOCK_HAS_COPY_DISPOSE = (1 << 25), + BLOCK_HAS_CXX_OBJ = (1 << 26), + BLOCK_IS_GLOBAL = (1 << 28), + BLOCK_USE_STRET = (1 << 29), + BLOCK_HAS_SIGNATURE = (1 << 30) }; +class BlockFlags { + uint32_t flags; - -class BlockModule : public BlockBase { - ASTContext &Context; - llvm::Module &TheModule; - const llvm::TargetData &TheTargetData; - CodeGenTypes &Types; - CodeGenModule &CGM; - llvm::LLVMContext &VMContext; - - ASTContext &getContext() const { return Context; } - llvm::Module &getModule() const { return TheModule; } - CodeGenTypes &getTypes() { return Types; } - const llvm::TargetData &getTargetData() const { return TheTargetData; } + BlockFlags(uint32_t flags) : flags(flags) {} public: - int getGlobalUniqueCount() { return ++Block.GlobalUniqueCount; } - const llvm::Type *getBlockDescriptorType(); - - const llvm::Type *getGenericBlockLiteralType(); - - llvm::Constant *GetAddrOfGlobalBlock(const BlockExpr *BE, const char *); + BlockFlags() : flags(0) {} + BlockFlags(BlockFlag_t flag) : flags(flag) {} - const llvm::Type *BlockDescriptorType; - const llvm::Type *GenericBlockLiteralType; + uint32_t getBitMask() const { return flags; } + bool empty() const { return flags == 0; } - struct { - int GlobalUniqueCount; - } Block; - - const llvm::PointerType *PtrToInt8Ty; - - std::map<uint64_t, llvm::Constant *> AssignCache; - std::map<uint64_t, llvm::Constant *> DestroyCache; - - BlockModule(ASTContext &C, llvm::Module &M, const llvm::TargetData &TD, - CodeGenTypes &T, CodeGenModule &CodeGen) - : Context(C), TheModule(M), TheTargetData(TD), Types(T), - CGM(CodeGen), VMContext(M.getContext()), - BlockDescriptorType(0), GenericBlockLiteralType(0) { - Block.GlobalUniqueCount = 0; - PtrToInt8Ty = llvm::Type::getInt8PtrTy(M.getContext()); + friend BlockFlags operator|(BlockFlags l, BlockFlags r) { + return BlockFlags(l.flags | r.flags); + } + friend BlockFlags &operator|=(BlockFlags &l, BlockFlags r) { + l.flags |= r.flags; + return l; + } + friend bool operator&(BlockFlags l, BlockFlags r) { + return (l.flags & r.flags); } }; +inline BlockFlags operator|(BlockFlag_t l, BlockFlag_t r) { + return BlockFlags(l) | BlockFlags(r); +} -class BlockFunction : public BlockBase { - CodeGenModule &CGM; - ASTContext &getContext() const; +enum BlockFieldFlag_t { + BLOCK_FIELD_IS_OBJECT = 0x03, /* id, NSObject, __attribute__((NSObject)), + block, ... */ + BLOCK_FIELD_IS_BLOCK = 0x07, /* a block variable */ -protected: - llvm::LLVMContext &VMContext; + BLOCK_FIELD_IS_BYREF = 0x08, /* the on stack structure holding the __block + variable */ + BLOCK_FIELD_IS_WEAK = 0x10, /* declared __weak, only used in byref copy + helpers */ -public: - CodeGenFunction &CGF; + BLOCK_BYREF_CALLER = 128, /* called from __block (byref) copy/dispose + support routines */ + BLOCK_BYREF_CURRENT_MAX = 256 +}; - const CodeGen::CGBlockInfo *BlockInfo; - llvm::Value *BlockPointer; +class BlockFieldFlags { + uint32_t flags; - const llvm::PointerType *PtrToInt8Ty; - struct HelperInfo { - int index; - int flag; - const BlockDeclRefExpr *cxxvar_import; - bool RequiresCopying; - }; + BlockFieldFlags(uint32_t flags) : flags(flags) {} +public: + BlockFieldFlags() : flags(0) {} + BlockFieldFlags(BlockFieldFlag_t flag) : flags(flag) {} - enum { - BLOCK_FIELD_IS_OBJECT = 3, /* id, NSObject, __attribute__((NSObject)), - block, ... */ - BLOCK_FIELD_IS_BLOCK = 7, /* a block variable */ - BLOCK_FIELD_IS_BYREF = 8, /* the on stack structure holding the __block - variable */ - BLOCK_FIELD_IS_WEAK = 16, /* declared __weak, only used in byref copy - helpers */ - BLOCK_BYREF_CALLER = 128, /* called from __block (byref) copy/dispose - support routines */ - BLOCK_BYREF_CURRENT_MAX = 256 - }; + uint32_t getBitMask() const { return flags; } + bool empty() const { return flags == 0; } - CGBuilderTy &Builder; + /// Answers whether the flags indicate that this field is an object + /// or block pointer that requires _Block_object_assign/dispose. + bool isSpecialPointer() const { return flags & BLOCK_FIELD_IS_OBJECT; } - BlockFunction(CodeGenModule &cgm, CodeGenFunction &cgf, CGBuilderTy &B); + friend BlockFieldFlags operator|(BlockFieldFlags l, BlockFieldFlags r) { + return BlockFieldFlags(l.flags | r.flags); + } + friend BlockFieldFlags &operator|=(BlockFieldFlags &l, BlockFieldFlags r) { + l.flags |= r.flags; + return l; + } + friend bool operator&(BlockFieldFlags l, BlockFieldFlags r) { + return (l.flags & r.flags); + } +}; +inline BlockFieldFlags operator|(BlockFieldFlag_t l, BlockFieldFlag_t r) { + return BlockFieldFlags(l) | BlockFieldFlags(r); +} - llvm::Constant *GenerateCopyHelperFunction(const CGBlockInfo &blockInfo); - llvm::Constant *GenerateDestroyHelperFunction(const CGBlockInfo &blockInfo); +/// CGBlockInfo - Information to generate a block literal. +class CGBlockInfo { +public: + /// Name - The name of the block, kindof. + const char *Name; + + /// The field index of 'this' within the block, if there is one. + unsigned CXXThisIndex; + + class Capture { + uintptr_t Data; + + public: + bool isIndex() const { return (Data & 1) != 0; } + bool isConstant() const { return !isIndex(); } + unsigned getIndex() const { assert(isIndex()); return Data >> 1; } + llvm::Value *getConstant() const { + assert(isConstant()); + return reinterpret_cast<llvm::Value*>(Data); + } + + static Capture makeIndex(unsigned index) { + Capture v; + v.Data = (index << 1) | 1; + return v; + } + + static Capture makeConstant(llvm::Value *value) { + Capture v; + v.Data = reinterpret_cast<uintptr_t>(value); + return v; + } + }; - llvm::Constant *GeneratebyrefCopyHelperFunction(const llvm::Type *, int flag, - const VarDecl *BD); - llvm::Constant *GeneratebyrefDestroyHelperFunction(const llvm::Type *T, - int flag, - const VarDecl *BD); + /// The mapping of allocated indexes within the block. + llvm::DenseMap<const VarDecl*, Capture> Captures; + + /// CanBeGlobal - True if the block can be global, i.e. it has + /// no non-constant captures. + bool CanBeGlobal : 1; + + /// True if the block needs a custom copy or dispose function. + bool NeedsCopyDispose : 1; + + /// HasCXXObject - True if the block's custom copy/dispose functions + /// need to be run even in GC mode. + bool HasCXXObject : 1; + + /// HasWeakBlockVariable - True if block captures a weak __block variable. + bool HasWeakBlockVariable : 1; + + const llvm::StructType *StructureType; + const BlockExpr *Block; + CharUnits BlockSize; + CharUnits BlockAlign; + llvm::SmallVector<const Expr*, 8> BlockLayout; + + const Capture &getCapture(const VarDecl *var) const { + llvm::DenseMap<const VarDecl*, Capture>::const_iterator + it = Captures.find(var); + assert(it != Captures.end() && "no entry for variable!"); + return it->second; + } - llvm::Constant *BuildbyrefCopyHelper(const llvm::Type *T, uint32_t flags, - unsigned Align, const VarDecl *BD); - llvm::Constant *BuildbyrefDestroyHelper(const llvm::Type *T, uint32_t flags, - unsigned Align, const VarDecl *BD); + const BlockDecl *getBlockDecl() const { return Block->getBlockDecl(); } + const BlockExpr *getBlockExpr() const { return Block; } - void BuildBlockRelease(llvm::Value *DeclPtr, uint32_t flags); + CGBlockInfo(const BlockExpr *blockExpr, const char *Name); }; } // end namespace CodeGen diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 4e59c8d517..87572d68c6 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -30,8 +30,8 @@ static void EmitMemoryBarrier(CodeGenFunction &CGF, bool LoadLoad, bool LoadStore, bool StoreLoad, bool StoreStore, bool Device) { - Value *True = llvm::ConstantInt::getTrue(CGF.getLLVMContext()); - Value *False = llvm::ConstantInt::getFalse(CGF.getLLVMContext()); + Value *True = CGF.Builder.getTrue(); + Value *False = CGF.Builder.getFalse(); Value *C[5] = { LoadLoad ? True : False, LoadStore ? True : False, StoreLoad ? True : False, @@ -178,10 +178,11 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, Expr::EvalResult Result; if (E->Evaluate(Result, CGM.getContext())) { if (Result.Val.isInt()) - return RValue::get(llvm::ConstantInt::get(VMContext, + return RValue::get(llvm::ConstantInt::get(getLLVMContext(), Result.Val.getInt())); if (Result.Val.isFloat()) - return RValue::get(ConstantFP::get(VMContext, Result.Val.getFloat())); + return RValue::get(llvm::ConstantFP::get(getLLVMContext(), + Result.Val.getFloat())); } switch (BuiltinID) { @@ -193,7 +194,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, case Builtin::BI__builtin_va_start: case Builtin::BI__builtin_va_end: { Value *ArgValue = EmitVAListRef(E->getArg(0)); - const llvm::Type *DestType = llvm::Type::getInt8PtrTy(VMContext); + const llvm::Type *DestType = Int8PtrTy; if (ArgValue->getType() != DestType) ArgValue = Builder.CreateBitCast(ArgValue, DestType, ArgValue->getName().data()); @@ -206,7 +207,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, Value *DstPtr = EmitVAListRef(E->getArg(0)); Value *SrcPtr = EmitVAListRef(E->getArg(1)); - const llvm::Type *Type = llvm::Type::getInt8PtrTy(VMContext); |