[SYCL] AST support for SYCL kernel entry point functions. (#122379)
[llvm-project.git] / clang / unittests / AST / ByteCode / Descriptor.cpp
blobb3517d8731c85b96c9ed0f471a80d407d65a435e
1 #include "../../../lib/AST/ByteCode/Descriptor.h"
2 #include "../../../lib/AST/ByteCode/Context.h"
3 #include "../../../lib/AST/ByteCode/Program.h"
4 #include "clang/AST/ASTContext.h"
5 #include "clang/AST/Decl.h"
6 #include "clang/ASTMatchers/ASTMatchFinder.h"
7 #include "clang/ASTMatchers/ASTMatchers.h"
8 #include "clang/Tooling/Tooling.h"
9 #include "gtest/gtest.h"
11 using namespace clang;
12 using namespace clang::interp;
13 using namespace clang::ast_matchers;
15 /// Inspect generated Descriptors as well as the pointers we create.
16 ///
17 TEST(Descriptor, Primitives) {
18 constexpr char Code[] = "struct A { bool a; bool b; };\n"
19 "struct S {\n"
20 " float f;\n"
21 " char s[4];\n"
22 " A a[3];\n"
23 " short l[3][3];\n"
24 " int EmptyA[0];\n"
25 "};\n"
26 "constexpr S d = {0.0, \"foo\", {{true, false}, "
27 "{false, true}, {false, false}},\n"
28 " {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, {}};\n";
30 auto AST = tooling::buildASTFromCodeWithArgs(
31 Code, {"-fexperimental-new-constant-interpreter"});
33 const VarDecl *D = selectFirst<VarDecl>(
34 "d", match(varDecl().bind("d"), AST->getASTContext()));
35 ASSERT_NE(D, nullptr);
37 const auto &Ctx = AST->getASTContext().getInterpContext();
38 Program &Prog = Ctx.getProgram();
39 // Global is registered.
40 ASSERT_TRUE(Prog.getGlobal(D));
42 // Get a Pointer to the global.
43 const Pointer &GlobalPtr = Prog.getPtrGlobal(*Prog.getGlobal(D));
45 // Test Descriptor of the struct S.
46 const Descriptor *GlobalDesc = GlobalPtr.getFieldDesc();
47 ASSERT_TRUE(GlobalDesc == GlobalPtr.getDeclDesc());
49 ASSERT_TRUE(GlobalDesc->asDecl() == D);
50 ASSERT_FALSE(GlobalDesc->asExpr());
51 ASSERT_TRUE(GlobalDesc->asValueDecl() == D);
52 ASSERT_FALSE(GlobalDesc->asFieldDecl());
53 ASSERT_FALSE(GlobalDesc->asRecordDecl());
55 // Still true because this is a global variable.
56 ASSERT_TRUE(GlobalDesc->getMetadataSize() == sizeof(GlobalInlineDescriptor));
57 ASSERT_FALSE(GlobalDesc->isPrimitiveArray());
58 ASSERT_FALSE(GlobalDesc->isCompositeArray());
59 ASSERT_FALSE(GlobalDesc->isZeroSizeArray());
60 ASSERT_FALSE(GlobalDesc->isUnknownSizeArray());
61 ASSERT_FALSE(GlobalDesc->isPrimitive());
62 ASSERT_FALSE(GlobalDesc->isArray());
63 ASSERT_TRUE(GlobalDesc->isRecord());
65 // Test the Record for the struct S.
66 const Record *SRecord = GlobalDesc->ElemRecord;
67 ASSERT_TRUE(SRecord);
68 ASSERT_TRUE(SRecord->getNumFields() == 5);
69 ASSERT_TRUE(SRecord->getNumBases() == 0);
70 ASSERT_FALSE(SRecord->getDestructor());
72 // First field.
73 const Record::Field *F1 = SRecord->getField(0u);
74 ASSERT_TRUE(F1);
75 ASSERT_FALSE(F1->isBitField());
76 ASSERT_TRUE(F1->Desc->isPrimitive());
78 // Second field.
79 const Record::Field *F2 = SRecord->getField(1u);
80 ASSERT_TRUE(F2);
81 ASSERT_FALSE(F2->isBitField());
82 ASSERT_TRUE(F2->Desc->isArray());
83 ASSERT_FALSE(F2->Desc->isCompositeArray());
84 ASSERT_TRUE(F2->Desc->isPrimitiveArray());
85 ASSERT_FALSE(F2->Desc->isPrimitive());
86 ASSERT_FALSE(F2->Desc->ElemDesc);
87 ASSERT_EQ(F2->Desc->getNumElems(), 4u);
88 ASSERT_TRUE(F2->Desc->getElemSize() > 0);
90 // Third field.
91 const Record::Field *F3 = SRecord->getField(2u);
92 ASSERT_TRUE(F3);
93 ASSERT_FALSE(F3->isBitField());
94 ASSERT_TRUE(F3->Desc->isArray());
95 ASSERT_TRUE(F3->Desc->isCompositeArray());
96 ASSERT_FALSE(F3->Desc->isPrimitiveArray());
97 ASSERT_FALSE(F3->Desc->isPrimitive());
98 ASSERT_TRUE(F3->Desc->ElemDesc);
99 ASSERT_EQ(F3->Desc->getNumElems(), 3u);
100 ASSERT_TRUE(F3->Desc->getElemSize() > 0);
102 // Fourth field.
103 // Multidimensional arrays are treated as composite arrays, even
104 // if the value type is primitive.
105 const Record::Field *F4 = SRecord->getField(3u);
106 ASSERT_TRUE(F4);
107 ASSERT_FALSE(F4->isBitField());
108 ASSERT_TRUE(F4->Desc->isArray());
109 ASSERT_TRUE(F4->Desc->isCompositeArray());
110 ASSERT_FALSE(F4->Desc->isPrimitiveArray());
111 ASSERT_FALSE(F4->Desc->isPrimitive());
112 ASSERT_TRUE(F4->Desc->ElemDesc);
113 ASSERT_EQ(F4->Desc->getNumElems(), 3u);
114 ASSERT_TRUE(F4->Desc->getElemSize() > 0);
115 ASSERT_TRUE(F4->Desc->ElemDesc->isPrimitiveArray());
117 // Fifth field. Zero-size array.
118 const Record::Field *F5 = SRecord->getField(4u);
119 ASSERT_TRUE(F5);
120 ASSERT_FALSE(F5->isBitField());
121 ASSERT_TRUE(F5->Desc->isArray());
122 ASSERT_FALSE(F5->Desc->isCompositeArray());
123 ASSERT_TRUE(F5->Desc->isPrimitiveArray());
124 ASSERT_FALSE(F5->Desc->isPrimitive());
125 ASSERT_EQ(F5->Desc->getNumElems(), 0u);
127 // Check pointer stuff.
128 // Global variables have an inline descriptor.
129 ASSERT_TRUE(GlobalPtr.isRoot());
130 ASSERT_TRUE(GlobalPtr.isLive());
131 ASSERT_FALSE(GlobalPtr.isZero());
132 ASSERT_FALSE(GlobalPtr.isField());
133 ASSERT_TRUE(GlobalPtr.getFieldDesc() == GlobalPtr.getDeclDesc());
134 ASSERT_TRUE(GlobalPtr.getOffset() == 0);
135 ASSERT_FALSE(GlobalPtr.inArray());
136 ASSERT_FALSE(GlobalPtr.isArrayElement());
137 ASSERT_FALSE(GlobalPtr.isArrayRoot());
138 ASSERT_FALSE(GlobalPtr.inPrimitiveArray());
139 ASSERT_TRUE(GlobalPtr.isStatic());
140 ASSERT_TRUE(GlobalPtr.isInitialized());
141 ASSERT_FALSE(GlobalPtr.isOnePastEnd());
142 ASSERT_FALSE(GlobalPtr.isElementPastEnd());
144 // Pointer to the first field (a primitive).
145 const Pointer &PF1 = GlobalPtr.atField(F1->Offset);
146 ASSERT_TRUE(PF1.isLive());
147 ASSERT_TRUE(PF1.isInitialized());
148 ASSERT_TRUE(PF1.isField());
149 ASSERT_FALSE(PF1.inArray());
150 ASSERT_FALSE(PF1.isArrayElement());
151 ASSERT_FALSE(PF1.isArrayRoot());
152 ASSERT_FALSE(PF1.isOnePastEnd());
153 ASSERT_FALSE(PF1.isRoot());
154 ASSERT_TRUE(PF1.getFieldDesc()->isPrimitive());
155 ASSERT_TRUE(Pointer::hasSameBase(PF1, GlobalPtr));
156 ASSERT_TRUE(PF1.getBase() == GlobalPtr);
158 // Pointer to the second field (a primitive array).
159 const Pointer &PF2 = GlobalPtr.atField(F2->Offset);
160 ASSERT_TRUE(PF2.isLive());
161 ASSERT_TRUE(PF2.isInitialized());
162 ASSERT_TRUE(PF2.isField());
163 ASSERT_TRUE(PF2.inArray());
164 ASSERT_FALSE(PF2.isArrayElement());
165 ASSERT_TRUE(PF2.isArrayRoot());
166 ASSERT_TRUE(PF2.getNumElems() == 4);
167 ASSERT_FALSE(PF2.isOnePastEnd());
168 ASSERT_FALSE(PF2.isRoot());
169 ASSERT_FALSE(PF2.getFieldDesc()->isPrimitive());
170 ASSERT_TRUE(PF2.getFieldDesc()->isArray());
171 ASSERT_TRUE(Pointer::hasSameBase(PF2, GlobalPtr));
172 ASSERT_TRUE(PF2.getBase() == GlobalPtr);
174 // Check contents of field 2 (a primitive array).
176 const Pointer &E1 = PF2.atIndex(0);
177 ASSERT_TRUE(E1.isLive());
178 ASSERT_FALSE(E1.isArrayRoot());
179 ASSERT_TRUE(E1.isArrayElement());
180 ASSERT_TRUE(E1.inPrimitiveArray());
181 ASSERT_TRUE(E1.deref<char>() == 'f');
182 ASSERT_EQ(E1.getIndex(), 0u);
183 ASSERT_TRUE(E1 == E1.atIndex(0));
184 ASSERT_TRUE(Pointer::hasSameBase(E1, GlobalPtr));
186 const Pointer &E2 = PF2.atIndex(1);
187 ASSERT_TRUE(E2.isLive());
188 ASSERT_FALSE(E2.isArrayRoot());
189 ASSERT_TRUE(E2.isArrayElement());
190 ASSERT_EQ(E2.getIndex(), 1u);
191 // Narrow() doesn't do anything on primitive array elements, as there is
192 // nothing to narrow into.
193 ASSERT_EQ(E2.narrow(), E2);
194 // ... so this should also hold.
195 ASSERT_EQ(E2.expand(), E2);
196 ASSERT_EQ(E2.narrow().expand(), E2);
198 // .atIndex(1).atIndex(1) should be index 1.
199 ASSERT_EQ(PF2.atIndex(1).atIndex(1), PF2.atIndex(1));
200 ASSERT_EQ(PF2.atIndex(1).narrow().atIndex(1), PF2.atIndex(1));
202 // getArray() should give us the array field again.
203 ASSERT_EQ(E2.getArray(), PF2);
205 // One-after-the-end pointer.
206 const Pointer &O = PF2.atIndex(PF2.getNumElems());
207 ASSERT_TRUE(O.isLive());
208 ASSERT_TRUE(O.isOnePastEnd());
209 ASSERT_TRUE(O.isInitialized());
210 ASSERT_TRUE(O.getIndex() == PF2.getNumElems());
213 // Pointer to the third field (a composite array).
214 const Pointer &PF3 = GlobalPtr.atField(F3->Offset);
215 ASSERT_TRUE(PF3.isLive());
216 ASSERT_TRUE(PF3.isInitialized());
217 ASSERT_TRUE(PF3.isField());
218 ASSERT_TRUE(PF3.inArray());
219 ASSERT_TRUE(PF3.isArrayRoot());
220 ASSERT_FALSE(PF3.isArrayElement());
221 ASSERT_TRUE(PF3.getNumElems() == 3);
222 ASSERT_FALSE(PF3.isOnePastEnd());
223 ASSERT_FALSE(PF3.isRoot());
224 ASSERT_FALSE(PF3.getFieldDesc()->isPrimitive());
225 ASSERT_TRUE(PF3.getFieldDesc()->isArray());
226 ASSERT_TRUE(Pointer::hasSameBase(PF3, GlobalPtr));
227 ASSERT_TRUE(PF3.getBase() == GlobalPtr);
228 ASSERT_EQ(PF3.getRecord(), nullptr);
229 ASSERT_TRUE(PF3.getElemRecord());
231 // Check contents of field 3 (a composite array).
233 const Pointer &E1 = PF3.atIndex(0);
234 // Note that we didn't call narrow() above, so this points
235 // to an array element and not just a field.
236 ASSERT_TRUE(E1.isLive());
237 ASSERT_EQ(E1.getIndex(), 0);
238 ASSERT_TRUE(E1.isInitialized());
239 ASSERT_TRUE(E1.isArrayElement());
240 ASSERT_TRUE(E1.inArray());
241 ASSERT_FALSE(E1.isArrayRoot());
242 ASSERT_FALSE(E1.isRoot());
243 ASSERT_EQ(E1.getArray(), PF3);
244 ASSERT_TRUE(E1.isField());
245 ASSERT_TRUE(E1.getElemRecord());
246 ASSERT_FALSE(E1.getRecord());
248 // Now the same with narrow().
249 const Pointer &NE1 = PF3.atIndex(0).narrow();
250 ASSERT_NE(E1, NE1);
251 ASSERT_TRUE(NE1.isLive());
252 ASSERT_EQ(NE1.getIndex(), 0);
253 ASSERT_TRUE(NE1.isInitialized());
254 ASSERT_TRUE(NE1.isArrayElement());
255 ASSERT_TRUE(NE1.isField());
256 ASSERT_FALSE(NE1.inArray());
257 ASSERT_FALSE(NE1.isArrayRoot());
258 ASSERT_FALSE(NE1.isRoot());
259 // Not possible, since this is narrow()ed:
260 // ASSERT_EQ(NE1.getArray(), PF3);
261 ASSERT_EQ(NE1.expand(), E1);
262 ASSERT_FALSE(NE1.getElemRecord());
263 ASSERT_TRUE(NE1.getRecord());
265 // Second element, NOT narrowed.
266 const Pointer &E2 = PF3.atIndex(1);
267 ASSERT_TRUE(E2.isLive());
268 ASSERT_EQ(E2.getIndex(), 1);
269 ASSERT_TRUE(E2.isInitialized());
270 ASSERT_TRUE(E2.isArrayElement());
271 ASSERT_TRUE(E2.isField());
272 ASSERT_TRUE(E2.inArray());
273 ASSERT_FALSE(E2.isArrayRoot());
274 ASSERT_FALSE(E2.isRoot());
275 ASSERT_EQ(E2.getArray(), PF3);
277 // Second element, narrowed.
278 const Pointer &NE2 = PF3.atIndex(1).narrow();
279 ASSERT_TRUE(NE2.isLive());
280 ASSERT_EQ(NE2.getIndex(), 0);
281 ASSERT_TRUE(NE2.isInitialized());
282 ASSERT_TRUE(NE2.isArrayElement());
283 ASSERT_TRUE(NE2.isField());
284 ASSERT_FALSE(NE2.inArray());
285 ASSERT_FALSE(NE2.isArrayRoot());
286 ASSERT_FALSE(NE2.isRoot());
287 // Not possible, since this is narrow()ed:
288 // ASSERT_EQ(NE2.getArray(), PF3);
289 ASSERT_FALSE(NE2.getElemRecord());
290 ASSERT_TRUE(NE2.getRecord());
292 // Chained atIndex() without narrowing in between.
293 ASSERT_EQ(PF3.atIndex(1).atIndex(1), PF3.atIndex(1));
295 // First field of the second element.
296 const Pointer &FP1 = NE2.atField(NE2.getRecord()->getField(0u)->Offset);
297 ASSERT_TRUE(FP1.isLive());
298 ASSERT_TRUE(FP1.isInitialized());
299 ASSERT_EQ(FP1.getBase(), NE2);
300 ASSERT_FALSE(FP1.isArrayElement());
301 ASSERT_FALSE(FP1.inArray());
302 ASSERT_FALSE(FP1.inPrimitiveArray());
303 ASSERT_TRUE(FP1.isField());
305 // One-past-the-end of a composite array.
306 const Pointer &O = PF3.atIndex(PF3.getNumElems()).narrow();
307 ASSERT_TRUE(O.isOnePastEnd());
308 ASSERT_TRUE(O.isElementPastEnd());
311 // Pointer to the fourth field (a multidimensional primitive array).
312 const Pointer &PF4 = GlobalPtr.atField(F4->Offset);
313 ASSERT_TRUE(PF4.isLive());
314 ASSERT_TRUE(PF4.isInitialized());
315 ASSERT_TRUE(PF4.isField());
316 ASSERT_TRUE(PF4.inArray());
317 ASSERT_TRUE(PF4.isArrayRoot());
318 ASSERT_FALSE(PF4.isArrayElement());
319 ASSERT_TRUE(PF4.getNumElems() == 3);
320 ASSERT_FALSE(PF4.isOnePastEnd());
321 ASSERT_FALSE(PF4.isRoot());
322 ASSERT_FALSE(PF4.getFieldDesc()->isPrimitive());
323 ASSERT_TRUE(PF4.getFieldDesc()->isArray());
324 ASSERT_TRUE(Pointer::hasSameBase(PF4, GlobalPtr));
325 ASSERT_TRUE(PF4.getBase() == GlobalPtr);
326 ASSERT_EQ(PF4.getRecord(), nullptr);
327 ASSERT_EQ(PF4.getElemRecord(), nullptr);
328 ASSERT_NE(PF4.getField(), nullptr);
329 ASSERT_TRUE(PF4.getFieldDesc()->ElemDesc->isPrimitiveArray());
330 // Check contents of field 4 (a primitive array).
332 // Pointer to the first element, is of type short[3].
333 const Pointer &E1 = PF4.atIndex(0);
334 ASSERT_NE(E1, PF4);
335 ASSERT_TRUE(E1.isLive());
336 ASSERT_TRUE(E1.isArrayElement());
337 ASSERT_TRUE(E1.inArray());
338 ASSERT_EQ(E1.getNumElems(), 3u);
339 ASSERT_EQ(E1.getIndex(), 0u);
340 ASSERT_EQ(E1.getArray(), PF4);
342 // Now narrow()'ed.
343 const Pointer &NE1 = PF4.atIndex(0).narrow();
344 ASSERT_NE(NE1, PF4);
345 ASSERT_NE(NE1, E1);
346 ASSERT_TRUE(NE1.isLive());
347 ASSERT_TRUE(NE1.isArrayElement());
348 ASSERT_TRUE(NE1.isArrayRoot());
349 ASSERT_FALSE(NE1.getFieldDesc()->isCompositeArray());
350 ASSERT_TRUE(NE1.getFieldDesc()->isPrimitiveArray());
351 ASSERT_EQ(NE1.getFieldDesc()->getNumElems(), 3u);
352 ASSERT_TRUE(NE1.inArray());
353 ASSERT_EQ(NE1.getNumElems(), 3u);
354 ASSERT_EQ(NE1.getIndex(), 0u);
356 // Last element of the first dimension.
357 const Pointer &PE1 = PF4.atIndex(0).narrow().atIndex(2);
358 ASSERT_TRUE(PE1.isLive());
359 ASSERT_EQ(PE1.deref<short>(), 3);
360 ASSERT_EQ(PE1.getArray(), NE1);
361 ASSERT_EQ(PE1.getIndex(), 2u);
363 // third dimension
364 const Pointer &E3 = PF4.atIndex(2);
365 ASSERT_NE(E3, PF4);
366 ASSERT_TRUE(E3.isLive());
367 ASSERT_TRUE(E3.isArrayElement());
368 ASSERT_FALSE(E3.isArrayRoot());
369 ASSERT_TRUE(E3.inArray());
370 ASSERT_EQ(E3.getNumElems(), 3u);
371 ASSERT_EQ(E3.getIndex(), 2u);
373 // Same, but narrow()'ed.
374 const Pointer &NE3 = PF4.atIndex(2).narrow();
375 ASSERT_NE(NE3, PF4);
376 ASSERT_NE(NE3, E1);
377 ASSERT_TRUE(NE3.isLive());
378 ASSERT_TRUE(NE3.isArrayElement());
379 ASSERT_TRUE(NE3.isArrayRoot());
380 ASSERT_FALSE(NE3.getFieldDesc()->isCompositeArray());
381 ASSERT_TRUE(NE3.getFieldDesc()->isPrimitiveArray());
382 ASSERT_EQ(NE3.getFieldDesc()->getNumElems(), 3u);
383 ASSERT_TRUE(NE3.inArray());
384 ASSERT_EQ(NE3.getNumElems(), 3u);
385 // This is narrow()'ed, so not an "array elemnet"
386 ASSERT_EQ(PF4.atIndex(2).getIndex(), 2u);
387 ASSERT_EQ(NE3.getIndex(), 0u);
389 // Last element of the last dimension
390 const Pointer &PE3 = PF4.atIndex(2).narrow().atIndex(2);
391 ASSERT_TRUE(PE3.isLive());
392 ASSERT_EQ(PE3.deref<short>(), 9);
393 ASSERT_EQ(PE3.getArray(), NE3);
394 ASSERT_EQ(PE3.getIndex(), 2u);
397 // Zero-size array.
399 const Pointer &PF5 = GlobalPtr.atField(F5->Offset);
401 ASSERT_TRUE(PF5.isZeroSizeArray());
402 ASSERT_FALSE(PF5.isOnePastEnd());
403 ASSERT_FALSE(PF5.isElementPastEnd());