1fd4e5da5Sopenharmony_ci// Copyright (c) 2019 Google LLC.
2fd4e5da5Sopenharmony_ci//
3fd4e5da5Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License");
4fd4e5da5Sopenharmony_ci// you may not use this file except in compliance with the License.
5fd4e5da5Sopenharmony_ci// You may obtain a copy of the License at
6fd4e5da5Sopenharmony_ci//
7fd4e5da5Sopenharmony_ci//     http://www.apache.org/licenses/LICENSE-2.0
8fd4e5da5Sopenharmony_ci//
9fd4e5da5Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software
10fd4e5da5Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS,
11fd4e5da5Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fd4e5da5Sopenharmony_ci// See the License for the specific language governing permissions and
13fd4e5da5Sopenharmony_ci// limitations under the License.
14fd4e5da5Sopenharmony_ci
15fd4e5da5Sopenharmony_ci#include <string>
16fd4e5da5Sopenharmony_ci#include <tuple>
17fd4e5da5Sopenharmony_ci
18fd4e5da5Sopenharmony_ci#include "gmock/gmock.h"
19fd4e5da5Sopenharmony_ci#include "test/unit_spirv.h"
20fd4e5da5Sopenharmony_ci#include "test/val/val_fixtures.h"
21fd4e5da5Sopenharmony_ci
22fd4e5da5Sopenharmony_cinamespace spvtools {
23fd4e5da5Sopenharmony_cinamespace val {
24fd4e5da5Sopenharmony_cinamespace {
25fd4e5da5Sopenharmony_ci
26fd4e5da5Sopenharmony_ciusing ::testing::Combine;
27fd4e5da5Sopenharmony_ciusing ::testing::HasSubstr;
28fd4e5da5Sopenharmony_ciusing ::testing::Values;
29fd4e5da5Sopenharmony_ci
30fd4e5da5Sopenharmony_ciusing ValidateFunctionCall = spvtest::ValidateBase<std::string>;
31fd4e5da5Sopenharmony_ci
32fd4e5da5Sopenharmony_cistd::string GenerateShader(const std::string& storage_class,
33fd4e5da5Sopenharmony_ci                           const std::string& capabilities,
34fd4e5da5Sopenharmony_ci                           const std::string& extensions) {
35fd4e5da5Sopenharmony_ci  std::string spirv = R"(
36fd4e5da5Sopenharmony_ciOpCapability Shader
37fd4e5da5Sopenharmony_ciOpCapability Linkage
38fd4e5da5Sopenharmony_ciOpCapability AtomicStorage
39fd4e5da5Sopenharmony_ci)" + capabilities + R"(
40fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_storage_buffer_storage_class"
41fd4e5da5Sopenharmony_ci)" +
42fd4e5da5Sopenharmony_ci                      extensions + R"(
43fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
44fd4e5da5Sopenharmony_ciOpName %var "var"
45fd4e5da5Sopenharmony_ci%void = OpTypeVoid
46fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
47fd4e5da5Sopenharmony_ci%ptr = OpTypePointer )" + storage_class + R"( %int
48fd4e5da5Sopenharmony_ci%caller_ty = OpTypeFunction %void
49fd4e5da5Sopenharmony_ci%callee_ty = OpTypeFunction %void %ptr
50fd4e5da5Sopenharmony_ci)";
51fd4e5da5Sopenharmony_ci
52fd4e5da5Sopenharmony_ci  if (storage_class != "Function") {
53fd4e5da5Sopenharmony_ci    spirv += "%var = OpVariable %ptr " + storage_class;
54fd4e5da5Sopenharmony_ci  }
55fd4e5da5Sopenharmony_ci
56fd4e5da5Sopenharmony_ci  spirv += R"(
57fd4e5da5Sopenharmony_ci%caller = OpFunction %void None %caller_ty
58fd4e5da5Sopenharmony_ci%1 = OpLabel
59fd4e5da5Sopenharmony_ci)";
60fd4e5da5Sopenharmony_ci
61fd4e5da5Sopenharmony_ci  if (storage_class == "Function") {
62fd4e5da5Sopenharmony_ci    spirv += "%var = OpVariable %ptr Function";
63fd4e5da5Sopenharmony_ci  }
64fd4e5da5Sopenharmony_ci
65fd4e5da5Sopenharmony_ci  spirv += R"(
66fd4e5da5Sopenharmony_ci%call = OpFunctionCall %void %callee %var
67fd4e5da5Sopenharmony_ciOpReturn
68fd4e5da5Sopenharmony_ciOpFunctionEnd
69fd4e5da5Sopenharmony_ci%callee = OpFunction %void None %callee_ty
70fd4e5da5Sopenharmony_ci%param = OpFunctionParameter %ptr
71fd4e5da5Sopenharmony_ci%2 = OpLabel
72fd4e5da5Sopenharmony_ciOpReturn
73fd4e5da5Sopenharmony_ciOpFunctionEnd
74fd4e5da5Sopenharmony_ci)";
75fd4e5da5Sopenharmony_ci
76fd4e5da5Sopenharmony_ci  return spirv;
77fd4e5da5Sopenharmony_ci}
78fd4e5da5Sopenharmony_ci
79fd4e5da5Sopenharmony_cistd::string GenerateShaderParameter(const std::string& storage_class,
80fd4e5da5Sopenharmony_ci                                    const std::string& capabilities,
81fd4e5da5Sopenharmony_ci                                    const std::string& extensions) {
82fd4e5da5Sopenharmony_ci  std::string spirv = R"(
83fd4e5da5Sopenharmony_ciOpCapability Shader
84fd4e5da5Sopenharmony_ciOpCapability Linkage
85fd4e5da5Sopenharmony_ciOpCapability AtomicStorage
86fd4e5da5Sopenharmony_ci)" + capabilities + R"(
87fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_storage_buffer_storage_class"
88fd4e5da5Sopenharmony_ci)" +
89fd4e5da5Sopenharmony_ci                      extensions + R"(
90fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
91fd4e5da5Sopenharmony_ciOpName %p "p"
92fd4e5da5Sopenharmony_ci%void = OpTypeVoid
93fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
94fd4e5da5Sopenharmony_ci%ptr = OpTypePointer )" + storage_class + R"( %int
95fd4e5da5Sopenharmony_ci%func_ty = OpTypeFunction %void %ptr
96fd4e5da5Sopenharmony_ci%caller = OpFunction %void None %func_ty
97fd4e5da5Sopenharmony_ci%p = OpFunctionParameter %ptr
98fd4e5da5Sopenharmony_ci%1 = OpLabel
99fd4e5da5Sopenharmony_ci%call = OpFunctionCall %void %callee %p
100fd4e5da5Sopenharmony_ciOpReturn
101fd4e5da5Sopenharmony_ciOpFunctionEnd
102fd4e5da5Sopenharmony_ci%callee = OpFunction %void None %func_ty
103fd4e5da5Sopenharmony_ci%param = OpFunctionParameter %ptr
104fd4e5da5Sopenharmony_ci%2 = OpLabel
105fd4e5da5Sopenharmony_ciOpReturn
106fd4e5da5Sopenharmony_ciOpFunctionEnd
107fd4e5da5Sopenharmony_ci)";
108fd4e5da5Sopenharmony_ci
109fd4e5da5Sopenharmony_ci  return spirv;
110fd4e5da5Sopenharmony_ci}
111fd4e5da5Sopenharmony_ci
112fd4e5da5Sopenharmony_cistd::string GenerateShaderAccessChain(const std::string& storage_class,
113fd4e5da5Sopenharmony_ci                                      const std::string& capabilities,
114fd4e5da5Sopenharmony_ci                                      const std::string& extensions) {
115fd4e5da5Sopenharmony_ci  std::string spirv = R"(
116fd4e5da5Sopenharmony_ciOpCapability Shader
117fd4e5da5Sopenharmony_ciOpCapability Linkage
118fd4e5da5Sopenharmony_ciOpCapability AtomicStorage
119fd4e5da5Sopenharmony_ci)" + capabilities + R"(
120fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_storage_buffer_storage_class"
121fd4e5da5Sopenharmony_ci)" +
122fd4e5da5Sopenharmony_ci                      extensions + R"(
123fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
124fd4e5da5Sopenharmony_ciOpName %var "var"
125fd4e5da5Sopenharmony_ciOpName %gep "gep"
126fd4e5da5Sopenharmony_ci%void = OpTypeVoid
127fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
128fd4e5da5Sopenharmony_ci%int2 = OpTypeVector %int 2
129fd4e5da5Sopenharmony_ci%int_0 = OpConstant %int 0
130fd4e5da5Sopenharmony_ci%ptr = OpTypePointer )" + storage_class + R"( %int2
131fd4e5da5Sopenharmony_ci%ptr2 = OpTypePointer )" +
132fd4e5da5Sopenharmony_ci                      storage_class + R"( %int
133fd4e5da5Sopenharmony_ci%caller_ty = OpTypeFunction %void
134fd4e5da5Sopenharmony_ci%callee_ty = OpTypeFunction %void %ptr2
135fd4e5da5Sopenharmony_ci)";
136fd4e5da5Sopenharmony_ci
137fd4e5da5Sopenharmony_ci  if (storage_class != "Function") {
138fd4e5da5Sopenharmony_ci    spirv += "%var = OpVariable %ptr " + storage_class;
139fd4e5da5Sopenharmony_ci  }
140fd4e5da5Sopenharmony_ci
141fd4e5da5Sopenharmony_ci  spirv += R"(
142fd4e5da5Sopenharmony_ci%caller = OpFunction %void None %caller_ty
143fd4e5da5Sopenharmony_ci%1 = OpLabel
144fd4e5da5Sopenharmony_ci)";
145fd4e5da5Sopenharmony_ci
146fd4e5da5Sopenharmony_ci  if (storage_class == "Function") {
147fd4e5da5Sopenharmony_ci    spirv += "%var = OpVariable %ptr Function";
148fd4e5da5Sopenharmony_ci  }
149fd4e5da5Sopenharmony_ci
150fd4e5da5Sopenharmony_ci  spirv += R"(
151fd4e5da5Sopenharmony_ci%gep = OpAccessChain %ptr2 %var %int_0
152fd4e5da5Sopenharmony_ci%call = OpFunctionCall %void %callee %gep
153fd4e5da5Sopenharmony_ciOpReturn
154fd4e5da5Sopenharmony_ciOpFunctionEnd
155fd4e5da5Sopenharmony_ci%callee = OpFunction %void None %callee_ty
156fd4e5da5Sopenharmony_ci%param = OpFunctionParameter %ptr2
157fd4e5da5Sopenharmony_ci%2 = OpLabel
158fd4e5da5Sopenharmony_ciOpReturn
159fd4e5da5Sopenharmony_ciOpFunctionEnd
160fd4e5da5Sopenharmony_ci)";
161fd4e5da5Sopenharmony_ci
162fd4e5da5Sopenharmony_ci  return spirv;
163fd4e5da5Sopenharmony_ci}
164fd4e5da5Sopenharmony_ci
165fd4e5da5Sopenharmony_ciTEST_P(ValidateFunctionCall, VariableNoVariablePointers) {
166fd4e5da5Sopenharmony_ci  const std::string storage_class = GetParam();
167fd4e5da5Sopenharmony_ci
168fd4e5da5Sopenharmony_ci  std::string spirv = GenerateShader(storage_class, "", "");
169fd4e5da5Sopenharmony_ci
170fd4e5da5Sopenharmony_ci  const std::vector<std::string> valid_storage_classes = {
171fd4e5da5Sopenharmony_ci      "UniformConstant", "Function", "Private", "Workgroup", "AtomicCounter"};
172fd4e5da5Sopenharmony_ci  bool valid =
173fd4e5da5Sopenharmony_ci      std::find(valid_storage_classes.begin(), valid_storage_classes.end(),
174fd4e5da5Sopenharmony_ci                storage_class) != valid_storage_classes.end();
175fd4e5da5Sopenharmony_ci
176fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
177fd4e5da5Sopenharmony_ci  if (valid) {
178fd4e5da5Sopenharmony_ci    EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
179fd4e5da5Sopenharmony_ci  } else {
180fd4e5da5Sopenharmony_ci    EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
181fd4e5da5Sopenharmony_ci    if (storage_class == "StorageBuffer") {
182fd4e5da5Sopenharmony_ci      EXPECT_THAT(
183fd4e5da5Sopenharmony_ci          getDiagnosticString(),
184fd4e5da5Sopenharmony_ci          HasSubstr("StorageBuffer pointer operand '1[%var]' requires a "
185fd4e5da5Sopenharmony_ci                    "variable pointers capability"));
186fd4e5da5Sopenharmony_ci    } else {
187fd4e5da5Sopenharmony_ci      EXPECT_THAT(
188fd4e5da5Sopenharmony_ci          getDiagnosticString(),
189fd4e5da5Sopenharmony_ci          HasSubstr("Invalid storage class for pointer operand '1[%var]'"));
190fd4e5da5Sopenharmony_ci    }
191fd4e5da5Sopenharmony_ci  }
192fd4e5da5Sopenharmony_ci}
193fd4e5da5Sopenharmony_ci
194fd4e5da5Sopenharmony_ciTEST_P(ValidateFunctionCall, VariableVariablePointersStorageClass) {
195fd4e5da5Sopenharmony_ci  const std::string storage_class = GetParam();
196fd4e5da5Sopenharmony_ci
197fd4e5da5Sopenharmony_ci  std::string spirv = GenerateShader(
198fd4e5da5Sopenharmony_ci      storage_class, "OpCapability VariablePointersStorageBuffer",
199fd4e5da5Sopenharmony_ci      "OpExtension \"SPV_KHR_variable_pointers\"");
200fd4e5da5Sopenharmony_ci
201fd4e5da5Sopenharmony_ci  const std::vector<std::string> valid_storage_classes = {
202fd4e5da5Sopenharmony_ci      "UniformConstant", "Function",      "Private",
203fd4e5da5Sopenharmony_ci      "Workgroup",       "StorageBuffer", "AtomicCounter"};
204fd4e5da5Sopenharmony_ci  bool valid =
205fd4e5da5Sopenharmony_ci      std::find(valid_storage_classes.begin(), valid_storage_classes.end(),
206fd4e5da5Sopenharmony_ci                storage_class) != valid_storage_classes.end();
207fd4e5da5Sopenharmony_ci
208fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
209fd4e5da5Sopenharmony_ci  if (valid) {
210fd4e5da5Sopenharmony_ci    EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
211fd4e5da5Sopenharmony_ci  } else {
212fd4e5da5Sopenharmony_ci    EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
213fd4e5da5Sopenharmony_ci    EXPECT_THAT(
214fd4e5da5Sopenharmony_ci        getDiagnosticString(),
215fd4e5da5Sopenharmony_ci        HasSubstr("Invalid storage class for pointer operand '1[%var]'"));
216fd4e5da5Sopenharmony_ci  }
217fd4e5da5Sopenharmony_ci}
218fd4e5da5Sopenharmony_ci
219fd4e5da5Sopenharmony_ciTEST_P(ValidateFunctionCall, VariableVariablePointers) {
220fd4e5da5Sopenharmony_ci  const std::string storage_class = GetParam();
221fd4e5da5Sopenharmony_ci
222fd4e5da5Sopenharmony_ci  std::string spirv =
223fd4e5da5Sopenharmony_ci      GenerateShader(storage_class, "OpCapability VariablePointers",
224fd4e5da5Sopenharmony_ci                     "OpExtension \"SPV_KHR_variable_pointers\"");
225fd4e5da5Sopenharmony_ci
226fd4e5da5Sopenharmony_ci  const std::vector<std::string> valid_storage_classes = {
227fd4e5da5Sopenharmony_ci      "UniformConstant", "Function",      "Private",
228fd4e5da5Sopenharmony_ci      "Workgroup",       "StorageBuffer", "AtomicCounter"};
229fd4e5da5Sopenharmony_ci  bool valid =
230fd4e5da5Sopenharmony_ci      std::find(valid_storage_classes.begin(), valid_storage_classes.end(),
231fd4e5da5Sopenharmony_ci                storage_class) != valid_storage_classes.end();
232fd4e5da5Sopenharmony_ci
233fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
234fd4e5da5Sopenharmony_ci  if (valid) {
235fd4e5da5Sopenharmony_ci    EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
236fd4e5da5Sopenharmony_ci  } else {
237fd4e5da5Sopenharmony_ci    EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
238fd4e5da5Sopenharmony_ci    EXPECT_THAT(
239fd4e5da5Sopenharmony_ci        getDiagnosticString(),
240fd4e5da5Sopenharmony_ci        HasSubstr("Invalid storage class for pointer operand '1[%var]'"));
241fd4e5da5Sopenharmony_ci  }
242fd4e5da5Sopenharmony_ci}
243fd4e5da5Sopenharmony_ci
244fd4e5da5Sopenharmony_ciTEST_P(ValidateFunctionCall, ParameterNoVariablePointers) {
245fd4e5da5Sopenharmony_ci  const std::string storage_class = GetParam();
246fd4e5da5Sopenharmony_ci
247fd4e5da5Sopenharmony_ci  std::string spirv = GenerateShaderParameter(storage_class, "", "");
248fd4e5da5Sopenharmony_ci
249fd4e5da5Sopenharmony_ci  const std::vector<std::string> valid_storage_classes = {
250fd4e5da5Sopenharmony_ci      "UniformConstant", "Function", "Private", "Workgroup", "AtomicCounter"};
251fd4e5da5Sopenharmony_ci  bool valid =
252fd4e5da5Sopenharmony_ci      std::find(valid_storage_classes.begin(), valid_storage_classes.end(),
253fd4e5da5Sopenharmony_ci                storage_class) != valid_storage_classes.end();
254fd4e5da5Sopenharmony_ci
255fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
256fd4e5da5Sopenharmony_ci  if (valid) {
257fd4e5da5Sopenharmony_ci    EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
258fd4e5da5Sopenharmony_ci  } else {
259fd4e5da5Sopenharmony_ci    EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
260fd4e5da5Sopenharmony_ci    if (storage_class == "StorageBuffer") {
261fd4e5da5Sopenharmony_ci      EXPECT_THAT(getDiagnosticString(),
262fd4e5da5Sopenharmony_ci                  HasSubstr("StorageBuffer pointer operand '1[%p]' requires a "
263fd4e5da5Sopenharmony_ci                            "variable pointers capability"));
264fd4e5da5Sopenharmony_ci    } else {
265fd4e5da5Sopenharmony_ci      EXPECT_THAT(
266fd4e5da5Sopenharmony_ci          getDiagnosticString(),
267fd4e5da5Sopenharmony_ci          HasSubstr("Invalid storage class for pointer operand '1[%p]'"));
268fd4e5da5Sopenharmony_ci    }
269fd4e5da5Sopenharmony_ci  }
270fd4e5da5Sopenharmony_ci}
271fd4e5da5Sopenharmony_ci
272fd4e5da5Sopenharmony_ciTEST_P(ValidateFunctionCall, ParameterVariablePointersStorageBuffer) {
273fd4e5da5Sopenharmony_ci  const std::string storage_class = GetParam();
274fd4e5da5Sopenharmony_ci
275fd4e5da5Sopenharmony_ci  std::string spirv = GenerateShaderParameter(
276fd4e5da5Sopenharmony_ci      storage_class, "OpCapability VariablePointersStorageBuffer",
277fd4e5da5Sopenharmony_ci      "OpExtension \"SPV_KHR_variable_pointers\"");
278fd4e5da5Sopenharmony_ci
279fd4e5da5Sopenharmony_ci  const std::vector<std::string> valid_storage_classes = {
280fd4e5da5Sopenharmony_ci      "UniformConstant", "Function",      "Private",
281fd4e5da5Sopenharmony_ci      "Workgroup",       "StorageBuffer", "AtomicCounter"};
282fd4e5da5Sopenharmony_ci  bool valid =
283fd4e5da5Sopenharmony_ci      std::find(valid_storage_classes.begin(), valid_storage_classes.end(),
284fd4e5da5Sopenharmony_ci                storage_class) != valid_storage_classes.end();
285fd4e5da5Sopenharmony_ci
286fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
287fd4e5da5Sopenharmony_ci  if (valid) {
288fd4e5da5Sopenharmony_ci    EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
289fd4e5da5Sopenharmony_ci  } else {
290fd4e5da5Sopenharmony_ci    EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
291fd4e5da5Sopenharmony_ci    EXPECT_THAT(getDiagnosticString(),
292fd4e5da5Sopenharmony_ci                HasSubstr("Invalid storage class for pointer operand '1[%p]'"));
293fd4e5da5Sopenharmony_ci  }
294fd4e5da5Sopenharmony_ci}
295fd4e5da5Sopenharmony_ci
296fd4e5da5Sopenharmony_ciTEST_P(ValidateFunctionCall, ParameterVariablePointers) {
297fd4e5da5Sopenharmony_ci  const std::string storage_class = GetParam();
298fd4e5da5Sopenharmony_ci
299fd4e5da5Sopenharmony_ci  std::string spirv =
300fd4e5da5Sopenharmony_ci      GenerateShaderParameter(storage_class, "OpCapability VariablePointers",
301fd4e5da5Sopenharmony_ci                              "OpExtension \"SPV_KHR_variable_pointers\"");
302fd4e5da5Sopenharmony_ci
303fd4e5da5Sopenharmony_ci  const std::vector<std::string> valid_storage_classes = {
304fd4e5da5Sopenharmony_ci      "UniformConstant", "Function",      "Private",
305fd4e5da5Sopenharmony_ci      "Workgroup",       "StorageBuffer", "AtomicCounter"};
306fd4e5da5Sopenharmony_ci  bool valid =
307fd4e5da5Sopenharmony_ci      std::find(valid_storage_classes.begin(), valid_storage_classes.end(),
308fd4e5da5Sopenharmony_ci                storage_class) != valid_storage_classes.end();
309fd4e5da5Sopenharmony_ci
310fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
311fd4e5da5Sopenharmony_ci  if (valid) {
312fd4e5da5Sopenharmony_ci    EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
313fd4e5da5Sopenharmony_ci  } else {
314fd4e5da5Sopenharmony_ci    EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
315fd4e5da5Sopenharmony_ci    EXPECT_THAT(getDiagnosticString(),
316fd4e5da5Sopenharmony_ci                HasSubstr("Invalid storage class for pointer operand '1[%p]'"));
317fd4e5da5Sopenharmony_ci  }
318fd4e5da5Sopenharmony_ci}
319fd4e5da5Sopenharmony_ci
320fd4e5da5Sopenharmony_ciTEST_P(ValidateFunctionCall, NonMemoryObjectDeclarationNoVariablePointers) {
321fd4e5da5Sopenharmony_ci  const std::string storage_class = GetParam();
322fd4e5da5Sopenharmony_ci
323fd4e5da5Sopenharmony_ci  std::string spirv = GenerateShaderAccessChain(storage_class, "", "");
324fd4e5da5Sopenharmony_ci
325fd4e5da5Sopenharmony_ci  const std::vector<std::string> valid_storage_classes = {
326fd4e5da5Sopenharmony_ci      "Function", "Private", "Workgroup", "AtomicCounter"};
327fd4e5da5Sopenharmony_ci  bool valid_sc =
328fd4e5da5Sopenharmony_ci      std::find(valid_storage_classes.begin(), valid_storage_classes.end(),
329fd4e5da5Sopenharmony_ci                storage_class) != valid_storage_classes.end();
330fd4e5da5Sopenharmony_ci
331fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
332fd4e5da5Sopenharmony_ci  spv_result_t expected_result =
333fd4e5da5Sopenharmony_ci      storage_class == "UniformConstant" ? SPV_SUCCESS : SPV_ERROR_INVALID_ID;
334fd4e5da5Sopenharmony_ci  EXPECT_EQ(expected_result, ValidateInstructions());
335fd4e5da5Sopenharmony_ci  if (valid_sc) {
336fd4e5da5Sopenharmony_ci    EXPECT_THAT(
337fd4e5da5Sopenharmony_ci        getDiagnosticString(),
338fd4e5da5Sopenharmony_ci        HasSubstr(
339fd4e5da5Sopenharmony_ci            "Pointer operand '2[%gep]' must be a memory object declaration"));
340fd4e5da5Sopenharmony_ci  } else {
341fd4e5da5Sopenharmony_ci    if (storage_class == "StorageBuffer") {
342fd4e5da5Sopenharmony_ci      EXPECT_THAT(
343fd4e5da5Sopenharmony_ci          getDiagnosticString(),
344fd4e5da5Sopenharmony_ci          HasSubstr("StorageBuffer pointer operand '2[%gep]' requires a "
345fd4e5da5Sopenharmony_ci                    "variable pointers capability"));
346fd4e5da5Sopenharmony_ci    } else if (storage_class != "UniformConstant") {
347fd4e5da5Sopenharmony_ci      EXPECT_THAT(
348fd4e5da5Sopenharmony_ci          getDiagnosticString(),
349fd4e5da5Sopenharmony_ci          HasSubstr("Invalid storage class for pointer operand '2[%gep]'"));
350fd4e5da5Sopenharmony_ci    }
351fd4e5da5Sopenharmony_ci  }
352fd4e5da5Sopenharmony_ci}
353fd4e5da5Sopenharmony_ci
354fd4e5da5Sopenharmony_ciTEST_P(ValidateFunctionCall,
355fd4e5da5Sopenharmony_ci       NonMemoryObjectDeclarationVariablePointersStorageBuffer) {
356fd4e5da5Sopenharmony_ci  const std::string storage_class = GetParam();
357fd4e5da5Sopenharmony_ci
358fd4e5da5Sopenharmony_ci  std::string spirv = GenerateShaderAccessChain(
359fd4e5da5Sopenharmony_ci      storage_class, "OpCapability VariablePointersStorageBuffer",
360fd4e5da5Sopenharmony_ci      "OpExtension \"SPV_KHR_variable_pointers\"");
361fd4e5da5Sopenharmony_ci
362fd4e5da5Sopenharmony_ci  const std::vector<std::string> valid_storage_classes = {
363fd4e5da5Sopenharmony_ci      "Function", "Private", "Workgroup", "StorageBuffer", "AtomicCounter"};
364fd4e5da5Sopenharmony_ci  bool valid_sc =
365fd4e5da5Sopenharmony_ci      std::find(valid_storage_classes.begin(), valid_storage_classes.end(),
366fd4e5da5Sopenharmony_ci                storage_class) != valid_storage_classes.end();
367fd4e5da5Sopenharmony_ci  bool validate =
368fd4e5da5Sopenharmony_ci      storage_class == "StorageBuffer" || storage_class == "UniformConstant";
369fd4e5da5Sopenharmony_ci
370fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
371fd4e5da5Sopenharmony_ci  if (validate) {
372fd4e5da5Sopenharmony_ci    EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
373fd4e5da5Sopenharmony_ci  } else {
374fd4e5da5Sopenharmony_ci    EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
375fd4e5da5Sopenharmony_ci    if (valid_sc) {
376fd4e5da5Sopenharmony_ci      EXPECT_THAT(
377fd4e5da5Sopenharmony_ci          getDiagnosticString(),
378fd4e5da5Sopenharmony_ci          HasSubstr(
379fd4e5da5Sopenharmony_ci              "Pointer operand '2[%gep]' must be a memory object declaration"));
380fd4e5da5Sopenharmony_ci    } else {
381fd4e5da5Sopenharmony_ci      EXPECT_THAT(
382fd4e5da5Sopenharmony_ci          getDiagnosticString(),
383fd4e5da5Sopenharmony_ci          HasSubstr("Invalid storage class for pointer operand '2[%gep]'"));
384fd4e5da5Sopenharmony_ci    }
385fd4e5da5Sopenharmony_ci  }
386fd4e5da5Sopenharmony_ci}
387fd4e5da5Sopenharmony_ci
388fd4e5da5Sopenharmony_ciTEST_P(ValidateFunctionCall, NonMemoryObjectDeclarationVariablePointers) {
389fd4e5da5Sopenharmony_ci  const std::string storage_class = GetParam();
390fd4e5da5Sopenharmony_ci
391fd4e5da5Sopenharmony_ci  std::string spirv =
392fd4e5da5Sopenharmony_ci      GenerateShaderAccessChain(storage_class, "OpCapability VariablePointers",
393fd4e5da5Sopenharmony_ci                                "OpExtension \"SPV_KHR_variable_pointers\"");
394fd4e5da5Sopenharmony_ci
395fd4e5da5Sopenharmony_ci  const std::vector<std::string> valid_storage_classes = {
396fd4e5da5Sopenharmony_ci      "Function", "Private", "Workgroup", "StorageBuffer", "AtomicCounter"};
397fd4e5da5Sopenharmony_ci  bool valid_sc =
398fd4e5da5Sopenharmony_ci      std::find(valid_storage_classes.begin(), valid_storage_classes.end(),
399fd4e5da5Sopenharmony_ci                storage_class) != valid_storage_classes.end();
400fd4e5da5Sopenharmony_ci  bool validate = storage_class == "StorageBuffer" ||
401fd4e5da5Sopenharmony_ci                  storage_class == "Workgroup" ||
402fd4e5da5Sopenharmony_ci                  storage_class == "UniformConstant";
403fd4e5da5Sopenharmony_ci
404fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
405fd4e5da5Sopenharmony_ci  if (validate) {
406fd4e5da5Sopenharmony_ci    EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
407fd4e5da5Sopenharmony_ci  } else {
408fd4e5da5Sopenharmony_ci    EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
409fd4e5da5Sopenharmony_ci    if (valid_sc) {
410fd4e5da5Sopenharmony_ci      EXPECT_THAT(
411fd4e5da5Sopenharmony_ci          getDiagnosticString(),
412fd4e5da5Sopenharmony_ci          HasSubstr(
413fd4e5da5Sopenharmony_ci              "Pointer operand '2[%gep]' must be a memory object declaration"));
414fd4e5da5Sopenharmony_ci    } else {
415fd4e5da5Sopenharmony_ci      EXPECT_THAT(
416fd4e5da5Sopenharmony_ci          getDiagnosticString(),
417fd4e5da5Sopenharmony_ci          HasSubstr("Invalid storage class for pointer operand '2[%gep]'"));
418fd4e5da5Sopenharmony_ci    }
419fd4e5da5Sopenharmony_ci  }
420fd4e5da5Sopenharmony_ci}
421fd4e5da5Sopenharmony_ci
422fd4e5da5Sopenharmony_ciTEST_F(ValidateFunctionCall, LogicallyMatchingPointers) {
423fd4e5da5Sopenharmony_ci  std::string spirv =
424fd4e5da5Sopenharmony_ci      R"(
425fd4e5da5Sopenharmony_ci               OpCapability Shader
426fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
427fd4e5da5Sopenharmony_ci               OpEntryPoint GLCompute %1 "main"
428fd4e5da5Sopenharmony_ci               OpExecutionMode %1 LocalSize 1 1 1
429fd4e5da5Sopenharmony_ci               OpSource HLSL 600
430fd4e5da5Sopenharmony_ci               OpDecorate %2 DescriptorSet 0
431fd4e5da5Sopenharmony_ci               OpDecorate %2 Binding 0
432fd4e5da5Sopenharmony_ci               OpMemberDecorate %_struct_3 0 Offset 0
433fd4e5da5Sopenharmony_ci               OpDecorate %_runtimearr__struct_3 ArrayStride 4
434fd4e5da5Sopenharmony_ci               OpMemberDecorate %_struct_5 0 Offset 0
435fd4e5da5Sopenharmony_ci               OpDecorate %_struct_5 BufferBlock
436fd4e5da5Sopenharmony_ci        %int = OpTypeInt 32 1
437fd4e5da5Sopenharmony_ci      %int_0 = OpConstant %int 0
438fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
439fd4e5da5Sopenharmony_ci     %uint_0 = OpConstant %uint 0
440fd4e5da5Sopenharmony_ci  %_struct_3 = OpTypeStruct %int
441fd4e5da5Sopenharmony_ci%_runtimearr__struct_3 = OpTypeRuntimeArray %_struct_3
442fd4e5da5Sopenharmony_ci  %_struct_5 = OpTypeStruct %_runtimearr__struct_3
443fd4e5da5Sopenharmony_ci%_ptr_Uniform__struct_5 = OpTypePointer Uniform %_struct_5
444fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
445fd4e5da5Sopenharmony_ci         %14 = OpTypeFunction %void
446fd4e5da5Sopenharmony_ci %_struct_15 = OpTypeStruct %int
447fd4e5da5Sopenharmony_ci%_ptr_Function__struct_15 = OpTypePointer Function %_struct_15
448fd4e5da5Sopenharmony_ci%_ptr_Uniform__struct_3 = OpTypePointer Uniform %_struct_3
449fd4e5da5Sopenharmony_ci         %18 = OpTypeFunction %void %_ptr_Function__struct_15
450fd4e5da5Sopenharmony_ci          %2 = OpVariable %_ptr_Uniform__struct_5 Uniform
451fd4e5da5Sopenharmony_ci          %1 = OpFunction %void None %14
452fd4e5da5Sopenharmony_ci         %19 = OpLabel
453fd4e5da5Sopenharmony_ci         %20 = OpAccessChain %_ptr_Uniform__struct_3 %2 %int_0 %uint_0
454fd4e5da5Sopenharmony_ci         %21 = OpFunctionCall %void %22 %20
455fd4e5da5Sopenharmony_ci               OpReturn
456fd4e5da5Sopenharmony_ci               OpFunctionEnd
457fd4e5da5Sopenharmony_ci         %22 = OpFunction %void None %18
458fd4e5da5Sopenharmony_ci         %23 = OpFunctionParameter %_ptr_Function__struct_15
459fd4e5da5Sopenharmony_ci         %24 = OpLabel
460fd4e5da5Sopenharmony_ci               OpReturn
461fd4e5da5Sopenharmony_ci               OpFunctionEnd
462fd4e5da5Sopenharmony_ci)";
463fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
464fd4e5da5Sopenharmony_ci  spvValidatorOptionsSetBeforeHlslLegalization(getValidatorOptions(), true);
465fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
466fd4e5da5Sopenharmony_ci}
467fd4e5da5Sopenharmony_ci
468fd4e5da5Sopenharmony_ciTEST_F(ValidateFunctionCall, LogicallyMatchingPointersNestedStruct) {
469fd4e5da5Sopenharmony_ci  std::string spirv =
470fd4e5da5Sopenharmony_ci      R"(
471fd4e5da5Sopenharmony_ci               OpCapability Shader
472fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
473fd4e5da5Sopenharmony_ci               OpEntryPoint GLCompute %1 "main"
474fd4e5da5Sopenharmony_ci               OpExecutionMode %1 LocalSize 1 1 1
475fd4e5da5Sopenharmony_ci               OpSource HLSL 600
476fd4e5da5Sopenharmony_ci               OpDecorate %2 DescriptorSet 0
477fd4e5da5Sopenharmony_ci               OpDecorate %2 Binding 0
478fd4e5da5Sopenharmony_ci               OpMemberDecorate %_struct_3 0 Offset 0
479fd4e5da5Sopenharmony_ci               OpMemberDecorate %_struct_4 0 Offset 0
480fd4e5da5Sopenharmony_ci               OpDecorate %_runtimearr__struct_4 ArrayStride 4
481fd4e5da5Sopenharmony_ci               OpMemberDecorate %_struct_6 0 Offset 0
482fd4e5da5Sopenharmony_ci               OpDecorate %_struct_6 BufferBlock
483fd4e5da5Sopenharmony_ci        %int = OpTypeInt 32 1
484fd4e5da5Sopenharmony_ci      %int_0 = OpConstant %int 0
485fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
486fd4e5da5Sopenharmony_ci     %uint_0 = OpConstant %uint 0
487fd4e5da5Sopenharmony_ci  %_struct_3 = OpTypeStruct %int
488fd4e5da5Sopenharmony_ci  %_struct_4 = OpTypeStruct %_struct_3
489fd4e5da5Sopenharmony_ci%_runtimearr__struct_4 = OpTypeRuntimeArray %_struct_4
490fd4e5da5Sopenharmony_ci  %_struct_6 = OpTypeStruct %_runtimearr__struct_4
491fd4e5da5Sopenharmony_ci%_ptr_Uniform__struct_6 = OpTypePointer Uniform %_struct_6
492fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
493fd4e5da5Sopenharmony_ci         %13 = OpTypeFunction %void
494fd4e5da5Sopenharmony_ci %_struct_14 = OpTypeStruct %int
495fd4e5da5Sopenharmony_ci %_struct_15 = OpTypeStruct %_struct_14
496fd4e5da5Sopenharmony_ci%_ptr_Function__struct_15 = OpTypePointer Function %_struct_15
497fd4e5da5Sopenharmony_ci%_ptr_Uniform__struct_4 = OpTypePointer Uniform %_struct_4
498fd4e5da5Sopenharmony_ci         %18 = OpTypeFunction %void %_ptr_Function__struct_15
499fd4e5da5Sopenharmony_ci          %2 = OpVariable %_ptr_Uniform__struct_6 Uniform
500fd4e5da5Sopenharmony_ci          %1 = OpFunction %void None %13
501fd4e5da5Sopenharmony_ci         %19 = OpLabel
502fd4e5da5Sopenharmony_ci         %20 = OpVariable %_ptr_Function__struct_15 Function
503fd4e5da5Sopenharmony_ci         %21 = OpAccessChain %_ptr_Uniform__struct_4 %2 %int_0 %uint_0
504fd4e5da5Sopenharmony_ci         %22 = OpFunctionCall %void %23 %21
505fd4e5da5Sopenharmony_ci               OpReturn
506fd4e5da5Sopenharmony_ci               OpFunctionEnd
507fd4e5da5Sopenharmony_ci         %23 = OpFunction %void None %18
508fd4e5da5Sopenharmony_ci         %24 = OpFunctionParameter %_ptr_Function__struct_15
509fd4e5da5Sopenharmony_ci         %25 = OpLabel
510fd4e5da5Sopenharmony_ci               OpReturn
511fd4e5da5Sopenharmony_ci               OpFunctionEnd
512fd4e5da5Sopenharmony_ci)";
513fd4e5da5Sopenharmony_ci
514fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
515fd4e5da5Sopenharmony_ci  spvValidatorOptionsSetBeforeHlslLegalization(getValidatorOptions(), true);
516fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
517fd4e5da5Sopenharmony_ci}
518fd4e5da5Sopenharmony_ci
519fd4e5da5Sopenharmony_ciTEST_F(ValidateFunctionCall, LogicallyMatchingPointersNestedArray) {
520fd4e5da5Sopenharmony_ci  std::string spirv =
521fd4e5da5Sopenharmony_ci      R"(
522fd4e5da5Sopenharmony_ci              OpCapability Shader
523fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
524fd4e5da5Sopenharmony_ci               OpEntryPoint GLCompute %1 "main"
525fd4e5da5Sopenharmony_ci               OpExecutionMode %1 LocalSize 1 1 1
526fd4e5da5Sopenharmony_ci               OpSource HLSL 600
527fd4e5da5Sopenharmony_ci               OpDecorate %2 DescriptorSet 0
528fd4e5da5Sopenharmony_ci               OpDecorate %2 Binding 0
529fd4e5da5Sopenharmony_ci               OpDecorate %_arr_int_uint_10 ArrayStride 4
530fd4e5da5Sopenharmony_ci               OpMemberDecorate %_struct_4 0 Offset 0
531fd4e5da5Sopenharmony_ci               OpDecorate %_runtimearr__struct_4 ArrayStride 40
532fd4e5da5Sopenharmony_ci               OpMemberDecorate %_struct_6 0 Offset 0
533fd4e5da5Sopenharmony_ci               OpDecorate %_struct_6 BufferBlock
534fd4e5da5Sopenharmony_ci        %int = OpTypeInt 32 1
535fd4e5da5Sopenharmony_ci      %int_0 = OpConstant %int 0
536fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
537fd4e5da5Sopenharmony_ci     %uint_0 = OpConstant %uint 0
538fd4e5da5Sopenharmony_ci    %uint_10 = OpConstant %uint 10
539fd4e5da5Sopenharmony_ci%_arr_int_uint_10 = OpTypeArray %int %uint_10
540fd4e5da5Sopenharmony_ci  %_struct_4 = OpTypeStruct %_arr_int_uint_10
541fd4e5da5Sopenharmony_ci%_runtimearr__struct_4 = OpTypeRuntimeArray %_struct_4
542fd4e5da5Sopenharmony_ci  %_struct_6 = OpTypeStruct %_runtimearr__struct_4
543fd4e5da5Sopenharmony_ci%_ptr_Uniform__struct_6 = OpTypePointer Uniform %_struct_6
544fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
545fd4e5da5Sopenharmony_ci         %14 = OpTypeFunction %void
546fd4e5da5Sopenharmony_ci%_ptr_Uniform__struct_4 = OpTypePointer Uniform %_struct_4
547fd4e5da5Sopenharmony_ci%_arr_int_uint_10_0 = OpTypeArray %int %uint_10
548fd4e5da5Sopenharmony_ci %_struct_17 = OpTypeStruct %_arr_int_uint_10_0
549fd4e5da5Sopenharmony_ci%_ptr_Function__struct_17 = OpTypePointer Function %_struct_17
550fd4e5da5Sopenharmony_ci         %19 = OpTypeFunction %void %_ptr_Function__struct_17
551fd4e5da5Sopenharmony_ci          %2 = OpVariable %_ptr_Uniform__struct_6 Uniform
552fd4e5da5Sopenharmony_ci          %1 = OpFunction %void None %14
553fd4e5da5Sopenharmony_ci         %20 = OpLabel
554fd4e5da5Sopenharmony_ci         %21 = OpAccessChain %_ptr_Uniform__struct_4 %2 %int_0 %uint_0
555fd4e5da5Sopenharmony_ci         %22 = OpFunctionCall %void %23 %21
556fd4e5da5Sopenharmony_ci               OpReturn
557fd4e5da5Sopenharmony_ci               OpFunctionEnd
558fd4e5da5Sopenharmony_ci         %23 = OpFunction %void None %19
559fd4e5da5Sopenharmony_ci         %24 = OpFunctionParameter %_ptr_Function__struct_17
560fd4e5da5Sopenharmony_ci         %25 = OpLabel
561fd4e5da5Sopenharmony_ci               OpReturn
562fd4e5da5Sopenharmony_ci               OpFunctionEnd
563fd4e5da5Sopenharmony_ci)";
564fd4e5da5Sopenharmony_ci
565fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
566fd4e5da5Sopenharmony_ci  spvValidatorOptionsSetBeforeHlslLegalization(getValidatorOptions(), true);
567fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
568fd4e5da5Sopenharmony_ci}
569fd4e5da5Sopenharmony_ci
570fd4e5da5Sopenharmony_ciTEST_F(ValidateFunctionCall, LogicallyMismatchedPointersMissingMember) {
571fd4e5da5Sopenharmony_ci  //  Validation should fail because the formal parameter type has two members,
572fd4e5da5Sopenharmony_ci  //  while the actual parameter only has 1.
573fd4e5da5Sopenharmony_ci  std::string spirv =
574fd4e5da5Sopenharmony_ci      R"(
575fd4e5da5Sopenharmony_ci               OpCapability Shader
576fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
577fd4e5da5Sopenharmony_ci               OpEntryPoint GLCompute %1 "main"
578fd4e5da5Sopenharmony_ci               OpExecutionMode %1 LocalSize 1 1 1
579fd4e5da5Sopenharmony_ci               OpSource HLSL 600
580fd4e5da5Sopenharmony_ci               OpDecorate %2 DescriptorSet 0
581fd4e5da5Sopenharmony_ci               OpDecorate %2 Binding 0
582fd4e5da5Sopenharmony_ci               OpMemberDecorate %_struct_3 0 Offset 0
583fd4e5da5Sopenharmony_ci               OpDecorate %_runtimearr__struct_3 ArrayStride 4
584fd4e5da5Sopenharmony_ci               OpMemberDecorate %_struct_5 0 Offset 0
585fd4e5da5Sopenharmony_ci               OpDecorate %_struct_5 BufferBlock
586fd4e5da5Sopenharmony_ci        %int = OpTypeInt 32 1
587fd4e5da5Sopenharmony_ci      %int_0 = OpConstant %int 0
588fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
589fd4e5da5Sopenharmony_ci     %uint_0 = OpConstant %uint 0
590fd4e5da5Sopenharmony_ci  %_struct_3 = OpTypeStruct %int
591fd4e5da5Sopenharmony_ci%_runtimearr__struct_3 = OpTypeRuntimeArray %_struct_3
592fd4e5da5Sopenharmony_ci  %_struct_5 = OpTypeStruct %_runtimearr__struct_3
593fd4e5da5Sopenharmony_ci%_ptr_Uniform__struct_5 = OpTypePointer Uniform %_struct_5
594fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
595fd4e5da5Sopenharmony_ci         %14 = OpTypeFunction %void
596fd4e5da5Sopenharmony_ci %_struct_15 = OpTypeStruct %int %int
597fd4e5da5Sopenharmony_ci%_ptr_Function__struct_15 = OpTypePointer Function %_struct_15
598fd4e5da5Sopenharmony_ci%_ptr_Uniform__struct_3 = OpTypePointer Uniform %_struct_3
599fd4e5da5Sopenharmony_ci         %18 = OpTypeFunction %void %_ptr_Function__struct_15
600fd4e5da5Sopenharmony_ci          %2 = OpVariable %_ptr_Uniform__struct_5 Uniform
601fd4e5da5Sopenharmony_ci          %1 = OpFunction %void None %14
602fd4e5da5Sopenharmony_ci         %19 = OpLabel
603fd4e5da5Sopenharmony_ci         %20 = OpAccessChain %_ptr_Uniform__struct_3 %2 %int_0 %uint_0
604fd4e5da5Sopenharmony_ci         %21 = OpFunctionCall %void %22 %20
605fd4e5da5Sopenharmony_ci               OpReturn
606fd4e5da5Sopenharmony_ci               OpFunctionEnd
607fd4e5da5Sopenharmony_ci         %22 = OpFunction %void None %18
608fd4e5da5Sopenharmony_ci         %23 = OpFunctionParameter %_ptr_Function__struct_15
609fd4e5da5Sopenharmony_ci         %24 = OpLabel
610fd4e5da5Sopenharmony_ci               OpReturn
611fd4e5da5Sopenharmony_ci               OpFunctionEnd
612fd4e5da5Sopenharmony_ci)";
613fd4e5da5Sopenharmony_ci
614fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
615fd4e5da5Sopenharmony_ci  spvValidatorOptionsSetBeforeHlslLegalization(getValidatorOptions(), true);
616fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
617fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr("OpFunctionCall Argument <id>"));
618fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
619fd4e5da5Sopenharmony_ci              HasSubstr("type does not match Function <id>"));
620fd4e5da5Sopenharmony_ci}
621fd4e5da5Sopenharmony_ci
622fd4e5da5Sopenharmony_ciTEST_F(ValidateFunctionCall, LogicallyMismatchedPointersDifferentMemberType) {
623fd4e5da5Sopenharmony_ci  //  Validation should fail because the formal parameter has a member that is
624fd4e5da5Sopenharmony_ci  // a different type than the actual parameter.
625fd4e5da5Sopenharmony_ci  std::string spirv =
626fd4e5da5Sopenharmony_ci      R"(
627fd4e5da5Sopenharmony_ci               OpCapability Shader
628fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
629fd4e5da5Sopenharmony_ci               OpEntryPoint GLCompute %1 "main"
630fd4e5da5Sopenharmony_ci               OpExecutionMode %1 LocalSize 1 1 1
631fd4e5da5Sopenharmony_ci               OpSource HLSL 600
632fd4e5da5Sopenharmony_ci               OpDecorate %2 DescriptorSet 0
633fd4e5da5Sopenharmony_ci               OpDecorate %2 Binding 0
634fd4e5da5Sopenharmony_ci               OpMemberDecorate %_struct_3 0 Offset 0
635fd4e5da5Sopenharmony_ci               OpDecorate %_runtimearr__struct_3 ArrayStride 4
636fd4e5da5Sopenharmony_ci               OpMemberDecorate %_struct_5 0 Offset 0
637fd4e5da5Sopenharmony_ci               OpDecorate %_struct_5 BufferBlock
638fd4e5da5Sopenharmony_ci        %int = OpTypeInt 32 1
639fd4e5da5Sopenharmony_ci      %int_0 = OpConstant %int 0
640fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
641fd4e5da5Sopenharmony_ci     %uint_0 = OpConstant %uint 0
642fd4e5da5Sopenharmony_ci  %_struct_3 = OpTypeStruct %uint
643fd4e5da5Sopenharmony_ci%_runtimearr__struct_3 = OpTypeRuntimeArray %_struct_3
644fd4e5da5Sopenharmony_ci  %_struct_5 = OpTypeStruct %_runtimearr__struct_3
645fd4e5da5Sopenharmony_ci%_ptr_Uniform__struct_5 = OpTypePointer Uniform %_struct_5
646fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
647fd4e5da5Sopenharmony_ci         %14 = OpTypeFunction %void
648fd4e5da5Sopenharmony_ci %_struct_15 = OpTypeStruct %int
649fd4e5da5Sopenharmony_ci%_ptr_Function__struct_15 = OpTypePointer Function %_struct_15
650fd4e5da5Sopenharmony_ci%_ptr_Uniform__struct_3 = OpTypePointer Uniform %_struct_3
651fd4e5da5Sopenharmony_ci         %18 = OpTypeFunction %void %_ptr_Function__struct_15
652fd4e5da5Sopenharmony_ci          %2 = OpVariable %_ptr_Uniform__struct_5 Uniform
653fd4e5da5Sopenharmony_ci          %1 = OpFunction %void None %14
654fd4e5da5Sopenharmony_ci         %19 = OpLabel
655fd4e5da5Sopenharmony_ci         %20 = OpAccessChain %_ptr_Uniform__struct_3 %2 %int_0 %uint_0
656fd4e5da5Sopenharmony_ci         %21 = OpFunctionCall %void %22 %20
657fd4e5da5Sopenharmony_ci               OpReturn
658fd4e5da5Sopenharmony_ci               OpFunctionEnd
659fd4e5da5Sopenharmony_ci         %22 = OpFunction %void None %18
660fd4e5da5Sopenharmony_ci         %23 = OpFunctionParameter %_ptr_Function__struct_15
661fd4e5da5Sopenharmony_ci         %24 = OpLabel
662fd4e5da5Sopenharmony_ci               OpReturn
663fd4e5da5Sopenharmony_ci               OpFunctionEnd
664fd4e5da5Sopenharmony_ci)";
665fd4e5da5Sopenharmony_ci
666fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
667fd4e5da5Sopenharmony_ci  spvValidatorOptionsSetBeforeHlslLegalization(getValidatorOptions(), true);
668fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
669fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr("OpFunctionCall Argument <id>"));
670fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
671fd4e5da5Sopenharmony_ci              HasSubstr("type does not match Function <id>"));
672fd4e5da5Sopenharmony_ci}
673fd4e5da5Sopenharmony_ci
674fd4e5da5Sopenharmony_ciTEST_F(ValidateFunctionCall,
675fd4e5da5Sopenharmony_ci       LogicallyMismatchedPointersIncompatableDecorations) {
676fd4e5da5Sopenharmony_ci  //  Validation should fail because the formal parameter has an incompatible
677fd4e5da5Sopenharmony_ci  //  decoration.
678fd4e5da5Sopenharmony_ci  std::string spirv =
679fd4e5da5Sopenharmony_ci      R"(
680fd4e5da5Sopenharmony_ci               OpCapability Shader
681fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
682fd4e5da5Sopenharmony_ci               OpEntryPoint GLCompute %1 "main"
683fd4e5da5Sopenharmony_ci               OpExecutionMode %1 LocalSize 1 1 1
684fd4e5da5Sopenharmony_ci               OpSource HLSL 600
685fd4e5da5Sopenharmony_ci               OpDecorate %2 DescriptorSet 0
686fd4e5da5Sopenharmony_ci               OpDecorate %2 Binding 0
687fd4e5da5Sopenharmony_ci               OpMemberDecorate %_struct_3 0 Offset 0
688fd4e5da5Sopenharmony_ci               OpDecorate %_runtimearr__struct_3 ArrayStride 4
689fd4e5da5Sopenharmony_ci               OpMemberDecorate %_struct_5 0 Offset 0
690fd4e5da5Sopenharmony_ci               OpDecorate %_struct_5 Block
691fd4e5da5Sopenharmony_ci               OpMemberDecorate %_struct_15 0 NonWritable
692fd4e5da5Sopenharmony_ci        %int = OpTypeInt 32 1
693fd4e5da5Sopenharmony_ci      %int_0 = OpConstant %int 0
694fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
695fd4e5da5Sopenharmony_ci     %uint_0 = OpConstant %uint 0
696fd4e5da5Sopenharmony_ci  %_struct_3 = OpTypeStruct %int
697fd4e5da5Sopenharmony_ci%_runtimearr__struct_3 = OpTypeRuntimeArray %_struct_3
698fd4e5da5Sopenharmony_ci  %_struct_5 = OpTypeStruct %_runtimearr__struct_3
699fd4e5da5Sopenharmony_ci%_ptr_StorageBuffer__struct_5 = OpTypePointer StorageBuffer %_struct_5
700fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
701fd4e5da5Sopenharmony_ci         %14 = OpTypeFunction %void
702fd4e5da5Sopenharmony_ci %_struct_15 = OpTypeStruct %int
703fd4e5da5Sopenharmony_ci%_ptr_Function__struct_15 = OpTypePointer Function %_struct_15
704fd4e5da5Sopenharmony_ci%_ptr_StorageBuffer__struct_3 = OpTypePointer StorageBuffer %_struct_3
705fd4e5da5Sopenharmony_ci         %18 = OpTypeFunction %void %_ptr_Function__struct_15
706fd4e5da5Sopenharmony_ci          %2 = OpVariable %_ptr_StorageBuffer__struct_5 StorageBuffer
707fd4e5da5Sopenharmony_ci          %1 = OpFunction %void None %14
708fd4e5da5Sopenharmony_ci         %19 = OpLabel
709fd4e5da5Sopenharmony_ci         %20 = OpAccessChain %_ptr_StorageBuffer__struct_3 %2 %int_0 %uint_0
710fd4e5da5Sopenharmony_ci         %21 = OpFunctionCall %void %22 %20
711fd4e5da5Sopenharmony_ci               OpReturn
712fd4e5da5Sopenharmony_ci               OpFunctionEnd
713fd4e5da5Sopenharmony_ci         %22 = OpFunction %void None %18
714fd4e5da5Sopenharmony_ci         %23 = OpFunctionParameter %_ptr_Function__struct_15
715fd4e5da5Sopenharmony_ci         %24 = OpLabel
716fd4e5da5Sopenharmony_ci               OpReturn
717fd4e5da5Sopenharmony_ci               OpFunctionEnd
718fd4e5da5Sopenharmony_ci)";
719fd4e5da5Sopenharmony_ci
720fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_4);
721fd4e5da5Sopenharmony_ci  spvValidatorOptionsSetBeforeHlslLegalization(getValidatorOptions(), true);
722fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_4));
723fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr("OpFunctionCall Argument <id>"));
724fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
725fd4e5da5Sopenharmony_ci              HasSubstr("type does not match Function <id>"));
726fd4e5da5Sopenharmony_ci}
727fd4e5da5Sopenharmony_ci
728fd4e5da5Sopenharmony_ciTEST_F(ValidateFunctionCall,
729fd4e5da5Sopenharmony_ci       LogicallyMismatchedPointersIncompatableDecorations2) {
730fd4e5da5Sopenharmony_ci  //  Validation should fail because the formal parameter has an incompatible
731fd4e5da5Sopenharmony_ci  //  decoration.
732fd4e5da5Sopenharmony_ci  std::string spirv =
733fd4e5da5Sopenharmony_ci      R"(
734fd4e5da5Sopenharmony_ci               OpCapability Shader
735fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
736fd4e5da5Sopenharmony_ci               OpEntryPoint GLCompute %1 "main"
737fd4e5da5Sopenharmony_ci               OpExecutionMode %1 LocalSize 1 1 1
738fd4e5da5Sopenharmony_ci               OpSource HLSL 600
739fd4e5da5Sopenharmony_ci               OpDecorate %2 DescriptorSet 0
740fd4e5da5Sopenharmony_ci               OpDecorate %2 Binding 0
741fd4e5da5Sopenharmony_ci               OpMemberDecorate %_struct_3 0 Offset 0
742fd4e5da5Sopenharmony_ci               OpDecorate %_runtimearr__struct_3 ArrayStride 4
743fd4e5da5Sopenharmony_ci               OpMemberDecorate %_struct_5 0 Offset 0
744fd4e5da5Sopenharmony_ci               OpDecorate %_struct_5 BufferBlock
745fd4e5da5Sopenharmony_ci               OpDecorate %_ptr_Uniform__struct_3 ArrayStride 4
746fd4e5da5Sopenharmony_ci               OpDecorate %_ptr_Uniform__struct_3_0 ArrayStride 8
747fd4e5da5Sopenharmony_ci        %int = OpTypeInt 32 1
748fd4e5da5Sopenharmony_ci      %int_0 = OpConstant %int 0
749fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
750fd4e5da5Sopenharmony_ci     %uint_0 = OpConstant %uint 0
751fd4e5da5Sopenharmony_ci  %_struct_3 = OpTypeStruct %int
752fd4e5da5Sopenharmony_ci%_runtimearr__struct_3 = OpTypeRuntimeArray %_struct_3
753fd4e5da5Sopenharmony_ci  %_struct_5 = OpTypeStruct %_runtimearr__struct_3
754fd4e5da5Sopenharmony_ci%_ptr_Uniform__struct_5 = OpTypePointer Uniform %_struct_5
755fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
756fd4e5da5Sopenharmony_ci         %14 = OpTypeFunction %void
757fd4e5da5Sopenharmony_ci%_ptr_Uniform__struct_3 = OpTypePointer Uniform %_struct_3
758fd4e5da5Sopenharmony_ci%_ptr_Uniform__struct_3_0 = OpTypePointer Uniform %_struct_3
759fd4e5da5Sopenharmony_ci         %18 = OpTypeFunction %void %_ptr_Uniform__struct_3_0
760fd4e5da5Sopenharmony_ci          %2 = OpVariable %_ptr_Uniform__struct_5 Uniform
761fd4e5da5Sopenharmony_ci          %1 = OpFunction %void None %14
762fd4e5da5Sopenharmony_ci         %19 = OpLabel
763fd4e5da5Sopenharmony_ci         %20 = OpAccessChain %_ptr_Uniform__struct_3 %2 %int_0 %uint_0
764fd4e5da5Sopenharmony_ci         %21 = OpFunctionCall %void %22 %20
765fd4e5da5Sopenharmony_ci               OpReturn
766fd4e5da5Sopenharmony_ci               OpFunctionEnd
767fd4e5da5Sopenharmony_ci         %22 = OpFunction %void None %18
768fd4e5da5Sopenharmony_ci         %23 = OpFunctionParameter %_ptr_Uniform__struct_3_0
769fd4e5da5Sopenharmony_ci         %24 = OpLabel
770fd4e5da5Sopenharmony_ci               OpReturn
771fd4e5da5Sopenharmony_ci               OpFunctionEnd
772fd4e5da5Sopenharmony_ci)";
773fd4e5da5Sopenharmony_ci
774fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
775fd4e5da5Sopenharmony_ci  spvValidatorOptionsSetBeforeHlslLegalization(getValidatorOptions(), true);
776fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
777fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr("OpFunctionCall Argument <id>"));
778fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
779fd4e5da5Sopenharmony_ci              HasSubstr("type does not match Function <id>"));
780fd4e5da5Sopenharmony_ci}
781fd4e5da5Sopenharmony_ci
782fd4e5da5Sopenharmony_ciTEST_F(ValidateFunctionCall, LogicallyMismatchedPointersArraySize) {
783fd4e5da5Sopenharmony_ci  //  Validation should fail because the formal parameter array has a different
784fd4e5da5Sopenharmony_ci  // number of element than the actual parameter.
785fd4e5da5Sopenharmony_ci  std::string spirv =
786fd4e5da5Sopenharmony_ci      R"(
787fd4e5da5Sopenharmony_ci               OpCapability Shader
788fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
789fd4e5da5Sopenharmony_ci               OpEntryPoint GLCompute %1 "main"
790fd4e5da5Sopenharmony_ci               OpExecutionMode %1 LocalSize 1 1 1
791fd4e5da5Sopenharmony_ci               OpSource HLSL 600
792fd4e5da5Sopenharmony_ci               OpDecorate %2 DescriptorSet 0
793fd4e5da5Sopenharmony_ci               OpDecorate %2 Binding 0
794fd4e5da5Sopenharmony_ci               OpDecorate %_arr_int_uint_10 ArrayStride 4
795fd4e5da5Sopenharmony_ci               OpMemberDecorate %_struct_4 0 Offset 0
796fd4e5da5Sopenharmony_ci               OpDecorate %_runtimearr__struct_4 ArrayStride 40
797fd4e5da5Sopenharmony_ci               OpMemberDecorate %_struct_6 0 Offset 0
798fd4e5da5Sopenharmony_ci               OpDecorate %_struct_6 BufferBlock
799fd4e5da5Sopenharmony_ci        %int = OpTypeInt 32 1
800fd4e5da5Sopenharmony_ci      %int_0 = OpConstant %int 0
801fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
802fd4e5da5Sopenharmony_ci     %uint_0 = OpConstant %uint 0
803fd4e5da5Sopenharmony_ci    %uint_5 = OpConstant %uint 5
804fd4e5da5Sopenharmony_ci    %uint_10 = OpConstant %uint 10
805fd4e5da5Sopenharmony_ci%_arr_int_uint_10 = OpTypeArray %int %uint_10
806fd4e5da5Sopenharmony_ci  %_struct_4 = OpTypeStruct %_arr_int_uint_10
807fd4e5da5Sopenharmony_ci%_runtimearr__struct_4 = OpTypeRuntimeArray %_struct_4
808fd4e5da5Sopenharmony_ci  %_struct_6 = OpTypeStruct %_runtimearr__struct_4
809fd4e5da5Sopenharmony_ci%_ptr_Uniform__struct_6 = OpTypePointer Uniform %_struct_6
810fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
811fd4e5da5Sopenharmony_ci         %14 = OpTypeFunction %void
812fd4e5da5Sopenharmony_ci%_ptr_Uniform__struct_4 = OpTypePointer Uniform %_struct_4
813fd4e5da5Sopenharmony_ci%_arr_int_uint_5 = OpTypeArray %int %uint_5
814fd4e5da5Sopenharmony_ci %_struct_17 = OpTypeStruct %_arr_int_uint_5
815fd4e5da5Sopenharmony_ci%_ptr_Function__struct_17 = OpTypePointer Function %_struct_17
816fd4e5da5Sopenharmony_ci         %19 = OpTypeFunction %void %_ptr_Function__struct_17
817fd4e5da5Sopenharmony_ci          %2 = OpVariable %_ptr_Uniform__struct_6 Uniform
818fd4e5da5Sopenharmony_ci          %1 = OpFunction %void None %14
819fd4e5da5Sopenharmony_ci         %20 = OpLabel
820fd4e5da5Sopenharmony_ci         %21 = OpAccessChain %_ptr_Uniform__struct_4 %2 %int_0 %uint_0
821fd4e5da5Sopenharmony_ci         %22 = OpFunctionCall %void %23 %21
822fd4e5da5Sopenharmony_ci               OpReturn
823fd4e5da5Sopenharmony_ci               OpFunctionEnd
824fd4e5da5Sopenharmony_ci         %23 = OpFunction %void None %19
825fd4e5da5Sopenharmony_ci         %24 = OpFunctionParameter %_ptr_Function__struct_17
826fd4e5da5Sopenharmony_ci         %25 = OpLabel
827fd4e5da5Sopenharmony_ci               OpReturn
828fd4e5da5Sopenharmony_ci               OpFunctionEnd
829fd4e5da5Sopenharmony_ci)";
830fd4e5da5Sopenharmony_ci
831fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
832fd4e5da5Sopenharmony_ci  spvValidatorOptionsSetBeforeHlslLegalization(getValidatorOptions(), true);
833fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
834fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr("OpFunctionCall Argument <id>"));
835fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
836fd4e5da5Sopenharmony_ci              HasSubstr("type does not match Function <id>"));
837fd4e5da5Sopenharmony_ci}
838fd4e5da5Sopenharmony_ci
839fd4e5da5Sopenharmony_ciINSTANTIATE_TEST_SUITE_P(StorageClass, ValidateFunctionCall,
840fd4e5da5Sopenharmony_ci                         Values("UniformConstant", "Input", "Uniform", "Output",
841fd4e5da5Sopenharmony_ci                                "Workgroup", "Private", "Function",
842fd4e5da5Sopenharmony_ci                                "PushConstant", "Image", "StorageBuffer",
843fd4e5da5Sopenharmony_ci                                "AtomicCounter"));
844fd4e5da5Sopenharmony_ci}  // namespace
845fd4e5da5Sopenharmony_ci}  // namespace val
846fd4e5da5Sopenharmony_ci}  // namespace spvtools
847