CGBlocks.h revision 39605b4eab472a37cec287f9d4663805e60346f3
1//===-- CGBlocks.h - state for LLVM CodeGen for blocks ----------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This is the internal state used for llvm translation for block literals. 11// 12//===----------------------------------------------------------------------===// 13 14#ifndef CLANG_CODEGEN_CGBLOCKS_H 15#define CLANG_CODEGEN_CGBLOCKS_H 16 17#include "CodeGenTypes.h" 18#include "clang/AST/Type.h" 19#include "llvm/Module.h" 20#include "llvm/ADT/DenseMap.h" 21#include "llvm/ADT/SmallVector.h" 22#include "clang/Basic/TargetInfo.h" 23#include "clang/AST/Expr.h" 24#include "clang/AST/ExprCXX.h" 25#include "clang/AST/ExprObjC.h" 26 27#include <vector> 28#include <map> 29 30#include "CGBuilder.h" 31#include "CGCall.h" 32#include "CGValue.h" 33 34namespace llvm { 35 class Module; 36 class Constant; 37 class Function; 38 class GlobalValue; 39 class TargetData; 40 class FunctionType; 41 class Value; 42 class LLVMContext; 43} 44 45namespace clang { 46 47namespace CodeGen { 48class CodeGenModule; 49 50class BlockBase { 51public: 52 enum { 53 BLOCK_NEEDS_FREE = (1 << 24), 54 BLOCK_HAS_COPY_DISPOSE = (1 << 25), 55 BLOCK_HAS_CXX_OBJ = (1 << 26), 56 BLOCK_IS_GC = (1 << 27), 57 BLOCK_IS_GLOBAL = (1 << 28), 58 BLOCK_HAS_DESCRIPTOR = (1 << 29) 59 }; 60}; 61 62class BlockModule : public BlockBase { 63 ASTContext &Context; 64 llvm::Module &TheModule; 65 const llvm::TargetData &TheTargetData; 66 CodeGenTypes &Types; 67 CodeGenModule &CGM; 68 llvm::LLVMContext &VMContext; 69 70 ASTContext &getContext() const { return Context; } 71 llvm::Module &getModule() const { return TheModule; } 72 CodeGenTypes &getTypes() { return Types; } 73 const llvm::TargetData &getTargetData() const { return TheTargetData; } 74public: 75 llvm::Constant *getNSConcreteGlobalBlock(); 76 llvm::Constant *getNSConcreteStackBlock(); 77 int getGlobalUniqueCount() { return ++Block.GlobalUniqueCount; } 78 const llvm::Type *getBlockDescriptorType(); 79 80 const llvm::Type *getGenericBlockLiteralType(); 81 const llvm::Type *getGenericExtendedBlockLiteralType(); 82 83 llvm::Constant *GetAddrOfGlobalBlock(const BlockExpr *BE, const char *); 84 85 /// NSConcreteGlobalBlock - Cached reference to the class pointer for global 86 /// blocks. 87 llvm::Constant *NSConcreteGlobalBlock; 88 89 /// NSConcreteStackBlock - Cached reference to the class poinnter for stack 90 /// blocks. 91 llvm::Constant *NSConcreteStackBlock; 92 93 const llvm::Type *BlockDescriptorType; 94 const llvm::Type *GenericBlockLiteralType; 95 const llvm::Type *GenericExtendedBlockLiteralType; 96 struct { 97 int GlobalUniqueCount; 98 } Block; 99 100 llvm::Value *BlockObjectAssign; 101 llvm::Value *BlockObjectDispose; 102 const llvm::Type *PtrToInt8Ty; 103 104 std::map<uint64_t, llvm::Constant *> AssignCache; 105 std::map<uint64_t, llvm::Constant *> DestroyCache; 106 107 BlockModule(ASTContext &C, llvm::Module &M, const llvm::TargetData &TD, 108 CodeGenTypes &T, CodeGenModule &CodeGen) 109 : Context(C), TheModule(M), TheTargetData(TD), Types(T), 110 CGM(CodeGen), VMContext(M.getContext()), 111 NSConcreteGlobalBlock(0), NSConcreteStackBlock(0), BlockDescriptorType(0), 112 GenericBlockLiteralType(0), GenericExtendedBlockLiteralType(0), 113 BlockObjectAssign(0), BlockObjectDispose(0) { 114 Block.GlobalUniqueCount = 0; 115 PtrToInt8Ty = llvm::PointerType::getUnqual( 116 llvm::Type::getInt8Ty(M.getContext())); 117 } 118 119 bool BlockRequiresCopying(QualType Ty) { 120 if (Ty->isBlockPointerType()) 121 return true; 122 if (getContext().isObjCNSObjectType(Ty)) 123 return true; 124 if (Ty->isObjCObjectPointerType()) 125 return true; 126 return false; 127 } 128}; 129 130class BlockFunction : public BlockBase { 131 CodeGenModule &CGM; 132 CodeGenFunction &CGF; 133 ASTContext &getContext() const; 134 135protected: 136 llvm::LLVMContext &VMContext; 137 138public: 139 const llvm::Type *PtrToInt8Ty; 140 struct HelperInfo { 141 int index; 142 int flag; 143 bool RequiresCopying; 144 }; 145 146 enum { 147 BLOCK_FIELD_IS_OBJECT = 3, /* id, NSObject, __attribute__((NSObject)), 148 block, ... */ 149 BLOCK_FIELD_IS_BLOCK = 7, /* a block variable */ 150 BLOCK_FIELD_IS_BYREF = 8, /* the on stack structure holding the __block 151 variable */ 152 BLOCK_FIELD_IS_WEAK = 16, /* declared __weak, only used in byref copy 153 helpers */ 154 BLOCK_BYREF_CALLER = 128, /* called from __block (byref) copy/dispose 155 support routines */ 156 BLOCK_BYREF_CURRENT_MAX = 256 157 }; 158 159 /// BlockInfo - Information to generate a block literal. 160 struct BlockInfo { 161 /// BlockLiteralTy - The type of the block literal. 162 const llvm::Type *BlockLiteralTy; 163 164 /// Name - the name of the function this block was created for, if any. 165 const char *Name; 166 167 /// ByCopyDeclRefs - Variables from parent scopes that have been imported 168 /// into this block. 169 llvm::SmallVector<const BlockDeclRefExpr *, 8> ByCopyDeclRefs; 170 171 // ByRefDeclRefs - __block variables from parent scopes that have been 172 // imported into this block. 173 llvm::SmallVector<const BlockDeclRefExpr *, 8> ByRefDeclRefs; 174 175 BlockInfo(const llvm::Type *blt, const char *n) 176 : BlockLiteralTy(blt), Name(n) { 177 // Skip asm prefix, if any. 178 if (Name && Name[0] == '\01') 179 ++Name; 180 } 181 }; 182 183 CGBuilderTy &Builder; 184 185 BlockFunction(CodeGenModule &cgm, CodeGenFunction &cgf, CGBuilderTy &B); 186 187 /// BlockOffset - The offset in bytes for the next allocation of an 188 /// imported block variable. 189 uint64_t BlockOffset; 190 /// BlockAlign - Maximal alignment needed for the Block expressed in bytes. 191 uint64_t BlockAlign; 192 193 /// getBlockOffset - Allocate an offset for the ValueDecl from a 194 /// BlockDeclRefExpr in a block literal (BlockExpr). 195 uint64_t getBlockOffset(const BlockDeclRefExpr *E); 196 197 /// BlockHasCopyDispose - True iff the block uses copy/dispose. 198 bool BlockHasCopyDispose; 199 200 /// BlockDeclRefDecls - Decls from BlockDeclRefExprs in apperance order 201 /// in a block literal. Decls without names are used for padding. 202 llvm::SmallVector<const Expr *, 8> BlockDeclRefDecls; 203 204 /// BlockDecls - Offsets for all Decls in BlockDeclRefExprs. 205 std::map<const Decl*, uint64_t> BlockDecls; 206 207 ImplicitParamDecl *BlockStructDecl; 208 ImplicitParamDecl *getBlockStructDecl() { return BlockStructDecl; } 209 210 llvm::Constant *GenerateCopyHelperFunction(bool, const llvm::StructType *, 211 std::vector<HelperInfo> *); 212 llvm::Constant *GenerateDestroyHelperFunction(bool, const llvm::StructType *, 213 std::vector<HelperInfo> *); 214 215 llvm::Constant *BuildCopyHelper(const llvm::StructType *, 216 std::vector<HelperInfo> *); 217 llvm::Constant *BuildDestroyHelper(const llvm::StructType *, 218 std::vector<HelperInfo> *); 219 220 llvm::Constant *GeneratebyrefCopyHelperFunction(const llvm::Type *, int flag); 221 llvm::Constant *GeneratebyrefDestroyHelperFunction(const llvm::Type *T, int); 222 223 llvm::Constant *BuildbyrefCopyHelper(const llvm::Type *T, int flag, 224 unsigned Align); 225 llvm::Constant *BuildbyrefDestroyHelper(const llvm::Type *T, int flag, 226 unsigned Align); 227 228 llvm::Value *getBlockObjectAssign(); 229 llvm::Value *getBlockObjectDispose(); 230 void BuildBlockRelease(llvm::Value *DeclPtr, int flag = BLOCK_FIELD_IS_BYREF); 231 232 bool BlockRequiresCopying(QualType Ty); 233}; 234 235} // end namespace CodeGen 236} // end namespace clang 237 238#endif 239