forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			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);
 | 
						|
}
 | 
						|
}
 |