1fd4e5da5Sopenharmony_ci// Copyright (c) 2017 Google Inc.
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#include <sstream>
16fd4e5da5Sopenharmony_ci#include <string>
17fd4e5da5Sopenharmony_ci
18fd4e5da5Sopenharmony_ci#include "gmock/gmock.h"
19fd4e5da5Sopenharmony_ci#include "test/unit_spirv.h"
20fd4e5da5Sopenharmony_ci#include "test/val/val_code_generator.h"
21fd4e5da5Sopenharmony_ci#include "test/val/val_fixtures.h"
22fd4e5da5Sopenharmony_ci
23fd4e5da5Sopenharmony_cinamespace spvtools {
24fd4e5da5Sopenharmony_cinamespace val {
25fd4e5da5Sopenharmony_cinamespace {
26fd4e5da5Sopenharmony_ci
27fd4e5da5Sopenharmony_ciusing ::testing::HasSubstr;
28fd4e5da5Sopenharmony_ciusing ::testing::Not;
29fd4e5da5Sopenharmony_ciusing ::testing::Values;
30fd4e5da5Sopenharmony_ci
31fd4e5da5Sopenharmony_ciusing ValidateComposites = spvtest::ValidateBase<bool>;
32fd4e5da5Sopenharmony_ci
33fd4e5da5Sopenharmony_cistd::string GenerateShaderCode(
34fd4e5da5Sopenharmony_ci    const std::string& body,
35fd4e5da5Sopenharmony_ci    const std::string& capabilities_and_extensions = "",
36fd4e5da5Sopenharmony_ci    const std::string& execution_model = "Fragment") {
37fd4e5da5Sopenharmony_ci  std::ostringstream ss;
38fd4e5da5Sopenharmony_ci  ss << R"(
39fd4e5da5Sopenharmony_ciOpCapability Shader
40fd4e5da5Sopenharmony_ciOpCapability Float64
41fd4e5da5Sopenharmony_ci)";
42fd4e5da5Sopenharmony_ci
43fd4e5da5Sopenharmony_ci  ss << capabilities_and_extensions;
44fd4e5da5Sopenharmony_ci  ss << "OpMemoryModel Logical GLSL450\n";
45fd4e5da5Sopenharmony_ci  ss << "OpEntryPoint " << execution_model << " %main \"main\"\n";
46fd4e5da5Sopenharmony_ci  if (execution_model == "Fragment") {
47fd4e5da5Sopenharmony_ci    ss << "OpExecutionMode %main OriginUpperLeft\n";
48fd4e5da5Sopenharmony_ci  }
49fd4e5da5Sopenharmony_ci
50fd4e5da5Sopenharmony_ci  ss << R"(
51fd4e5da5Sopenharmony_ci%void = OpTypeVoid
52fd4e5da5Sopenharmony_ci%func = OpTypeFunction %void
53fd4e5da5Sopenharmony_ci%bool = OpTypeBool
54fd4e5da5Sopenharmony_ci%f32 = OpTypeFloat 32
55fd4e5da5Sopenharmony_ci%f64 = OpTypeFloat 64
56fd4e5da5Sopenharmony_ci%u32 = OpTypeInt 32 0
57fd4e5da5Sopenharmony_ci%s32 = OpTypeInt 32 1
58fd4e5da5Sopenharmony_ci%f32vec2 = OpTypeVector %f32 2
59fd4e5da5Sopenharmony_ci%f32vec3 = OpTypeVector %f32 3
60fd4e5da5Sopenharmony_ci%f32vec4 = OpTypeVector %f32 4
61fd4e5da5Sopenharmony_ci%f64vec2 = OpTypeVector %f64 2
62fd4e5da5Sopenharmony_ci%u32vec2 = OpTypeVector %u32 2
63fd4e5da5Sopenharmony_ci%u32vec4 = OpTypeVector %u32 4
64fd4e5da5Sopenharmony_ci%f64mat22 = OpTypeMatrix %f64vec2 2
65fd4e5da5Sopenharmony_ci%f32mat22 = OpTypeMatrix %f32vec2 2
66fd4e5da5Sopenharmony_ci%f32mat23 = OpTypeMatrix %f32vec2 3
67fd4e5da5Sopenharmony_ci%f32mat32 = OpTypeMatrix %f32vec3 2
68fd4e5da5Sopenharmony_ci
69fd4e5da5Sopenharmony_ci%f32_0 = OpConstant %f32 0
70fd4e5da5Sopenharmony_ci%f32_1 = OpConstant %f32 1
71fd4e5da5Sopenharmony_ci%f32_2 = OpConstant %f32 2
72fd4e5da5Sopenharmony_ci%f32_3 = OpConstant %f32 3
73fd4e5da5Sopenharmony_ci%f32vec2_01 = OpConstantComposite %f32vec2 %f32_0 %f32_1
74fd4e5da5Sopenharmony_ci%f32vec2_12 = OpConstantComposite %f32vec2 %f32_1 %f32_2
75fd4e5da5Sopenharmony_ci%f32vec4_0123 = OpConstantComposite %f32vec4 %f32_0 %f32_1 %f32_2 %f32_3
76fd4e5da5Sopenharmony_ci
77fd4e5da5Sopenharmony_ci%u32_0 = OpConstant %u32 0
78fd4e5da5Sopenharmony_ci%u32_1 = OpConstant %u32 1
79fd4e5da5Sopenharmony_ci%u32_2 = OpConstant %u32 2
80fd4e5da5Sopenharmony_ci%u32_3 = OpConstant %u32 3
81fd4e5da5Sopenharmony_ci
82fd4e5da5Sopenharmony_ci%u32vec2_01 = OpConstantComposite %u32vec2 %u32_0 %u32_1
83fd4e5da5Sopenharmony_ci%u32vec4_0123 = OpConstantComposite %u32vec4 %u32_0 %u32_1 %u32_2 %u32_3
84fd4e5da5Sopenharmony_ci
85fd4e5da5Sopenharmony_ci%f32mat22_1212 = OpConstantComposite %f32mat22 %f32vec2_12 %f32vec2_12
86fd4e5da5Sopenharmony_ci%f32mat23_121212 = OpConstantComposite %f32mat23 %f32vec2_12 %f32vec2_12 %f32vec2_12
87fd4e5da5Sopenharmony_ci
88fd4e5da5Sopenharmony_ci%f32vec2arr3 = OpTypeArray %f32vec2 %u32_3
89fd4e5da5Sopenharmony_ci%f32vec2arr2 = OpTypeArray %f32vec2 %u32_2
90fd4e5da5Sopenharmony_ci
91fd4e5da5Sopenharmony_ci%f32u32struct = OpTypeStruct %f32 %u32
92fd4e5da5Sopenharmony_ci%big_struct = OpTypeStruct %f32 %f32vec4 %f32mat23 %f32vec2arr3 %f32vec2arr2 %f32u32struct
93fd4e5da5Sopenharmony_ci
94fd4e5da5Sopenharmony_ci%ptr_big_struct = OpTypePointer Uniform %big_struct
95fd4e5da5Sopenharmony_ci%var_big_struct = OpVariable %ptr_big_struct Uniform
96fd4e5da5Sopenharmony_ci
97fd4e5da5Sopenharmony_ci%main = OpFunction %void None %func
98fd4e5da5Sopenharmony_ci%main_entry = OpLabel
99fd4e5da5Sopenharmony_ci)";
100fd4e5da5Sopenharmony_ci
101fd4e5da5Sopenharmony_ci  ss << body;
102fd4e5da5Sopenharmony_ci
103fd4e5da5Sopenharmony_ci  ss << R"(
104fd4e5da5Sopenharmony_ciOpReturn
105fd4e5da5Sopenharmony_ciOpFunctionEnd)";
106fd4e5da5Sopenharmony_ci
107fd4e5da5Sopenharmony_ci  return ss.str();
108fd4e5da5Sopenharmony_ci}
109fd4e5da5Sopenharmony_ci
110fd4e5da5Sopenharmony_ci// Returns header for legacy tests taken from val_id_test.cpp.
111fd4e5da5Sopenharmony_cistd::string GetHeaderForTestsFromValId() {
112fd4e5da5Sopenharmony_ci  return R"(
113fd4e5da5Sopenharmony_ciOpCapability Shader
114fd4e5da5Sopenharmony_ciOpCapability Linkage
115fd4e5da5Sopenharmony_ciOpCapability Addresses
116fd4e5da5Sopenharmony_ciOpCapability Pipes
117fd4e5da5Sopenharmony_ciOpCapability LiteralSampler
118fd4e5da5Sopenharmony_ciOpCapability DeviceEnqueue
119fd4e5da5Sopenharmony_ciOpCapability Vector16
120fd4e5da5Sopenharmony_ciOpCapability Int8
121fd4e5da5Sopenharmony_ciOpCapability Int16
122fd4e5da5Sopenharmony_ciOpCapability Int64
123fd4e5da5Sopenharmony_ciOpCapability Float64
124fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
125fd4e5da5Sopenharmony_ci%void = OpTypeVoid
126fd4e5da5Sopenharmony_ci%void_f  = OpTypeFunction %void
127fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
128fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
129fd4e5da5Sopenharmony_ci%v3float = OpTypeVector %float 3
130fd4e5da5Sopenharmony_ci%mat4x3 = OpTypeMatrix %v3float 4
131fd4e5da5Sopenharmony_ci%_ptr_Private_mat4x3 = OpTypePointer Private %mat4x3
132fd4e5da5Sopenharmony_ci%_ptr_Private_float = OpTypePointer Private %float
133fd4e5da5Sopenharmony_ci%my_matrix = OpVariable %_ptr_Private_mat4x3 Private
134fd4e5da5Sopenharmony_ci%my_float_var = OpVariable %_ptr_Private_float Private
135fd4e5da5Sopenharmony_ci%_ptr_Function_float = OpTypePointer Function %float
136fd4e5da5Sopenharmony_ci%int_0 = OpConstant %int 0
137fd4e5da5Sopenharmony_ci%int_1 = OpConstant %int 1
138fd4e5da5Sopenharmony_ci%int_2 = OpConstant %int 2
139fd4e5da5Sopenharmony_ci%int_3 = OpConstant %int 3
140fd4e5da5Sopenharmony_ci%int_5 = OpConstant %int 5
141fd4e5da5Sopenharmony_ci
142fd4e5da5Sopenharmony_ci; Making the following nested structures.
143fd4e5da5Sopenharmony_ci;
144fd4e5da5Sopenharmony_ci; struct S {
145fd4e5da5Sopenharmony_ci;   bool b;
146fd4e5da5Sopenharmony_ci;   vec4 v[5];
147fd4e5da5Sopenharmony_ci;   int i;
148fd4e5da5Sopenharmony_ci;   mat4x3 m[5];
149fd4e5da5Sopenharmony_ci; }
150fd4e5da5Sopenharmony_ci; uniform blockName {
151fd4e5da5Sopenharmony_ci;   S s;
152fd4e5da5Sopenharmony_ci;   bool cond;
153fd4e5da5Sopenharmony_ci; }
154fd4e5da5Sopenharmony_ci
155fd4e5da5Sopenharmony_ci%f32arr = OpTypeRuntimeArray %float
156fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
157fd4e5da5Sopenharmony_ci%array5_mat4x3 = OpTypeArray %mat4x3 %int_5
158fd4e5da5Sopenharmony_ci%array5_vec4 = OpTypeArray %v4float %int_5
159fd4e5da5Sopenharmony_ci%_ptr_Uniform_float = OpTypePointer Uniform %float
160fd4e5da5Sopenharmony_ci%_ptr_Function_vec4 = OpTypePointer Function %v4float
161fd4e5da5Sopenharmony_ci%_ptr_Uniform_vec4 = OpTypePointer Uniform %v4float
162fd4e5da5Sopenharmony_ci%struct_s = OpTypeStruct %int %array5_vec4 %int %array5_mat4x3
163fd4e5da5Sopenharmony_ci%struct_blockName = OpTypeStruct %struct_s %int
164fd4e5da5Sopenharmony_ci%_ptr_Uniform_blockName = OpTypePointer Uniform %struct_blockName
165fd4e5da5Sopenharmony_ci%_ptr_Uniform_struct_s = OpTypePointer Uniform %struct_s
166fd4e5da5Sopenharmony_ci%_ptr_Uniform_array5_mat4x3 = OpTypePointer Uniform %array5_mat4x3
167fd4e5da5Sopenharmony_ci%_ptr_Uniform_mat4x3 = OpTypePointer Uniform %mat4x3
168fd4e5da5Sopenharmony_ci%_ptr_Uniform_v3float = OpTypePointer Uniform %v3float
169fd4e5da5Sopenharmony_ci%blockName_var = OpVariable %_ptr_Uniform_blockName Uniform
170fd4e5da5Sopenharmony_ci%spec_int = OpSpecConstant %int 2
171fd4e5da5Sopenharmony_ci%func = OpFunction %void None %void_f
172fd4e5da5Sopenharmony_ci%my_label = OpLabel
173fd4e5da5Sopenharmony_ci)";
174fd4e5da5Sopenharmony_ci}
175fd4e5da5Sopenharmony_ci
176fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, VectorExtractDynamicSuccess) {
177fd4e5da5Sopenharmony_ci  const std::string body = R"(
178fd4e5da5Sopenharmony_ci%val1 = OpVectorExtractDynamic %f32 %f32vec4_0123 %u32_0
179fd4e5da5Sopenharmony_ci)";
180fd4e5da5Sopenharmony_ci
181fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body).c_str());
182fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
183fd4e5da5Sopenharmony_ci}
184fd4e5da5Sopenharmony_ci
185fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, VectorExtractDynamicWrongResultType) {
186fd4e5da5Sopenharmony_ci  const std::string body = R"(
187fd4e5da5Sopenharmony_ci%val1 = OpVectorExtractDynamic %f32vec4 %f32vec4_0123 %u32_0
188fd4e5da5Sopenharmony_ci)";
189fd4e5da5Sopenharmony_ci
190fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body).c_str());
191fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
192fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
193fd4e5da5Sopenharmony_ci              HasSubstr("Expected Result Type to be a scalar type"));
194fd4e5da5Sopenharmony_ci}
195fd4e5da5Sopenharmony_ci
196fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, VectorExtractDynamicNotVector) {
197fd4e5da5Sopenharmony_ci  const std::string body = R"(
198fd4e5da5Sopenharmony_ci%val1 = OpVectorExtractDynamic %f32 %f32mat22_1212 %u32_0
199fd4e5da5Sopenharmony_ci)";
200fd4e5da5Sopenharmony_ci
201fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body).c_str());
202fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
203fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
204fd4e5da5Sopenharmony_ci              HasSubstr("Expected Vector type to be OpTypeVector"));
205fd4e5da5Sopenharmony_ci}
206fd4e5da5Sopenharmony_ci
207fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, VectorExtractDynamicWrongVectorComponent) {
208fd4e5da5Sopenharmony_ci  const std::string body = R"(
209fd4e5da5Sopenharmony_ci%val1 = OpVectorExtractDynamic %f32 %u32vec4_0123 %u32_0
210fd4e5da5Sopenharmony_ci)";
211fd4e5da5Sopenharmony_ci
212fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body).c_str());
213fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
214fd4e5da5Sopenharmony_ci  EXPECT_THAT(
215fd4e5da5Sopenharmony_ci      getDiagnosticString(),
216fd4e5da5Sopenharmony_ci      HasSubstr("Expected Vector component type to be equal to Result Type"));
217fd4e5da5Sopenharmony_ci}
218fd4e5da5Sopenharmony_ci
219fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, VectorExtractDynamicWrongIndexType) {
220fd4e5da5Sopenharmony_ci  const std::string body = R"(
221fd4e5da5Sopenharmony_ci%val1 = OpVectorExtractDynamic %f32 %f32vec4_0123 %f32_0
222fd4e5da5Sopenharmony_ci)";
223fd4e5da5Sopenharmony_ci
224fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body).c_str());
225fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
226fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
227fd4e5da5Sopenharmony_ci              HasSubstr("Expected Index to be int scalar"));
228fd4e5da5Sopenharmony_ci}
229fd4e5da5Sopenharmony_ci
230fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, VectorInsertDynamicSuccess) {
231fd4e5da5Sopenharmony_ci  const std::string body = R"(
232fd4e5da5Sopenharmony_ci%val1 = OpVectorInsertDynamic %f32vec4 %f32vec4_0123 %f32_1 %u32_0
233fd4e5da5Sopenharmony_ci)";
234fd4e5da5Sopenharmony_ci
235fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body).c_str());
236fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
237fd4e5da5Sopenharmony_ci}
238fd4e5da5Sopenharmony_ci
239fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, VectorInsertDynamicWrongResultType) {
240fd4e5da5Sopenharmony_ci  const std::string body = R"(
241fd4e5da5Sopenharmony_ci%val1 = OpVectorInsertDynamic %f32 %f32vec4_0123 %f32_1 %u32_0
242fd4e5da5Sopenharmony_ci)";
243fd4e5da5Sopenharmony_ci
244fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body).c_str());
245fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
246fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
247fd4e5da5Sopenharmony_ci              HasSubstr("Expected Result Type to be OpTypeVector"));
248fd4e5da5Sopenharmony_ci}
249fd4e5da5Sopenharmony_ci
250fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, VectorInsertDynamicNotVector) {
251fd4e5da5Sopenharmony_ci  const std::string body = R"(
252fd4e5da5Sopenharmony_ci%val1 = OpVectorInsertDynamic %f32vec4 %f32mat22_1212 %f32_1 %u32_0
253fd4e5da5Sopenharmony_ci)";
254fd4e5da5Sopenharmony_ci
255fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body).c_str());
256fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
257fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
258fd4e5da5Sopenharmony_ci              HasSubstr("Expected Vector type to be equal to Result Type"));
259fd4e5da5Sopenharmony_ci}
260fd4e5da5Sopenharmony_ci
261fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, VectorInsertDynamicWrongComponentType) {
262fd4e5da5Sopenharmony_ci  const std::string body = R"(
263fd4e5da5Sopenharmony_ci%val1 = OpVectorInsertDynamic %f32vec4 %f32vec4_0123 %u32_1 %u32_0
264fd4e5da5Sopenharmony_ci)";
265fd4e5da5Sopenharmony_ci
266fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body).c_str());
267fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
268fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
269fd4e5da5Sopenharmony_ci              HasSubstr("Expected Component type to be equal to Result Type "
270fd4e5da5Sopenharmony_ci                        "component type"));
271fd4e5da5Sopenharmony_ci}
272fd4e5da5Sopenharmony_ci
273fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, VectorInsertDynamicWrongIndexType) {
274fd4e5da5Sopenharmony_ci  const std::string body = R"(
275fd4e5da5Sopenharmony_ci%val1 = OpVectorInsertDynamic %f32vec4 %f32vec4_0123 %f32_1 %f32_0
276fd4e5da5Sopenharmony_ci)";
277fd4e5da5Sopenharmony_ci
278fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body).c_str());
279fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
280fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
281fd4e5da5Sopenharmony_ci              HasSubstr("Expected Index to be int scalar"));
282fd4e5da5Sopenharmony_ci}
283fd4e5da5Sopenharmony_ci
284fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeConstructNotComposite) {
285fd4e5da5Sopenharmony_ci  const std::string body = R"(
286fd4e5da5Sopenharmony_ci%val1 = OpCompositeConstruct %f32 %f32_1
287fd4e5da5Sopenharmony_ci)";
288fd4e5da5Sopenharmony_ci
289fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body).c_str());
290fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
291fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
292fd4e5da5Sopenharmony_ci              HasSubstr("Expected Result Type to be a composite type"));
293fd4e5da5Sopenharmony_ci}
294fd4e5da5Sopenharmony_ci
295fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeConstructVectorSuccess) {
296fd4e5da5Sopenharmony_ci  const std::string body = R"(
297fd4e5da5Sopenharmony_ci%val1 = OpCompositeConstruct %f32vec4 %f32vec2_12 %f32vec2_12
298fd4e5da5Sopenharmony_ci%val2 = OpCompositeConstruct %f32vec4 %f32vec2_12 %f32_0 %f32_0
299fd4e5da5Sopenharmony_ci%val3 = OpCompositeConstruct %f32vec4 %f32_0 %f32_0 %f32vec2_12
300fd4e5da5Sopenharmony_ci%val4 = OpCompositeConstruct %f32vec4 %f32_0 %f32_1 %f32_2 %f32_3
301fd4e5da5Sopenharmony_ci)";
302fd4e5da5Sopenharmony_ci
303fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body).c_str());
304fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
305fd4e5da5Sopenharmony_ci}
306fd4e5da5Sopenharmony_ci
307fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeConstructVectorOnlyOneConstituent) {
308fd4e5da5Sopenharmony_ci  const std::string body = R"(
309fd4e5da5Sopenharmony_ci%val1 = OpCompositeConstruct %f32vec4 %f32vec4_0123
310fd4e5da5Sopenharmony_ci)";
311fd4e5da5Sopenharmony_ci
312fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body).c_str());
313fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
314fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
315fd4e5da5Sopenharmony_ci              HasSubstr("Expected number of constituents to be at least 2"));
316fd4e5da5Sopenharmony_ci}
317fd4e5da5Sopenharmony_ci
318fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeConstructVectorWrongConsituent1) {
319fd4e5da5Sopenharmony_ci  const std::string body = R"(
320fd4e5da5Sopenharmony_ci%val1 = OpCompositeConstruct %f32vec4 %f32 %f32vec2_12
321fd4e5da5Sopenharmony_ci)";
322fd4e5da5Sopenharmony_ci
323fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body).c_str());
324fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
325fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
326fd4e5da5Sopenharmony_ci              HasSubstr("Operand '5[%float]' cannot be a "
327fd4e5da5Sopenharmony_ci                        "type"));
328fd4e5da5Sopenharmony_ci}
329fd4e5da5Sopenharmony_ci
330fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeConstructVectorWrongConsituent2) {
331fd4e5da5Sopenharmony_ci  const std::string body = R"(
332fd4e5da5Sopenharmony_ci%val1 = OpCompositeConstruct %f32vec4 %f32vec2_12 %u32vec2_01
333fd4e5da5Sopenharmony_ci)";
334fd4e5da5Sopenharmony_ci
335fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body).c_str());
336fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
337fd4e5da5Sopenharmony_ci  EXPECT_THAT(
338fd4e5da5Sopenharmony_ci      getDiagnosticString(),
339fd4e5da5Sopenharmony_ci      HasSubstr("Expected Constituents to be scalars or vectors of the same "
340fd4e5da5Sopenharmony_ci                "type as Result Type components"));
341fd4e5da5Sopenharmony_ci}
342fd4e5da5Sopenharmony_ci
343fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeConstructVectorWrongConsituent3) {
344fd4e5da5Sopenharmony_ci  const std::string body = R"(
345fd4e5da5Sopenharmony_ci%val1 = OpCompositeConstruct %f32vec4 %f32vec2_12 %u32_0 %f32_0
346fd4e5da5Sopenharmony_ci)";
347fd4e5da5Sopenharmony_ci
348fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body).c_str());
349fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
350fd4e5da5Sopenharmony_ci  EXPECT_THAT(
351fd4e5da5Sopenharmony_ci      getDiagnosticString(),
352fd4e5da5Sopenharmony_ci      HasSubstr("Expected Constituents to be scalars or vectors of the same "
353fd4e5da5Sopenharmony_ci                "type as Result Type components"));
354fd4e5da5Sopenharmony_ci}
355fd4e5da5Sopenharmony_ci
356fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeConstructVectorWrongComponentNumber1) {
357fd4e5da5Sopenharmony_ci  const std::string body = R"(
358fd4e5da5Sopenharmony_ci%val1 = OpCompositeConstruct %f32vec4 %f32vec2_12 %f32_0
359fd4e5da5Sopenharmony_ci)";
360fd4e5da5Sopenharmony_ci
361fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body).c_str());
362fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
363fd4e5da5Sopenharmony_ci  EXPECT_THAT(
364fd4e5da5Sopenharmony_ci      getDiagnosticString(),
365fd4e5da5Sopenharmony_ci      HasSubstr("Expected total number of given components to be equal to the "
366fd4e5da5Sopenharmony_ci                "size of Result Type vector"));
367fd4e5da5Sopenharmony_ci}
368fd4e5da5Sopenharmony_ci
369fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeConstructVectorWrongComponentNumber2) {
370fd4e5da5Sopenharmony_ci  const std::string body = R"(
371fd4e5da5Sopenharmony_ci%val1 = OpCompositeConstruct %f32vec4 %f32vec2_12 %f32vec2_12 %f32_0
372fd4e5da5Sopenharmony_ci)";
373fd4e5da5Sopenharmony_ci
374fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body).c_str());
375fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
376fd4e5da5Sopenharmony_ci  EXPECT_THAT(
377fd4e5da5Sopenharmony_ci      getDiagnosticString(),
378fd4e5da5Sopenharmony_ci      HasSubstr("Expected total number of given components to be equal to the "
379fd4e5da5Sopenharmony_ci                "size of Result Type vector"));
380fd4e5da5Sopenharmony_ci}
381fd4e5da5Sopenharmony_ci
382fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeConstructMatrixSuccess) {
383fd4e5da5Sopenharmony_ci  const std::string body = R"(
384fd4e5da5Sopenharmony_ci%val1 = OpCompositeConstruct %f32mat22 %f32vec2_12 %f32vec2_12
385fd4e5da5Sopenharmony_ci%val2 = OpCompositeConstruct %f32mat23 %f32vec2_12 %f32vec2_12 %f32vec2_12
386fd4e5da5Sopenharmony_ci)";
387fd4e5da5Sopenharmony_ci
388fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body).c_str());
389fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
390fd4e5da5Sopenharmony_ci}
391fd4e5da5Sopenharmony_ci
392fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeConstructVectorWrongConsituentNumber1) {
393fd4e5da5Sopenharmony_ci  const std::string body = R"(
394fd4e5da5Sopenharmony_ci%val1 = OpCompositeConstruct %f32mat22 %f32vec2_12
395fd4e5da5Sopenharmony_ci)";
396fd4e5da5Sopenharmony_ci
397fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body).c_str());
398fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
399fd4e5da5Sopenharmony_ci  EXPECT_THAT(
400fd4e5da5Sopenharmony_ci      getDiagnosticString(),
401fd4e5da5Sopenharmony_ci      HasSubstr("Expected total number of Constituents to be equal to the "
402fd4e5da5Sopenharmony_ci                "number of columns of Result Type matrix"));
403fd4e5da5Sopenharmony_ci}
404fd4e5da5Sopenharmony_ci
405fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeConstructVectorWrongConsituentNumber2) {
406fd4e5da5Sopenharmony_ci  const std::string body = R"(
407fd4e5da5Sopenharmony_ci%val1 = OpCompositeConstruct %f32mat22 %f32vec2_12 %f32vec2_12 %f32vec2_12
408fd4e5da5Sopenharmony_ci)";
409fd4e5da5Sopenharmony_ci
410fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body).c_str());
411fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
412fd4e5da5Sopenharmony_ci  EXPECT_THAT(
413fd4e5da5Sopenharmony_ci      getDiagnosticString(),
414fd4e5da5Sopenharmony_ci      HasSubstr("Expected total number of Constituents to be equal to the "
415fd4e5da5Sopenharmony_ci                "number of columns of Result Type matrix"));
416fd4e5da5Sopenharmony_ci}
417fd4e5da5Sopenharmony_ci
418fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeConstructVectorWrongConsituent) {
419fd4e5da5Sopenharmony_ci  const std::string body = R"(
420fd4e5da5Sopenharmony_ci%val1 = OpCompositeConstruct %f32mat22 %f32vec2_12 %u32vec2_01
421fd4e5da5Sopenharmony_ci)";
422fd4e5da5Sopenharmony_ci
423fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body).c_str());
424fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
425fd4e5da5Sopenharmony_ci  EXPECT_THAT(
426fd4e5da5Sopenharmony_ci      getDiagnosticString(),
427fd4e5da5Sopenharmony_ci      HasSubstr("Expected Constituent type to be equal to the column type "
428fd4e5da5Sopenharmony_ci                "Result Type matrix"));
429fd4e5da5Sopenharmony_ci}
430fd4e5da5Sopenharmony_ci
431fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeConstructArraySuccess) {
432fd4e5da5Sopenharmony_ci  const std::string body = R"(
433fd4e5da5Sopenharmony_ci%val1 = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12
434fd4e5da5Sopenharmony_ci)";
435fd4e5da5Sopenharmony_ci
436fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body).c_str());
437fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
438fd4e5da5Sopenharmony_ci}
439fd4e5da5Sopenharmony_ci
440fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeConstructArrayWrongConsituentNumber1) {
441fd4e5da5Sopenharmony_ci  const std::string body = R"(
442fd4e5da5Sopenharmony_ci%val1 = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12
443fd4e5da5Sopenharmony_ci)";
444fd4e5da5Sopenharmony_ci
445fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body).c_str());
446fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
447fd4e5da5Sopenharmony_ci  EXPECT_THAT(
448fd4e5da5Sopenharmony_ci      getDiagnosticString(),
449fd4e5da5Sopenharmony_ci      HasSubstr("Expected total number of Constituents to be equal to the "
450fd4e5da5Sopenharmony_ci                "number of elements of Result Type array"));
451fd4e5da5Sopenharmony_ci}
452fd4e5da5Sopenharmony_ci
453fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeConstructArrayWrongConsituentNumber2) {
454fd4e5da5Sopenharmony_ci  const std::string body = R"(
455fd4e5da5Sopenharmony_ci%val1 = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12 %f32vec2_12
456fd4e5da5Sopenharmony_ci)";
457fd4e5da5Sopenharmony_ci
458fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body).c_str());
459fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
460fd4e5da5Sopenharmony_ci  EXPECT_THAT(
461fd4e5da5Sopenharmony_ci      getDiagnosticString(),
462fd4e5da5Sopenharmony_ci      HasSubstr("Expected total number of Constituents to be equal to the "
463fd4e5da5Sopenharmony_ci                "number of elements of Result Type array"));
464fd4e5da5Sopenharmony_ci}
465fd4e5da5Sopenharmony_ci
466fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeConstructArrayWrongConsituent) {
467fd4e5da5Sopenharmony_ci  const std::string body = R"(
468fd4e5da5Sopenharmony_ci%val1 = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %u32vec2_01 %f32vec2_12
469fd4e5da5Sopenharmony_ci)";
470fd4e5da5Sopenharmony_ci
471fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body).c_str());
472fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
473fd4e5da5Sopenharmony_ci  EXPECT_THAT(
474fd4e5da5Sopenharmony_ci      getDiagnosticString(),
475fd4e5da5Sopenharmony_ci      HasSubstr("Expected Constituent type to be equal to the column type "
476fd4e5da5Sopenharmony_ci                "Result Type array"));
477fd4e5da5Sopenharmony_ci}
478fd4e5da5Sopenharmony_ci
479fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeConstructStructSuccess) {
480fd4e5da5Sopenharmony_ci  const std::string body = R"(
481fd4e5da5Sopenharmony_ci%val1 = OpCompositeConstruct %f32u32struct %f32_0 %u32_1
482fd4e5da5Sopenharmony_ci)";
483fd4e5da5Sopenharmony_ci
484fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body).c_str());
485fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
486fd4e5da5Sopenharmony_ci}
487fd4e5da5Sopenharmony_ci
488fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeConstructStructWrongConstituentNumber1) {
489fd4e5da5Sopenharmony_ci  const std::string body = R"(
490fd4e5da5Sopenharmony_ci%val1 = OpCompositeConstruct %f32u32struct %f32_0
491fd4e5da5Sopenharmony_ci)";
492fd4e5da5Sopenharmony_ci
493fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body).c_str());
494fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
495fd4e5da5Sopenharmony_ci  EXPECT_THAT(
496fd4e5da5Sopenharmony_ci      getDiagnosticString(),
497fd4e5da5Sopenharmony_ci      HasSubstr("Expected total number of Constituents to be equal to the "
498fd4e5da5Sopenharmony_ci                "number of members of Result Type struct"));
499fd4e5da5Sopenharmony_ci}
500fd4e5da5Sopenharmony_ci
501fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeConstructStructWrongConstituentNumber2) {
502fd4e5da5Sopenharmony_ci  const std::string body = R"(
503fd4e5da5Sopenharmony_ci%val1 = OpCompositeConstruct %f32u32struct %f32_0 %u32_1 %u32_1
504fd4e5da5Sopenharmony_ci)";
505fd4e5da5Sopenharmony_ci
506fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body).c_str());
507fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
508fd4e5da5Sopenharmony_ci  EXPECT_THAT(
509fd4e5da5Sopenharmony_ci      getDiagnosticString(),
510fd4e5da5Sopenharmony_ci      HasSubstr("Expected total number of Constituents to be equal to the "
511fd4e5da5Sopenharmony_ci                "number of members of Result Type struct"));
512fd4e5da5Sopenharmony_ci}
513fd4e5da5Sopenharmony_ci
514fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeConstructStructWrongConstituent) {
515fd4e5da5Sopenharmony_ci  const std::string body = R"(
516fd4e5da5Sopenharmony_ci%val1 = OpCompositeConstruct %f32u32struct %f32_0 %f32_1
517fd4e5da5Sopenharmony_ci)";
518fd4e5da5Sopenharmony_ci
519fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body).c_str());
520fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
521fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
522fd4e5da5Sopenharmony_ci              HasSubstr("Expected Constituent type to be equal to the "
523fd4e5da5Sopenharmony_ci                        "corresponding member type of Result Type struct"));
524fd4e5da5Sopenharmony_ci}
525fd4e5da5Sopenharmony_ci
526fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CopyObjectSuccess) {
527fd4e5da5Sopenharmony_ci  const std::string body = R"(
528fd4e5da5Sopenharmony_ci%val1 = OpCopyObject %f32 %f32_0
529fd4e5da5Sopenharmony_ci%val2 = OpCopyObject %f32vec4 %f32vec4_0123
530fd4e5da5Sopenharmony_ci)";
531fd4e5da5Sopenharmony_ci
532fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body).c_str());
533fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
534fd4e5da5Sopenharmony_ci}
535fd4e5da5Sopenharmony_ci
536fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CopyObjectResultTypeNotType) {
537fd4e5da5Sopenharmony_ci  const std::string body = R"(
538fd4e5da5Sopenharmony_ci%val1 = OpCopyObject %f32_0 %f32_0
539fd4e5da5Sopenharmony_ci)";
540fd4e5da5Sopenharmony_ci
541fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body).c_str());
542fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
543fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
544fd4e5da5Sopenharmony_ci              HasSubstr("ID '19[%float_0]' is not a type id"));
545fd4e5da5Sopenharmony_ci}
546fd4e5da5Sopenharmony_ci
547fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CopyObjectWrongOperandType) {
548fd4e5da5Sopenharmony_ci  const std::string body = R"(
549fd4e5da5Sopenharmony_ci%val1 = OpCopyObject %f32 %u32_0
550fd4e5da5Sopenharmony_ci)";
551fd4e5da5Sopenharmony_ci
552fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body).c_str());
553fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
554fd4e5da5Sopenharmony_ci  EXPECT_THAT(
555fd4e5da5Sopenharmony_ci      getDiagnosticString(),
556fd4e5da5Sopenharmony_ci      HasSubstr("Expected Result Type and Operand type to be the same"));
557fd4e5da5Sopenharmony_ci}
558fd4e5da5Sopenharmony_ci
559fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, TransposeSuccess) {
560fd4e5da5Sopenharmony_ci  const std::string body = R"(
561fd4e5da5Sopenharmony_ci%val1 = OpTranspose %f32mat32 %f32mat23_121212
562fd4e5da5Sopenharmony_ci%val2 = OpTranspose %f32mat22 %f32mat22_1212
563fd4e5da5Sopenharmony_ci)";
564fd4e5da5Sopenharmony_ci
565fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body).c_str());
566fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
567fd4e5da5Sopenharmony_ci}
568fd4e5da5Sopenharmony_ci
569fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, TransposeResultTypeNotMatrix) {
570fd4e5da5Sopenharmony_ci  const std::string body = R"(
571fd4e5da5Sopenharmony_ci%val1 = OpTranspose %f32vec4 %f32mat22_1212
572fd4e5da5Sopenharmony_ci)";
573fd4e5da5Sopenharmony_ci
574fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body).c_str());
575fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
576fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
577fd4e5da5Sopenharmony_ci              HasSubstr("Expected Result Type to be a matrix type"));
578fd4e5da5Sopenharmony_ci}
579fd4e5da5Sopenharmony_ci
580fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, TransposeDifferentComponentTypes) {
581fd4e5da5Sopenharmony_ci  const std::string body = R"(
582fd4e5da5Sopenharmony_ci%val1 = OpTranspose %f64mat22 %f32mat22_1212
583fd4e5da5Sopenharmony_ci)";
584fd4e5da5Sopenharmony_ci
585fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body).c_str());
586fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
587fd4e5da5Sopenharmony_ci  EXPECT_THAT(
588fd4e5da5Sopenharmony_ci      getDiagnosticString(),
589fd4e5da5Sopenharmony_ci      HasSubstr("Expected component types of Matrix and Result Type to be "
590fd4e5da5Sopenharmony_ci                "identical"));
591fd4e5da5Sopenharmony_ci}
592fd4e5da5Sopenharmony_ci
593fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, TransposeIncompatibleDimensions1) {
594fd4e5da5Sopenharmony_ci  const std::string body = R"(
595fd4e5da5Sopenharmony_ci%val1 = OpTranspose %f32mat23 %f32mat22_1212
596fd4e5da5Sopenharmony_ci)";
597fd4e5da5Sopenharmony_ci
598fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body).c_str());
599fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
600fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
601fd4e5da5Sopenharmony_ci              HasSubstr("Expected number of columns and the column size "
602fd4e5da5Sopenharmony_ci                        "of Matrix to be the reverse of those of Result Type"));
603fd4e5da5Sopenharmony_ci}
604fd4e5da5Sopenharmony_ci
605fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, TransposeIncompatibleDimensions2) {
606fd4e5da5Sopenharmony_ci  const std::string body = R"(
607fd4e5da5Sopenharmony_ci%val1 = OpTranspose %f32mat32 %f32mat22_1212
608fd4e5da5Sopenharmony_ci)";
609fd4e5da5Sopenharmony_ci
610fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body).c_str());
611fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
612fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
613fd4e5da5Sopenharmony_ci              HasSubstr("Expected number of columns and the column size "
614fd4e5da5Sopenharmony_ci                        "of Matrix to be the reverse of those of Result Type"));
615fd4e5da5Sopenharmony_ci}
616fd4e5da5Sopenharmony_ci
617fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, TransposeIncompatibleDimensions3) {
618fd4e5da5Sopenharmony_ci  const std::string body = R"(
619fd4e5da5Sopenharmony_ci%val1 = OpTranspose %f32mat23 %f32mat23_121212
620fd4e5da5Sopenharmony_ci)";
621fd4e5da5Sopenharmony_ci
622fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body).c_str());
623fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
624fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
625fd4e5da5Sopenharmony_ci              HasSubstr("Expected number of columns and the column size "
626fd4e5da5Sopenharmony_ci                        "of Matrix to be the reverse of those of Result Type"));
627fd4e5da5Sopenharmony_ci}
628fd4e5da5Sopenharmony_ci
629fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeExtractSuccess) {
630fd4e5da5Sopenharmony_ci  const std::string body = R"(
631fd4e5da5Sopenharmony_ci%val1 = OpCompositeExtract %f32 %f32vec4_0123 1
632fd4e5da5Sopenharmony_ci%val2 = OpCompositeExtract %u32 %u32vec4_0123 0
633fd4e5da5Sopenharmony_ci%val3 = OpCompositeExtract %f32 %f32mat22_1212 0 1
634fd4e5da5Sopenharmony_ci%val4 = OpCompositeExtract %f32vec2 %f32mat22_1212 0
635fd4e5da5Sopenharmony_ci%array = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12
636fd4e5da5Sopenharmony_ci%val5 = OpCompositeExtract %f32vec2 %array 2
637fd4e5da5Sopenharmony_ci%val6 = OpCompositeExtract %f32 %array 2 1
638fd4e5da5Sopenharmony_ci%struct = OpLoad %big_struct %var_big_struct
639fd4e5da5Sopenharmony_ci%val7 = OpCompositeExtract %f32 %struct 0
640fd4e5da5Sopenharmony_ci%val8 = OpCompositeExtract %f32vec4 %struct 1
641fd4e5da5Sopenharmony_ci%val9 = OpCompositeExtract %f32 %struct 1 2
642fd4e5da5Sopenharmony_ci%val10 = OpCompositeExtract %f32mat23 %struct 2
643fd4e5da5Sopenharmony_ci%val11 = OpCompositeExtract %f32vec2 %struct 2 2
644fd4e5da5Sopenharmony_ci%val12 = OpCompositeExtract %f32 %struct 2 2 1
645fd4e5da5Sopenharmony_ci%val13 = OpCompositeExtract %f32vec2 %struct 3 2
646fd4e5da5Sopenharmony_ci%val14 = OpCompositeExtract %f32 %struct 3 2 1
647fd4e5da5Sopenharmony_ci%val15 = OpCompositeExtract %f32vec2 %struct 4 1
648fd4e5da5Sopenharmony_ci%val16 = OpCompositeExtract %f32 %struct 4 0 1
649fd4e5da5Sopenharmony_ci%val17 = OpCompositeExtract %f32 %struct 5 0
650fd4e5da5Sopenharmony_ci%val18 = OpCompositeExtract %u32 %struct 5 1
651fd4e5da5Sopenharmony_ci)";
652fd4e5da5Sopenharmony_ci
653fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body));
654fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
655fd4e5da5Sopenharmony_ci}
656fd4e5da5Sopenharmony_ci
657fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeExtractNotObject) {
658fd4e5da5Sopenharmony_ci  const std::string body = R"(
659fd4e5da5Sopenharmony_ci%val1 = OpCompositeExtract %f32 %f32vec4 1
660fd4e5da5Sopenharmony_ci)";
661fd4e5da5Sopenharmony_ci
662fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body));
663fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
664fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand '11[%v4float]' cannot "
665fd4e5da5Sopenharmony_ci                                               "be a type"));
666fd4e5da5Sopenharmony_ci}
667fd4e5da5Sopenharmony_ci
668fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeExtractNotComposite) {
669fd4e5da5Sopenharmony_ci  const std::string body = R"(
670fd4e5da5Sopenharmony_ci%val1 = OpCompositeExtract %f32 %f32_1 0
671fd4e5da5Sopenharmony_ci)";
672fd4e5da5Sopenharmony_ci
673fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body));
674fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
675fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
676fd4e5da5Sopenharmony_ci              HasSubstr("Reached non-composite type while indexes still remain "
677fd4e5da5Sopenharmony_ci                        "to be traversed."));
678fd4e5da5Sopenharmony_ci}
679fd4e5da5Sopenharmony_ci
680fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeExtractVectorOutOfBounds) {
681fd4e5da5Sopenharmony_ci  const std::string body = R"(
682fd4e5da5Sopenharmony_ci%val1 = OpCompositeExtract %f32 %f32vec4_0123 4
683fd4e5da5Sopenharmony_ci)";
684fd4e5da5Sopenharmony_ci
685fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body));
686fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
687fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
688fd4e5da5Sopenharmony_ci              HasSubstr("Vector access is out of bounds, "
689fd4e5da5Sopenharmony_ci                        "vector size is 4, but access index is 4"));
690fd4e5da5Sopenharmony_ci}
691fd4e5da5Sopenharmony_ci
692fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeExtractMatrixOutOfCols) {
693fd4e5da5Sopenharmony_ci  const std::string body = R"(
694fd4e5da5Sopenharmony_ci%val1 = OpCompositeExtract %f32 %f32mat23_121212 3 1
695fd4e5da5Sopenharmony_ci)";
696fd4e5da5Sopenharmony_ci
697fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body));
698fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
699fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
700fd4e5da5Sopenharmony_ci              HasSubstr("Matrix access is out of bounds, "
701fd4e5da5Sopenharmony_ci                        "matrix has 3 columns, but access index is 3"));
702fd4e5da5Sopenharmony_ci}
703fd4e5da5Sopenharmony_ci
704fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeExtractMatrixOutOfRows) {
705fd4e5da5Sopenharmony_ci  const std::string body = R"(
706fd4e5da5Sopenharmony_ci%val1 = OpCompositeExtract %f32 %f32mat23_121212 2 5
707fd4e5da5Sopenharmony_ci)";
708fd4e5da5Sopenharmony_ci
709fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body));
710fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
711fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
712fd4e5da5Sopenharmony_ci              HasSubstr("Vector access is out of bounds, "
713fd4e5da5Sopenharmony_ci                        "vector size is 2, but access index is 5"));
714fd4e5da5Sopenharmony_ci}
715fd4e5da5Sopenharmony_ci
716fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeExtractArrayOutOfBounds) {
717fd4e5da5Sopenharmony_ci  const std::string body = R"(
718fd4e5da5Sopenharmony_ci%array = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12
719fd4e5da5Sopenharmony_ci%val1 = OpCompositeExtract %f32vec2 %array 3
720fd4e5da5Sopenharmony_ci)";
721fd4e5da5Sopenharmony_ci
722fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body));
723fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
724fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
725fd4e5da5Sopenharmony_ci              HasSubstr("Array access is out of bounds, "
726fd4e5da5Sopenharmony_ci                        "array size is 3, but access index is 3"));
727fd4e5da5Sopenharmony_ci}
728fd4e5da5Sopenharmony_ci
729fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeExtractStructOutOfBounds) {
730fd4e5da5Sopenharmony_ci  const std::string body = R"(
731fd4e5da5Sopenharmony_ci%struct = OpLoad %big_struct %var_big_struct
732fd4e5da5Sopenharmony_ci%val1 = OpCompositeExtract %f32 %struct 6
733fd4e5da5Sopenharmony_ci)";
734fd4e5da5Sopenharmony_ci
735fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body));
736fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
737fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
738fd4e5da5Sopenharmony_ci              HasSubstr("Index is out of bounds, can not find index 6 in the "
739fd4e5da5Sopenharmony_ci                        "structure <id> '37'. This structure has 6 members. "
740fd4e5da5Sopenharmony_ci                        "Largest valid index is 5."));
741fd4e5da5Sopenharmony_ci}
742fd4e5da5Sopenharmony_ci
743fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeExtractNestedVectorOutOfBounds) {
744fd4e5da5Sopenharmony_ci  const std::string body = R"(
745fd4e5da5Sopenharmony_ci%struct = OpLoad %big_struct %var_big_struct
746fd4e5da5Sopenharmony_ci%val1 = OpCompositeExtract %f32 %struct 3 1 5
747fd4e5da5Sopenharmony_ci)";
748fd4e5da5Sopenharmony_ci
749fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body));
750fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
751fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
752fd4e5da5Sopenharmony_ci              HasSubstr("Vector access is out of bounds, "
753fd4e5da5Sopenharmony_ci                        "vector size is 2, but access index is 5"));
754fd4e5da5Sopenharmony_ci}
755fd4e5da5Sopenharmony_ci
756fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeExtractTooManyIndices) {
757fd4e5da5Sopenharmony_ci  const std::string body = R"(
758fd4e5da5Sopenharmony_ci%struct = OpLoad %big_struct %var_big_struct
759fd4e5da5Sopenharmony_ci%val1 = OpCompositeExtract %f32 %struct 3 1 1 2
760fd4e5da5Sopenharmony_ci)";
761fd4e5da5Sopenharmony_ci
762fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body));
763fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
764fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
765fd4e5da5Sopenharmony_ci              HasSubstr("Reached non-composite type while "
766fd4e5da5Sopenharmony_ci                        "indexes still remain to be traversed."));
767fd4e5da5Sopenharmony_ci}
768fd4e5da5Sopenharmony_ci
769fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeExtractNoIndices) {
770fd4e5da5Sopenharmony_ci  const std::string body = R"(
771fd4e5da5Sopenharmony_ci%struct = OpLoad %big_struct %var_big_struct
772fd4e5da5Sopenharmony_ci%val1 = OpCompositeExtract %big_struct %struct
773fd4e5da5Sopenharmony_ci)";
774fd4e5da5Sopenharmony_ci
775fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body));
776fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
777fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
778fd4e5da5Sopenharmony_ci              HasSubstr("Expected at least one index to OpCompositeExtract"));
779fd4e5da5Sopenharmony_ci}
780fd4e5da5Sopenharmony_ci
781fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeExtractWrongType1) {
782fd4e5da5Sopenharmony_ci  const std::string body = R"(
783fd4e5da5Sopenharmony_ci%struct = OpLoad %big_struct %var_big_struct
784fd4e5da5Sopenharmony_ci%val1 = OpCompositeExtract %f32vec2 %struct 3 1 1
785fd4e5da5Sopenharmony_ci)";
786fd4e5da5Sopenharmony_ci
787fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body));
788fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
789fd4e5da5Sopenharmony_ci  EXPECT_THAT(
790fd4e5da5Sopenharmony_ci      getDiagnosticString(),
791fd4e5da5Sopenharmony_ci      HasSubstr(
792fd4e5da5Sopenharmony_ci          "Result type (OpTypeVector) does not match the type that results "
793fd4e5da5Sopenharmony_ci          "from indexing into the composite (OpTypeFloat)."));
794fd4e5da5Sopenharmony_ci}
795fd4e5da5Sopenharmony_ci
796fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeExtractWrongType2) {
797fd4e5da5Sopenharmony_ci  const std::string body = R"(
798fd4e5da5Sopenharmony_ci%struct = OpLoad %big_struct %var_big_struct
799fd4e5da5Sopenharmony_ci%val1 = OpCompositeExtract %f32 %struct 3 1
800fd4e5da5Sopenharmony_ci)";
801fd4e5da5Sopenharmony_ci
802fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body));
803fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
804fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
805fd4e5da5Sopenharmony_ci              HasSubstr("Result type (OpTypeFloat) does not match the type "
806fd4e5da5Sopenharmony_ci                        "that results from indexing into the composite "
807fd4e5da5Sopenharmony_ci                        "(OpTypeVector)."));
808fd4e5da5Sopenharmony_ci}
809fd4e5da5Sopenharmony_ci
810fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeExtractWrongType3) {
811fd4e5da5Sopenharmony_ci  const std::string body = R"(
812fd4e5da5Sopenharmony_ci%struct = OpLoad %big_struct %var_big_struct
813fd4e5da5Sopenharmony_ci%val1 = OpCompositeExtract %f32 %struct 2 1
814fd4e5da5Sopenharmony_ci)";
815fd4e5da5Sopenharmony_ci
816fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body));
817fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
818fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
819fd4e5da5Sopenharmony_ci              HasSubstr("Result type (OpTypeFloat) does not match the type "
820fd4e5da5Sopenharmony_ci                        "that results from indexing into the composite "
821fd4e5da5Sopenharmony_ci                        "(OpTypeVector)."));
822fd4e5da5Sopenharmony_ci}
823fd4e5da5Sopenharmony_ci
824fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeExtractWrongType4) {
825fd4e5da5Sopenharmony_ci  const std::string body = R"(
826fd4e5da5Sopenharmony_ci%struct = OpLoad %big_struct %var_big_struct
827fd4e5da5Sopenharmony_ci%val1 = OpCompositeExtract %f32 %struct 4 1
828fd4e5da5Sopenharmony_ci)";
829fd4e5da5Sopenharmony_ci
830fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body));
831fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
832fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
833fd4e5da5Sopenharmony_ci              HasSubstr("Result type (OpTypeFloat) does not match the type "
834fd4e5da5Sopenharmony_ci                        "that results from indexing into the composite "
835fd4e5da5Sopenharmony_ci                        "(OpTypeVector)."));
836fd4e5da5Sopenharmony_ci}
837fd4e5da5Sopenharmony_ci
838fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeExtractWrongType5) {
839fd4e5da5Sopenharmony_ci  const std::string body = R"(
840fd4e5da5Sopenharmony_ci%struct = OpLoad %big_struct %var_big_struct
841fd4e5da5Sopenharmony_ci%val1 = OpCompositeExtract %f32 %struct 5 1
842fd4e5da5Sopenharmony_ci)";
843fd4e5da5Sopenharmony_ci
844fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body));
845fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
846fd4e5da5Sopenharmony_ci  EXPECT_THAT(
847fd4e5da5Sopenharmony_ci      getDiagnosticString(),
848fd4e5da5Sopenharmony_ci      HasSubstr(
849fd4e5da5Sopenharmony_ci          "Result type (OpTypeFloat) does not match the "
850fd4e5da5Sopenharmony_ci          "type that results from indexing into the composite (OpTypeInt)."));
851fd4e5da5Sopenharmony_ci}
852fd4e5da5Sopenharmony_ci
853fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeInsertSuccess) {
854fd4e5da5Sopenharmony_ci  const std::string body = R"(
855fd4e5da5Sopenharmony_ci%val1 = OpCompositeInsert %f32vec4 %f32_1 %f32vec4_0123 0
856fd4e5da5Sopenharmony_ci%val2 = OpCompositeInsert %u32vec4 %u32_1 %u32vec4_0123 0
857fd4e5da5Sopenharmony_ci%val3 = OpCompositeInsert %f32mat22 %f32_2 %f32mat22_1212 0 1
858fd4e5da5Sopenharmony_ci%val4 = OpCompositeInsert %f32mat22 %f32vec2_01 %f32mat22_1212 0
859fd4e5da5Sopenharmony_ci%array = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12
860fd4e5da5Sopenharmony_ci%val5 = OpCompositeInsert %f32vec2arr3 %f32vec2_01 %array 2
861fd4e5da5Sopenharmony_ci%val6 = OpCompositeInsert %f32vec2arr3 %f32_3 %array 2 1
862fd4e5da5Sopenharmony_ci%struct = OpLoad %big_struct %var_big_struct
863fd4e5da5Sopenharmony_ci%val7 = OpCompositeInsert %big_struct %f32_3 %struct 0
864fd4e5da5Sopenharmony_ci%val8 = OpCompositeInsert %big_struct %f32vec4_0123 %struct 1
865fd4e5da5Sopenharmony_ci%val9 = OpCompositeInsert %big_struct %f32_3 %struct 1 2
866fd4e5da5Sopenharmony_ci%val10 = OpCompositeInsert %big_struct %f32mat23_121212 %struct 2
867fd4e5da5Sopenharmony_ci%val11 = OpCompositeInsert %big_struct %f32vec2_01 %struct 2 2
868fd4e5da5Sopenharmony_ci%val12 = OpCompositeInsert %big_struct %f32_3 %struct 2 2 1
869fd4e5da5Sopenharmony_ci%val13 = OpCompositeInsert %big_struct %f32vec2_01 %struct 3 2
870fd4e5da5Sopenharmony_ci%val14 = OpCompositeInsert %big_struct %f32_3 %struct 3 2 1
871fd4e5da5Sopenharmony_ci%val15 = OpCompositeInsert %big_struct %f32vec2_01 %struct 4 1
872fd4e5da5Sopenharmony_ci%val16 = OpCompositeInsert %big_struct %f32_3 %struct 4 0 1
873fd4e5da5Sopenharmony_ci%val17 = OpCompositeInsert %big_struct %f32_3 %struct 5 0
874fd4e5da5Sopenharmony_ci%val18 = OpCompositeInsert %big_struct %u32_3 %struct 5 1
875fd4e5da5Sopenharmony_ci)";
876fd4e5da5Sopenharmony_ci
877fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body));
878fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
879fd4e5da5Sopenharmony_ci}
880fd4e5da5Sopenharmony_ci
881fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeInsertResultTypeDifferentFromComposite) {
882fd4e5da5Sopenharmony_ci  const std::string body = R"(
883fd4e5da5Sopenharmony_ci%val1 = OpCompositeInsert %f32 %f32_1 %f32vec4_0123 0
884fd4e5da5Sopenharmony_ci)";
885fd4e5da5Sopenharmony_ci
886fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body));
887fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
888fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
889fd4e5da5Sopenharmony_ci              HasSubstr("The Result Type must be the same as Composite type in "
890fd4e5da5Sopenharmony_ci                        "OpCompositeInsert yielding Result Id 5."));
891fd4e5da5Sopenharmony_ci}
892fd4e5da5Sopenharmony_ci
893fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeInsertNotComposite) {
894fd4e5da5Sopenharmony_ci  const std::string body = R"(
895fd4e5da5Sopenharmony_ci%val1 = OpCompositeInsert %f32 %f32_1 %f32_0 0
896fd4e5da5Sopenharmony_ci)";
897fd4e5da5Sopenharmony_ci
898fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body));
899fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
900fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
901fd4e5da5Sopenharmony_ci              HasSubstr("Reached non-composite type while indexes still remain "
902fd4e5da5Sopenharmony_ci                        "to be traversed."));
903fd4e5da5Sopenharmony_ci}
904fd4e5da5Sopenharmony_ci
905fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeInsertVectorOutOfBounds) {
906fd4e5da5Sopenharmony_ci  const std::string body = R"(
907fd4e5da5Sopenharmony_ci%val1 = OpCompositeInsert %f32vec4 %f32_1 %f32vec4_0123 4
908fd4e5da5Sopenharmony_ci)";
909fd4e5da5Sopenharmony_ci
910fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body));
911fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
912fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
913fd4e5da5Sopenharmony_ci              HasSubstr("Vector access is out of bounds, "
914fd4e5da5Sopenharmony_ci                        "vector size is 4, but access index is 4"));
915fd4e5da5Sopenharmony_ci}
916fd4e5da5Sopenharmony_ci
917fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeInsertMatrixOutOfCols) {
918fd4e5da5Sopenharmony_ci  const std::string body = R"(
919fd4e5da5Sopenharmony_ci%val1 = OpCompositeInsert %f32mat23 %f32_1 %f32mat23_121212 3 1
920fd4e5da5Sopenharmony_ci)";
921fd4e5da5Sopenharmony_ci
922fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body));
923fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
924fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
925fd4e5da5Sopenharmony_ci              HasSubstr("Matrix access is out of bounds, "
926fd4e5da5Sopenharmony_ci                        "matrix has 3 columns, but access index is 3"));
927fd4e5da5Sopenharmony_ci}
928fd4e5da5Sopenharmony_ci
929fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeInsertMatrixOutOfRows) {
930fd4e5da5Sopenharmony_ci  const std::string body = R"(
931fd4e5da5Sopenharmony_ci%val1 = OpCompositeInsert %f32mat23 %f32_1 %f32mat23_121212 2 5
932fd4e5da5Sopenharmony_ci)";
933fd4e5da5Sopenharmony_ci
934fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body));
935fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
936fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
937fd4e5da5Sopenharmony_ci              HasSubstr("Vector access is out of bounds, "
938fd4e5da5Sopenharmony_ci                        "vector size is 2, but access index is 5"));
939fd4e5da5Sopenharmony_ci}
940fd4e5da5Sopenharmony_ci
941fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeInsertArrayOutOfBounds) {
942fd4e5da5Sopenharmony_ci  const std::string body = R"(
943fd4e5da5Sopenharmony_ci%array = OpCompositeConstruct %f32vec2arr3 %f32vec2_12 %f32vec2_12 %f32vec2_12
944fd4e5da5Sopenharmony_ci%val1 = OpCompositeInsert %f32vec2arr3 %f32vec2_01 %array 3
945fd4e5da5Sopenharmony_ci)";
946fd4e5da5Sopenharmony_ci
947fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body));
948fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
949fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
950fd4e5da5Sopenharmony_ci              HasSubstr("Array access is out of bounds, array "
951fd4e5da5Sopenharmony_ci                        "size is 3, but access index is 3"));
952fd4e5da5Sopenharmony_ci}
953fd4e5da5Sopenharmony_ci
954fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeInsertStructOutOfBounds) {
955fd4e5da5Sopenharmony_ci  const std::string body = R"(
956fd4e5da5Sopenharmony_ci%struct = OpLoad %big_struct %var_big_struct
957fd4e5da5Sopenharmony_ci%val1 = OpCompositeInsert %big_struct %f32_1 %struct 6
958fd4e5da5Sopenharmony_ci)";
959fd4e5da5Sopenharmony_ci
960fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body));
961fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
962fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
963fd4e5da5Sopenharmony_ci              HasSubstr("Index is out of bounds, can not find index 6 in the "
964fd4e5da5Sopenharmony_ci                        "structure <id> '37'. This structure has 6 members. "
965fd4e5da5Sopenharmony_ci                        "Largest valid index is 5."));
966fd4e5da5Sopenharmony_ci}
967fd4e5da5Sopenharmony_ci
968fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeInsertNestedVectorOutOfBounds) {
969fd4e5da5Sopenharmony_ci  const std::string body = R"(
970fd4e5da5Sopenharmony_ci%struct = OpLoad %big_struct %var_big_struct
971fd4e5da5Sopenharmony_ci%val1 = OpCompositeInsert %big_struct %f32_1 %struct 3 1 5
972fd4e5da5Sopenharmony_ci)";
973fd4e5da5Sopenharmony_ci
974fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body));
975fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
976fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
977fd4e5da5Sopenharmony_ci              HasSubstr("Vector access is out of bounds, "
978fd4e5da5Sopenharmony_ci                        "vector size is 2, but access index is 5"));
979fd4e5da5Sopenharmony_ci}
980fd4e5da5Sopenharmony_ci
981fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeInsertTooManyIndices) {
982fd4e5da5Sopenharmony_ci  const std::string body = R"(
983fd4e5da5Sopenharmony_ci%struct = OpLoad %big_struct %var_big_struct
984fd4e5da5Sopenharmony_ci%val1 = OpCompositeInsert %big_struct %f32_1 %struct 3 1 1 2
985fd4e5da5Sopenharmony_ci)";
986fd4e5da5Sopenharmony_ci
987fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body));
988fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
989fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
990fd4e5da5Sopenharmony_ci              HasSubstr("Reached non-composite type while indexes still remain "
991fd4e5da5Sopenharmony_ci                        "to be traversed."));
992fd4e5da5Sopenharmony_ci}
993fd4e5da5Sopenharmony_ci
994fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeInsertWrongType1) {
995fd4e5da5Sopenharmony_ci  const std::string body = R"(
996fd4e5da5Sopenharmony_ci%struct = OpLoad %big_struct %var_big_struct
997fd4e5da5Sopenharmony_ci%val1 = OpCompositeInsert %big_struct %f32vec2_01 %struct 3 1 1
998fd4e5da5Sopenharmony_ci)";
999fd4e5da5Sopenharmony_ci
1000fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body));
1001fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1002fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1003fd4e5da5Sopenharmony_ci              HasSubstr("The Object type (OpTypeVector) does not match the "
1004fd4e5da5Sopenharmony_ci                        "type that results from indexing into the Composite "
1005fd4e5da5Sopenharmony_ci                        "(OpTypeFloat)."));
1006fd4e5da5Sopenharmony_ci}
1007fd4e5da5Sopenharmony_ci
1008fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeInsertWrongType2) {
1009fd4e5da5Sopenharmony_ci  const std::string body = R"(
1010fd4e5da5Sopenharmony_ci%struct = OpLoad %big_struct %var_big_struct
1011fd4e5da5Sopenharmony_ci%val1 = OpCompositeInsert %big_struct %f32_1 %struct 3 1
1012fd4e5da5Sopenharmony_ci)";
1013fd4e5da5Sopenharmony_ci
1014fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body));
1015fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1016fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1017fd4e5da5Sopenharmony_ci              HasSubstr("The Object type (OpTypeFloat) does not match the type "
1018fd4e5da5Sopenharmony_ci                        "that results from indexing into the Composite "
1019fd4e5da5Sopenharmony_ci                        "(OpTypeVector)."));
1020fd4e5da5Sopenharmony_ci}
1021fd4e5da5Sopenharmony_ci
1022fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeInsertWrongType3) {
1023fd4e5da5Sopenharmony_ci  const std::string body = R"(
1024fd4e5da5Sopenharmony_ci%struct = OpLoad %big_struct %var_big_struct
1025fd4e5da5Sopenharmony_ci%val1 = OpCompositeInsert %big_struct %f32_1 %struct 2 1
1026fd4e5da5Sopenharmony_ci)";
1027fd4e5da5Sopenharmony_ci
1028fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body));
1029fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1030fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1031fd4e5da5Sopenharmony_ci              HasSubstr("The Object type (OpTypeFloat) does not match the type "
1032fd4e5da5Sopenharmony_ci                        "that results from indexing into the Composite "
1033fd4e5da5Sopenharmony_ci                        "(OpTypeVector)."));
1034fd4e5da5Sopenharmony_ci}
1035fd4e5da5Sopenharmony_ci
1036fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeInsertWrongType4) {
1037fd4e5da5Sopenharmony_ci  const std::string body = R"(
1038fd4e5da5Sopenharmony_ci%struct = OpLoad %big_struct %var_big_struct
1039fd4e5da5Sopenharmony_ci%val1 = OpCompositeInsert %big_struct %f32_1 %struct 4 1
1040fd4e5da5Sopenharmony_ci)";
1041fd4e5da5Sopenharmony_ci
1042fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body));
1043fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1044fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1045fd4e5da5Sopenharmony_ci              HasSubstr("The Object type (OpTypeFloat) does not match the type "
1046fd4e5da5Sopenharmony_ci                        "that results from indexing into the Composite "
1047fd4e5da5Sopenharmony_ci                        "(OpTypeVector)."));
1048fd4e5da5Sopenharmony_ci}
1049fd4e5da5Sopenharmony_ci
1050fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeInsertWrongType5) {
1051fd4e5da5Sopenharmony_ci  const std::string body = R"(
1052fd4e5da5Sopenharmony_ci%struct = OpLoad %big_struct %var_big_struct
1053fd4e5da5Sopenharmony_ci%val1 = OpCompositeInsert %big_struct %f32_1 %struct 5 1
1054fd4e5da5Sopenharmony_ci)";
1055fd4e5da5Sopenharmony_ci
1056fd4e5da5Sopenharmony_ci  CompileSuccessfully(GenerateShaderCode(body));
1057fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1058fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1059fd4e5da5Sopenharmony_ci              HasSubstr("The Object type (OpTypeFloat) does not match the type "
1060fd4e5da5Sopenharmony_ci                        "that results from indexing into the Composite "
1061fd4e5da5Sopenharmony_ci                        "(OpTypeInt)."));
1062fd4e5da5Sopenharmony_ci}
1063fd4e5da5Sopenharmony_ci
1064fd4e5da5Sopenharmony_ci// Tests ported from val_id_test.cpp.
1065fd4e5da5Sopenharmony_ci
1066fd4e5da5Sopenharmony_ci// Valid. Tests both CompositeExtract and CompositeInsert with 255 indexes.
1067fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeExtractInsertLimitsGood) {
1068fd4e5da5Sopenharmony_ci  int depth = 255;
1069fd4e5da5Sopenharmony_ci  std::string header = GetHeaderForTestsFromValId();
1070fd4e5da5Sopenharmony_ci  header.erase(header.find("%func"));
1071fd4e5da5Sopenharmony_ci  std::ostringstream spirv;
1072fd4e5da5Sopenharmony_ci  spirv << header << std::endl;
1073fd4e5da5Sopenharmony_ci
1074fd4e5da5Sopenharmony_ci  // Build nested structures. Struct 'i' contains struct 'i-1'
1075fd4e5da5Sopenharmony_ci  spirv << "%s_depth_1 = OpTypeStruct %float\n";
1076fd4e5da5Sopenharmony_ci  for (int i = 2; i <= depth; ++i) {
1077fd4e5da5Sopenharmony_ci    spirv << "%s_depth_" << i << " = OpTypeStruct %s_depth_" << i - 1 << "\n";
1078fd4e5da5Sopenharmony_ci  }
1079fd4e5da5Sopenharmony_ci
1080fd4e5da5Sopenharmony_ci  // Define Pointer and Variable to use for CompositeExtract/Insert.
1081fd4e5da5Sopenharmony_ci  spirv << "%_ptr_Uniform_deep_struct = OpTypePointer Uniform %s_depth_"
1082fd4e5da5Sopenharmony_ci        << depth << "\n";
1083fd4e5da5Sopenharmony_ci  spirv << "%deep_var = OpVariable %_ptr_Uniform_deep_struct Uniform\n";
1084fd4e5da5Sopenharmony_ci
1085fd4e5da5Sopenharmony_ci  // Function Start
1086fd4e5da5Sopenharmony_ci  spirv << R"(
1087fd4e5da5Sopenharmony_ci  %func = OpFunction %void None %void_f
1088fd4e5da5Sopenharmony_ci  %my_label = OpLabel
1089fd4e5da5Sopenharmony_ci  )";
1090fd4e5da5Sopenharmony_ci
1091fd4e5da5Sopenharmony_ci  // OpCompositeExtract/Insert with 'n' indexes (n = depth)
1092fd4e5da5Sopenharmony_ci  spirv << "%deep = OpLoad %s_depth_" << depth << " %deep_var" << std::endl;
1093fd4e5da5Sopenharmony_ci  spirv << "%entry = OpCompositeExtract  %float %deep";
1094fd4e5da5Sopenharmony_ci  for (int i = 0; i < depth; ++i) {
1095fd4e5da5Sopenharmony_ci    spirv << " 0";
1096fd4e5da5Sopenharmony_ci  }
1097fd4e5da5Sopenharmony_ci  spirv << std::endl;
1098fd4e5da5Sopenharmony_ci  spirv << "%new_composite = OpCompositeInsert %s_depth_" << depth
1099fd4e5da5Sopenharmony_ci        << " %entry %deep";
1100fd4e5da5Sopenharmony_ci  for (int i = 0; i < depth; ++i) {
1101fd4e5da5Sopenharmony_ci    spirv << " 0";
1102fd4e5da5Sopenharmony_ci  }
1103fd4e5da5Sopenharmony_ci  spirv << std::endl;
1104fd4e5da5Sopenharmony_ci
1105fd4e5da5Sopenharmony_ci  // Function end
1106fd4e5da5Sopenharmony_ci  spirv << R"(
1107fd4e5da5Sopenharmony_ci    OpReturn
1108fd4e5da5Sopenharmony_ci    OpFunctionEnd
1109fd4e5da5Sopenharmony_ci  )";
1110fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.str());
1111fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1112fd4e5da5Sopenharmony_ci}
1113fd4e5da5Sopenharmony_ci
1114fd4e5da5Sopenharmony_ci// Invalid: 256 indexes passed to OpCompositeExtract. Limit is 255.
1115fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeExtractArgCountExceededLimitBad) {
1116fd4e5da5Sopenharmony_ci  std::ostringstream spirv;
1117fd4e5da5Sopenharmony_ci  spirv << GetHeaderForTestsFromValId() << std::endl;
1118fd4e5da5Sopenharmony_ci  spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl;
1119fd4e5da5Sopenharmony_ci  spirv << "%entry = OpCompositeExtract %float %matrix";
1120fd4e5da5Sopenharmony_ci  for (int i = 0; i < 256; ++i) {
1121fd4e5da5Sopenharmony_ci    spirv << " 0";
1122fd4e5da5Sopenharmony_ci  }
1123fd4e5da5Sopenharmony_ci  spirv << R"(
1124fd4e5da5Sopenharmony_ci    OpReturn
1125fd4e5da5Sopenharmony_ci    OpFunctionEnd
1126fd4e5da5Sopenharmony_ci  )";
1127fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.str());
1128fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1129fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1130fd4e5da5Sopenharmony_ci              HasSubstr("The number of indexes in OpCompositeExtract may not "
1131fd4e5da5Sopenharmony_ci                        "exceed 255. Found 256 indexes."));
1132fd4e5da5Sopenharmony_ci}
1133fd4e5da5Sopenharmony_ci
1134fd4e5da5Sopenharmony_ci// Invalid: 256 indexes passed to OpCompositeInsert. Limit is 255.
1135fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeInsertArgCountExceededLimitBad) {
1136fd4e5da5Sopenharmony_ci  std::ostringstream spirv;
1137fd4e5da5Sopenharmony_ci  spirv << GetHeaderForTestsFromValId() << std::endl;
1138fd4e5da5Sopenharmony_ci  spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl;
1139fd4e5da5Sopenharmony_ci  spirv << "%new_composite = OpCompositeInsert %mat4x3 %int_0 %matrix";
1140fd4e5da5Sopenharmony_ci  for (int i = 0; i < 256; ++i) {
1141fd4e5da5Sopenharmony_ci    spirv << " 0";
1142fd4e5da5Sopenharmony_ci  }
1143fd4e5da5Sopenharmony_ci  spirv << R"(
1144fd4e5da5Sopenharmony_ci    OpReturn
1145fd4e5da5Sopenharmony_ci    OpFunctionEnd
1146fd4e5da5Sopenharmony_ci  )";
1147fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.str());
1148fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1149fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1150fd4e5da5Sopenharmony_ci              HasSubstr("The number of indexes in OpCompositeInsert may not "
1151fd4e5da5Sopenharmony_ci                        "exceed 255. Found 256 indexes."));
1152fd4e5da5Sopenharmony_ci}
1153fd4e5da5Sopenharmony_ci
1154fd4e5da5Sopenharmony_ci// Invalid: In OpCompositeInsert, result type must be the same as composite type
1155fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeInsertWrongResultTypeBad) {
1156fd4e5da5Sopenharmony_ci  std::ostringstream spirv;
1157fd4e5da5Sopenharmony_ci  spirv << GetHeaderForTestsFromValId() << std::endl;
1158fd4e5da5Sopenharmony_ci  spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl;
1159fd4e5da5Sopenharmony_ci  spirv << "%float_entry = OpCompositeExtract  %float %matrix 0 1" << std::endl;
1160fd4e5da5Sopenharmony_ci  spirv << "%new_composite = OpCompositeInsert %float %float_entry %matrix 0 1"
1161fd4e5da5Sopenharmony_ci        << std::endl;
1162fd4e5da5Sopenharmony_ci  spirv << R"(OpReturn
1163fd4e5da5Sopenharmony_ci              OpFunctionEnd)";
1164fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.str());
1165fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1166fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1167fd4e5da5Sopenharmony_ci              HasSubstr("The Result Type must be the same as Composite type"));
1168fd4e5da5Sopenharmony_ci}
1169fd4e5da5Sopenharmony_ci
1170fd4e5da5Sopenharmony_ci// Invalid: No Indexes were passed to OpCompositeExtract.
1171fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeExtractNoIndices2) {
1172fd4e5da5Sopenharmony_ci  std::ostringstream spirv;
1173fd4e5da5Sopenharmony_ci  spirv << GetHeaderForTestsFromValId() << std::endl;
1174fd4e5da5Sopenharmony_ci  spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl;
1175fd4e5da5Sopenharmony_ci  spirv << "%float_entry = OpCompositeExtract  %mat4x3 %matrix" << std::endl;
1176fd4e5da5Sopenharmony_ci  spirv << R"(OpReturn
1177fd4e5da5Sopenharmony_ci              OpFunctionEnd)";
1178fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.str());
1179fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1180fd4e5da5Sopenharmony_ci  EXPECT_THAT(
1181fd4e5da5Sopenharmony_ci      getDiagnosticString(),
1182fd4e5da5Sopenharmony_ci      HasSubstr(
1183fd4e5da5Sopenharmony_ci          "Expected at least one index to OpCompositeExtract, zero found"));
1184fd4e5da5Sopenharmony_ci}
1185fd4e5da5Sopenharmony_ci
1186fd4e5da5Sopenharmony_ci// Invalid: No Indexes were passed to OpCompositeExtract.
1187fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeExtractNoIndicesWrongResultType) {
1188fd4e5da5Sopenharmony_ci  std::ostringstream spirv;
1189fd4e5da5Sopenharmony_ci  spirv << GetHeaderForTestsFromValId() << std::endl;
1190fd4e5da5Sopenharmony_ci  spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl;
1191fd4e5da5Sopenharmony_ci  spirv << "%float_entry = OpCompositeExtract %float %matrix" << std::endl;
1192fd4e5da5Sopenharmony_ci  spirv << R"(OpReturn
1193fd4e5da5Sopenharmony_ci              OpFunctionEnd)";
1194fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.str());
1195fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1196fd4e5da5Sopenharmony_ci  EXPECT_THAT(
1197fd4e5da5Sopenharmony_ci      getDiagnosticString(),
1198fd4e5da5Sopenharmony_ci      HasSubstr(
1199fd4e5da5Sopenharmony_ci          "Expected at least one index to OpCompositeExtract, zero found"));
1200fd4e5da5Sopenharmony_ci}
1201fd4e5da5Sopenharmony_ci
1202fd4e5da5Sopenharmony_ci// Invalid: No Indices were passed to OpCompositeInsert, and the type of the
1203fd4e5da5Sopenharmony_ci// Object<id> argument matches the Composite type.
1204fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeInsertMissingIndices) {
1205fd4e5da5Sopenharmony_ci  std::ostringstream spirv;
1206fd4e5da5Sopenharmony_ci  spirv << GetHeaderForTestsFromValId() << std::endl;
1207fd4e5da5Sopenharmony_ci  spirv << "%matrix   = OpLoad %mat4x3 %my_matrix" << std::endl;
1208fd4e5da5Sopenharmony_ci  spirv << "%matrix_2 = OpLoad %mat4x3 %my_matrix" << std::endl;
1209fd4e5da5Sopenharmony_ci  spirv << "%new_composite = OpCompositeInsert %mat4x3 %matrix_2 %matrix";
1210fd4e5da5Sopenharmony_ci  spirv << R"(
1211fd4e5da5Sopenharmony_ci              OpReturn
1212fd4e5da5Sopenharmony_ci              OpFunctionEnd)";
1213fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.str());
1214fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1215fd4e5da5Sopenharmony_ci  EXPECT_THAT(
1216fd4e5da5Sopenharmony_ci      getDiagnosticString(),
1217fd4e5da5Sopenharmony_ci      HasSubstr(
1218fd4e5da5Sopenharmony_ci          "Expected at least one index to OpCompositeInsert, zero found"));
1219fd4e5da5Sopenharmony_ci}
1220fd4e5da5Sopenharmony_ci
1221fd4e5da5Sopenharmony_ci// Invalid: No Indices were passed to OpCompositeInsert, but the type of the
1222fd4e5da5Sopenharmony_ci// Object<id> argument does not match the Composite type.
1223fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeInsertMissingIndices2) {
1224fd4e5da5Sopenharmony_ci  std::ostringstream spirv;
1225fd4e5da5Sopenharmony_ci  spirv << GetHeaderForTestsFromValId() << std::endl;
1226fd4e5da5Sopenharmony_ci  spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl;
1227fd4e5da5Sopenharmony_ci  spirv << "%new_composite = OpCompositeInsert %mat4x3 %int_0 %matrix";
1228fd4e5da5Sopenharmony_ci  spirv << R"(
1229fd4e5da5Sopenharmony_ci              OpReturn
1230fd4e5da5Sopenharmony_ci              OpFunctionEnd)";
1231fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.str());
1232fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1233fd4e5da5Sopenharmony_ci  EXPECT_THAT(
1234fd4e5da5Sopenharmony_ci      getDiagnosticString(),
1235fd4e5da5Sopenharmony_ci      HasSubstr(
1236fd4e5da5Sopenharmony_ci          "Expected at least one index to OpCompositeInsert, zero found"));
1237fd4e5da5Sopenharmony_ci}
1238fd4e5da5Sopenharmony_ci
1239fd4e5da5Sopenharmony_ci// Valid: Tests that we can index into Struct, Array, Matrix, and Vector!
1240fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeExtractInsertIndexIntoAllTypesGood) {
1241fd4e5da5Sopenharmony_ci  // indexes that we are passing are: 0, 3, 1, 2, 0
1242fd4e5da5Sopenharmony_ci  // 0 will select the struct_s within the base struct (blockName)
1243fd4e5da5Sopenharmony_ci  // 3 will select the Array that contains 5 matrices
1244fd4e5da5Sopenharmony_ci  // 1 will select the Matrix that is at index 1 of the array
1245fd4e5da5Sopenharmony_ci  // 2 will select the column (which is a vector) within the matrix at index 2
1246fd4e5da5Sopenharmony_ci  // 0 will select the element at the index 0 of the vector. (which is a float).
1247fd4e5da5Sopenharmony_ci  std::ostringstream spirv;
1248fd4e5da5Sopenharmony_ci  spirv << GetHeaderForTestsFromValId() << R"(
1249fd4e5da5Sopenharmony_ci    %myblock = OpLoad %struct_blockName %blockName_var
1250fd4e5da5Sopenharmony_ci    %ss = OpCompositeExtract %struct_s %myblock 0
1251fd4e5da5Sopenharmony_ci    %sa = OpCompositeExtract %array5_mat4x3 %myblock 0 3
1252fd4e5da5Sopenharmony_ci    %sm = OpCompositeExtract %mat4x3 %myblock 0 3 1
1253fd4e5da5Sopenharmony_ci    %sc = OpCompositeExtract %v3float %myblock 0 3 1 2
1254fd4e5da5Sopenharmony_ci    %fl = OpCompositeExtract %float %myblock 0 3 1 2 0
1255fd4e5da5Sopenharmony_ci    ;
1256fd4e5da5Sopenharmony_ci    ; Now let's insert back at different levels...
1257fd4e5da5Sopenharmony_ci    ;
1258fd4e5da5Sopenharmony_ci    %b1 = OpCompositeInsert %struct_blockName %ss %myblock 0
1259fd4e5da5Sopenharmony_ci    %b2 = OpCompositeInsert %struct_blockName %sa %myblock 0 3
1260fd4e5da5Sopenharmony_ci    %b3 = OpCompositeInsert %struct_blockName %sm %myblock 0 3 1
1261fd4e5da5Sopenharmony_ci    %b4 = OpCompositeInsert %struct_blockName %sc %myblock 0 3 1 2
1262fd4e5da5Sopenharmony_ci    %b5 = OpCompositeInsert %struct_blockName %fl %myblock 0 3 1 2 0
1263fd4e5da5Sopenharmony_ci    OpReturn
1264fd4e5da5Sopenharmony_ci    OpFunctionEnd
1265fd4e5da5Sopenharmony_ci  )";
1266fd4e5da5Sopenharmony_ci
1267fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.str());
1268fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1269fd4e5da5Sopenharmony_ci}
1270fd4e5da5Sopenharmony_ci
1271fd4e5da5Sopenharmony_ci// Invalid. More indexes are provided than needed for OpCompositeExtract.
1272fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeExtractReachedScalarBad) {
1273fd4e5da5Sopenharmony_ci  // indexes that we are passing are: 0, 3, 1, 2, 0
1274fd4e5da5Sopenharmony_ci  // 0 will select the struct_s within the base struct (blockName)
1275fd4e5da5Sopenharmony_ci  // 3 will select the Array that contains 5 matrices
1276fd4e5da5Sopenharmony_ci  // 1 will select the Matrix that is at index 1 of the array
1277fd4e5da5Sopenharmony_ci  // 2 will select the column (which is a vector) within the matrix at index 2
1278fd4e5da5Sopenharmony_ci  // 0 will select the element at the index 0 of the vector. (which is a float).
1279fd4e5da5Sopenharmony_ci  std::ostringstream spirv;
1280fd4e5da5Sopenharmony_ci  spirv << GetHeaderForTestsFromValId() << R"(
1281fd4e5da5Sopenharmony_ci    %myblock = OpLoad %struct_blockName %blockName_var
1282fd4e5da5Sopenharmony_ci    %fl = OpCompositeExtract %float %myblock 0 3 1 2 0 1
1283fd4e5da5Sopenharmony_ci    OpReturn
1284fd4e5da5Sopenharmony_ci    OpFunctionEnd
1285fd4e5da5Sopenharmony_ci  )";
1286fd4e5da5Sopenharmony_ci
1287fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.str());
1288fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1289fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1290fd4e5da5Sopenharmony_ci              HasSubstr("Reached non-composite type while indexes still remain "
1291fd4e5da5Sopenharmony_ci                        "to be traversed."));
1292fd4e5da5Sopenharmony_ci}
1293fd4e5da5Sopenharmony_ci
1294fd4e5da5Sopenharmony_ci// Invalid. More indexes are provided than needed for OpCompositeInsert.
1295fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeInsertReachedScalarBad) {
1296fd4e5da5Sopenharmony_ci  // indexes that we are passing are: 0, 3, 1, 2, 0
1297fd4e5da5Sopenharmony_ci  // 0 will select the struct_s within the base struct (blockName)
1298fd4e5da5Sopenharmony_ci  // 3 will select the Array that contains 5 matrices
1299fd4e5da5Sopenharmony_ci  // 1 will select the Matrix that is at index 1 of the array
1300fd4e5da5Sopenharmony_ci  // 2 will select the column (which is a vector) within the matrix at index 2
1301fd4e5da5Sopenharmony_ci  // 0 will select the element at the index 0 of the vector. (which is a float).
1302fd4e5da5Sopenharmony_ci  std::ostringstream spirv;
1303fd4e5da5Sopenharmony_ci  spirv << GetHeaderForTestsFromValId() << R"(
1304fd4e5da5Sopenharmony_ci    %myblock = OpLoad %struct_blockName %blockName_var
1305fd4e5da5Sopenharmony_ci    %fl = OpCompositeExtract %float %myblock 0 3 1 2 0
1306fd4e5da5Sopenharmony_ci    %b5 = OpCompositeInsert %struct_blockName %fl %myblock 0 3 1 2 0 1
1307fd4e5da5Sopenharmony_ci    OpReturn
1308fd4e5da5Sopenharmony_ci    OpFunctionEnd
1309fd4e5da5Sopenharmony_ci  )";
1310fd4e5da5Sopenharmony_ci
1311fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.str());
1312fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1313fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1314fd4e5da5Sopenharmony_ci              HasSubstr("Reached non-composite type while indexes still remain "
1315fd4e5da5Sopenharmony_ci                        "to be traversed."));
1316fd4e5da5Sopenharmony_ci}
1317fd4e5da5Sopenharmony_ci
1318fd4e5da5Sopenharmony_ci// Invalid. Result type doesn't match the type we get from indexing into
1319fd4e5da5Sopenharmony_ci// the composite.
1320fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites,
1321fd4e5da5Sopenharmony_ci       CompositeExtractResultTypeDoesntMatchIndexedTypeBad) {
1322fd4e5da5Sopenharmony_ci  // indexes that we are passing are: 0, 3, 1, 2, 0
1323fd4e5da5Sopenharmony_ci  // 0 will select the struct_s within the base struct (blockName)
1324fd4e5da5Sopenharmony_ci  // 3 will select the Array that contains 5 matrices
1325fd4e5da5Sopenharmony_ci  // 1 will select the Matrix that is at index 1 of the array
1326fd4e5da5Sopenharmony_ci  // 2 will select the column (which is a vector) within the matrix at index 2
1327fd4e5da5Sopenharmony_ci  // 0 will select the element at the index 0 of the vector. (which is a float).
1328fd4e5da5Sopenharmony_ci  std::ostringstream spirv;
1329fd4e5da5Sopenharmony_ci  spirv << GetHeaderForTestsFromValId() << R"(
1330fd4e5da5Sopenharmony_ci    %myblock = OpLoad %struct_blockName %blockName_var
1331fd4e5da5Sopenharmony_ci    %fl = OpCompositeExtract %int %myblock 0 3 1 2 0
1332fd4e5da5Sopenharmony_ci    OpReturn
1333fd4e5da5Sopenharmony_ci    OpFunctionEnd
1334fd4e5da5Sopenharmony_ci  )";
1335fd4e5da5Sopenharmony_ci
1336fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.str());
1337fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1338fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1339fd4e5da5Sopenharmony_ci              HasSubstr("Result type (OpTypeInt) does not match the type that "
1340fd4e5da5Sopenharmony_ci                        "results from indexing into the composite "
1341fd4e5da5Sopenharmony_ci                        "(OpTypeFloat)."));
1342fd4e5da5Sopenharmony_ci}
1343fd4e5da5Sopenharmony_ci
1344fd4e5da5Sopenharmony_ci// Invalid. Given object type doesn't match the type we get from indexing into
1345fd4e5da5Sopenharmony_ci// the composite.
1346fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeInsertObjectTypeDoesntMatchIndexedTypeBad) {
1347fd4e5da5Sopenharmony_ci  // indexes that we are passing are: 0, 3, 1, 2, 0
1348fd4e5da5Sopenharmony_ci  // 0 will select the struct_s within the base struct (blockName)
1349fd4e5da5Sopenharmony_ci  // 3 will select the Array that contains 5 matrices
1350fd4e5da5Sopenharmony_ci  // 1 will select the Matrix that is at index 1 of the array
1351fd4e5da5Sopenharmony_ci  // 2 will select the column (which is a vector) within the matrix at index 2
1352fd4e5da5Sopenharmony_ci  // 0 will select the element at the index 0 of the vector. (which is a float).
1353fd4e5da5Sopenharmony_ci  // We are trying to insert an integer where we should be inserting a float.
1354fd4e5da5Sopenharmony_ci  std::ostringstream spirv;
1355fd4e5da5Sopenharmony_ci  spirv << GetHeaderForTestsFromValId() << R"(
1356fd4e5da5Sopenharmony_ci    %myblock = OpLoad %struct_blockName %blockName_var
1357fd4e5da5Sopenharmony_ci    %b5 = OpCompositeInsert %struct_blockName %int_0 %myblock 0 3 1 2 0
1358fd4e5da5Sopenharmony_ci    OpReturn
1359fd4e5da5Sopenharmony_ci    OpFunctionEnd
1360fd4e5da5Sopenharmony_ci  )";
1361fd4e5da5Sopenharmony_ci
1362fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.str());
1363fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1364fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1365fd4e5da5Sopenharmony_ci              HasSubstr("The Object type (OpTypeInt) does not match the type "
1366fd4e5da5Sopenharmony_ci                        "that results from indexing into the Composite "
1367fd4e5da5Sopenharmony_ci                        "(OpTypeFloat)."));
1368fd4e5da5Sopenharmony_ci}
1369fd4e5da5Sopenharmony_ci
1370fd4e5da5Sopenharmony_ci// Invalid. Index into a struct is larger than the number of struct members.
1371fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeExtractStructIndexOutOfBoundBad) {
1372fd4e5da5Sopenharmony_ci  // struct_blockName has 3 members (index 0,1,2). We'll try to access index 3.
1373fd4e5da5Sopenharmony_ci  std::ostringstream spirv;
1374fd4e5da5Sopenharmony_ci  spirv << GetHeaderForTestsFromValId() << R"(
1375fd4e5da5Sopenharmony_ci    %myblock = OpLoad %struct_blockName %blockName_var
1376fd4e5da5Sopenharmony_ci    %ss = OpCompositeExtract %struct_s %myblock 3
1377fd4e5da5Sopenharmony_ci    OpReturn
1378fd4e5da5Sopenharmony_ci    OpFunctionEnd
1379fd4e5da5Sopenharmony_ci  )";
1380fd4e5da5Sopenharmony_ci
1381fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.str());
1382fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1383fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1384fd4e5da5Sopenharmony_ci              HasSubstr("Index is out of bounds, can not find index 3 in the "
1385fd4e5da5Sopenharmony_ci                        "structure <id> '25'. This structure has 2 members. "
1386fd4e5da5Sopenharmony_ci                        "Largest valid index is 1."));
1387fd4e5da5Sopenharmony_ci}
1388fd4e5da5Sopenharmony_ci
1389fd4e5da5Sopenharmony_ci// Invalid. Index into a struct is larger than the number of struct members.
1390fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeInsertStructIndexOutOfBoundBad) {
1391fd4e5da5Sopenharmony_ci  // struct_blockName has 3 members (index 0,1,2). We'll try to access index 3.
1392fd4e5da5Sopenharmony_ci  std::ostringstream spirv;
1393fd4e5da5Sopenharmony_ci  spirv << GetHeaderForTestsFromValId() << R"(
1394fd4e5da5Sopenharmony_ci    %myblock = OpLoad %struct_blockName %blockName_var
1395fd4e5da5Sopenharmony_ci    %ss = OpCompositeExtract %struct_s %myblock 0
1396fd4e5da5Sopenharmony_ci    %new_composite = OpCompositeInsert %struct_blockName %ss %myblock 3
1397fd4e5da5Sopenharmony_ci    OpReturn
1398fd4e5da5Sopenharmony_ci    OpFunctionEnd
1399fd4e5da5Sopenharmony_ci  )";
1400fd4e5da5Sopenharmony_ci
1401fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.str());
1402fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1403fd4e5da5Sopenharmony_ci  EXPECT_THAT(
1404fd4e5da5Sopenharmony_ci      getDiagnosticString(),
1405fd4e5da5Sopenharmony_ci      HasSubstr("Index is out of bounds, can not find index 3 in the structure "
1406fd4e5da5Sopenharmony_ci                "<id> '25'. This structure has 2 members. Largest valid index "
1407fd4e5da5Sopenharmony_ci                "is 1."));
1408fd4e5da5Sopenharmony_ci}
1409fd4e5da5Sopenharmony_ci
1410fd4e5da5Sopenharmony_ci// #1403: Ensure that the default spec constant value is not used to check the
1411fd4e5da5Sopenharmony_ci// extract index.
1412fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, ExtractFromSpecConstantSizedArray) {
1413fd4e5da5Sopenharmony_ci  std::string spirv = R"(
1414fd4e5da5Sopenharmony_ciOpCapability Kernel
1415fd4e5da5Sopenharmony_ciOpCapability Linkage
1416fd4e5da5Sopenharmony_ciOpMemoryModel Logical OpenCL
1417fd4e5da5Sopenharmony_ciOpDecorate %spec_const SpecId 1
1418fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1419fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
1420fd4e5da5Sopenharmony_ci%spec_const = OpSpecConstant %uint 3
1421fd4e5da5Sopenharmony_ci%uint_array = OpTypeArray %uint %spec_const
1422fd4e5da5Sopenharmony_ci%undef = OpUndef %uint_array
1423fd4e5da5Sopenharmony_ci%voidf = OpTypeFunction %void
1424fd4e5da5Sopenharmony_ci%func = OpFunction %void None %voidf
1425fd4e5da5Sopenharmony_ci%1 = OpLabel
1426fd4e5da5Sopenharmony_ci%2 = OpCompositeExtract %uint %undef 4
1427fd4e5da5Sopenharmony_ciOpReturn
1428fd4e5da5Sopenharmony_ciOpFunctionEnd
1429fd4e5da5Sopenharmony_ci)";
1430fd4e5da5Sopenharmony_ci
1431fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
1432fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1433fd4e5da5Sopenharmony_ci}
1434fd4e5da5Sopenharmony_ci
1435fd4e5da5Sopenharmony_ci// #1403: Ensure that spec constant ops do not produce false positives.
1436fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, ExtractFromSpecConstantOpSizedArray) {
1437fd4e5da5Sopenharmony_ci  std::string spirv = R"(
1438fd4e5da5Sopenharmony_ciOpCapability Kernel
1439fd4e5da5Sopenharmony_ciOpCapability Linkage
1440fd4e5da5Sopenharmony_ciOpMemoryModel Logical OpenCL
1441fd4e5da5Sopenharmony_ciOpDecorate %spec_const SpecId 1
1442fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1443fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
1444fd4e5da5Sopenharmony_ci%const = OpConstant %uint 1
1445fd4e5da5Sopenharmony_ci%spec_const = OpSpecConstant %uint 3
1446fd4e5da5Sopenharmony_ci%spec_const_op = OpSpecConstantOp %uint IAdd %spec_const %const
1447fd4e5da5Sopenharmony_ci%uint_array = OpTypeArray %uint %spec_const_op
1448fd4e5da5Sopenharmony_ci%undef = OpUndef %uint_array
1449fd4e5da5Sopenharmony_ci%voidf = OpTypeFunction %void
1450fd4e5da5Sopenharmony_ci%func = OpFunction %void None %voidf
1451fd4e5da5Sopenharmony_ci%1 = OpLabel
1452fd4e5da5Sopenharmony_ci%2 = OpCompositeExtract %uint %undef 4
1453fd4e5da5Sopenharmony_ciOpReturn
1454fd4e5da5Sopenharmony_ciOpFunctionEnd
1455fd4e5da5Sopenharmony_ci)";
1456fd4e5da5Sopenharmony_ci
1457fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
1458fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1459fd4e5da5Sopenharmony_ci}
1460fd4e5da5Sopenharmony_ci
1461fd4e5da5Sopenharmony_ci// #1403: Ensure that the default spec constant value is not used to check the
1462fd4e5da5Sopenharmony_ci// size of the array for a composite construct. This code has limited actual
1463fd4e5da5Sopenharmony_ci// value as it is incorrect unless the specialization constant is assigned the
1464fd4e5da5Sopenharmony_ci// value of 2, but it is still a valid module.
1465fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CompositeConstructSpecConstantSizedArray) {
1466fd4e5da5Sopenharmony_ci  std::string spirv = R"(
1467fd4e5da5Sopenharmony_ciOpCapability Kernel
1468fd4e5da5Sopenharmony_ciOpCapability Linkage
1469fd4e5da5Sopenharmony_ciOpMemoryModel Logical OpenCL
1470fd4e5da5Sopenharmony_ciOpDecorate %spec_const SpecId 1
1471fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1472fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
1473fd4e5da5Sopenharmony_ci%uint_0 = OpConstant %uint 0
1474fd4e5da5Sopenharmony_ci%spec_const = OpSpecConstant %uint 3
1475fd4e5da5Sopenharmony_ci%uint_array = OpTypeArray %uint %spec_const
1476fd4e5da5Sopenharmony_ci%voidf = OpTypeFunction %void
1477fd4e5da5Sopenharmony_ci%func = OpFunction %void None %voidf
1478fd4e5da5Sopenharmony_ci%1 = OpLabel
1479fd4e5da5Sopenharmony_ci%2 = OpCompositeConstruct %uint_array %uint_0 %uint_0
1480fd4e5da5Sopenharmony_ciOpReturn
1481fd4e5da5Sopenharmony_ciOpFunctionEnd
1482fd4e5da5Sopenharmony_ci)";
1483fd4e5da5Sopenharmony_ci
1484fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
1485fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1486fd4e5da5Sopenharmony_ci}
1487fd4e5da5Sopenharmony_ci
1488fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CoopMatConstantCompositeMismatchFail) {
1489fd4e5da5Sopenharmony_ci  const std::string body = R"(
1490fd4e5da5Sopenharmony_ciOpCapability Shader
1491fd4e5da5Sopenharmony_ciOpCapability Float16
1492fd4e5da5Sopenharmony_ciOpCapability CooperativeMatrixNV
1493fd4e5da5Sopenharmony_ciOpExtension "SPV_NV_cooperative_matrix"
1494fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1495fd4e5da5Sopenharmony_ciOpEntryPoint GLCompute %main "main"
1496fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1497fd4e5da5Sopenharmony_ci%func = OpTypeFunction %void
1498fd4e5da5Sopenharmony_ci%bool = OpTypeBool
1499fd4e5da5Sopenharmony_ci%f16 = OpTypeFloat 16
1500fd4e5da5Sopenharmony_ci%f32 = OpTypeFloat 32
1501fd4e5da5Sopenharmony_ci%u32 = OpTypeInt 32 0
1502fd4e5da5Sopenharmony_ci
1503fd4e5da5Sopenharmony_ci%u32_8 = OpConstant %u32 8
1504fd4e5da5Sopenharmony_ci%subgroup = OpConstant %u32 3
1505fd4e5da5Sopenharmony_ci
1506fd4e5da5Sopenharmony_ci%f16mat = OpTypeCooperativeMatrixNV %f16 %subgroup %u32_8 %u32_8
1507fd4e5da5Sopenharmony_ci
1508fd4e5da5Sopenharmony_ci%f32_1 = OpConstant %f32 1
1509fd4e5da5Sopenharmony_ci
1510fd4e5da5Sopenharmony_ci%f16mat_1 = OpConstantComposite %f16mat %f32_1
1511fd4e5da5Sopenharmony_ci
1512fd4e5da5Sopenharmony_ci%main = OpFunction %void None %func
1513fd4e5da5Sopenharmony_ci%main_entry = OpLabel
1514fd4e5da5Sopenharmony_ci
1515fd4e5da5Sopenharmony_ciOpReturn
1516fd4e5da5Sopenharmony_ciOpFunctionEnd)";
1517fd4e5da5Sopenharmony_ci
1518fd4e5da5Sopenharmony_ci  CompileSuccessfully(body.c_str());
1519fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1520fd4e5da5Sopenharmony_ci  EXPECT_THAT(
1521fd4e5da5Sopenharmony_ci      getDiagnosticString(),
1522fd4e5da5Sopenharmony_ci      HasSubstr("OpConstantComposite Constituent <id> '11[%float_1]' type does "
1523fd4e5da5Sopenharmony_ci                "not match the Result Type <id> '10[%10]'s component type."));
1524fd4e5da5Sopenharmony_ci}
1525fd4e5da5Sopenharmony_ci
1526fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CoopMatCompositeConstructMismatchFail) {
1527fd4e5da5Sopenharmony_ci  const std::string body = R"(
1528fd4e5da5Sopenharmony_ciOpCapability Shader
1529fd4e5da5Sopenharmony_ciOpCapability Float16
1530fd4e5da5Sopenharmony_ciOpCapability CooperativeMatrixNV
1531fd4e5da5Sopenharmony_ciOpExtension "SPV_NV_cooperative_matrix"
1532fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1533fd4e5da5Sopenharmony_ciOpEntryPoint GLCompute %main "main"
1534fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1535fd4e5da5Sopenharmony_ci%func = OpTypeFunction %void
1536fd4e5da5Sopenharmony_ci%bool = OpTypeBool
1537fd4e5da5Sopenharmony_ci%f16 = OpTypeFloat 16
1538fd4e5da5Sopenharmony_ci%f32 = OpTypeFloat 32
1539fd4e5da5Sopenharmony_ci%u32 = OpTypeInt 32 0
1540fd4e5da5Sopenharmony_ci
1541fd4e5da5Sopenharmony_ci%u32_8 = OpConstant %u32 8
1542fd4e5da5Sopenharmony_ci%subgroup = OpConstant %u32 3
1543fd4e5da5Sopenharmony_ci
1544fd4e5da5Sopenharmony_ci%f16mat = OpTypeCooperativeMatrixNV %f16 %subgroup %u32_8 %u32_8
1545fd4e5da5Sopenharmony_ci
1546fd4e5da5Sopenharmony_ci%f32_1 = OpConstant %f32 1
1547fd4e5da5Sopenharmony_ci
1548fd4e5da5Sopenharmony_ci%main = OpFunction %void None %func
1549fd4e5da5Sopenharmony_ci%main_entry = OpLabel
1550fd4e5da5Sopenharmony_ci
1551fd4e5da5Sopenharmony_ci%f16mat_1 = OpCompositeConstruct %f16mat %f32_1
1552fd4e5da5Sopenharmony_ci
1553fd4e5da5Sopenharmony_ciOpReturn
1554fd4e5da5Sopenharmony_ciOpFunctionEnd)";
1555fd4e5da5Sopenharmony_ci
1556fd4e5da5Sopenharmony_ci  CompileSuccessfully(body.c_str());
1557fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1558fd4e5da5Sopenharmony_ci  EXPECT_THAT(
1559fd4e5da5Sopenharmony_ci      getDiagnosticString(),
1560fd4e5da5Sopenharmony_ci      HasSubstr("Expected Constituent type to be equal to the component type"));
1561fd4e5da5Sopenharmony_ci}
1562fd4e5da5Sopenharmony_ci
1563fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CoopMatKHRConstantCompositeMismatchFail) {
1564fd4e5da5Sopenharmony_ci  const std::string body = R"(
1565fd4e5da5Sopenharmony_ciOpCapability Shader
1566fd4e5da5Sopenharmony_ciOpCapability Float16
1567fd4e5da5Sopenharmony_ciOpCapability CooperativeMatrixKHR
1568fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_cooperative_matrix"
1569fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_vulkan_memory_model"
1570fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1571fd4e5da5Sopenharmony_ciOpEntryPoint GLCompute %main "main"
1572fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1573fd4e5da5Sopenharmony_ci%func = OpTypeFunction %void
1574fd4e5da5Sopenharmony_ci%bool = OpTypeBool
1575fd4e5da5Sopenharmony_ci%f16 = OpTypeFloat 16
1576fd4e5da5Sopenharmony_ci%f32 = OpTypeFloat 32
1577fd4e5da5Sopenharmony_ci%u32 = OpTypeInt 32 0
1578fd4e5da5Sopenharmony_ci
1579fd4e5da5Sopenharmony_ci%u32_16 = OpConstant %u32 16
1580fd4e5da5Sopenharmony_ci%useA = OpConstant %u32 0
1581fd4e5da5Sopenharmony_ci%subgroup = OpConstant %u32 3
1582fd4e5da5Sopenharmony_ci
1583fd4e5da5Sopenharmony_ci%f16mat = OpTypeCooperativeMatrixKHR %f16 %subgroup %u32_16 %u32_16 %useA
1584fd4e5da5Sopenharmony_ci
1585fd4e5da5Sopenharmony_ci%f32_1 = OpConstant %f32 1
1586fd4e5da5Sopenharmony_ci
1587fd4e5da5Sopenharmony_ci%f16mat_1 = OpConstantComposite %f16mat %f32_1
1588fd4e5da5Sopenharmony_ci
1589fd4e5da5Sopenharmony_ci%main = OpFunction %void None %func
1590fd4e5da5Sopenharmony_ci%main_entry = OpLabel
1591fd4e5da5Sopenharmony_ci
1592fd4e5da5Sopenharmony_ciOpReturn
1593fd4e5da5Sopenharmony_ciOpFunctionEnd)";
1594fd4e5da5Sopenharmony_ci
1595fd4e5da5Sopenharmony_ci  CompileSuccessfully(body.c_str());
1596fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1597fd4e5da5Sopenharmony_ci  EXPECT_THAT(
1598fd4e5da5Sopenharmony_ci      getDiagnosticString(),
1599fd4e5da5Sopenharmony_ci      HasSubstr(
1600fd4e5da5Sopenharmony_ci          "OpConstantComposite Constituent <id> '12[%float_1]' type "
1601fd4e5da5Sopenharmony_ci          "does not match the Result Type <id> '11[%11]'s component type."));
1602fd4e5da5Sopenharmony_ci}
1603fd4e5da5Sopenharmony_ci
1604fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CoopMatKHRCompositeConstructMismatchFail) {
1605fd4e5da5Sopenharmony_ci  const std::string body = R"(
1606fd4e5da5Sopenharmony_ciOpCapability Shader
1607fd4e5da5Sopenharmony_ciOpCapability Float16
1608fd4e5da5Sopenharmony_ciOpCapability CooperativeMatrixKHR
1609fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_cooperative_matrix"
1610fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_vulkan_memory_model"
1611fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1612fd4e5da5Sopenharmony_ciOpEntryPoint GLCompute %main "main"
1613fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1614fd4e5da5Sopenharmony_ci%func = OpTypeFunction %void
1615fd4e5da5Sopenharmony_ci%bool = OpTypeBool
1616fd4e5da5Sopenharmony_ci%f16 = OpTypeFloat 16
1617fd4e5da5Sopenharmony_ci%f32 = OpTypeFloat 32
1618fd4e5da5Sopenharmony_ci%u32 = OpTypeInt 32 0
1619fd4e5da5Sopenharmony_ci
1620fd4e5da5Sopenharmony_ci%u32_16 = OpConstant %u32 16
1621fd4e5da5Sopenharmony_ci%useA = OpConstant %u32 0
1622fd4e5da5Sopenharmony_ci%subgroup = OpConstant %u32 3
1623fd4e5da5Sopenharmony_ci
1624fd4e5da5Sopenharmony_ci%f16mat = OpTypeCooperativeMatrixKHR %f16 %subgroup %u32_16 %u32_16 %useA
1625fd4e5da5Sopenharmony_ci
1626fd4e5da5Sopenharmony_ci%f32_1 = OpConstant %f32 1
1627fd4e5da5Sopenharmony_ci
1628fd4e5da5Sopenharmony_ci%main = OpFunction %void None %func
1629fd4e5da5Sopenharmony_ci%main_entry = OpLabel
1630fd4e5da5Sopenharmony_ci
1631fd4e5da5Sopenharmony_ci%f16mat_1 = OpCompositeConstruct %f16mat %f32_1
1632fd4e5da5Sopenharmony_ci
1633fd4e5da5Sopenharmony_ciOpReturn
1634fd4e5da5Sopenharmony_ciOpFunctionEnd)";
1635fd4e5da5Sopenharmony_ci
1636fd4e5da5Sopenharmony_ci  CompileSuccessfully(body.c_str());
1637fd4e5da5Sopenharmony_ci  ASSERT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1638fd4e5da5Sopenharmony_ci  EXPECT_THAT(
1639fd4e5da5Sopenharmony_ci      getDiagnosticString(),
1640fd4e5da5Sopenharmony_ci      HasSubstr("Expected Constituent type to be equal to the component type"));
1641fd4e5da5Sopenharmony_ci}
1642fd4e5da5Sopenharmony_ci
1643fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, ExtractDynamicLabelIndex) {
1644fd4e5da5Sopenharmony_ci  const std::string spirv = R"(
1645fd4e5da5Sopenharmony_ciOpCapability Shader
1646fd4e5da5Sopenharmony_ciOpCapability Linkage
1647fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1648fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1649fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
1650fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
1651fd4e5da5Sopenharmony_ci%void_fn = OpTypeFunction %void
1652fd4e5da5Sopenharmony_ci%float_0 = OpConstant %float 0
1653fd4e5da5Sopenharmony_ci%v4float_0 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
1654fd4e5da5Sopenharmony_ci%func = OpFunction %void None %void_fn
1655fd4e5da5Sopenharmony_ci%1 = OpLabel
1656fd4e5da5Sopenharmony_ci%ex = OpVectorExtractDynamic %float %v4float_0 %v4float_0
1657fd4e5da5Sopenharmony_ciOpReturn
1658fd4e5da5Sopenharmony_ciOpFunctionEnd
1659fd4e5da5Sopenharmony_ci)";
1660fd4e5da5Sopenharmony_ci
1661fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
1662fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
1663fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1664fd4e5da5Sopenharmony_ci              HasSubstr("Expected Index to be int scalar"));
1665fd4e5da5Sopenharmony_ci}
1666fd4e5da5Sopenharmony_ci
1667fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CopyLogicalSameType) {
1668fd4e5da5Sopenharmony_ci  const std::string spirv = R"(
1669fd4e5da5Sopenharmony_ciOpCapability Shader
1670fd4e5da5Sopenharmony_ciOpCapability Linkage
1671fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1672fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1673fd4e5da5Sopenharmony_ci%struct = OpTypeStruct
1674fd4e5da5Sopenharmony_ci%const_struct = OpConstantComposite %struct
1675fd4e5da5Sopenharmony_ci%void_fn = OpTypeFunction %void
1676fd4e5da5Sopenharmony_ci%func = OpFunction %void None %void_fn
1677fd4e5da5Sopenharmony_ci%1 = OpLabel
1678fd4e5da5Sopenharmony_ci%copy = OpCopyLogical %struct %const_struct
1679fd4e5da5Sopenharmony_ciOpReturn
1680fd4e5da5Sopenharmony_ciOpFunctionEnd
1681fd4e5da5Sopenharmony_ci)";
1682fd4e5da5Sopenharmony_ci
1683fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
1684fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
1685fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1686fd4e5da5Sopenharmony_ci              HasSubstr("Result Type must not equal the Operand type"));
1687fd4e5da5Sopenharmony_ci}
1688fd4e5da5Sopenharmony_ci
1689fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CopyLogicalSameStructDifferentId) {
1690fd4e5da5Sopenharmony_ci  const std::string spirv = R"(
1691fd4e5da5Sopenharmony_ciOpCapability Shader
1692fd4e5da5Sopenharmony_ciOpCapability Linkage
1693fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1694fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1695fd4e5da5Sopenharmony_ci%struct1 = OpTypeStruct
1696fd4e5da5Sopenharmony_ci%struct2 = OpTypeStruct
1697fd4e5da5Sopenharmony_ci%const_struct = OpConstantComposite %struct1
1698fd4e5da5Sopenharmony_ci%void_fn = OpTypeFunction %void
1699fd4e5da5Sopenharmony_ci%func = OpFunction %void None %void_fn
1700fd4e5da5Sopenharmony_ci%1 = OpLabel
1701fd4e5da5Sopenharmony_ci%copy = OpCopyLogical %struct2 %const_struct
1702fd4e5da5Sopenharmony_ciOpReturn
1703fd4e5da5Sopenharmony_ciOpFunctionEnd
1704fd4e5da5Sopenharmony_ci)";
1705fd4e5da5Sopenharmony_ci
1706fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
1707fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
1708fd4e5da5Sopenharmony_ci}
1709fd4e5da5Sopenharmony_ci
1710fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CopyLogicalArrayDifferentLength) {
1711fd4e5da5Sopenharmony_ci  const std::string spirv = R"(
1712fd4e5da5Sopenharmony_ciOpCapability Shader
1713fd4e5da5Sopenharmony_ciOpCapability Linkage
1714fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1715fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1716fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
1717fd4e5da5Sopenharmony_ci%int_4 = OpConstant %int 4
1718fd4e5da5Sopenharmony_ci%int_5 = OpConstant %int 5
1719fd4e5da5Sopenharmony_ci%array1 = OpTypeArray %int %int_4
1720fd4e5da5Sopenharmony_ci%array2 = OpTypeArray %int %int_5
1721fd4e5da5Sopenharmony_ci%const_array = OpConstantComposite %array1 %int_4 %int_4 %int_4 %int_4
1722fd4e5da5Sopenharmony_ci%void_fn = OpTypeFunction %void
1723fd4e5da5Sopenharmony_ci%func = OpFunction %void None %void_fn
1724fd4e5da5Sopenharmony_ci%1 = OpLabel
1725fd4e5da5Sopenharmony_ci%copy = OpCopyLogical %array2 %const_array
1726fd4e5da5Sopenharmony_ciOpReturn
1727fd4e5da5Sopenharmony_ciOpFunctionEnd
1728fd4e5da5Sopenharmony_ci)";
1729fd4e5da5Sopenharmony_ci
1730fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
1731fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
1732fd4e5da5Sopenharmony_ci  EXPECT_THAT(
1733fd4e5da5Sopenharmony_ci      getDiagnosticString(),
1734fd4e5da5Sopenharmony_ci      HasSubstr("Result Type does not logically match the Operand type"));
1735fd4e5da5Sopenharmony_ci}
1736fd4e5da5Sopenharmony_ci
1737fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CopyLogicalArrayDifferentElement) {
1738fd4e5da5Sopenharmony_ci  const std::string spirv = R"(
1739fd4e5da5Sopenharmony_ciOpCapability Shader
1740fd4e5da5Sopenharmony_ciOpCapability Linkage
1741fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1742fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1743fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
1744fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
1745fd4e5da5Sopenharmony_ci%int_4 = OpConstant %int 4
1746fd4e5da5Sopenharmony_ci%array1 = OpTypeArray %int %int_4
1747fd4e5da5Sopenharmony_ci%array2 = OpTypeArray %float %int_4
1748fd4e5da5Sopenharmony_ci%const_array = OpConstantComposite %array1 %int_4 %int_4 %int_4 %int_4
1749fd4e5da5Sopenharmony_ci%void_fn = OpTypeFunction %void
1750fd4e5da5Sopenharmony_ci%func = OpFunction %void None %void_fn
1751fd4e5da5Sopenharmony_ci%1 = OpLabel
1752fd4e5da5Sopenharmony_ci%copy = OpCopyLogical %array2 %const_array
1753fd4e5da5Sopenharmony_ciOpReturn
1754fd4e5da5Sopenharmony_ciOpFunctionEnd
1755fd4e5da5Sopenharmony_ci)";
1756fd4e5da5Sopenharmony_ci
1757fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
1758fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
1759fd4e5da5Sopenharmony_ci  EXPECT_THAT(
1760fd4e5da5Sopenharmony_ci      getDiagnosticString(),
1761fd4e5da5Sopenharmony_ci      HasSubstr("Result Type does not logically match the Operand type"));
1762fd4e5da5Sopenharmony_ci}
1763fd4e5da5Sopenharmony_ci
1764fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CopyLogicalArrayLogicallyMatchedElement) {
1765fd4e5da5Sopenharmony_ci  const std::string spirv = R"(
1766fd4e5da5Sopenharmony_ciOpCapability Shader
1767fd4e5da5Sopenharmony_ciOpCapability Linkage
1768fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1769fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1770fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
1771fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
1772fd4e5da5Sopenharmony_ci%int_1 = OpConstant %int 1
1773fd4e5da5Sopenharmony_ci%inner1 = OpTypeArray %int %int_1
1774fd4e5da5Sopenharmony_ci%inner2 = OpTypeArray %int %int_1
1775fd4e5da5Sopenharmony_ci%array1 = OpTypeArray %inner1 %int_1
1776fd4e5da5Sopenharmony_ci%array2 = OpTypeArray %inner2 %int_1
1777fd4e5da5Sopenharmony_ci%const_inner = OpConstantComposite %inner1 %int_1
1778fd4e5da5Sopenharmony_ci%const_array = OpConstantComposite %array1 %const_inner
1779fd4e5da5Sopenharmony_ci%void_fn = OpTypeFunction %void
1780fd4e5da5Sopenharmony_ci%func = OpFunction %void None %void_fn
1781fd4e5da5Sopenharmony_ci%1 = OpLabel
1782fd4e5da5Sopenharmony_ci%copy = OpCopyLogical %array2 %const_array
1783fd4e5da5Sopenharmony_ciOpReturn
1784fd4e5da5Sopenharmony_ciOpFunctionEnd
1785fd4e5da5Sopenharmony_ci)";
1786fd4e5da5Sopenharmony_ci
1787fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
1788fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
1789fd4e5da5Sopenharmony_ci}
1790fd4e5da5Sopenharmony_ci
1791fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CopyLogicalStructDifferentNumberElements) {
1792fd4e5da5Sopenharmony_ci  const std::string spirv = R"(
1793fd4e5da5Sopenharmony_ciOpCapability Shader
1794fd4e5da5Sopenharmony_ciOpCapability Linkage
1795fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1796fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1797fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
1798fd4e5da5Sopenharmony_ci%struct1 = OpTypeStruct
1799fd4e5da5Sopenharmony_ci%struct2 = OpTypeStruct %int
1800fd4e5da5Sopenharmony_ci%const_struct = OpConstantComposite %struct1
1801fd4e5da5Sopenharmony_ci%void_fn = OpTypeFunction %void
1802fd4e5da5Sopenharmony_ci%func = OpFunction %void None %void_fn
1803fd4e5da5Sopenharmony_ci%1 = OpLabel
1804fd4e5da5Sopenharmony_ci%copy = OpCopyLogical %struct2 %const_struct
1805fd4e5da5Sopenharmony_ciOpReturn
1806fd4e5da5Sopenharmony_ciOpFunctionEnd
1807fd4e5da5Sopenharmony_ci)";
1808fd4e5da5Sopenharmony_ci
1809fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
1810fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
1811fd4e5da5Sopenharmony_ci  EXPECT_THAT(
1812fd4e5da5Sopenharmony_ci      getDiagnosticString(),
1813fd4e5da5Sopenharmony_ci      HasSubstr("Result Type does not logically match the Operand type"));
1814fd4e5da5Sopenharmony_ci}
1815fd4e5da5Sopenharmony_ci
1816fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CopyLogicalStructDifferentElement) {
1817fd4e5da5Sopenharmony_ci  const std::string spirv = R"(
1818fd4e5da5Sopenharmony_ciOpCapability Shader
1819fd4e5da5Sopenharmony_ciOpCapability Linkage
1820fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1821fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1822fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0
1823fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
1824fd4e5da5Sopenharmony_ci%int_0 = OpConstant %int 0
1825fd4e5da5Sopenharmony_ci%uint_0 = OpConstant %uint 0
1826fd4e5da5Sopenharmony_ci%struct1 = OpTypeStruct %int %uint
1827fd4e5da5Sopenharmony_ci%struct2 = OpTypeStruct %int %int
1828fd4e5da5Sopenharmony_ci%const_struct = OpConstantComposite %struct1 %int_0 %uint_0
1829fd4e5da5Sopenharmony_ci%void_fn = OpTypeFunction %void
1830fd4e5da5Sopenharmony_ci%func = OpFunction %void None %void_fn
1831fd4e5da5Sopenharmony_ci%1 = OpLabel
1832fd4e5da5Sopenharmony_ci%copy = OpCopyLogical %struct2 %const_struct
1833fd4e5da5Sopenharmony_ciOpReturn
1834fd4e5da5Sopenharmony_ciOpFunctionEnd
1835fd4e5da5Sopenharmony_ci)";
1836fd4e5da5Sopenharmony_ci
1837fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
1838fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
1839fd4e5da5Sopenharmony_ci  EXPECT_THAT(
1840fd4e5da5Sopenharmony_ci      getDiagnosticString(),
1841fd4e5da5Sopenharmony_ci      HasSubstr("Result Type does not logically match the Operand type"));
1842fd4e5da5Sopenharmony_ci}
1843fd4e5da5Sopenharmony_ci
1844fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CopyLogicalStructLogicallyMatch) {
1845fd4e5da5Sopenharmony_ci  const std::string spirv = R"(
1846fd4e5da5Sopenharmony_ciOpCapability Shader
1847fd4e5da5Sopenharmony_ciOpCapability Linkage
1848fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
1849fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1850fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
1851fd4e5da5Sopenharmony_ci%int_1 = OpConstant %int 1
1852fd4e5da5Sopenharmony_ci%array1 = OpTypeArray %int %int_1
1853fd4e5da5Sopenharmony_ci%array2 = OpTypeArray %int %int_1
1854fd4e5da5Sopenharmony_ci%struct1 = OpTypeStruct %int %array1
1855fd4e5da5Sopenharmony_ci%struct2 = OpTypeStruct %int %array2
1856fd4e5da5Sopenharmony_ci%const_array = OpConstantComposite %array1 %int_1
1857fd4e5da5Sopenharmony_ci%const_struct = OpConstantComposite %struct1 %int_1 %const_array
1858fd4e5da5Sopenharmony_ci%void_fn = OpTypeFunction %void
1859fd4e5da5Sopenharmony_ci%func = OpFunction %void None %void_fn
1860fd4e5da5Sopenharmony_ci%1 = OpLabel
1861fd4e5da5Sopenharmony_ci%copy = OpCopyLogical %struct2 %const_struct
1862fd4e5da5Sopenharmony_ciOpReturn
1863fd4e5da5Sopenharmony_ciOpFunctionEnd
1864fd4e5da5Sopenharmony_ci)";
1865fd4e5da5Sopenharmony_ci
1866fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
1867fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
1868fd4e5da5Sopenharmony_ci}
1869fd4e5da5Sopenharmony_ci
1870fd4e5da5Sopenharmony_ciusing ValidateSmallComposites = spvtest::ValidateBase<std::string>;
1871fd4e5da5Sopenharmony_ci
1872fd4e5da5Sopenharmony_ciCodeGenerator GetSmallCompositesCodeGenerator() {
1873fd4e5da5Sopenharmony_ci  CodeGenerator generator;
1874fd4e5da5Sopenharmony_ci  generator.capabilities_ = R"(
1875fd4e5da5Sopenharmony_ciOpCapability Shader
1876fd4e5da5Sopenharmony_ciOpCapability Linkage
1877fd4e5da5Sopenharmony_ciOpCapability UniformAndStorageBuffer16BitAccess
1878fd4e5da5Sopenharmony_ciOpCapability UniformAndStorageBuffer8BitAccess
1879fd4e5da5Sopenharmony_ci)";
1880fd4e5da5Sopenharmony_ci  generator.extensions_ = R"(
1881fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_16bit_storage"
1882fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_8bit_storage"
1883fd4e5da5Sopenharmony_ci)";
1884fd4e5da5Sopenharmony_ci  generator.memory_model_ = "OpMemoryModel Logical GLSL450\n";
1885fd4e5da5Sopenharmony_ci  generator.before_types_ = R"(
1886fd4e5da5Sopenharmony_ciOpDecorate %char_block Block
1887fd4e5da5Sopenharmony_ciOpMemberDecorate %char_block 0 Offset 0
1888fd4e5da5Sopenharmony_ciOpDecorate %short_block Block
1889fd4e5da5Sopenharmony_ciOpMemberDecorate %short_block 0 Offset 0
1890fd4e5da5Sopenharmony_ciOpDecorate %half_block Block
1891fd4e5da5Sopenharmony_ciOpMemberDecorate %half_block 0 Offset 0
1892fd4e5da5Sopenharmony_ci)";
1893fd4e5da5Sopenharmony_ci  generator.types_ = R"(
1894fd4e5da5Sopenharmony_ci%void = OpTypeVoid
1895fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
1896fd4e5da5Sopenharmony_ci%int_0 = OpConstant %int 0
1897fd4e5da5Sopenharmony_ci%int_1 = OpConstant %int 1
1898fd4e5da5Sopenharmony_ci%char = OpTypeInt 8 0
1899fd4e5da5Sopenharmony_ci%char2 = OpTypeVector %char 2
1900fd4e5da5Sopenharmony_ci%short = OpTypeInt 16 0
1901fd4e5da5Sopenharmony_ci%short2 = OpTypeVector %short 2
1902fd4e5da5Sopenharmony_ci%half = OpTypeFloat 16
1903fd4e5da5Sopenharmony_ci%half2 = OpTypeVector %half 2
1904fd4e5da5Sopenharmony_ci%char_block = OpTypeStruct %char2
1905fd4e5da5Sopenharmony_ci%short_block = OpTypeStruct %short2
1906fd4e5da5Sopenharmony_ci%half_block = OpTypeStruct %half2
1907fd4e5da5Sopenharmony_ci%ptr_ssbo_char_block = OpTypePointer StorageBuffer %char_block
1908fd4e5da5Sopenharmony_ci%ptr_ssbo_char2 = OpTypePointer StorageBuffer %char2
1909fd4e5da5Sopenharmony_ci%ptr_ssbo_char = OpTypePointer StorageBuffer %char
1910fd4e5da5Sopenharmony_ci%ptr_ssbo_short_block = OpTypePointer StorageBuffer %short_block
1911fd4e5da5Sopenharmony_ci%ptr_ssbo_short2 = OpTypePointer StorageBuffer %short2
1912fd4e5da5Sopenharmony_ci%ptr_ssbo_short = OpTypePointer StorageBuffer %short
1913fd4e5da5Sopenharmony_ci%ptr_ssbo_half_block = OpTypePointer StorageBuffer %half_block
1914fd4e5da5Sopenharmony_ci%ptr_ssbo_half2 = OpTypePointer StorageBuffer %half2
1915fd4e5da5Sopenharmony_ci%ptr_ssbo_half = OpTypePointer StorageBuffer %half
1916fd4e5da5Sopenharmony_ci%void_fn = OpTypeFunction %void
1917fd4e5da5Sopenharmony_ci%char_var = OpVariable %ptr_ssbo_char_block StorageBuffer
1918fd4e5da5Sopenharmony_ci%short_var = OpVariable %ptr_ssbo_short_block StorageBuffer
1919fd4e5da5Sopenharmony_ci%half_var = OpVariable %ptr_ssbo_half_block StorageBuffer
1920fd4e5da5Sopenharmony_ci)";
1921fd4e5da5Sopenharmony_ci  generator.after_types_ = R"(
1922fd4e5da5Sopenharmony_ci%func = OpFunction %void None %void_fn
1923fd4e5da5Sopenharmony_ci%entry = OpLabel
1924fd4e5da5Sopenharmony_ci%char2_gep = OpAccessChain %ptr_ssbo_char2 %char_var %int_0
1925fd4e5da5Sopenharmony_ci%ld_char2 = OpLoad %char2 %char2_gep
1926fd4e5da5Sopenharmony_ci%char_gep = OpAccessChain %ptr_ssbo_char %char_var %int_0 %int_0
1927fd4e5da5Sopenharmony_ci%ld_char = OpLoad %char %char_gep
1928fd4e5da5Sopenharmony_ci%short2_gep = OpAccessChain %ptr_ssbo_short2 %short_var %int_0
1929fd4e5da5Sopenharmony_ci%ld_short2 = OpLoad %short2 %short2_gep
1930fd4e5da5Sopenharmony_ci%short_gep = OpAccessChain %ptr_ssbo_short %short_var %int_0 %int_0
1931fd4e5da5Sopenharmony_ci%ld_short = OpLoad %short %short_gep
1932fd4e5da5Sopenharmony_ci%half2_gep = OpAccessChain %ptr_ssbo_half2 %half_var %int_0
1933fd4e5da5Sopenharmony_ci%ld_half2 = OpLoad %half2 %half2_gep
1934fd4e5da5Sopenharmony_ci%half_gep = OpAccessChain %ptr_ssbo_half %half_var %int_0 %int_0
1935fd4e5da5Sopenharmony_ci%ld_half = OpLoad %half %half_gep
1936fd4e5da5Sopenharmony_ci)";
1937fd4e5da5Sopenharmony_ci  generator.add_at_the_end_ = R"(
1938fd4e5da5Sopenharmony_ciOpReturn
1939fd4e5da5Sopenharmony_ciOpFunctionEnd
1940fd4e5da5Sopenharmony_ci)";
1941fd4e5da5Sopenharmony_ci  return generator;
1942fd4e5da5Sopenharmony_ci}
1943fd4e5da5Sopenharmony_ci
1944fd4e5da5Sopenharmony_ciTEST_P(ValidateSmallComposites, VectorExtractDynamic) {
1945fd4e5da5Sopenharmony_ci  std::string type = GetParam();
1946fd4e5da5Sopenharmony_ci  CodeGenerator generator = GetSmallCompositesCodeGenerator();
1947fd4e5da5Sopenharmony_ci  std::string inst =
1948fd4e5da5Sopenharmony_ci      "%inst = OpVectorExtractDynamic %" + type + " %ld_" + type + "2 %int_0\n";
1949fd4e5da5Sopenharmony_ci  generator.after_types_ += inst;
1950fd4e5da5Sopenharmony_ci  CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
1951fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1952fd4e5da5Sopenharmony_ci            ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1953fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1954fd4e5da5Sopenharmony_ci              HasSubstr("Cannot extract from a vector of 8- or 16-bit types"));
1955fd4e5da5Sopenharmony_ci}
1956fd4e5da5Sopenharmony_ci
1957fd4e5da5Sopenharmony_ciTEST_P(ValidateSmallComposites, VectorInsertDynamic) {
1958fd4e5da5Sopenharmony_ci  std::string type = GetParam();
1959fd4e5da5Sopenharmony_ci  CodeGenerator generator = GetSmallCompositesCodeGenerator();
1960fd4e5da5Sopenharmony_ci  std::string inst = "%inst = OpVectorInsertDynamic %" + type + "2 %ld_" +
1961fd4e5da5Sopenharmony_ci                     type + "2 %ld_" + type + " %int_0\n";
1962fd4e5da5Sopenharmony_ci  generator.after_types_ += inst;
1963fd4e5da5Sopenharmony_ci  CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
1964fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1965fd4e5da5Sopenharmony_ci            ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1966fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1967fd4e5da5Sopenharmony_ci              HasSubstr("Cannot insert into a vector of 8- or 16-bit types"));
1968fd4e5da5Sopenharmony_ci}
1969fd4e5da5Sopenharmony_ci
1970fd4e5da5Sopenharmony_ciTEST_P(ValidateSmallComposites, VectorShuffle) {
1971fd4e5da5Sopenharmony_ci  std::string type = GetParam();
1972fd4e5da5Sopenharmony_ci  CodeGenerator generator = GetSmallCompositesCodeGenerator();
1973fd4e5da5Sopenharmony_ci  std::string inst = "%inst = OpVectorShuffle %" + type + "2 %ld_" + type +
1974fd4e5da5Sopenharmony_ci                     "2 %ld_" + type + "2 0 0\n";
1975fd4e5da5Sopenharmony_ci  generator.after_types_ += inst;
1976fd4e5da5Sopenharmony_ci  CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
1977fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1978fd4e5da5Sopenharmony_ci            ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1979fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1980fd4e5da5Sopenharmony_ci              HasSubstr("Cannot shuffle a vector of 8- or 16-bit types"));
1981fd4e5da5Sopenharmony_ci}
1982fd4e5da5Sopenharmony_ci
1983fd4e5da5Sopenharmony_ciTEST_P(ValidateSmallComposites, CompositeConstruct) {
1984fd4e5da5Sopenharmony_ci  std::string type = GetParam();
1985fd4e5da5Sopenharmony_ci  CodeGenerator generator = GetSmallCompositesCodeGenerator();
1986fd4e5da5Sopenharmony_ci  std::string inst = "%inst = OpCompositeConstruct %" + type + "2 %ld_" + type +
1987fd4e5da5Sopenharmony_ci                     " %ld_" + type + "\n";
1988fd4e5da5Sopenharmony_ci  generator.after_types_ += inst;
1989fd4e5da5Sopenharmony_ci  CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
1990fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_DATA,
1991fd4e5da5Sopenharmony_ci            ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
1992fd4e5da5Sopenharmony_ci  EXPECT_THAT(
1993fd4e5da5Sopenharmony_ci      getDiagnosticString(),
1994fd4e5da5Sopenharmony_ci      HasSubstr("Cannot create a composite containing 8- or 16-bit types"));
1995fd4e5da5Sopenharmony_ci}
1996fd4e5da5Sopenharmony_ci
1997fd4e5da5Sopenharmony_ciTEST_P(ValidateSmallComposites, CompositeExtract) {
1998fd4e5da5Sopenharmony_ci  std::string type = GetParam();
1999fd4e5da5Sopenharmony_ci  CodeGenerator generator = GetSmallCompositesCodeGenerator();
2000fd4e5da5Sopenharmony_ci  std::string inst =
2001fd4e5da5Sopenharmony_ci      "%inst = OpCompositeExtract %" + type + " %ld_" + type + "2 0\n";
2002fd4e5da5Sopenharmony_ci  generator.after_types_ += inst;
2003fd4e5da5Sopenharmony_ci  CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
2004fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_DATA,
2005fd4e5da5Sopenharmony_ci            ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2006fd4e5da5Sopenharmony_ci  EXPECT_THAT(
2007fd4e5da5Sopenharmony_ci      getDiagnosticString(),
2008fd4e5da5Sopenharmony_ci      HasSubstr("Cannot extract from a composite of 8- or 16-bit types"));
2009fd4e5da5Sopenharmony_ci}
2010fd4e5da5Sopenharmony_ci
2011fd4e5da5Sopenharmony_ciTEST_P(ValidateSmallComposites, CompositeInsert) {
2012fd4e5da5Sopenharmony_ci  std::string type = GetParam();
2013fd4e5da5Sopenharmony_ci  CodeGenerator generator = GetSmallCompositesCodeGenerator();
2014fd4e5da5Sopenharmony_ci  std::string inst = "%inst = OpCompositeInsert %" + type + "2 %ld_" + type +
2015fd4e5da5Sopenharmony_ci                     " %ld_" + type + "2 0\n";
2016fd4e5da5Sopenharmony_ci  generator.after_types_ += inst;
2017fd4e5da5Sopenharmony_ci  CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
2018fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_DATA,
2019fd4e5da5Sopenharmony_ci            ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2020fd4e5da5Sopenharmony_ci  EXPECT_THAT(
2021fd4e5da5Sopenharmony_ci      getDiagnosticString(),
2022fd4e5da5Sopenharmony_ci      HasSubstr("Cannot insert into a composite of 8- or 16-bit types"));
2023fd4e5da5Sopenharmony_ci}
2024fd4e5da5Sopenharmony_ci
2025fd4e5da5Sopenharmony_ciTEST_P(ValidateSmallComposites, CopyObject) {
2026fd4e5da5Sopenharmony_ci  std::string type = GetParam();
2027fd4e5da5Sopenharmony_ci  CodeGenerator generator = GetSmallCompositesCodeGenerator();
2028fd4e5da5Sopenharmony_ci  std::string inst = "%inst = OpCopyObject %" + type + "2 %ld_" + type + "2\n";
2029fd4e5da5Sopenharmony_ci  generator.after_types_ += inst;
2030fd4e5da5Sopenharmony_ci  CompileSuccessfully(generator.Build(), SPV_ENV_UNIVERSAL_1_3);
2031fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2032fd4e5da5Sopenharmony_ci}
2033fd4e5da5Sopenharmony_ci
2034fd4e5da5Sopenharmony_ciINSTANTIATE_TEST_SUITE_P(SmallCompositeInstructions, ValidateSmallComposites,
2035fd4e5da5Sopenharmony_ci                         Values("char", "short", "half"));
2036fd4e5da5Sopenharmony_ci
2037fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, HalfMatrixCannotTranspose) {
2038fd4e5da5Sopenharmony_ci  const std::string spirv = R"(
2039fd4e5da5Sopenharmony_ciOpCapability Shader
2040fd4e5da5Sopenharmony_ciOpCapability Linkage
2041fd4e5da5Sopenharmony_ciOpCapability UniformAndStorageBuffer16BitAccess
2042fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_16bit_storage"
2043fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
2044fd4e5da5Sopenharmony_ciOpDecorate %block Block
2045fd4e5da5Sopenharmony_ciOpMemberDecorate %block 0 Offset 0
2046fd4e5da5Sopenharmony_ciOpMemberDecorate %block 0 RowMajor
2047fd4e5da5Sopenharmony_ciOpMemberDecorate %block 0 MatrixStride 8
2048fd4e5da5Sopenharmony_ci%void = OpTypeVoid
2049fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
2050fd4e5da5Sopenharmony_ci%int_0 = OpConstant %int 0
2051fd4e5da5Sopenharmony_ci%float = OpTypeFloat 16
2052fd4e5da5Sopenharmony_ci%float2 = OpTypeVector %float 2
2053fd4e5da5Sopenharmony_ci%mat2x2 = OpTypeMatrix %float2 2
2054fd4e5da5Sopenharmony_ci%block = OpTypeStruct %mat2x2
2055fd4e5da5Sopenharmony_ci%ptr_ssbo_block = OpTypePointer StorageBuffer %block
2056fd4e5da5Sopenharmony_ci%ptr_ssbo_mat2x2 = OpTypePointer StorageBuffer %mat2x2
2057fd4e5da5Sopenharmony_ci%var = OpVariable %ptr_ssbo_block StorageBuffer
2058fd4e5da5Sopenharmony_ci%void_fn = OpTypeFunction %void
2059fd4e5da5Sopenharmony_ci%func = OpFunction %void None %void_fn
2060fd4e5da5Sopenharmony_ci%entry = OpLabel
2061fd4e5da5Sopenharmony_ci%gep = OpAccessChain %ptr_ssbo_mat2x2 %var %int_0
2062fd4e5da5Sopenharmony_ci%ld = OpLoad %mat2x2 %gep
2063fd4e5da5Sopenharmony_ci%inst = OpTranspose %mat2x2 %ld
2064fd4e5da5Sopenharmony_ciOpReturn
2065fd4e5da5Sopenharmony_ciOpFunctionEnd
2066fd4e5da5Sopenharmony_ci)";
2067fd4e5da5Sopenharmony_ci
2068fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
2069fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_DATA,
2070fd4e5da5Sopenharmony_ci            ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
2071fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
2072fd4e5da5Sopenharmony_ci              HasSubstr("Cannot transpose matrices of 16-bit floats"));
2073fd4e5da5Sopenharmony_ci}
2074fd4e5da5Sopenharmony_ci
2075fd4e5da5Sopenharmony_ciTEST_F(ValidateComposites, CopyObjectVoid) {
2076fd4e5da5Sopenharmony_ci  const std::string spirv = R"(
2077fd4e5da5Sopenharmony_ci               OpCapability Shader
2078fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
2079fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
2080fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
2081fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
2082fd4e5da5Sopenharmony_ci               OpSource ESSL 320
2083fd4e5da5Sopenharmony_ci               OpName %4 "main"
2084fd4e5da5Sopenharmony_ci               OpName %6 "foo("
2085fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
2086fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
2087fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
2088fd4e5da5Sopenharmony_ci          %5 = OpLabel
2089fd4e5da5Sopenharmony_ci          %8 = OpFunctionCall %2 %6
2090fd4e5da5Sopenharmony_ci         %20 = OpCopyObject %2 %8
2091fd4e5da5Sopenharmony_ci               OpReturn
2092fd4e5da5Sopenharmony_ci               OpFunctionEnd
2093fd4e5da5Sopenharmony_ci          %6 = OpFunction %2 None %3
2094fd4e5da5Sopenharmony_ci          %7 = OpLabel
2095fd4e5da5Sopenharmony_ci               OpReturn
2096fd4e5da5Sopenharmony_ci               OpFunctionEnd
2097fd4e5da5Sopenharmony_ci)";
2098fd4e5da5Sopenharmony_ci
2099fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
2100fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2101fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
2102fd4e5da5Sopenharmony_ci              HasSubstr("OpCopyObject cannot have void result type"));
2103fd4e5da5Sopenharmony_ci}
2104fd4e5da5Sopenharmony_ci
2105fd4e5da5Sopenharmony_ci}  // namespace
2106fd4e5da5Sopenharmony_ci}  // namespace val
2107fd4e5da5Sopenharmony_ci}  // namespace spvtools
2108