//===-- 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/CharUnits.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include #include #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_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 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(); 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; struct { int GlobalUniqueCount; } Block; llvm::Value *BlockObjectAssign; llvm::Value *BlockObjectDispose; const llvm::Type *PtrToInt8Ty; std::map AssignCache; std::map 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), BlockObjectAssign(0), BlockObjectDispose(0) { Block.GlobalUniqueCount = 0; PtrToInt8Ty = llvm::Type::getInt8PtrTy(M.getContext()); } bool BlockRequiresCopying(QualType Ty) { return getContext().BlockRequiresCopying(Ty); } }; 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 DeclRefs; 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. CharUnits BlockOffset; /// BlockAlign - Maximal alignment needed for the Block expressed in /// characters. CharUnits BlockAlign; /// getBlockOffset - Allocate an offset for the ValueDecl from a /// BlockDeclRefExpr in a block literal (BlockExpr). CharUnits 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 BlockDeclRefDecls; /// BlockDecls - Offsets for all Decls in BlockDeclRefExprs. std::map BlockDecls; ImplicitParamDecl *BlockStructDecl; ImplicitParamDecl *getBlockStructDecl() { return BlockStructDecl; } llvm::Constant *GenerateCopyHelperFunction(bool, const llvm::StructType *, std::vector *); llvm::Constant *GenerateDestroyHelperFunction(bool, const llvm::StructType *, std::vector *); llvm::Constant *BuildCopyHelper(const llvm::StructType *, std::vector *); llvm::Constant *BuildDestroyHelper(const llvm::StructType *, std::vector *); 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) { return getContext().BlockRequiresCopying(Ty); } }; } // end namespace CodeGen } // end namespace clang #endif