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 "clang/Basic/TargetInfo.h" 21 #include "clang/AST/CharUnits.h" 22 #include "clang/AST/Expr.h" 23 #include "clang/AST/ExprCXX.h" 24 #include "clang/AST/ExprObjC.h" 25 26 #include "CGBuilder.h" 27 #include "CGCall.h" 28 #include "CGValue.h" 29 30 namespace llvm { 31 class Module; 32 class Constant; 33 class Function; 34 class GlobalValue; 35 class TargetData; 36 class FunctionType; 37 class PointerType; 38 class Value; 39 class LLVMContext; 40 } 41 42 namespace clang { 43 44 namespace CodeGen { 45 46 class CodeGenModule; 47 class CGBlockInfo; 48 49 enum BlockFlag_t { 50 BLOCK_HAS_COPY_DISPOSE = (1 << 25), 51 BLOCK_HAS_CXX_OBJ = (1 << 26), 52 BLOCK_IS_GLOBAL = (1 << 28), 53 BLOCK_USE_STRET = (1 << 29), 54 BLOCK_HAS_SIGNATURE = (1 << 30) 55 }; 56 class BlockFlags { 57 uint32_t flags; 58 BlockFlags(uint32_t flags)59 BlockFlags(uint32_t flags) : flags(flags) {} 60 public: BlockFlags()61 BlockFlags() : flags(0) {} BlockFlags(BlockFlag_t flag)62 BlockFlags(BlockFlag_t flag) : flags(flag) {} 63 getBitMask()64 uint32_t getBitMask() const { return flags; } empty()65 bool empty() const { return flags == 0; } 66 67 friend BlockFlags operator|(BlockFlags l, BlockFlags r) { 68 return BlockFlags(l.flags | r.flags); 69 } 70 friend BlockFlags &operator|=(BlockFlags &l, BlockFlags r) { 71 l.flags |= r.flags; 72 return l; 73 } 74 friend bool operator&(BlockFlags l, BlockFlags r) { 75 return (l.flags & r.flags); 76 } 77 }; 78 inline BlockFlags operator|(BlockFlag_t l, BlockFlag_t r) { 79 return BlockFlags(l) | BlockFlags(r); 80 } 81 82 enum BlockFieldFlag_t { 83 BLOCK_FIELD_IS_OBJECT = 0x03, /* id, NSObject, __attribute__((NSObject)), 84 block, ... */ 85 BLOCK_FIELD_IS_BLOCK = 0x07, /* a block variable */ 86 87 BLOCK_FIELD_IS_BYREF = 0x08, /* the on stack structure holding the __block 88 variable */ 89 BLOCK_FIELD_IS_WEAK = 0x10, /* declared __weak, only used in byref copy 90 helpers */ 91 BLOCK_FIELD_IS_ARC = 0x40, /* field has ARC-specific semantics */ 92 BLOCK_BYREF_CALLER = 128, /* called from __block (byref) copy/dispose 93 support routines */ 94 BLOCK_BYREF_CURRENT_MAX = 256 95 }; 96 97 class BlockFieldFlags { 98 uint32_t flags; 99 BlockFieldFlags(uint32_t flags)100 BlockFieldFlags(uint32_t flags) : flags(flags) {} 101 public: BlockFieldFlags()102 BlockFieldFlags() : flags(0) {} BlockFieldFlags(BlockFieldFlag_t flag)103 BlockFieldFlags(BlockFieldFlag_t flag) : flags(flag) {} 104 getBitMask()105 uint32_t getBitMask() const { return flags; } empty()106 bool empty() const { return flags == 0; } 107 108 /// Answers whether the flags indicate that this field is an object 109 /// or block pointer that requires _Block_object_assign/dispose. isSpecialPointer()110 bool isSpecialPointer() const { return flags & BLOCK_FIELD_IS_OBJECT; } 111 112 friend BlockFieldFlags operator|(BlockFieldFlags l, BlockFieldFlags r) { 113 return BlockFieldFlags(l.flags | r.flags); 114 } 115 friend BlockFieldFlags &operator|=(BlockFieldFlags &l, BlockFieldFlags r) { 116 l.flags |= r.flags; 117 return l; 118 } 119 friend bool operator&(BlockFieldFlags l, BlockFieldFlags r) { 120 return (l.flags & r.flags); 121 } 122 }; 123 inline BlockFieldFlags operator|(BlockFieldFlag_t l, BlockFieldFlag_t r) { 124 return BlockFieldFlags(l) | BlockFieldFlags(r); 125 } 126 127 /// CGBlockInfo - Information to generate a block literal. 128 class CGBlockInfo { 129 public: 130 /// Name - The name of the block, kindof. 131 const char *Name; 132 133 /// The field index of 'this' within the block, if there is one. 134 unsigned CXXThisIndex; 135 136 class Capture { 137 uintptr_t Data; 138 139 public: isIndex()140 bool isIndex() const { return (Data & 1) != 0; } isConstant()141 bool isConstant() const { return !isIndex(); } getIndex()142 unsigned getIndex() const { assert(isIndex()); return Data >> 1; } getConstant()143 llvm::Value *getConstant() const { 144 assert(isConstant()); 145 return reinterpret_cast<llvm::Value*>(Data); 146 } 147 makeIndex(unsigned index)148 static Capture makeIndex(unsigned index) { 149 Capture v; 150 v.Data = (index << 1) | 1; 151 return v; 152 } 153 makeConstant(llvm::Value * value)154 static Capture makeConstant(llvm::Value *value) { 155 Capture v; 156 v.Data = reinterpret_cast<uintptr_t>(value); 157 return v; 158 } 159 }; 160 161 /// The mapping of allocated indexes within the block. 162 llvm::DenseMap<const VarDecl*, Capture> Captures; 163 164 /// CanBeGlobal - True if the block can be global, i.e. it has 165 /// no non-constant captures. 166 bool CanBeGlobal : 1; 167 168 /// True if the block needs a custom copy or dispose function. 169 bool NeedsCopyDispose : 1; 170 171 /// HasCXXObject - True if the block's custom copy/dispose functions 172 /// need to be run even in GC mode. 173 bool HasCXXObject : 1; 174 175 /// UsesStret : True if the block uses an stret return. Mutable 176 /// because it gets set later in the block-creation process. 177 mutable bool UsesStret : 1; 178 179 llvm::StructType *StructureType; 180 const BlockExpr *Block; 181 CharUnits BlockSize; 182 CharUnits BlockAlign; 183 getCapture(const VarDecl * var)184 const Capture &getCapture(const VarDecl *var) const { 185 llvm::DenseMap<const VarDecl*, Capture>::const_iterator 186 it = Captures.find(var); 187 assert(it != Captures.end() && "no entry for variable!"); 188 return it->second; 189 } 190 getBlockDecl()191 const BlockDecl *getBlockDecl() const { return Block->getBlockDecl(); } getBlockExpr()192 const BlockExpr *getBlockExpr() const { return Block; } 193 194 CGBlockInfo(const BlockExpr *blockExpr, const char *Name); 195 }; 196 197 } // end namespace CodeGen 198 } // end namespace clang 199 200 #endif 201