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