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