diff options
author | John McCall <rjmccall@apple.com> | 2011-02-08 08:22:06 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2011-02-08 08:22:06 +0000 |
commit | ad7c5c1657f2504537bb62298f9372873c63d508 (patch) | |
tree | 2a6f5a80a514910228be09928ec2b813f131681c /clang/lib/CodeGen/CGBlocks.h | |
parent | f9399453c38f8c7ea5d2784847119937c440e40e (diff) | |
download | bcm5719-llvm-ad7c5c1657f2504537bb62298f9372873c63d508.tar.gz bcm5719-llvm-ad7c5c1657f2504537bb62298f9372873c63d508.zip |
Reorganize CodeGen{Function,Module} to eliminate the unfortunate
Block{Function,Module} base class. Minor other refactorings.
Fixed a few address-space bugs while I was there.
llvm-svn: 125085
Diffstat (limited to 'clang/lib/CodeGen/CGBlocks.h')
-rw-r--r-- | clang/lib/CodeGen/CGBlocks.h | 219 |
1 files changed, 128 insertions, 91 deletions
diff --git a/clang/lib/CodeGen/CGBlocks.h b/clang/lib/CodeGen/CGBlocks.h index 888fdb6a400..a2a1cdfdf6a 100644 --- a/clang/lib/CodeGen/CGBlocks.h +++ b/clang/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 |