1fd4e5da5Sopenharmony_ci// Copyright (c) 2019 Google LLC
2fd4e5da5Sopenharmony_ci//
3fd4e5da5Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License");
4fd4e5da5Sopenharmony_ci// you may not use this file except in compliance with the License.
5fd4e5da5Sopenharmony_ci// You may obtain a copy of the License at
6fd4e5da5Sopenharmony_ci//
7fd4e5da5Sopenharmony_ci//     http://www.apache.org/licenses/LICENSE-2.0
8fd4e5da5Sopenharmony_ci//
9fd4e5da5Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software
10fd4e5da5Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS,
11fd4e5da5Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fd4e5da5Sopenharmony_ci// See the License for the specific language governing permissions and
13fd4e5da5Sopenharmony_ci// limitations under the License.
14fd4e5da5Sopenharmony_ci
15fd4e5da5Sopenharmony_ci// Test validation of constants.
16fd4e5da5Sopenharmony_ci//
17fd4e5da5Sopenharmony_ci// This file contains newer tests.  Older tests may be in other files such as
18fd4e5da5Sopenharmony_ci// val_id_test.cpp.
19fd4e5da5Sopenharmony_ci
20fd4e5da5Sopenharmony_ci#include <string>
21fd4e5da5Sopenharmony_ci#include <vector>
22fd4e5da5Sopenharmony_ci
23fd4e5da5Sopenharmony_ci#include "gmock/gmock.h"
24fd4e5da5Sopenharmony_ci#include "test/unit_spirv.h"
25fd4e5da5Sopenharmony_ci#include "test/val/val_code_generator.h"
26fd4e5da5Sopenharmony_ci#include "test/val/val_fixtures.h"
27fd4e5da5Sopenharmony_ci
28fd4e5da5Sopenharmony_cinamespace spvtools {
29fd4e5da5Sopenharmony_cinamespace val {
30fd4e5da5Sopenharmony_cinamespace {
31fd4e5da5Sopenharmony_ci
32fd4e5da5Sopenharmony_ciusing ::testing::Combine;
33fd4e5da5Sopenharmony_ciusing ::testing::Eq;
34fd4e5da5Sopenharmony_ciusing ::testing::HasSubstr;
35fd4e5da5Sopenharmony_ciusing ::testing::Values;
36fd4e5da5Sopenharmony_ciusing ::testing::ValuesIn;
37fd4e5da5Sopenharmony_ci
38fd4e5da5Sopenharmony_ciusing ValidateConstant = spvtest::ValidateBase<bool>;
39fd4e5da5Sopenharmony_ci
40fd4e5da5Sopenharmony_ci#define kBasicTypes                             \
41fd4e5da5Sopenharmony_ci  "%bool = OpTypeBool "                         \
42fd4e5da5Sopenharmony_ci  "%uint = OpTypeInt 32 0 "                     \
43fd4e5da5Sopenharmony_ci  "%uint2 = OpTypeVector %uint 2 "              \
44fd4e5da5Sopenharmony_ci  "%float = OpTypeFloat 32 "                    \
45fd4e5da5Sopenharmony_ci  "%_ptr_uint = OpTypePointer Workgroup %uint " \
46fd4e5da5Sopenharmony_ci  "%uint_0 = OpConstantNull %uint "             \
47fd4e5da5Sopenharmony_ci  "%uint2_0 = OpConstantNull %uint "            \
48fd4e5da5Sopenharmony_ci  "%float_0 = OpConstantNull %float "           \
49fd4e5da5Sopenharmony_ci  "%false = OpConstantFalse %bool "             \
50fd4e5da5Sopenharmony_ci  "%true = OpConstantTrue %bool "               \
51fd4e5da5Sopenharmony_ci  "%null = OpConstantNull %_ptr_uint "
52fd4e5da5Sopenharmony_ci
53fd4e5da5Sopenharmony_ci#define kShaderPreamble    \
54fd4e5da5Sopenharmony_ci  "OpCapability Shader\n"  \
55fd4e5da5Sopenharmony_ci  "OpCapability Linkage\n" \
56fd4e5da5Sopenharmony_ci  "OpMemoryModel Logical Simple\n"
57fd4e5da5Sopenharmony_ci
58fd4e5da5Sopenharmony_ci#define kKernelPreamble      \
59fd4e5da5Sopenharmony_ci  "OpCapability Kernel\n"    \
60fd4e5da5Sopenharmony_ci  "OpCapability Linkage\n"   \
61fd4e5da5Sopenharmony_ci  "OpCapability Addresses\n" \
62fd4e5da5Sopenharmony_ci  "OpMemoryModel Physical32 OpenCL\n"
63fd4e5da5Sopenharmony_ci
64fd4e5da5Sopenharmony_cistruct ConstantOpCase {
65fd4e5da5Sopenharmony_ci  spv_target_env env;
66fd4e5da5Sopenharmony_ci  std::string assembly;
67fd4e5da5Sopenharmony_ci  bool expect_success;
68fd4e5da5Sopenharmony_ci  std::string expect_err;
69fd4e5da5Sopenharmony_ci};
70fd4e5da5Sopenharmony_ci
71fd4e5da5Sopenharmony_ciusing ValidateConstantOp = spvtest::ValidateBase<ConstantOpCase>;
72fd4e5da5Sopenharmony_ci
73fd4e5da5Sopenharmony_ciTEST_P(ValidateConstantOp, Samples) {
74fd4e5da5Sopenharmony_ci  const auto env = GetParam().env;
75fd4e5da5Sopenharmony_ci  CompileSuccessfully(GetParam().assembly, env);
76fd4e5da5Sopenharmony_ci  const auto result = ValidateInstructions(env);
77fd4e5da5Sopenharmony_ci  if (GetParam().expect_success) {
78fd4e5da5Sopenharmony_ci    EXPECT_EQ(SPV_SUCCESS, result);
79fd4e5da5Sopenharmony_ci    EXPECT_THAT(getDiagnosticString(), Eq(""));
80fd4e5da5Sopenharmony_ci  } else {
81fd4e5da5Sopenharmony_ci    EXPECT_EQ(SPV_ERROR_INVALID_ID, result);
82fd4e5da5Sopenharmony_ci    EXPECT_THAT(getDiagnosticString(), HasSubstr(GetParam().expect_err));
83fd4e5da5Sopenharmony_ci  }
84fd4e5da5Sopenharmony_ci}
85fd4e5da5Sopenharmony_ci
86fd4e5da5Sopenharmony_ci#define GOOD_SHADER_10(STR) \
87fd4e5da5Sopenharmony_ci  { SPV_ENV_UNIVERSAL_1_0, kShaderPreamble kBasicTypes STR, true, "" }
88fd4e5da5Sopenharmony_ci#define GOOD_KERNEL_10(STR) \
89fd4e5da5Sopenharmony_ci  { SPV_ENV_UNIVERSAL_1_0, kKernelPreamble kBasicTypes STR, true, "" }
90fd4e5da5Sopenharmony_ciINSTANTIATE_TEST_SUITE_P(
91fd4e5da5Sopenharmony_ci    UniversalInShader, ValidateConstantOp,
92fd4e5da5Sopenharmony_ci    ValuesIn(std::vector<ConstantOpCase>{
93fd4e5da5Sopenharmony_ci        // TODO(dneto): Conversions must change width.
94fd4e5da5Sopenharmony_ci        GOOD_SHADER_10("%v = OpSpecConstantOp %uint SConvert %uint_0"),
95fd4e5da5Sopenharmony_ci        GOOD_SHADER_10("%v = OpSpecConstantOp %float FConvert %float_0"),
96fd4e5da5Sopenharmony_ci        GOOD_SHADER_10("%v = OpSpecConstantOp %uint SNegate %uint_0"),
97fd4e5da5Sopenharmony_ci        GOOD_SHADER_10("%v = OpSpecConstantOp %uint Not %uint_0"),
98fd4e5da5Sopenharmony_ci        GOOD_SHADER_10("%v = OpSpecConstantOp %uint IAdd %uint_0 %uint_0"),
99fd4e5da5Sopenharmony_ci        GOOD_SHADER_10("%v = OpSpecConstantOp %uint ISub %uint_0 %uint_0"),
100fd4e5da5Sopenharmony_ci        GOOD_SHADER_10("%v = OpSpecConstantOp %uint IMul %uint_0 %uint_0"),
101fd4e5da5Sopenharmony_ci        GOOD_SHADER_10("%v = OpSpecConstantOp %uint UDiv %uint_0 %uint_0"),
102fd4e5da5Sopenharmony_ci        GOOD_SHADER_10("%v = OpSpecConstantOp %uint SDiv %uint_0 %uint_0"),
103fd4e5da5Sopenharmony_ci        GOOD_SHADER_10("%v = OpSpecConstantOp %uint UMod %uint_0 %uint_0"),
104fd4e5da5Sopenharmony_ci        GOOD_SHADER_10("%v = OpSpecConstantOp %uint SRem %uint_0 %uint_0"),
105fd4e5da5Sopenharmony_ci        GOOD_SHADER_10("%v = OpSpecConstantOp %uint SMod %uint_0 %uint_0"),
106fd4e5da5Sopenharmony_ci        GOOD_SHADER_10(
107fd4e5da5Sopenharmony_ci            "%v = OpSpecConstantOp %uint ShiftRightLogical %uint_0 %uint_0"),
108fd4e5da5Sopenharmony_ci        GOOD_SHADER_10(
109fd4e5da5Sopenharmony_ci            "%v = OpSpecConstantOp %uint ShiftRightArithmetic %uint_0 %uint_0"),
110fd4e5da5Sopenharmony_ci        GOOD_SHADER_10(
111fd4e5da5Sopenharmony_ci            "%v = OpSpecConstantOp %uint ShiftLeftLogical %uint_0 %uint_0"),
112fd4e5da5Sopenharmony_ci        GOOD_SHADER_10("%v = OpSpecConstantOp %uint BitwiseOr %uint_0 %uint_0"),
113fd4e5da5Sopenharmony_ci        GOOD_SHADER_10(
114fd4e5da5Sopenharmony_ci            "%v = OpSpecConstantOp %uint BitwiseXor %uint_0 %uint_0"),
115fd4e5da5Sopenharmony_ci        GOOD_SHADER_10(
116fd4e5da5Sopenharmony_ci            "%v = OpSpecConstantOp %uint2 VectorShuffle %uint2_0 %uint2_0 1 3"),
117fd4e5da5Sopenharmony_ci        GOOD_SHADER_10(
118fd4e5da5Sopenharmony_ci            "%v = OpSpecConstantOp %uint CompositeExtract %uint2_0 1"),
119fd4e5da5Sopenharmony_ci        GOOD_SHADER_10(
120fd4e5da5Sopenharmony_ci            "%v = OpSpecConstantOp %uint2 CompositeInsert %uint_0 %uint2_0 1"),
121fd4e5da5Sopenharmony_ci        GOOD_SHADER_10("%v = OpSpecConstantOp %bool LogicalOr %true %false"),
122fd4e5da5Sopenharmony_ci        GOOD_SHADER_10("%v = OpSpecConstantOp %bool LogicalNot %true"),
123fd4e5da5Sopenharmony_ci        GOOD_SHADER_10("%v = OpSpecConstantOp %bool LogicalAnd %true %false"),
124fd4e5da5Sopenharmony_ci        GOOD_SHADER_10("%v = OpSpecConstantOp %bool LogicalEqual %true %false"),
125fd4e5da5Sopenharmony_ci        GOOD_SHADER_10(
126fd4e5da5Sopenharmony_ci            "%v = OpSpecConstantOp %bool LogicalNotEqual %true %false"),
127fd4e5da5Sopenharmony_ci        GOOD_SHADER_10(
128fd4e5da5Sopenharmony_ci            "%v = OpSpecConstantOp %uint Select %true %uint_0 %uint_0"),
129fd4e5da5Sopenharmony_ci        GOOD_SHADER_10("%v = OpSpecConstantOp %bool IEqual %uint_0 %uint_0"),
130fd4e5da5Sopenharmony_ci        GOOD_SHADER_10("%v = OpSpecConstantOp %bool INotEqual %uint_0 %uint_0"),
131fd4e5da5Sopenharmony_ci        GOOD_SHADER_10("%v = OpSpecConstantOp %bool ULessThan %uint_0 %uint_0"),
132fd4e5da5Sopenharmony_ci        GOOD_SHADER_10("%v = OpSpecConstantOp %bool SLessThan %uint_0 %uint_0"),
133fd4e5da5Sopenharmony_ci        GOOD_SHADER_10(
134fd4e5da5Sopenharmony_ci            "%v = OpSpecConstantOp %bool ULessThanEqual %uint_0 %uint_0"),
135fd4e5da5Sopenharmony_ci        GOOD_SHADER_10(
136fd4e5da5Sopenharmony_ci            "%v = OpSpecConstantOp %bool SLessThanEqual %uint_0 %uint_0"),
137fd4e5da5Sopenharmony_ci        GOOD_SHADER_10(
138fd4e5da5Sopenharmony_ci            "%v = OpSpecConstantOp %bool UGreaterThan %uint_0 %uint_0"),
139fd4e5da5Sopenharmony_ci        GOOD_SHADER_10(
140fd4e5da5Sopenharmony_ci            "%v = OpSpecConstantOp %bool UGreaterThanEqual %uint_0 %uint_0"),
141fd4e5da5Sopenharmony_ci        GOOD_SHADER_10(
142fd4e5da5Sopenharmony_ci            "%v = OpSpecConstantOp %bool SGreaterThan %uint_0 %uint_0"),
143fd4e5da5Sopenharmony_ci        GOOD_SHADER_10(
144fd4e5da5Sopenharmony_ci            "%v = OpSpecConstantOp %bool SGreaterThanEqual %uint_0 %uint_0"),
145fd4e5da5Sopenharmony_ci    }));
146fd4e5da5Sopenharmony_ci
147fd4e5da5Sopenharmony_ciINSTANTIATE_TEST_SUITE_P(
148fd4e5da5Sopenharmony_ci    UniversalInKernel, ValidateConstantOp,
149fd4e5da5Sopenharmony_ci    ValuesIn(std::vector<ConstantOpCase>{
150fd4e5da5Sopenharmony_ci        // TODO(dneto): Conversions must change width.
151fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10("%v = OpSpecConstantOp %uint SConvert %uint_0"),
152fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10("%v = OpSpecConstantOp %float FConvert %float_0"),
153fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10("%v = OpSpecConstantOp %uint SNegate %uint_0"),
154fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10("%v = OpSpecConstantOp %uint Not %uint_0"),
155fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10("%v = OpSpecConstantOp %uint IAdd %uint_0 %uint_0"),
156fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10("%v = OpSpecConstantOp %uint ISub %uint_0 %uint_0"),
157fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10("%v = OpSpecConstantOp %uint IMul %uint_0 %uint_0"),
158fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10("%v = OpSpecConstantOp %uint UDiv %uint_0 %uint_0"),
159fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10("%v = OpSpecConstantOp %uint SDiv %uint_0 %uint_0"),
160fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10("%v = OpSpecConstantOp %uint UMod %uint_0 %uint_0"),
161fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10("%v = OpSpecConstantOp %uint SRem %uint_0 %uint_0"),
162fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10("%v = OpSpecConstantOp %uint SMod %uint_0 %uint_0"),
163fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10(
164fd4e5da5Sopenharmony_ci            "%v = OpSpecConstantOp %uint ShiftRightLogical %uint_0 %uint_0"),
165fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10(
166fd4e5da5Sopenharmony_ci            "%v = OpSpecConstantOp %uint ShiftRightArithmetic %uint_0 %uint_0"),
167fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10(
168fd4e5da5Sopenharmony_ci            "%v = OpSpecConstantOp %uint ShiftLeftLogical %uint_0 %uint_0"),
169fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10("%v = OpSpecConstantOp %uint BitwiseOr %uint_0 %uint_0"),
170fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10(
171fd4e5da5Sopenharmony_ci            "%v = OpSpecConstantOp %uint BitwiseXor %uint_0 %uint_0"),
172fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10(
173fd4e5da5Sopenharmony_ci            "%v = OpSpecConstantOp %uint2 VectorShuffle %uint2_0 %uint2_0 1 3"),
174fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10(
175fd4e5da5Sopenharmony_ci            "%v = OpSpecConstantOp %uint CompositeExtract %uint2_0 1"),
176fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10(
177fd4e5da5Sopenharmony_ci            "%v = OpSpecConstantOp %uint2 CompositeInsert %uint_0 %uint2_0 1"),
178fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10("%v = OpSpecConstantOp %bool LogicalOr %true %false"),
179fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10("%v = OpSpecConstantOp %bool LogicalNot %true"),
180fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10("%v = OpSpecConstantOp %bool LogicalAnd %true %false"),
181fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10("%v = OpSpecConstantOp %bool LogicalEqual %true %false"),
182fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10(
183fd4e5da5Sopenharmony_ci            "%v = OpSpecConstantOp %bool LogicalNotEqual %true %false"),
184fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10(
185fd4e5da5Sopenharmony_ci            "%v = OpSpecConstantOp %uint Select %true %uint_0 %uint_0"),
186fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10("%v = OpSpecConstantOp %bool IEqual %uint_0 %uint_0"),
187fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10("%v = OpSpecConstantOp %bool INotEqual %uint_0 %uint_0"),
188fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10("%v = OpSpecConstantOp %bool ULessThan %uint_0 %uint_0"),
189fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10("%v = OpSpecConstantOp %bool SLessThan %uint_0 %uint_0"),
190fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10(
191fd4e5da5Sopenharmony_ci            "%v = OpSpecConstantOp %bool ULessThanEqual %uint_0 %uint_0"),
192fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10(
193fd4e5da5Sopenharmony_ci            "%v = OpSpecConstantOp %bool SLessThanEqual %uint_0 %uint_0"),
194fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10(
195fd4e5da5Sopenharmony_ci            "%v = OpSpecConstantOp %bool UGreaterThan %uint_0 %uint_0"),
196fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10(
197fd4e5da5Sopenharmony_ci            "%v = OpSpecConstantOp %bool UGreaterThanEqual %uint_0 %uint_0"),
198fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10(
199fd4e5da5Sopenharmony_ci            "%v = OpSpecConstantOp %bool SGreaterThan %uint_0 %uint_0"),
200fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10(
201fd4e5da5Sopenharmony_ci            "%v = OpSpecConstantOp %bool SGreaterThanEqual %uint_0 %uint_0"),
202fd4e5da5Sopenharmony_ci    }));
203fd4e5da5Sopenharmony_ci
204fd4e5da5Sopenharmony_ciINSTANTIATE_TEST_SUITE_P(
205fd4e5da5Sopenharmony_ci    UConvert, ValidateConstantOp,
206fd4e5da5Sopenharmony_ci    ValuesIn(std::vector<ConstantOpCase>{
207fd4e5da5Sopenharmony_ci        // TODO(dneto): Conversions must change width.
208fd4e5da5Sopenharmony_ci        {SPV_ENV_UNIVERSAL_1_0,
209fd4e5da5Sopenharmony_ci         kKernelPreamble kBasicTypes
210fd4e5da5Sopenharmony_ci         "%v = OpSpecConstantOp %uint UConvert %uint_0",
211fd4e5da5Sopenharmony_ci         true, ""},
212fd4e5da5Sopenharmony_ci        {SPV_ENV_UNIVERSAL_1_1,
213fd4e5da5Sopenharmony_ci         kKernelPreamble kBasicTypes
214fd4e5da5Sopenharmony_ci         "%v = OpSpecConstantOp %uint UConvert %uint_0",
215fd4e5da5Sopenharmony_ci         true, ""},
216fd4e5da5Sopenharmony_ci        {SPV_ENV_UNIVERSAL_1_3,
217fd4e5da5Sopenharmony_ci         kKernelPreamble kBasicTypes
218fd4e5da5Sopenharmony_ci         "%v = OpSpecConstantOp %uint UConvert %uint_0",
219fd4e5da5Sopenharmony_ci         true, ""},
220fd4e5da5Sopenharmony_ci        {SPV_ENV_UNIVERSAL_1_3,
221fd4e5da5Sopenharmony_ci         kKernelPreamble kBasicTypes
222fd4e5da5Sopenharmony_ci         "%v = OpSpecConstantOp %uint UConvert %uint_0",
223fd4e5da5Sopenharmony_ci         true, ""},
224fd4e5da5Sopenharmony_ci        {SPV_ENV_UNIVERSAL_1_4,
225fd4e5da5Sopenharmony_ci         kKernelPreamble kBasicTypes
226fd4e5da5Sopenharmony_ci         "%v = OpSpecConstantOp %uint UConvert %uint_0",
227fd4e5da5Sopenharmony_ci         true, ""},
228fd4e5da5Sopenharmony_ci        {SPV_ENV_UNIVERSAL_1_0,
229fd4e5da5Sopenharmony_ci         kShaderPreamble kBasicTypes
230fd4e5da5Sopenharmony_ci         "%v = OpSpecConstantOp %uint UConvert %uint_0",
231fd4e5da5Sopenharmony_ci         false,
232fd4e5da5Sopenharmony_ci         "Prior to SPIR-V 1.4, specialization constant operation "
233fd4e5da5Sopenharmony_ci         "UConvert requires Kernel capability"},
234fd4e5da5Sopenharmony_ci        {SPV_ENV_UNIVERSAL_1_1,
235fd4e5da5Sopenharmony_ci         kShaderPreamble kBasicTypes
236fd4e5da5Sopenharmony_ci         "%v = OpSpecConstantOp %uint UConvert %uint_0",
237fd4e5da5Sopenharmony_ci         false,
238fd4e5da5Sopenharmony_ci         "Prior to SPIR-V 1.4, specialization constant operation "
239fd4e5da5Sopenharmony_ci         "UConvert requires Kernel capability"},
240fd4e5da5Sopenharmony_ci        {SPV_ENV_UNIVERSAL_1_3,
241fd4e5da5Sopenharmony_ci         kShaderPreamble kBasicTypes
242fd4e5da5Sopenharmony_ci         "%v = OpSpecConstantOp %uint UConvert %uint_0",
243fd4e5da5Sopenharmony_ci         false,
244fd4e5da5Sopenharmony_ci         "Prior to SPIR-V 1.4, specialization constant operation "
245fd4e5da5Sopenharmony_ci         "UConvert requires Kernel capability"},
246fd4e5da5Sopenharmony_ci        {SPV_ENV_UNIVERSAL_1_3,
247fd4e5da5Sopenharmony_ci         kShaderPreamble kBasicTypes
248fd4e5da5Sopenharmony_ci         "%v = OpSpecConstantOp %uint UConvert %uint_0",
249fd4e5da5Sopenharmony_ci         false,
250fd4e5da5Sopenharmony_ci         "Prior to SPIR-V 1.4, specialization constant operation "
251fd4e5da5Sopenharmony_ci         "UConvert requires Kernel capability"},
252fd4e5da5Sopenharmony_ci        {SPV_ENV_UNIVERSAL_1_4,
253fd4e5da5Sopenharmony_ci         kShaderPreamble kBasicTypes
254fd4e5da5Sopenharmony_ci         "%v = OpSpecConstantOp %uint UConvert %uint_0",
255fd4e5da5Sopenharmony_ci         true, ""},
256fd4e5da5Sopenharmony_ci    }));
257fd4e5da5Sopenharmony_ci
258fd4e5da5Sopenharmony_ciINSTANTIATE_TEST_SUITE_P(
259fd4e5da5Sopenharmony_ci    KernelInKernel, ValidateConstantOp,
260fd4e5da5Sopenharmony_ci    ValuesIn(std::vector<ConstantOpCase>{
261fd4e5da5Sopenharmony_ci        // TODO(dneto): Conversions must change width.
262fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10("%v = OpSpecConstantOp %uint ConvertFToS %float_0"),
263fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10("%v = OpSpecConstantOp %float ConvertSToF %uint_0"),
264fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10("%v = OpSpecConstantOp %uint ConvertFToU %float_0"),
265fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10("%v = OpSpecConstantOp %float ConvertUToF %uint_0"),
266fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10("%v = OpSpecConstantOp %uint UConvert %uint_0"),
267fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10(
268fd4e5da5Sopenharmony_ci            "%v = OpSpecConstantOp %_ptr_uint GenericCastToPtr %null"),
269fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10(
270fd4e5da5Sopenharmony_ci            "%v = OpSpecConstantOp %_ptr_uint PtrCastToGeneric %null"),
271fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10("%v = OpSpecConstantOp %uint Bitcast %uint_0"),
272fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10("%v = OpSpecConstantOp %float FNegate %float_0"),
273fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10("%v = OpSpecConstantOp %float FAdd %float_0 %float_0"),
274fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10("%v = OpSpecConstantOp %float FSub %float_0 %float_0"),
275fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10("%v = OpSpecConstantOp %float FMul %float_0 %float_0"),
276fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10("%v = OpSpecConstantOp %float FDiv %float_0 %float_0"),
277fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10("%v = OpSpecConstantOp %float FRem %float_0 %float_0"),
278fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10("%v = OpSpecConstantOp %float FMod %float_0 %float_0"),
279fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10(
280fd4e5da5Sopenharmony_ci            "%v = OpSpecConstantOp %_ptr_uint AccessChain %null %uint_0"),
281fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10("%v = OpSpecConstantOp %_ptr_uint InBoundsAccessChain "
282fd4e5da5Sopenharmony_ci                       "%null %uint_0"),
283fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10(
284fd4e5da5Sopenharmony_ci            "%v = OpSpecConstantOp %_ptr_uint PtrAccessChain %null %uint_0"),
285fd4e5da5Sopenharmony_ci        GOOD_KERNEL_10("%v = OpSpecConstantOp %_ptr_uint "
286fd4e5da5Sopenharmony_ci                       "InBoundsPtrAccessChain %null %uint_0"),
287fd4e5da5Sopenharmony_ci    }));
288fd4e5da5Sopenharmony_ci
289fd4e5da5Sopenharmony_ci#define BAD_SHADER_10(STR, NAME)                                   \
290fd4e5da5Sopenharmony_ci  {                                                                \
291fd4e5da5Sopenharmony_ci    SPV_ENV_UNIVERSAL_1_0, kShaderPreamble kBasicTypes STR, false, \
292fd4e5da5Sopenharmony_ci        "Specialization constant operation " NAME                  \
293fd4e5da5Sopenharmony_ci        " requires Kernel capability"                              \
294fd4e5da5Sopenharmony_ci  }
295fd4e5da5Sopenharmony_ciINSTANTIATE_TEST_SUITE_P(
296fd4e5da5Sopenharmony_ci    KernelInShader, ValidateConstantOp,
297fd4e5da5Sopenharmony_ci    ValuesIn(std::vector<ConstantOpCase>{
298fd4e5da5Sopenharmony_ci        // TODO(dneto): Conversions must change width.
299fd4e5da5Sopenharmony_ci        BAD_SHADER_10("%v = OpSpecConstantOp %uint ConvertFToS %float_0",
300fd4e5da5Sopenharmony_ci                      "ConvertFToS"),
301fd4e5da5Sopenharmony_ci        BAD_SHADER_10("%v = OpSpecConstantOp %float ConvertSToF %uint_0",
302fd4e5da5Sopenharmony_ci                      "ConvertSToF"),
303fd4e5da5Sopenharmony_ci        BAD_SHADER_10("%v = OpSpecConstantOp %uint ConvertFToU %float_0",
304fd4e5da5Sopenharmony_ci                      "ConvertFToU"),
305fd4e5da5Sopenharmony_ci        BAD_SHADER_10("%v = OpSpecConstantOp %float ConvertUToF %uint_0",
306fd4e5da5Sopenharmony_ci                      "ConvertUToF"),
307fd4e5da5Sopenharmony_ci        BAD_SHADER_10("%v = OpSpecConstantOp %_ptr_uint GenericCastToPtr %null",
308fd4e5da5Sopenharmony_ci                      "GenericCastToPtr"),
309fd4e5da5Sopenharmony_ci        BAD_SHADER_10("%v = OpSpecConstantOp %_ptr_uint PtrCastToGeneric %null",
310fd4e5da5Sopenharmony_ci                      "PtrCastToGeneric"),
311fd4e5da5Sopenharmony_ci        BAD_SHADER_10("%v = OpSpecConstantOp %uint Bitcast %uint_0", "Bitcast"),
312fd4e5da5Sopenharmony_ci        BAD_SHADER_10("%v = OpSpecConstantOp %float FNegate %float_0",
313fd4e5da5Sopenharmony_ci                      "FNegate"),
314fd4e5da5Sopenharmony_ci        BAD_SHADER_10("%v = OpSpecConstantOp %float FAdd %float_0 %float_0",
315fd4e5da5Sopenharmony_ci                      "FAdd"),
316fd4e5da5Sopenharmony_ci        BAD_SHADER_10("%v = OpSpecConstantOp %float FSub %float_0 %float_0",
317fd4e5da5Sopenharmony_ci                      "FSub"),
318fd4e5da5Sopenharmony_ci        BAD_SHADER_10("%v = OpSpecConstantOp %float FMul %float_0 %float_0",
319fd4e5da5Sopenharmony_ci                      "FMul"),
320fd4e5da5Sopenharmony_ci        BAD_SHADER_10("%v = OpSpecConstantOp %float FDiv %float_0 %float_0",
321fd4e5da5Sopenharmony_ci                      "FDiv"),
322fd4e5da5Sopenharmony_ci        BAD_SHADER_10("%v = OpSpecConstantOp %float FRem %float_0 %float_0",
323fd4e5da5Sopenharmony_ci                      "FRem"),
324fd4e5da5Sopenharmony_ci        BAD_SHADER_10("%v = OpSpecConstantOp %float FMod %float_0 %float_0",
325fd4e5da5Sopenharmony_ci                      "FMod"),
326fd4e5da5Sopenharmony_ci        BAD_SHADER_10(
327fd4e5da5Sopenharmony_ci            "%v = OpSpecConstantOp %_ptr_uint AccessChain %null %uint_0",
328fd4e5da5Sopenharmony_ci            "AccessChain"),
329fd4e5da5Sopenharmony_ci        BAD_SHADER_10("%v = OpSpecConstantOp %_ptr_uint InBoundsAccessChain "
330fd4e5da5Sopenharmony_ci                      "%null %uint_0",
331fd4e5da5Sopenharmony_ci                      "InBoundsAccessChain"),
332fd4e5da5Sopenharmony_ci        BAD_SHADER_10(
333fd4e5da5Sopenharmony_ci            "%v = OpSpecConstantOp %_ptr_uint PtrAccessChain %null %uint_0",
334fd4e5da5Sopenharmony_ci            "PtrAccessChain"),
335fd4e5da5Sopenharmony_ci        BAD_SHADER_10("%v = OpSpecConstantOp %_ptr_uint "
336fd4e5da5Sopenharmony_ci                      "InBoundsPtrAccessChain %null %uint_0",
337fd4e5da5Sopenharmony_ci                      "InBoundsPtrAccessChain"),
338fd4e5da5Sopenharmony_ci    }));
339fd4e5da5Sopenharmony_ci
340fd4e5da5Sopenharmony_ciINSTANTIATE_TEST_SUITE_P(
341fd4e5da5Sopenharmony_ci    UConvertInAMD_gpu_shader_int16, ValidateConstantOp,
342fd4e5da5Sopenharmony_ci    ValuesIn(std::vector<ConstantOpCase>{
343fd4e5da5Sopenharmony_ci        // SPV_AMD_gpu_shader_int16 should enable UConvert for OpSpecConstantOp
344fd4e5da5Sopenharmony_ci        // https://github.com/KhronosGroup/glslang/issues/848
345fd4e5da5Sopenharmony_ci        {SPV_ENV_UNIVERSAL_1_0,
346fd4e5da5Sopenharmony_ci         "OpCapability Shader "
347fd4e5da5Sopenharmony_ci         "OpCapability Linkage ; So we don't need to define a function\n"
348fd4e5da5Sopenharmony_ci         "OpExtension \"SPV_AMD_gpu_shader_int16\" "
349fd4e5da5Sopenharmony_ci         "OpMemoryModel Logical Simple " kBasicTypes
350fd4e5da5Sopenharmony_ci         "%v = OpSpecConstantOp %uint UConvert %uint_0",
351fd4e5da5Sopenharmony_ci         true, ""},
352fd4e5da5Sopenharmony_ci    }));
353fd4e5da5Sopenharmony_ci
354fd4e5da5Sopenharmony_ciTEST_F(ValidateConstant, SpecConstantUConvert1p3Binary1p4EnvBad) {
355fd4e5da5Sopenharmony_ci  const std::string spirv = R"(
356fd4e5da5Sopenharmony_ciOpCapability Shader
357fd4e5da5Sopenharmony_ciOpCapability Linkage
358fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
359fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
360fd4e5da5Sopenharmony_ci%int0 = OpConstant %int 0
361fd4e5da5Sopenharmony_ci%const = OpSpecConstantOp %int UConvert %int0
362fd4e5da5Sopenharmony_ci)";
363fd4e5da5Sopenharmony_ci
364fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
365fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
366fd4e5da5Sopenharmony_ci  EXPECT_THAT(
367fd4e5da5Sopenharmony_ci      getDiagnosticString(),
368fd4e5da5Sopenharmony_ci      HasSubstr(
369fd4e5da5Sopenharmony_ci          "Prior to SPIR-V 1.4, specialization constant operation UConvert "
370fd4e5da5Sopenharmony_ci          "requires Kernel capability or extension SPV_AMD_gpu_shader_int16"));
371fd4e5da5Sopenharmony_ci}
372fd4e5da5Sopenharmony_ci
373fd4e5da5Sopenharmony_ciusing SmallStorageConstants = spvtest::ValidateBase<std::string>;
374fd4e5da5Sopenharmony_ci
375fd4e5da5Sopenharmony_ciCodeGenerator GetSmallStorageCodeGenerator() {
376fd4e5da5Sopenharmony_ci  CodeGenerator generator;
377fd4e5da5Sopenharmony_ci  generator.capabilities_ = R"(
378fd4e5da5Sopenharmony_ciOpCapability Shader
379fd4e5da5Sopenharmony_ciOpCapability Linkage
380fd4e5da5Sopenharmony_ciOpCapability UniformAndStorageBuffer16BitAccess
381fd4e5da5Sopenharmony_ciOpCapability StoragePushConstant16
382fd4e5da5Sopenharmony_ciOpCapability StorageInputOutput16
383fd4e5da5Sopenharmony_ciOpCapability UniformAndStorageBuffer8BitAccess
384fd4e5da5Sopenharmony_ciOpCapability StoragePushConstant8
385fd4e5da5Sopenharmony_ci)";
386fd4e5da5Sopenharmony_ci  generator.extensions_ = R"(
387fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_16bit_storage"
388fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_8bit_storage"
389fd4e5da5Sopenharmony_ci)";
390fd4e5da5Sopenharmony_ci  generator.memory_model_ = "OpMemoryModel Logical GLSL450\n";
391fd4e5da5Sopenharmony_ci  generator.types_ = R"(
392fd4e5da5Sopenharmony_ci%short = OpTypeInt 16 0
393fd4e5da5Sopenharmony_ci%short2 = OpTypeVector %short 2
394fd4e5da5Sopenharmony_ci%char = OpTypeInt 8 0
395fd4e5da5Sopenharmony_ci%char2 = OpTypeVector %char 2
396fd4e5da5Sopenharmony_ci%half = OpTypeFloat 16
397fd4e5da5Sopenharmony_ci%half2 = OpTypeVector %half 2
398fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
399fd4e5da5Sopenharmony_ci%int_0 = OpConstant %int 0
400fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
401fd4e5da5Sopenharmony_ci%float_0 = OpConstant %float 0
402fd4e5da5Sopenharmony_ci)";
403fd4e5da5Sopenharmony_ci  return generator;
404fd4e5da5Sopenharmony_ci}
405fd4e5da5Sopenharmony_ci
406fd4e5da5Sopenharmony_ciTEST_P(SmallStorageConstants, SmallConstant) {
407fd4e5da5Sopenharmony_ci  std::string constant = GetParam();
408fd4e5da5Sopenharmony_ci  CodeGenerator generator = GetSmallStorageCodeGenerator();
409fd4e5da5Sopenharmony_ci  generator.after_types_ += constant + "\n";
410fd4e5da5Sopenharmony_ci  CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
411fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
412fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
413fd4e5da5Sopenharmony_ci              HasSubstr("Cannot form constants of 8- or 16-bit types"));
414fd4e5da5Sopenharmony_ci}
415fd4e5da5Sopenharmony_ci
416fd4e5da5Sopenharmony_ci// Constant composites would be caught through scalar constants.
417fd4e5da5Sopenharmony_ciINSTANTIATE_TEST_SUITE_P(
418fd4e5da5Sopenharmony_ci    SmallConstants, SmallStorageConstants,
419fd4e5da5Sopenharmony_ci    Values("%c = OpConstant %char 0", "%c = OpConstantNull %char2",
420fd4e5da5Sopenharmony_ci           "%c = OpConstant %short 0", "%c = OpConstantNull %short",
421fd4e5da5Sopenharmony_ci           "%c = OpConstant %half 0", "%c = OpConstantNull %half",
422fd4e5da5Sopenharmony_ci           "%c = OpSpecConstant %char 0", "%c = OpSpecConstant %short 0",
423fd4e5da5Sopenharmony_ci           "%c = OpSpecConstant %half 0",
424fd4e5da5Sopenharmony_ci           "%c = OpSpecConstantOp %char SConvert %int_0",
425fd4e5da5Sopenharmony_ci           "%c = OpSpecConstantOp %short SConvert %int_0",
426fd4e5da5Sopenharmony_ci           "%c = OpSpecConstantOp %half FConvert %float_0"));
427fd4e5da5Sopenharmony_ci
428fd4e5da5Sopenharmony_ciTEST_F(ValidateConstant, NullPointerTo16BitStorageOk) {
429fd4e5da5Sopenharmony_ci  std::string spirv = R"(
430fd4e5da5Sopenharmony_ciOpCapability Shader
431fd4e5da5Sopenharmony_ciOpCapability VariablePointersStorageBuffer
432fd4e5da5Sopenharmony_ciOpCapability UniformAndStorageBuffer16BitAccess
433fd4e5da5Sopenharmony_ciOpCapability Linkage
434fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_16bit_storage"
435fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
436fd4e5da5Sopenharmony_ci%half = OpTypeFloat 16
437fd4e5da5Sopenharmony_ci%ptr_ssbo_half = OpTypePointer StorageBuffer %half
438fd4e5da5Sopenharmony_ci%null_ptr = OpConstantNull %ptr_ssbo_half
439fd4e5da5Sopenharmony_ci)";
440fd4e5da5Sopenharmony_ci
441fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
442fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
443fd4e5da5Sopenharmony_ci}
444fd4e5da5Sopenharmony_ci
445fd4e5da5Sopenharmony_ciTEST_F(ValidateConstant, NullMatrix) {
446fd4e5da5Sopenharmony_ci  std::string spirv = R"(
447fd4e5da5Sopenharmony_ciOpCapability Shader
448fd4e5da5Sopenharmony_ciOpCapability Linkage
449fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
450fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
451fd4e5da5Sopenharmony_ci%v2float = OpTypeVector %float 2
452fd4e5da5Sopenharmony_ci%mat2x2 = OpTypeMatrix %v2float 2
453fd4e5da5Sopenharmony_ci%null_vector = OpConstantNull %v2float
454fd4e5da5Sopenharmony_ci%null_matrix = OpConstantComposite %mat2x2 %null_vector %null_vector
455fd4e5da5Sopenharmony_ci)";
456fd4e5da5Sopenharmony_ci
457fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
458fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
459fd4e5da5Sopenharmony_ci}
460fd4e5da5Sopenharmony_ci
461fd4e5da5Sopenharmony_ciTEST_F(ValidateConstant, NullPhysicalStorageBuffer) {
462fd4e5da5Sopenharmony_ci  std::string spirv = R"(
463fd4e5da5Sopenharmony_ciOpCapability Shader
464fd4e5da5Sopenharmony_ciOpCapability PhysicalStorageBufferAddresses
465fd4e5da5Sopenharmony_ciOpCapability Linkage
466fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_physical_storage_buffer"
467fd4e5da5Sopenharmony_ciOpMemoryModel PhysicalStorageBuffer64 GLSL450
468fd4e5da5Sopenharmony_ciOpName %ptr "ptr"
469fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
470fd4e5da5Sopenharmony_ci%ptr = OpTypePointer PhysicalStorageBuffer %int
471fd4e5da5Sopenharmony_ci%null = OpConstantNull %ptr
472fd4e5da5Sopenharmony_ci)";
473fd4e5da5Sopenharmony_ci
474fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
475fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
476fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
477fd4e5da5Sopenharmony_ci              HasSubstr("OpConstantNull Result Type <id> '1[%ptr]' cannot have "
478fd4e5da5Sopenharmony_ci                        "a null value"));
479fd4e5da5Sopenharmony_ci}
480fd4e5da5Sopenharmony_ci
481fd4e5da5Sopenharmony_ciTEST_F(ValidateConstant, VectorMismatchedConstituents) {
482fd4e5da5Sopenharmony_ci  std::string spirv = kShaderPreamble kBasicTypes R"(
483fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
484fd4e5da5Sopenharmony_ci%int_0 = OpConstantNull %int
485fd4e5da5Sopenharmony_ci%const_vector = OpConstantComposite %uint2 %uint_0 %int_0
486fd4e5da5Sopenharmony_ci)";
487fd4e5da5Sopenharmony_ci
488fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
489fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
490fd4e5da5Sopenharmony_ci  EXPECT_THAT(
491fd4e5da5Sopenharmony_ci      getDiagnosticString(),
492fd4e5da5Sopenharmony_ci      HasSubstr(
493fd4e5da5Sopenharmony_ci          "OpConstantComposite Constituent <id> '13[%13]'s type "
494fd4e5da5Sopenharmony_ci          "does not match Result Type <id> '3[%v2uint]'s vector element type"));
495fd4e5da5Sopenharmony_ci}
496fd4e5da5Sopenharmony_ci
497fd4e5da5Sopenharmony_ci}  // namespace
498fd4e5da5Sopenharmony_ci}  // namespace val
499fd4e5da5Sopenharmony_ci}  // namespace spvtools
500