blob: 19eec4e6744b256d7cf73be42557eba9b0ea42a5 [file] [log] [blame]
// Copyright (c) 2023-2025 Arm Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "gmock/gmock.h"
#include "test/unit_spirv.h"
#include "test/val/val_fixtures.h"
namespace spvtools {
namespace val {
namespace {
using ::testing::ContainsRegex;
using ::testing::HasSubstr;
using ValidateTensor = spvtest::ValidateBase<std::string>;
constexpr spv_target_env SPVENV = SPV_ENV_VULKAN_1_3;
std::string GenerateModule(const std::string& body) {
const std::string header = R"(
OpCapability Shader
OpCapability VulkanMemoryModel
OpCapability Int8
OpCapability TensorsARM
OpExtension "SPV_ARM_tensors"
OpMemoryModel Logical Vulkan
OpEntryPoint GLCompute %fnep "main"
OpExecutionMode %fnep LocalSize 1 1 1
OpDecorate %tensor_var DescriptorSet 0
OpDecorate %tensor_var Binding 0
OpDecorate %tensor_var_float_unranked DescriptorSet 0
OpDecorate %tensor_var_float_unranked Binding 1
%void = OpTypeVoid
%uint = OpTypeInt 32 0
%float = OpTypeFloat 32
%fnty = OpTypeFunction %void
%uint_vec4 = OpTypeVector %uint 4
%uint_0 = OpConstant %uint 0
%uint_0_spec = OpSpecConstant %uint 0
%uint_1 = OpConstant %uint 1
%uint_2 = OpConstant %uint 2
%uint_3 = OpConstant %uint 3
%uint_4 = OpConstant %uint 4
%uint_42 = OpConstant %uint 42
%uint_1_bis = OpConstant %uint 1
%float_1 = OpConstant %float 1
%uint_vec4_1_1_1_1 = OpConstantComposite %uint_vec4 %uint_1 %uint_1 %uint_1 %uint_1
%uint_arr1 = OpTypeArray %uint %uint_1
%uint_arr2 = OpTypeArray %uint %uint_2
%uint_arr3 = OpTypeArray %uint %uint_3
%uint_arr4 = OpTypeArray %uint %uint_4
%float_arr4 = OpTypeArray %float %uint_4
%uint_arr4_1_1_1_1 = OpConstantComposite %uint_arr4 %uint_1 %uint_1 %uint_1 %uint_1
%uint_arr4_0_0_0_0_spec = OpSpecConstantComposite %uint_arr4 %uint_0_spec %uint_0_spec %uint_0_spec %uint_0_spec
%uint_arr2_1_1 = OpConstantComposite %uint_arr2 %uint_1 %uint_1
%float_arr4_1_1_1_1 = OpConstantComposite %float_arr4 %float_1 %float_1 %float_1 %float_1
%uint_arr4_1_1_0_1 = OpConstantComposite %uint_arr4 %uint_1 %uint_1 %uint_0 %uint_1
%uint_ptr_Private = OpTypePointer Private %uint
%uint_arr4_ptr_Private = OpTypePointer Private %uint_arr4
%uint_var_1 = OpVariable %uint_ptr_Private Private %uint_1
%var_uint_arr4_1_1_1_1 = OpVariable %uint_arr4_ptr_Private Private %uint_arr4_1_1_1_1
%tensor_uint_4 = OpTypeTensorARM %uint %uint_4
%tensor_uint_spec = OpTypeTensorARM %uint %uint_0_spec
%tensor_float = OpTypeTensorARM %float
%tensor_uint_4_ptr_UniformConstant = OpTypePointer UniformConstant %tensor_uint_4
%tensor_var = OpVariable %tensor_uint_4_ptr_UniformConstant UniformConstant
%tensor_float_ptr_UniformConstant = OpTypePointer UniformConstant %tensor_float
%tensor_var_float_unranked = OpVariable %tensor_float_ptr_UniformConstant UniformConstant
%tensor_uint_spec_ptr_UniformConstant = OpTypePointer UniformConstant %tensor_uint_spec
%tensor_var_spec_rank = OpVariable %tensor_uint_spec_ptr_UniformConstant UniformConstant
)";
const std::string footer = R"(
%fnep = OpFunction %void None %fnty
%label = OpLabel
OpReturn
OpFunctionEnd
)";
return header + body + footer;
}
//
// Type tests
//
TEST_F(ValidateTensor, ValidTypeElementTypeOnly) {
const std::string src = R"(
%test_type = OpTypeTensorARM %uint
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPVENV));
}
TEST_F(ValidateTensor, InvalidTypeTensorElementTypeNotScalar) {
const std::string src = R"(
%test_type = OpTypeTensorARM %void
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPVENV));
EXPECT_THAT(getDiagnosticString(),
ContainsRegex("OpTypeTensorARM Element Type <id> "
"'.*' is not a scalar type.*"));
}
TEST_F(ValidateTensor, InvalidTypeDuplicateElementTypeTensorType) {
const std::string src = R"(
%typeA = OpTypeTensorARM %uint
%typeB = OpTypeTensorARM %uint
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPVENV));
EXPECT_THAT(
getDiagnosticString(),
HasSubstr("Duplicate non-aggregate type declarations are not allowed."));
}
TEST_F(ValidateTensor, ValidTypeElementTypeAndRank) {
const std::string src = R"(
%test_type = OpTypeTensorARM %uint %uint_1
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPVENV));
}
TEST_F(ValidateTensor, ValidTypeElementTypeAndRankUsingSpecConstant) {
const std::string src = R"(
%rank_spec = OpSpecConstant %uint 0
%test_type = OpTypeTensorARM %uint %rank_spec
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPVENV));
}
TEST_F(ValidateTensor, InvalidTypeDuplicateRankedTensorType) {
const std::string src = R"(
%typeA = OpTypeTensorARM %uint %uint_1
%typeB = OpTypeTensorARM %uint %uint_1
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPVENV));
EXPECT_THAT(
getDiagnosticString(),
HasSubstr("Duplicate non-aggregate type declarations are not allowed."));
}
TEST_F(ValidateTensor, ValidTypeEquivalentRankedTensorType) {
const std::string src = R"(
%typeA = OpTypeTensorARM %uint %uint_1
%typeB = OpTypeTensorARM %uint %uint_1_bis
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPVENV));
}
TEST_F(ValidateTensor, InvalidTypeRankNotConstant) {
const std::string src = R"(
%test_type = OpTypeTensorARM %uint %uint_var_1
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPVENV));
EXPECT_THAT(getDiagnosticString(),
ContainsRegex("OpTypeTensorARM Rank <id> '.*' "
"is not a constant instruction.*"));
}
TEST_F(ValidateTensor, InvalidTypeRankConstantButNotIntegerType) {
const std::string src = R"(
%test_type = OpTypeTensorARM %uint %float_1
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPVENV));
EXPECT_THAT(getDiagnosticString(),
ContainsRegex("OpTypeTensorARM Rank <id> '.*' "
"does not have a scalar integer type.*"));
}
TEST_F(ValidateTensor, InvalidTypeRankConstantIntegerTypeButNotScalar) {
const std::string src = R"(
%test_type = OpTypeTensorARM %uint %uint_vec4_1_1_1_1
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPVENV));
EXPECT_THAT(getDiagnosticString(),
ContainsRegex("OpTypeTensorARM Rank <id> '.*' "
"does not have a scalar integer type.*"));
}
TEST_F(ValidateTensor, InvalidTypeRank0) {
const std::string src = R"(
%test_type = OpTypeTensorARM %uint %uint_0
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPVENV));
EXPECT_THAT(getDiagnosticString(),
ContainsRegex("OpTypeTensorARM Rank <id> '.*' must "
"define a value greater than 0.*"));
}
TEST_F(ValidateTensor, ValidTypeElementTypeAndRankAndShape) {
const std::string src = R"(
%test_type = OpTypeTensorARM %uint %uint_4 %uint_arr4_1_1_1_1
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPVENV));
}
TEST_F(ValidateTensor, ValidTypeElementTypeAndRankAndShapeUsingSpecConstant) {
const std::string src = R"(
%test_type = OpTypeTensorARM %uint %uint_0_spec %uint_arr4_0_0_0_0_spec
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPVENV));
}
TEST_F(ValidateTensor, InvalidTypeShapeNotConstant) {
const std::string src = R"(
%test_type = OpTypeTensorARM %uint %uint_4 %var_uint_arr4_1_1_1_1
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPVENV));
EXPECT_THAT(getDiagnosticString(),
ContainsRegex("OpTypeTensorARM Shape <id> '.*' is not "
"a constant instruction.*"));
}
TEST_F(ValidateTensor, InvalidTypeShapeConstantButNotArrayOfInteger) {
const std::string src = R"(
%test_type = OpTypeTensorARM %uint %uint_4 %uint_vec4_1_1_1_1
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPVENV));
EXPECT_THAT(getDiagnosticString(),
ContainsRegex(
"OpTypeTensorARM Shape <id> '.*' is not "
"an array of integer type whose Length is equal to Rank.*"));
}
TEST_F(ValidateTensor, InvalidTypeShapeConstantArrayOfIntegerWrongLength) {
const std::string src = R"(
%test_type = OpTypeTensorARM %uint %uint_1 %uint_arr4_1_1_1_1
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPVENV));
EXPECT_THAT(getDiagnosticString(),
ContainsRegex(
"OpTypeTensorARM Shape <id> '.*' is not "
"an array of integer type whose Length is equal to Rank.*"));
}
TEST_F(ValidateTensor,
InvalidTypeShapeConstantArrayOfIntegerWithZeroConstituent) {
const std::string src = R"(
%test_type = OpTypeTensorARM %uint %uint_4 %uint_arr4_1_1_0_1
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPVENV));
EXPECT_THAT(
getDiagnosticString(),
ContainsRegex(
"OpTypeTensorARM Shape constituent 2 is not greater than 0.*"));
}
//
// Constants tests
//
TEST_F(ValidateTensor, ValidNullTensorConstantRank1) {
const std::string src = R"(
%uint_arr1_4 = OpConstantComposite %uint_arr1 %uint_4
%ts_uint_r1 = OpTypeTensorARM %uint %uint_1 %uint_arr1_4
%cst = OpConstantNull %ts_uint_r1
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPVENV));
}
TEST_F(ValidateTensor, ValidNullTensorConstantRank4) {
const std::string src = R"(
%uint_arr4_2_2_2_2 = OpConstantComposite %uint_arr4 %uint_2 %uint_2 %uint_2 %uint_2
%ts_uint_r4 = OpTypeTensorARM %uint %uint_4 %uint_arr4_2_2_2_2
%cst = OpConstantNull %ts_uint_r4
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPVENV));
}
TEST_F(ValidateTensor, InvalidNullTensorConstantRankedButNotShaped) {
const std::string src = R"(
%ts_uint_r1 = OpTypeTensorARM %uint %uint_1
%cst = OpConstantNull %ts_uint_r1
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPVENV));
EXPECT_THAT(getDiagnosticString(),
ContainsRegex("OpConstantNull Result Type <id> '.*' "
"cannot have a null value.*"));
}
TEST_F(ValidateTensor, InvalidNullTensorConstantNotRanked) {
const std::string src = R"(
%ts_uint_r1 = OpTypeTensorARM %uint
%cst = OpConstantNull %ts_uint_r1
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPVENV));
EXPECT_THAT(getDiagnosticString(),
ContainsRegex("OpConstantNull Result Type <id> '.*' "
"cannot have a null value.*"));
}
TEST_F(ValidateTensor, ValidTensorConstantRank1) {
const std::string src = R"(
%uint_arr1_4 = OpConstantComposite %uint_arr1 %uint_4
%ts_uint_r1 = OpTypeTensorARM %uint %uint_1 %uint_arr1_4
%cst = OpConstantComposite %ts_uint_r1 %uint_42 %uint_42 %uint_42 %uint_42
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPVENV));
}
TEST_F(ValidateTensor, ValidTensorConstantRank1SpecConstant) {
const std::string src = R"(
%uint_arr1_4 = OpSpecConstantComposite %uint_arr1 %uint_0_spec
%ts_uint_r1 = OpTypeTensorARM %uint %uint_0_spec %uint_arr1_4
%cst = OpSpecConstantComposite %ts_uint_r1 %uint_0_spec %uint_0_spec %uint_0_spec %uint_0_spec
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPVENV));
}
TEST_F(ValidateTensor, InvalidTensorConstantRank1NotEnoughConstituents) {
const std::string src = R"(
%uint_arr1_4 = OpConstantComposite %uint_arr1 %uint_4
%ts_uint_r1 = OpTypeTensorARM %uint %uint_1 %uint_arr1_4
%cst = OpConstantComposite %ts_uint_r1 %uint_42 %uint_42 %uint_42
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPVENV));
EXPECT_THAT(
getDiagnosticString(),
ContainsRegex("OpConstantComposite Constituent count does not match the "
"shape of Result Type <id> '.*' "
"along its outermost dimension, expected 4 but got 3.*"));
}
TEST_F(ValidateTensor, InvalidTensorConstantRank1TooManyConstituents) {
const std::string src = R"(
%uint_arr1_4 = OpConstantComposite %uint_arr1 %uint_4
%ts_uint_r1 = OpTypeTensorARM %uint %uint_1 %uint_arr1_4
%cst = OpConstantComposite %ts_uint_r1 %uint_42 %uint_42 %uint_42 %uint_42 %uint_42
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPVENV));
EXPECT_THAT(
getDiagnosticString(),
ContainsRegex("OpConstantComposite Constituent count does not match the "
"shape of Result Type <id> '.*' "
"along its outermost dimension, expected 4 but got 5.*"));
}
TEST_F(ValidateTensor,
InvalidTensorConstantRank1ConstituentNotConstantOrUndef) {
const std::string src = R"(
%uint_arr1_4 = OpConstantComposite %uint_arr1 %uint_4
%ts_uint_r1 = OpTypeTensorARM %uint %uint_1 %uint_arr1_4
%cst = OpConstantComposite %ts_uint_r1 %tensor_var %tensor_var %tensor_var %tensor_var
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPVENV));
EXPECT_THAT(getDiagnosticString(),
ContainsRegex("OpConstantComposite Constituent <id> "
"'.*' is not a constant or undef.*"));
}
TEST_F(ValidateTensor, InvalidTensorConstantRank1WrongConstituentType) {
const std::string src = R"(
%uint_arr1_4 = OpConstantComposite %uint_arr1 %uint_4
%ts_uint_r1 = OpTypeTensorARM %uint %uint_1 %uint_arr1_4
%cst = OpConstantComposite %ts_uint_r1 %uint_42 %uint_42 %float_1 %uint_42
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPVENV));
EXPECT_THAT(
getDiagnosticString(),
ContainsRegex("OpConstantComposite Constituent <id> '.*' "
"type does not match the element type of the tensor "
".*"));
}
TEST_F(ValidateTensor, ValidTensorConstantRank4) {
const std::string src = R"(
%uint_arr1_2 = OpConstantComposite %uint_arr1 %uint_2
%uint_arr2_2_2 = OpConstantComposite %uint_arr2 %uint_2 %uint_2
%uint_arr3_2_2_2 = OpConstantComposite %uint_arr3 %uint_2 %uint_2 %uint_2
%uint_arr4_2_2_2_2 = OpConstantComposite %uint_arr4 %uint_2 %uint_2 %uint_2 %uint_2
%ts_uint_r1 = OpTypeTensorARM %uint %uint_1 %uint_arr1_2
%ts_uint_r2 = OpTypeTensorARM %uint %uint_2 %uint_arr2_2_2
%ts_uint_r3 = OpTypeTensorARM %uint %uint_3 %uint_arr3_2_2_2
%ts_uint_r4 = OpTypeTensorARM %uint %uint_4 %uint_arr4_2_2_2_2
%cst_r1 = OpConstantComposite %ts_uint_r1 %uint_42 %uint_42
%cst_r2 = OpConstantComposite %ts_uint_r2 %cst_r1 %cst_r1
%cst_r3 = OpConstantComposite %ts_uint_r3 %cst_r2 %cst_r2
%cst_r4 = OpConstantComposite %ts_uint_r4 %cst_r3 %cst_r3
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPVENV));
}
TEST_F(ValidateTensor, ValidTensorConstantRank2SpecConstantConstituent) {
const std::string src = R"(
%uint_arr1_2 = OpSpecConstantComposite %uint_arr1 %uint_0_spec
%uint_arr2_2_2 = OpSpecConstantComposite %uint_arr2 %uint_0_spec %uint_0_spec
%ts_uint_r1 = OpTypeTensorARM %uint %uint_0_spec %uint_arr1_2
%ts_uint_r2 = OpTypeTensorARM %uint %uint_2 %uint_arr2_2_2
%cst_r1 = OpSpecConstantComposite %ts_uint_r1 %uint_0_spec %uint_0_spec
%cst_r2 = OpSpecConstantComposite %ts_uint_r2 %cst_r1 %cst_r1
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPVENV));
}
TEST_F(ValidateTensor, InvalidTensorConstantRank2ConstituentNotATensor) {
const std::string src = R"(
%uint_arr1_2 = OpConstantComposite %uint_arr1 %uint_2
%uint_arr2_2_2 = OpConstantComposite %uint_arr2 %uint_2 %uint_2
%ts_uint_r1 = OpTypeTensorARM %uint %uint_1 %uint_arr1_2
%ts_uint_r2 = OpTypeTensorARM %uint %uint_2 %uint_arr2_2_2
%cst_r1 = OpConstantComposite %ts_uint_r1 %uint_42 %uint_42
%cst_r2 = OpConstantComposite %ts_uint_r2 %uint_1 %cst_r1
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPVENV));
EXPECT_THAT(getDiagnosticString(),
ContainsRegex("OpConstantComposite Constituent <id> "
"'.*' must be an OpTypeTensorARM.*"));
}
TEST_F(ValidateTensor,
InvalidTensorConstantRank2ConstituentTensorWrongElementType) {
const std::string src = R"(
%uint_arr1_2 = OpConstantComposite %uint_arr1 %uint_2
%uint_arr2_2_2 = OpConstantComposite %uint_arr2 %uint_2 %uint_2
%ts_float_r1 = OpTypeTensorARM %float %uint_1 %uint_arr1_2
%ts_uint_r2 = OpTypeTensorARM %uint %uint_2 %uint_arr2_2_2
%cst_r1 = OpConstantComposite %ts_float_r1 %float_1 %float_1
%cst_r2 = OpConstantComposite %ts_uint_r2 %cst_r1 %cst_r1
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPVENV));
EXPECT_THAT(getDiagnosticString(),
ContainsRegex("OpConstantComposite Constituent <id> "
"'.*' must have the same Element Type "
"as Result Type <id> .*"));
}
TEST_F(ValidateTensor, InvalidTensorConstantRank2ConstituentTensorWrongRank) {
const std::string src = R"(
%uint_arr1_2 = OpConstantComposite %uint_arr1 %uint_2
%uint_arr2_2_2 = OpConstantComposite %uint_arr2 %uint_2 %uint_2
%ts_uint_r1 = OpTypeTensorARM %uint %uint_1 %uint_arr1_2
%ts_uint_r2 = OpTypeTensorARM %uint %uint_2 %uint_arr2_2_2
%cst_r1 = OpConstantComposite %ts_uint_r1 %uint_42 %uint_42
%cst_r2 = OpConstantComposite %ts_uint_r2 %cst_r1 %cst_r1
%cst = OpConstantComposite %ts_uint_r2 %cst_r1 %cst_r2
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPVENV));
EXPECT_THAT(getDiagnosticString(),
ContainsRegex("OpConstantComposite Constituent <id> "
"'.*' must have a Rank that is "
"1 less than the Rank of Result Type <id> "
"'.*', expected 1 but got 2.*"));
}
TEST_F(ValidateTensor, InvalidTensorConstantRank2ConstituentTensorWrongShape) {
const std::string src = R"(
%uint_arr1_3 = OpConstantComposite %uint_arr1 %uint_3
%uint_arr2_2_2 = OpConstantComposite %uint_arr2 %uint_2 %uint_2
%ts_uint_r1 = OpTypeTensorARM %uint %uint_1 %uint_arr1_3
%ts_uint_r2 = OpTypeTensorARM %uint %uint_2 %uint_arr2_2_2
%cst_r1 = OpConstantComposite %ts_uint_r1 %uint_42 %uint_42 %uint_42
%cst_r2 = OpConstantComposite %ts_uint_r2 %cst_r1 %cst_r1
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPVENV));
EXPECT_THAT(
getDiagnosticString(),
ContainsRegex(
"OpConstantComposite Constituent <id> "
"'.*' must have a Shape that matches "
"that of Result Type <id> '.*' along "
"all inner dimensions of Result Type, expected 2 for dimension 0 of "
"Constituent but got 3.*"));
}
//
// Read tests
//
TEST_F(ValidateTensor, ValidTensorReadScalar) {
const std::string src = R"(
%fn = OpFunction %void None %fnty
%label1 = OpLabel
%tensor = OpLoad %tensor_uint_4 %tensor_var
%val = OpTensorReadARM %uint %tensor %uint_arr4_1_1_1_1
OpReturn
OpFunctionEnd
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPVENV));
}
TEST_F(ValidateTensor, ValidTensorReadArray) {
const std::string src = R"(
%fn = OpFunction %void None %fnty
%label1 = OpLabel
%tensor = OpLoad %tensor_uint_4 %tensor_var
%val = OpTensorReadARM %uint_arr2 %tensor %uint_arr4_1_1_1_1
OpReturn
OpFunctionEnd
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPVENV));
}
TEST_F(ValidateTensor, ValidTensorReadSpecConstantRank) {
const std::string src = R"(
%fn = OpFunction %void None %fnty
%label1 = OpLabel
%tensor = OpLoad %tensor_uint_spec %tensor_var_spec_rank
%val = OpTensorReadARM %uint %tensor %uint_arr4_1_1_1_1
OpReturn
OpFunctionEnd
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPVENV));
}
TEST_F(ValidateTensor, InvalidTensorReadResultTypeVoid) {
const std::string src = R"(
%fn = OpFunction %void None %fnty
%label1 = OpLabel
%tensor = OpLoad %tensor_uint_4 %tensor_var
%val = OpTensorReadARM %void %tensor %uint_arr4_1_1_1_1
OpReturn
OpFunctionEnd
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPVENV));
EXPECT_THAT(
getDiagnosticString(),
HasSubstr(
"Expected Result Type to be a scalar type or array of scalar type"));
}
TEST_F(ValidateTensor, InvalidTensorReadResultTypeVector) {
const std::string src = R"(
%fn = OpFunction %void None %fnty
%label1 = OpLabel
%tensor = OpLoad %tensor_uint_4 %tensor_var
%val = OpTensorReadARM %uint_vec4 %tensor %uint_arr4_1_1_1_1
OpReturn
OpFunctionEnd
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPVENV));
EXPECT_THAT(
getDiagnosticString(),
HasSubstr(
"Expected Result Type to be a scalar type or array of scalar type"));
}
TEST_F(ValidateTensor,
InvalidTensorReadResultTypeDoesNotMatchTensorElementType) {
const std::string src = R"(
%fn = OpFunction %void None %fnty
%label1 = OpLabel
%tensor = OpLoad %tensor_uint_4 %tensor_var
%val = OpTensorReadARM %float %tensor %uint_arr4_1_1_1_1
OpReturn
OpFunctionEnd
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPVENV));
EXPECT_THAT(
getDiagnosticString(),
HasSubstr(
"Expected Result Type to be the same as the Element Type of Tensor"));
}
TEST_F(ValidateTensor, InvalidTensorReadTensorNotRanked) {
const std::string src = R"(
%fn = OpFunction %void None %fnty
%label1 = OpLabel
%tensor = OpLoad %tensor_float %tensor_var_float_unranked
%val = OpTensorReadARM %float %tensor %uint_arr4_1_1_1_1
OpReturn
OpFunctionEnd
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPVENV));
EXPECT_THAT(
getDiagnosticString(),
HasSubstr(
"Expected Tensor to be an OpTypeTensorARM whose Rank is specified"));
}
TEST_F(ValidateTensor, InvalidTensorReadCoordinatesNotArray) {
const std::string src = R"(
%fn = OpFunction %void None %fnty
%label1 = OpLabel
%tensor = OpLoad %tensor_uint_4 %tensor_var
%val = OpTensorReadARM %uint %tensor %uint_1
OpReturn
OpFunctionEnd
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPVENV));
EXPECT_THAT(
getDiagnosticString(),
HasSubstr(
"Expected Coordinates to be an array whose Element Type is an "
"integer type and whose Length is equal to the Rank of Tensor."));
}
TEST_F(ValidateTensor, InvalidTensorReadCoordinatesArrayNotInteger) {
const std::string src = R"(
%fn = OpFunction %void None %fnty
%label1 = OpLabel
%tensor = OpLoad %tensor_uint_4 %tensor_var
%val = OpTensorReadARM %uint %tensor %float_arr4_1_1_1_1
OpReturn
OpFunctionEnd
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPVENV));
EXPECT_THAT(
getDiagnosticString(),
HasSubstr(
"Expected Coordinates to be an array whose Element Type is an "
"integer type and whose Length is equal to the Rank of Tensor."));
}
TEST_F(ValidateTensor, InvalidTensorReadCoordinatesArrayIntegerWrongLength) {
const std::string src = R"(
%fn = OpFunction %void None %fnty
%label1 = OpLabel
%tensor = OpLoad %tensor_uint_4 %tensor_var
%val = OpTensorReadARM %uint %tensor %uint_arr2_1_1
OpReturn
OpFunctionEnd
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPVENV));
EXPECT_THAT(
getDiagnosticString(),
HasSubstr(
"Expected Coordinates to be an array whose Element Type is an "
"integer type and whose Length is equal to the Rank of Tensor."));
}
TEST_F(ValidateTensor, ValidTensorReadScalarWithNoneTensorOperands) {
const std::string src = R"(
%fn = OpFunction %void None %fnty
%label1 = OpLabel
%tensor = OpLoad %tensor_uint_4 %tensor_var
%val = OpTensorReadARM %uint %tensor %uint_arr4_1_1_1_1 NoneARM
OpReturn
OpFunctionEnd
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPVENV));
}
TEST_F(ValidateTensor, ValidTensorReadScalarWithNontemporalTensorOperands) {
const std::string src = R"(
%fn = OpFunction %void None %fnty
%label1 = OpLabel
%tensor = OpLoad %tensor_uint_4 %tensor_var
%val = OpTensorReadARM %uint %tensor %uint_arr4_1_1_1_1 NontemporalARM
OpReturn
OpFunctionEnd
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPVENV));
}
TEST_F(ValidateTensor, ValidTensorReadScalarOutOfBoundsValueTensorOperands) {
const std::string src = R"(
%fn = OpFunction %void None %fnty
%label1 = OpLabel
%tensor = OpLoad %tensor_uint_4 %tensor_var
%val = OpTensorReadARM %uint %tensor %uint_arr4_1_1_1_1 OutOfBoundsValueARM %uint_42
OpReturn
OpFunctionEnd
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPVENV));
}
TEST_F(ValidateTensor,
InvalidTensorReadScalarOutOfBoundsValueTensorOperandsValueWrongType) {
const std::string src = R"(
%fn = OpFunction %void None %fnty
%label1 = OpLabel
%tensor = OpLoad %tensor_uint_4 %tensor_var
%val = OpTensorReadARM %uint %tensor %uint_arr4_1_1_1_1 OutOfBoundsValueARM %float_1
OpReturn
OpFunctionEnd
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPVENV));
EXPECT_THAT(
getDiagnosticString(),
HasSubstr(
"Expected the type of the OutOfBoundsValueARM value to be the same "
"as the Element Type of Tensor."));
}
TEST_F(ValidateTensor,
InvalidTensorReadScalarMakeElementAvailableTensorOperands) {
const std::string src = R"(
%fn = OpFunction %void None %fnty
%label1 = OpLabel
%tensor = OpLoad %tensor_uint_4 %tensor_var
%val = OpTensorReadARM %uint %tensor %uint_arr4_1_1_1_1 MakeElementAvailableARM %uint_1
OpReturn
OpFunctionEnd
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPVENV));
EXPECT_THAT(
getDiagnosticString(),
HasSubstr(
"MakeElementAvailableARM cannot be used with OpTensorReadARM."));
}
TEST_F(ValidateTensor,
ValidTensorReadScalarWithMakeElementVisibleTensorOperands) {
const std::string src = R"(
%fn = OpFunction %void None %fnty
%label1 = OpLabel
%tensor = OpLoad %tensor_uint_4 %tensor_var
%val = OpTensorReadARM %uint %tensor %uint_arr4_1_1_1_1 MakeElementVisibleARM|NonPrivateElementARM %uint_1
OpReturn
OpFunctionEnd
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPVENV));
}
TEST_F(
ValidateTensor,
InvalidTensorReadScalarMakeElementVisibleTensorOperandsWithoutNonPrivateElement) {
const std::string src = R"(
%fn = OpFunction %void None %fnty
%label1 = OpLabel
%tensor = OpLoad %tensor_uint_4 %tensor_var
%val = OpTensorReadARM %uint %tensor %uint_arr4_1_1_1_1 MakeElementVisibleARM %uint_1
OpReturn
OpFunctionEnd
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPVENV));
EXPECT_THAT(
getDiagnosticString(),
HasSubstr("MakeElementAvailableARM requires NonPrivateElementARM"));
}
//
// Write tests
//
TEST_F(ValidateTensor, ValidTensorWriteScalar) {
const std::string src = R"(
%fn = OpFunction %void None %fnty
%label1 = OpLabel
%tensor = OpLoad %tensor_uint_4 %tensor_var
OpTensorWriteARM %tensor %uint_arr4_1_1_1_1 %uint_1
OpReturn
OpFunctionEnd
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPVENV));
}
TEST_F(ValidateTensor, ValidTensorWriteArray) {
const std::string src = R"(
%fn = OpFunction %void None %fnty
%label1 = OpLabel
%tensor = OpLoad %tensor_uint_4 %tensor_var
OpTensorWriteARM %tensor %uint_arr4_1_1_1_1 %uint_arr2_1_1
OpReturn
OpFunctionEnd
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPVENV));
}
TEST_F(ValidateTensor, ValidTensorWriteSpecConstantRank) {
const std::string src = R"(
%fn = OpFunction %void None %fnty
%label1 = OpLabel
%tensor = OpLoad %tensor_uint_spec %tensor_var_spec_rank
OpTensorWriteARM %tensor %uint_arr4_1_1_1_1 %uint_1
OpReturn
OpFunctionEnd
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPVENV));
}
TEST_F(ValidateTensor, InvalidTensorWriteObjectNotScalarOrArrayOfScalar) {
const std::string src = R"(
%fn = OpFunction %void None %fnty
%label1 = OpLabel
%tensor = OpLoad %tensor_uint_4 %tensor_var
OpTensorWriteARM %tensor %uint_arr4_1_1_1_1 %uint_vec4_1_1_1_1
OpReturn
OpFunctionEnd
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPVENV));
EXPECT_THAT(
getDiagnosticString(),
HasSubstr("Expected Object to be a scalar type or array of scalar type "
"that is the same as the Element Type of Tensor."));
}
TEST_F(ValidateTensor, InvalidTensorWriteObjectDoesNotMatchTensorElementType) {
const std::string src = R"(
%fn = OpFunction %void None %fnty
%label1 = OpLabel
%tensor = OpLoad %tensor_uint_4 %tensor_var
OpTensorWriteARM %tensor %uint_arr4_1_1_1_1 %float_1
OpReturn
OpFunctionEnd
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPVENV));
EXPECT_THAT(
getDiagnosticString(),
HasSubstr("Expected Object to be a scalar type or array of scalar type "
"that is the same as the Element Type of Tensor."));
}
TEST_F(ValidateTensor, InvalidTensorWriteTensorNotRanked) {
const std::string src = R"(
%fn = OpFunction %void None %fnty
%label1 = OpLabel
%tensor = OpLoad %tensor_float %tensor_var_float_unranked
OpTensorWriteARM %tensor %uint_arr4_1_1_1_1 %float_1
OpReturn
OpFunctionEnd
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPVENV));
EXPECT_THAT(
getDiagnosticString(),
HasSubstr(
"Expected Tensor to be an OpTypeTensorARM whose Rank is specified"));
}
TEST_F(ValidateTensor, InvalidTensorWriteCoordinatesNotArray) {
const std::string src = R"(
%fn = OpFunction %void None %fnty
%label1 = OpLabel
%tensor = OpLoad %tensor_uint_4 %tensor_var
OpTensorWriteARM %tensor %uint_1 %uint_1
OpReturn
OpFunctionEnd
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPVENV));
EXPECT_THAT(
getDiagnosticString(),
HasSubstr(
"Expected Coordinates to be an array whose Element Type is an "
"integer type and whose Length is equal to the Rank of Tensor."));
}
TEST_F(ValidateTensor, InvalidTensorWriteCoordinatesArrayNotInteger) {
const std::string src = R"(
%fn = OpFunction %void None %fnty
%label1 = OpLabel
%tensor = OpLoad %tensor_uint_4 %tensor_var
OpTensorWriteARM %tensor %float_arr4_1_1_1_1 %uint_1
OpReturn
OpFunctionEnd
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPVENV));
EXPECT_THAT(
getDiagnosticString(),
HasSubstr(
"Expected Coordinates to be an array whose Element Type is an "
"integer type and whose Length is equal to the Rank of Tensor."));
}
TEST_F(ValidateTensor, InvalidTensorWriteCoordinatesArrayIntegerWrongLength) {
const std::string src = R"(
%fn = OpFunction %void None %fnty
%label1 = OpLabel
%tensor = OpLoad %tensor_uint_4 %tensor_var
OpTensorWriteARM %tensor %uint_arr2_1_1 %uint_1
OpReturn
OpFunctionEnd
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPVENV));
EXPECT_THAT(
getDiagnosticString(),
HasSubstr(
"Expected Coordinates to be an array whose Element Type is an "
"integer type and whose Length is equal to the Rank of Tensor."));
}
TEST_F(ValidateTensor, ValidTensorWriteScalarWithNoneTensorOperands) {
const std::string src = R"(
%fn = OpFunction %void None %fnty
%label1 = OpLabel
%tensor = OpLoad %tensor_uint_4 %tensor_var
OpTensorWriteARM %tensor %uint_arr4_1_1_1_1 %uint_1 NoneARM
OpReturn
OpFunctionEnd
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPVENV));
}
TEST_F(ValidateTensor, ValidTensorWriteScalarWithNontemporalTensorOperands) {
const std::string src = R"(
%fn = OpFunction %void None %fnty
%label1 = OpLabel
%tensor = OpLoad %tensor_uint_4 %tensor_var
OpTensorWriteARM %tensor %uint_arr4_1_1_1_1 %uint_1 NontemporalARM
OpReturn
OpFunctionEnd
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPVENV));
}
TEST_F(ValidateTensor,
ValidTensorWriteScalarWithMakeElementAvailableTensorOperands) {
const std::string src = R"(
%fn = OpFunction %void None %fnty
%label1 = OpLabel
%tensor = OpLoad %tensor_uint_4 %tensor_var
OpTensorWriteARM %tensor %uint_arr4_1_1_1_1 %uint_1 MakeElementAvailableARM|NonPrivateElementARM %uint_1
OpReturn
OpFunctionEnd
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPVENV));
}
TEST_F(ValidateTensor,
InvalidTensorWriteScalarWithOutOfVoundsValueTensorOperands) {
const std::string src = R"(
%fn = OpFunction %void None %fnty
%label1 = OpLabel
%tensor = OpLoad %tensor_uint_4 %tensor_var
OpTensorWriteARM %tensor %uint_arr4_1_1_1_1 %uint_1 OutOfBoundsValueARM %uint_42
OpReturn
OpFunctionEnd
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPVENV));
EXPECT_THAT(getDiagnosticString(),
HasSubstr("OutOfBoundsValue Tensor Operand not allowed with "
"OpTensorWriteARM."));
}
TEST_F(ValidateTensor,
InvalidTensorWriteScalarWithMakeElementVisibleTensorOperands) {
const std::string src = R"(
%fn = OpFunction %void None %fnty
%label1 = OpLabel
%tensor = OpLoad %tensor_uint_4 %tensor_var
OpTensorWriteARM %tensor %uint_arr4_1_1_1_1 %uint_1 MakeElementVisibleARM %uint_1
OpReturn
OpFunctionEnd
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPVENV));
EXPECT_THAT(
getDiagnosticString(),
HasSubstr("MakeElementVisibleARM not allowed with OpTensorWriteARM."));
}
TEST_F(
ValidateTensor,
InvalidTensorWriteScalarWithMakeElementAvailableTensorOperandsWithoutNonPrivateElement) {
const std::string src = R"(
%fn = OpFunction %void None %fnty
%label1 = OpLabel
%tensor = OpLoad %tensor_uint_4 %tensor_var
OpTensorWriteARM %tensor %uint_arr4_1_1_1_1 %uint_1 MakeElementAvailableARM %uint_1
OpReturn
OpFunctionEnd
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPVENV));
EXPECT_THAT(
getDiagnosticString(),
HasSubstr("MakeElementAvailableARM requires NonPrivateElementARM."));
}
//
// Query Size tests
//
TEST_F(ValidateTensor, ValidTensorQuerySize) {
const std::string src = R"(
%fn = OpFunction %void None %fnty
%label1 = OpLabel
%tensor = OpLoad %tensor_uint_4 %tensor_var
%size = OpTensorQuerySizeARM %uint %tensor %uint_1
OpReturn
OpFunctionEnd
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPVENV));
}
TEST_F(ValidateTensor, ValidTensorQuerySizeSpecConstant) {
const std::string src = R"(
%fn = OpFunction %void None %fnty
%label1 = OpLabel
%tensor = OpLoad %tensor_uint_spec %tensor_var_spec_rank
%size = OpTensorQuerySizeARM %uint %tensor %uint_0_spec
OpReturn
OpFunctionEnd
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPVENV));
}
TEST_F(ValidateTensor, InvalidTensorQuerySizeTensorNotRanked) {
const std::string src = R"(
%fn = OpFunction %void None %fnty
%label1 = OpLabel
%tensor = OpLoad %tensor_float %tensor_var_float_unranked
%size = OpTensorQuerySizeARM %uint %tensor %uint_1
OpReturn
OpFunctionEnd
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPVENV));
EXPECT_THAT(
getDiagnosticString(),
HasSubstr(
"Expected Tensor to be an OpTypeTensorARM whose Rank is specified"));
}
TEST_F(ValidateTensor, InvalidTensorQuerySizeResultNotIntegerScalarType) {
const std::string src = R"(
%fn = OpFunction %void None %fnty
%label1 = OpLabel
%tensor = OpLoad %tensor_float %tensor_var_float_unranked
%size = OpTensorQuerySizeARM %float %tensor %uint_1
OpReturn
OpFunctionEnd
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPVENV));
EXPECT_THAT(getDiagnosticString(),
HasSubstr("Expected Result Type to be an integer type scalar"));
}
TEST_F(ValidateTensor, InvalidTensorQuerySizeDimensionNotIntegerType) {
const std::string src = R"(
%fn = OpFunction %void None %fnty
%label1 = OpLabel
%tensor = OpLoad %tensor_uint_4 %tensor_var
%size = OpTensorQuerySizeARM %uint %tensor %float_1
OpReturn
OpFunctionEnd
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPVENV));
EXPECT_THAT(getDiagnosticString(),
HasSubstr("Dimension must come from a constant instruction of "
"scalar integer type."));
}
TEST_F(ValidateTensor, InvalidTensorQuerySizeDimensionNotConstant) {
const std::string src = R"(
%fn = OpFunction %void None %fnty
%label1 = OpLabel
%tensor = OpLoad %tensor_uint_4 %tensor_var
%dims = OpLoad %uint_arr4 %var_uint_arr4_1_1_1_1
%dim = OpCompositeExtract %uint %dims 0
%size = OpTensorQuerySizeARM %uint %tensor %dim
OpReturn
OpFunctionEnd
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPVENV));
EXPECT_THAT(getDiagnosticString(),
HasSubstr("Dimension must come from a constant instruction of "
"scalar integer type."));
}
TEST_F(ValidateTensor, InvalidTensorQuerySizeDimension) {
const std::string src = R"(
%fn = OpFunction %void None %fnty
%label1 = OpLabel
%tensor = OpLoad %tensor_uint_4 %tensor_var
%size = OpTensorQuerySizeARM %uint %tensor %uint_42
OpReturn
OpFunctionEnd
)";
std::string spvasm = GenerateModule(src);
CompileSuccessfully(spvasm, SPVENV);
EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPVENV));
EXPECT_THAT(
getDiagnosticString(),
HasSubstr("Dimension (42) must be less than the Rank of Tensor (4)"));
}
} // namespace
} // namespace val
} // namespace spvtools