xref: /minix3/external/bsd/llvm/dist/clang/lib/CodeGen/CGBlocks.h (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1f4a2713aSLionel Sambuc //===-- CGBlocks.h - state for LLVM CodeGen for blocks ----------*- C++ -*-===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // This is the internal state used for llvm translation for block literals.
11f4a2713aSLionel Sambuc //
12f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
13f4a2713aSLionel Sambuc 
14*0a6a1f1dSLionel Sambuc #ifndef LLVM_CLANG_LIB_CODEGEN_CGBLOCKS_H
15*0a6a1f1dSLionel Sambuc #define LLVM_CLANG_LIB_CODEGEN_CGBLOCKS_H
16f4a2713aSLionel Sambuc 
17f4a2713aSLionel Sambuc #include "CGBuilder.h"
18f4a2713aSLionel Sambuc #include "CGCall.h"
19f4a2713aSLionel Sambuc #include "CGValue.h"
20f4a2713aSLionel Sambuc #include "CodeGenFunction.h"
21f4a2713aSLionel Sambuc #include "CodeGenTypes.h"
22f4a2713aSLionel Sambuc #include "clang/AST/CharUnits.h"
23f4a2713aSLionel Sambuc #include "clang/AST/Expr.h"
24f4a2713aSLionel Sambuc #include "clang/AST/ExprCXX.h"
25f4a2713aSLionel Sambuc #include "clang/AST/ExprObjC.h"
26f4a2713aSLionel Sambuc #include "clang/AST/Type.h"
27f4a2713aSLionel Sambuc #include "clang/Basic/TargetInfo.h"
28f4a2713aSLionel Sambuc #include "llvm/IR/Module.h"
29f4a2713aSLionel Sambuc 
30f4a2713aSLionel Sambuc namespace llvm {
31f4a2713aSLionel Sambuc class Module;
32f4a2713aSLionel Sambuc class Constant;
33f4a2713aSLionel Sambuc class Function;
34f4a2713aSLionel Sambuc class GlobalValue;
35f4a2713aSLionel Sambuc class DataLayout;
36f4a2713aSLionel Sambuc class FunctionType;
37f4a2713aSLionel Sambuc class PointerType;
38f4a2713aSLionel Sambuc class Value;
39f4a2713aSLionel Sambuc class LLVMContext;
40f4a2713aSLionel Sambuc }
41f4a2713aSLionel Sambuc 
42f4a2713aSLionel Sambuc namespace clang {
43f4a2713aSLionel Sambuc 
44f4a2713aSLionel Sambuc namespace CodeGen {
45f4a2713aSLionel Sambuc 
46f4a2713aSLionel Sambuc class CodeGenModule;
47f4a2713aSLionel Sambuc class CGBlockInfo;
48f4a2713aSLionel Sambuc 
49f4a2713aSLionel Sambuc // Flags stored in __block variables.
50f4a2713aSLionel Sambuc enum BlockByrefFlags {
51f4a2713aSLionel Sambuc   BLOCK_BYREF_HAS_COPY_DISPOSE         = (1   << 25), // compiler
52f4a2713aSLionel Sambuc   BLOCK_BYREF_LAYOUT_MASK              = (0xF << 28), // compiler
53f4a2713aSLionel Sambuc   BLOCK_BYREF_LAYOUT_EXTENDED          = (1   << 28),
54f4a2713aSLionel Sambuc   BLOCK_BYREF_LAYOUT_NON_OBJECT        = (2   << 28),
55f4a2713aSLionel Sambuc   BLOCK_BYREF_LAYOUT_STRONG            = (3   << 28),
56f4a2713aSLionel Sambuc   BLOCK_BYREF_LAYOUT_WEAK              = (4   << 28),
57f4a2713aSLionel Sambuc   BLOCK_BYREF_LAYOUT_UNRETAINED        = (5   << 28)
58f4a2713aSLionel Sambuc };
59f4a2713aSLionel Sambuc 
60f4a2713aSLionel Sambuc enum BlockLiteralFlags {
61f4a2713aSLionel Sambuc   BLOCK_HAS_COPY_DISPOSE =  (1 << 25),
62f4a2713aSLionel Sambuc   BLOCK_HAS_CXX_OBJ =       (1 << 26),
63f4a2713aSLionel Sambuc   BLOCK_IS_GLOBAL =         (1 << 28),
64f4a2713aSLionel Sambuc   BLOCK_USE_STRET =         (1 << 29),
65f4a2713aSLionel Sambuc   BLOCK_HAS_SIGNATURE  =    (1 << 30),
66f4a2713aSLionel Sambuc   BLOCK_HAS_EXTENDED_LAYOUT = (1 << 31)
67f4a2713aSLionel Sambuc };
68f4a2713aSLionel Sambuc class BlockFlags {
69f4a2713aSLionel Sambuc   uint32_t flags;
70f4a2713aSLionel Sambuc 
71f4a2713aSLionel Sambuc public:
BlockFlags(uint32_t flags)72f4a2713aSLionel Sambuc   BlockFlags(uint32_t flags) : flags(flags) {}
BlockFlags()73f4a2713aSLionel Sambuc   BlockFlags() : flags(0) {}
BlockFlags(BlockLiteralFlags flag)74f4a2713aSLionel Sambuc   BlockFlags(BlockLiteralFlags flag) : flags(flag) {}
BlockFlags(BlockByrefFlags flag)75f4a2713aSLionel Sambuc   BlockFlags(BlockByrefFlags flag) : flags(flag) {}
76f4a2713aSLionel Sambuc 
getBitMask()77f4a2713aSLionel Sambuc   uint32_t getBitMask() const { return flags; }
empty()78f4a2713aSLionel Sambuc   bool empty() const { return flags == 0; }
79f4a2713aSLionel Sambuc 
80f4a2713aSLionel Sambuc   friend BlockFlags operator|(BlockFlags l, BlockFlags r) {
81f4a2713aSLionel Sambuc     return BlockFlags(l.flags | r.flags);
82f4a2713aSLionel Sambuc   }
83f4a2713aSLionel Sambuc   friend BlockFlags &operator|=(BlockFlags &l, BlockFlags r) {
84f4a2713aSLionel Sambuc     l.flags |= r.flags;
85f4a2713aSLionel Sambuc     return l;
86f4a2713aSLionel Sambuc   }
87f4a2713aSLionel Sambuc   friend bool operator&(BlockFlags l, BlockFlags r) {
88f4a2713aSLionel Sambuc     return (l.flags & r.flags);
89f4a2713aSLionel Sambuc   }
90f4a2713aSLionel Sambuc   bool operator==(BlockFlags r) {
91f4a2713aSLionel Sambuc     return (flags == r.flags);
92f4a2713aSLionel Sambuc   }
93f4a2713aSLionel Sambuc };
94f4a2713aSLionel Sambuc inline BlockFlags operator|(BlockLiteralFlags l, BlockLiteralFlags r) {
95f4a2713aSLionel Sambuc   return BlockFlags(l) | BlockFlags(r);
96f4a2713aSLionel Sambuc }
97f4a2713aSLionel Sambuc 
98f4a2713aSLionel Sambuc enum BlockFieldFlag_t {
99f4a2713aSLionel Sambuc   BLOCK_FIELD_IS_OBJECT   = 0x03,  /* id, NSObject, __attribute__((NSObject)),
100f4a2713aSLionel Sambuc                                     block, ... */
101f4a2713aSLionel Sambuc   BLOCK_FIELD_IS_BLOCK    = 0x07,  /* a block variable */
102f4a2713aSLionel Sambuc 
103f4a2713aSLionel Sambuc   BLOCK_FIELD_IS_BYREF    = 0x08,  /* the on stack structure holding the __block
104f4a2713aSLionel Sambuc                                     variable */
105f4a2713aSLionel Sambuc   BLOCK_FIELD_IS_WEAK     = 0x10,  /* declared __weak, only used in byref copy
106f4a2713aSLionel Sambuc                                     helpers */
107f4a2713aSLionel Sambuc   BLOCK_FIELD_IS_ARC      = 0x40,  /* field has ARC-specific semantics */
108f4a2713aSLionel Sambuc   BLOCK_BYREF_CALLER      = 128,   /* called from __block (byref) copy/dispose
109f4a2713aSLionel Sambuc                                       support routines */
110f4a2713aSLionel Sambuc   BLOCK_BYREF_CURRENT_MAX = 256
111f4a2713aSLionel Sambuc };
112f4a2713aSLionel Sambuc 
113f4a2713aSLionel Sambuc class BlockFieldFlags {
114f4a2713aSLionel Sambuc   uint32_t flags;
115f4a2713aSLionel Sambuc 
BlockFieldFlags(uint32_t flags)116f4a2713aSLionel Sambuc   BlockFieldFlags(uint32_t flags) : flags(flags) {}
117f4a2713aSLionel Sambuc public:
BlockFieldFlags()118f4a2713aSLionel Sambuc   BlockFieldFlags() : flags(0) {}
BlockFieldFlags(BlockFieldFlag_t flag)119f4a2713aSLionel Sambuc   BlockFieldFlags(BlockFieldFlag_t flag) : flags(flag) {}
120f4a2713aSLionel Sambuc 
getBitMask()121f4a2713aSLionel Sambuc   uint32_t getBitMask() const { return flags; }
empty()122f4a2713aSLionel Sambuc   bool empty() const { return flags == 0; }
123f4a2713aSLionel Sambuc 
124f4a2713aSLionel Sambuc   /// Answers whether the flags indicate that this field is an object
125f4a2713aSLionel Sambuc   /// or block pointer that requires _Block_object_assign/dispose.
isSpecialPointer()126f4a2713aSLionel Sambuc   bool isSpecialPointer() const { return flags & BLOCK_FIELD_IS_OBJECT; }
127f4a2713aSLionel Sambuc 
128f4a2713aSLionel Sambuc   friend BlockFieldFlags operator|(BlockFieldFlags l, BlockFieldFlags r) {
129f4a2713aSLionel Sambuc     return BlockFieldFlags(l.flags | r.flags);
130f4a2713aSLionel Sambuc   }
131f4a2713aSLionel Sambuc   friend BlockFieldFlags &operator|=(BlockFieldFlags &l, BlockFieldFlags r) {
132f4a2713aSLionel Sambuc     l.flags |= r.flags;
133f4a2713aSLionel Sambuc     return l;
134f4a2713aSLionel Sambuc   }
135f4a2713aSLionel Sambuc   friend bool operator&(BlockFieldFlags l, BlockFieldFlags r) {
136f4a2713aSLionel Sambuc     return (l.flags & r.flags);
137f4a2713aSLionel Sambuc   }
138f4a2713aSLionel Sambuc };
139f4a2713aSLionel Sambuc inline BlockFieldFlags operator|(BlockFieldFlag_t l, BlockFieldFlag_t r) {
140f4a2713aSLionel Sambuc   return BlockFieldFlags(l) | BlockFieldFlags(r);
141f4a2713aSLionel Sambuc }
142f4a2713aSLionel Sambuc 
143f4a2713aSLionel Sambuc /// CGBlockInfo - Information to generate a block literal.
144f4a2713aSLionel Sambuc class CGBlockInfo {
145f4a2713aSLionel Sambuc public:
146f4a2713aSLionel Sambuc   /// Name - The name of the block, kindof.
147f4a2713aSLionel Sambuc   StringRef Name;
148f4a2713aSLionel Sambuc 
149f4a2713aSLionel Sambuc   /// The field index of 'this' within the block, if there is one.
150f4a2713aSLionel Sambuc   unsigned CXXThisIndex;
151f4a2713aSLionel Sambuc 
152f4a2713aSLionel Sambuc   class Capture {
153f4a2713aSLionel Sambuc     uintptr_t Data;
154f4a2713aSLionel Sambuc     EHScopeStack::stable_iterator Cleanup;
155f4a2713aSLionel Sambuc 
156f4a2713aSLionel Sambuc   public:
isIndex()157f4a2713aSLionel Sambuc     bool isIndex() const { return (Data & 1) != 0; }
isConstant()158f4a2713aSLionel Sambuc     bool isConstant() const { return !isIndex(); }
getIndex()159f4a2713aSLionel Sambuc     unsigned getIndex() const { assert(isIndex()); return Data >> 1; }
getConstant()160f4a2713aSLionel Sambuc     llvm::Value *getConstant() const {
161f4a2713aSLionel Sambuc       assert(isConstant());
162f4a2713aSLionel Sambuc       return reinterpret_cast<llvm::Value*>(Data);
163f4a2713aSLionel Sambuc     }
getCleanup()164f4a2713aSLionel Sambuc     EHScopeStack::stable_iterator getCleanup() const {
165f4a2713aSLionel Sambuc       assert(isIndex());
166f4a2713aSLionel Sambuc       return Cleanup;
167f4a2713aSLionel Sambuc     }
setCleanup(EHScopeStack::stable_iterator cleanup)168f4a2713aSLionel Sambuc     void setCleanup(EHScopeStack::stable_iterator cleanup) {
169f4a2713aSLionel Sambuc       assert(isIndex());
170f4a2713aSLionel Sambuc       Cleanup = cleanup;
171f4a2713aSLionel Sambuc     }
172f4a2713aSLionel Sambuc 
makeIndex(unsigned index)173f4a2713aSLionel Sambuc     static Capture makeIndex(unsigned index) {
174f4a2713aSLionel Sambuc       Capture v;
175f4a2713aSLionel Sambuc       v.Data = (index << 1) | 1;
176f4a2713aSLionel Sambuc       return v;
177f4a2713aSLionel Sambuc     }
178f4a2713aSLionel Sambuc 
makeConstant(llvm::Value * value)179f4a2713aSLionel Sambuc     static Capture makeConstant(llvm::Value *value) {
180f4a2713aSLionel Sambuc       Capture v;
181f4a2713aSLionel Sambuc       v.Data = reinterpret_cast<uintptr_t>(value);
182f4a2713aSLionel Sambuc       return v;
183f4a2713aSLionel Sambuc     }
184f4a2713aSLionel Sambuc   };
185f4a2713aSLionel Sambuc 
186f4a2713aSLionel Sambuc   /// CanBeGlobal - True if the block can be global, i.e. it has
187f4a2713aSLionel Sambuc   /// no non-constant captures.
188f4a2713aSLionel Sambuc   bool CanBeGlobal : 1;
189f4a2713aSLionel Sambuc 
190f4a2713aSLionel Sambuc   /// True if the block needs a custom copy or dispose function.
191f4a2713aSLionel Sambuc   bool NeedsCopyDispose : 1;
192f4a2713aSLionel Sambuc 
193f4a2713aSLionel Sambuc   /// HasCXXObject - True if the block's custom copy/dispose functions
194f4a2713aSLionel Sambuc   /// need to be run even in GC mode.
195f4a2713aSLionel Sambuc   bool HasCXXObject : 1;
196f4a2713aSLionel Sambuc 
197f4a2713aSLionel Sambuc   /// UsesStret : True if the block uses an stret return.  Mutable
198f4a2713aSLionel Sambuc   /// because it gets set later in the block-creation process.
199f4a2713aSLionel Sambuc   mutable bool UsesStret : 1;
200f4a2713aSLionel Sambuc 
201f4a2713aSLionel Sambuc   /// HasCapturedVariableLayout : True if block has captured variables
202f4a2713aSLionel Sambuc   /// and their layout meta-data has been generated.
203f4a2713aSLionel Sambuc   bool HasCapturedVariableLayout : 1;
204f4a2713aSLionel Sambuc 
205f4a2713aSLionel Sambuc   /// The mapping of allocated indexes within the block.
206f4a2713aSLionel Sambuc   llvm::DenseMap<const VarDecl*, Capture> Captures;
207f4a2713aSLionel Sambuc 
208f4a2713aSLionel Sambuc   llvm::AllocaInst *Address;
209f4a2713aSLionel Sambuc   llvm::StructType *StructureType;
210f4a2713aSLionel Sambuc   const BlockDecl *Block;
211f4a2713aSLionel Sambuc   const BlockExpr *BlockExpression;
212f4a2713aSLionel Sambuc   CharUnits BlockSize;
213f4a2713aSLionel Sambuc   CharUnits BlockAlign;
214f4a2713aSLionel Sambuc 
215f4a2713aSLionel Sambuc   // Offset of the gap caused by block header having a smaller
216f4a2713aSLionel Sambuc   // alignment than the alignment of the block descriptor. This
217f4a2713aSLionel Sambuc   // is the gap offset before the first capturued field.
218f4a2713aSLionel Sambuc   CharUnits BlockHeaderForcedGapOffset;
219f4a2713aSLionel Sambuc   // Gap size caused by aligning first field after block header.
220f4a2713aSLionel Sambuc   // This could be zero if no forced alignment is required.
221f4a2713aSLionel Sambuc   CharUnits BlockHeaderForcedGapSize;
222f4a2713aSLionel Sambuc 
223f4a2713aSLionel Sambuc   /// An instruction which dominates the full-expression that the
224f4a2713aSLionel Sambuc   /// block is inside.
225f4a2713aSLionel Sambuc   llvm::Instruction *DominatingIP;
226f4a2713aSLionel Sambuc 
227f4a2713aSLionel Sambuc   /// The next block in the block-info chain.  Invalid if this block
228f4a2713aSLionel Sambuc   /// info is not part of the CGF's block-info chain, which is true
229f4a2713aSLionel Sambuc   /// if it corresponds to a global block or a block whose expression
230f4a2713aSLionel Sambuc   /// has been encountered.
231f4a2713aSLionel Sambuc   CGBlockInfo *NextBlockInfo;
232f4a2713aSLionel Sambuc 
getCapture(const VarDecl * var)233f4a2713aSLionel Sambuc   const Capture &getCapture(const VarDecl *var) const {
234f4a2713aSLionel Sambuc     return const_cast<CGBlockInfo*>(this)->getCapture(var);
235f4a2713aSLionel Sambuc   }
getCapture(const VarDecl * var)236f4a2713aSLionel Sambuc   Capture &getCapture(const VarDecl *var) {
237f4a2713aSLionel Sambuc     llvm::DenseMap<const VarDecl*, Capture>::iterator
238f4a2713aSLionel Sambuc       it = Captures.find(var);
239f4a2713aSLionel Sambuc     assert(it != Captures.end() && "no entry for variable!");
240f4a2713aSLionel Sambuc     return it->second;
241f4a2713aSLionel Sambuc   }
242f4a2713aSLionel Sambuc 
getBlockDecl()243f4a2713aSLionel Sambuc   const BlockDecl *getBlockDecl() const { return Block; }
getBlockExpr()244f4a2713aSLionel Sambuc   const BlockExpr *getBlockExpr() const {
245f4a2713aSLionel Sambuc     assert(BlockExpression);
246f4a2713aSLionel Sambuc     assert(BlockExpression->getBlockDecl() == Block);
247f4a2713aSLionel Sambuc     return BlockExpression;
248f4a2713aSLionel Sambuc   }
249f4a2713aSLionel Sambuc 
250f4a2713aSLionel Sambuc   CGBlockInfo(const BlockDecl *blockDecl, StringRef Name);
251f4a2713aSLionel Sambuc };
252f4a2713aSLionel Sambuc 
253f4a2713aSLionel Sambuc }  // end namespace CodeGen
254f4a2713aSLionel Sambuc }  // end namespace clang
255f4a2713aSLionel Sambuc 
256f4a2713aSLionel Sambuc #endif
257