|
@@ -0,0 +1,1299 @@
|
|
|
+//=== unittests/CodeGen/TBAAMetadataTest.cpp - Checks metadata generation -===//
|
|
|
+//
|
|
|
+// The LLVM Compiler Infrastructure
|
|
|
+//
|
|
|
+// This file is distributed under the University of Illinois Open Source
|
|
|
+// License. See LICENSE.TXT for details.
|
|
|
+//
|
|
|
+//===----------------------------------------------------------------------===//
|
|
|
+
|
|
|
+#include "IRMatchers.h"
|
|
|
+#include "clang/AST/ASTConsumer.h"
|
|
|
+#include "clang/AST/ASTContext.h"
|
|
|
+#include "clang/CodeGen/ModuleBuilder.h"
|
|
|
+#include "clang/Frontend/CompilerInstance.h"
|
|
|
+#include "clang/Parse/ParseAST.h"
|
|
|
+#include "llvm/ADT/Triple.h"
|
|
|
+#include "llvm/IR/LLVMContext.h"
|
|
|
+#include "llvm/IR/Constants.h"
|
|
|
+#include "llvm/IR/Module.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);
|
|
|
+}
|
|
|
+}
|