blob: 880caa7137a4449dbe1074f0b288842635b15152 [file] [log] [blame]
//===- TypesTest.cpp ------------------------------------------------------===//
//
// 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 "llvm/ADT/SmallPtrSet.h"
#include "llvm/AsmParser/Parser.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Module.h"
#include "llvm/SandboxIR/Constant.h"
#include "llvm/SandboxIR/Context.h"
#include "llvm/SandboxIR/Function.h"
#include "llvm/Support/SourceMgr.h"
#include "gtest/gtest.h"
using namespace llvm;
struct SandboxTypeTest : public testing::Test {
LLVMContext C;
std::unique_ptr<Module> M;
void parseIR(LLVMContext &C, const char *IR) {
SMDiagnostic Err;
M = parseAssemblyString(IR, Err, C);
if (!M)
Err.print("SandboxTypeTest", errs());
}
BasicBlock *getBasicBlockByName(Function &F, StringRef Name) {
for (BasicBlock &BB : F)
if (BB.getName() == Name)
return &BB;
llvm_unreachable("Expected to find basic block!");
}
};
TEST_F(SandboxTypeTest, Type) {
parseIR(C, R"IR(
define void @foo(i32 %v0) {
ret void
}
)IR");
llvm::Function *LLVMF = &*M->getFunction("foo");
sandboxir::Context Ctx(C);
auto *F = Ctx.createFunction(LLVMF);
sandboxir::Type *I32Ty = F->getArg(0)->getType();
auto *LLVMInt32Ty = llvm::Type::getInt32Ty(C);
auto *LLVMFloatTy = llvm::Type::getFloatTy(C);
auto *LLVMInt8Ty = llvm::Type::getInt8Ty(C);
auto *Int32Ty = Ctx.getType(LLVMInt32Ty);
auto *FloatTy = Ctx.getType(LLVMFloatTy);
// Check print().
std::string Buff1;
raw_string_ostream BS1(Buff1);
Int32Ty->print(BS1, /*IsForDebug=*/true, /*NoDetails=*/false);
std::string Buff2;
raw_string_ostream BS2(Buff2);
LLVMInt32Ty->print(BS2, /*IsForDebug=*/true, /*NoDetails=*/false);
EXPECT_EQ(Buff1, Buff2);
// Check getContext().
EXPECT_EQ(&I32Ty->getContext(), &Ctx);
// Check that Ctx.getType(nullptr) == nullptr.
EXPECT_EQ(Ctx.getType(nullptr), nullptr);
#define CHK(LLVMCreate, SBCheck) \
Ctx.getType(llvm::Type::LLVMCreate(C))->SBCheck()
// Check isVoidTy().
EXPECT_TRUE(Ctx.getType(llvm::Type::getVoidTy(C))->isVoidTy());
EXPECT_TRUE(CHK(getVoidTy, isVoidTy));
// Check isHalfTy().
EXPECT_TRUE(CHK(getHalfTy, isHalfTy));
// Check isBFloatTy().
EXPECT_TRUE(CHK(getBFloatTy, isBFloatTy));
// Check is16bitFPTy().
EXPECT_TRUE(CHK(getHalfTy, is16bitFPTy));
// Check isFloatTy().
EXPECT_TRUE(CHK(getFloatTy, isFloatTy));
// Check isDoubleTy().
EXPECT_TRUE(CHK(getDoubleTy, isDoubleTy));
// Check isX86_FP80Ty().
EXPECT_TRUE(CHK(getX86_FP80Ty, isX86_FP80Ty));
// Check isFP128Ty().
EXPECT_TRUE(CHK(getFP128Ty, isFP128Ty));
// Check isPPC_FP128Ty().
EXPECT_TRUE(CHK(getPPC_FP128Ty, isPPC_FP128Ty));
// Check isIEEELikeFPTy().
EXPECT_TRUE(CHK(getFloatTy, isIEEELikeFPTy));
// Check isFloatingPointTy().
EXPECT_TRUE(CHK(getFloatTy, isFloatingPointTy));
EXPECT_TRUE(CHK(getDoubleTy, isFloatingPointTy));
// Check isMultiUnitFPType().
EXPECT_TRUE(CHK(getPPC_FP128Ty, isMultiUnitFPType));
EXPECT_FALSE(CHK(getFloatTy, isMultiUnitFPType));
// Check getFltSemantics().
EXPECT_EQ(&sandboxir::Type::getFloatTy(Ctx)->getFltSemantics(),
&llvm::Type::getFloatTy(C)->getFltSemantics());
// Check isX86_AMXTy().
EXPECT_TRUE(CHK(getX86_AMXTy, isX86_AMXTy));
// Check isTargetExtTy().
EXPECT_TRUE(Ctx.getType(llvm::TargetExtType::get(C, "foo"))->isTargetExtTy());
// Check isScalableTargetExtTy().
EXPECT_TRUE(Ctx.getType(llvm::TargetExtType::get(C, "aarch64.svcount"))
->isScalableTargetExtTy());
// Check isScalableTy().
EXPECT_TRUE(Ctx.getType(llvm::ScalableVectorType::get(LLVMInt32Ty, 2u))
->isScalableTy());
// Check isFPOrFPVectorTy().
EXPECT_TRUE(CHK(getFloatTy, isFPOrFPVectorTy));
EXPECT_FALSE(CHK(getInt32Ty, isFPOrFPVectorTy));
// Check isLabelTy().
EXPECT_TRUE(CHK(getLabelTy, isLabelTy));
// Check isMetadataTy().
EXPECT_TRUE(CHK(getMetadataTy, isMetadataTy));
// Check isTokenTy().
EXPECT_TRUE(CHK(getTokenTy, isTokenTy));
// Check isIntegerTy().
EXPECT_TRUE(CHK(getInt32Ty, isIntegerTy));
EXPECT_FALSE(CHK(getFloatTy, isIntegerTy));
// Check isIntegerTy(Bitwidth).
EXPECT_TRUE(LLVMInt32Ty->isIntegerTy(32u));
EXPECT_FALSE(LLVMInt32Ty->isIntegerTy(31u));
EXPECT_FALSE(Ctx.getType(llvm::Type::getFloatTy(C))->isIntegerTy(32u));
// Check isIntOrIntVectorTy().
EXPECT_TRUE(LLVMInt32Ty->isIntOrIntVectorTy());
EXPECT_TRUE(Ctx.getType(llvm::FixedVectorType::get(LLVMInt32Ty, 8))
->isIntOrIntVectorTy());
EXPECT_FALSE(Ctx.getType(LLVMFloatTy)->isIntOrIntVectorTy());
EXPECT_FALSE(Ctx.getType(llvm::FixedVectorType::get(LLVMFloatTy, 8))
->isIntOrIntVectorTy());
// Check isIntOrPtrTy().
EXPECT_TRUE(Int32Ty->isIntOrPtrTy());
EXPECT_TRUE(Ctx.getType(llvm::PointerType::get(C, 0u))->isIntOrPtrTy());
EXPECT_FALSE(FloatTy->isIntOrPtrTy());
// Check isFunctionTy().
EXPECT_TRUE(Ctx.getType(llvm::FunctionType::get(LLVMInt32Ty, {}, false))
->isFunctionTy());
// Check isStructTy().
EXPECT_TRUE(Ctx.getType(llvm::StructType::get(C))->isStructTy());
// Check isArrayTy().
EXPECT_TRUE(Ctx.getType(llvm::ArrayType::get(LLVMInt32Ty, 10))->isArrayTy());
// Check isPointerTy().
EXPECT_TRUE(Ctx.getType(llvm::PointerType::get(C, 0u))->isPointerTy());
// Check isPtrOrPtrVectroTy().
EXPECT_TRUE(
Ctx.getType(llvm::FixedVectorType::get(llvm::PointerType::get(C, 0u), 8u))
->isPtrOrPtrVectorTy());
// Check isVectorTy().
EXPECT_TRUE(
Ctx.getType(llvm::FixedVectorType::get(LLVMInt32Ty, 8u))->isVectorTy());
// Check canLosslesslyBitCastTo().
auto *VecTy32x4 = Ctx.getType(llvm::FixedVectorType::get(LLVMInt32Ty, 4u));
auto *VecTy32x2 = Ctx.getType(llvm::FixedVectorType::get(LLVMInt32Ty, 2u));
auto *VecTy8x16 = Ctx.getType(llvm::FixedVectorType::get(LLVMInt8Ty, 16u));
EXPECT_TRUE(VecTy32x4->canLosslesslyBitCastTo(VecTy8x16));
EXPECT_FALSE(VecTy32x4->canLosslesslyBitCastTo(VecTy32x2));
// Check isEmptyTy().
EXPECT_TRUE(Ctx.getType(llvm::StructType::get(C))->isEmptyTy());
// Check isFirstClassType().
EXPECT_TRUE(Int32Ty->isFirstClassType());
// Check isSingleValueType().
EXPECT_TRUE(Int32Ty->isSingleValueType());
// Check isAggregateType().
EXPECT_FALSE(Int32Ty->isAggregateType());
// Check isSized().
SmallPtrSet<sandboxir::Type *, 1> Visited;
EXPECT_TRUE(Int32Ty->isSized(&Visited));
// Check getPrimitiveSizeInBits().
EXPECT_EQ(VecTy32x2->getPrimitiveSizeInBits(), 32u * 2);
// Check getScalarSizeInBits().
EXPECT_EQ(VecTy32x2->getScalarSizeInBits(), 32u);
// Check getFPMantissaWidth().
EXPECT_EQ(FloatTy->getFPMantissaWidth(), LLVMFloatTy->getFPMantissaWidth());
// Check isIEEELikeFPTy().
EXPECT_EQ(FloatTy->isIEEELikeFPTy(), LLVMFloatTy->isIEEELikeFPTy());
// Check getScalarType().
EXPECT_EQ(
Ctx.getType(llvm::FixedVectorType::get(LLVMInt32Ty, 8u))->getScalarType(),
Int32Ty);
#define CHK_GET(TY) \
EXPECT_EQ(Ctx.getType(llvm::Type::get##TY##Ty(C)), \
sandboxir::Type::get##TY##Ty(Ctx))
// Check getInt64Ty().
CHK_GET(Int64);
// Check getInt32Ty().
CHK_GET(Int32);
// Check getInt16Ty().
CHK_GET(Int16);
// Check getInt8Ty().
CHK_GET(Int8);
// Check getInt1Ty().
CHK_GET(Int1);
// Check getDoubleTy().
CHK_GET(Double);
// Check getFloatTy().
CHK_GET(Float);
}
TEST_F(SandboxTypeTest, PointerType) {
parseIR(C, R"IR(
define void @foo(ptr %ptr) {
ret void
}
)IR");
llvm::Function *LLVMF = &*M->getFunction("foo");
sandboxir::Context Ctx(C);
auto *F = Ctx.createFunction(LLVMF);
// Check classof(), creation.
auto *PtrTy = cast<sandboxir::PointerType>(F->getArg(0)->getType());
// Check get(Ctx, AddressSpace).
auto *NewPtrTy2 = sandboxir::PointerType::get(Ctx, 0u);
EXPECT_EQ(NewPtrTy2, PtrTy);
}
TEST_F(SandboxTypeTest, ArrayType) {
parseIR(C, R"IR(
define void @foo([2 x i8] %v0) {
ret void
}
)IR");
llvm::Function *LLVMF = &*M->getFunction("foo");
sandboxir::Context Ctx(C);
auto *F = Ctx.createFunction(LLVMF);
// Check classof(), creation.
[[maybe_unused]] auto *ArrayTy =
cast<sandboxir::ArrayType>(F->getArg(0)->getType());
// Check get().
auto *NewArrayTy =
sandboxir::ArrayType::get(sandboxir::Type::getInt8Ty(Ctx), 2u);
EXPECT_EQ(NewArrayTy, ArrayTy);
}
TEST_F(SandboxTypeTest, StructType) {
parseIR(C, R"IR(
define void @foo({i32, i8} %v0) {
ret void
}
)IR");
llvm::Function *LLVMF = &*M->getFunction("foo");
sandboxir::Context Ctx(C);
auto *F = Ctx.createFunction(LLVMF);
auto *Int32Ty = sandboxir::Type::getInt32Ty(Ctx);
auto *Int8Ty = sandboxir::Type::getInt8Ty(Ctx);
// Check classof(), creation.
[[maybe_unused]] auto *StructTy =
cast<sandboxir::StructType>(F->getArg(0)->getType());
// Check get().
auto *NewStructTy = sandboxir::StructType::get(Ctx, {Int32Ty, Int8Ty});
EXPECT_EQ(NewStructTy, StructTy);
// Check get(Packed).
auto *NewStructTyPacked =
sandboxir::StructType::get(Ctx, {Int32Ty, Int8Ty}, /*Packed=*/true);
EXPECT_NE(NewStructTyPacked, StructTy);
EXPECT_TRUE(NewStructTyPacked->isPacked());
}
TEST_F(SandboxTypeTest, VectorType) {
parseIR(C, R"IR(
define void @foo(<4 x i16> %vi0, <4 x float> %vf1, i8 %i0) {
ret void
}
)IR");
llvm::Function *LLVMF = &*M->getFunction("foo");
sandboxir::Context Ctx(C);
auto *F = Ctx.createFunction(LLVMF);
// Check classof(), creation, accessors
auto *VecTy = cast<sandboxir::VectorType>(F->getArg(0)->getType());
EXPECT_TRUE(VecTy->getElementType()->isIntegerTy(16));
EXPECT_EQ(VecTy->getElementCount(), ElementCount::getFixed(4));
// get(ElementType, NumElements, Scalable)
EXPECT_EQ(sandboxir::VectorType::get(sandboxir::Type::getInt16Ty(Ctx), 4,
/*Scalable=*/false),
F->getArg(0)->getType());
// get(ElementType, Other)
EXPECT_EQ(sandboxir::VectorType::get(
sandboxir::Type::getInt16Ty(Ctx),
cast<sandboxir::VectorType>(F->getArg(0)->getType())),
F->getArg(0)->getType());
auto *FVecTy = cast<sandboxir::VectorType>(F->getArg(1)->getType());
EXPECT_TRUE(FVecTy->getElementType()->isFloatTy());
// getInteger
auto *IVecTy = sandboxir::VectorType::getInteger(FVecTy);
EXPECT_TRUE(IVecTy->getElementType()->isIntegerTy(32));
EXPECT_EQ(IVecTy->getElementCount(), FVecTy->getElementCount());
// getExtendedElementCountVectorType
auto *ExtVecTy = sandboxir::VectorType::getExtendedElementVectorType(IVecTy);
EXPECT_TRUE(ExtVecTy->getElementType()->isIntegerTy(64));
EXPECT_EQ(ExtVecTy->getElementCount(), VecTy->getElementCount());
// getTruncatedElementVectorType
auto *TruncVecTy =
sandboxir::VectorType::getTruncatedElementVectorType(IVecTy);
EXPECT_TRUE(TruncVecTy->getElementType()->isIntegerTy(16));
EXPECT_EQ(TruncVecTy->getElementCount(), VecTy->getElementCount());
// getSubdividedVectorType
auto *SubVecTy = sandboxir::VectorType::getSubdividedVectorType(VecTy, 1);
EXPECT_TRUE(SubVecTy->getElementType()->isIntegerTy(8));
EXPECT_EQ(SubVecTy->getElementCount(), ElementCount::getFixed(8));
// getHalfElementsVectorType
auto *HalfVecTy = sandboxir::VectorType::getHalfElementsVectorType(VecTy);
EXPECT_TRUE(HalfVecTy->getElementType()->isIntegerTy(16));
EXPECT_EQ(HalfVecTy->getElementCount(), ElementCount::getFixed(2));
// getDoubleElementsVectorType
auto *DoubleVecTy = sandboxir::VectorType::getDoubleElementsVectorType(VecTy);
EXPECT_TRUE(DoubleVecTy->getElementType()->isIntegerTy(16));
EXPECT_EQ(DoubleVecTy->getElementCount(), ElementCount::getFixed(8));
// isValidElementType
auto *I8Type = F->getArg(2)->getType();
EXPECT_TRUE(I8Type->isIntegerTy());
EXPECT_TRUE(sandboxir::VectorType::isValidElementType(I8Type));
EXPECT_FALSE(sandboxir::VectorType::isValidElementType(FVecTy));
}
TEST_F(SandboxTypeTest, FixedVectorType) {
parseIR(C, R"IR(
define void @foo(<4 x i16> %vi0, <4 x float> %vf1, i8 %i0) {
ret void
}
)IR");
llvm::Function *LLVMF = &*M->getFunction("foo");
sandboxir::Context Ctx(C);
auto *F = Ctx.createFunction(LLVMF);
// Check classof(), creation, accessors
auto *Vec4i16Ty = cast<sandboxir::FixedVectorType>(F->getArg(0)->getType());
EXPECT_TRUE(Vec4i16Ty->getElementType()->isIntegerTy(16));
EXPECT_EQ(Vec4i16Ty->getElementCount(), ElementCount::getFixed(4));
// get(ElementType, NumElements)
EXPECT_EQ(
sandboxir::FixedVectorType::get(sandboxir::Type::getInt16Ty(Ctx), 4),
F->getArg(0)->getType());
// get(ElementType, Other)
EXPECT_EQ(sandboxir::FixedVectorType::get(
sandboxir::Type::getInt16Ty(Ctx),
cast<sandboxir::FixedVectorType>(F->getArg(0)->getType())),
F->getArg(0)->getType());
auto *Vec4FTy = cast<sandboxir::FixedVectorType>(F->getArg(1)->getType());
EXPECT_TRUE(Vec4FTy->getElementType()->isFloatTy());
// getInteger
auto *Vec4i32Ty = sandboxir::FixedVectorType::getInteger(Vec4FTy);
EXPECT_TRUE(Vec4i32Ty->getElementType()->isIntegerTy(32));
EXPECT_EQ(Vec4i32Ty->getElementCount(), Vec4FTy->getElementCount());
// getExtendedElementCountVectorType
auto *Vec4i64Ty =
sandboxir::FixedVectorType::getExtendedElementVectorType(Vec4i16Ty);
EXPECT_TRUE(Vec4i64Ty->getElementType()->isIntegerTy(32));
EXPECT_EQ(Vec4i64Ty->getElementCount(), Vec4i16Ty->getElementCount());
// getTruncatedElementVectorType
auto *Vec4i8Ty =
sandboxir::FixedVectorType::getTruncatedElementVectorType(Vec4i16Ty);
EXPECT_TRUE(Vec4i8Ty->getElementType()->isIntegerTy(8));
EXPECT_EQ(Vec4i8Ty->getElementCount(), Vec4i8Ty->getElementCount());
// getSubdividedVectorType
auto *Vec8i8Ty =
sandboxir::FixedVectorType::getSubdividedVectorType(Vec4i16Ty, 1);
EXPECT_TRUE(Vec8i8Ty->getElementType()->isIntegerTy(8));
EXPECT_EQ(Vec8i8Ty->getElementCount(), ElementCount::getFixed(8));
// getNumElements
EXPECT_EQ(Vec8i8Ty->getNumElements(), 8u);
// getHalfElementsVectorType
auto *Vec2i16Ty =
sandboxir::FixedVectorType::getHalfElementsVectorType(Vec4i16Ty);
EXPECT_TRUE(Vec2i16Ty->getElementType()->isIntegerTy(16));
EXPECT_EQ(Vec2i16Ty->getElementCount(), ElementCount::getFixed(2));
// getDoubleElementsVectorType
auto *Vec8i16Ty =
sandboxir::FixedVectorType::getDoubleElementsVectorType(Vec4i16Ty);
EXPECT_TRUE(Vec8i16Ty->getElementType()->isIntegerTy(16));
EXPECT_EQ(Vec8i16Ty->getElementCount(), ElementCount::getFixed(8));
}
TEST_F(SandboxTypeTest, ScalableVectorType) {
parseIR(C, R"IR(
define void @foo(<vscale x 4 x i16> %vi0, <vscale x 4 x float> %vf1, i8 %i0) {
ret void
}
)IR");
llvm::Function *LLVMF = &*M->getFunction("foo");
sandboxir::Context Ctx(C);
auto *F = Ctx.createFunction(LLVMF);
// Check classof(), creation, accessors
auto *Vec4i16Ty =
cast<sandboxir::ScalableVectorType>(F->getArg(0)->getType());
EXPECT_TRUE(Vec4i16Ty->getElementType()->isIntegerTy(16));
EXPECT_EQ(Vec4i16Ty->getMinNumElements(), 4u);
// get(ElementType, NumElements)
EXPECT_EQ(
sandboxir::ScalableVectorType::get(sandboxir::Type::getInt16Ty(Ctx), 4),
F->getArg(0)->getType());
// get(ElementType, Other)
EXPECT_EQ(sandboxir::ScalableVectorType::get(
sandboxir::Type::getInt16Ty(Ctx),
cast<sandboxir::ScalableVectorType>(F->getArg(0)->getType())),
F->getArg(0)->getType());
auto *Vec4FTy = cast<sandboxir::ScalableVectorType>(F->getArg(1)->getType());
EXPECT_TRUE(Vec4FTy->getElementType()->isFloatTy());
// getInteger
auto *Vec4i32Ty = sandboxir::ScalableVectorType::getInteger(Vec4FTy);
EXPECT_TRUE(Vec4i32Ty->getElementType()->isIntegerTy(32));
EXPECT_EQ(Vec4i32Ty->getMinNumElements(), Vec4FTy->getMinNumElements());
// getExtendedElementCountVectorType
auto *Vec4i64Ty =
sandboxir::ScalableVectorType::getExtendedElementVectorType(Vec4i16Ty);
EXPECT_TRUE(Vec4i64Ty->getElementType()->isIntegerTy(32));
EXPECT_EQ(Vec4i64Ty->getMinNumElements(), Vec4i16Ty->getMinNumElements());
// getTruncatedElementVectorType
auto *Vec4i8Ty =
sandboxir::ScalableVectorType::getTruncatedElementVectorType(Vec4i16Ty);
EXPECT_TRUE(Vec4i8Ty->getElementType()->isIntegerTy(8));
EXPECT_EQ(Vec4i8Ty->getMinNumElements(), Vec4i8Ty->getMinNumElements());
// getSubdividedVectorType
auto *Vec8i8Ty =
sandboxir::ScalableVectorType::getSubdividedVectorType(Vec4i16Ty, 1);
EXPECT_TRUE(Vec8i8Ty->getElementType()->isIntegerTy(8));
EXPECT_EQ(Vec8i8Ty->getMinNumElements(), 8u);
// getMinNumElements
EXPECT_EQ(Vec8i8Ty->getMinNumElements(), 8u);
// getHalfElementsVectorType
auto *Vec2i16Ty =
sandboxir::ScalableVectorType::getHalfElementsVectorType(Vec4i16Ty);
EXPECT_TRUE(Vec2i16Ty->getElementType()->isIntegerTy(16));
EXPECT_EQ(Vec2i16Ty->getMinNumElements(), 2u);
// getDoubleElementsVectorType
auto *Vec8i16Ty =
sandboxir::ScalableVectorType::getDoubleElementsVectorType(Vec4i16Ty);
EXPECT_TRUE(Vec8i16Ty->getElementType()->isIntegerTy(16));
EXPECT_EQ(Vec8i16Ty->getMinNumElements(), 8u);
}
TEST_F(SandboxTypeTest, FunctionType) {
parseIR(C, R"IR(
define void @foo() {
ret void
}
)IR");
llvm::Function *LLVMF = &*M->getFunction("foo");
sandboxir::Context Ctx(C);
auto *F = Ctx.createFunction(LLVMF);
// Check classof(), creation.
[[maybe_unused]] auto *FTy =
cast<sandboxir::FunctionType>(F->getFunctionType());
}
TEST_F(SandboxTypeTest, IntegerType) {
parseIR(C, R"IR(
define void @foo(i32 %v0) {
ret void
}
)IR");
llvm::Function *LLVMF = &*M->getFunction("foo");
sandboxir::Context Ctx(C);
auto *F = Ctx.createFunction(LLVMF);
// Check classof(), creation.
auto *Int32Ty = cast<sandboxir::IntegerType>(F->getArg(0)->getType());
// Check get().
auto *NewInt32Ty = sandboxir::IntegerType::get(Ctx, 32u);
EXPECT_EQ(NewInt32Ty, Int32Ty);
}