1 | //=== unittests/CodeGen/TBAAMetadataTest.cpp - Checks metadata generation -===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "IRMatchers.h" |
10 | #include "TestCompiler.h" |
11 | #include "clang/AST/ASTConsumer.h" |
12 | #include "clang/AST/ASTContext.h" |
13 | #include "clang/Basic/SourceManager.h" |
14 | #include "clang/Basic/TargetInfo.h" |
15 | #include "llvm/IR/Constants.h" |
16 | #include "llvm/Support/MemoryBuffer.h" |
17 | #include "gtest/gtest.h" |
18 | #include <memory> |
19 | |
20 | using namespace llvm; |
21 | |
22 | namespace { |
23 | |
24 | struct TBAATestCompiler : public TestCompiler { |
25 | TBAATestCompiler(clang::LangOptions LO, clang::CodeGenOptions CGO) |
26 | : TestCompiler(LO, CGO) {} |
27 | static clang::CodeGenOptions getCommonCodeGenOpts() { |
28 | clang::CodeGenOptions CGOpts; |
29 | CGOpts.StructPathTBAA = 1; |
30 | CGOpts.OptimizationLevel = 1; |
31 | return CGOpts; |
32 | } |
33 | }; |
34 | |
35 | auto OmnipotentCharC = MMTuple( |
36 | Args: MMString(Name: "omnipotent char" ), |
37 | Args: MMTuple( |
38 | Args: MMString(Name: "Simple C/C++ TBAA" )), |
39 | Args: MConstInt(V: 0, W: 64) |
40 | ); |
41 | |
42 | |
43 | auto OmnipotentCharCXX = MMTuple( |
44 | Args: MMString(Name: "omnipotent char" ), |
45 | Args: MMTuple( |
46 | Args: MMString(Name: "Simple C++ TBAA" )), |
47 | Args: MConstInt(V: 0, W: 64) |
48 | ); |
49 | |
50 | |
51 | TEST(TBAAMetadataTest, BasicTypes) { |
52 | const char TestProgram[] = R"**( |
53 | void func(char *CP, short *SP, int *IP, long long *LP, void **VPP, |
54 | int **IPP) { |
55 | *CP = 4; |
56 | *SP = 11; |
57 | *IP = 601; |
58 | *LP = 604; |
59 | *VPP = CP; |
60 | *IPP = IP; |
61 | } |
62 | )**" ; |
63 | |
64 | clang::LangOptions LO; |
65 | TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts()); |
66 | Compiler.init(TestProgram); |
67 | const BasicBlock *BB = Compiler.compile(); |
68 | |
69 | const Instruction *I = match(BB, |
70 | M: MInstruction(C: Instruction::Store, |
71 | Args: MConstInt(V: 4, W: 8), |
72 | Args: MMTuple( |
73 | Args: OmnipotentCharC, |
74 | Args: MSameAs(N: 0), |
75 | Args: MConstInt(V: 0)))); |
76 | ASSERT_TRUE(I); |
77 | |
78 | I = matchNext(I, |
79 | M: MInstruction(C: Instruction::Store, |
80 | Args: MConstInt(V: 11, W: 16), |
81 | Args: MMTuple( |
82 | Args: MMTuple( |
83 | Args: MMString(Name: "short" ), |
84 | Args: OmnipotentCharC, |
85 | Args: MConstInt(V: 0)), |
86 | Args: MSameAs(N: 0), |
87 | Args: MConstInt(V: 0)))); |
88 | ASSERT_TRUE(I); |
89 | |
90 | I = matchNext(I, |
91 | M: MInstruction(C: Instruction::Store, |
92 | Args: MConstInt(V: 601, W: 32), |
93 | Args: MMTuple( |
94 | Args: MMTuple( |
95 | Args: MMString(Name: "int" ), |
96 | Args: OmnipotentCharC, |
97 | Args: MConstInt(V: 0)), |
98 | Args: MSameAs(N: 0), |
99 | Args: MConstInt(V: 0)))); |
100 | ASSERT_TRUE(I); |
101 | |
102 | I = matchNext(I, |
103 | M: MInstruction(C: Instruction::Store, |
104 | Args: MConstInt(V: 604, W: 64), |
105 | Args: MMTuple( |
106 | Args: MMTuple( |
107 | Args: MMString(Name: "long long" ), |
108 | Args: OmnipotentCharC, |
109 | Args: MConstInt(V: 0)), |
110 | Args: MSameAs(N: 0), |
111 | Args: MConstInt(V: 0)))); |
112 | ASSERT_TRUE(I); |
113 | |
114 | I = matchNext(I, |
115 | M: MInstruction(C: Instruction::Store, |
116 | Args: MValType(T: PointerType::getUnqual(C&: Compiler.Context)), |
117 | Args: MMTuple( |
118 | Args: MMTuple( |
119 | Args: MMString(Name: "any pointer" ), |
120 | Args: OmnipotentCharC, |
121 | Args: MConstInt(V: 0)), |
122 | Args: MSameAs(N: 0), |
123 | Args: MConstInt(V: 0)))); |
124 | ASSERT_TRUE(I); |
125 | |
126 | I = matchNext(I, |
127 | M: MInstruction(C: Instruction::Store, |
128 | Args: MValType(T: PointerType::getUnqual(C&: Compiler.Context)), |
129 | Args: MMTuple( |
130 | Args: MMTuple( |
131 | Args: MMString(Name: "any pointer" ), |
132 | Args: OmnipotentCharC, |
133 | Args: MConstInt(V: 0)), |
134 | Args: MSameAs(N: 0), |
135 | Args: MConstInt(V: 0)))); |
136 | ASSERT_TRUE(I); |
137 | } |
138 | |
139 | TEST(TBAAMetadataTest, CFields) { |
140 | const char TestProgram[] = R"**( |
141 | struct ABC { |
142 | short f16; |
143 | int f32; |
144 | long long f64; |
145 | unsigned short f16_2; |
146 | unsigned f32_2; |
147 | unsigned long long f64_2; |
148 | }; |
149 | |
150 | void func(struct ABC *A) { |
151 | A->f32 = 4; |
152 | A->f16 = 11; |
153 | A->f64 = 601; |
154 | A->f16_2 = 22; |
155 | A->f32_2 = 77; |
156 | A->f64_2 = 604; |
157 | } |
158 | )**" ; |
159 | |
160 | clang::LangOptions LO; |
161 | LO.C11 = 1; |
162 | TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts()); |
163 | Compiler.init(TestProgram); |
164 | const BasicBlock *BB = Compiler.compile(); |
165 | |
166 | auto StructABC = MMTuple( |
167 | Args: MMString(Name: "ABC" ), |
168 | Args: MMTuple( |
169 | Args: MMString(Name: "short" ), |
170 | Args: OmnipotentCharC, |
171 | Args: MConstInt(V: 0)), |
172 | Args: MConstInt(V: 0), |
173 | Args: MMTuple( |
174 | Args: MMString(Name: "int" ), |
175 | Args: OmnipotentCharC, |
176 | Args: MConstInt(V: 0)), |
177 | Args: MConstInt(V: 4), |
178 | Args: MMTuple( |
179 | Args: MMString(Name: "long long" ), |
180 | Args: OmnipotentCharC, |
181 | Args: MConstInt(V: 0)), |
182 | Args: MConstInt(V: 8), |
183 | Args: MSameAs(N: 1), |
184 | Args: MConstInt(V: 16), |
185 | Args: MSameAs(N: 3), |
186 | Args: MConstInt(V: 20), |
187 | Args: MSameAs(N: 5), |
188 | Args: MConstInt(V: 24)); |
189 | |
190 | const Instruction *I = match(BB, |
191 | M: MInstruction(C: Instruction::Store, |
192 | Args: MConstInt(V: 4, W: 32), |
193 | Args: MMTuple( |
194 | Args: StructABC, |
195 | Args: MMTuple( |
196 | Args: MMString(Name: "int" ), |
197 | Args: OmnipotentCharC, |
198 | Args: MConstInt(V: 0)), |
199 | Args: MConstInt(V: 4)))); |
200 | ASSERT_TRUE(I); |
201 | |
202 | I = matchNext(I, |
203 | M: MInstruction(C: Instruction::Store, |
204 | Args: MConstInt(V: 11, W: 16), |
205 | Args: MMTuple( |
206 | Args: StructABC, |
207 | Args: MMTuple( |
208 | Args: MMString(Name: "short" ), |
209 | Args: OmnipotentCharC, |
210 | Args: MConstInt(V: 0)), |
211 | Args: MConstInt(V: 0)))); |
212 | ASSERT_TRUE(I); |
213 | |
214 | I = matchNext(I, |
215 | M: MInstruction(C: Instruction::Store, |
216 | Args: MConstInt(V: 601, W: 64), |
217 | Args: MMTuple( |
218 | Args: StructABC, |
219 | Args: MMTuple( |
220 | Args: MMString(Name: "long long" ), |
221 | Args: OmnipotentCharC, |
222 | Args: MConstInt(V: 0)), |
223 | Args: MConstInt(V: 8)))); |
224 | ASSERT_TRUE(I); |
225 | |
226 | I = matchNext(I, |
227 | M: MInstruction(C: Instruction::Store, |
228 | Args: MConstInt(V: 22, W: 16), |
229 | Args: MMTuple( |
230 | Args: StructABC, |
231 | Args: MMTuple( |
232 | Args: MMString(Name: "short" ), |
233 | Args: OmnipotentCharC, |
234 | Args: MConstInt(V: 0)), |
235 | Args: MConstInt(V: 16)))); |
236 | ASSERT_TRUE(I); |
237 | |
238 | I = matchNext(I, |
239 | M: MInstruction(C: Instruction::Store, |
240 | Args: MConstInt(V: 77, W: 32), |
241 | Args: MMTuple( |
242 | Args: StructABC, |
243 | Args: MMTuple( |
244 | Args: MMString(Name: "int" ), |
245 | Args: OmnipotentCharC, |
246 | Args: MConstInt(V: 0)), |
247 | Args: MConstInt(V: 20)))); |
248 | ASSERT_TRUE(I); |
249 | |
250 | I = matchNext(I, |
251 | M: MInstruction(C: Instruction::Store, |
252 | Args: MConstInt(V: 604, W: 64), |
253 | Args: MMTuple( |
254 | Args: StructABC, |
255 | Args: MMTuple( |
256 | Args: MMString(Name: "long long" ), |
257 | Args: OmnipotentCharC, |
258 | Args: MConstInt(V: 0)), |
259 | Args: MConstInt(V: 24)))); |
260 | ASSERT_TRUE(I); |
261 | } |
262 | |
263 | TEST(TBAAMetadataTest, CTypedefFields) { |
264 | const char TestProgram[] = R"**( |
265 | typedef struct { |
266 | short f16; |
267 | int f32; |
268 | } ABC; |
269 | typedef struct { |
270 | short value_f16; |
271 | int value_f32; |
272 | } CDE; |
273 | |
274 | void func(ABC *A, CDE *B) { |
275 | A->f32 = 4; |
276 | A->f16 = 11; |
277 | B->value_f32 = 44; |
278 | B->value_f16 = 111; |
279 | } |
280 | )**" ; |
281 | |
282 | clang::LangOptions LO; |
283 | LO.C11 = 1; |
284 | TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts()); |
285 | Compiler.init(TestProgram); |
286 | const BasicBlock *BB = Compiler.compile(); |
287 | |
288 | auto NamelessStruct = MMTuple( |
289 | Args: MMString(Name: "" ), |
290 | Args: MMTuple( |
291 | Args: MMString(Name: "short" ), |
292 | Args: OmnipotentCharC, |
293 | Args: MConstInt(V: 0)), |
294 | Args: MConstInt(V: 0), |
295 | Args: MMTuple( |
296 | Args: MMString(Name: "int" ), |
297 | Args: OmnipotentCharC, |
298 | Args: MConstInt(V: 0)), |
299 | Args: MConstInt(V: 4)); |
300 | |
301 | const Metadata *MetaABC = nullptr; |
302 | const Instruction *I = match(BB, |
303 | M: MInstruction(C: Instruction::Store, |
304 | Args: MConstInt(V: 4, W: 32), |
305 | Args: MMTuple( |
306 | Args: MMSave(V&: MetaABC, M: NamelessStruct), |
307 | Args: MMTuple( |
308 | Args: MMString(Name: "int" ), |
309 | Args: OmnipotentCharC, |
310 | Args: MConstInt(V: 0)), |
311 | Args: MConstInt(V: 4)))); |
312 | ASSERT_TRUE(I); |
313 | |
314 | I = matchNext(I, |
315 | M: MInstruction(C: Instruction::Store, |
316 | Args: MConstInt(V: 11, W: 16), |
317 | Args: MMTuple( |
318 | Args: NamelessStruct, |
319 | Args: MMTuple( |
320 | Args: MMString(Name: "short" ), |
321 | Args: OmnipotentCharC, |
322 | Args: MConstInt(V: 0)), |
323 | Args: MConstInt(V: 0)))); |
324 | ASSERT_TRUE(I); |
325 | |
326 | const Metadata *MetaCDE = nullptr; |
327 | I = matchNext(I, |
328 | M: MInstruction(C: Instruction::Store, |
329 | Args: MConstInt(V: 44, W: 32), |
330 | Args: MMTuple( |
331 | Args: MMSave(V&: MetaCDE, M: NamelessStruct), |
332 | Args: MMTuple( |
333 | Args: MMString(Name: "int" ), |
334 | Args: OmnipotentCharC, |
335 | Args: MConstInt(V: 0)), |
336 | Args: MConstInt(V: 4)))); |
337 | ASSERT_TRUE(I); |
338 | |
339 | I = matchNext(I, |
340 | M: MInstruction(C: Instruction::Store, |
341 | Args: MConstInt(V: 111, W: 16), |
342 | Args: MMTuple( |
343 | Args: NamelessStruct, |
344 | Args: MMTuple( |
345 | Args: MMString(Name: "short" ), |
346 | Args: OmnipotentCharC, |
347 | Args: MConstInt(V: 0)), |
348 | Args: MConstInt(V: 0)))); |
349 | ASSERT_TRUE(I); |
350 | |
351 | // FIXME: Nameless structures used in definitions of 'ABC' and 'CDE' are |
352 | // different structures and must be described by different descriptors. |
353 | //ASSERT_TRUE(MetaABC != MetaCDE); |
354 | } |
355 | |
356 | TEST(TBAAMetadataTest, CTypedefFields2) { |
357 | const char TestProgram[] = R"**( |
358 | typedef struct { |
359 | short f16; |
360 | int f32; |
361 | } ABC; |
362 | typedef struct { |
363 | short f16; |
364 | int f32; |
365 | } CDE; |
366 | |
367 | void func(ABC *A, CDE *B) { |
368 | A->f32 = 4; |
369 | A->f16 = 11; |
370 | B->f32 = 44; |
371 | B->f16 = 111; |
372 | } |
373 | )**" ; |
374 | |
375 | clang::LangOptions LO; |
376 | LO.C11 = 1; |
377 | TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts()); |
378 | Compiler.init(TestProgram); |
379 | const BasicBlock *BB = Compiler.compile(); |
380 | |
381 | auto NamelessStruct = MMTuple( |
382 | Args: MMString(Name: "" ), |
383 | Args: MMTuple( |
384 | Args: MMString(Name: "short" ), |
385 | Args: OmnipotentCharC, |
386 | Args: MConstInt(V: 0)), |
387 | Args: MConstInt(V: 0), |
388 | Args: MMTuple( |
389 | Args: MMString(Name: "int" ), |
390 | Args: OmnipotentCharC, |
391 | Args: MConstInt(V: 0)), |
392 | Args: MConstInt(V: 4)); |
393 | |
394 | const Metadata *MetaABC = nullptr; |
395 | const Instruction *I = match(BB, |
396 | M: MInstruction(C: Instruction::Store, |
397 | Args: MConstInt(V: 4, W: 32), |
398 | Args: MMTuple( |
399 | Args: MMSave(V&: MetaABC, M: NamelessStruct), |
400 | Args: MMTuple( |
401 | Args: MMString(Name: "int" ), |
402 | Args: OmnipotentCharC, |
403 | Args: MConstInt(V: 0)), |
404 | Args: MConstInt(V: 4)))); |
405 | ASSERT_TRUE(I); |
406 | |
407 | I = matchNext(I, |
408 | M: MInstruction(C: Instruction::Store, |
409 | Args: MConstInt(V: 11, W: 16), |
410 | Args: MMTuple( |
411 | Args: NamelessStruct, |
412 | Args: MMTuple( |
413 | Args: MMString(Name: "short" ), |
414 | Args: OmnipotentCharC, |
415 | Args: MConstInt(V: 0)), |
416 | Args: MConstInt(V: 0)))); |
417 | ASSERT_TRUE(I); |
418 | |
419 | const Metadata *MetaCDE = nullptr; |
420 | I = matchNext(I, |
421 | M: MInstruction(C: Instruction::Store, |
422 | Args: MConstInt(V: 44, W: 32), |
423 | Args: MMTuple( |
424 | Args: MMSave(V&: MetaCDE, M: NamelessStruct), |
425 | Args: MMTuple( |
426 | Args: MMString(Name: "int" ), |
427 | Args: OmnipotentCharC, |
428 | Args: MConstInt(V: 0)), |
429 | Args: MConstInt(V: 4)))); |
430 | ASSERT_TRUE(I); |
431 | |
432 | I = matchNext(I, |
433 | M: MInstruction(C: Instruction::Store, |
434 | Args: MConstInt(V: 111, W: 16), |
435 | Args: MMTuple( |
436 | Args: NamelessStruct, |
437 | Args: MMTuple( |
438 | Args: MMString(Name: "short" ), |
439 | Args: OmnipotentCharC, |
440 | Args: MConstInt(V: 0)), |
441 | Args: MConstInt(V: 0)))); |
442 | ASSERT_TRUE(I); |
443 | |
444 | // FIXME: Nameless structures used in definitions of 'ABC' and 'CDE' are |
445 | // different structures, although they have the same field sequence. They must |
446 | // be described by different descriptors. |
447 | //ASSERT_TRUE(MetaABC != MetaCDE); |
448 | } |
449 | |
450 | TEST(TBAAMetadataTest, CTypedefFields3) { |
451 | const char TestProgram[] = R"**( |
452 | typedef struct { |
453 | short f16; |
454 | int f32; |
455 | } ABC; |
456 | typedef struct { |
457 | int f32; |
458 | short f16; |
459 | } CDE; |
460 | |
461 | void func(ABC *A, CDE *B) { |
462 | A->f32 = 4; |
463 | A->f16 = 11; |
464 | B->f32 = 44; |
465 | B->f16 = 111; |
466 | } |
467 | )**" ; |
468 | |
469 | clang::LangOptions LO; |
470 | LO.C11 = 1; |
471 | TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts()); |
472 | Compiler.init(TestProgram); |
473 | const BasicBlock *BB = Compiler.compile(); |
474 | |
475 | auto NamelessStruct1 = MMTuple( |
476 | Args: MMString(Name: "" ), |
477 | Args: MMTuple( |
478 | Args: MMString(Name: "short" ), |
479 | Args: OmnipotentCharC, |
480 | Args: MConstInt(V: 0)), |
481 | Args: MConstInt(V: 0), |
482 | Args: MMTuple( |
483 | Args: MMString(Name: "int" ), |
484 | Args: OmnipotentCharC, |
485 | Args: MConstInt(V: 0)), |
486 | Args: MConstInt(V: 4)); |
487 | |
488 | auto NamelessStruct2 = MMTuple( |
489 | Args: MMString(Name: "" ), |
490 | Args: MMTuple( |
491 | Args: MMString(Name: "int" ), |
492 | Args: OmnipotentCharC, |
493 | Args: MConstInt(V: 0)), |
494 | Args: MConstInt(V: 0), |
495 | Args: MMTuple( |
496 | Args: MMString(Name: "short" ), |
497 | Args: OmnipotentCharC, |
498 | Args: MConstInt(V: 0)), |
499 | Args: MConstInt(V: 4)); |
500 | |
501 | const Instruction *I = match(BB, |
502 | M: MInstruction(C: Instruction::Store, |
503 | Args: MConstInt(V: 4, W: 32), |
504 | Args: MMTuple( |
505 | Args: NamelessStruct1, |
506 | Args: MMTuple( |
507 | Args: MMString(Name: "int" ), |
508 | Args: OmnipotentCharC, |
509 | Args: MConstInt(V: 0)), |
510 | Args: MConstInt(V: 4)))); |
511 | ASSERT_TRUE(I); |
512 | |
513 | I = matchNext(I, |
514 | M: MInstruction(C: Instruction::Store, |
515 | Args: MConstInt(V: 11, W: 16), |
516 | Args: MMTuple( |
517 | Args: NamelessStruct1, |
518 | Args: MMTuple( |
519 | Args: MMString(Name: "short" ), |
520 | Args: OmnipotentCharC, |
521 | Args: MConstInt(V: 0)), |
522 | Args: MConstInt(V: 0)))); |
523 | ASSERT_TRUE(I); |
524 | |
525 | I = matchNext(I, |
526 | M: MInstruction(C: Instruction::Store, |
527 | Args: MConstInt(V: 44, W: 32), |
528 | Args: MMTuple( |
529 | Args: NamelessStruct2, |
530 | Args: MMTuple( |
531 | Args: MMString(Name: "int" ), |
532 | Args: OmnipotentCharC, |
533 | Args: MConstInt(V: 0)), |
534 | Args: MConstInt(V: 0)))); |
535 | ASSERT_TRUE(I); |
536 | |
537 | I = matchNext(I, |
538 | M: MInstruction(C: Instruction::Store, |
539 | Args: MConstInt(V: 111, W: 16), |
540 | Args: MMTuple( |
541 | Args: NamelessStruct2, |
542 | Args: MMTuple( |
543 | Args: MMString(Name: "short" ), |
544 | Args: OmnipotentCharC, |
545 | Args: MConstInt(V: 0)), |
546 | Args: MConstInt(V: 4)))); |
547 | ASSERT_TRUE(I); |
548 | } |
549 | |
550 | TEST(TBAAMetadataTest, CXXFields) { |
551 | const char TestProgram[] = R"**( |
552 | struct ABC { |
553 | short f16; |
554 | int f32; |
555 | long long f64; |
556 | unsigned short f16_2; |
557 | unsigned f32_2; |
558 | unsigned long long f64_2; |
559 | }; |
560 | |
561 | void func(struct ABC *A) { |
562 | A->f32 = 4; |
563 | A->f16 = 11; |
564 | A->f64 = 601; |
565 | A->f16_2 = 22; |
566 | A->f32_2 = 77; |
567 | A->f64_2 = 604; |
568 | } |
569 | )**" ; |
570 | |
571 | clang::LangOptions LO; |
572 | LO.CPlusPlus = 1; |
573 | LO.CPlusPlus11 = 1; |
574 | TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts()); |
575 | Compiler.init(TestProgram); |
576 | const BasicBlock *BB = Compiler.compile(); |
577 | |
578 | auto StructABC = MMTuple( |
579 | Args: MMString(Name: "_ZTS3ABC" ), |
580 | Args: MMTuple( |
581 | Args: MMString(Name: "short" ), |
582 | Args: OmnipotentCharCXX, |
583 | Args: MConstInt(V: 0)), |
584 | Args: MConstInt(V: 0), |
585 | Args: MMTuple( |
586 | Args: MMString(Name: "int" ), |
587 | Args: OmnipotentCharCXX, |
588 | Args: MConstInt(V: 0)), |
589 | Args: MConstInt(V: 4), |
590 | Args: MMTuple( |
591 | Args: MMString(Name: "long long" ), |
592 | Args: OmnipotentCharCXX, |
593 | Args: MConstInt(V: 0)), |
594 | Args: MConstInt(V: 8), |
595 | Args: MSameAs(N: 1), |
596 | Args: MConstInt(V: 16), |
597 | Args: MSameAs(N: 3), |
598 | Args: MConstInt(V: 20), |
599 | Args: MSameAs(N: 5), |
600 | Args: MConstInt(V: 24)); |
601 | |
602 | const Instruction *I = match(BB, |
603 | M: MInstruction(C: Instruction::Store, |
604 | Args: MConstInt(V: 4, W: 32), |
605 | Args: MMTuple( |
606 | Args: StructABC, |
607 | Args: MMTuple( |
608 | Args: MMString(Name: "int" ), |
609 | Args: OmnipotentCharCXX, |
610 | Args: MConstInt(V: 0)), |
611 | Args: MConstInt(V: 4)))); |
612 | ASSERT_TRUE(I); |
613 | |
614 | I = matchNext(I, |
615 | M: MInstruction(C: Instruction::Store, |
616 | Args: MConstInt(V: 11, W: 16), |
617 | Args: MMTuple( |
618 | Args: StructABC, |
619 | Args: MMTuple( |
620 | Args: MMString(Name: "short" ), |
621 | Args: OmnipotentCharCXX, |
622 | Args: MConstInt(V: 0)), |
623 | Args: MConstInt(V: 0)))); |
624 | ASSERT_TRUE(I); |
625 | |
626 | I = matchNext(I, |
627 | M: MInstruction(C: Instruction::Store, |
628 | Args: MConstInt(V: 601, W: 64), |
629 | Args: MMTuple( |
630 | Args: StructABC, |
631 | Args: MMTuple( |
632 | Args: MMString(Name: "long long" ), |
633 | Args: OmnipotentCharCXX, |
634 | Args: MConstInt(V: 0)), |
635 | Args: MConstInt(V: 8)))); |
636 | ASSERT_TRUE(I); |
637 | |
638 | I = matchNext(I, |
639 | M: MInstruction(C: Instruction::Store, |
640 | Args: MConstInt(V: 22, W: 16), |
641 | Args: MMTuple( |
642 | Args: StructABC, |
643 | Args: MMTuple( |
644 | Args: MMString(Name: "short" ), |
645 | Args: OmnipotentCharCXX, |
646 | Args: MConstInt(V: 0)), |
647 | Args: MConstInt(V: 16)))); |
648 | ASSERT_TRUE(I); |
649 | |
650 | I = matchNext(I, |
651 | M: MInstruction(C: Instruction::Store, |
652 | Args: MConstInt(V: 77, W: 32), |
653 | Args: MMTuple( |
654 | Args: StructABC, |
655 | Args: MMTuple( |
656 | Args: MMString(Name: "int" ), |
657 | Args: OmnipotentCharCXX, |
658 | Args: MConstInt(V: 0)), |
659 | Args: MConstInt(V: 20)))); |
660 | ASSERT_TRUE(I); |
661 | |
662 | I = matchNext(I, |
663 | M: MInstruction(C: Instruction::Store, |
664 | Args: MConstInt(V: 604, W: 64), |
665 | Args: MMTuple( |
666 | Args: StructABC, |
667 | Args: MMTuple( |
668 | Args: MMString(Name: "long long" ), |
669 | Args: OmnipotentCharCXX, |
670 | Args: MConstInt(V: 0)), |
671 | Args: MConstInt(V: 24)))); |
672 | ASSERT_TRUE(I); |
673 | } |
674 | |
675 | TEST(TBAAMetadataTest, CXXTypedefFields) { |
676 | const char TestProgram[] = R"**( |
677 | typedef struct { |
678 | short f16; |
679 | int f32; |
680 | } ABC; |
681 | typedef struct { |
682 | short value_f16; |
683 | int value_f32; |
684 | } CDE; |
685 | |
686 | void func(ABC *A, CDE *B) { |
687 | A->f32 = 4; |
688 | A->f16 = 11; |
689 | B->value_f32 = 44; |
690 | B->value_f16 = 111; |
691 | } |
692 | )**" ; |
693 | |
694 | clang::LangOptions LO; |
695 | LO.CPlusPlus = 1; |
696 | LO.CPlusPlus11 = 1; |
697 | TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts()); |
698 | Compiler.init(TestProgram); |
699 | const BasicBlock *BB = Compiler.compile(); |
700 | |
701 | auto StructABC = MMTuple( |
702 | Args: MMString(Name: "_ZTS3ABC" ), |
703 | Args: MMTuple( |
704 | Args: MMString(Name: "short" ), |
705 | Args: OmnipotentCharCXX, |
706 | Args: MConstInt(V: 0)), |
707 | Args: MConstInt(V: 0), |
708 | Args: MMTuple( |
709 | Args: MMString(Name: "int" ), |
710 | Args: OmnipotentCharCXX, |
711 | Args: MConstInt(V: 0)), |
712 | Args: MConstInt(V: 4)); |
713 | |
714 | auto StructCDE = MMTuple( |
715 | Args: MMString(Name: "_ZTS3CDE" ), |
716 | Args: MMTuple( |
717 | Args: MMString(Name: "short" ), |
718 | Args: OmnipotentCharCXX, |
719 | Args: MConstInt(V: 0)), |
720 | Args: MConstInt(V: 0), |
721 | Args: MMTuple( |
722 | Args: MMString(Name: "int" ), |
723 | Args: OmnipotentCharCXX, |
724 | Args: MConstInt(V: 0)), |
725 | Args: MConstInt(V: 4)); |
726 | |
727 | const Instruction *I = match(BB, |
728 | M: MInstruction(C: Instruction::Store, |
729 | Args: MConstInt(V: 4, W: 32), |
730 | Args: MMTuple( |
731 | Args: StructABC, |
732 | Args: MMTuple( |
733 | Args: MMString(Name: "int" ), |
734 | Args: OmnipotentCharCXX, |
735 | Args: MConstInt(V: 0)), |
736 | Args: MConstInt(V: 4)))); |
737 | ASSERT_TRUE(I); |
738 | |
739 | I = matchNext(I, |
740 | M: MInstruction(C: Instruction::Store, |
741 | Args: MConstInt(V: 11, W: 16), |
742 | Args: MMTuple( |
743 | Args: StructABC, |
744 | Args: MMTuple( |
745 | Args: MMString(Name: "short" ), |
746 | Args: OmnipotentCharCXX, |
747 | Args: MConstInt(V: 0)), |
748 | Args: MConstInt(V: 0)))); |
749 | ASSERT_TRUE(I); |
750 | |
751 | I = matchNext(I, |
752 | M: MInstruction(C: Instruction::Store, |
753 | Args: MConstInt(V: 44, W: 32), |
754 | Args: MMTuple( |
755 | Args: StructCDE, |
756 | Args: MMTuple( |
757 | Args: MMString(Name: "int" ), |
758 | Args: OmnipotentCharCXX, |
759 | Args: MConstInt(V: 0)), |
760 | Args: MConstInt(V: 4)))); |
761 | ASSERT_TRUE(I); |
762 | |
763 | I = matchNext(I, |
764 | M: MInstruction(C: Instruction::Store, |
765 | Args: MConstInt(V: 111, W: 16), |
766 | Args: MMTuple( |
767 | Args: StructCDE, |
768 | Args: MMTuple( |
769 | Args: MMString(Name: "short" ), |
770 | Args: OmnipotentCharCXX, |
771 | Args: MConstInt(V: 0)), |
772 | Args: MConstInt(V: 0)))); |
773 | ASSERT_TRUE(I); |
774 | } |
775 | |
776 | TEST(TBAAMetadataTest, StructureFields) { |
777 | const char TestProgram[] = R"**( |
778 | struct Inner { |
779 | int f32; |
780 | }; |
781 | |
782 | struct Outer { |
783 | short f16; |
784 | Inner b1; |
785 | Inner b2; |
786 | }; |
787 | |
788 | void func(Outer *S) { |
789 | S->f16 = 14; |
790 | S->b1.f32 = 35; |
791 | S->b2.f32 = 77; |
792 | } |
793 | )**" ; |
794 | |
795 | clang::LangOptions LO; |
796 | LO.CPlusPlus = 1; |
797 | LO.CPlusPlus11 = 1; |
798 | TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts()); |
799 | Compiler.init(TestProgram); |
800 | const BasicBlock *BB = Compiler.compile(); |
801 | |
802 | auto StructInner = MMTuple( |
803 | Args: MMString(Name: "_ZTS5Inner" ), |
804 | Args: MMTuple( |
805 | Args: MMString(Name: "int" ), |
806 | Args: OmnipotentCharCXX, |
807 | Args: MConstInt(V: 0)), |
808 | Args: MConstInt(V: 0)); |
809 | |
810 | auto StructOuter = MMTuple( |
811 | Args: MMString(Name: "_ZTS5Outer" ), |
812 | Args: MMTuple( |
813 | Args: MMString(Name: "short" ), |
814 | Args: OmnipotentCharCXX, |
815 | Args: MConstInt(V: 0)), |
816 | Args: MConstInt(V: 0), |
817 | Args: StructInner, |
818 | Args: MConstInt(V: 4), |
819 | Args: MSameAs(N: 3), |
820 | Args: MConstInt(V: 8)); |
821 | |
822 | const Instruction *I = match(BB, |
823 | M: MInstruction(C: Instruction::Store, |
824 | Args: MConstInt(V: 14, W: 16), |
825 | Args: MMTuple( |
826 | Args: StructOuter, |
827 | Args: MMTuple( |
828 | Args: MMString(Name: "short" ), |
829 | Args: OmnipotentCharCXX, |
830 | Args: MConstInt(V: 0)), |
831 | Args: MConstInt(V: 0)))); |
832 | ASSERT_TRUE(I); |
833 | |
834 | I = matchNext(I, |
835 | M: MInstruction(C: Instruction::Store, |
836 | Args: MConstInt(V: 35, W: 32), |
837 | Args: MMTuple( |
838 | Args: StructOuter, |
839 | Args: MMTuple( |
840 | Args: MMString(Name: "int" ), |
841 | Args: OmnipotentCharCXX, |
842 | Args: MConstInt(V: 0)), |
843 | Args: MConstInt(V: 4)))); |
844 | ASSERT_TRUE(I); |
845 | |
846 | I = matchNext(I, |
847 | M: MInstruction(C: Instruction::Store, |
848 | Args: MConstInt(V: 77, W: 32), |
849 | Args: MMTuple( |
850 | Args: StructOuter, |
851 | Args: MMTuple( |
852 | Args: MMString(Name: "int" ), |
853 | Args: OmnipotentCharCXX, |
854 | Args: MConstInt(V: 0)), |
855 | Args: MConstInt(V: 8)))); |
856 | ASSERT_TRUE(I); |
857 | } |
858 | |
859 | TEST(TBAAMetadataTest, ArrayFields) { |
860 | const char TestProgram[] = R"**( |
861 | struct Inner { |
862 | int f32; |
863 | }; |
864 | |
865 | struct Outer { |
866 | short f16; |
867 | Inner b1[2]; |
868 | }; |
869 | |
870 | void func(Outer *S) { |
871 | S->f16 = 14; |
872 | S->b1[0].f32 = 35; |
873 | S->b1[1].f32 = 77; |
874 | } |
875 | )**" ; |
876 | |
877 | clang::LangOptions LO; |
878 | LO.CPlusPlus = 1; |
879 | LO.CPlusPlus11 = 1; |
880 | TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts()); |
881 | Compiler.init(TestProgram); |
882 | const BasicBlock *BB = Compiler.compile(); |
883 | |
884 | auto StructInner = MMTuple( |
885 | Args: MMString(Name: "_ZTS5Inner" ), |
886 | Args: MMTuple( |
887 | Args: MMString(Name: "int" ), |
888 | Args: OmnipotentCharCXX, |
889 | Args: MConstInt(V: 0)), |
890 | Args: MConstInt(V: 0)); |
891 | |
892 | auto StructOuter = MMTuple( |
893 | Args: MMString(Name: "_ZTS5Outer" ), |
894 | Args: MMTuple( |
895 | Args: MMString(Name: "short" ), |
896 | Args: OmnipotentCharCXX, |
897 | Args: MConstInt(V: 0)), |
898 | Args: MConstInt(V: 0), |
899 | Args: OmnipotentCharCXX, // FIXME: Info about array field is lost. |
900 | Args: MConstInt(V: 4)); |
901 | |
902 | const Instruction *I = match(BB, |
903 | M: MInstruction(C: Instruction::Store, |
904 | Args: MConstInt(V: 14, W: 16), |
905 | Args: MMTuple( |
906 | Args: StructOuter, |
907 | Args: MMTuple( |
908 | Args: MMString(Name: "short" ), |
909 | Args: OmnipotentCharCXX, |
910 | Args: MConstInt(V: 0)), |
911 | Args: MConstInt(V: 0)))); |
912 | ASSERT_TRUE(I); |
913 | |
914 | I = matchNext(I, |
915 | M: MInstruction(C: Instruction::Store, |
916 | Args: MConstInt(V: 35, W: 32), |
917 | Args: MMTuple( |
918 | Args: StructInner, |
919 | Args: MMTuple( |
920 | Args: MMString(Name: "int" ), |
921 | Args: OmnipotentCharCXX, |
922 | Args: MConstInt(V: 0)), |
923 | Args: MConstInt(V: 0)))); |
924 | ASSERT_TRUE(I); |
925 | |
926 | I = matchNext(I, |
927 | M: MInstruction(C: Instruction::Store, |
928 | Args: MConstInt(V: 77, W: 32), |
929 | Args: MMTuple( |
930 | Args: StructInner, |
931 | Args: MMTuple( |
932 | Args: MMString(Name: "int" ), |
933 | Args: OmnipotentCharCXX, |
934 | Args: MConstInt(V: 0)), |
935 | Args: MConstInt(V: 0)))); |
936 | ASSERT_TRUE(I); |
937 | } |
938 | |
939 | TEST(TBAAMetadataTest, BaseClass) { |
940 | const char TestProgram[] = R"**( |
941 | struct Base { |
942 | int f32; |
943 | }; |
944 | |
945 | struct Derived : public Base { |
946 | short f16; |
947 | }; |
948 | |
949 | void func(Base *B, Derived *D) { |
950 | B->f32 = 14; |
951 | D->f16 = 35; |
952 | D->f32 = 77; |
953 | } |
954 | )**" ; |
955 | |
956 | clang::LangOptions LO; |
957 | LO.CPlusPlus = 1; |
958 | LO.CPlusPlus11 = 1; |
959 | TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts()); |
960 | Compiler.init(TestProgram); |
961 | const BasicBlock *BB = Compiler.compile(); |
962 | |
963 | auto ClassBase = MMTuple( |
964 | Args: MMString(Name: "_ZTS4Base" ), |
965 | Args: MMTuple( |
966 | Args: MMString(Name: "int" ), |
967 | Args: OmnipotentCharCXX, |
968 | Args: MConstInt(V: 0)), |
969 | Args: MConstInt(V: 0)); |
970 | |
971 | auto ClassDerived = |
972 | MMTuple(Args: MMString(Name: "_ZTS7Derived" ), Args: ClassBase, Args: MConstInt(V: 0), |
973 | Args: MMTuple(Args: MMString(Name: "short" ), Args: OmnipotentCharCXX, Args: MConstInt(V: 0)), |
974 | Args: MConstInt(V: 4)); |
975 | |
976 | const Instruction *I = match(BB, |
977 | M: MInstruction(C: Instruction::Store, |
978 | Args: MConstInt(V: 14, W: 32), |
979 | Args: MMTuple( |
980 | Args: ClassBase, |
981 | Args: MMTuple( |
982 | Args: MMString(Name: "int" ), |
983 | Args: OmnipotentCharCXX, |
984 | Args: MConstInt(V: 0)), |
985 | Args: MConstInt(V: 0)))); |
986 | ASSERT_TRUE(I); |
987 | |
988 | I = matchNext(I, |
989 | M: MInstruction(C: Instruction::Store, |
990 | Args: MConstInt(V: 35, W: 16), |
991 | Args: MMTuple( |
992 | Args: ClassDerived, |
993 | Args: MMTuple( |
994 | Args: MMString(Name: "short" ), |
995 | Args: OmnipotentCharCXX, |
996 | Args: MConstInt(V: 0)), |
997 | Args: MConstInt(V: 4)))); |
998 | ASSERT_TRUE(I); |
999 | |
1000 | I = matchNext(I, |
1001 | M: MInstruction(C: Instruction::Store, |
1002 | Args: MConstInt(V: 77, W: 32), |
1003 | Args: MMTuple( |
1004 | Args: ClassBase, |
1005 | Args: MMTuple( |
1006 | Args: MMString(Name: "int" ), |
1007 | Args: OmnipotentCharCXX, |
1008 | Args: MConstInt(V: 0)), |
1009 | Args: MConstInt(V: 0)))); |
1010 | ASSERT_TRUE(I); |
1011 | } |
1012 | |
1013 | TEST(TBAAMetadataTest, PolymorphicClass) { |
1014 | const char TestProgram[] = R"**( |
1015 | struct Base { |
1016 | virtual void m1(int *) = 0; |
1017 | int f32; |
1018 | }; |
1019 | |
1020 | struct Derived : public Base { |
1021 | virtual void m1(int *) override; |
1022 | short f16; |
1023 | }; |
1024 | |
1025 | void func(Base *B, Derived *D) { |
1026 | B->f32 = 14; |
1027 | D->f16 = 35; |
1028 | D->f32 = 77; |
1029 | } |
1030 | )**" ; |
1031 | |
1032 | clang::LangOptions LO; |
1033 | LO.CPlusPlus = 1; |
1034 | LO.CPlusPlus11 = 1; |
1035 | TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts()); |
1036 | Compiler.init(TestProgram); |
1037 | const BasicBlock *BB = Compiler.compile(); |
1038 | |
1039 | auto ClassBase = MMTuple( |
1040 | Args: MMString(Name: "_ZTS4Base" ), |
1041 | Args: MMTuple( |
1042 | Args: MMString(Name: "int" ), |
1043 | Args: OmnipotentCharCXX, |
1044 | Args: MConstInt(V: 0)), |
1045 | Args: MConstInt(V: Compiler.PtrSize)); |
1046 | |
1047 | auto ClassDerived = |
1048 | MMTuple(Args: MMString(Name: "_ZTS7Derived" ), Args: ClassBase, Args: MConstInt(V: 0), |
1049 | Args: MMTuple(Args: MMString(Name: "short" ), Args: OmnipotentCharCXX, Args: MConstInt(V: 0)), |
1050 | Args: MConstInt(V: Compiler.PtrSize + 4)); |
1051 | |
1052 | const Instruction *I = match(BB, |
1053 | M: MInstruction(C: Instruction::Store, |
1054 | Args: MConstInt(V: 14, W: 32), |
1055 | Args: MMTuple( |
1056 | Args: ClassBase, |
1057 | Args: MMTuple( |
1058 | Args: MMString(Name: "int" ), |
1059 | Args: OmnipotentCharCXX, |
1060 | Args: MConstInt(V: 0)), |
1061 | Args: MConstInt(V: Compiler.PtrSize)))); |
1062 | ASSERT_TRUE(I); |
1063 | |
1064 | I = matchNext(I, |
1065 | M: MInstruction(C: Instruction::Store, |
1066 | Args: MConstInt(V: 35, W: 16), |
1067 | Args: MMTuple( |
1068 | Args: ClassDerived, |
1069 | Args: MMTuple( |
1070 | Args: MMString(Name: "short" ), |
1071 | Args: OmnipotentCharCXX, |
1072 | Args: MConstInt(V: 0)), |
1073 | Args: MConstInt(V: Compiler.PtrSize + 4)))); |
1074 | ASSERT_TRUE(I); |
1075 | |
1076 | I = matchNext(I, |
1077 | M: MInstruction(C: Instruction::Store, |
1078 | Args: MConstInt(V: 77, W: 32), |
1079 | Args: MMTuple( |
1080 | Args: ClassBase, |
1081 | Args: MMTuple( |
1082 | Args: MMString(Name: "int" ), |
1083 | Args: OmnipotentCharCXX, |
1084 | Args: MConstInt(V: 0)), |
1085 | Args: MConstInt(V: Compiler.PtrSize)))); |
1086 | ASSERT_TRUE(I); |
1087 | } |
1088 | |
1089 | TEST(TBAAMetadataTest, VirtualBase) { |
1090 | const char TestProgram[] = R"**( |
1091 | struct Base { |
1092 | int f32; |
1093 | }; |
1094 | |
1095 | struct Derived : public virtual Base { |
1096 | short f16; |
1097 | }; |
1098 | |
1099 | void func(Base *B, Derived *D) { |
1100 | B->f32 = 14; |
1101 | D->f16 = 35; |
1102 | D->f32 = 77; |
1103 | } |
1104 | )**" ; |
1105 | |
1106 | clang::LangOptions LO; |
1107 | LO.CPlusPlus = 1; |
1108 | LO.CPlusPlus11 = 1; |
1109 | TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts()); |
1110 | Compiler.init(TestProgram); |
1111 | const BasicBlock *BB = Compiler.compile(); |
1112 | |
1113 | auto ClassBase = MMTuple( |
1114 | Args: MMString(Name: "_ZTS4Base" ), |
1115 | Args: MMTuple( |
1116 | Args: MMString(Name: "int" ), |
1117 | Args: OmnipotentCharCXX, |
1118 | Args: MConstInt(V: 0)), |
1119 | Args: MConstInt(V: 0)); |
1120 | |
1121 | auto ClassDerived = MMTuple( |
1122 | Args: MMString(Name: "_ZTS7Derived" ), |
1123 | Args: MMTuple( |
1124 | Args: MMString(Name: "short" ), |
1125 | Args: OmnipotentCharCXX, |
1126 | Args: MConstInt(V: 0)), |
1127 | Args: MConstInt(V: Compiler.PtrSize)); |
1128 | |
1129 | const Instruction *I = match(BB, |
1130 | M: MInstruction(C: Instruction::Store, |
1131 | Args: MConstInt(V: 14, W: 32), |
1132 | Args: MMTuple( |
1133 | Args: ClassBase, |
1134 | Args: MMTuple( |
1135 | Args: MMString(Name: "int" ), |
1136 | Args: OmnipotentCharCXX, |
1137 | Args: MConstInt(V: 0)), |
1138 | Args: MConstInt(V: 0)))); |
1139 | ASSERT_TRUE(I); |
1140 | |
1141 | I = matchNext(I, |
1142 | M: MInstruction(C: Instruction::Store, |
1143 | Args: MConstInt(V: 35, W: 16), |
1144 | Args: MMTuple( |
1145 | Args: ClassDerived, |
1146 | Args: MMTuple( |
1147 | Args: MMString(Name: "short" ), |
1148 | Args: OmnipotentCharCXX, |
1149 | Args: MConstInt(V: 0)), |
1150 | Args: MConstInt(V: Compiler.PtrSize)))); |
1151 | ASSERT_TRUE(I); |
1152 | |
1153 | I = matchNext(I, |
1154 | M: MInstruction(C: Instruction::Load, |
1155 | Args: MMTuple( |
1156 | Args: MMTuple( |
1157 | Args: MMString(Name: "vtable pointer" ), |
1158 | Args: MMTuple( |
1159 | Args: MMString(Name: "Simple C++ TBAA" )), |
1160 | Args: MConstInt(V: 0)), |
1161 | Args: MSameAs(N: 0), |
1162 | Args: MConstInt(V: 0)))); |
1163 | ASSERT_TRUE(I); |
1164 | |
1165 | I = matchNext(I, |
1166 | M: MInstruction(C: Instruction::Store, |
1167 | Args: MConstInt(V: 77, W: 32), |
1168 | Args: MMTuple( |
1169 | Args: ClassBase, |
1170 | Args: MMTuple( |
1171 | Args: MMString(Name: "int" ), |
1172 | Args: OmnipotentCharCXX, |
1173 | Args: MConstInt(V: 0)), |
1174 | Args: MConstInt(V: 0)))); |
1175 | ASSERT_TRUE(I); |
1176 | } |
1177 | |
1178 | TEST(TBAAMetadataTest, TemplSpec) { |
1179 | const char TestProgram[] = R"**( |
1180 | template<typename T1, typename T2> |
1181 | struct ABC { |
1182 | T1 f1; |
1183 | T2 f2; |
1184 | }; |
1185 | |
1186 | void func(ABC<double, int> *p) { |
1187 | p->f1 = 12.1; |
1188 | p->f2 = 44; |
1189 | } |
1190 | )**" ; |
1191 | |
1192 | clang::LangOptions LO; |
1193 | LO.CPlusPlus = 1; |
1194 | LO.CPlusPlus11 = 1; |
1195 | TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts()); |
1196 | Compiler.init(TestProgram); |
1197 | const BasicBlock *BB = Compiler.compile(); |
1198 | |
1199 | auto SpecABC = MMTuple( |
1200 | Args: MMString(Name: "_ZTS3ABCIdiE" ), |
1201 | Args: MMTuple( |
1202 | Args: MMString(Name: "double" ), |
1203 | Args: OmnipotentCharCXX, |
1204 | Args: MConstInt(V: 0)), |
1205 | Args: MConstInt(V: 0), |
1206 | Args: MMTuple( |
1207 | Args: MMString(Name: "int" ), |
1208 | Args: OmnipotentCharCXX, |
1209 | Args: MConstInt(V: 0)), |
1210 | Args: MConstInt(V: 8)); |
1211 | |
1212 | const Instruction *I = match(BB, |
1213 | M: MInstruction(C: Instruction::Store, |
1214 | Args: MValType(T: MType(C: [](const Type &T)->bool { return T.isDoubleTy(); })), |
1215 | Args: MMTuple( |
1216 | Args: SpecABC, |
1217 | Args: MMTuple( |
1218 | Args: MMString(Name: "double" ), |
1219 | Args: OmnipotentCharCXX, |
1220 | Args: MConstInt(V: 0)), |
1221 | Args: MConstInt(V: 0)))); |
1222 | ASSERT_TRUE(I); |
1223 | |
1224 | I = matchNext(I, |
1225 | M: MInstruction(C: Instruction::Store, |
1226 | Args: MConstInt(V: 44, W: 32), |
1227 | Args: MMTuple( |
1228 | Args: SpecABC, |
1229 | Args: MMTuple( |
1230 | Args: MMString(Name: "int" ), |
1231 | Args: OmnipotentCharCXX, |
1232 | Args: MConstInt(V: 0)), |
1233 | Args: MConstInt(V: 8)))); |
1234 | ASSERT_TRUE(I); |
1235 | } |
1236 | } |
1237 | |