1 // Copyright (c) 2017 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 // Tests for unique type declaration rules validator.
16 
17 #include <string>
18 
19 #include "gmock/gmock.h"
20 #include "test/unit_spirv.h"
21 #include "test/val/val_code_generator.h"
22 #include "test/val/val_fixtures.h"
23 
24 namespace spvtools {
25 namespace val {
26 namespace {
27 
28 using ::testing::HasSubstr;
29 using ::testing::Not;
30 using ::testing::Values;
31 
32 using ValidateConversion = spvtest::ValidateBase<bool>;
33 
GenerateShaderCode(const std::string & body,const std::string & capabilities_and_extensions="",const std::string & decorations="",const std::string & types="",const std::string & variables="")34 std::string GenerateShaderCode(
35     const std::string& body,
36     const std::string& capabilities_and_extensions = "",
37     const std::string& decorations = "", const std::string& types = "",
38     const std::string& variables = "") {
39   const std::string capabilities =
40       R"(
41 OpCapability Shader
42 OpCapability Int64
43 OpCapability Float64)";
44 
45   const std::string after_extension_before_decorations =
46       R"(
47 OpMemoryModel Logical GLSL450
48 OpEntryPoint Fragment %main "main"
49 OpExecutionMode %main OriginUpperLeft)";
50 
51   const std::string after_decorations_before_types =
52       R"(
53 %void = OpTypeVoid
54 %func = OpTypeFunction %void
55 %bool = OpTypeBool
56 %f32 = OpTypeFloat 32
57 %u32 = OpTypeInt 32 0
58 %s32 = OpTypeInt 32 1
59 %f64 = OpTypeFloat 64
60 %u64 = OpTypeInt 64 0
61 %s64 = OpTypeInt 64 1
62 %boolvec2 = OpTypeVector %bool 2
63 %s32vec2 = OpTypeVector %s32 2
64 %u32vec2 = OpTypeVector %u32 2
65 %u64vec2 = OpTypeVector %u64 2
66 %f32vec2 = OpTypeVector %f32 2
67 %f64vec2 = OpTypeVector %f64 2
68 %boolvec3 = OpTypeVector %bool 3
69 %u32vec3 = OpTypeVector %u32 3
70 %u64vec3 = OpTypeVector %u64 3
71 %s32vec3 = OpTypeVector %s32 3
72 %f32vec3 = OpTypeVector %f32 3
73 %f64vec3 = OpTypeVector %f64 3
74 %boolvec4 = OpTypeVector %bool 4
75 %u32vec4 = OpTypeVector %u32 4
76 %u64vec4 = OpTypeVector %u64 4
77 %s32vec4 = OpTypeVector %s32 4
78 %f32vec4 = OpTypeVector %f32 4
79 %f64vec4 = OpTypeVector %f64 4
80 
81 %f32_0 = OpConstant %f32 0
82 %f32_1 = OpConstant %f32 1
83 %f32_2 = OpConstant %f32 2
84 %f32_3 = OpConstant %f32 3
85 %f32_4 = OpConstant %f32 4
86 
87 %s32_0 = OpConstant %s32 0
88 %s32_1 = OpConstant %s32 1
89 %s32_2 = OpConstant %s32 2
90 %s32_3 = OpConstant %s32 3
91 %s32_4 = OpConstant %s32 4
92 %s32_m1 = OpConstant %s32 -1
93 
94 %u32_0 = OpConstant %u32 0
95 %u32_1 = OpConstant %u32 1
96 %u32_2 = OpConstant %u32 2
97 %u32_3 = OpConstant %u32 3
98 %u32_4 = OpConstant %u32 4
99 
100 %f64_0 = OpConstant %f64 0
101 %f64_1 = OpConstant %f64 1
102 %f64_2 = OpConstant %f64 2
103 %f64_3 = OpConstant %f64 3
104 %f64_4 = OpConstant %f64 4
105 
106 %s64_0 = OpConstant %s64 0
107 %s64_1 = OpConstant %s64 1
108 %s64_2 = OpConstant %s64 2
109 %s64_3 = OpConstant %s64 3
110 %s64_4 = OpConstant %s64 4
111 %s64_m1 = OpConstant %s64 -1
112 
113 %u64_0 = OpConstant %u64 0
114 %u64_1 = OpConstant %u64 1
115 %u64_2 = OpConstant %u64 2
116 %u64_3 = OpConstant %u64 3
117 %u64_4 = OpConstant %u64 4
118 
119 %u32vec2_01 = OpConstantComposite %u32vec2 %u32_0 %u32_1
120 %u32vec2_12 = OpConstantComposite %u32vec2 %u32_1 %u32_2
121 %u32vec3_012 = OpConstantComposite %u32vec3 %u32_0 %u32_1 %u32_2
122 %u32vec3_123 = OpConstantComposite %u32vec3 %u32_1 %u32_2 %u32_3
123 %u32vec4_0123 = OpConstantComposite %u32vec4 %u32_0 %u32_1 %u32_2 %u32_3
124 %u32vec4_1234 = OpConstantComposite %u32vec4 %u32_1 %u32_2 %u32_3 %u32_4
125 
126 %s32vec2_01 = OpConstantComposite %s32vec2 %s32_0 %s32_1
127 %s32vec2_12 = OpConstantComposite %s32vec2 %s32_1 %s32_2
128 %s32vec3_012 = OpConstantComposite %s32vec3 %s32_0 %s32_1 %s32_2
129 %s32vec3_123 = OpConstantComposite %s32vec3 %s32_1 %s32_2 %s32_3
130 %s32vec4_0123 = OpConstantComposite %s32vec4 %s32_0 %s32_1 %s32_2 %s32_3
131 %s32vec4_1234 = OpConstantComposite %s32vec4 %s32_1 %s32_2 %s32_3 %s32_4
132 
133 %f32vec2_01 = OpConstantComposite %f32vec2 %f32_0 %f32_1
134 %f32vec2_12 = OpConstantComposite %f32vec2 %f32_1 %f32_2
135 %f32vec3_012 = OpConstantComposite %f32vec3 %f32_0 %f32_1 %f32_2
136 %f32vec3_123 = OpConstantComposite %f32vec3 %f32_1 %f32_2 %f32_3
137 %f32vec4_0123 = OpConstantComposite %f32vec4 %f32_0 %f32_1 %f32_2 %f32_3
138 %f32vec4_1234 = OpConstantComposite %f32vec4 %f32_1 %f32_2 %f32_3 %f32_4
139 
140 %f64vec2_01 = OpConstantComposite %f64vec2 %f64_0 %f64_1
141 %f64vec2_12 = OpConstantComposite %f64vec2 %f64_1 %f64_2
142 %f64vec3_012 = OpConstantComposite %f64vec3 %f64_0 %f64_1 %f64_2
143 %f64vec3_123 = OpConstantComposite %f64vec3 %f64_1 %f64_2 %f64_3
144 %f64vec4_0123 = OpConstantComposite %f64vec4 %f64_0 %f64_1 %f64_2 %f64_3
145 %f64vec4_1234 = OpConstantComposite %f64vec4 %f64_1 %f64_2 %f64_3 %f64_4
146 
147 %true = OpConstantTrue %bool
148 %false = OpConstantFalse %bool
149 
150 %f32ptr_func = OpTypePointer Function %f32)";
151 
152   const std::string after_variables_before_body =
153       R"(
154 %main = OpFunction %void None %func
155 %main_entry = OpLabel)";
156 
157   const std::string after_body =
158       R"(
159 OpReturn
160 OpFunctionEnd)";
161 
162   return capabilities + capabilities_and_extensions +
163          after_extension_before_decorations + decorations +
164          after_decorations_before_types + types + variables +
165          after_variables_before_body + body + after_body;
166 }
167 
GenerateKernelCode(const std::string & body,const std::string & capabilities_and_extensions="")168 std::string GenerateKernelCode(
169     const std::string& body,
170     const std::string& capabilities_and_extensions = "") {
171   const std::string capabilities =
172       R"(
173 OpCapability Addresses
174 OpCapability Kernel
175 OpCapability Linkage
176 OpCapability GenericPointer
177 OpCapability Int64
178 OpCapability Float64)";
179 
180   const std::string after_extension_before_body =
181       R"(
182 OpMemoryModel Physical32 OpenCL
183 %void = OpTypeVoid
184 %func = OpTypeFunction %void
185 %bool = OpTypeBool
186 %f32 = OpTypeFloat 32
187 %u32 = OpTypeInt 32 0
188 %f64 = OpTypeFloat 64
189 %u64 = OpTypeInt 64 0
190 %boolvec2 = OpTypeVector %bool 2
191 %u32vec2 = OpTypeVector %u32 2
192 %u64vec2 = OpTypeVector %u64 2
193 %f32vec2 = OpTypeVector %f32 2
194 %f64vec2 = OpTypeVector %f64 2
195 %boolvec3 = OpTypeVector %bool 3
196 %u32vec3 = OpTypeVector %u32 3
197 %u64vec3 = OpTypeVector %u64 3
198 %f32vec3 = OpTypeVector %f32 3
199 %f64vec3 = OpTypeVector %f64 3
200 %boolvec4 = OpTypeVector %bool 4
201 %u32vec4 = OpTypeVector %u32 4
202 %u64vec4 = OpTypeVector %u64 4
203 %f32vec4 = OpTypeVector %f32 4
204 %f64vec4 = OpTypeVector %f64 4
205 
206 %f32_0 = OpConstant %f32 0
207 %f32_1 = OpConstant %f32 1
208 %f32_2 = OpConstant %f32 2
209 %f32_3 = OpConstant %f32 3
210 %f32_4 = OpConstant %f32 4
211 
212 %u32_0 = OpConstant %u32 0
213 %u32_1 = OpConstant %u32 1
214 %u32_2 = OpConstant %u32 2
215 %u32_3 = OpConstant %u32 3
216 %u32_4 = OpConstant %u32 4
217 
218 %f64_0 = OpConstant %f64 0
219 %f64_1 = OpConstant %f64 1
220 %f64_2 = OpConstant %f64 2
221 %f64_3 = OpConstant %f64 3
222 %f64_4 = OpConstant %f64 4
223 
224 %u64_0 = OpConstant %u64 0
225 %u64_1 = OpConstant %u64 1
226 %u64_2 = OpConstant %u64 2
227 %u64_3 = OpConstant %u64 3
228 %u64_4 = OpConstant %u64 4
229 
230 %u32vec2_01 = OpConstantComposite %u32vec2 %u32_0 %u32_1
231 %u32vec2_12 = OpConstantComposite %u32vec2 %u32_1 %u32_2
232 %u32vec3_012 = OpConstantComposite %u32vec3 %u32_0 %u32_1 %u32_2
233 %u32vec3_123 = OpConstantComposite %u32vec3 %u32_1 %u32_2 %u32_3
234 %u32vec4_0123 = OpConstantComposite %u32vec4 %u32_0 %u32_1 %u32_2 %u32_3
235 %u32vec4_1234 = OpConstantComposite %u32vec4 %u32_1 %u32_2 %u32_3 %u32_4
236 
237 %f32vec2_01 = OpConstantComposite %f32vec2 %f32_0 %f32_1
238 %f32vec2_12 = OpConstantComposite %f32vec2 %f32_1 %f32_2
239 %f32vec3_012 = OpConstantComposite %f32vec3 %f32_0 %f32_1 %f32_2
240 %f32vec3_123 = OpConstantComposite %f32vec3 %f32_1 %f32_2 %f32_3
241 %f32vec4_0123 = OpConstantComposite %f32vec4 %f32_0 %f32_1 %f32_2 %f32_3
242 %f32vec4_1234 = OpConstantComposite %f32vec4 %f32_1 %f32_2 %f32_3 %f32_4
243 
244 %f64vec2_01 = OpConstantComposite %f64vec2 %f64_0 %f64_1
245 %f64vec2_12 = OpConstantComposite %f64vec2 %f64_1 %f64_2
246 %f64vec3_012 = OpConstantComposite %f64vec3 %f64_0 %f64_1 %f64_2
247 %f64vec3_123 = OpConstantComposite %f64vec3 %f64_1 %f64_2 %f64_3
248 %f64vec4_0123 = OpConstantComposite %f64vec4 %f64_0 %f64_1 %f64_2 %f64_3
249 %f64vec4_1234 = OpConstantComposite %f64vec4 %f64_1 %f64_2 %f64_3 %f64_4
250 
251 %u64vec2_01 = OpConstantComposite %u64vec2 %u64_0 %u64_1
252 
253 %true = OpConstantTrue %bool
254 %false = OpConstantFalse %bool
255 
256 %f32ptr_func = OpTypePointer Function %f32
257 %u32ptr_func = OpTypePointer Function %u32
258 %f32ptr_gen = OpTypePointer Generic %f32
259 %f32ptr_inp = OpTypePointer Input %f32
260 %f32ptr_wg = OpTypePointer Workgroup %f32
261 %f32ptr_cwg = OpTypePointer CrossWorkgroup %f32
262 
263 %f32inp = OpVariable %f32ptr_inp Input
264 
265 %main = OpFunction %void None %func
266 %main_entry = OpLabel)";
267 
268   const std::string after_body =
269       R"(
270 OpReturn
271 OpFunctionEnd)";
272 
273   return capabilities + capabilities_and_extensions +
274          after_extension_before_body + body + after_body;
275 }
276 
TEST_F(ValidateConversion,ConvertFToUSuccess)277 TEST_F(ValidateConversion, ConvertFToUSuccess) {
278   const std::string body = R"(
279 %val1 = OpConvertFToU %u32 %f32_1
280 %val2 = OpConvertFToU %u32 %f64_0
281 %val3 = OpConvertFToU %u32vec2 %f32vec2_01
282 )";
283 
284   CompileSuccessfully(GenerateShaderCode(body).c_str());
285   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
286 }
287 
TEST_F(ValidateConversion,ConvertFToUWrongResultType)288 TEST_F(ValidateConversion, ConvertFToUWrongResultType) {
289   const std::string body = R"(
290 %val = OpConvertFToU %s32 %f32_1
291 )";
292 
293   CompileSuccessfully(GenerateShaderCode(body).c_str());
294   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
295   EXPECT_THAT(getDiagnosticString(),
296               HasSubstr("Expected unsigned int scalar or vector type as Result "
297                         "Type: ConvertFToU"));
298 }
299 
TEST_F(ValidateConversion,ConvertFToUWrongInputType)300 TEST_F(ValidateConversion, ConvertFToUWrongInputType) {
301   const std::string body = R"(
302 %val = OpConvertFToU %u32 %u32_1
303 )";
304 
305   CompileSuccessfully(GenerateShaderCode(body).c_str());
306   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
307   EXPECT_THAT(
308       getDiagnosticString(),
309       HasSubstr("Expected input to be float scalar or vector: ConvertFToU"));
310 }
311 
TEST_F(ValidateConversion,ConvertFToUDifferentDimension)312 TEST_F(ValidateConversion, ConvertFToUDifferentDimension) {
313   const std::string body = R"(
314 %val = OpConvertFToU %u32 %f32vec2_01
315 )";
316 
317   CompileSuccessfully(GenerateShaderCode(body).c_str());
318   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
319   EXPECT_THAT(getDiagnosticString(),
320               HasSubstr("Expected input to have the same dimension as Result "
321                         "Type: ConvertFToU"));
322 }
323 
TEST_F(ValidateConversion,ConvertFToSSuccess)324 TEST_F(ValidateConversion, ConvertFToSSuccess) {
325   const std::string body = R"(
326 %val1 = OpConvertFToS %s32 %f32_1
327 %val2 = OpConvertFToS %u32 %f64_0
328 %val3 = OpConvertFToS %s32vec2 %f32vec2_01
329 )";
330 
331   CompileSuccessfully(GenerateShaderCode(body).c_str());
332   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
333 }
334 
TEST_F(ValidateConversion,ConvertFToSWrongResultType)335 TEST_F(ValidateConversion, ConvertFToSWrongResultType) {
336   const std::string body = R"(
337 %val = OpConvertFToS %bool %f32_1
338 )";
339 
340   CompileSuccessfully(GenerateShaderCode(body).c_str());
341   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
342   EXPECT_THAT(
343       getDiagnosticString(),
344       HasSubstr(
345           "Expected int scalar or vector type as Result Type: ConvertFToS"));
346 }
347 
TEST_F(ValidateConversion,ConvertFToSWrongInputType)348 TEST_F(ValidateConversion, ConvertFToSWrongInputType) {
349   const std::string body = R"(
350 %val = OpConvertFToS %s32 %u32_1
351 )";
352 
353   CompileSuccessfully(GenerateShaderCode(body).c_str());
354   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
355   EXPECT_THAT(
356       getDiagnosticString(),
357       HasSubstr("Expected input to be float scalar or vector: ConvertFToS"));
358 }
359 
TEST_F(ValidateConversion,ConvertFToSDifferentDimension)360 TEST_F(ValidateConversion, ConvertFToSDifferentDimension) {
361   const std::string body = R"(
362 %val = OpConvertFToS %u32 %f32vec2_01
363 )";
364 
365   CompileSuccessfully(GenerateShaderCode(body).c_str());
366   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
367   EXPECT_THAT(getDiagnosticString(),
368               HasSubstr("Expected input to have the same dimension as Result "
369                         "Type: ConvertFToS"));
370 }
371 
TEST_F(ValidateConversion,ConvertSToFSuccess)372 TEST_F(ValidateConversion, ConvertSToFSuccess) {
373   const std::string body = R"(
374 %val1 = OpConvertSToF %f32 %u32_1
375 %val2 = OpConvertSToF %f32 %s64_0
376 %val3 = OpConvertSToF %f32vec2 %s32vec2_01
377 )";
378 
379   CompileSuccessfully(GenerateShaderCode(body).c_str());
380   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
381 }
382 
TEST_F(ValidateConversion,ConvertSToFWrongResultType)383 TEST_F(ValidateConversion, ConvertSToFWrongResultType) {
384   const std::string body = R"(
385 %val = OpConvertSToF %u32 %s32_1
386 )";
387 
388   CompileSuccessfully(GenerateShaderCode(body).c_str());
389   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
390   EXPECT_THAT(
391       getDiagnosticString(),
392       HasSubstr(
393           "Expected float scalar or vector type as Result Type: ConvertSToF"));
394 }
395 
TEST_F(ValidateConversion,ConvertSToFWrongInputType)396 TEST_F(ValidateConversion, ConvertSToFWrongInputType) {
397   const std::string body = R"(
398 %val = OpConvertSToF %f32 %f32_1
399 )";
400 
401   CompileSuccessfully(GenerateShaderCode(body).c_str());
402   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
403   EXPECT_THAT(
404       getDiagnosticString(),
405       HasSubstr("Expected input to be int scalar or vector: ConvertSToF"));
406 }
407 
TEST_F(ValidateConversion,ConvertSToFDifferentDimension)408 TEST_F(ValidateConversion, ConvertSToFDifferentDimension) {
409   const std::string body = R"(
410 %val = OpConvertSToF %f32 %u32vec2_01
411 )";
412 
413   CompileSuccessfully(GenerateShaderCode(body).c_str());
414   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
415   EXPECT_THAT(getDiagnosticString(),
416               HasSubstr("Expected input to have the same dimension as Result "
417                         "Type: ConvertSToF"));
418 }
419 
TEST_F(ValidateConversion,UConvertSuccess)420 TEST_F(ValidateConversion, UConvertSuccess) {
421   const std::string body = R"(
422 %val1 = OpUConvert %u32 %u64_1
423 %val2 = OpUConvert %u64 %s32_0
424 %val3 = OpUConvert %u64vec2 %s32vec2_01
425 )";
426 
427   CompileSuccessfully(GenerateShaderCode(body).c_str());
428   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
429 }
430 
TEST_F(ValidateConversion,UConvertWrongResultType)431 TEST_F(ValidateConversion, UConvertWrongResultType) {
432   const std::string body = R"(
433 %val = OpUConvert %s32 %s32_1
434 )";
435 
436   CompileSuccessfully(GenerateShaderCode(body).c_str());
437   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
438   EXPECT_THAT(getDiagnosticString(),
439               HasSubstr("Expected unsigned int scalar or vector type as Result "
440                         "Type: UConvert"));
441 }
442 
TEST_F(ValidateConversion,UConvertWrongInputType)443 TEST_F(ValidateConversion, UConvertWrongInputType) {
444   const std::string body = R"(
445 %val = OpUConvert %u32 %f32_1
446 )";
447 
448   CompileSuccessfully(GenerateShaderCode(body).c_str());
449   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
450   EXPECT_THAT(getDiagnosticString(),
451               HasSubstr("Expected input to be int scalar or vector: UConvert"));
452 }
453 
TEST_F(ValidateConversion,UConvertDifferentDimension)454 TEST_F(ValidateConversion, UConvertDifferentDimension) {
455   const std::string body = R"(
456 %val = OpUConvert %u32 %u32vec2_01
457 )";
458 
459   CompileSuccessfully(GenerateShaderCode(body).c_str());
460   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
461   EXPECT_THAT(getDiagnosticString(),
462               HasSubstr("Expected input to have the same dimension as Result "
463                         "Type: UConvert"));
464 }
465 
TEST_F(ValidateConversion,UConvertSameBitWidth)466 TEST_F(ValidateConversion, UConvertSameBitWidth) {
467   const std::string body = R"(
468 %val = OpUConvert %u32 %s32_1
469 )";
470 
471   CompileSuccessfully(GenerateShaderCode(body).c_str());
472   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
473   EXPECT_THAT(getDiagnosticString(),
474               HasSubstr("Expected input to have different bit width from "
475                         "Result Type: UConvert"));
476 }
477 
TEST_F(ValidateConversion,SConvertSuccess)478 TEST_F(ValidateConversion, SConvertSuccess) {
479   const std::string body = R"(
480 %val1 = OpSConvert %s32 %u64_1
481 %val2 = OpSConvert %s64 %s32_0
482 %val3 = OpSConvert %u64vec2 %s32vec2_01
483 )";
484 
485   CompileSuccessfully(GenerateShaderCode(body).c_str());
486   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
487 }
488 
TEST_F(ValidateConversion,SConvertWrongResultType)489 TEST_F(ValidateConversion, SConvertWrongResultType) {
490   const std::string body = R"(
491 %val = OpSConvert %f32 %s32_1
492 )";
493 
494   CompileSuccessfully(GenerateShaderCode(body).c_str());
495   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
496   EXPECT_THAT(
497       getDiagnosticString(),
498       HasSubstr("Expected int scalar or vector type as Result Type: SConvert"));
499 }
500 
TEST_F(ValidateConversion,SConvertWrongInputType)501 TEST_F(ValidateConversion, SConvertWrongInputType) {
502   const std::string body = R"(
503 %val = OpSConvert %u32 %f32_1
504 )";
505 
506   CompileSuccessfully(GenerateShaderCode(body).c_str());
507   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
508   EXPECT_THAT(getDiagnosticString(),
509               HasSubstr("Expected input to be int scalar or vector: SConvert"));
510 }
511 
TEST_F(ValidateConversion,SConvertDifferentDimension)512 TEST_F(ValidateConversion, SConvertDifferentDimension) {
513   const std::string body = R"(
514 %val = OpSConvert %s32 %u32vec2_01
515 )";
516 
517   CompileSuccessfully(GenerateShaderCode(body).c_str());
518   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
519   EXPECT_THAT(getDiagnosticString(),
520               HasSubstr("Expected input to have the same dimension as Result "
521                         "Type: SConvert"));
522 }
523 
TEST_F(ValidateConversion,SConvertSameBitWidth)524 TEST_F(ValidateConversion, SConvertSameBitWidth) {
525   const std::string body = R"(
526 %val = OpSConvert %u32 %s32_1
527 )";
528 
529   CompileSuccessfully(GenerateShaderCode(body).c_str());
530   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
531   EXPECT_THAT(getDiagnosticString(),
532               HasSubstr("Expected input to have different bit width from "
533                         "Result Type: SConvert"));
534 }
535 
TEST_F(ValidateConversion,FConvertSuccess)536 TEST_F(ValidateConversion, FConvertSuccess) {
537   const std::string body = R"(
538 %val1 = OpFConvert %f32 %f64_1
539 %val2 = OpFConvert %f64 %f32_0
540 %val3 = OpFConvert %f64vec2 %f32vec2_01
541 )";
542 
543   CompileSuccessfully(GenerateShaderCode(body).c_str());
544   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
545 }
546 
TEST_F(ValidateConversion,FConvertWrongResultType)547 TEST_F(ValidateConversion, FConvertWrongResultType) {
548   const std::string body = R"(
549 %val = OpFConvert %u32 %f32_1
550 )";
551 
552   CompileSuccessfully(GenerateShaderCode(body).c_str());
553   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
554   EXPECT_THAT(
555       getDiagnosticString(),
556       HasSubstr(
557           "Expected float scalar or vector type as Result Type: FConvert"));
558 }
559 
TEST_F(ValidateConversion,FConvertWrongInputType)560 TEST_F(ValidateConversion, FConvertWrongInputType) {
561   const std::string body = R"(
562 %val = OpFConvert %f32 %u64_1
563 )";
564 
565   CompileSuccessfully(GenerateShaderCode(body).c_str());
566   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
567   EXPECT_THAT(
568       getDiagnosticString(),
569       HasSubstr("Expected input to be float scalar or vector: FConvert"));
570 }
571 
TEST_F(ValidateConversion,FConvertDifferentDimension)572 TEST_F(ValidateConversion, FConvertDifferentDimension) {
573   const std::string body = R"(
574 %val = OpFConvert %f64 %f32vec2_01
575 )";
576 
577   CompileSuccessfully(GenerateShaderCode(body).c_str());
578   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
579   EXPECT_THAT(getDiagnosticString(),
580               HasSubstr("Expected input to have the same dimension as Result "
581                         "Type: FConvert"));
582 }
583 
TEST_F(ValidateConversion,FConvertSameBitWidth)584 TEST_F(ValidateConversion, FConvertSameBitWidth) {
585   const std::string body = R"(
586 %val = OpFConvert %f32 %f32_1
587 )";
588 
589   CompileSuccessfully(GenerateShaderCode(body).c_str());
590   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
591   EXPECT_THAT(getDiagnosticString(),
592               HasSubstr("Expected input to have different bit width from "
593                         "Result Type: FConvert"));
594 }
595 
TEST_F(ValidateConversion,QuantizeToF16Success)596 TEST_F(ValidateConversion, QuantizeToF16Success) {
597   const std::string body = R"(
598 %val1 = OpQuantizeToF16 %f32 %f32_1
599 %val2 = OpQuantizeToF16 %f32 %f32_0
600 %val3 = OpQuantizeToF16 %f32vec2 %f32vec2_01
601 )";
602 
603   CompileSuccessfully(GenerateShaderCode(body).c_str());
604   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
605 }
606 
TEST_F(ValidateConversion,QuantizeToF16WrongResultType)607 TEST_F(ValidateConversion, QuantizeToF16WrongResultType) {
608   const std::string body = R"(
609 %val = OpQuantizeToF16 %u32 %f32_1
610 )";
611 
612   CompileSuccessfully(GenerateShaderCode(body).c_str());
613   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
614   EXPECT_THAT(
615       getDiagnosticString(),
616       HasSubstr("Expected 32-bit float scalar or vector type as Result Type: "
617                 "QuantizeToF16"));
618 }
619 
TEST_F(ValidateConversion,QuantizeToF16WrongResultTypeBitWidth)620 TEST_F(ValidateConversion, QuantizeToF16WrongResultTypeBitWidth) {
621   const std::string body = R"(
622 %val = OpQuantizeToF16 %u64 %f64_1
623 )";
624 
625   CompileSuccessfully(GenerateShaderCode(body).c_str());
626   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
627   EXPECT_THAT(
628       getDiagnosticString(),
629       HasSubstr("Expected 32-bit float scalar or vector type as Result Type: "
630                 "QuantizeToF16"));
631 }
632 
TEST_F(ValidateConversion,QuantizeToF16WrongInputType)633 TEST_F(ValidateConversion, QuantizeToF16WrongInputType) {
634   const std::string body = R"(
635 %val = OpQuantizeToF16 %f32 %f64_1
636 )";
637 
638   CompileSuccessfully(GenerateShaderCode(body).c_str());
639   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
640   EXPECT_THAT(
641       getDiagnosticString(),
642       HasSubstr(
643           "Expected input type to be equal to Result Type: QuantizeToF16"));
644 }
645 
TEST_F(ValidateConversion,ConvertPtrToUSuccess)646 TEST_F(ValidateConversion, ConvertPtrToUSuccess) {
647   const std::string body = R"(
648 %ptr = OpVariable %f32ptr_func Function
649 %val1 = OpConvertPtrToU %u32 %ptr
650 %val2 = OpConvertPtrToU %u64 %ptr
651 )";
652 
653   CompileSuccessfully(GenerateKernelCode(body).c_str());
654   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
655 }
656 
TEST_F(ValidateConversion,ConvertPtrToUWrongResultType)657 TEST_F(ValidateConversion, ConvertPtrToUWrongResultType) {
658   const std::string body = R"(
659 %ptr = OpVariable %f32ptr_func Function
660 %val = OpConvertPtrToU %f32 %ptr
661 )";
662 
663   CompileSuccessfully(GenerateKernelCode(body).c_str());
664   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
665   EXPECT_THAT(getDiagnosticString(),
666               HasSubstr("Expected unsigned int scalar type as Result Type: "
667                         "ConvertPtrToU"));
668 }
669 
TEST_F(ValidateConversion,ConvertPtrToUNotPointer)670 TEST_F(ValidateConversion, ConvertPtrToUNotPointer) {
671   const std::string body = R"(
672 %val = OpConvertPtrToU %u32 %f32_1
673 )";
674 
675   CompileSuccessfully(GenerateKernelCode(body).c_str());
676   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
677   EXPECT_THAT(getDiagnosticString(),
678               HasSubstr("Expected input to be a pointer: ConvertPtrToU"));
679 }
680 
TEST_F(ValidateConversion,SatConvertSToUSuccess)681 TEST_F(ValidateConversion, SatConvertSToUSuccess) {
682   const std::string body = R"(
683 %val1 = OpSatConvertSToU %u32 %u64_2
684 %val2 = OpSatConvertSToU %u64 %u32_1
685 %val3 = OpSatConvertSToU %u64vec2 %u32vec2_12
686 )";
687 
688   CompileSuccessfully(GenerateKernelCode(body).c_str());
689   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
690 }
691 
TEST_F(ValidateConversion,SatConvertSToUWrongResultType)692 TEST_F(ValidateConversion, SatConvertSToUWrongResultType) {
693   const std::string body = R"(
694 %val = OpSatConvertSToU %f32 %u32_1
695 )";
696 
697   CompileSuccessfully(GenerateKernelCode(body).c_str());
698   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
699   EXPECT_THAT(getDiagnosticString(),
700               HasSubstr("Expected int scalar or vector type as Result Type: "
701                         "SatConvertSToU"));
702 }
703 
TEST_F(ValidateConversion,SatConvertSToUWrongInputType)704 TEST_F(ValidateConversion, SatConvertSToUWrongInputType) {
705   const std::string body = R"(
706 %val = OpSatConvertSToU %u32 %f32_1
707 )";
708 
709   CompileSuccessfully(GenerateKernelCode(body).c_str());
710   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
711   EXPECT_THAT(
712       getDiagnosticString(),
713       HasSubstr("Expected int scalar or vector as input: SatConvertSToU"));
714 }
715 
TEST_F(ValidateConversion,SatConvertSToUDifferentDimension)716 TEST_F(ValidateConversion, SatConvertSToUDifferentDimension) {
717   const std::string body = R"(
718 %val = OpSatConvertSToU %u32 %u32vec2_12
719 )";
720 
721   CompileSuccessfully(GenerateKernelCode(body).c_str());
722   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
723   EXPECT_THAT(
724       getDiagnosticString(),
725       HasSubstr("Expected input to have the same dimension as Result Type: "
726                 "SatConvertSToU"));
727 }
728 
TEST_F(ValidateConversion,ConvertUToPtrSuccess)729 TEST_F(ValidateConversion, ConvertUToPtrSuccess) {
730   const std::string body = R"(
731 %val1 = OpConvertUToPtr %f32ptr_func %u32_1
732 %val2 = OpConvertUToPtr %f32ptr_func %u64_1
733 )";
734 
735   CompileSuccessfully(GenerateKernelCode(body).c_str());
736   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
737 }
738 
TEST_F(ValidateConversion,ConvertUToPtrWrongResultType)739 TEST_F(ValidateConversion, ConvertUToPtrWrongResultType) {
740   const std::string body = R"(
741 %val = OpConvertUToPtr %f32 %u32_1
742 )";
743 
744   CompileSuccessfully(GenerateKernelCode(body).c_str());
745   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
746   EXPECT_THAT(getDiagnosticString(),
747               HasSubstr("Expected Result Type to be a pointer: ConvertUToPtr"));
748 }
749 
TEST_F(ValidateConversion,ConvertUToPtrNotInt)750 TEST_F(ValidateConversion, ConvertUToPtrNotInt) {
751   const std::string body = R"(
752 %val = OpConvertUToPtr %f32ptr_func %f32_1
753 )";
754 
755   CompileSuccessfully(GenerateKernelCode(body).c_str());
756   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
757   EXPECT_THAT(getDiagnosticString(),
758               HasSubstr("Expected int scalar as input: ConvertUToPtr"));
759 }
760 
TEST_F(ValidateConversion,ConvertUToPtrNotIntScalar)761 TEST_F(ValidateConversion, ConvertUToPtrNotIntScalar) {
762   const std::string body = R"(
763 %val = OpConvertUToPtr %f32ptr_func %u32vec2_12
764 )";
765 
766   CompileSuccessfully(GenerateKernelCode(body).c_str());
767   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
768   EXPECT_THAT(getDiagnosticString(),
769               HasSubstr("Expected int scalar as input: ConvertUToPtr"));
770 }
771 
TEST_F(ValidateConversion,PtrCastToGenericSuccess)772 TEST_F(ValidateConversion, PtrCastToGenericSuccess) {
773   const std::string body = R"(
774 %ptr_func = OpVariable %f32ptr_func Function
775 %val = OpPtrCastToGeneric %f32ptr_gen %ptr_func
776 )";
777 
778   CompileSuccessfully(GenerateKernelCode(body).c_str());
779   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
780 }
781 
TEST_F(ValidateConversion,PtrCastToGenericWrongResultType)782 TEST_F(ValidateConversion, PtrCastToGenericWrongResultType) {
783   const std::string body = R"(
784 %ptr_func = OpVariable %f32ptr_func Function
785 %val = OpPtrCastToGeneric %f32 %ptr_func
786 )";
787 
788   CompileSuccessfully(GenerateKernelCode(body).c_str());
789   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
790   EXPECT_THAT(
791       getDiagnosticString(),
792       HasSubstr("Expected Result Type to be a pointer: PtrCastToGeneric"));
793 }
794 
TEST_F(ValidateConversion,PtrCastToGenericWrongResultStorageClass)795 TEST_F(ValidateConversion, PtrCastToGenericWrongResultStorageClass) {
796   const std::string body = R"(
797 %ptr_func = OpVariable %f32ptr_func Function
798 %val = OpPtrCastToGeneric %f32ptr_func %ptr_func
799 )";
800 
801   CompileSuccessfully(GenerateKernelCode(body).c_str());
802   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
803   EXPECT_THAT(getDiagnosticString(),
804               HasSubstr("Expected Result Type to have storage class Generic: "
805                         "PtrCastToGeneric"));
806 }
807 
TEST_F(ValidateConversion,PtrCastToGenericWrongInputType)808 TEST_F(ValidateConversion, PtrCastToGenericWrongInputType) {
809   const std::string body = R"(
810 %ptr_func = OpVariable %f32ptr_func Function
811 %val = OpPtrCastToGeneric %f32ptr_gen %f32
812 )";
813 
814   CompileSuccessfully(GenerateKernelCode(body).c_str());
815   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
816   EXPECT_THAT(getDiagnosticString(),
817               HasSubstr("Operand '4[%float]' cannot be a "
818                         "type"));
819 }
820 
TEST_F(ValidateConversion,PtrCastToGenericWrongInputStorageClass)821 TEST_F(ValidateConversion, PtrCastToGenericWrongInputStorageClass) {
822   const std::string body = R"(
823 %val = OpPtrCastToGeneric %f32ptr_gen %f32inp
824 )";
825 
826   CompileSuccessfully(GenerateKernelCode(body).c_str());
827   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
828   EXPECT_THAT(getDiagnosticString(),
829               HasSubstr("Expected input to have storage class Workgroup, "
830                         "CrossWorkgroup or Function: PtrCastToGeneric"));
831 }
832 
TEST_F(ValidateConversion,PtrCastToGenericPointToDifferentType)833 TEST_F(ValidateConversion, PtrCastToGenericPointToDifferentType) {
834   const std::string body = R"(
835 %ptr_func = OpVariable %u32ptr_func Function
836 %val = OpPtrCastToGeneric %f32ptr_gen %ptr_func
837 )";
838 
839   CompileSuccessfully(GenerateKernelCode(body).c_str());
840   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
841   EXPECT_THAT(
842       getDiagnosticString(),
843       HasSubstr("Expected input and Result Type to point to the same type: "
844                 "PtrCastToGeneric"));
845 }
846 
TEST_F(ValidateConversion,GenericCastToPtrSuccess)847 TEST_F(ValidateConversion, GenericCastToPtrSuccess) {
848   const std::string body = R"(
849 %ptr_func = OpVariable %f32ptr_func Function
850 %ptr_gen = OpPtrCastToGeneric %f32ptr_gen %ptr_func
851 %ptr_func2 = OpGenericCastToPtr %f32ptr_func %ptr_gen
852 %ptr_wg = OpGenericCastToPtr %f32ptr_wg %ptr_gen
853 %ptr_cwg = OpGenericCastToPtr %f32ptr_cwg %ptr_gen
854 )";
855 
856   CompileSuccessfully(GenerateKernelCode(body).c_str());
857   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
858 }
859 
TEST_F(ValidateConversion,GenericCastToPtrWrongResultType)860 TEST_F(ValidateConversion, GenericCastToPtrWrongResultType) {
861   const std::string body = R"(
862 %ptr_func = OpVariable %f32ptr_func Function
863 %ptr_gen = OpPtrCastToGeneric %f32ptr_gen %ptr_func
864 %ptr_func2 = OpGenericCastToPtr %f32 %ptr_gen
865 )";
866 
867   CompileSuccessfully(GenerateKernelCode(body).c_str());
868   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
869   EXPECT_THAT(
870       getDiagnosticString(),
871       HasSubstr("Expected Result Type to be a pointer: GenericCastToPtr"));
872 }
873 
TEST_F(ValidateConversion,GenericCastToPtrWrongResultStorageClass)874 TEST_F(ValidateConversion, GenericCastToPtrWrongResultStorageClass) {
875   const std::string body = R"(
876 %ptr_func = OpVariable %f32ptr_func Function
877 %ptr_gen = OpPtrCastToGeneric %f32ptr_gen %ptr_func
878 %ptr_func2 = OpGenericCastToPtr %f32ptr_gen %ptr_gen
879 )";
880 
881   CompileSuccessfully(GenerateKernelCode(body).c_str());
882   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
883   EXPECT_THAT(getDiagnosticString(),
884               HasSubstr("Expected Result Type to have storage class Workgroup, "
885                         "CrossWorkgroup or Function: GenericCastToPtr"));
886 }
887 
TEST_F(ValidateConversion,GenericCastToPtrWrongInputType)888 TEST_F(ValidateConversion, GenericCastToPtrWrongInputType) {
889   const std::string body = R"(
890 %ptr_func = OpVariable %f32ptr_func Function
891 %ptr_gen = OpPtrCastToGeneric %f32ptr_gen %ptr_func
892 %ptr_func2 = OpGenericCastToPtr %f32ptr_func %f32_1
893 )";
894 
895   CompileSuccessfully(GenerateKernelCode(body).c_str());
896   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
897   EXPECT_THAT(getDiagnosticString(),
898               HasSubstr("Expected input to be a pointer: GenericCastToPtr"));
899 }
900 
TEST_F(ValidateConversion,GenericCastToPtrWrongInputStorageClass)901 TEST_F(ValidateConversion, GenericCastToPtrWrongInputStorageClass) {
902   const std::string body = R"(
903 %ptr_func = OpVariable %f32ptr_func Function
904 %ptr_func2 = OpGenericCastToPtr %f32ptr_func %ptr_func
905 )";
906 
907   CompileSuccessfully(GenerateKernelCode(body).c_str());
908   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
909   EXPECT_THAT(getDiagnosticString(),
910               HasSubstr("Expected input to have storage class Generic: "
911                         "GenericCastToPtr"));
912 }
913 
TEST_F(ValidateConversion,GenericCastToPtrPointToDifferentType)914 TEST_F(ValidateConversion, GenericCastToPtrPointToDifferentType) {
915   const std::string body = R"(
916 %ptr_func = OpVariable %f32ptr_func Function
917 %ptr_gen = OpPtrCastToGeneric %f32ptr_gen %ptr_func
918 %ptr_func2 = OpGenericCastToPtr %u32ptr_func %ptr_gen
919 )";
920 
921   CompileSuccessfully(GenerateKernelCode(body).c_str());
922   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
923   EXPECT_THAT(
924       getDiagnosticString(),
925       HasSubstr("Expected input and Result Type to point to the same type: "
926                 "GenericCastToPtr"));
927 }
928 
TEST_F(ValidateConversion,GenericCastToPtrExplicitSuccess)929 TEST_F(ValidateConversion, GenericCastToPtrExplicitSuccess) {
930   const std::string body = R"(
931 %ptr_func = OpVariable %f32ptr_func Function
932 %ptr_gen = OpPtrCastToGeneric %f32ptr_gen %ptr_func
933 %ptr_func2 = OpGenericCastToPtrExplicit %f32ptr_func %ptr_gen Function
934 %ptr_wg = OpGenericCastToPtrExplicit %f32ptr_wg %ptr_gen Workgroup
935 %ptr_cwg = OpGenericCastToPtrExplicit %f32ptr_cwg %ptr_gen CrossWorkgroup
936 )";
937 
938   CompileSuccessfully(GenerateKernelCode(body).c_str());
939   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
940 }
941 
TEST_F(ValidateConversion,GenericCastToPtrExplicitWrongResultType)942 TEST_F(ValidateConversion, GenericCastToPtrExplicitWrongResultType) {
943   const std::string body = R"(
944 %ptr_func = OpVariable %f32ptr_func Function
945 %ptr_gen = OpPtrCastToGeneric %f32ptr_gen %ptr_func
946 %ptr_func2 = OpGenericCastToPtrExplicit %f32 %ptr_gen Function
947 )";
948 
949   CompileSuccessfully(GenerateKernelCode(body).c_str());
950   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
951   EXPECT_THAT(
952       getDiagnosticString(),
953       HasSubstr(
954           "Expected Result Type to be a pointer: GenericCastToPtrExplicit"));
955 }
956 
TEST_F(ValidateConversion,GenericCastToPtrExplicitResultStorageClassDiffers)957 TEST_F(ValidateConversion, GenericCastToPtrExplicitResultStorageClassDiffers) {
958   const std::string body = R"(
959 %ptr_func = OpVariable %f32ptr_func Function
960 %ptr_gen = OpPtrCastToGeneric %f32ptr_gen %ptr_func
961 %ptr_func2 = OpGenericCastToPtrExplicit %f32ptr_func %ptr_gen Workgroup
962 )";
963 
964   CompileSuccessfully(GenerateKernelCode(body).c_str());
965   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
966   EXPECT_THAT(getDiagnosticString(),
967               HasSubstr("Expected Result Type to be of target storage class: "
968                         "GenericCastToPtrExplicit"));
969 }
970 
TEST_F(ValidateConversion,GenericCastToPtrExplicitWrongResultStorageClass)971 TEST_F(ValidateConversion, GenericCastToPtrExplicitWrongResultStorageClass) {
972   const std::string body = R"(
973 %ptr_func = OpVariable %f32ptr_func Function
974 %ptr_gen = OpPtrCastToGeneric %f32ptr_gen %ptr_func
975 %ptr_func2 = OpGenericCastToPtrExplicit %f32ptr_gen %ptr_gen Generic
976 )";
977 
978   CompileSuccessfully(GenerateKernelCode(body).c_str());
979   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
980   EXPECT_THAT(
981       getDiagnosticString(),
982       HasSubstr("Expected target storage class to be Workgroup, "
983                 "CrossWorkgroup or Function: GenericCastToPtrExplicit"));
984 }
985 
TEST_F(ValidateConversion,GenericCastToPtrExplicitWrongInputType)986 TEST_F(ValidateConversion, GenericCastToPtrExplicitWrongInputType) {
987   const std::string body = R"(
988 %ptr_func = OpVariable %f32ptr_func Function
989 %ptr_gen = OpPtrCastToGeneric %f32ptr_gen %ptr_func
990 %ptr_func2 = OpGenericCastToPtrExplicit %f32ptr_func %f32_1 Function
991 )";
992 
993   CompileSuccessfully(GenerateKernelCode(body).c_str());
994   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
995   EXPECT_THAT(
996       getDiagnosticString(),
997       HasSubstr("Expected input to be a pointer: GenericCastToPtrExplicit"));
998 }
999 
TEST_F(ValidateConversion,GenericCastToPtrExplicitWrongInputStorageClass)1000 TEST_F(ValidateConversion, GenericCastToPtrExplicitWrongInputStorageClass) {
1001   const std::string body = R"(
1002 %ptr_func = OpVariable %f32ptr_func Function
1003 %ptr_func2 = OpGenericCastToPtrExplicit %f32ptr_func %ptr_func Function
1004 )";
1005 
1006   CompileSuccessfully(GenerateKernelCode(body).c_str());
1007   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1008   EXPECT_THAT(getDiagnosticString(),
1009               HasSubstr("Expected input to have storage class Generic: "
1010                         "GenericCastToPtrExplicit"));
1011 }
1012 
TEST_F(ValidateConversion,GenericCastToPtrExplicitPointToDifferentType)1013 TEST_F(ValidateConversion, GenericCastToPtrExplicitPointToDifferentType) {
1014   const std::string body = R"(
1015 %ptr_func = OpVariable %f32ptr_func Function
1016 %ptr_gen = OpPtrCastToGeneric %f32ptr_gen %ptr_func
1017 %ptr_func2 = OpGenericCastToPtrExplicit %u32ptr_func %ptr_gen Function
1018 )";
1019 
1020   CompileSuccessfully(GenerateKernelCode(body).c_str());
1021   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1022   EXPECT_THAT(
1023       getDiagnosticString(),
1024       HasSubstr("Expected input and Result Type to point to the same type: "
1025                 "GenericCastToPtrExplicit"));
1026 }
1027 
TEST_F(ValidateConversion,CoopMatConversionSuccess)1028 TEST_F(ValidateConversion, CoopMatConversionSuccess) {
1029   const std::string body =
1030       R"(
1031 OpCapability Shader
1032 OpCapability Float16
1033 OpCapability Int16
1034 OpCapability CooperativeMatrixNV
1035 OpExtension "SPV_NV_cooperative_matrix"
1036 OpMemoryModel Logical GLSL450
1037 OpEntryPoint GLCompute %main "main"
1038 %void = OpTypeVoid
1039 %func = OpTypeFunction %void
1040 %bool = OpTypeBool
1041 %f16 = OpTypeFloat 16
1042 %f32 = OpTypeFloat 32
1043 %u16 = OpTypeInt 16 0
1044 %u32 = OpTypeInt 32 0
1045 %s16 = OpTypeInt 16 1
1046 %s32 = OpTypeInt 32 1
1047 
1048 %u32_8 = OpConstant %u32 8
1049 %subgroup = OpConstant %u32 3
1050 
1051 %f16mat = OpTypeCooperativeMatrixNV %f16 %subgroup %u32_8 %u32_8
1052 %f32mat = OpTypeCooperativeMatrixNV %f32 %subgroup %u32_8 %u32_8
1053 %u16mat = OpTypeCooperativeMatrixNV %u16 %subgroup %u32_8 %u32_8
1054 %u32mat = OpTypeCooperativeMatrixNV %u32 %subgroup %u32_8 %u32_8
1055 %s16mat = OpTypeCooperativeMatrixNV %s16 %subgroup %u32_8 %u32_8
1056 %s32mat = OpTypeCooperativeMatrixNV %s32 %subgroup %u32_8 %u32_8
1057 
1058 %f16_1 = OpConstant %f16 1
1059 %f32_1 = OpConstant %f32 1
1060 %u16_1 = OpConstant %u16 1
1061 %u32_1 = OpConstant %u32 1
1062 %s16_1 = OpConstant %s16 1
1063 %s32_1 = OpConstant %s32 1
1064 
1065 %f16mat_1 = OpConstantComposite %f16mat %f16_1
1066 %f32mat_1 = OpConstantComposite %f32mat %f32_1
1067 %u16mat_1 = OpConstantComposite %u16mat %u16_1
1068 %u32mat_1 = OpConstantComposite %u32mat %u32_1
1069 %s16mat_1 = OpConstantComposite %s16mat %s16_1
1070 %s32mat_1 = OpConstantComposite %s32mat %s32_1
1071 
1072 %main = OpFunction %void None %func
1073 %main_entry = OpLabel
1074 
1075 %val11 = OpConvertFToU %u16mat %f16mat_1
1076 %val12 = OpConvertFToU %u32mat %f16mat_1
1077 %val13 = OpConvertFToS %s16mat %f16mat_1
1078 %val14 = OpConvertFToS %s32mat %f16mat_1
1079 %val15 = OpFConvert %f32mat %f16mat_1
1080 
1081 %val21 = OpConvertFToU %u16mat %f32mat_1
1082 %val22 = OpConvertFToU %u32mat %f32mat_1
1083 %val23 = OpConvertFToS %s16mat %f32mat_1
1084 %val24 = OpConvertFToS %s32mat %f32mat_1
1085 %val25 = OpFConvert %f16mat %f32mat_1
1086 
1087 %val31 = OpConvertUToF %f16mat %u16mat_1
1088 %val32 = OpConvertUToF %f32mat %u16mat_1
1089 %val33 = OpUConvert %u32mat %u16mat_1
1090 %val34 = OpSConvert %s32mat %u16mat_1
1091 
1092 %val41 = OpConvertSToF %f16mat %s16mat_1
1093 %val42 = OpConvertSToF %f32mat %s16mat_1
1094 %val43 = OpUConvert %u32mat %s16mat_1
1095 %val44 = OpSConvert %s32mat %s16mat_1
1096 
1097 OpReturn
1098 OpFunctionEnd)";
1099 
1100   CompileSuccessfully(body.c_str());
1101   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1102 }
1103 
TEST_F(ValidateConversion,CoopMatConversionShapesMismatchFail)1104 TEST_F(ValidateConversion, CoopMatConversionShapesMismatchFail) {
1105   const std::string body =
1106       R"(
1107 OpCapability Shader
1108 OpCapability Float16
1109 OpCapability Int16
1110 OpCapability CooperativeMatrixNV
1111 OpExtension "SPV_NV_cooperative_matrix"
1112 OpMemoryModel Logical GLSL450
1113 OpEntryPoint GLCompute %main "main"
1114 %void = OpTypeVoid
1115 %func = OpTypeFunction %void
1116 %bool = OpTypeBool
1117 %f16 = OpTypeFloat 16
1118 %f32 = OpTypeFloat 32
1119 %u16 = OpTypeInt 16 0
1120 %u32 = OpTypeInt 32 0
1121 %s16 = OpTypeInt 16 1
1122 %s32 = OpTypeInt 32 1
1123 
1124 %u32_8 = OpConstant %u32 8
1125 %u32_4 = OpConstant %u32 4
1126 %subgroup = OpConstant %u32 3
1127 
1128 %f16mat = OpTypeCooperativeMatrixNV %f16 %subgroup %u32_8 %u32_8
1129 %f32mat = OpTypeCooperativeMatrixNV %f32 %subgroup %u32_4 %u32_4
1130 
1131 %f16_1 = OpConstant %f16 1
1132 
1133 %f16mat_1 = OpConstantComposite %f16mat %f16_1
1134 
1135 %main = OpFunction %void None %func
1136 %main_entry = OpLabel
1137 
1138 %val15 = OpFConvert %f32mat %f16mat_1
1139 
1140 OpReturn
1141 OpFunctionEnd)";
1142 
1143   CompileSuccessfully(body.c_str());
1144   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1145   EXPECT_THAT(
1146       getDiagnosticString(),
1147       HasSubstr(
1148           "Expected rows of Matrix type and Result Type to be identical"));
1149 }
1150 
TEST_F(ValidateConversion,CoopMatConversionShapesMismatchPass)1151 TEST_F(ValidateConversion, CoopMatConversionShapesMismatchPass) {
1152   const std::string body = R"(
1153 OpCapability Shader
1154 OpCapability Float16
1155 OpCapability Int16
1156 OpCapability CooperativeMatrixNV
1157 OpExtension "SPV_NV_cooperative_matrix"
1158 OpMemoryModel Logical GLSL450
1159 OpEntryPoint GLCompute %main "main"
1160 %void = OpTypeVoid
1161 %func = OpTypeFunction %void
1162 %bool = OpTypeBool
1163 %f16 = OpTypeFloat 16
1164 %f32 = OpTypeFloat 32
1165 %u16 = OpTypeInt 16 0
1166 %u32 = OpTypeInt 32 0
1167 %s16 = OpTypeInt 16 1
1168 %s32 = OpTypeInt 32 1
1169 
1170 %u32_8 = OpConstant %u32 8
1171 %u32_4 = OpSpecConstant %u32 4
1172 %subgroup = OpConstant %u32 3
1173 
1174 %f16mat = OpTypeCooperativeMatrixNV %f16 %subgroup %u32_8 %u32_8
1175 %f32mat = OpTypeCooperativeMatrixNV %f32 %subgroup %u32_4 %u32_4
1176 
1177 %f16_1 = OpConstant %f16 1
1178 
1179 %f16mat_1 = OpConstantComposite %f16mat %f16_1
1180 
1181 %main = OpFunction %void None %func
1182 %main_entry = OpLabel
1183 
1184 %val15 = OpFConvert %f32mat %f16mat_1
1185 
1186 OpReturn
1187 OpFunctionEnd)";
1188 
1189   CompileSuccessfully(body.c_str());
1190   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1191 }
1192 
TEST_F(ValidateConversion,CoopMatKHRConversionSuccess)1193 TEST_F(ValidateConversion, CoopMatKHRConversionSuccess) {
1194   const std::string body = R"(
1195 OpCapability Shader
1196 OpCapability Float16
1197 OpCapability Int16
1198 OpCapability CooperativeMatrixKHR
1199 OpExtension "SPV_KHR_cooperative_matrix"
1200 OpExtension "SPV_KHR_vulkan_memory_model"
1201 OpMemoryModel Logical GLSL450
1202 OpEntryPoint GLCompute %main "main"
1203 %void = OpTypeVoid
1204 %func = OpTypeFunction %void
1205 %bool = OpTypeBool
1206 %f16 = OpTypeFloat 16
1207 %f32 = OpTypeFloat 32
1208 %u16 = OpTypeInt 16 0
1209 %u32 = OpTypeInt 32 0
1210 %s16 = OpTypeInt 16 1
1211 %s32 = OpTypeInt 32 1
1212 
1213 %u32_8 = OpConstant %u32 8
1214 %use_A = OpConstant %u32 0
1215 %subgroup = OpConstant %u32 3
1216 
1217 %f16mat = OpTypeCooperativeMatrixKHR %f16 %subgroup %u32_8 %u32_8 %use_A
1218 %f32mat = OpTypeCooperativeMatrixKHR %f32 %subgroup %u32_8 %u32_8 %use_A
1219 %u16mat = OpTypeCooperativeMatrixKHR %u16 %subgroup %u32_8 %u32_8 %use_A
1220 %u32mat = OpTypeCooperativeMatrixKHR %u32 %subgroup %u32_8 %u32_8 %use_A
1221 %s16mat = OpTypeCooperativeMatrixKHR %s16 %subgroup %u32_8 %u32_8 %use_A
1222 %s32mat = OpTypeCooperativeMatrixKHR %s32 %subgroup %u32_8 %u32_8 %use_A
1223 
1224 %f16_1 = OpConstant %f16 1
1225 %f32_1 = OpConstant %f32 1
1226 %u16_1 = OpConstant %u16 1
1227 %u32_1 = OpConstant %u32 1
1228 %s16_1 = OpConstant %s16 1
1229 %s32_1 = OpConstant %s32 1
1230 
1231 %f16mat_1 = OpConstantComposite %f16mat %f16_1
1232 %f32mat_1 = OpConstantComposite %f32mat %f32_1
1233 %u16mat_1 = OpConstantComposite %u16mat %u16_1
1234 %u32mat_1 = OpConstantComposite %u32mat %u32_1
1235 %s16mat_1 = OpConstantComposite %s16mat %s16_1
1236 %s32mat_1 = OpConstantComposite %s32mat %s32_1
1237 
1238 %main = OpFunction %void None %func
1239 %main_entry = OpLabel
1240 
1241 %val11 = OpConvertFToU %u16mat %f16mat_1
1242 %val12 = OpConvertFToU %u32mat %f16mat_1
1243 %val13 = OpConvertFToS %s16mat %f16mat_1
1244 %val14 = OpConvertFToS %s32mat %f16mat_1
1245 %val15 = OpFConvert %f32mat %f16mat_1
1246 
1247 %val21 = OpConvertFToU %u16mat %f32mat_1
1248 %val22 = OpConvertFToU %u32mat %f32mat_1
1249 %val23 = OpConvertFToS %s16mat %f32mat_1
1250 %val24 = OpConvertFToS %s32mat %f32mat_1
1251 %val25 = OpFConvert %f16mat %f32mat_1
1252 
1253 %val31 = OpConvertUToF %f16mat %u16mat_1
1254 %val32 = OpConvertUToF %f32mat %u16mat_1
1255 %val33 = OpUConvert %u32mat %u16mat_1
1256 %val34 = OpSConvert %s32mat %u16mat_1
1257 
1258 %val41 = OpConvertSToF %f16mat %s16mat_1
1259 %val42 = OpConvertSToF %f32mat %s16mat_1
1260 %val43 = OpUConvert %u32mat %s16mat_1
1261 %val44 = OpSConvert %s32mat %s16mat_1
1262 
1263 OpReturn
1264 OpFunctionEnd)";
1265 
1266   CompileSuccessfully(body.c_str());
1267   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1268 }
1269 
TEST_F(ValidateConversion,CoopMatKHRConversionUseMismatchFail)1270 TEST_F(ValidateConversion, CoopMatKHRConversionUseMismatchFail) {
1271   const std::string body = R"(
1272 OpCapability Shader
1273 OpCapability Float16
1274 OpCapability Int16
1275 OpCapability CooperativeMatrixKHR
1276 OpExtension "SPV_KHR_cooperative_matrix"
1277 OpExtension "SPV_KHR_vulkan_memory_model"
1278 OpMemoryModel Logical GLSL450
1279 OpEntryPoint GLCompute %main "main"
1280 %void = OpTypeVoid
1281 %func = OpTypeFunction %void
1282 %bool = OpTypeBool
1283 %f16 = OpTypeFloat 16
1284 %f32 = OpTypeFloat 32
1285 %u16 = OpTypeInt 16 0
1286 %u32 = OpTypeInt 32 0
1287 %s16 = OpTypeInt 16 1
1288 %s32 = OpTypeInt 32 1
1289 
1290 %u32_8 = OpConstant %u32 8
1291 %u32_4 = OpConstant %u32 4
1292 %subgroup = OpConstant %u32 3
1293 %use_A = OpConstant %u32 0
1294 %use_B = OpConstant %u32 1
1295 
1296 %f16mat = OpTypeCooperativeMatrixKHR %f16 %subgroup %u32_8 %u32_8 %use_A
1297 %f32mat = OpTypeCooperativeMatrixKHR %f32 %subgroup %u32_8 %u32_8 %use_B
1298 
1299 %f16_1 = OpConstant %f16 1
1300 
1301 %f16mat_1 = OpConstantComposite %f16mat %f16_1
1302 
1303 %main = OpFunction %void None %func
1304 %main_entry = OpLabel
1305 
1306 %val1 = OpFConvert %f32mat %f16mat_1
1307 
1308 OpReturn
1309 OpFunctionEnd)";
1310 
1311   CompileSuccessfully(body.c_str());
1312   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1313   EXPECT_THAT(
1314       getDiagnosticString(),
1315       HasSubstr("Expected Use of Matrix type and Result Type to be identical"));
1316 }
1317 
TEST_F(ValidateConversion,CoopMatKHRConversionScopeMismatchFail)1318 TEST_F(ValidateConversion, CoopMatKHRConversionScopeMismatchFail) {
1319   const std::string body = R"(
1320 OpCapability Shader
1321 OpCapability Float16
1322 OpCapability Int16
1323 OpCapability CooperativeMatrixKHR
1324 OpExtension "SPV_KHR_cooperative_matrix"
1325 OpExtension "SPV_KHR_vulkan_memory_model"
1326 OpMemoryModel Logical GLSL450
1327 OpEntryPoint GLCompute %main "main"
1328 %void = OpTypeVoid
1329 %func = OpTypeFunction %void
1330 %bool = OpTypeBool
1331 %f16 = OpTypeFloat 16
1332 %f32 = OpTypeFloat 32
1333 %u16 = OpTypeInt 16 0
1334 %u32 = OpTypeInt 32 0
1335 %s16 = OpTypeInt 16 1
1336 %s32 = OpTypeInt 32 1
1337 
1338 %u32_8 = OpConstant %u32 8
1339 %u32_4 = OpConstant %u32 4
1340 %subgroup = OpConstant %u32 3
1341 %workgroup = OpConstant %u32 2
1342 %use_A = OpConstant %u32 0
1343 
1344 %f16mat = OpTypeCooperativeMatrixKHR %f16 %subgroup %u32_8 %u32_8 %use_A
1345 %f32mat = OpTypeCooperativeMatrixKHR %f32 %workgroup %u32_8 %u32_8 %use_A
1346 
1347 %f16_1 = OpConstant %f16 1
1348 
1349 %f16mat_1 = OpConstantComposite %f16mat %f16_1
1350 
1351 %main = OpFunction %void None %func
1352 %main_entry = OpLabel
1353 
1354 %val1 = OpFConvert %f32mat %f16mat_1
1355 
1356 OpReturn
1357 OpFunctionEnd)";
1358 
1359   CompileSuccessfully(body.c_str());
1360   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1361   EXPECT_THAT(
1362       getDiagnosticString(),
1363       HasSubstr("Expected scopes of Matrix and Result Type to be identical"));
1364 }
1365 
TEST_F(ValidateConversion,BitcastSuccess)1366 TEST_F(ValidateConversion, BitcastSuccess) {
1367   const std::string body = R"(
1368 %ptr = OpVariable %f32ptr_func Function
1369 %val1 = OpBitcast %u32 %ptr
1370 %val2 = OpBitcast %u64 %ptr
1371 %val3 = OpBitcast %f32ptr_func %u32_1
1372 %val4 = OpBitcast %f32ptr_wg %u64_1
1373 %val5 = OpBitcast %f32 %u32_1
1374 %val6 = OpBitcast %f32vec2 %u32vec2_12
1375 %val7 = OpBitcast %f32vec2 %u64_1
1376 %val8 = OpBitcast %f64 %u32vec2_12
1377 %val9 = OpBitcast %f32vec4 %f64vec2_12
1378 )";
1379 
1380   CompileSuccessfully(GenerateKernelCode(body).c_str());
1381   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1382 }
1383 
TEST_F(ValidateConversion,BitcastSuccessSPV1p5)1384 TEST_F(ValidateConversion, BitcastSuccessSPV1p5) {
1385   const std::string body = R"(
1386 %ptr = OpVariable %f32ptr_func Function
1387 %val1 = OpBitcast %u32 %ptr
1388 %val2 = OpBitcast %u64 %ptr
1389 %val3 = OpBitcast %f32ptr_func %u32_1
1390 %val4 = OpBitcast %f32ptr_wg %u64_1
1391 %val5 = OpBitcast %f32 %u32_1
1392 %val6 = OpBitcast %f32vec2 %u32vec2_12
1393 %val7 = OpBitcast %f32vec2 %u64_1
1394 %val8 = OpBitcast %f64 %u32vec2_12
1395 %val9 = OpBitcast %f32vec4 %f64vec2_12
1396 %val10 = OpBitcast %u32ptr_func %u32vec2_01
1397 %val11 = OpBitcast %u32vec2 %ptr
1398 )";
1399 
1400   CompileSuccessfully(GenerateKernelCode(body).c_str(), SPV_ENV_UNIVERSAL_1_5);
1401   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
1402 }
1403 
TEST_F(ValidateConversion,BitcastSuccessPhysicalStorageBufferKHR)1404 TEST_F(ValidateConversion, BitcastSuccessPhysicalStorageBufferKHR) {
1405   const std::string body = R"(
1406 %ptr = OpVariable %f32ptr_func Function
1407 %val1 = OpBitcast %u32 %ptr
1408 %val2 = OpBitcast %u64 %ptr
1409 %val3 = OpBitcast %f32ptr_func %u32_1
1410 %val4 = OpBitcast %f32ptr_wg %u64_1
1411 %val5 = OpBitcast %f32 %u32_1
1412 %val6 = OpBitcast %f32vec2 %u32vec2_12
1413 %val7 = OpBitcast %f32vec2 %u64_1
1414 %val8 = OpBitcast %f64 %u32vec2_12
1415 %val9 = OpBitcast %f32vec4 %f64vec2_12
1416 %val10 = OpBitcast %u32ptr_func %u32vec2_01
1417 %val11 = OpBitcast %u32vec2 %ptr
1418 )";
1419 
1420   CompileSuccessfully(
1421       GenerateKernelCode(body,
1422                          "\nOpExtension \"SPV_KHR_physical_storage_buffer\"")
1423           .c_str());
1424   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1425 }
1426 
TEST_F(ValidateConversion,BitcastInputHasNoType)1427 TEST_F(ValidateConversion, BitcastInputHasNoType) {
1428   const std::string body = R"(
1429 %val = OpBitcast %u32 %f32
1430 )";
1431 
1432   CompileSuccessfully(GenerateKernelCode(body).c_str());
1433   ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1434   EXPECT_THAT(getDiagnosticString(),
1435               HasSubstr("Operand '4[%float]' cannot be a "
1436                         "type"));
1437 }
1438 
TEST_F(ValidateConversion,BitcastWrongResultType)1439 TEST_F(ValidateConversion, BitcastWrongResultType) {
1440   const std::string body = R"(
1441 %val = OpBitcast %bool %f32_1
1442 )";
1443 
1444   CompileSuccessfully(GenerateKernelCode(body).c_str());
1445   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1446   EXPECT_THAT(
1447       getDiagnosticString(),
1448       HasSubstr("Expected Result Type to be a pointer or int or float vector "
1449                 "or scalar type: Bitcast"));
1450 }
1451 
TEST_F(ValidateConversion,BitcastWrongInputType)1452 TEST_F(ValidateConversion, BitcastWrongInputType) {
1453   const std::string body = R"(
1454 %val = OpBitcast %u32 %true
1455 )";
1456 
1457   CompileSuccessfully(GenerateKernelCode(body).c_str());
1458   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1459   EXPECT_THAT(getDiagnosticString(),
1460               HasSubstr("Expected input to be a pointer or int or float vector "
1461                         "or scalar: Bitcast"));
1462 }
1463 
TEST_F(ValidateConversion,BitcastPtrWrongInputType)1464 TEST_F(ValidateConversion, BitcastPtrWrongInputType) {
1465   const std::string body = R"(
1466 %val = OpBitcast %u32ptr_func %f32_1
1467 )";
1468 
1469   CompileSuccessfully(GenerateKernelCode(body).c_str());
1470   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1471   EXPECT_THAT(getDiagnosticString(),
1472               HasSubstr("Expected input to be a pointer or int scalar if "
1473                         "Result Type is pointer: Bitcast"));
1474 }
1475 
TEST_F(ValidateConversion,BitcastPtrWrongInputTypeSPV1p5)1476 TEST_F(ValidateConversion, BitcastPtrWrongInputTypeSPV1p5) {
1477   const std::string body = R"(
1478 %val = OpBitcast %u32ptr_func %f32_1
1479 )";
1480 
1481   CompileSuccessfully(GenerateKernelCode(body).c_str(), SPV_ENV_UNIVERSAL_1_5);
1482   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
1483             ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
1484   EXPECT_THAT(getDiagnosticString(),
1485               HasSubstr("Expected input to be a pointer, int scalar or 32-bit "
1486                         "int vector if Result Type is pointer: Bitcast"));
1487 }
1488 
TEST_F(ValidateConversion,BitcastPtrWrongInputTypePhysicalStorageBufferKHR)1489 TEST_F(ValidateConversion, BitcastPtrWrongInputTypePhysicalStorageBufferKHR) {
1490   const std::string body = R"(
1491 %val = OpBitcast %u32ptr_func %f32_1
1492 )";
1493 
1494   CompileSuccessfully(
1495       GenerateKernelCode(body,
1496                          "\nOpExtension \"SPV_KHR_physical_storage_buffer\"")
1497           .c_str());
1498   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1499   EXPECT_THAT(getDiagnosticString(),
1500               HasSubstr("Expected input to be a pointer, int scalar or 32-bit "
1501                         "int vector if Result Type is pointer: Bitcast"));
1502 }
1503 
TEST_F(ValidateConversion,BitcastPtrWrongInputTypeIntVectorSPV1p5)1504 TEST_F(ValidateConversion, BitcastPtrWrongInputTypeIntVectorSPV1p5) {
1505   const std::string body = R"(
1506 %val = OpBitcast %u32ptr_func %u64vec2_01
1507 )";
1508 
1509   CompileSuccessfully(GenerateKernelCode(body).c_str(), SPV_ENV_UNIVERSAL_1_5);
1510   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
1511             ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
1512   EXPECT_THAT(getDiagnosticString(),
1513               HasSubstr("Expected input to be a pointer, int scalar or 32-bit "
1514                         "int vector if Result Type is pointer: Bitcast"));
1515 }
1516 
TEST_F(ValidateConversion,BitcastPtrWrongInputTypeIntVectorPhysicalStorageBufferKHR)1517 TEST_F(ValidateConversion,
1518        BitcastPtrWrongInputTypeIntVectorPhysicalStorageBufferKHR) {
1519   const std::string body = R"(
1520 %val = OpBitcast %u32ptr_func %u64vec2_01
1521 )";
1522 
1523   CompileSuccessfully(
1524       GenerateKernelCode(body,
1525                          "\nOpExtension \"SPV_KHR_physical_storage_buffer\"")
1526           .c_str());
1527   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1528   EXPECT_THAT(getDiagnosticString(),
1529               HasSubstr("Expected input to be a pointer, int scalar or 32-bit "
1530                         "int vector if Result Type is pointer: Bitcast"));
1531 }
1532 
TEST_F(ValidateConversion,BitcastPtrWrongResultType)1533 TEST_F(ValidateConversion, BitcastPtrWrongResultType) {
1534   const std::string body = R"(
1535 %val = OpBitcast %f32 %f32inp
1536 )";
1537 
1538   CompileSuccessfully(GenerateKernelCode(body).c_str());
1539   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1540   EXPECT_THAT(getDiagnosticString(),
1541               HasSubstr("Pointer can only be converted to another pointer or "
1542                         "int scalar: Bitcast"));
1543 }
1544 
TEST_F(ValidateConversion,BitcastPtrWrongResultTypeSPV1p5)1545 TEST_F(ValidateConversion, BitcastPtrWrongResultTypeSPV1p5) {
1546   const std::string body = R"(
1547 %val = OpBitcast %f32 %f32inp
1548 )";
1549 
1550   CompileSuccessfully(GenerateKernelCode(body).c_str(), SPV_ENV_UNIVERSAL_1_5);
1551   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
1552             ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
1553   EXPECT_THAT(getDiagnosticString(),
1554               HasSubstr("Pointer can only be converted to another pointer, int "
1555                         "scalar or 32-bit int vector: Bitcast"));
1556 }
1557 
TEST_F(ValidateConversion,BitcastPtrWrongResultTypePhysicalStorageBufferKHR)1558 TEST_F(ValidateConversion, BitcastPtrWrongResultTypePhysicalStorageBufferKHR) {
1559   const std::string body = R"(
1560 %val = OpBitcast %f32 %f32inp
1561 )";
1562 
1563   CompileSuccessfully(
1564       GenerateKernelCode(body,
1565                          "\nOpExtension \"SPV_KHR_physical_storage_buffer\"")
1566           .c_str());
1567   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1568   EXPECT_THAT(getDiagnosticString(),
1569               HasSubstr("Pointer can only be converted to another pointer, int "
1570                         "scalar or 32-bit int vector: Bitcast"));
1571 }
1572 
TEST_F(ValidateConversion,BitcastPtrWrongResultTypeIntVectorSPV1p5)1573 TEST_F(ValidateConversion, BitcastPtrWrongResultTypeIntVectorSPV1p5) {
1574   const std::string body = R"(
1575 %val = OpBitcast %u64vec2 %f32inp
1576 )";
1577 
1578   CompileSuccessfully(GenerateKernelCode(body).c_str(), SPV_ENV_UNIVERSAL_1_5);
1579   ASSERT_EQ(SPV_ERROR_INVALID_DATA,
1580             ValidateInstructions(SPV_ENV_UNIVERSAL_1_5));
1581   EXPECT_THAT(getDiagnosticString(),
1582               HasSubstr("Pointer can only be converted to another pointer, int "
1583                         "scalar or 32-bit int vector: Bitcast"));
1584 }
1585 
TEST_F(ValidateConversion,BitcastPtrWrongResultTypeIntVectorPhysicalStorageBufferKHR)1586 TEST_F(ValidateConversion,
1587        BitcastPtrWrongResultTypeIntVectorPhysicalStorageBufferKHR) {
1588   const std::string body = R"(
1589 %val = OpBitcast %u64vec2 %f32inp
1590 )";
1591 
1592   CompileSuccessfully(
1593       GenerateKernelCode(body,
1594                          "\nOpExtension \"SPV_KHR_physical_storage_buffer\"")
1595           .c_str());
1596   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1597   EXPECT_THAT(getDiagnosticString(),
1598               HasSubstr("Pointer can only be converted to another pointer, int "
1599                         "scalar or 32-bit int vector: Bitcast"));
1600 }
1601 
TEST_F(ValidateConversion,BitcastDifferentTotalBitWidth)1602 TEST_F(ValidateConversion, BitcastDifferentTotalBitWidth) {
1603   const std::string body = R"(
1604 %val = OpBitcast %f32 %u64_1
1605 )";
1606 
1607   CompileSuccessfully(GenerateKernelCode(body).c_str());
1608   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1609   EXPECT_THAT(
1610       getDiagnosticString(),
1611       HasSubstr(
1612           "Expected input to have the same total bit width as Result Type: "
1613           "Bitcast"));
1614 }
1615 
TEST_F(ValidateConversion,ConvertUToPtrInputIsAType)1616 TEST_F(ValidateConversion, ConvertUToPtrInputIsAType) {
1617   const std::string spirv = R"(
1618 OpCapability Addresses
1619 OpCapability Shader
1620 OpCapability Linkage
1621 OpMemoryModel Logical GLSL450
1622 %int = OpTypeInt 32 0
1623 %ptr_int = OpTypePointer Function %int
1624 %void = OpTypeVoid
1625 %voidfn = OpTypeFunction %void
1626 %func = OpFunction %void None %voidfn
1627 %entry = OpLabel
1628 %1 = OpConvertUToPtr %ptr_int %int
1629 OpReturn
1630 OpFunctionEnd
1631 )";
1632 
1633   CompileSuccessfully(spirv);
1634   EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1635   EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand '1[%uint]' cannot be a "
1636                                                "type"));
1637 }
1638 
TEST_F(ValidateConversion,ConvertUToPtrPSBSuccess)1639 TEST_F(ValidateConversion, ConvertUToPtrPSBSuccess) {
1640   const std::string body = R"(
1641 OpCapability PhysicalStorageBufferAddresses
1642 OpCapability Int64
1643 OpCapability Shader
1644 OpExtension "SPV_EXT_physical_storage_buffer"
1645 OpMemoryModel PhysicalStorageBuffer64 GLSL450
1646 OpEntryPoint Fragment %main "main"
1647 OpExecutionMode %main OriginUpperLeft
1648 %uint64 = OpTypeInt 64 0
1649 %u64_1 = OpConstant %uint64 1
1650 %ptr = OpTypePointer PhysicalStorageBuffer %uint64
1651 %void = OpTypeVoid
1652 %voidfn = OpTypeFunction %void
1653 %main = OpFunction %void None %voidfn
1654 %entry = OpLabel
1655 %val1 = OpConvertUToPtr %ptr %u64_1
1656 OpReturn
1657 OpFunctionEnd
1658 )";
1659 
1660   CompileSuccessfully(body.c_str());
1661   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1662 }
1663 
TEST_F(ValidateConversion,ConvertUToPtrPSBStorageClass)1664 TEST_F(ValidateConversion, ConvertUToPtrPSBStorageClass) {
1665   const std::string body = R"(
1666 OpCapability PhysicalStorageBufferAddresses
1667 OpCapability Int64
1668 OpCapability Shader
1669 OpExtension "SPV_EXT_physical_storage_buffer"
1670 OpMemoryModel PhysicalStorageBuffer64 GLSL450
1671 OpEntryPoint Fragment %main "main"
1672 OpExecutionMode %main OriginUpperLeft
1673 %uint64 = OpTypeInt 64 0
1674 %u64_1 = OpConstant %uint64 1
1675 %ptr = OpTypePointer Function %uint64
1676 %void = OpTypeVoid
1677 %voidfn = OpTypeFunction %void
1678 %main = OpFunction %void None %voidfn
1679 %entry = OpLabel
1680 %val1 = OpConvertUToPtr %ptr %u64_1
1681 %val2 = OpConvertPtrToU %uint64 %val1
1682 OpReturn
1683 OpFunctionEnd
1684 )";
1685 
1686   CompileSuccessfully(body.c_str());
1687   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1688   EXPECT_THAT(getDiagnosticString(),
1689               HasSubstr("Pointer storage class must be "
1690                         "PhysicalStorageBuffer: ConvertUToPtr"));
1691 }
1692 
TEST_F(ValidateConversion,ConvertUToPtrVulkanWrongWidth)1693 TEST_F(ValidateConversion, ConvertUToPtrVulkanWrongWidth) {
1694   const std::string body = R"(
1695 OpCapability PhysicalStorageBufferAddresses
1696 OpCapability Int64
1697 OpCapability Shader
1698 OpExtension "SPV_EXT_physical_storage_buffer"
1699 OpMemoryModel PhysicalStorageBuffer64 GLSL450
1700 OpEntryPoint Fragment %main "main"
1701 OpExecutionMode %main OriginUpperLeft
1702 %uint32 = OpTypeInt 32 0
1703 %uint64 = OpTypeInt 64 0
1704 %u32_1 = OpConstant %uint32 1
1705 %ptr = OpTypePointer PhysicalStorageBuffer %uint64
1706 %void = OpTypeVoid
1707 %voidfn = OpTypeFunction %void
1708 %main = OpFunction %void None %voidfn
1709 %entry = OpLabel
1710 %val1 = OpConvertUToPtr %ptr %u32_1
1711 OpReturn
1712 OpFunctionEnd
1713 )";
1714 
1715   CompileSuccessfully(body.c_str());
1716   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1717   EXPECT_THAT(getDiagnosticString(),
1718               AnyVUID("VUID-StandaloneSpirv-PhysicalStorageBuffer64-04710"));
1719   EXPECT_THAT(
1720       getDiagnosticString(),
1721       HasSubstr("PhysicalStorageBuffer64 addressing mode requires the input "
1722                 "integer to have a 64-bit width for Vulkan environment."));
1723 }
1724 
TEST_F(ValidateConversion,ConvertPtrToUPSBSuccess)1725 TEST_F(ValidateConversion, ConvertPtrToUPSBSuccess) {
1726   const std::string body = R"(
1727 OpCapability PhysicalStorageBufferAddresses
1728 OpCapability Int64
1729 OpCapability Shader
1730 OpExtension "SPV_EXT_physical_storage_buffer"
1731 OpMemoryModel PhysicalStorageBuffer64 GLSL450
1732 OpEntryPoint Fragment %main "main"
1733 OpExecutionMode %main OriginUpperLeft
1734 OpDecorate %val1 RestrictPointer
1735 %uint64 = OpTypeInt 64 0
1736 %u64_1 = OpConstant %uint64 1
1737 %ptr = OpTypePointer PhysicalStorageBuffer %uint64
1738 %pptr_f = OpTypePointer Function %ptr
1739 %void = OpTypeVoid
1740 %voidfn = OpTypeFunction %void
1741 %main = OpFunction %void None %voidfn
1742 %entry = OpLabel
1743 %val1 = OpVariable %pptr_f Function
1744 %val2 = OpLoad %ptr %val1
1745 %val3 = OpConvertPtrToU %uint64 %val2
1746 OpReturn
1747 OpFunctionEnd
1748 )";
1749 
1750   CompileSuccessfully(body.c_str());
1751   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1752 }
1753 
TEST_F(ValidateConversion,ConvertPtrToUPSBStorageClass)1754 TEST_F(ValidateConversion, ConvertPtrToUPSBStorageClass) {
1755   const std::string body = R"(
1756 OpCapability PhysicalStorageBufferAddresses
1757 OpCapability Int64
1758 OpCapability Shader
1759 OpExtension "SPV_EXT_physical_storage_buffer"
1760 OpMemoryModel PhysicalStorageBuffer64 GLSL450
1761 OpEntryPoint Fragment %main "main"
1762 OpExecutionMode %main OriginUpperLeft
1763 %uint64 = OpTypeInt 64 0
1764 %u64_1 = OpConstant %uint64 1
1765 %ptr = OpTypePointer Function %uint64
1766 %void = OpTypeVoid
1767 %voidfn = OpTypeFunction %void
1768 %main = OpFunction %void None %voidfn
1769 %entry = OpLabel
1770 %val1 = OpVariable %ptr Function
1771 %val2 = OpConvertPtrToU %uint64 %val1
1772 OpReturn
1773 OpFunctionEnd
1774 )";
1775 
1776   CompileSuccessfully(body.c_str());
1777   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1778   EXPECT_THAT(getDiagnosticString(),
1779               HasSubstr("Pointer storage class must be "
1780                         "PhysicalStorageBuffer: ConvertPtrToU"));
1781 }
1782 
TEST_F(ValidateConversion,ConvertPtrToUVulkanWrongWidth)1783 TEST_F(ValidateConversion, ConvertPtrToUVulkanWrongWidth) {
1784   const std::string body = R"(
1785 OpCapability PhysicalStorageBufferAddresses
1786 OpCapability Int64
1787 OpCapability Shader
1788 OpExtension "SPV_EXT_physical_storage_buffer"
1789 OpMemoryModel PhysicalStorageBuffer64 GLSL450
1790 OpEntryPoint Fragment %main "main"
1791 OpExecutionMode %main OriginUpperLeft
1792 OpDecorate %val1 RestrictPointer
1793 %uint32 = OpTypeInt 32 0
1794 %uint64 = OpTypeInt 64 0
1795 %ptr = OpTypePointer PhysicalStorageBuffer %uint64
1796 %pptr_f = OpTypePointer Function %ptr
1797 %void = OpTypeVoid
1798 %voidfn = OpTypeFunction %void
1799 %main = OpFunction %void None %voidfn
1800 %entry = OpLabel
1801 %val1 = OpVariable %pptr_f Function
1802 %val2 = OpLoad %ptr %val1
1803 %val3 = OpConvertPtrToU %uint32 %val2
1804 OpReturn
1805 OpFunctionEnd
1806 )";
1807 
1808   CompileSuccessfully(body.c_str());
1809   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1810   EXPECT_THAT(getDiagnosticString(),
1811               AnyVUID("VUID-StandaloneSpirv-PhysicalStorageBuffer64-04710"));
1812   EXPECT_THAT(
1813       getDiagnosticString(),
1814       HasSubstr("PhysicalStorageBuffer64 addressing mode requires the result "
1815                 "integer type to have a 64-bit width for Vulkan environment."));
1816 }
1817 
TEST_F(ValidateConversion,ConvertUToAccelerationStructureU32Vec2)1818 TEST_F(ValidateConversion, ConvertUToAccelerationStructureU32Vec2) {
1819   const std::string extensions = R"(
1820 OpCapability RayQueryKHR
1821 OpExtension "SPV_KHR_ray_query"
1822 )";
1823   const std::string types = R"(
1824 %u32vec2ptr_func = OpTypePointer Function %u32vec2
1825 %typeAS = OpTypeAccelerationStructureKHR
1826 )";
1827   const std::string body = R"(
1828 %asHandle = OpVariable %u32vec2ptr_func Function
1829 %load = OpLoad %u32vec2 %asHandle
1830 %val = OpConvertUToAccelerationStructureKHR %typeAS %load
1831 )";
1832 
1833   CompileSuccessfully(GenerateShaderCode(body, extensions, "", types).c_str());
1834   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1835 }
1836 
TEST_F(ValidateConversion,ConvertUToAccelerationStructureSuccessU64)1837 TEST_F(ValidateConversion, ConvertUToAccelerationStructureSuccessU64) {
1838   const std::string extensions = R"(
1839 OpCapability RayQueryKHR
1840 OpExtension "SPV_KHR_ray_query"
1841 )";
1842   const std::string types = R"(
1843 %u64_func = OpTypePointer Function %u64
1844 %typeAS = OpTypeAccelerationStructureKHR
1845 )";
1846   const std::string body = R"(
1847 %asHandle = OpVariable %u64_func Function
1848 %load = OpLoad %u64 %asHandle
1849 %val = OpConvertUToAccelerationStructureKHR %typeAS %load
1850 )";
1851 
1852   CompileSuccessfully(GenerateShaderCode(body, extensions, "", types).c_str());
1853   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
1854 }
1855 
TEST_F(ValidateConversion,ConvertUToAccelerationStructureResult)1856 TEST_F(ValidateConversion, ConvertUToAccelerationStructureResult) {
1857   const std::string extensions = R"(
1858 OpCapability RayQueryKHR
1859 OpExtension "SPV_KHR_ray_query"
1860 )";
1861   const std::string types = R"(
1862 %u32vec2ptr_func = OpTypePointer Function %u32vec2
1863 %typeRQ = OpTypeRayQueryKHR
1864 )";
1865   const std::string body = R"(
1866 %asHandle = OpVariable %u32vec2ptr_func Function
1867 %load = OpLoad %u32vec2 %asHandle
1868 %val = OpConvertUToAccelerationStructureKHR %typeRQ %load
1869 )";
1870 
1871   CompileSuccessfully(GenerateShaderCode(body, extensions, "", types).c_str());
1872   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1873   EXPECT_THAT(getDiagnosticString(),
1874               HasSubstr("Expected Result Type to be a Acceleration Structure"));
1875 }
1876 
TEST_F(ValidateConversion,ConvertUToAccelerationStructureU32)1877 TEST_F(ValidateConversion, ConvertUToAccelerationStructureU32) {
1878   const std::string extensions = R"(
1879 OpCapability RayQueryKHR
1880 OpExtension "SPV_KHR_ray_query"
1881 )";
1882   const std::string types = R"(
1883 %u32ptr_func = OpTypePointer Function %u32
1884 %typeAS = OpTypeAccelerationStructureKHR
1885 )";
1886   const std::string body = R"(
1887 %asHandle = OpVariable %u32ptr_func Function
1888 %load = OpLoad %u32 %asHandle
1889 %val = OpConvertUToAccelerationStructureKHR %typeAS %load
1890 )";
1891 
1892   CompileSuccessfully(GenerateShaderCode(body, extensions, "", types).c_str());
1893   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1894   EXPECT_THAT(getDiagnosticString(),
1895               HasSubstr("Expected 64-bit uint scalar or 2-component 32-bit "
1896                         "uint vector as input"));
1897 }
1898 
TEST_F(ValidateConversion,ConvertUToAccelerationStructureS64)1899 TEST_F(ValidateConversion, ConvertUToAccelerationStructureS64) {
1900   const std::string extensions = R"(
1901 OpCapability RayQueryKHR
1902 OpExtension "SPV_KHR_ray_query"
1903 )";
1904   const std::string types = R"(
1905 %s64ptr_func = OpTypePointer Function %s64
1906 %typeAS = OpTypeAccelerationStructureKHR
1907 )";
1908   const std::string body = R"(
1909 %asHandle = OpVariable %s64ptr_func Function
1910 %load = OpLoad %s64 %asHandle
1911 %val = OpConvertUToAccelerationStructureKHR %typeAS %load
1912 )";
1913 
1914   CompileSuccessfully(GenerateShaderCode(body, extensions, "", types).c_str());
1915   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1916   EXPECT_THAT(getDiagnosticString(),
1917               HasSubstr("Expected 64-bit uint scalar or 2-component 32-bit "
1918                         "uint vector as input"));
1919 }
1920 
TEST_F(ValidateConversion,ConvertUToAccelerationStructureS32Vec2)1921 TEST_F(ValidateConversion, ConvertUToAccelerationStructureS32Vec2) {
1922   const std::string extensions = R"(
1923 OpCapability RayQueryKHR
1924 OpExtension "SPV_KHR_ray_query"
1925 )";
1926   const std::string types = R"(
1927 %s32vec2ptr_func = OpTypePointer Function %s32vec2
1928 %typeAS = OpTypeAccelerationStructureKHR
1929 )";
1930   const std::string body = R"(
1931 %asHandle = OpVariable %s32vec2ptr_func Function
1932 %load = OpLoad %s32vec2 %asHandle
1933 %val = OpConvertUToAccelerationStructureKHR %typeAS %load
1934 )";
1935 
1936   CompileSuccessfully(GenerateShaderCode(body, extensions, "", types).c_str());
1937   ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1938   EXPECT_THAT(getDiagnosticString(),
1939               HasSubstr("Expected 64-bit uint scalar or 2-component 32-bit "
1940                         "uint vector as input"));
1941 }
1942 
1943 using ValidateSmallConversions = spvtest::ValidateBase<std::string>;
1944 
GetSmallConversionsCodeGenerator()1945 CodeGenerator GetSmallConversionsCodeGenerator() {
1946   CodeGenerator generator;
1947   generator.capabilities_ = R"(
1948 OpCapability Shader
1949 OpCapability Linkage
1950 OpCapability UniformAndStorageBuffer16BitAccess
1951 OpCapability UniformAndStorageBuffer8BitAccess
1952 )";
1953   generator.extensions_ = R"(
1954 OpExtension "SPV_KHR_16bit_storage"
1955 OpExtension "SPV_KHR_8bit_storage"
1956 )";
1957   generator.memory_model_ = "OpMemoryModel Logical GLSL450\n";
1958   generator.before_types_ = R"(
1959 OpDecorate %char_block Block
1960 OpMemberDecorate %char_block 0 Offset 0
1961 OpDecorate %short_block Block
1962 OpMemberDecorate %short_block 0 Offset 0
1963 OpDecorate %half_block Block
1964 OpMemberDecorate %half_block 0 Offset 0
1965 OpDecorate %int_block Block
1966 OpMemberDecorate %int_block 0 Offset 0
1967 OpDecorate %float_block Block
1968 OpMemberDecorate %float_block 0 Offset 0
1969 )";
1970   generator.types_ = R"(
1971 %void = OpTypeVoid
1972 %int = OpTypeInt 32 0
1973 %int_0 = OpConstant %int 0
1974 %int_1 = OpConstant %int 1
1975 %int2 = OpTypeVector %int 2
1976 %float = OpTypeFloat 32
1977 %float_0 = OpConstant %float 0
1978 %float2 = OpTypeVector %float 2
1979 %char = OpTypeInt 8 0
1980 %char2 = OpTypeVector %char 2
1981 %short = OpTypeInt 16 0
1982 %short2 = OpTypeVector %short 2
1983 %half = OpTypeFloat 16
1984 %half2 = OpTypeVector %half 2
1985 %char_block = OpTypeStruct %char2
1986 %short_block = OpTypeStruct %short2
1987 %half_block = OpTypeStruct %half2
1988 %int_block = OpTypeStruct %int2
1989 %float_block = OpTypeStruct %float2
1990 %ptr_ssbo_char_block = OpTypePointer StorageBuffer %char_block
1991 %ptr_ssbo_char2 = OpTypePointer StorageBuffer %char2
1992 %ptr_ssbo_char = OpTypePointer StorageBuffer %char
1993 %ptr_ssbo_short_block = OpTypePointer StorageBuffer %short_block
1994 %ptr_ssbo_short2 = OpTypePointer StorageBuffer %short2
1995 %ptr_ssbo_short = OpTypePointer StorageBuffer %short
1996 %ptr_ssbo_half_block = OpTypePointer StorageBuffer %half_block
1997 %ptr_ssbo_half2 = OpTypePointer StorageBuffer %half2
1998 %ptr_ssbo_half = OpTypePointer StorageBuffer %half
1999 %ptr_ssbo_int_block = OpTypePointer StorageBuffer %int_block
2000 %ptr_ssbo_int2 = OpTypePointer StorageBuffer %int2
2001 %ptr_ssbo_int = OpTypePointer StorageBuffer %int
2002 %ptr_ssbo_float_block = OpTypePointer StorageBuffer %float_block
2003 %ptr_ssbo_float2 = OpTypePointer StorageBuffer %float2
2004 %ptr_ssbo_float = OpTypePointer StorageBuffer %float
2005 %void_fn = OpTypeFunction %void
2006 %char_var = OpVariable %ptr_ssbo_char_block StorageBuffer
2007 %short_var = OpVariable %ptr_ssbo_short_block StorageBuffer
2008 %half_var = OpVariable %ptr_ssbo_half_block StorageBuffer
2009 %int_var = OpVariable %ptr_ssbo_int_block StorageBuffer
2010 %float_var = OpVariable %ptr_ssbo_float_block StorageBuffer
2011 )";
2012   generator.after_types_ = R"(
2013 %func = OpFunction %void None %void_fn
2014 %entry = OpLabel
2015 %char2_gep = OpAccessChain %ptr_ssbo_char2 %char_var %int_0
2016 %ld_char2 = OpLoad %char2 %char2_gep
2017 %char_gep = OpAccessChain %ptr_ssbo_char %char_var %int_0 %int_0
2018 %ld_char = OpLoad %char %char_gep
2019 %short2_gep = OpAccessChain %ptr_ssbo_short2 %short_var %int_0
2020 %ld_short2 = OpLoad %short2 %short2_gep
2021 %short_gep = OpAccessChain %ptr_ssbo_short %short_var %int_0 %int_0
2022 %ld_short = OpLoad %short %short_gep
2023 %half2_gep = OpAccessChain %ptr_ssbo_half2 %half_var %int_0
2024 %ld_half2 = OpLoad %half2 %half2_gep
2025 %half_gep = OpAccessChain %ptr_ssbo_half %half_var %int_0 %int_0
2026 %ld_half = OpLoad %half %half_gep
2027 %int2_gep = OpAccessChain %ptr_ssbo_int2 %int_var %int_0
2028 %ld_int2 = OpLoad %int2 %int2_gep
2029 %int_gep = OpAccessChain %ptr_ssbo_int %int_var %int_0 %int_0
2030 %ld_int = OpLoad %int %int_gep
2031 %float2_gep = OpAccessChain %ptr_ssbo_float2 %float_var %int_0
2032 %ld_float2 = OpLoad %float2 %float2_gep
2033 %float_gep = OpAccessChain %ptr_ssbo_float %float_var %int_0 %int_0
2034 %ld_float = OpLoad %float %float_gep
2035 )";
2036   generator.add_at_the_end_ = R"(
2037 OpReturn
2038 OpFunctionEnd
2039 )";
2040   return generator;
2041 }
2042 
TEST_P(ValidateSmallConversions,Instruction)2043 TEST_P(ValidateSmallConversions, Instruction) {
2044   CodeGenerator generator = GetSmallConversionsCodeGenerator();
2045   generator.after_types_ += GetParam() + "\n";
2046   CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
2047   EXPECT_EQ(SPV_ERROR_INVALID_DATA,
2048             ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2049   EXPECT_THAT(
2050       getDiagnosticString(),
2051       HasSubstr(
2052           "8- or 16-bit types can only be used with width-only conversions"));
2053 }
2054 
2055 INSTANTIATE_TEST_SUITE_P(SmallConversionInstructions, ValidateSmallConversions,
2056                          Values("%inst = OpConvertFToU %char %ld_float",
2057                                 "%inst = OpConvertFToU %char2 %ld_float2",
2058                                 "%inst = OpConvertFToU %short %ld_float",
2059                                 "%inst = OpConvertFToU %short2 %ld_float2",
2060                                 "%inst = OpConvertFToU %int %ld_half",
2061                                 "%inst = OpConvertFToU %int2 %ld_half2",
2062                                 "%inst = OpConvertFToS %char %ld_float",
2063                                 "%inst = OpConvertFToS %char2 %ld_float2",
2064                                 "%inst = OpConvertFToS %short %ld_float",
2065                                 "%inst = OpConvertFToS %short2 %ld_float2",
2066                                 "%inst = OpConvertFToS %int %ld_half",
2067                                 "%inst = OpConvertFToS %int2 %ld_half2",
2068                                 "%inst = OpConvertSToF %float %ld_char",
2069                                 "%inst = OpConvertSToF %float2 %ld_char2",
2070                                 "%inst = OpConvertSToF %float %ld_short",
2071                                 "%inst = OpConvertSToF %float2 %ld_short2",
2072                                 "%inst = OpConvertSToF %half %ld_int",
2073                                 "%inst = OpConvertSToF %half2 %ld_int2",
2074                                 "%inst = OpConvertUToF %float %ld_char",
2075                                 "%inst = OpConvertUToF %float2 %ld_char2",
2076                                 "%inst = OpConvertUToF %float %ld_short",
2077                                 "%inst = OpConvertUToF %float2 %ld_short2",
2078                                 "%inst = OpConvertUToF %half %ld_int",
2079                                 "%inst = OpConvertUToF %half2 %ld_int2",
2080                                 "%inst = OpBitcast %half %ld_short",
2081                                 "%inst = OpBitcast %half2 %ld_short2",
2082                                 "%inst = OpBitcast %short %ld_half",
2083                                 "%inst = OpBitcast %short2 %ld_half2"));
2084 
2085 }  // namespace
2086 }  // namespace val
2087 }  // namespace spvtools
2088