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