1302 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			1302 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			C++
		
	
	
	
| //=== unittests/CodeGen/TBAAMetadataTest.cpp - Checks metadata generation -===//
 | |
| //
 | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | |
| // See https://llvm.org/LICENSE.txt for license information.
 | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #include "IRMatchers.h"
 | |
| #include "clang/AST/ASTConsumer.h"
 | |
| #include "clang/AST/ASTContext.h"
 | |
| #include "clang/Basic/SourceManager.h"
 | |
| #include "clang/Basic/TargetInfo.h"
 | |
| #include "clang/CodeGen/ModuleBuilder.h"
 | |
| #include "clang/Frontend/CompilerInstance.h"
 | |
| #include "clang/Parse/ParseAST.h"
 | |
| #include "llvm/ADT/Triple.h"
 | |
| #include "llvm/IR/Constants.h"
 | |
| #include "llvm/IR/LLVMContext.h"
 | |
| #include "llvm/IR/Module.h"
 | |
| #include "llvm/Support/Host.h"
 | |
| #include "llvm/Support/MemoryBuffer.h"
 | |
| #include "gtest/gtest.h"
 | |
| #include <memory>
 | |
| 
 | |
| using namespace llvm;
 | |
| 
 | |
| namespace {
 | |
| 
 | |
| struct TestCompiler {
 | |
|   LLVMContext Context;
 | |
|   clang::CompilerInstance compiler;
 | |
|   clang::CodeGenerator *CG = nullptr;
 | |
|   llvm::Module *M = nullptr;
 | |
|   unsigned PtrSize = 0;
 | |
| 
 | |
|   void init(const char *TestProgram) {
 | |
|     compiler.createDiagnostics();
 | |
|     compiler.getCodeGenOpts().StructPathTBAA = 1;
 | |
|     compiler.getCodeGenOpts().OptimizationLevel = 1;
 | |
| 
 | |
|     std::string TrStr = llvm::Triple::normalize(llvm::sys::getProcessTriple());
 | |
|     llvm::Triple Tr(TrStr);
 | |
|     Tr.setOS(Triple::Linux);
 | |
|     Tr.setVendor(Triple::VendorType::UnknownVendor);
 | |
|     Tr.setEnvironment(Triple::EnvironmentType::UnknownEnvironment);
 | |
|     compiler.getTargetOpts().Triple = Tr.getTriple();
 | |
|     compiler.setTarget(clang::TargetInfo::CreateTargetInfo(
 | |
|         compiler.getDiagnostics(),
 | |
|         std::make_shared<clang::TargetOptions>(compiler.getTargetOpts())));
 | |
| 
 | |
|     const clang::TargetInfo &TInfo = compiler.getTarget();
 | |
|     PtrSize = TInfo.getPointerWidth(0) / 8;
 | |
| 
 | |
|     compiler.createFileManager();
 | |
|     compiler.createSourceManager(compiler.getFileManager());
 | |
|     compiler.createPreprocessor(clang::TU_Prefix);
 | |
| 
 | |
|     compiler.createASTContext();
 | |
| 
 | |
|     CG = CreateLLVMCodeGen(
 | |
|         compiler.getDiagnostics(),
 | |
|         "main-module",
 | |
|         compiler.getHeaderSearchOpts(),
 | |
|         compiler.getPreprocessorOpts(),
 | |
|         compiler.getCodeGenOpts(),
 | |
|         Context);
 | |
|     compiler.setASTConsumer(std::unique_ptr<clang::ASTConsumer>(CG));
 | |
| 
 | |
|     compiler.createSema(clang::TU_Prefix, nullptr);
 | |
| 
 | |
|     clang::SourceManager &sm = compiler.getSourceManager();
 | |
|     sm.setMainFileID(sm.createFileID(
 | |
|         llvm::MemoryBuffer::getMemBuffer(TestProgram), clang::SrcMgr::C_User));
 | |
|   }
 | |
| 
 | |
|   const BasicBlock *compile() {
 | |
|     clang::ParseAST(compiler.getSema(), false, false);
 | |
|     M = CG->GetModule();
 | |
| 
 | |
|     // Do not expect more than one function definition.
 | |
|     auto FuncPtr = M->begin();
 | |
|     for (; FuncPtr != M->end(); ++FuncPtr)
 | |
|       if (!FuncPtr->isDeclaration())
 | |
|         break;
 | |
|     assert(FuncPtr != M->end());
 | |
|     const llvm::Function &Func = *FuncPtr;
 | |
|     ++FuncPtr;
 | |
|     for (; FuncPtr != M->end(); ++FuncPtr)
 | |
|       if (!FuncPtr->isDeclaration())
 | |
|         break;
 | |
|     assert(FuncPtr == M->end());
 | |
| 
 | |
|     // The function must consist of single basic block.
 | |
|     auto BBPtr = Func.begin();
 | |
|     assert(Func.begin() != Func.end());
 | |
|     const BasicBlock &BB = *BBPtr;
 | |
|     ++BBPtr;
 | |
|     assert(BBPtr == Func.end());
 | |
| 
 | |
|     return &BB;
 | |
|   }
 | |
| };
 | |
| 
 | |
| 
 | |
| auto OmnipotentCharC = MMTuple(
 | |
|   MMString("omnipotent char"),
 | |
|   MMTuple(
 | |
|     MMString("Simple C/C++ TBAA")),
 | |
|   MConstInt(0, 64)
 | |
| );
 | |
| 
 | |
| 
 | |
| auto OmnipotentCharCXX = MMTuple(
 | |
|   MMString("omnipotent char"),
 | |
|   MMTuple(
 | |
|     MMString("Simple C++ TBAA")),
 | |
|   MConstInt(0, 64)
 | |
| );
 | |
| 
 | |
| 
 | |
| TEST(TBAAMetadataTest, BasicTypes) {
 | |
|   const char TestProgram[] = R"**(
 | |
|     void func(char *CP, short *SP, int *IP, long long *LP, void **VPP,
 | |
|               int **IPP) {
 | |
|       *CP = 4;
 | |
|       *SP = 11;
 | |
|       *IP = 601;
 | |
|       *LP = 604;
 | |
|       *VPP = CP;
 | |
|       *IPP = IP;
 | |
|     }
 | |
|   )**";
 | |
| 
 | |
|   TestCompiler Compiler;
 | |
|   Compiler.compiler.getLangOpts().C11 = 1;
 | |
|   Compiler.init(TestProgram);
 | |
|   const BasicBlock *BB = Compiler.compile();
 | |
| 
 | |
|   const Instruction *I = match(BB,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(4, 8),
 | |
|         MMTuple(
 | |
|           OmnipotentCharC,
 | |
|           MSameAs(0),
 | |
|           MConstInt(0))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   I = matchNext(I,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(11, 16),
 | |
|         MMTuple(
 | |
|           MMTuple(
 | |
|             MMString("short"),
 | |
|             OmnipotentCharC,
 | |
|             MConstInt(0)),
 | |
|           MSameAs(0),
 | |
|           MConstInt(0))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   I = matchNext(I,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(601, 32),
 | |
|         MMTuple(
 | |
|           MMTuple(
 | |
|             MMString("int"),
 | |
|             OmnipotentCharC,
 | |
|             MConstInt(0)),
 | |
|           MSameAs(0),
 | |
|           MConstInt(0))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   I = matchNext(I,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(604, 64),
 | |
|         MMTuple(
 | |
|           MMTuple(
 | |
|             MMString("long long"),
 | |
|             OmnipotentCharC,
 | |
|             MConstInt(0)),
 | |
|           MSameAs(0),
 | |
|           MConstInt(0))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   I = matchNext(I,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MValType(Type::getInt8PtrTy(Compiler.Context)),
 | |
|         MMTuple(
 | |
|           MMTuple(
 | |
|             MMString("any pointer"),
 | |
|             OmnipotentCharC,
 | |
|             MConstInt(0)),
 | |
|           MSameAs(0),
 | |
|           MConstInt(0))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   I = matchNext(I,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MValType(Type::getInt32PtrTy(Compiler.Context)),
 | |
|         MMTuple(
 | |
|           MMTuple(
 | |
|             MMString("any pointer"),
 | |
|             OmnipotentCharC,
 | |
|             MConstInt(0)),
 | |
|           MSameAs(0),
 | |
|           MConstInt(0))));
 | |
|   ASSERT_TRUE(I);
 | |
| }
 | |
| 
 | |
| TEST(TBAAMetadataTest, CFields) {
 | |
|   const char TestProgram[] = R"**(
 | |
|     struct ABC {
 | |
|        short f16;
 | |
|        int f32;
 | |
|        long long f64;
 | |
|        unsigned short f16_2;
 | |
|        unsigned f32_2;
 | |
|        unsigned long long f64_2;
 | |
|     };
 | |
| 
 | |
|     void func(struct ABC *A) {
 | |
|       A->f32 = 4;
 | |
|       A->f16 = 11;
 | |
|       A->f64 = 601;
 | |
|       A->f16_2 = 22;
 | |
|       A->f32_2 = 77;
 | |
|       A->f64_2 = 604;
 | |
|     }
 | |
|   )**";
 | |
| 
 | |
|   TestCompiler Compiler;
 | |
|   Compiler.compiler.getLangOpts().C11 = 1;
 | |
|   Compiler.init(TestProgram);
 | |
|   const BasicBlock *BB = Compiler.compile();
 | |
| 
 | |
|   auto StructABC = MMTuple(
 | |
|     MMString("ABC"),
 | |
|     MMTuple(
 | |
|       MMString("short"),
 | |
|       OmnipotentCharC,
 | |
|       MConstInt(0)),
 | |
|     MConstInt(0),
 | |
|     MMTuple(
 | |
|       MMString("int"),
 | |
|       OmnipotentCharC,
 | |
|       MConstInt(0)),
 | |
|     MConstInt(4),
 | |
|     MMTuple(
 | |
|       MMString("long long"),
 | |
|       OmnipotentCharC,
 | |
|       MConstInt(0)),
 | |
|     MConstInt(8),
 | |
|     MSameAs(1),
 | |
|     MConstInt(16),
 | |
|     MSameAs(3),
 | |
|     MConstInt(20),
 | |
|     MSameAs(5),
 | |
|     MConstInt(24));
 | |
| 
 | |
|   const Instruction *I = match(BB,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(4, 32),
 | |
|         MMTuple(
 | |
|           StructABC,
 | |
|           MMTuple(
 | |
|             MMString("int"),
 | |
|             OmnipotentCharC,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(4))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   I = matchNext(I,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(11, 16),
 | |
|         MMTuple(
 | |
|           StructABC,
 | |
|           MMTuple(
 | |
|             MMString("short"),
 | |
|             OmnipotentCharC,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(0))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   I = matchNext(I,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(601, 64),
 | |
|         MMTuple(
 | |
|           StructABC,
 | |
|           MMTuple(
 | |
|             MMString("long long"),
 | |
|             OmnipotentCharC,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(8))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   I = matchNext(I,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(22, 16),
 | |
|         MMTuple(
 | |
|           StructABC,
 | |
|           MMTuple(
 | |
|             MMString("short"),
 | |
|             OmnipotentCharC,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(16))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   I = matchNext(I,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(77, 32),
 | |
|         MMTuple(
 | |
|           StructABC,
 | |
|           MMTuple(
 | |
|             MMString("int"),
 | |
|             OmnipotentCharC,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(20))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   I = matchNext(I,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(604, 64),
 | |
|         MMTuple(
 | |
|           StructABC,
 | |
|           MMTuple(
 | |
|             MMString("long long"),
 | |
|             OmnipotentCharC,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(24))));
 | |
|   ASSERT_TRUE(I);
 | |
| }
 | |
| 
 | |
| TEST(TBAAMetadataTest, CTypedefFields) {
 | |
|   const char TestProgram[] = R"**(
 | |
|     typedef struct {
 | |
|        short f16;
 | |
|        int f32;
 | |
|     } ABC;
 | |
|     typedef struct {
 | |
|        short value_f16;
 | |
|        int value_f32;
 | |
|     } CDE;
 | |
| 
 | |
|     void func(ABC *A, CDE *B) {
 | |
|       A->f32 = 4;
 | |
|       A->f16 = 11;
 | |
|       B->value_f32 = 44;
 | |
|       B->value_f16 = 111;
 | |
|     }
 | |
|   )**";
 | |
| 
 | |
|   TestCompiler Compiler;
 | |
|   Compiler.compiler.getLangOpts().C11 = 1;
 | |
|   Compiler.init(TestProgram);
 | |
|   const BasicBlock *BB = Compiler.compile();
 | |
| 
 | |
|   auto NamelessStruct = MMTuple(
 | |
|     MMString(""),
 | |
|     MMTuple(
 | |
|       MMString("short"),
 | |
|       OmnipotentCharC,
 | |
|       MConstInt(0)),
 | |
|     MConstInt(0),
 | |
|     MMTuple(
 | |
|       MMString("int"),
 | |
|       OmnipotentCharC,
 | |
|       MConstInt(0)),
 | |
|     MConstInt(4));
 | |
| 
 | |
|   const Metadata *MetaABC = nullptr;
 | |
|   const Instruction *I = match(BB,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(4, 32),
 | |
|         MMTuple(
 | |
|           MMSave(MetaABC, NamelessStruct),
 | |
|           MMTuple(
 | |
|             MMString("int"),
 | |
|             OmnipotentCharC,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(4))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   I = matchNext(I,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(11, 16),
 | |
|         MMTuple(
 | |
|           NamelessStruct,
 | |
|           MMTuple(
 | |
|             MMString("short"),
 | |
|             OmnipotentCharC,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(0))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   const Metadata *MetaCDE = nullptr;
 | |
|   I = matchNext(I,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(44, 32),
 | |
|         MMTuple(
 | |
|           MMSave(MetaCDE, NamelessStruct),
 | |
|           MMTuple(
 | |
|             MMString("int"),
 | |
|             OmnipotentCharC,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(4))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   I = matchNext(I,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(111, 16),
 | |
|         MMTuple(
 | |
|           NamelessStruct,
 | |
|           MMTuple(
 | |
|             MMString("short"),
 | |
|             OmnipotentCharC,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(0))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   // FIXME: Nameless structures used in definitions of 'ABC' and 'CDE' are
 | |
|   // different structures and must be described by different descriptors.
 | |
|   //ASSERT_TRUE(MetaABC != MetaCDE);
 | |
| }
 | |
| 
 | |
| TEST(TBAAMetadataTest, CTypedefFields2) {
 | |
|   const char TestProgram[] = R"**(
 | |
|     typedef struct {
 | |
|        short f16;
 | |
|        int f32;
 | |
|     } ABC;
 | |
|     typedef struct {
 | |
|        short f16;
 | |
|        int f32;
 | |
|     } CDE;
 | |
| 
 | |
|     void func(ABC *A, CDE *B) {
 | |
|       A->f32 = 4;
 | |
|       A->f16 = 11;
 | |
|       B->f32 = 44;
 | |
|       B->f16 = 111;
 | |
|     }
 | |
|   )**";
 | |
| 
 | |
|   TestCompiler Compiler;
 | |
|   Compiler.compiler.getLangOpts().C11 = 1;
 | |
|   Compiler.init(TestProgram);
 | |
|   const BasicBlock *BB = Compiler.compile();
 | |
| 
 | |
|   auto NamelessStruct = MMTuple(
 | |
|     MMString(""),
 | |
|     MMTuple(
 | |
|       MMString("short"),
 | |
|       OmnipotentCharC,
 | |
|       MConstInt(0)),
 | |
|     MConstInt(0),
 | |
|     MMTuple(
 | |
|       MMString("int"),
 | |
|       OmnipotentCharC,
 | |
|       MConstInt(0)),
 | |
|     MConstInt(4));
 | |
| 
 | |
|   const Metadata *MetaABC = nullptr;
 | |
|   const Instruction *I = match(BB,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(4, 32),
 | |
|         MMTuple(
 | |
|           MMSave(MetaABC, NamelessStruct),
 | |
|           MMTuple(
 | |
|             MMString("int"),
 | |
|             OmnipotentCharC,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(4))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   I = matchNext(I,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(11, 16),
 | |
|         MMTuple(
 | |
|           NamelessStruct,
 | |
|           MMTuple(
 | |
|             MMString("short"),
 | |
|             OmnipotentCharC,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(0))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   const Metadata *MetaCDE = nullptr;
 | |
|   I = matchNext(I,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(44, 32),
 | |
|         MMTuple(
 | |
|           MMSave(MetaCDE, NamelessStruct),
 | |
|           MMTuple(
 | |
|             MMString("int"),
 | |
|             OmnipotentCharC,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(4))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   I = matchNext(I,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(111, 16),
 | |
|         MMTuple(
 | |
|           NamelessStruct,
 | |
|           MMTuple(
 | |
|             MMString("short"),
 | |
|             OmnipotentCharC,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(0))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   // FIXME: Nameless structures used in definitions of 'ABC' and 'CDE' are
 | |
|   // different structures, although they have the same field sequence. They must
 | |
|   // be described by different descriptors.
 | |
|   //ASSERT_TRUE(MetaABC != MetaCDE);
 | |
| }
 | |
| 
 | |
| TEST(TBAAMetadataTest, CTypedefFields3) {
 | |
|   const char TestProgram[] = R"**(
 | |
|     typedef struct {
 | |
|        short f16;
 | |
|        int f32;
 | |
|     } ABC;
 | |
|     typedef struct {
 | |
|        int f32;
 | |
|        short f16;
 | |
|     } CDE;
 | |
| 
 | |
|     void func(ABC *A, CDE *B) {
 | |
|       A->f32 = 4;
 | |
|       A->f16 = 11;
 | |
|       B->f32 = 44;
 | |
|       B->f16 = 111;
 | |
|     }
 | |
|   )**";
 | |
| 
 | |
|   TestCompiler Compiler;
 | |
|   Compiler.compiler.getLangOpts().C11 = 1;
 | |
|   Compiler.init(TestProgram);
 | |
|   const BasicBlock *BB = Compiler.compile();
 | |
| 
 | |
|   auto NamelessStruct1 = MMTuple(
 | |
|     MMString(""),
 | |
|     MMTuple(
 | |
|       MMString("short"),
 | |
|       OmnipotentCharC,
 | |
|       MConstInt(0)),
 | |
|     MConstInt(0),
 | |
|     MMTuple(
 | |
|       MMString("int"),
 | |
|       OmnipotentCharC,
 | |
|       MConstInt(0)),
 | |
|     MConstInt(4));
 | |
| 
 | |
|   auto NamelessStruct2 = MMTuple(
 | |
|     MMString(""),
 | |
|     MMTuple(
 | |
|       MMString("int"),
 | |
|       OmnipotentCharC,
 | |
|       MConstInt(0)),
 | |
|     MConstInt(0),
 | |
|     MMTuple(
 | |
|       MMString("short"),
 | |
|       OmnipotentCharC,
 | |
|       MConstInt(0)),
 | |
|     MConstInt(4));
 | |
| 
 | |
|   const Instruction *I = match(BB,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(4, 32),
 | |
|         MMTuple(
 | |
|           NamelessStruct1,
 | |
|           MMTuple(
 | |
|             MMString("int"),
 | |
|             OmnipotentCharC,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(4))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   I = matchNext(I,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(11, 16),
 | |
|         MMTuple(
 | |
|           NamelessStruct1,
 | |
|           MMTuple(
 | |
|             MMString("short"),
 | |
|             OmnipotentCharC,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(0))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   I = matchNext(I,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(44, 32),
 | |
|         MMTuple(
 | |
|           NamelessStruct2,
 | |
|           MMTuple(
 | |
|             MMString("int"),
 | |
|             OmnipotentCharC,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(0))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   I = matchNext(I,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(111, 16),
 | |
|         MMTuple(
 | |
|           NamelessStruct2,
 | |
|           MMTuple(
 | |
|             MMString("short"),
 | |
|             OmnipotentCharC,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(4))));
 | |
|   ASSERT_TRUE(I);
 | |
| }
 | |
| 
 | |
| TEST(TBAAMetadataTest, CXXFields) {
 | |
|   const char TestProgram[] = R"**(
 | |
|     struct ABC {
 | |
|        short f16;
 | |
|        int f32;
 | |
|        long long f64;
 | |
|        unsigned short f16_2;
 | |
|        unsigned f32_2;
 | |
|        unsigned long long f64_2;
 | |
|     };
 | |
| 
 | |
|     void func(struct ABC *A) {
 | |
|       A->f32 = 4;
 | |
|       A->f16 = 11;
 | |
|       A->f64 = 601;
 | |
|       A->f16_2 = 22;
 | |
|       A->f32_2 = 77;
 | |
|       A->f64_2 = 604;
 | |
|     }
 | |
|   )**";
 | |
| 
 | |
|   TestCompiler Compiler;
 | |
|   Compiler.compiler.getLangOpts().CPlusPlus = 1;
 | |
|   Compiler.compiler.getLangOpts().CPlusPlus11 = 1;
 | |
|   Compiler.init(TestProgram);
 | |
|   const BasicBlock *BB = Compiler.compile();
 | |
| 
 | |
|   auto StructABC = MMTuple(
 | |
|     MMString("_ZTS3ABC"),
 | |
|     MMTuple(
 | |
|       MMString("short"),
 | |
|       OmnipotentCharCXX,
 | |
|       MConstInt(0)),
 | |
|     MConstInt(0),
 | |
|     MMTuple(
 | |
|       MMString("int"),
 | |
|       OmnipotentCharCXX,
 | |
|       MConstInt(0)),
 | |
|     MConstInt(4),
 | |
|     MMTuple(
 | |
|       MMString("long long"),
 | |
|       OmnipotentCharCXX,
 | |
|       MConstInt(0)),
 | |
|     MConstInt(8),
 | |
|     MSameAs(1),
 | |
|     MConstInt(16),
 | |
|     MSameAs(3),
 | |
|     MConstInt(20),
 | |
|     MSameAs(5),
 | |
|     MConstInt(24));
 | |
| 
 | |
|   const Instruction *I = match(BB,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(4, 32),
 | |
|         MMTuple(
 | |
|           StructABC,
 | |
|           MMTuple(
 | |
|             MMString("int"),
 | |
|             OmnipotentCharCXX,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(4))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   I = matchNext(I,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(11, 16),
 | |
|         MMTuple(
 | |
|           StructABC,
 | |
|           MMTuple(
 | |
|             MMString("short"),
 | |
|             OmnipotentCharCXX,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(0))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   I = matchNext(I,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(601, 64),
 | |
|         MMTuple(
 | |
|           StructABC,
 | |
|           MMTuple(
 | |
|             MMString("long long"),
 | |
|             OmnipotentCharCXX,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(8))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   I = matchNext(I,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(22, 16),
 | |
|         MMTuple(
 | |
|           StructABC,
 | |
|           MMTuple(
 | |
|             MMString("short"),
 | |
|             OmnipotentCharCXX,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(16))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   I = matchNext(I,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(77, 32),
 | |
|         MMTuple(
 | |
|           StructABC,
 | |
|           MMTuple(
 | |
|             MMString("int"),
 | |
|             OmnipotentCharCXX,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(20))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   I = matchNext(I,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(604, 64),
 | |
|         MMTuple(
 | |
|           StructABC,
 | |
|           MMTuple(
 | |
|             MMString("long long"),
 | |
|             OmnipotentCharCXX,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(24))));
 | |
|   ASSERT_TRUE(I);
 | |
| }
 | |
| 
 | |
| TEST(TBAAMetadataTest, CXXTypedefFields) {
 | |
|   const char TestProgram[] = R"**(
 | |
|     typedef struct {
 | |
|        short f16;
 | |
|        int f32;
 | |
|     } ABC;
 | |
|     typedef struct {
 | |
|        short value_f16;
 | |
|        int value_f32;
 | |
|     } CDE;
 | |
| 
 | |
|     void func(ABC *A, CDE *B) {
 | |
|       A->f32 = 4;
 | |
|       A->f16 = 11;
 | |
|       B->value_f32 = 44;
 | |
|       B->value_f16 = 111;
 | |
|     }
 | |
|   )**";
 | |
| 
 | |
|   TestCompiler Compiler;
 | |
|   Compiler.compiler.getLangOpts().CPlusPlus = 1;
 | |
|   Compiler.compiler.getLangOpts().CPlusPlus11 = 1;
 | |
|   Compiler.init(TestProgram);
 | |
|   const BasicBlock *BB = Compiler.compile();
 | |
| 
 | |
|   auto StructABC = MMTuple(
 | |
|     MMString("_ZTS3ABC"),
 | |
|     MMTuple(
 | |
|       MMString("short"),
 | |
|       OmnipotentCharCXX,
 | |
|       MConstInt(0)),
 | |
|     MConstInt(0),
 | |
|     MMTuple(
 | |
|       MMString("int"),
 | |
|       OmnipotentCharCXX,
 | |
|       MConstInt(0)),
 | |
|     MConstInt(4));
 | |
| 
 | |
|   auto StructCDE = MMTuple(
 | |
|     MMString("_ZTS3CDE"),
 | |
|     MMTuple(
 | |
|       MMString("short"),
 | |
|       OmnipotentCharCXX,
 | |
|       MConstInt(0)),
 | |
|     MConstInt(0),
 | |
|     MMTuple(
 | |
|       MMString("int"),
 | |
|       OmnipotentCharCXX,
 | |
|       MConstInt(0)),
 | |
|     MConstInt(4));
 | |
| 
 | |
|   const Instruction *I = match(BB,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(4, 32),
 | |
|         MMTuple(
 | |
|           StructABC,
 | |
|           MMTuple(
 | |
|             MMString("int"),
 | |
|             OmnipotentCharCXX,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(4))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   I = matchNext(I,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(11, 16),
 | |
|         MMTuple(
 | |
|           StructABC,
 | |
|           MMTuple(
 | |
|             MMString("short"),
 | |
|             OmnipotentCharCXX,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(0))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   I = matchNext(I,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(44, 32),
 | |
|         MMTuple(
 | |
|           StructCDE,
 | |
|           MMTuple(
 | |
|             MMString("int"),
 | |
|             OmnipotentCharCXX,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(4))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   I = matchNext(I,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(111, 16),
 | |
|         MMTuple(
 | |
|           StructCDE,
 | |
|           MMTuple(
 | |
|             MMString("short"),
 | |
|             OmnipotentCharCXX,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(0))));
 | |
|   ASSERT_TRUE(I);
 | |
| }
 | |
| 
 | |
| TEST(TBAAMetadataTest, StructureFields) {
 | |
|   const char TestProgram[] = R"**(
 | |
|     struct Inner {
 | |
|       int f32;
 | |
|     };
 | |
| 
 | |
|     struct Outer {
 | |
|       short f16;
 | |
|       Inner b1;
 | |
|       Inner b2;
 | |
|     };
 | |
| 
 | |
|     void func(Outer *S) {
 | |
|       S->f16 = 14;
 | |
|       S->b1.f32 = 35;
 | |
|       S->b2.f32 = 77;
 | |
|     }
 | |
|   )**";
 | |
| 
 | |
|   TestCompiler Compiler;
 | |
|   Compiler.compiler.getLangOpts().CPlusPlus = 1;
 | |
|   Compiler.compiler.getLangOpts().CPlusPlus11 = 1;
 | |
|   Compiler.init(TestProgram);
 | |
|   const BasicBlock *BB = Compiler.compile();
 | |
| 
 | |
|   auto StructInner = MMTuple(
 | |
|     MMString("_ZTS5Inner"),
 | |
|     MMTuple(
 | |
|       MMString("int"),
 | |
|       OmnipotentCharCXX,
 | |
|       MConstInt(0)),
 | |
|     MConstInt(0));
 | |
| 
 | |
|   auto StructOuter = MMTuple(
 | |
|     MMString("_ZTS5Outer"),
 | |
|     MMTuple(
 | |
|       MMString("short"),
 | |
|       OmnipotentCharCXX,
 | |
|       MConstInt(0)),
 | |
|     MConstInt(0),
 | |
|     StructInner,
 | |
|     MConstInt(4),
 | |
|     MSameAs(3),
 | |
|     MConstInt(8));
 | |
| 
 | |
|   const Instruction *I = match(BB,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(14, 16),
 | |
|         MMTuple(
 | |
|           StructOuter,
 | |
|           MMTuple(
 | |
|             MMString("short"),
 | |
|             OmnipotentCharCXX,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(0))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   I = matchNext(I,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(35, 32),
 | |
|         MMTuple(
 | |
|           StructOuter,
 | |
|           MMTuple(
 | |
|             MMString("int"),
 | |
|             OmnipotentCharCXX,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(4))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   I = matchNext(I,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(77, 32),
 | |
|         MMTuple(
 | |
|           StructOuter,
 | |
|           MMTuple(
 | |
|             MMString("int"),
 | |
|             OmnipotentCharCXX,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(8))));
 | |
|   ASSERT_TRUE(I);
 | |
| }
 | |
| 
 | |
| TEST(TBAAMetadataTest, ArrayFields) {
 | |
|   const char TestProgram[] = R"**(
 | |
|     struct Inner {
 | |
|       int f32;
 | |
|     };
 | |
| 
 | |
|     struct Outer {
 | |
|       short f16;
 | |
|       Inner b1[2];
 | |
|     };
 | |
| 
 | |
|     void func(Outer *S) {
 | |
|       S->f16 = 14;
 | |
|       S->b1[0].f32 = 35;
 | |
|       S->b1[1].f32 = 77;
 | |
|     }
 | |
|   )**";
 | |
| 
 | |
|   TestCompiler Compiler;
 | |
|   Compiler.compiler.getLangOpts().CPlusPlus = 1;
 | |
|   Compiler.compiler.getLangOpts().CPlusPlus11 = 1;
 | |
|   Compiler.init(TestProgram);
 | |
|   const BasicBlock *BB = Compiler.compile();
 | |
| 
 | |
|   auto StructInner = MMTuple(
 | |
|     MMString("_ZTS5Inner"),
 | |
|     MMTuple(
 | |
|       MMString("int"),
 | |
|       OmnipotentCharCXX,
 | |
|       MConstInt(0)),
 | |
|     MConstInt(0));
 | |
| 
 | |
|   auto StructOuter = MMTuple(
 | |
|     MMString("_ZTS5Outer"),
 | |
|     MMTuple(
 | |
|       MMString("short"),
 | |
|       OmnipotentCharCXX,
 | |
|       MConstInt(0)),
 | |
|     MConstInt(0),
 | |
|     OmnipotentCharCXX,    // FIXME: Info about array field is lost.
 | |
|     MConstInt(4));
 | |
| 
 | |
|   const Instruction *I = match(BB,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(14, 16),
 | |
|         MMTuple(
 | |
|           StructOuter,
 | |
|           MMTuple(
 | |
|             MMString("short"),
 | |
|             OmnipotentCharCXX,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(0))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   I = matchNext(I,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(35, 32),
 | |
|         MMTuple(
 | |
|           StructInner,
 | |
|           MMTuple(
 | |
|             MMString("int"),
 | |
|             OmnipotentCharCXX,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(0))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   I = matchNext(I,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(77, 32),
 | |
|         MMTuple(
 | |
|           StructInner,
 | |
|           MMTuple(
 | |
|             MMString("int"),
 | |
|             OmnipotentCharCXX,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(0))));
 | |
|   ASSERT_TRUE(I);
 | |
| }
 | |
| 
 | |
| TEST(TBAAMetadataTest, BaseClass) {
 | |
|   const char TestProgram[] = R"**(
 | |
|     struct Base {
 | |
|       int f32;
 | |
|     };
 | |
| 
 | |
|     struct Derived : public Base {
 | |
|       short f16;
 | |
|     };
 | |
| 
 | |
|     void func(Base *B, Derived *D) {
 | |
|       B->f32 = 14;
 | |
|       D->f16 = 35;
 | |
|       D->f32 = 77;
 | |
|     }
 | |
|   )**";
 | |
| 
 | |
|   TestCompiler Compiler;
 | |
|   Compiler.compiler.getLangOpts().CPlusPlus = 1;
 | |
|   Compiler.compiler.getLangOpts().CPlusPlus11 = 1;
 | |
|   Compiler.init(TestProgram);
 | |
|   const BasicBlock *BB = Compiler.compile();
 | |
| 
 | |
|   auto ClassBase = MMTuple(
 | |
|     MMString("_ZTS4Base"),
 | |
|     MMTuple(
 | |
|       MMString("int"),
 | |
|       OmnipotentCharCXX,
 | |
|       MConstInt(0)),
 | |
|     MConstInt(0));
 | |
| 
 | |
|   auto ClassDerived = MMTuple(
 | |
|     MMString("_ZTS7Derived"),
 | |
|     MMTuple(
 | |
|       MMString("short"),
 | |
|       OmnipotentCharCXX,
 | |
|       MConstInt(0)),
 | |
|     MConstInt(4));
 | |
| 
 | |
|   const Instruction *I = match(BB,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(14, 32),
 | |
|         MMTuple(
 | |
|           ClassBase,
 | |
|           MMTuple(
 | |
|             MMString("int"),
 | |
|             OmnipotentCharCXX,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(0))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   I = matchNext(I,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(35, 16),
 | |
|         MMTuple(
 | |
|           ClassDerived,
 | |
|           MMTuple(
 | |
|             MMString("short"),
 | |
|             OmnipotentCharCXX,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(4))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   I = matchNext(I,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(77, 32),
 | |
|         MMTuple(
 | |
|           ClassBase,
 | |
|           MMTuple(
 | |
|             MMString("int"),
 | |
|             OmnipotentCharCXX,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(0))));
 | |
|   ASSERT_TRUE(I);
 | |
| }
 | |
| 
 | |
| TEST(TBAAMetadataTest, PolymorphicClass) {
 | |
|   const char TestProgram[] = R"**(
 | |
|     struct Base {
 | |
|       virtual void m1(int *) = 0;
 | |
|       int f32;
 | |
|     };
 | |
| 
 | |
|     struct Derived : public Base {
 | |
|       virtual void m1(int *) override;
 | |
|       short f16;
 | |
|     };
 | |
| 
 | |
|     void func(Base *B, Derived *D) {
 | |
|       B->f32 = 14;
 | |
|       D->f16 = 35;
 | |
|       D->f32 = 77;
 | |
|     }
 | |
|   )**";
 | |
| 
 | |
|   TestCompiler Compiler;
 | |
|   Compiler.compiler.getLangOpts().CPlusPlus = 1;
 | |
|   Compiler.compiler.getLangOpts().CPlusPlus11 = 1;
 | |
|   Compiler.init(TestProgram);
 | |
|   const BasicBlock *BB = Compiler.compile();
 | |
| 
 | |
|   auto ClassBase = MMTuple(
 | |
|     MMString("_ZTS4Base"),
 | |
|     MMTuple(
 | |
|       MMString("int"),
 | |
|       OmnipotentCharCXX,
 | |
|       MConstInt(0)),
 | |
|     MConstInt(Compiler.PtrSize));
 | |
| 
 | |
|   auto ClassDerived = MMTuple(
 | |
|     MMString("_ZTS7Derived"),
 | |
|     MMTuple(
 | |
|       MMString("short"),
 | |
|       OmnipotentCharCXX,
 | |
|       MConstInt(0)),
 | |
|     MConstInt(Compiler.PtrSize + 4));
 | |
| 
 | |
|   const Instruction *I = match(BB,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(14, 32),
 | |
|         MMTuple(
 | |
|           ClassBase,
 | |
|           MMTuple(
 | |
|             MMString("int"),
 | |
|             OmnipotentCharCXX,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(Compiler.PtrSize))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   I = matchNext(I,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(35, 16),
 | |
|         MMTuple(
 | |
|           ClassDerived,
 | |
|           MMTuple(
 | |
|             MMString("short"),
 | |
|             OmnipotentCharCXX,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(Compiler.PtrSize + 4))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   I = matchNext(I,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(77, 32),
 | |
|         MMTuple(
 | |
|           ClassBase,
 | |
|           MMTuple(
 | |
|             MMString("int"),
 | |
|             OmnipotentCharCXX,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(Compiler.PtrSize))));
 | |
|   ASSERT_TRUE(I);
 | |
| }
 | |
| 
 | |
| TEST(TBAAMetadataTest, VirtualBase) {
 | |
|   const char TestProgram[] = R"**(
 | |
|     struct Base {
 | |
|       int f32;
 | |
|     };
 | |
| 
 | |
|     struct Derived : public virtual Base {
 | |
|       short f16;
 | |
|     };
 | |
| 
 | |
|     void func(Base *B, Derived *D) {
 | |
|       B->f32 = 14;
 | |
|       D->f16 = 35;
 | |
|       D->f32 = 77;
 | |
|     }
 | |
|   )**";
 | |
| 
 | |
|   TestCompiler Compiler;
 | |
|   Compiler.compiler.getLangOpts().CPlusPlus = 1;
 | |
|   Compiler.compiler.getLangOpts().CPlusPlus11 = 1;
 | |
|   Compiler.init(TestProgram);
 | |
|   const BasicBlock *BB = Compiler.compile();
 | |
| 
 | |
|   auto ClassBase = MMTuple(
 | |
|     MMString("_ZTS4Base"),
 | |
|     MMTuple(
 | |
|       MMString("int"),
 | |
|       OmnipotentCharCXX,
 | |
|       MConstInt(0)),
 | |
|     MConstInt(0));
 | |
| 
 | |
|   auto ClassDerived = MMTuple(
 | |
|     MMString("_ZTS7Derived"),
 | |
|     MMTuple(
 | |
|       MMString("short"),
 | |
|       OmnipotentCharCXX,
 | |
|       MConstInt(0)),
 | |
|     MConstInt(Compiler.PtrSize));
 | |
| 
 | |
|   const Instruction *I = match(BB,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(14, 32),
 | |
|         MMTuple(
 | |
|           ClassBase,
 | |
|           MMTuple(
 | |
|             MMString("int"),
 | |
|             OmnipotentCharCXX,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(0))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   I = matchNext(I,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(35, 16),
 | |
|         MMTuple(
 | |
|           ClassDerived,
 | |
|           MMTuple(
 | |
|             MMString("short"),
 | |
|             OmnipotentCharCXX,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(Compiler.PtrSize))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   I = matchNext(I,
 | |
|       MInstruction(Instruction::Load,
 | |
|         MMTuple(
 | |
|           MMTuple(
 | |
|             MMString("vtable pointer"),
 | |
|             MMTuple(
 | |
|               MMString("Simple C++ TBAA")),
 | |
|             MConstInt(0)),
 | |
|           MSameAs(0),
 | |
|           MConstInt(0))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   I = matchNext(I,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(77, 32),
 | |
|         MMTuple(
 | |
|           ClassBase,
 | |
|           MMTuple(
 | |
|             MMString("int"),
 | |
|             OmnipotentCharCXX,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(0))));
 | |
|   ASSERT_TRUE(I);
 | |
| }
 | |
| 
 | |
| TEST(TBAAMetadataTest, TemplSpec) {
 | |
|   const char TestProgram[] = R"**(
 | |
|     template<typename T1, typename T2>
 | |
|     struct ABC {
 | |
|       T1 f1;
 | |
|       T2 f2;
 | |
|     };
 | |
| 
 | |
|     void func(ABC<double, int> *p) {
 | |
|       p->f1 = 12.1;
 | |
|       p->f2 = 44;
 | |
|     }
 | |
|   )**";
 | |
| 
 | |
|   TestCompiler Compiler;
 | |
|   Compiler.compiler.getLangOpts().CPlusPlus = 1;
 | |
|   Compiler.compiler.getLangOpts().CPlusPlus11 = 1;
 | |
|   Compiler.init(TestProgram);
 | |
|   const BasicBlock *BB = Compiler.compile();
 | |
| 
 | |
|   auto SpecABC = MMTuple(
 | |
|     MMString("_ZTS3ABCIdiE"),
 | |
|     MMTuple(
 | |
|       MMString("double"),
 | |
|       OmnipotentCharCXX,
 | |
|       MConstInt(0)),
 | |
|     MConstInt(0),
 | |
|     MMTuple(
 | |
|       MMString("int"),
 | |
|       OmnipotentCharCXX,
 | |
|       MConstInt(0)),
 | |
|     MConstInt(8));
 | |
| 
 | |
|   const Instruction *I = match(BB,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MValType(MType([](const Type &T)->bool { return T.isDoubleTy(); })),
 | |
|         MMTuple(
 | |
|           SpecABC,
 | |
|           MMTuple(
 | |
|             MMString("double"),
 | |
|             OmnipotentCharCXX,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(0))));
 | |
|   ASSERT_TRUE(I);
 | |
| 
 | |
|   I = matchNext(I,
 | |
|       MInstruction(Instruction::Store,
 | |
|         MConstInt(44, 32),
 | |
|         MMTuple(
 | |
|           SpecABC,
 | |
|           MMTuple(
 | |
|             MMString("int"),
 | |
|             OmnipotentCharCXX,
 | |
|             MConstInt(0)),
 | |
|           MConstInt(8))));
 | |
|   ASSERT_TRUE(I);
 | |
| }
 | |
| }
 |