1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | #ifndef LLVM_CLANG_LIB_CODEGEN_CGBLOCKS_H |
14 | #define LLVM_CLANG_LIB_CODEGEN_CGBLOCKS_H |
15 | |
16 | #include "CGBuilder.h" |
17 | #include "CGCall.h" |
18 | #include "CGValue.h" |
19 | #include "CodeGenFunction.h" |
20 | #include "CodeGenTypes.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 | #include "clang/AST/Type.h" |
26 | #include "clang/Basic/TargetInfo.h" |
27 | |
28 | namespace llvm { |
29 | class Constant; |
30 | class Function; |
31 | class GlobalValue; |
32 | class DataLayout; |
33 | class FunctionType; |
34 | class PointerType; |
35 | class Value; |
36 | class LLVMContext; |
37 | } |
38 | |
39 | namespace clang { |
40 | namespace CodeGen { |
41 | |
42 | class CGBlockInfo; |
43 | |
44 | |
45 | enum BlockByrefFlags { |
46 | BLOCK_BYREF_HAS_COPY_DISPOSE = (1 << 25), |
47 | BLOCK_BYREF_LAYOUT_MASK = (0xF << 28), |
48 | BLOCK_BYREF_LAYOUT_EXTENDED = (1 << 28), |
49 | BLOCK_BYREF_LAYOUT_NON_OBJECT = (2 << 28), |
50 | BLOCK_BYREF_LAYOUT_STRONG = (3 << 28), |
51 | BLOCK_BYREF_LAYOUT_WEAK = (4 << 28), |
52 | BLOCK_BYREF_LAYOUT_UNRETAINED = (5 << 28) |
53 | }; |
54 | |
55 | enum BlockLiteralFlags { |
56 | BLOCK_IS_NOESCAPE = (1 << 23), |
57 | BLOCK_HAS_COPY_DISPOSE = (1 << 25), |
58 | BLOCK_HAS_CXX_OBJ = (1 << 26), |
59 | BLOCK_IS_GLOBAL = (1 << 28), |
60 | BLOCK_USE_STRET = (1 << 29), |
61 | BLOCK_HAS_SIGNATURE = (1 << 30), |
62 | BLOCK_HAS_EXTENDED_LAYOUT = (1u << 31) |
63 | }; |
64 | class BlockFlags { |
65 | uint32_t flags; |
66 | |
67 | public: |
68 | BlockFlags(uint32_t flags) : flags(flags) {} |
69 | BlockFlags() : flags(0) {} |
70 | BlockFlags(BlockLiteralFlags flag) : flags(flag) {} |
71 | BlockFlags(BlockByrefFlags flag) : flags(flag) {} |
72 | |
73 | uint32_t getBitMask() const { return flags; } |
74 | bool empty() const { return flags == 0; } |
75 | |
76 | friend BlockFlags operator|(BlockFlags l, BlockFlags r) { |
77 | return BlockFlags(l.flags | r.flags); |
78 | } |
79 | friend BlockFlags &operator|=(BlockFlags &l, BlockFlags r) { |
80 | l.flags |= r.flags; |
81 | return l; |
82 | } |
83 | friend bool operator&(BlockFlags l, BlockFlags r) { |
84 | return (l.flags & r.flags); |
85 | } |
86 | bool operator==(BlockFlags r) { |
87 | return (flags == r.flags); |
88 | } |
89 | }; |
90 | inline BlockFlags operator|(BlockLiteralFlags l, BlockLiteralFlags r) { |
91 | return BlockFlags(l) | BlockFlags(r); |
92 | } |
93 | |
94 | enum BlockFieldFlag_t { |
95 | BLOCK_FIELD_IS_OBJECT = 0x03, |
96 | |
97 | BLOCK_FIELD_IS_BLOCK = 0x07, |
98 | |
99 | BLOCK_FIELD_IS_BYREF = 0x08, |
100 | |
101 | BLOCK_FIELD_IS_WEAK = 0x10, |
102 | |
103 | BLOCK_FIELD_IS_ARC = 0x40, |
104 | BLOCK_BYREF_CALLER = 128, |
105 | |
106 | BLOCK_BYREF_CURRENT_MAX = 256 |
107 | }; |
108 | |
109 | class BlockFieldFlags { |
110 | uint32_t flags; |
111 | |
112 | BlockFieldFlags(uint32_t flags) : flags(flags) {} |
113 | public: |
114 | BlockFieldFlags() : flags(0) {} |
115 | BlockFieldFlags(BlockFieldFlag_t flag) : flags(flag) {} |
116 | |
117 | uint32_t getBitMask() const { return flags; } |
118 | bool empty() const { return flags == 0; } |
119 | |
120 | |
121 | |
122 | bool isSpecialPointer() const { return flags & BLOCK_FIELD_IS_OBJECT; } |
123 | |
124 | friend BlockFieldFlags operator|(BlockFieldFlags l, BlockFieldFlags r) { |
125 | return BlockFieldFlags(l.flags | r.flags); |
126 | } |
127 | friend BlockFieldFlags &operator|=(BlockFieldFlags &l, BlockFieldFlags r) { |
128 | l.flags |= r.flags; |
129 | return l; |
130 | } |
131 | friend bool operator&(BlockFieldFlags l, BlockFieldFlags r) { |
132 | return (l.flags & r.flags); |
133 | } |
134 | bool operator==(BlockFieldFlags Other) const { |
135 | return flags == Other.flags; |
136 | } |
137 | }; |
138 | inline BlockFieldFlags operator|(BlockFieldFlag_t l, BlockFieldFlag_t r) { |
139 | return BlockFieldFlags(l) | BlockFieldFlags(r); |
140 | } |
141 | |
142 | |
143 | class BlockByrefInfo { |
144 | public: |
145 | llvm::StructType *Type; |
146 | unsigned FieldIndex; |
147 | CharUnits ByrefAlignment; |
148 | CharUnits FieldOffset; |
149 | }; |
150 | |
151 | |
152 | class CGBlockInfo { |
153 | public: |
154 | |
155 | StringRef Name; |
156 | |
157 | |
158 | unsigned CXXThisIndex; |
159 | |
160 | class Capture { |
161 | uintptr_t Data; |
162 | EHScopeStack::stable_iterator Cleanup; |
163 | CharUnits::QuantityType Offset; |
164 | |
165 | |
166 | |
167 | |
168 | QualType FieldType; |
169 | |
170 | public: |
171 | bool isIndex() const { return (Data & 1) != 0; } |
172 | bool isConstant() const { return !isIndex(); } |
173 | |
174 | unsigned getIndex() const { |
175 | assert(isIndex()); |
176 | return Data >> 1; |
177 | } |
178 | CharUnits getOffset() const { |
179 | assert(isIndex()); |
180 | return CharUnits::fromQuantity(Offset); |
181 | } |
182 | EHScopeStack::stable_iterator getCleanup() const { |
183 | assert(isIndex()); |
184 | return Cleanup; |
185 | } |
186 | void setCleanup(EHScopeStack::stable_iterator cleanup) { |
187 | assert(isIndex()); |
188 | Cleanup = cleanup; |
189 | } |
190 | |
191 | llvm::Value *getConstant() const { |
192 | assert(isConstant()); |
193 | return reinterpret_cast<llvm::Value*>(Data); |
194 | } |
195 | |
196 | QualType fieldType() const { |
197 | return FieldType; |
198 | } |
199 | |
200 | static Capture makeIndex(unsigned index, CharUnits offset, |
201 | QualType FieldType) { |
202 | Capture v; |
203 | v.Data = (index << 1) | 1; |
204 | v.Offset = offset.getQuantity(); |
205 | v.FieldType = FieldType; |
206 | return v; |
207 | } |
208 | |
209 | static Capture makeConstant(llvm::Value *value) { |
210 | Capture v; |
211 | v.Data = reinterpret_cast<uintptr_t>(value); |
212 | return v; |
213 | } |
214 | }; |
215 | |
216 | |
217 | |
218 | bool CanBeGlobal : 1; |
219 | |
220 | |
221 | |
222 | bool NeedsCopyDispose : 1; |
223 | |
224 | |
225 | |
226 | bool HasCXXObject : 1; |
227 | |
228 | |
229 | |
230 | mutable bool UsesStret : 1; |
231 | |
232 | |
233 | |
234 | bool HasCapturedVariableLayout : 1; |
235 | |
236 | |
237 | |
238 | |
239 | bool CapturesNonExternalType : 1; |
240 | |
241 | |
242 | llvm::DenseMap<const VarDecl*, Capture> Captures; |
243 | |
244 | Address LocalAddress; |
245 | llvm::StructType *StructureType; |
246 | const BlockDecl *Block; |
247 | const BlockExpr *BlockExpression; |
248 | CharUnits BlockSize; |
249 | CharUnits BlockAlign; |
250 | CharUnits CXXThisOffset; |
251 | |
252 | |
253 | |
254 | |
255 | CharUnits ; |
256 | |
257 | |
258 | CharUnits ; |
259 | |
260 | |
261 | |
262 | llvm::Instruction *DominatingIP; |
263 | |
264 | |
265 | |
266 | |
267 | |
268 | CGBlockInfo *NextBlockInfo; |
269 | |
270 | const Capture &getCapture(const VarDecl *var) const { |
271 | return const_cast<CGBlockInfo*>(this)->getCapture(var); |
272 | } |
273 | Capture &getCapture(const VarDecl *var) { |
274 | llvm::DenseMap<const VarDecl*, Capture>::iterator |
275 | it = Captures.find(var); |
276 | (0) . __assert_fail ("it != Captures.end() && \"no entry for variable!\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGBlocks.h", 276, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(it != Captures.end() && "no entry for variable!"); |
277 | return it->second; |
278 | } |
279 | |
280 | const BlockDecl *getBlockDecl() const { return Block; } |
281 | const BlockExpr *getBlockExpr() const { |
282 | assert(BlockExpression); |
283 | getBlockDecl() == Block", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGBlocks.h", 283, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(BlockExpression->getBlockDecl() == Block); |
284 | return BlockExpression; |
285 | } |
286 | |
287 | CGBlockInfo(const BlockDecl *blockDecl, StringRef Name); |
288 | |
289 | |
290 | bool needsCopyDisposeHelpers() const { |
291 | return NeedsCopyDispose && !Block->doesNotEscape(); |
292 | } |
293 | }; |
294 | |
295 | } |
296 | } |
297 | |
298 | #endif |
299 | |