mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-12-27 02:10:15 +00:00
1009 lines
32 KiB
C++
1009 lines
32 KiB
C++
// Copyright (c) 2015-2016 The Khronos Group Inc.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
// copy of this software and/or associated documentation files (the
|
|
// "Materials"), to deal in the Materials without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Materials, and to
|
|
// permit persons to whom the Materials are furnished to do so, subject to
|
|
// the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included
|
|
// in all copies or substantial portions of the Materials.
|
|
//
|
|
// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
|
|
// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
|
|
// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
|
|
// https://www.khronos.org/registry/
|
|
//
|
|
// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
|
|
|
// Validation tests for SSA
|
|
|
|
#include "UnitSPIRV.h"
|
|
#include "ValidateFixtures.h"
|
|
#include "gmock/gmock.h"
|
|
|
|
#include <sstream>
|
|
#include <string>
|
|
#include <utility>
|
|
|
|
using ::testing::HasSubstr;
|
|
|
|
using std::string;
|
|
using std::pair;
|
|
using std::stringstream;
|
|
|
|
namespace {
|
|
|
|
using Validate =
|
|
spvtest::ValidateBase<pair<string, bool>,
|
|
SPV_VALIDATE_SSA_BIT | SPV_VALIDATE_LAYOUT_BIT>;
|
|
|
|
TEST_F(Validate, Default) {
|
|
char str[] = R"(
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint GLCompute %3 ""
|
|
OpExecutionMode %3 LocalSize 1 1 1
|
|
%1 = OpTypeVoid
|
|
%2 = OpTypeFunction %1
|
|
%3 = OpFunction %1 None %2
|
|
%4 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
}
|
|
|
|
TEST_F(Validate, IdUndefinedBad) {
|
|
char str[] = R"(
|
|
OpMemoryModel Logical GLSL450
|
|
OpName %missing "missing"
|
|
%voidt = OpTypeVoid
|
|
%vfunct = OpTypeFunction %voidt
|
|
%func = OpFunction %vfunct None %missing
|
|
%flabel = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("missing"));
|
|
}
|
|
|
|
TEST_F(Validate, IdRedefinedBad) {
|
|
char str[] = R"(
|
|
OpMemoryModel Logical GLSL450
|
|
OpName %2 "redefined"
|
|
%1 = OpTypeVoid
|
|
%2 = OpTypeFunction %1
|
|
%2 = OpFunction %1 None %2
|
|
%4 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
}
|
|
|
|
TEST_F(Validate, DominateUsageBad) {
|
|
char str[] = R"(
|
|
OpMemoryModel Logical GLSL450
|
|
OpName %1 "not_dominant"
|
|
%2 = OpTypeFunction %1 ; uses %1 before it's definition
|
|
%1 = OpTypeVoid
|
|
)";
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("not_dominant"));
|
|
}
|
|
|
|
TEST_F(Validate, ForwardNameGood) {
|
|
char str[] = R"(
|
|
OpMemoryModel Logical GLSL450
|
|
OpName %3 "main"
|
|
%1 = OpTypeVoid
|
|
%2 = OpTypeFunction %1
|
|
%3 = OpFunction %1 None %2
|
|
%4 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
}
|
|
|
|
TEST_F(Validate, ForwardNameMissingTargetBad) {
|
|
char str[] = R"(
|
|
OpMemoryModel Logical GLSL450
|
|
OpName %5 "main" ; Target never defined
|
|
)";
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("main"));
|
|
}
|
|
|
|
TEST_F(Validate, ForwardMemberNameGood) {
|
|
char str[] = R"(
|
|
OpMemoryModel Logical GLSL450
|
|
OpMemberName %struct 0 "value"
|
|
OpMemberName %struct 1 "size"
|
|
%intt = OpTypeInt 32 1
|
|
%uintt = OpTypeInt 32 0
|
|
%struct = OpTypeStruct %intt %uintt
|
|
)";
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
}
|
|
|
|
TEST_F(Validate, ForwardMemberNameMissingTargetBad) {
|
|
char str[] = R"(
|
|
OpMemoryModel Logical GLSL450
|
|
OpMemberName %struct 0 "value"
|
|
OpMemberName %bad 1 "size" ; Target is not defined
|
|
%intt = OpTypeInt 32 1
|
|
%uintt = OpTypeInt 32 0
|
|
%struct = OpTypeStruct %intt %uintt
|
|
)";
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("size"));
|
|
}
|
|
|
|
TEST_F(Validate, ForwardDecorateGood) {
|
|
char str[] = R"(
|
|
OpMemoryModel Logical GLSL450
|
|
OpDecorate %var Restrict
|
|
%intt = OpTypeInt 32 1
|
|
%ptrt = OpTypePointer UniformConstant %intt
|
|
%var = OpVariable %ptrt UniformConstant
|
|
)";
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
}
|
|
|
|
TEST_F(Validate, ForwardDecorateInvalidIDBad) {
|
|
char str[] = R"(
|
|
OpMemoryModel Logical GLSL450
|
|
OpName %missing "missing"
|
|
OpDecorate %missing Restrict ;Missing ID
|
|
%voidt = OpTypeVoid
|
|
%intt = OpTypeInt 32 1
|
|
%ptrt = OpTypePointer UniformConstant %intt
|
|
%var = OpVariable %ptrt UniformConstant
|
|
%2 = OpTypeFunction %voidt
|
|
%3 = OpFunction %voidt None %2
|
|
%4 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("missing"));
|
|
}
|
|
|
|
TEST_F(Validate, ForwardMemberDecorateGood) {
|
|
char str[] = R"(
|
|
OpCapability Matrix
|
|
OpMemoryModel Logical GLSL450
|
|
OpMemberDecorate %struct 1 RowMajor
|
|
%intt = OpTypeInt 32 1
|
|
%vec3 = OpTypeVector %intt 3
|
|
%mat33 = OpTypeMatrix %vec3 3
|
|
%struct = OpTypeStruct %intt %mat33
|
|
)";
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
}
|
|
|
|
TEST_F(Validate, ForwardMemberDecorateInvalidIdBad) {
|
|
char str[] = R"(
|
|
OpCapability Matrix
|
|
OpMemoryModel Logical GLSL450
|
|
OpName %missing "missing"
|
|
OpMemberDecorate %missing 1 RowMajor ; Target not defined
|
|
%intt = OpTypeInt 32 1
|
|
%vec3 = OpTypeVector %intt 3
|
|
%mat33 = OpTypeMatrix %vec3 3
|
|
%struct = OpTypeStruct %intt %mat33
|
|
)";
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("missing"));
|
|
}
|
|
|
|
TEST_F(Validate, ForwardGroupDecorateGood) {
|
|
char str[] = R"(
|
|
OpCapability Matrix
|
|
OpMemoryModel Logical GLSL450
|
|
OpDecorate %dgrp RowMajor
|
|
%dgrp = OpDecorationGroup
|
|
OpGroupDecorate %dgrp %mat33 %mat44
|
|
%intt = OpTypeInt 32 1
|
|
%vec3 = OpTypeVector %intt 3
|
|
%vec4 = OpTypeVector %intt 4
|
|
%mat33 = OpTypeMatrix %vec3 3
|
|
%mat44 = OpTypeMatrix %vec4 4
|
|
)";
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
}
|
|
|
|
TEST_F(Validate, ForwardGroupDecorateMissingGroupBad) {
|
|
char str[] = R"(
|
|
OpCapability Matrix
|
|
OpMemoryModel Logical GLSL450
|
|
OpName %missing "missing"
|
|
OpDecorate %dgrp RowMajor
|
|
%dgrp = OpDecorationGroup
|
|
OpGroupDecorate %missing %mat33 %mat44 ; Target not defined
|
|
%intt = OpTypeInt 32 1
|
|
%vec3 = OpTypeVector %intt 3
|
|
%vec4 = OpTypeVector %intt 4
|
|
%mat33 = OpTypeMatrix %vec3 3
|
|
%mat44 = OpTypeMatrix %vec4 4
|
|
)";
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("missing"));
|
|
}
|
|
|
|
TEST_F(Validate, ForwardGroupDecorateMissingTargetBad) {
|
|
char str[] = R"(
|
|
OpCapability Matrix
|
|
OpMemoryModel Logical GLSL450
|
|
OpName %missing "missing"
|
|
OpDecorate %dgrp RowMajor
|
|
%dgrp = OpDecorationGroup
|
|
OpGroupDecorate %dgrp %missing %mat44 ; Target not defined
|
|
%intt = OpTypeInt 32 1
|
|
%vec3 = OpTypeVector %intt 3
|
|
%vec4 = OpTypeVector %intt 4
|
|
%mat33 = OpTypeMatrix %vec3 3
|
|
%mat44 = OpTypeMatrix %vec4 4
|
|
)";
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("missing"));
|
|
}
|
|
|
|
TEST_F(Validate, ForwardGroupDecorateDecorationGroupDominateBad) {
|
|
char str[] = R"(
|
|
OpCapability Matrix
|
|
OpMemoryModel Logical GLSL450
|
|
OpName %dgrp "group"
|
|
OpDecorate %dgrp RowMajor
|
|
OpGroupDecorate %dgrp %mat33 %mat44 ; Decoration group does not dominate usage
|
|
%dgrp = OpDecorationGroup
|
|
%intt = OpTypeInt 32 1
|
|
%vec3 = OpTypeVector %intt 3
|
|
%vec4 = OpTypeVector %intt 4
|
|
%mat33 = OpTypeMatrix %vec3 3
|
|
%mat44 = OpTypeMatrix %vec4 4
|
|
)";
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("group"));
|
|
}
|
|
|
|
TEST_F(Validate, ForwardDecorateInvalidIdBad) {
|
|
char str[] = R"(
|
|
OpMemoryModel Logical GLSL450
|
|
OpName %missing "missing"
|
|
OpDecorate %missing Restrict ; Missing target
|
|
%voidt = OpTypeVoid
|
|
%intt = OpTypeInt 32 1
|
|
%ptrt = OpTypePointer UniformConstant %intt
|
|
%var = OpVariable %ptrt UniformConstant
|
|
%2 = OpTypeFunction %voidt
|
|
%3 = OpFunction %voidt None %2
|
|
%4 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("missing"));
|
|
}
|
|
|
|
TEST_F(Validate, FunctionCallGood) {
|
|
char str[] = R"(
|
|
OpMemoryModel Logical GLSL450
|
|
%1 = OpTypeVoid
|
|
%2 = OpTypeInt 32 1
|
|
%3 = OpTypeInt 32 0
|
|
%4 = OpTypeFunction %1
|
|
%8 = OpTypeFunction %1 %2 %3
|
|
%four = OpConstant %2 4
|
|
%five = OpConstant %3 5
|
|
%9 = OpFunction %1 None %8
|
|
%10 = OpFunctionParameter %2
|
|
%11 = OpFunctionParameter %3
|
|
%12 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
%5 = OpFunction %1 None %4
|
|
%6 = OpLabel
|
|
%7 = OpFunctionCall %1 %9 %four %five
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
}
|
|
|
|
TEST_F(Validate, ForwardFunctionCallGood) {
|
|
char str[] = R"(
|
|
OpMemoryModel Logical GLSL450
|
|
%1 = OpTypeVoid
|
|
%2 = OpTypeInt 32 1
|
|
%3 = OpTypeInt 32 0
|
|
%four = OpConstant %2 4
|
|
%five = OpConstant %3 5
|
|
%8 = OpTypeFunction %1 %2 %3
|
|
%4 = OpTypeFunction %1
|
|
%5 = OpFunction %1 None %4
|
|
%6 = OpLabel
|
|
%7 = OpFunctionCall %1 %9 %four %five
|
|
OpReturn
|
|
OpFunctionEnd
|
|
%9 = OpFunction %1 None %8
|
|
%10 = OpFunctionParameter %2
|
|
%11 = OpFunctionParameter %3
|
|
%12 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
}
|
|
|
|
TEST_F(Validate, ForwardBranchConditionalGood) {
|
|
char str[] = R"(
|
|
OpMemoryModel Logical GLSL450
|
|
%voidt = OpTypeVoid
|
|
%boolt = OpTypeBool
|
|
%vfunct = OpTypeFunction %voidt
|
|
%true = OpConstantTrue %boolt
|
|
%main = OpFunction %voidt None %vfunct
|
|
%mainl = OpLabel
|
|
OpSelectionMerge %endl None
|
|
OpBranchConditional %true %truel %falsel
|
|
%truel = OpLabel
|
|
OpNop
|
|
OpBranch %endl
|
|
%falsel = OpLabel
|
|
OpNop
|
|
OpBranch %endl
|
|
%endl = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
}
|
|
|
|
TEST_F(Validate, ForwardBranchConditionalWithWeightsGood) {
|
|
char str[] = R"(
|
|
OpMemoryModel Logical GLSL450
|
|
%voidt = OpTypeVoid
|
|
%boolt = OpTypeBool
|
|
%vfunct = OpTypeFunction %voidt
|
|
%true = OpConstantTrue %boolt
|
|
%main = OpFunction %voidt None %vfunct
|
|
%mainl = OpLabel
|
|
OpSelectionMerge %endl None
|
|
OpBranchConditional %true %truel %falsel 1 9
|
|
%truel = OpLabel
|
|
OpNop
|
|
OpBranch %endl
|
|
%falsel = OpLabel
|
|
OpNop
|
|
OpBranch %endl
|
|
%endl = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
}
|
|
|
|
TEST_F(Validate, ForwardBranchConditionalNonDominantConditionBad) {
|
|
char str[] = R"(
|
|
OpMemoryModel Logical GLSL450
|
|
OpName %tcpy "conditional"
|
|
%voidt = OpTypeVoid
|
|
%boolt = OpTypeBool
|
|
%vfunct = OpTypeFunction %voidt
|
|
%true = OpConstantTrue %boolt
|
|
%main = OpFunction %voidt None %vfunct
|
|
%mainl = OpLabel
|
|
OpSelectionMerge %endl None
|
|
OpBranchConditional %tcpy %truel %falsel ;
|
|
%truel = OpLabel
|
|
OpNop
|
|
OpBranch %endl
|
|
%falsel = OpLabel
|
|
OpNop
|
|
OpBranch %endl
|
|
%endl = OpLabel
|
|
%tcpy = OpCopyObject %boolt %true
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("conditional"));
|
|
}
|
|
|
|
TEST_F(Validate, ForwardBranchConditionalMissingTargetBad) {
|
|
char str[] = R"(
|
|
OpMemoryModel Logical GLSL450
|
|
OpName %missing "missing"
|
|
%voidt = OpTypeVoid
|
|
%boolt = OpTypeBool
|
|
%vfunct = OpTypeFunction %voidt
|
|
%true = OpConstantTrue %boolt
|
|
%main = OpFunction %voidt None %vfunct
|
|
%mainl = OpLabel
|
|
OpSelectionMerge %endl None
|
|
OpBranchConditional %true %missing %falsel
|
|
%truel = OpLabel
|
|
OpNop
|
|
OpBranch %endl
|
|
%falsel = OpLabel
|
|
OpNop
|
|
OpBranch %endl
|
|
%endl = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("missing"));
|
|
}
|
|
|
|
const string kHeader = R"(
|
|
OpCapability Int8
|
|
OpCapability DeviceEnqueue
|
|
OpMemoryModel Logical GLSL450
|
|
)";
|
|
|
|
const string kBasicTypes = R"(
|
|
%voidt = OpTypeVoid
|
|
%boolt = OpTypeBool
|
|
%int8t = OpTypeInt 8 0
|
|
%intt = OpTypeInt 32 1
|
|
%uintt = OpTypeInt 32 0
|
|
%vfunct = OpTypeFunction %voidt
|
|
)";
|
|
|
|
const string kKernelTypesAndConstants = R"(
|
|
%queuet = OpTypeQueue
|
|
|
|
%three = OpConstant %uintt 3
|
|
%arr3t = OpTypeArray %intt %three
|
|
%ndt = OpTypeStruct %intt %arr3t %arr3t %arr3t
|
|
|
|
%eventt = OpTypeEvent
|
|
%intptrt = OpTypePointer UniformConstant %int8t
|
|
|
|
%offset = OpConstant %intt 0
|
|
%local = OpConstant %intt 1
|
|
%gl = OpConstant %intt 1
|
|
|
|
%nevent = OpConstant %intt 0
|
|
%event = OpConstantNull %eventt
|
|
|
|
%firstp = OpConstant %int8t 0
|
|
%psize = OpConstant %intt 0
|
|
%palign = OpConstant %intt 32
|
|
%lsize = OpConstant %intt 1
|
|
%flags = OpConstant %intt 0 ; NoWait
|
|
|
|
%kfunct = OpTypeFunction %voidt %intptrt
|
|
)";
|
|
|
|
const string kKernelSetup = R"(
|
|
%dqueue = OpGetDefaultQueue %queuet
|
|
%ndval = OpBuildNDRange %ndt %gl %local %offset
|
|
%revent = OpUndef %eventt
|
|
|
|
)";
|
|
|
|
const string kKernelDefinition = R"(
|
|
%kfunc = OpFunction %voidt None %kfunct
|
|
%iparam = OpFunctionParameter %intptrt
|
|
%kfuncl = OpLabel
|
|
OpNop
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
TEST_F(Validate, EnqueueKernelGood) {
|
|
string str = kHeader + kBasicTypes + kKernelTypesAndConstants +
|
|
kKernelDefinition + R"(
|
|
%main = OpFunction %voidt None %vfunct
|
|
%mainl = OpLabel
|
|
)" +
|
|
kKernelSetup + R"(
|
|
%err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent
|
|
%event %revent %kfunc %firstp %psize
|
|
%palign %lsize
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
}
|
|
|
|
TEST_F(Validate, ForwardEnqueueKernelGood) {
|
|
string str = kHeader + kBasicTypes + kKernelTypesAndConstants + R"(
|
|
%main = OpFunction %voidt None %vfunct
|
|
%mainl = OpLabel
|
|
)" +
|
|
kKernelSetup + R"(
|
|
%err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent
|
|
%event %revent %kfunc %firstp %psize
|
|
%palign %lsize
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)" +
|
|
kKernelDefinition;
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
}
|
|
|
|
TEST_F(Validate, EnqueueMissingFunctionBad) {
|
|
string str = kHeader + "OpName %kfunc \"kfunc\"" + kBasicTypes +
|
|
kKernelTypesAndConstants + R"(
|
|
%main = OpFunction %voidt None %vfunct
|
|
%mainl = OpLabel
|
|
)" +
|
|
kKernelSetup + R"(
|
|
%err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent
|
|
%event %revent %kfunc %firstp %psize
|
|
%palign %lsize
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("kfunc"));
|
|
}
|
|
|
|
string forwardKernelNonDominantParameterBaseCode(string name = string()) {
|
|
string op_name;
|
|
if (name.empty()) {
|
|
op_name = "";
|
|
} else {
|
|
op_name = "\nOpName %" + name + " \"" + name + "\"\n";
|
|
}
|
|
string out = kHeader + op_name + kBasicTypes + kKernelTypesAndConstants +
|
|
kKernelDefinition +
|
|
R"(
|
|
%main = OpFunction %voidt None %vfunct
|
|
%mainl = OpLabel
|
|
)" +
|
|
kKernelSetup;
|
|
return out;
|
|
}
|
|
|
|
TEST_F(Validate, ForwardEnqueueKernelMissingParameter1Bad) {
|
|
string str = forwardKernelNonDominantParameterBaseCode("missing") + R"(
|
|
%err = OpEnqueueKernel %missing %dqueue %flags %ndval
|
|
%nevent %event %revent %kfunc %firstp
|
|
%psize %palign %lsize
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("missing"));
|
|
}
|
|
|
|
TEST_F(Validate, ForwardEnqueueKernelNonDominantParameter2Bad) {
|
|
string str = forwardKernelNonDominantParameterBaseCode("dqueue2") + R"(
|
|
%err = OpEnqueueKernel %uintt %dqueue2 %flags %ndval
|
|
%nevent %event %revent %kfunc
|
|
%firstp %psize %palign %lsize
|
|
%dqueue2 = OpGetDefaultQueue %queuet
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("dqueue2"));
|
|
}
|
|
|
|
TEST_F(Validate, ForwardEnqueueKernelNonDominantParameter3Bad) {
|
|
string str = forwardKernelNonDominantParameterBaseCode("ndval2") + R"(
|
|
%err = OpEnqueueKernel %uintt %dqueue %flags %ndval2
|
|
%nevent %event %revent %kfunc %firstp
|
|
%psize %palign %lsize
|
|
%ndval2 = OpBuildNDRange %ndt %gl %local %offset
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("ndval2"));
|
|
}
|
|
|
|
TEST_F(Validate, ForwardEnqueueKernelNonDominantParameter4Bad) {
|
|
string str = forwardKernelNonDominantParameterBaseCode("nevent2") + R"(
|
|
%err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent2
|
|
%event %revent %kfunc %firstp %psize
|
|
%palign %lsize
|
|
%nevent2 = OpCopyObject %intt %nevent
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("nevent2"));
|
|
}
|
|
|
|
TEST_F(Validate, ForwardEnqueueKernelNonDominantParameter5Bad) {
|
|
string str = forwardKernelNonDominantParameterBaseCode("event2") + R"(
|
|
%err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent
|
|
%event2 %revent %kfunc %firstp %psize
|
|
%palign %lsize
|
|
%event2 = OpCopyObject %eventt %event
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("event2"));
|
|
}
|
|
|
|
TEST_F(Validate, ForwardEnqueueKernelNonDominantParameter6Bad) {
|
|
string str = forwardKernelNonDominantParameterBaseCode("revent2") + R"(
|
|
%err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent
|
|
%event %revent2 %kfunc %firstp %psize
|
|
%palign %lsize
|
|
%revent2 = OpCopyObject %eventt %revent
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("revent2"));
|
|
}
|
|
|
|
TEST_F(Validate, ForwardEnqueueKernelNonDominantParameter8Bad) {
|
|
string str = forwardKernelNonDominantParameterBaseCode("firstp2") + R"(
|
|
%err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent
|
|
%event %revent %kfunc %firstp2 %psize
|
|
%palign %lsize
|
|
%firstp2 = OpCopyObject %int8t %firstp
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("firstp2"));
|
|
}
|
|
|
|
TEST_F(Validate, ForwardEnqueueKernelNonDominantParameter9Bad) {
|
|
string str = forwardKernelNonDominantParameterBaseCode("psize2") + R"(
|
|
%err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent
|
|
%event %revent %kfunc %firstp %psize2
|
|
%palign %lsize
|
|
%psize2 = OpCopyObject %intt %psize
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("psize2"));
|
|
}
|
|
|
|
TEST_F(Validate, ForwardEnqueueKernelNonDominantParameter10Bad) {
|
|
string str = forwardKernelNonDominantParameterBaseCode("palign2") + R"(
|
|
%err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent
|
|
%event %revent %kfunc %firstp %psize
|
|
%palign2 %lsize
|
|
%palign2 = OpCopyObject %intt %palign
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("palign2"));
|
|
}
|
|
|
|
TEST_F(Validate, ForwardEnqueueKernelNonDominantParameter11Bad) {
|
|
string str = forwardKernelNonDominantParameterBaseCode("lsize2") + R"(
|
|
%err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent
|
|
%event %revent %kfunc %firstp %psize
|
|
%palign %lsize2
|
|
%lsize2 = OpCopyObject %intt %lsize
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("lsize2"));
|
|
}
|
|
|
|
static const bool kWithNDrange = true;
|
|
static const bool kNoNDrange = false;
|
|
pair<string, bool> cases[] = {
|
|
{"OpGetKernelNDrangeSubGroupCount", kWithNDrange},
|
|
{"OpGetKernelNDrangeMaxSubGroupSize", kWithNDrange},
|
|
{"OpGetKernelWorkGroupSize", kNoNDrange},
|
|
{"OpGetKernelPreferredWorkGroupSizeMultiple", kNoNDrange}};
|
|
|
|
INSTANTIATE_TEST_CASE_P(KernelArgs, Validate, ::testing::ValuesIn(cases));
|
|
|
|
static const string return_instructions = R"(
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
TEST_P(Validate, GetKernelGood) {
|
|
string instruction = GetParam().first;
|
|
bool with_ndrange = GetParam().second;
|
|
string ndrange_param = with_ndrange ? " %ndval " : " ";
|
|
|
|
stringstream ss;
|
|
// clang-format off
|
|
ss << forwardKernelNonDominantParameterBaseCode() + " %numsg = "
|
|
<< instruction + " %uintt" + ndrange_param + "%kfunc %firstp %psize %palign"
|
|
<< return_instructions;
|
|
// clang-format on
|
|
|
|
CompileSuccessfully(ss.str());
|
|
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
}
|
|
|
|
TEST_P(Validate, ForwardGetKernelGood) {
|
|
string instruction = GetParam().first;
|
|
bool with_ndrange = GetParam().second;
|
|
string ndrange_param = with_ndrange ? " %ndval " : " ";
|
|
|
|
// clang-format off
|
|
string str = kHeader + kBasicTypes + kKernelTypesAndConstants +
|
|
R"(
|
|
%main = OpFunction %voidt None %vfunct
|
|
%mainl = OpLabel
|
|
)"
|
|
+ kKernelSetup + " %numsg = "
|
|
+ instruction + " %uintt" + ndrange_param + "%kfunc %firstp %psize %palign"
|
|
+ return_instructions + kKernelDefinition;
|
|
// clang-format on
|
|
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
}
|
|
|
|
TEST_P(Validate, ForwardGetKernelMissingDefinitionBad) {
|
|
string instruction = GetParam().first;
|
|
bool with_ndrange = GetParam().second;
|
|
string ndrange_param = with_ndrange ? " %ndval " : " ";
|
|
|
|
stringstream ss;
|
|
// clang-format off
|
|
ss << forwardKernelNonDominantParameterBaseCode("missing") + " %numsg = "
|
|
<< instruction + " %uintt" + ndrange_param + "%missing %firstp %psize %palign"
|
|
<< return_instructions;
|
|
// clang-format on
|
|
|
|
CompileSuccessfully(ss.str());
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("missing"));
|
|
}
|
|
|
|
TEST_P(Validate, ForwardGetKernelNDrangeSubGroupCountMissingParameter1Bad) {
|
|
string instruction = GetParam().first;
|
|
bool with_ndrange = GetParam().second;
|
|
string ndrange_param = with_ndrange ? " %ndval " : " ";
|
|
|
|
stringstream ss;
|
|
// clang-format off
|
|
ss << forwardKernelNonDominantParameterBaseCode("missing") + " %numsg = "
|
|
<< instruction + " %missing" + ndrange_param + "%kfunc %firstp %psize %palign"
|
|
<< return_instructions;
|
|
// clang-format on
|
|
|
|
CompileSuccessfully(ss.str());
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("missing"));
|
|
}
|
|
|
|
TEST_P(Validate, ForwardGetKernelNDrangeSubGroupCountNonDominantParameter2Bad) {
|
|
string instruction = GetParam().first;
|
|
bool with_ndrange = GetParam().second;
|
|
string ndrange_param = with_ndrange ? " %ndval2 " : " ";
|
|
|
|
stringstream ss;
|
|
// clang-format off
|
|
ss << forwardKernelNonDominantParameterBaseCode("ndval2") + " %numsg = "
|
|
<< instruction + " %uintt" + ndrange_param + "%kfunc %firstp %psize %palign"
|
|
<< "\n %ndval2 = OpBuildNDRange %ndt %gl %local %offset"
|
|
<< return_instructions;
|
|
// clang-format on
|
|
|
|
if (GetParam().second) {
|
|
CompileSuccessfully(ss.str());
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("ndval2"));
|
|
}
|
|
}
|
|
|
|
TEST_P(Validate, ForwardGetKernelNDrangeSubGroupCountNonDominantParameter4Bad) {
|
|
string instruction = GetParam().first;
|
|
bool with_ndrange = GetParam().second;
|
|
string ndrange_param = with_ndrange ? " %ndval " : " ";
|
|
|
|
stringstream ss;
|
|
// clang-format off
|
|
ss << forwardKernelNonDominantParameterBaseCode("firstp2") + " %numsg = "
|
|
<< instruction + " %uintt" + ndrange_param + "%kfunc %firstp2 %psize %palign"
|
|
<< "\n %firstp2 = OpCopyObject %int8t %firstp"
|
|
<< return_instructions;
|
|
// clang-format on
|
|
|
|
CompileSuccessfully(ss.str());
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("firstp2"));
|
|
}
|
|
|
|
TEST_P(Validate, ForwardGetKernelNDrangeSubGroupCountNonDominantParameter5Bad) {
|
|
string instruction = GetParam().first;
|
|
bool with_ndrange = GetParam().second;
|
|
string ndrange_param = with_ndrange ? " %ndval " : " ";
|
|
|
|
stringstream ss;
|
|
// clang-format off
|
|
ss << forwardKernelNonDominantParameterBaseCode("psize2") + " %numsg = "
|
|
<< instruction + " %uintt" + ndrange_param + "%kfunc %firstp %psize2 %palign"
|
|
<< "\n %psize2 = OpCopyObject %intt %psize"
|
|
<< return_instructions;
|
|
// clang-format on
|
|
|
|
CompileSuccessfully(ss.str());
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("psize2"));
|
|
}
|
|
|
|
TEST_P(Validate, ForwardGetKernelNDrangeSubGroupCountNonDominantParameter6Bad) {
|
|
string instruction = GetParam().first;
|
|
bool with_ndrange = GetParam().second;
|
|
string ndrange_param = with_ndrange ? " %ndval " : " ";
|
|
|
|
stringstream ss;
|
|
// clang-format off
|
|
ss << forwardKernelNonDominantParameterBaseCode("palign2") + " %numsg = "
|
|
<< instruction + " %uintt" + ndrange_param + "%kfunc %firstp %psize %palign2"
|
|
<< "\n %palign2 = OpCopyObject %intt %palign"
|
|
<< return_instructions;
|
|
// clang-format on
|
|
|
|
if (GetParam().second) {
|
|
CompileSuccessfully(ss.str());
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("palign2"));
|
|
}
|
|
}
|
|
|
|
TEST_F(Validate, PhiGood) {
|
|
string str = kHeader + kBasicTypes +
|
|
R"(
|
|
%zero = OpConstant %intt 0
|
|
%one = OpConstant %intt 1
|
|
%ten = OpConstant %intt 10
|
|
%func = OpFunction %voidt None %vfunct
|
|
%preheader = OpLabel
|
|
%init = OpCopyObject %intt %zero
|
|
OpBranch %loop
|
|
%loop = OpLabel
|
|
%i = OpPhi %intt %init %preheader %loopi %loop
|
|
%loopi = OpIAdd %intt %i %one
|
|
OpNop
|
|
%cond = OpSLessThan %boolt %i %ten
|
|
OpLoopMerge %endl %loop None
|
|
OpBranchConditional %cond %loop %endl
|
|
%endl = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
|
|
}
|
|
|
|
TEST_F(Validate, PhiMissingTypeBad) {
|
|
string str = kHeader + "OpName %missing \"missing\"" + kBasicTypes +
|
|
R"(
|
|
%zero = OpConstant %intt 0
|
|
%one = OpConstant %intt 1
|
|
%ten = OpConstant %intt 10
|
|
%func = OpFunction %voidt None %vfunct
|
|
%preheader = OpLabel
|
|
%init = OpCopyObject %intt %zero
|
|
OpBranch %loop
|
|
%loop = OpLabel
|
|
%i = OpPhi %missing %init %preheader %loopi %loop
|
|
%loopi = OpIAdd %intt %i %one
|
|
OpNop
|
|
%cond = OpSLessThan %boolt %i %ten
|
|
OpLoopMerge %endl %loop None
|
|
OpBranchConditional %cond %loop %endl
|
|
%endl = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("missing"));
|
|
}
|
|
|
|
TEST_F(Validate, PhiMissingIdBad) {
|
|
string str = kHeader + "OpName %missing \"missing\"" + kBasicTypes +
|
|
R"(
|
|
%zero = OpConstant %intt 0
|
|
%one = OpConstant %intt 1
|
|
%ten = OpConstant %intt 10
|
|
%func = OpFunction %voidt None %vfunct
|
|
%preheader = OpLabel
|
|
%init = OpCopyObject %intt %zero
|
|
OpBranch %loop
|
|
%loop = OpLabel
|
|
%i = OpPhi %intt %missing %preheader %loopi %loop
|
|
%loopi = OpIAdd %intt %i %one
|
|
OpNop
|
|
%cond = OpSLessThan %boolt %i %ten
|
|
OpLoopMerge %endl %loop None
|
|
OpBranchConditional %cond %loop %endl
|
|
%endl = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("missing"));
|
|
}
|
|
|
|
TEST_F(Validate, PhiMissingLabelBad) {
|
|
string str = kHeader + "OpName %missing \"missing\"" + kBasicTypes +
|
|
R"(
|
|
%zero = OpConstant %intt 0
|
|
%one = OpConstant %intt 1
|
|
%ten = OpConstant %intt 10
|
|
%func = OpFunction %voidt None %vfunct
|
|
%preheader = OpLabel
|
|
%init = OpCopyObject %intt %zero
|
|
OpBranch %loop
|
|
%loop = OpLabel
|
|
%i = OpPhi %intt %init %missing %loopi %loop
|
|
%loopi = OpIAdd %intt %i %one
|
|
OpNop
|
|
%cond = OpSLessThan %boolt %i %ten
|
|
OpLoopMerge %endl %loop None
|
|
OpBranchConditional %cond %loop %endl
|
|
%endl = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
CompileSuccessfully(str);
|
|
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
|
EXPECT_THAT(getDiagnosticString(), HasSubstr("missing"));
|
|
}
|
|
|
|
// TODO(umar): OpGroupMemberDecorate
|
|
}
|