1243 lines
28 KiB
C++
1243 lines
28 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 "TestCompiler.h"
|
||
|
#include "clang/AST/ASTConsumer.h"
|
||
|
#include "clang/AST/ASTContext.h"
|
||
|
#include "clang/Basic/SourceManager.h"
|
||
|
#include "clang/Basic/TargetInfo.h"
|
||
|
#include "llvm/IR/Constants.h"
|
||
|
#include "llvm/Support/MemoryBuffer.h"
|
||
|
#include "gtest/gtest.h"
|
||
|
#include <memory>
|
||
|
|
||
|
using namespace llvm;
|
||
|
|
||
|
namespace {
|
||
|
|
||
|
struct TBAATestCompiler : public TestCompiler {
|
||
|
TBAATestCompiler(clang::LangOptions LO, clang::CodeGenOptions CGO)
|
||
|
: TestCompiler(LO, CGO) {}
|
||
|
static clang::CodeGenOptions getCommonCodeGenOpts() {
|
||
|
clang::CodeGenOptions CGOpts;
|
||
|
CGOpts.StructPathTBAA = 1;
|
||
|
CGOpts.OptimizationLevel = 1;
|
||
|
return CGOpts;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
)**";
|
||
|
|
||
|
clang::LangOptions LO;
|
||
|
TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts());
|
||
|
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;
|
||
|
}
|
||
|
)**";
|
||
|
|
||
|
clang::LangOptions LO;
|
||
|
LO.C11 = 1;
|
||
|
TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts());
|
||
|
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;
|
||
|
}
|
||
|
)**";
|
||
|
|
||
|
clang::LangOptions LO;
|
||
|
LO.C11 = 1;
|
||
|
TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts());
|
||
|
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;
|
||
|
}
|
||
|
)**";
|
||
|
|
||
|
clang::LangOptions LO;
|
||
|
LO.C11 = 1;
|
||
|
TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts());
|
||
|
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;
|
||
|
}
|
||
|
)**";
|
||
|
|
||
|
clang::LangOptions LO;
|
||
|
LO.C11 = 1;
|
||
|
TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts());
|
||
|
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;
|
||
|
}
|
||
|
)**";
|
||
|
|
||
|
clang::LangOptions LO;
|
||
|
LO.CPlusPlus = 1;
|
||
|
LO.CPlusPlus11 = 1;
|
||
|
TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts());
|
||
|
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;
|
||
|
}
|
||
|
)**";
|
||
|
|
||
|
clang::LangOptions LO;
|
||
|
LO.CPlusPlus = 1;
|
||
|
LO.CPlusPlus11 = 1;
|
||
|
TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts());
|
||
|
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;
|
||
|
}
|
||
|
)**";
|
||
|
|
||
|
clang::LangOptions LO;
|
||
|
LO.CPlusPlus = 1;
|
||
|
LO.CPlusPlus11 = 1;
|
||
|
TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts());
|
||
|
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;
|
||
|
}
|
||
|
)**";
|
||
|
|
||
|
clang::LangOptions LO;
|
||
|
LO.CPlusPlus = 1;
|
||
|
LO.CPlusPlus11 = 1;
|
||
|
TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts());
|
||
|
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;
|
||
|
}
|
||
|
)**";
|
||
|
|
||
|
clang::LangOptions LO;
|
||
|
LO.CPlusPlus = 1;
|
||
|
LO.CPlusPlus11 = 1;
|
||
|
TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts());
|
||
|
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;
|
||
|
}
|
||
|
)**";
|
||
|
|
||
|
clang::LangOptions LO;
|
||
|
LO.CPlusPlus = 1;
|
||
|
LO.CPlusPlus11 = 1;
|
||
|
TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts());
|
||
|
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;
|
||
|
}
|
||
|
)**";
|
||
|
|
||
|
clang::LangOptions LO;
|
||
|
LO.CPlusPlus = 1;
|
||
|
LO.CPlusPlus11 = 1;
|
||
|
TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts());
|
||
|
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;
|
||
|
}
|
||
|
)**";
|
||
|
|
||
|
clang::LangOptions LO;
|
||
|
LO.CPlusPlus = 1;
|
||
|
LO.CPlusPlus11 = 1;
|
||
|
TBAATestCompiler Compiler(LO, TBAATestCompiler::getCommonCodeGenOpts());
|
||
|
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);
|
||
|
}
|
||
|
}
|