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