| //===-- CGBlocks.h - state for LLVM CodeGen for blocks ----------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This is the internal state used for llvm translation for block literals. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef CLANG_CODEGEN_CGBLOCKS_H |
| #define CLANG_CODEGEN_CGBLOCKS_H |
| |
| #include "CodeGenTypes.h" |
| #include "clang/AST/Type.h" |
| #include "llvm/Module.h" |
| #include "llvm/ADT/DenseMap.h" |
| #include "llvm/ADT/SmallVector.h" |
| #include "clang/Basic/TargetInfo.h" |
| #include "clang/AST/Expr.h" |
| #include "clang/AST/ExprCXX.h" |
| #include "clang/AST/ExprObjC.h" |
| |
| #include <vector> |
| #include <map> |
| |
| #include "CGBuilder.h" |
| #include "CGCall.h" |
| #include "CGValue.h" |
| |
| namespace llvm { |
| class Module; |
| class Constant; |
| class Function; |
| class GlobalValue; |
| class TargetData; |
| class FunctionType; |
| class Value; |
| class LLVMContext; |
| } |
| |
| namespace clang { |
| |
| namespace CodeGen { |
| class CodeGenModule; |
| |
| class BlockBase { |
| public: |
| enum { |
| BLOCK_NEEDS_FREE = (1 << 24), |
| BLOCK_HAS_COPY_DISPOSE = (1 << 25), |
| BLOCK_HAS_CXX_OBJ = (1 << 26), |
| BLOCK_IS_GC = (1 << 27), |
| BLOCK_IS_GLOBAL = (1 << 28), |
| BLOCK_HAS_DESCRIPTOR = (1 << 29) |
| }; |
| }; |
| |
| 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; } |
| public: |
| llvm::Constant *getNSConcreteGlobalBlock(); |
| llvm::Constant *getNSConcreteStackBlock(); |
| int getGlobalUniqueCount() { return ++Block.GlobalUniqueCount; } |
| const llvm::Type *getBlockDescriptorType(); |
| |
| const llvm::Type *getGenericBlockLiteralType(); |
| const llvm::Type *getGenericExtendedBlockLiteralType(); |
| |
| llvm::Constant *GetAddrOfGlobalBlock(const BlockExpr *BE, const char *); |
| |
| /// NSConcreteGlobalBlock - Cached reference to the class pointer for global |
| /// blocks. |
| llvm::Constant *NSConcreteGlobalBlock; |
| |
| /// NSConcreteStackBlock - Cached reference to the class poinnter for stack |
| /// blocks. |
| llvm::Constant *NSConcreteStackBlock; |
| |
| const llvm::Type *BlockDescriptorType; |
| const llvm::Type *GenericBlockLiteralType; |
| const llvm::Type *GenericExtendedBlockLiteralType; |
| struct { |
| int GlobalUniqueCount; |
| } Block; |
| |
| llvm::Value *BlockObjectAssign; |
| llvm::Value *BlockObjectDispose; |
| const llvm::Type *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()), |
| NSConcreteGlobalBlock(0), NSConcreteStackBlock(0), BlockDescriptorType(0), |
| GenericBlockLiteralType(0), GenericExtendedBlockLiteralType(0), |
| BlockObjectAssign(0), BlockObjectDispose(0) { |
| Block.GlobalUniqueCount = 0; |
| PtrToInt8Ty = llvm::PointerType::getUnqual( |
| llvm::Type::getInt8Ty(M.getContext())); |
| } |
| }; |
| |
| class BlockFunction : public BlockBase { |
| CodeGenModule &CGM; |
| CodeGenFunction &CGF; |
| ASTContext &getContext() const; |
| |
| protected: |
| llvm::LLVMContext &VMContext; |
| |
| public: |
| const llvm::Type *PtrToInt8Ty; |
| struct HelperInfo { |
| int index; |
| int flag; |
| bool RequiresCopying; |
| }; |
| |
| 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 |
| }; |
| |
| /// BlockInfo - Information to generate a block literal. |
| struct BlockInfo { |
| /// BlockLiteralTy - The type of the block literal. |
| const llvm::Type *BlockLiteralTy; |
| |
| /// Name - the name of the function this block was created for, if any. |
| const char *Name; |
| |
| /// ByCopyDeclRefs - Variables from parent scopes that have been imported |
| /// into this block. |
| llvm::SmallVector<const BlockDeclRefExpr *, 8> ByCopyDeclRefs; |
| |
| // ByRefDeclRefs - __block variables from parent scopes that have been |
| // imported into this block. |
| llvm::SmallVector<const BlockDeclRefExpr *, 8> ByRefDeclRefs; |
| |
| BlockInfo(const llvm::Type *blt, const char *n) |
| : BlockLiteralTy(blt), Name(n) { |
| // Skip asm prefix, if any. |
| if (Name && Name[0] == '\01') |
| ++Name; |
| } |
| }; |
| |
| CGBuilderTy &Builder; |
| |
| BlockFunction(CodeGenModule &cgm, CodeGenFunction &cgf, CGBuilderTy &B); |
| |
| /// BlockOffset - The offset in bytes for the next allocation of an |
| /// imported block variable. |
| uint64_t BlockOffset; |
| /// BlockAlign - Maximal alignment needed for the Block expressed in bytes. |
| uint64_t BlockAlign; |
| |
| /// getBlockOffset - Allocate an offset for the ValueDecl from a |
| /// BlockDeclRefExpr in a block literal (BlockExpr). |
| uint64_t getBlockOffset(const BlockDeclRefExpr *E); |
| |
| /// BlockHasCopyDispose - True iff the block uses copy/dispose. |
| bool BlockHasCopyDispose; |
| |
| /// BlockDeclRefDecls - Decls from BlockDeclRefExprs in apperance order |
| /// in a block literal. Decls without names are used for padding. |
| llvm::SmallVector<const Expr *, 8> BlockDeclRefDecls; |
| |
| /// BlockDecls - Offsets for all Decls in BlockDeclRefExprs. |
| std::map<const Decl*, uint64_t> BlockDecls; |
| |
| ImplicitParamDecl *BlockStructDecl; |
| ImplicitParamDecl *getBlockStructDecl() { return BlockStructDecl; } |
| |
| llvm::Constant *GenerateCopyHelperFunction(bool, const llvm::StructType *, |
| std::vector<HelperInfo> *); |
| llvm::Constant *GenerateDestroyHelperFunction(bool, const llvm::StructType *, |
| std::vector<HelperInfo> *); |
| |
| llvm::Constant *BuildCopyHelper(const llvm::StructType *, |
| std::vector<HelperInfo> *); |
| 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 *BuildbyrefCopyHelper(const llvm::Type *T, int flag, |
| unsigned Align); |
| llvm::Constant *BuildbyrefDestroyHelper(const llvm::Type *T, int flag, |
| unsigned Align); |
| |
| llvm::Value *getBlockObjectAssign(); |
| llvm::Value *getBlockObjectDispose(); |
| void BuildBlockRelease(llvm::Value *DeclPtr, int flag = BLOCK_FIELD_IS_BYREF); |
| |
| bool BlockRequiresCopying(QualType Ty) { |
| if (Ty->isBlockPointerType()) |
| return true; |
| if (getContext().isObjCNSObjectType(Ty)) |
| return true; |
| if (Ty->isObjCObjectPointerType()) |
| return true; |
| return false; |
| } |
| }; |
| |
| } // end namespace CodeGen |
| } // end namespace clang |
| |
| #endif |