1fd4e5da5Sopenharmony_ci// Copyright (c) 2015-2016 The Khronos Group 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#include <vector>
18fd4e5da5Sopenharmony_ci
19fd4e5da5Sopenharmony_ci#include "gmock/gmock.h"
20fd4e5da5Sopenharmony_ci#include "test/test_fixture.h"
21fd4e5da5Sopenharmony_ci#include "test/unit_spirv.h"
22fd4e5da5Sopenharmony_ci#include "test/val/val_fixtures.h"
23fd4e5da5Sopenharmony_ci
24fd4e5da5Sopenharmony_ci// NOTE: The tests in this file are ONLY testing ID usage, there for the input
25fd4e5da5Sopenharmony_ci// SPIR-V does not follow the logical layout rules from the spec in all cases in
26fd4e5da5Sopenharmony_ci// order to makes the tests smaller. Validation of the whole module is handled
27fd4e5da5Sopenharmony_ci// in stages, ID validation is only one of these stages. All validation stages
28fd4e5da5Sopenharmony_ci// are stand alone.
29fd4e5da5Sopenharmony_ci
30fd4e5da5Sopenharmony_cinamespace spvtools {
31fd4e5da5Sopenharmony_cinamespace val {
32fd4e5da5Sopenharmony_cinamespace {
33fd4e5da5Sopenharmony_ci
34fd4e5da5Sopenharmony_ciusing spvtest::ScopedContext;
35fd4e5da5Sopenharmony_ciusing ::testing::HasSubstr;
36fd4e5da5Sopenharmony_ciusing ::testing::ValuesIn;
37fd4e5da5Sopenharmony_ci
38fd4e5da5Sopenharmony_ciclass ValidateIdWithMessage : public spvtest::ValidateBase<bool> {
39fd4e5da5Sopenharmony_ci public:
40fd4e5da5Sopenharmony_ci  ValidateIdWithMessage() {
41fd4e5da5Sopenharmony_ci    const bool use_friendly_names = GetParam();
42fd4e5da5Sopenharmony_ci    spvValidatorOptionsSetFriendlyNames(options_, use_friendly_names);
43fd4e5da5Sopenharmony_ci  }
44fd4e5da5Sopenharmony_ci
45fd4e5da5Sopenharmony_ci  std::string make_message(const char* msg);
46fd4e5da5Sopenharmony_ci};
47fd4e5da5Sopenharmony_ci
48fd4e5da5Sopenharmony_cistd::string kOpCapabilitySetupWithoutVector16 = R"(
49fd4e5da5Sopenharmony_ci     OpCapability Shader
50fd4e5da5Sopenharmony_ci     OpCapability Linkage
51fd4e5da5Sopenharmony_ci     OpCapability Addresses
52fd4e5da5Sopenharmony_ci     OpCapability Int8
53fd4e5da5Sopenharmony_ci     OpCapability Int16
54fd4e5da5Sopenharmony_ci     OpCapability Int64
55fd4e5da5Sopenharmony_ci     OpCapability Float64
56fd4e5da5Sopenharmony_ci     OpCapability LiteralSampler
57fd4e5da5Sopenharmony_ci     OpCapability Pipes
58fd4e5da5Sopenharmony_ci     OpCapability DeviceEnqueue
59fd4e5da5Sopenharmony_ci)";
60fd4e5da5Sopenharmony_ci
61fd4e5da5Sopenharmony_cistd::string kOpCapabilitySetup = R"(
62fd4e5da5Sopenharmony_ci     OpCapability Shader
63fd4e5da5Sopenharmony_ci     OpCapability Linkage
64fd4e5da5Sopenharmony_ci     OpCapability Addresses
65fd4e5da5Sopenharmony_ci     OpCapability Int8
66fd4e5da5Sopenharmony_ci     OpCapability Int16
67fd4e5da5Sopenharmony_ci     OpCapability Int64
68fd4e5da5Sopenharmony_ci     OpCapability Float64
69fd4e5da5Sopenharmony_ci     OpCapability LiteralSampler
70fd4e5da5Sopenharmony_ci     OpCapability Pipes
71fd4e5da5Sopenharmony_ci     OpCapability DeviceEnqueue
72fd4e5da5Sopenharmony_ci     OpCapability Vector16
73fd4e5da5Sopenharmony_ci)";
74fd4e5da5Sopenharmony_ci
75fd4e5da5Sopenharmony_cistd::string kOpVariablePtrSetUp = R"(
76fd4e5da5Sopenharmony_ci     OpCapability VariablePointers
77fd4e5da5Sopenharmony_ci     OpExtension "SPV_KHR_variable_pointers"
78fd4e5da5Sopenharmony_ci)";
79fd4e5da5Sopenharmony_ci
80fd4e5da5Sopenharmony_cistd::string kGLSL450MemoryModel =
81fd4e5da5Sopenharmony_ci    kOpCapabilitySetup + kOpVariablePtrSetUp + R"(
82fd4e5da5Sopenharmony_ci     OpMemoryModel Logical GLSL450
83fd4e5da5Sopenharmony_ci)";
84fd4e5da5Sopenharmony_ci
85fd4e5da5Sopenharmony_cistd::string kGLSL450MemoryModelWithoutVector16 =
86fd4e5da5Sopenharmony_ci    kOpCapabilitySetupWithoutVector16 + kOpVariablePtrSetUp + R"(
87fd4e5da5Sopenharmony_ci     OpMemoryModel Logical GLSL450
88fd4e5da5Sopenharmony_ci)";
89fd4e5da5Sopenharmony_ci
90fd4e5da5Sopenharmony_cistd::string kNoKernelGLSL450MemoryModel = R"(
91fd4e5da5Sopenharmony_ci     OpCapability Shader
92fd4e5da5Sopenharmony_ci     OpCapability Linkage
93fd4e5da5Sopenharmony_ci     OpCapability Addresses
94fd4e5da5Sopenharmony_ci     OpCapability Int8
95fd4e5da5Sopenharmony_ci     OpCapability Int16
96fd4e5da5Sopenharmony_ci     OpCapability Int64
97fd4e5da5Sopenharmony_ci     OpCapability Float64
98fd4e5da5Sopenharmony_ci     OpMemoryModel Logical GLSL450
99fd4e5da5Sopenharmony_ci)";
100fd4e5da5Sopenharmony_ci
101fd4e5da5Sopenharmony_cistd::string kOpenCLMemoryModel32 = R"(
102fd4e5da5Sopenharmony_ci     OpCapability Addresses
103fd4e5da5Sopenharmony_ci     OpCapability Linkage
104fd4e5da5Sopenharmony_ci     OpCapability Kernel
105fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "OpenCL.std"
106fd4e5da5Sopenharmony_ci     OpMemoryModel Physical32 OpenCL
107fd4e5da5Sopenharmony_ci)";
108fd4e5da5Sopenharmony_ci
109fd4e5da5Sopenharmony_cistd::string kOpenCLMemoryModel64 = R"(
110fd4e5da5Sopenharmony_ci     OpCapability Addresses
111fd4e5da5Sopenharmony_ci     OpCapability Linkage
112fd4e5da5Sopenharmony_ci     OpCapability Kernel
113fd4e5da5Sopenharmony_ci     OpCapability Int64
114fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "OpenCL.std"
115fd4e5da5Sopenharmony_ci     OpMemoryModel Physical64 OpenCL
116fd4e5da5Sopenharmony_ci)";
117fd4e5da5Sopenharmony_ci
118fd4e5da5Sopenharmony_cistd::string sampledImageSetup = R"(
119fd4e5da5Sopenharmony_ci                    %void = OpTypeVoid
120fd4e5da5Sopenharmony_ci            %typeFuncVoid = OpTypeFunction %void
121fd4e5da5Sopenharmony_ci                   %float = OpTypeFloat 32
122fd4e5da5Sopenharmony_ci                 %v4float = OpTypeVector %float 4
123fd4e5da5Sopenharmony_ci              %image_type = OpTypeImage %float 2D 0 0 0 1 Unknown
124fd4e5da5Sopenharmony_ci%_ptr_UniformConstant_img = OpTypePointer UniformConstant %image_type
125fd4e5da5Sopenharmony_ci                     %tex = OpVariable %_ptr_UniformConstant_img UniformConstant
126fd4e5da5Sopenharmony_ci            %sampler_type = OpTypeSampler
127fd4e5da5Sopenharmony_ci%_ptr_UniformConstant_sam = OpTypePointer UniformConstant %sampler_type
128fd4e5da5Sopenharmony_ci                       %s = OpVariable %_ptr_UniformConstant_sam UniformConstant
129fd4e5da5Sopenharmony_ci      %sampled_image_type = OpTypeSampledImage %image_type
130fd4e5da5Sopenharmony_ci                 %v2float = OpTypeVector %float 2
131fd4e5da5Sopenharmony_ci                 %float_1 = OpConstant %float 1
132fd4e5da5Sopenharmony_ci                 %float_2 = OpConstant %float 2
133fd4e5da5Sopenharmony_ci           %const_vec_1_1 = OpConstantComposite %v2float %float_1 %float_1
134fd4e5da5Sopenharmony_ci           %const_vec_2_2 = OpConstantComposite %v2float %float_2 %float_2
135fd4e5da5Sopenharmony_ci               %bool_type = OpTypeBool
136fd4e5da5Sopenharmony_ci               %spec_true = OpSpecConstantTrue %bool_type
137fd4e5da5Sopenharmony_ci                    %main = OpFunction %void None %typeFuncVoid
138fd4e5da5Sopenharmony_ci                 %label_1 = OpLabel
139fd4e5da5Sopenharmony_ci              %image_inst = OpLoad %image_type %tex
140fd4e5da5Sopenharmony_ci            %sampler_inst = OpLoad %sampler_type %s
141fd4e5da5Sopenharmony_ci)";
142fd4e5da5Sopenharmony_ci
143fd4e5da5Sopenharmony_cistd::string BranchConditionalSetup = R"(
144fd4e5da5Sopenharmony_ci               OpCapability Shader
145fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
146fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
147fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %main "main"
148fd4e5da5Sopenharmony_ci               OpExecutionMode %main OriginUpperLeft
149fd4e5da5Sopenharmony_ci               OpSource GLSL 140
150fd4e5da5Sopenharmony_ci               OpName %main "main"
151fd4e5da5Sopenharmony_ci
152fd4e5da5Sopenharmony_ci             ; type definitions
153fd4e5da5Sopenharmony_ci       %bool = OpTypeBool
154fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
155fd4e5da5Sopenharmony_ci        %int = OpTypeInt 32 1
156fd4e5da5Sopenharmony_ci      %float = OpTypeFloat 32
157fd4e5da5Sopenharmony_ci    %v4float = OpTypeVector %float 4
158fd4e5da5Sopenharmony_ci
159fd4e5da5Sopenharmony_ci             ; constants
160fd4e5da5Sopenharmony_ci       %true = OpConstantTrue %bool
161fd4e5da5Sopenharmony_ci         %i0 = OpConstant %int 0
162fd4e5da5Sopenharmony_ci         %i1 = OpConstant %int 1
163fd4e5da5Sopenharmony_ci         %f0 = OpConstant %float 0
164fd4e5da5Sopenharmony_ci         %f1 = OpConstant %float 1
165fd4e5da5Sopenharmony_ci
166fd4e5da5Sopenharmony_ci
167fd4e5da5Sopenharmony_ci             ; main function header
168fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
169fd4e5da5Sopenharmony_ci   %voidfunc = OpTypeFunction %void
170fd4e5da5Sopenharmony_ci       %main = OpFunction %void None %voidfunc
171fd4e5da5Sopenharmony_ci      %lmain = OpLabel
172fd4e5da5Sopenharmony_ci)";
173fd4e5da5Sopenharmony_ci
174fd4e5da5Sopenharmony_cistd::string BranchConditionalTail = R"(
175fd4e5da5Sopenharmony_ci   %target_t = OpLabel
176fd4e5da5Sopenharmony_ci               OpNop
177fd4e5da5Sopenharmony_ci               OpBranch %end
178fd4e5da5Sopenharmony_ci   %target_f = OpLabel
179fd4e5da5Sopenharmony_ci               OpNop
180fd4e5da5Sopenharmony_ci               OpBranch %end
181fd4e5da5Sopenharmony_ci
182fd4e5da5Sopenharmony_ci        %end = OpLabel
183fd4e5da5Sopenharmony_ci
184fd4e5da5Sopenharmony_ci               OpReturn
185fd4e5da5Sopenharmony_ci               OpFunctionEnd
186fd4e5da5Sopenharmony_ci)";
187fd4e5da5Sopenharmony_ci
188fd4e5da5Sopenharmony_ci// Transform an expected validation message to either use friendly names (as
189fd4e5da5Sopenharmony_ci// provided in the message) or replace the friendly names by the corresponding
190fd4e5da5Sopenharmony_ci// id.  The same flag used to configure the validator to output friendly names
191fd4e5da5Sopenharmony_ci// or not is used here.
192fd4e5da5Sopenharmony_cistd::string ValidateIdWithMessage::make_message(const char* msg) {
193fd4e5da5Sopenharmony_ci  const bool use_friendly_names = GetParam();
194fd4e5da5Sopenharmony_ci  if (use_friendly_names) {
195fd4e5da5Sopenharmony_ci    return msg;
196fd4e5da5Sopenharmony_ci  }
197fd4e5da5Sopenharmony_ci
198fd4e5da5Sopenharmony_ci  std::string message(msg);
199fd4e5da5Sopenharmony_ci  std::ostringstream result;
200fd4e5da5Sopenharmony_ci
201fd4e5da5Sopenharmony_ci  size_t next = 0;
202fd4e5da5Sopenharmony_ci  while (next < message.size()) {
203fd4e5da5Sopenharmony_ci    // Parse 'num[%name]'
204fd4e5da5Sopenharmony_ci    size_t open_quote = message.find('\'', next);
205fd4e5da5Sopenharmony_ci
206fd4e5da5Sopenharmony_ci    if (open_quote == std::string::npos) {
207fd4e5da5Sopenharmony_ci      break;
208fd4e5da5Sopenharmony_ci    }
209fd4e5da5Sopenharmony_ci
210fd4e5da5Sopenharmony_ci    // Copy up to the first quote
211fd4e5da5Sopenharmony_ci    result.write(msg + next, open_quote - next);
212fd4e5da5Sopenharmony_ci    // Handle apostrophes
213fd4e5da5Sopenharmony_ci    if (!isdigit(message[open_quote + 1])) {
214fd4e5da5Sopenharmony_ci      result << '\'';
215fd4e5da5Sopenharmony_ci      next = open_quote + 1;
216fd4e5da5Sopenharmony_ci      continue;
217fd4e5da5Sopenharmony_ci    }
218fd4e5da5Sopenharmony_ci
219fd4e5da5Sopenharmony_ci    size_t open_bracket = message.find('[', open_quote + 1);
220fd4e5da5Sopenharmony_ci    assert(open_bracket != std::string::npos);
221fd4e5da5Sopenharmony_ci
222fd4e5da5Sopenharmony_ci    size_t close_bracket = message.find(']', open_bracket + 1);
223fd4e5da5Sopenharmony_ci    assert(close_bracket != std::string::npos);
224fd4e5da5Sopenharmony_ci
225fd4e5da5Sopenharmony_ci    size_t close_quote = close_bracket + 1;
226fd4e5da5Sopenharmony_ci    assert(close_quote < message.size() && message[close_quote] == '\'');
227fd4e5da5Sopenharmony_ci
228fd4e5da5Sopenharmony_ci    // Change to 'num[%num]' because friendly names are not being used.
229fd4e5da5Sopenharmony_ci    result.write(msg + open_quote, open_bracket - open_quote + 1);
230fd4e5da5Sopenharmony_ci    result << '%';
231fd4e5da5Sopenharmony_ci    result.write(msg + open_quote + 1, open_bracket - open_quote - 1);
232fd4e5da5Sopenharmony_ci    result << "]'";
233fd4e5da5Sopenharmony_ci
234fd4e5da5Sopenharmony_ci    // Continue to the next id, or end of string.
235fd4e5da5Sopenharmony_ci    next = close_quote + 1;
236fd4e5da5Sopenharmony_ci  }
237fd4e5da5Sopenharmony_ci
238fd4e5da5Sopenharmony_ci  return result.str();
239fd4e5da5Sopenharmony_ci}
240fd4e5da5Sopenharmony_ci
241fd4e5da5Sopenharmony_ci// TODO: OpUndef
242fd4e5da5Sopenharmony_ci
243fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpName) {
244fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
245fd4e5da5Sopenharmony_ci     OpName %2 "name"
246fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
247fd4e5da5Sopenharmony_ci%2 = OpTypePointer UniformConstant %1
248fd4e5da5Sopenharmony_ci%3 = OpVariable %2 UniformConstant)";
249fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
250fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
251fd4e5da5Sopenharmony_ci}
252fd4e5da5Sopenharmony_ci
253fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpMemberNameGood) {
254fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
255fd4e5da5Sopenharmony_ci     OpMemberName %2 0 "foo"
256fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
257fd4e5da5Sopenharmony_ci%2 = OpTypeStruct %1)";
258fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
259fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
260fd4e5da5Sopenharmony_ci}
261fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpMemberNameTypeBad) {
262fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
263fd4e5da5Sopenharmony_ci     OpMemberName %1 0 "foo"
264fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0)";
265fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
266fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
267fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
268fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
269fd4e5da5Sopenharmony_ci                  "OpMemberName Type <id> '1[%uint]' is not a struct type.")));
270fd4e5da5Sopenharmony_ci}
271fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpMemberNameMemberBad) {
272fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
273fd4e5da5Sopenharmony_ci     OpMemberName %1 1 "foo"
274fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
275fd4e5da5Sopenharmony_ci%1 = OpTypeStruct %2)";
276fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
277fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
278fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
279fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
280fd4e5da5Sopenharmony_ci                  "OpMemberName Member <id> '1[%_struct_1]' index is larger "
281fd4e5da5Sopenharmony_ci                  "than Type <id> '1[%_struct_1]'s member count.")));
282fd4e5da5Sopenharmony_ci}
283fd4e5da5Sopenharmony_ci
284fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpLineGood) {
285fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
286fd4e5da5Sopenharmony_ci%1 = OpString "/path/to/source.file"
287fd4e5da5Sopenharmony_ci     OpLine %1 0 0
288fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
289fd4e5da5Sopenharmony_ci%3 = OpTypePointer Input %2
290fd4e5da5Sopenharmony_ci%4 = OpVariable %3 Input)";
291fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
292fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
293fd4e5da5Sopenharmony_ci}
294fd4e5da5Sopenharmony_ci
295fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpLineFileBad) {
296fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
297fd4e5da5Sopenharmony_ci  %1 = OpTypeInt 32 0
298fd4e5da5Sopenharmony_ci     OpLine %1 0 0
299fd4e5da5Sopenharmony_ci  )";
300fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
301fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
302fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
303fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
304fd4e5da5Sopenharmony_ci                  "OpLine Target <id> '1[%uint]' is not an OpString.")));
305fd4e5da5Sopenharmony_ci}
306fd4e5da5Sopenharmony_ci
307fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpDecorateGood) {
308fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
309fd4e5da5Sopenharmony_ci     OpDecorate %2 GLSLShared
310fd4e5da5Sopenharmony_ci%1 = OpTypeInt 64 0
311fd4e5da5Sopenharmony_ci%2 = OpTypeStruct %1 %1)";
312fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
313fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
314fd4e5da5Sopenharmony_ci}
315fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpDecorateBad) {
316fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
317fd4e5da5Sopenharmony_ciOpDecorate %1 GLSLShared)";
318fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
319fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
320fd4e5da5Sopenharmony_ci  EXPECT_THAT(
321fd4e5da5Sopenharmony_ci      getDiagnosticString(),
322fd4e5da5Sopenharmony_ci      HasSubstr(make_message("forward referenced IDs have not been defined")));
323fd4e5da5Sopenharmony_ci}
324fd4e5da5Sopenharmony_ci
325fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpMemberDecorateGood) {
326fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
327fd4e5da5Sopenharmony_ci     OpMemberDecorate %2 0 RelaxedPrecision
328fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
329fd4e5da5Sopenharmony_ci%2 = OpTypeStruct %1 %1)";
330fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
331fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
332fd4e5da5Sopenharmony_ci}
333fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpMemberDecorateBad) {
334fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
335fd4e5da5Sopenharmony_ci     OpMemberDecorate %1 0 RelaxedPrecision
336fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0)";
337fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
338fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
339fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
340fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
341fd4e5da5Sopenharmony_ci                  "OpMemberDecorate Structure type <id> '1[%uint]' is "
342fd4e5da5Sopenharmony_ci                  "not a struct type.")));
343fd4e5da5Sopenharmony_ci}
344fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpMemberDecorateMemberBad) {
345fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
346fd4e5da5Sopenharmony_ci     OpMemberDecorate %1 3 RelaxedPrecision
347fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
348fd4e5da5Sopenharmony_ci%1 = OpTypeStruct %int %int)";
349fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
350fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
351fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
352fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
353fd4e5da5Sopenharmony_ci                  "Index 3 provided in OpMemberDecorate for struct <id> "
354fd4e5da5Sopenharmony_ci                  "'1[%_struct_1]' is out of bounds. The structure has 2 "
355fd4e5da5Sopenharmony_ci                  "members. Largest valid index is 1.")));
356fd4e5da5Sopenharmony_ci}
357fd4e5da5Sopenharmony_ci
358fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpGroupDecorateGood) {
359fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
360fd4e5da5Sopenharmony_ci%1 = OpDecorationGroup
361fd4e5da5Sopenharmony_ci     OpDecorate %1 RelaxedPrecision
362fd4e5da5Sopenharmony_ci     OpDecorate %1 GLSLShared
363fd4e5da5Sopenharmony_ci     OpGroupDecorate %1 %3 %4
364fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
365fd4e5da5Sopenharmony_ci%3 = OpConstant %2 42
366fd4e5da5Sopenharmony_ci%4 = OpConstant %2 23)";
367fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
368fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
369fd4e5da5Sopenharmony_ci}
370fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpDecorationGroupBad) {
371fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
372fd4e5da5Sopenharmony_ci%1 = OpDecorationGroup
373fd4e5da5Sopenharmony_ci     OpDecorate %1 RelaxedPrecision
374fd4e5da5Sopenharmony_ci     OpDecorate %1 GLSLShared
375fd4e5da5Sopenharmony_ci     OpMemberDecorate %1 0 Constant
376fd4e5da5Sopenharmony_ci    )";
377fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
378fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
379fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
380fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
381fd4e5da5Sopenharmony_ci                  "Result id of OpDecorationGroup can only "
382fd4e5da5Sopenharmony_ci                  "be targeted by OpName, OpGroupDecorate, "
383fd4e5da5Sopenharmony_ci                  "OpDecorate, OpDecorateId, and OpGroupMemberDecorate")));
384fd4e5da5Sopenharmony_ci}
385fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpGroupDecorateDecorationGroupBad) {
386fd4e5da5Sopenharmony_ci  std::string spirv = R"(
387fd4e5da5Sopenharmony_ci    OpCapability Shader
388fd4e5da5Sopenharmony_ci    OpCapability Linkage
389fd4e5da5Sopenharmony_ci    %1 = OpExtInstImport "GLSL.std.450"
390fd4e5da5Sopenharmony_ci    OpMemoryModel Logical GLSL450
391fd4e5da5Sopenharmony_ci    OpGroupDecorate %1 %2 %3
392fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
393fd4e5da5Sopenharmony_ci%3 = OpConstant %2 42)";
394fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
395fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
396fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
397fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
398fd4e5da5Sopenharmony_ci                  "OpGroupDecorate Decoration group <id> '1[%1]' is not "
399fd4e5da5Sopenharmony_ci                  "a decoration group.")));
400fd4e5da5Sopenharmony_ci}
401fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpGroupDecorateTargetBad) {
402fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
403fd4e5da5Sopenharmony_ci%1 = OpDecorationGroup
404fd4e5da5Sopenharmony_ci     OpDecorate %1 RelaxedPrecision
405fd4e5da5Sopenharmony_ci     OpDecorate %1 GLSLShared
406fd4e5da5Sopenharmony_ci     OpGroupDecorate %1 %3
407fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0)";
408fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
409fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
410fd4e5da5Sopenharmony_ci  EXPECT_THAT(
411fd4e5da5Sopenharmony_ci      getDiagnosticString(),
412fd4e5da5Sopenharmony_ci      HasSubstr(make_message("forward referenced IDs have not been defined")));
413fd4e5da5Sopenharmony_ci}
414fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpGroupMemberDecorateDecorationGroupBad) {
415fd4e5da5Sopenharmony_ci  std::string spirv = R"(
416fd4e5da5Sopenharmony_ci    OpCapability Shader
417fd4e5da5Sopenharmony_ci    OpCapability Linkage
418fd4e5da5Sopenharmony_ci    %1 = OpExtInstImport "GLSL.std.450"
419fd4e5da5Sopenharmony_ci    OpMemoryModel Logical GLSL450
420fd4e5da5Sopenharmony_ci    OpGroupMemberDecorate %1 %2 0
421fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0)";
422fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
423fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
424fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
425fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
426fd4e5da5Sopenharmony_ci                  "OpGroupMemberDecorate Decoration group <id> '1[%1]' "
427fd4e5da5Sopenharmony_ci                  "is not a decoration group.")));
428fd4e5da5Sopenharmony_ci}
429fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpGroupMemberDecorateIdNotStructBad) {
430fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
431fd4e5da5Sopenharmony_ci     %1 = OpDecorationGroup
432fd4e5da5Sopenharmony_ci     OpGroupMemberDecorate %1 %2 0
433fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0)";
434fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
435fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
436fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
437fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
438fd4e5da5Sopenharmony_ci                  "OpGroupMemberDecorate Structure type <id> '2[%uint]' "
439fd4e5da5Sopenharmony_ci                  "is not a struct type.")));
440fd4e5da5Sopenharmony_ci}
441fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpGroupMemberDecorateIndexOutOfBoundBad) {
442fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
443fd4e5da5Sopenharmony_ci  OpDecorate %1 Offset 0
444fd4e5da5Sopenharmony_ci  %1 = OpDecorationGroup
445fd4e5da5Sopenharmony_ci  OpGroupMemberDecorate %1 %struct 3
446fd4e5da5Sopenharmony_ci%float  = OpTypeFloat 32
447fd4e5da5Sopenharmony_ci%struct = OpTypeStruct %float %float %float
448fd4e5da5Sopenharmony_ci)";
449fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
450fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
451fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
452fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
453fd4e5da5Sopenharmony_ci                  "Index 3 provided in OpGroupMemberDecorate for struct "
454fd4e5da5Sopenharmony_ci                  "<id> '2[%_struct_2]' is out of bounds. The structure "
455fd4e5da5Sopenharmony_ci                  "has 3 members. Largest valid index is 2.")));
456fd4e5da5Sopenharmony_ci}
457fd4e5da5Sopenharmony_ci
458fd4e5da5Sopenharmony_ci// TODO: OpExtInst
459fd4e5da5Sopenharmony_ci
460fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpEntryPointGood) {
461fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
462fd4e5da5Sopenharmony_ci     OpEntryPoint GLCompute %3 ""
463fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
464fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %1
465fd4e5da5Sopenharmony_ci%3 = OpFunction %1 None %2
466fd4e5da5Sopenharmony_ci%4 = OpLabel
467fd4e5da5Sopenharmony_ci     OpReturn
468fd4e5da5Sopenharmony_ci     OpFunctionEnd
469fd4e5da5Sopenharmony_ci)";
470fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
471fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
472fd4e5da5Sopenharmony_ci}
473fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpEntryPointFunctionBad) {
474fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
475fd4e5da5Sopenharmony_ci     OpEntryPoint GLCompute %1 ""
476fd4e5da5Sopenharmony_ci%1 = OpTypeVoid)";
477fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
478fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
479fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
480fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
481fd4e5da5Sopenharmony_ci                  "OpEntryPoint Entry Point <id> '1[%void]' is not a "
482fd4e5da5Sopenharmony_ci                  "function.")));
483fd4e5da5Sopenharmony_ci}
484fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpEntryPointParameterCountBad) {
485fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
486fd4e5da5Sopenharmony_ci     OpEntryPoint GLCompute %1 ""
487fd4e5da5Sopenharmony_ci%2 = OpTypeVoid
488fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %2 %2
489fd4e5da5Sopenharmony_ci%1 = OpFunction %2 None %3
490fd4e5da5Sopenharmony_ci%4 = OpLabel
491fd4e5da5Sopenharmony_ci     OpReturn
492fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
493fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
494fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
495fd4e5da5Sopenharmony_ci  EXPECT_THAT(
496fd4e5da5Sopenharmony_ci      getDiagnosticString(),
497fd4e5da5Sopenharmony_ci      HasSubstr(make_message("OpEntryPoint Entry Point <id> '1[%1]'s function "
498fd4e5da5Sopenharmony_ci                             "parameter count is not zero")));
499fd4e5da5Sopenharmony_ci}
500fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpEntryPointReturnTypeBad) {
501fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
502fd4e5da5Sopenharmony_ci     OpEntryPoint GLCompute %1 ""
503fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
504fd4e5da5Sopenharmony_ci%ret = OpConstant %2 0
505fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %2
506fd4e5da5Sopenharmony_ci%1 = OpFunction %2 None %3
507fd4e5da5Sopenharmony_ci%4 = OpLabel
508fd4e5da5Sopenharmony_ci     OpReturnValue %ret
509fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
510fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
511fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
512fd4e5da5Sopenharmony_ci  EXPECT_THAT(
513fd4e5da5Sopenharmony_ci      getDiagnosticString(),
514fd4e5da5Sopenharmony_ci      HasSubstr(make_message("OpEntryPoint Entry Point <id> '1[%1]'s function "
515fd4e5da5Sopenharmony_ci                             "return type is not void.")));
516fd4e5da5Sopenharmony_ci}
517fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpEntryPointParameterCountBadInVulkan) {
518fd4e5da5Sopenharmony_ci  std::string spirv = R"(
519fd4e5da5Sopenharmony_ci     OpCapability Shader
520fd4e5da5Sopenharmony_ci     OpMemoryModel Logical GLSL450
521fd4e5da5Sopenharmony_ci     OpEntryPoint GLCompute %1 ""
522fd4e5da5Sopenharmony_ci%2 = OpTypeVoid
523fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %2 %2
524fd4e5da5Sopenharmony_ci%1 = OpFunction %2 None %3
525fd4e5da5Sopenharmony_ci%4 = OpLabel
526fd4e5da5Sopenharmony_ci     OpReturn
527fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
528fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_0);
529fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
530fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
531fd4e5da5Sopenharmony_ci              AnyVUID("VUID-StandaloneSpirv-None-04633"));
532fd4e5da5Sopenharmony_ci  EXPECT_THAT(
533fd4e5da5Sopenharmony_ci      getDiagnosticString(),
534fd4e5da5Sopenharmony_ci      HasSubstr(make_message("OpEntryPoint Entry Point <id> '1[%1]'s function "
535fd4e5da5Sopenharmony_ci                             "parameter count is not zero")));
536fd4e5da5Sopenharmony_ci}
537fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpEntryPointReturnTypeBadInVulkan) {
538fd4e5da5Sopenharmony_ci  std::string spirv = R"(
539fd4e5da5Sopenharmony_ci     OpCapability Shader
540fd4e5da5Sopenharmony_ci     OpMemoryModel Logical GLSL450
541fd4e5da5Sopenharmony_ci     OpEntryPoint GLCompute %1 ""
542fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
543fd4e5da5Sopenharmony_ci%ret = OpConstant %2 0
544fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %2
545fd4e5da5Sopenharmony_ci%1 = OpFunction %2 None %3
546fd4e5da5Sopenharmony_ci%4 = OpLabel
547fd4e5da5Sopenharmony_ci     OpReturnValue %ret
548fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
549fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_0);
550fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
551fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
552fd4e5da5Sopenharmony_ci              AnyVUID("VUID-StandaloneSpirv-None-04633"));
553fd4e5da5Sopenharmony_ci  EXPECT_THAT(
554fd4e5da5Sopenharmony_ci      getDiagnosticString(),
555fd4e5da5Sopenharmony_ci      HasSubstr(make_message("OpEntryPoint Entry Point <id> '1[%1]'s function "
556fd4e5da5Sopenharmony_ci                             "return type is not void.")));
557fd4e5da5Sopenharmony_ci}
558fd4e5da5Sopenharmony_ci
559fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpEntryPointInterfaceIsNotVariableTypeBad) {
560fd4e5da5Sopenharmony_ci  std::string spirv = R"(
561fd4e5da5Sopenharmony_ci               OpCapability Shader
562fd4e5da5Sopenharmony_ci               OpCapability Geometry
563fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
564fd4e5da5Sopenharmony_ci               OpEntryPoint Geometry %main "main" %ptr_builtin_1
565fd4e5da5Sopenharmony_ci               OpExecutionMode %main InputPoints
566fd4e5da5Sopenharmony_ci               OpExecutionMode %main OutputPoints
567fd4e5da5Sopenharmony_ci               OpMemberDecorate %struct_1 0 BuiltIn InvocationId
568fd4e5da5Sopenharmony_ci      %int = OpTypeInt 32 1
569fd4e5da5Sopenharmony_ci     %void = OpTypeVoid
570fd4e5da5Sopenharmony_ci     %func = OpTypeFunction %void
571fd4e5da5Sopenharmony_ci %struct_1 = OpTypeStruct %int
572fd4e5da5Sopenharmony_ci%ptr_builtin_1 = OpTypePointer Input %struct_1
573fd4e5da5Sopenharmony_ci       %main = OpFunction %void None %func
574fd4e5da5Sopenharmony_ci          %5 = OpLabel
575fd4e5da5Sopenharmony_ci               OpReturn
576fd4e5da5Sopenharmony_ci               OpFunctionEnd
577fd4e5da5Sopenharmony_ci  )";
578fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
579fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
580fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
581fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
582fd4e5da5Sopenharmony_ci                  "Interfaces passed to OpEntryPoint must be of type "
583fd4e5da5Sopenharmony_ci                  "OpTypeVariable. Found OpTypePointer.")));
584fd4e5da5Sopenharmony_ci}
585fd4e5da5Sopenharmony_ci
586fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpEntryPointInterfaceStorageClassBad) {
587fd4e5da5Sopenharmony_ci  std::string spirv = R"(
588fd4e5da5Sopenharmony_ci               OpCapability Shader
589fd4e5da5Sopenharmony_ci               OpCapability Geometry
590fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
591fd4e5da5Sopenharmony_ci               OpEntryPoint Geometry %main "main" %in_1
592fd4e5da5Sopenharmony_ci               OpExecutionMode %main InputPoints
593fd4e5da5Sopenharmony_ci               OpExecutionMode %main OutputPoints
594fd4e5da5Sopenharmony_ci               OpMemberDecorate %struct_1 0 BuiltIn InvocationId
595fd4e5da5Sopenharmony_ci      %int = OpTypeInt 32 1
596fd4e5da5Sopenharmony_ci     %void = OpTypeVoid
597fd4e5da5Sopenharmony_ci     %func = OpTypeFunction %void
598fd4e5da5Sopenharmony_ci %struct_1 = OpTypeStruct %int
599fd4e5da5Sopenharmony_ci%ptr_builtin_1 = OpTypePointer Uniform %struct_1
600fd4e5da5Sopenharmony_ci       %in_1 = OpVariable %ptr_builtin_1 Uniform
601fd4e5da5Sopenharmony_ci       %main = OpFunction %void None %func
602fd4e5da5Sopenharmony_ci          %5 = OpLabel
603fd4e5da5Sopenharmony_ci               OpReturn
604fd4e5da5Sopenharmony_ci               OpFunctionEnd
605fd4e5da5Sopenharmony_ci  )";
606fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
607fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
608fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
609fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
610fd4e5da5Sopenharmony_ci                  "OpEntryPoint interfaces must be OpVariables with "
611fd4e5da5Sopenharmony_ci                  "Storage Class of Input(1) or Output(3). Found Storage "
612fd4e5da5Sopenharmony_ci                  "Class 2 for Entry Point id 1.")));
613fd4e5da5Sopenharmony_ci}
614fd4e5da5Sopenharmony_ci
615fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpExecutionModeGood) {
616fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
617fd4e5da5Sopenharmony_ci     OpEntryPoint GLCompute %3 ""
618fd4e5da5Sopenharmony_ci     OpExecutionMode %3 LocalSize 1 1 1
619fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
620fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %1
621fd4e5da5Sopenharmony_ci%3 = OpFunction %1 None %2
622fd4e5da5Sopenharmony_ci%4 = OpLabel
623fd4e5da5Sopenharmony_ci     OpReturn
624fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
625fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
626fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
627fd4e5da5Sopenharmony_ci}
628fd4e5da5Sopenharmony_ci
629fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpExecutionModeEntryPointMissing) {
630fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
631fd4e5da5Sopenharmony_ci     OpExecutionMode %3 LocalSize 1 1 1
632fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
633fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %1
634fd4e5da5Sopenharmony_ci%3 = OpFunction %1 None %2
635fd4e5da5Sopenharmony_ci%4 = OpLabel
636fd4e5da5Sopenharmony_ci     OpReturn
637fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
638fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
639fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
640fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
641fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
642fd4e5da5Sopenharmony_ci                  "OpExecutionMode Entry Point <id> '1[%1]' is not the "
643fd4e5da5Sopenharmony_ci                  "Entry Point operand of an OpEntryPoint.")));
644fd4e5da5Sopenharmony_ci}
645fd4e5da5Sopenharmony_ci
646fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpExecutionModeEntryPointBad) {
647fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
648fd4e5da5Sopenharmony_ci     OpEntryPoint GLCompute %3 "" %a
649fd4e5da5Sopenharmony_ci     OpExecutionMode %a LocalSize 1 1 1
650fd4e5da5Sopenharmony_ci%void = OpTypeVoid
651fd4e5da5Sopenharmony_ci%ptr = OpTypePointer Input %void
652fd4e5da5Sopenharmony_ci%a = OpVariable %ptr Input
653fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %void
654fd4e5da5Sopenharmony_ci%3 = OpFunction %void None %2
655fd4e5da5Sopenharmony_ci%4 = OpLabel
656fd4e5da5Sopenharmony_ci     OpReturn
657fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
658fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
659fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
660fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
661fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
662fd4e5da5Sopenharmony_ci                  "OpExecutionMode Entry Point <id> '2[%2]' is not the "
663fd4e5da5Sopenharmony_ci                  "Entry Point operand of an OpEntryPoint.")));
664fd4e5da5Sopenharmony_ci}
665fd4e5da5Sopenharmony_ci
666fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpTypeVectorFloat) {
667fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
668fd4e5da5Sopenharmony_ci%1 = OpTypeFloat 32
669fd4e5da5Sopenharmony_ci%2 = OpTypeVector %1 4)";
670fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
671fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
672fd4e5da5Sopenharmony_ci}
673fd4e5da5Sopenharmony_ci
674fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpTypeVectorInt) {
675fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
676fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
677fd4e5da5Sopenharmony_ci%2 = OpTypeVector %1 4)";
678fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
679fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
680fd4e5da5Sopenharmony_ci}
681fd4e5da5Sopenharmony_ci
682fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpTypeVectorUInt) {
683fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
684fd4e5da5Sopenharmony_ci%1 = OpTypeInt 64 0
685fd4e5da5Sopenharmony_ci%2 = OpTypeVector %1 4)";
686fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
687fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
688fd4e5da5Sopenharmony_ci}
689fd4e5da5Sopenharmony_ci
690fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpTypeVectorBool) {
691fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
692fd4e5da5Sopenharmony_ci%1 = OpTypeBool
693fd4e5da5Sopenharmony_ci%2 = OpTypeVector %1 4)";
694fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
695fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
696fd4e5da5Sopenharmony_ci}
697fd4e5da5Sopenharmony_ci
698fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpTypeVectorComponentTypeBad) {
699fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
700fd4e5da5Sopenharmony_ci%1 = OpTypeFloat 32
701fd4e5da5Sopenharmony_ci%2 = OpTypePointer UniformConstant %1
702fd4e5da5Sopenharmony_ci%3 = OpTypeVector %2 4)";
703fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
704fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
705fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
706fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
707fd4e5da5Sopenharmony_ci                  "OpTypeVector Component Type <id> "
708fd4e5da5Sopenharmony_ci                  "'2[%_ptr_UniformConstant_float]' is not a scalar type.")));
709fd4e5da5Sopenharmony_ci}
710fd4e5da5Sopenharmony_ci
711fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpTypeVectorColumnCountLessThanTwoBad) {
712fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
713fd4e5da5Sopenharmony_ci%1 = OpTypeFloat 32
714fd4e5da5Sopenharmony_ci%2 = OpTypeVector %1 1)";
715fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
716fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
717fd4e5da5Sopenharmony_ci  EXPECT_THAT(
718fd4e5da5Sopenharmony_ci      getDiagnosticString(),
719fd4e5da5Sopenharmony_ci      HasSubstr(make_message(
720fd4e5da5Sopenharmony_ci          "Illegal number of components (1) for TypeVector\n  %v1float = "
721fd4e5da5Sopenharmony_ci          "OpTypeVector %float 1\n")));
722fd4e5da5Sopenharmony_ci}
723fd4e5da5Sopenharmony_ci
724fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpTypeVectorColumnCountGreaterThanFourBad) {
725fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
726fd4e5da5Sopenharmony_ci%1 = OpTypeFloat 32
727fd4e5da5Sopenharmony_ci%2 = OpTypeVector %1 5)";
728fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
729fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
730fd4e5da5Sopenharmony_ci  EXPECT_THAT(
731fd4e5da5Sopenharmony_ci      getDiagnosticString(),
732fd4e5da5Sopenharmony_ci      HasSubstr(make_message(
733fd4e5da5Sopenharmony_ci          "Illegal number of components (5) for TypeVector\n  %v5float = "
734fd4e5da5Sopenharmony_ci          "OpTypeVector %float 5\n")));
735fd4e5da5Sopenharmony_ci}
736fd4e5da5Sopenharmony_ci
737fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpTypeVectorColumnCountEightWithoutVector16Bad) {
738fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModelWithoutVector16 + R"(
739fd4e5da5Sopenharmony_ci%1 = OpTypeFloat 32
740fd4e5da5Sopenharmony_ci%2 = OpTypeVector %1 8)";
741fd4e5da5Sopenharmony_ci
742fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
743fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
744fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
745fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
746fd4e5da5Sopenharmony_ci                  "Having 8 components for TypeVector requires the Vector16 "
747fd4e5da5Sopenharmony_ci                  "capability\n  %v8float = OpTypeVector %float 8\n")));
748fd4e5da5Sopenharmony_ci}
749fd4e5da5Sopenharmony_ci
750fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage,
751fd4e5da5Sopenharmony_ci       OpTypeVectorColumnCountSixteenWithoutVector16Bad) {
752fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModelWithoutVector16 + R"(
753fd4e5da5Sopenharmony_ci%1 = OpTypeFloat 32
754fd4e5da5Sopenharmony_ci%2 = OpTypeVector %1 16)";
755fd4e5da5Sopenharmony_ci
756fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
757fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
758fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
759fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
760fd4e5da5Sopenharmony_ci                  "Having 16 components for TypeVector requires the Vector16 "
761fd4e5da5Sopenharmony_ci                  "capability\n  %v16float = OpTypeVector %float 16\n")));
762fd4e5da5Sopenharmony_ci}
763fd4e5da5Sopenharmony_ci
764fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpTypeVectorColumnCountOfEightWithVector16Good) {
765fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
766fd4e5da5Sopenharmony_ci%1 = OpTypeFloat 32
767fd4e5da5Sopenharmony_ci%2 = OpTypeVector %1 8)";
768fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
769fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
770fd4e5da5Sopenharmony_ci}
771fd4e5da5Sopenharmony_ci
772fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage,
773fd4e5da5Sopenharmony_ci       OpTypeVectorColumnCountOfSixteenWithVector16Good) {
774fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
775fd4e5da5Sopenharmony_ci%1 = OpTypeFloat 32
776fd4e5da5Sopenharmony_ci%2 = OpTypeVector %1 16)";
777fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
778fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
779fd4e5da5Sopenharmony_ci}
780fd4e5da5Sopenharmony_ci
781fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpTypeMatrixGood) {
782fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
783fd4e5da5Sopenharmony_ci%1 = OpTypeFloat 32
784fd4e5da5Sopenharmony_ci%2 = OpTypeVector %1 2
785fd4e5da5Sopenharmony_ci%3 = OpTypeMatrix %2 3)";
786fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
787fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
788fd4e5da5Sopenharmony_ci}
789fd4e5da5Sopenharmony_ci
790fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpTypeMatrixColumnTypeNonVectorBad) {
791fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
792fd4e5da5Sopenharmony_ci%1 = OpTypeFloat 32
793fd4e5da5Sopenharmony_ci%2 = OpTypeMatrix %1 3)";
794fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
795fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
796fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
797fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
798fd4e5da5Sopenharmony_ci                  "olumns in a matrix must be of type vector.\n  %mat3float = "
799fd4e5da5Sopenharmony_ci                  "OpTypeMatrix %float 3\n")));
800fd4e5da5Sopenharmony_ci}
801fd4e5da5Sopenharmony_ci
802fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpTypeMatrixVectorTypeNonFloatBad) {
803fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
804fd4e5da5Sopenharmony_ci%1 = OpTypeInt 16 0
805fd4e5da5Sopenharmony_ci%2 = OpTypeVector %1 2
806fd4e5da5Sopenharmony_ci%3 = OpTypeMatrix %2 2)";
807fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
808fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
809fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
810fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
811fd4e5da5Sopenharmony_ci                  "Matrix types can only be parameterized with floating-point "
812fd4e5da5Sopenharmony_ci                  "types.\n  %mat2v2ushort = OpTypeMatrix %v2ushort 2\n")));
813fd4e5da5Sopenharmony_ci}
814fd4e5da5Sopenharmony_ci
815fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpTypeMatrixColumnCountLessThanTwoBad) {
816fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
817fd4e5da5Sopenharmony_ci%1 = OpTypeFloat 32
818fd4e5da5Sopenharmony_ci%2 = OpTypeVector %1 2
819fd4e5da5Sopenharmony_ci%3 = OpTypeMatrix %2 1)";
820fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
821fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
822fd4e5da5Sopenharmony_ci  EXPECT_THAT(
823fd4e5da5Sopenharmony_ci      getDiagnosticString(),
824fd4e5da5Sopenharmony_ci      HasSubstr(make_message(
825fd4e5da5Sopenharmony_ci          "Matrix types can only be parameterized as having only 2, 3, "
826fd4e5da5Sopenharmony_ci          "or 4 columns.\n  %mat1v2float = OpTypeMatrix %v2float 1\n")));
827fd4e5da5Sopenharmony_ci}
828fd4e5da5Sopenharmony_ci
829fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpTypeMatrixColumnCountGreaterThanFourBad) {
830fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
831fd4e5da5Sopenharmony_ci%1 = OpTypeFloat 32
832fd4e5da5Sopenharmony_ci%2 = OpTypeVector %1 2
833fd4e5da5Sopenharmony_ci%3 = OpTypeMatrix %2 8)";
834fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
835fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
836fd4e5da5Sopenharmony_ci  EXPECT_THAT(
837fd4e5da5Sopenharmony_ci      getDiagnosticString(),
838fd4e5da5Sopenharmony_ci      HasSubstr(make_message(
839fd4e5da5Sopenharmony_ci          "Matrix types can only be parameterized as having only 2, 3, "
840fd4e5da5Sopenharmony_ci          "or 4 columns.\n  %mat8v2float = OpTypeMatrix %v2float 8\n")));
841fd4e5da5Sopenharmony_ci}
842fd4e5da5Sopenharmony_ci
843fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpTypeSamplerGood) {
844fd4e5da5Sopenharmony_ci  // In Rev31, OpTypeSampler takes no arguments.
845fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
846fd4e5da5Sopenharmony_ci%s = OpTypeSampler)";
847fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
848fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
849fd4e5da5Sopenharmony_ci}
850fd4e5da5Sopenharmony_ci
851fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpTypeArrayGood) {
852fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
853fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
854fd4e5da5Sopenharmony_ci%2 = OpConstant %1 1
855fd4e5da5Sopenharmony_ci%3 = OpTypeArray %1 %2)";
856fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
857fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
858fd4e5da5Sopenharmony_ci}
859fd4e5da5Sopenharmony_ci
860fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpTypeArrayElementTypeBad) {
861fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
862fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
863fd4e5da5Sopenharmony_ci%2 = OpConstant %1 1
864fd4e5da5Sopenharmony_ci%3 = OpTypeArray %2 %2)";
865fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
866fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
867fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
868fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
869fd4e5da5Sopenharmony_ci                  "OpTypeArray Element Type <id> '2[%uint_1]' is not a "
870fd4e5da5Sopenharmony_ci                  "type.")));
871fd4e5da5Sopenharmony_ci}
872fd4e5da5Sopenharmony_ci
873fd4e5da5Sopenharmony_ci// Signed or unsigned.
874fd4e5da5Sopenharmony_cienum Signed { kSigned, kUnsigned };
875fd4e5da5Sopenharmony_ci
876fd4e5da5Sopenharmony_ci// Creates an assembly module declaring OpTypeArray with the given length.
877fd4e5da5Sopenharmony_cistd::string MakeArrayLength(const std::string& len, Signed isSigned, int width,
878fd4e5da5Sopenharmony_ci                            int max_int_width = 64,
879fd4e5da5Sopenharmony_ci                            bool use_vulkan_memory_model = false) {
880fd4e5da5Sopenharmony_ci  std::ostringstream ss;
881fd4e5da5Sopenharmony_ci  ss << R"(
882fd4e5da5Sopenharmony_ci    OpCapability Shader
883fd4e5da5Sopenharmony_ci  )";
884fd4e5da5Sopenharmony_ci  if (use_vulkan_memory_model) {
885fd4e5da5Sopenharmony_ci    ss << " OpCapability VulkanMemoryModel\n";
886fd4e5da5Sopenharmony_ci  }
887fd4e5da5Sopenharmony_ci  if (width == 16) {
888fd4e5da5Sopenharmony_ci    ss << " OpCapability Int16\n";
889fd4e5da5Sopenharmony_ci  }
890fd4e5da5Sopenharmony_ci  if (max_int_width > 32) {
891fd4e5da5Sopenharmony_ci    ss << "\n  OpCapability Int64\n";
892fd4e5da5Sopenharmony_ci  }
893fd4e5da5Sopenharmony_ci  if (use_vulkan_memory_model) {
894fd4e5da5Sopenharmony_ci    ss << " OpExtension \"SPV_KHR_vulkan_memory_model\"\n";
895fd4e5da5Sopenharmony_ci    ss << "OpMemoryModel Logical Vulkan\n";
896fd4e5da5Sopenharmony_ci  } else {
897fd4e5da5Sopenharmony_ci    ss << "OpMemoryModel Logical GLSL450\n";
898fd4e5da5Sopenharmony_ci  }
899fd4e5da5Sopenharmony_ci  ss << "OpEntryPoint GLCompute %main \"main\"\n";
900fd4e5da5Sopenharmony_ci  ss << "OpExecutionMode %main LocalSize 1 1 1\n";
901fd4e5da5Sopenharmony_ci  ss << " %t = OpTypeInt " << width << (isSigned == kSigned ? " 1" : " 0");
902fd4e5da5Sopenharmony_ci  ss << " %l = OpConstant %t " << len;
903fd4e5da5Sopenharmony_ci  ss << " %a = OpTypeArray %t %l";
904fd4e5da5Sopenharmony_ci  ss << " %void = OpTypeVoid \n"
905fd4e5da5Sopenharmony_ci        " %voidfn = OpTypeFunction %void \n"
906fd4e5da5Sopenharmony_ci        " %main = OpFunction %void None %voidfn \n"
907fd4e5da5Sopenharmony_ci        " %entry = OpLabel\n"
908fd4e5da5Sopenharmony_ci        " OpReturn\n"
909fd4e5da5Sopenharmony_ci        " OpFunctionEnd\n";
910fd4e5da5Sopenharmony_ci  return ss.str();
911fd4e5da5Sopenharmony_ci}
912fd4e5da5Sopenharmony_ci
913fd4e5da5Sopenharmony_ci// Tests OpTypeArray.  Parameter is the width (in bits) of the array-length's
914fd4e5da5Sopenharmony_ci// type.
915fd4e5da5Sopenharmony_ciclass OpTypeArrayLengthTest
916fd4e5da5Sopenharmony_ci    : public spvtest::TextToBinaryTestBase<::testing::TestWithParam<int>> {
917fd4e5da5Sopenharmony_ci protected:
918fd4e5da5Sopenharmony_ci  OpTypeArrayLengthTest()
919fd4e5da5Sopenharmony_ci      : env_(SPV_ENV_UNIVERSAL_1_0),
920fd4e5da5Sopenharmony_ci        position_(spv_position_t{0, 0, 0}),
921fd4e5da5Sopenharmony_ci        diagnostic_(spvDiagnosticCreate(&position_, "")) {}
922fd4e5da5Sopenharmony_ci
923fd4e5da5Sopenharmony_ci  ~OpTypeArrayLengthTest() override { spvDiagnosticDestroy(diagnostic_); }
924fd4e5da5Sopenharmony_ci
925fd4e5da5Sopenharmony_ci  // Runs spvValidate() on v, printing any errors via spvDiagnosticPrint().
926fd4e5da5Sopenharmony_ci  spv_result_t Val(const SpirvVector& v, const std::string& expected_err = "") {
927fd4e5da5Sopenharmony_ci    spv_const_binary_t cbinary{v.data(), v.size()};
928fd4e5da5Sopenharmony_ci    spvDiagnosticDestroy(diagnostic_);
929fd4e5da5Sopenharmony_ci    diagnostic_ = nullptr;
930fd4e5da5Sopenharmony_ci    const auto status =
931fd4e5da5Sopenharmony_ci        spvValidate(ScopedContext(env_).context, &cbinary, &diagnostic_);
932fd4e5da5Sopenharmony_ci    if (status != SPV_SUCCESS) {
933fd4e5da5Sopenharmony_ci      spvDiagnosticPrint(diagnostic_);
934fd4e5da5Sopenharmony_ci      EXPECT_THAT(std::string(diagnostic_->error),
935fd4e5da5Sopenharmony_ci                  testing::ContainsRegex(expected_err));
936fd4e5da5Sopenharmony_ci    }
937fd4e5da5Sopenharmony_ci    return status;
938fd4e5da5Sopenharmony_ci  }
939fd4e5da5Sopenharmony_ci
940fd4e5da5Sopenharmony_ci protected:
941fd4e5da5Sopenharmony_ci  spv_target_env env_;
942fd4e5da5Sopenharmony_ci
943fd4e5da5Sopenharmony_ci private:
944fd4e5da5Sopenharmony_ci  spv_position_t position_;  // For creating diagnostic_.
945fd4e5da5Sopenharmony_ci  spv_diagnostic diagnostic_;
946fd4e5da5Sopenharmony_ci};
947fd4e5da5Sopenharmony_ci
948fd4e5da5Sopenharmony_ciTEST_P(OpTypeArrayLengthTest, LengthPositiveSmall) {
949fd4e5da5Sopenharmony_ci  const int width = GetParam();
950fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS,
951fd4e5da5Sopenharmony_ci            Val(CompileSuccessfully(MakeArrayLength("1", kSigned, width))));
952fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS,
953fd4e5da5Sopenharmony_ci            Val(CompileSuccessfully(MakeArrayLength("1", kUnsigned, width))));
954fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS,
955fd4e5da5Sopenharmony_ci            Val(CompileSuccessfully(MakeArrayLength("2", kSigned, width))));
956fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS,
957fd4e5da5Sopenharmony_ci            Val(CompileSuccessfully(MakeArrayLength("2", kUnsigned, width))));
958fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS,
959fd4e5da5Sopenharmony_ci            Val(CompileSuccessfully(MakeArrayLength("55", kSigned, width))));
960fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS,
961fd4e5da5Sopenharmony_ci            Val(CompileSuccessfully(MakeArrayLength("55", kUnsigned, width))));
962fd4e5da5Sopenharmony_ci  const std::string fpad(width / 4 - 1, 'F');
963fd4e5da5Sopenharmony_ci  EXPECT_EQ(
964fd4e5da5Sopenharmony_ci      SPV_SUCCESS,
965fd4e5da5Sopenharmony_ci      Val(CompileSuccessfully(MakeArrayLength("0x7" + fpad, kSigned, width))))
966fd4e5da5Sopenharmony_ci      << MakeArrayLength("0x7" + fpad, kSigned, width);
967fd4e5da5Sopenharmony_ci}
968fd4e5da5Sopenharmony_ci
969fd4e5da5Sopenharmony_ciTEST_P(OpTypeArrayLengthTest, LengthZero) {
970fd4e5da5Sopenharmony_ci  const int width = GetParam();
971fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID,
972fd4e5da5Sopenharmony_ci            Val(CompileSuccessfully(MakeArrayLength("0", kSigned, width)),
973fd4e5da5Sopenharmony_ci                "OpTypeArray Length <id> '3\\[%.*\\]' default value must be at "
974fd4e5da5Sopenharmony_ci                "least 1."));
975fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID,
976fd4e5da5Sopenharmony_ci            Val(CompileSuccessfully(MakeArrayLength("0", kUnsigned, width)),
977fd4e5da5Sopenharmony_ci                "OpTypeArray Length <id> '3\\[%.*\\]' default value must be at "
978fd4e5da5Sopenharmony_ci                "least 1."));
979fd4e5da5Sopenharmony_ci}
980fd4e5da5Sopenharmony_ci
981fd4e5da5Sopenharmony_ciTEST_P(OpTypeArrayLengthTest, LengthNegative) {
982fd4e5da5Sopenharmony_ci  const int width = GetParam();
983fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID,
984fd4e5da5Sopenharmony_ci            Val(CompileSuccessfully(MakeArrayLength("-1", kSigned, width)),
985fd4e5da5Sopenharmony_ci                "OpTypeArray Length <id> '3\\[%.*\\]' default value must be at "
986fd4e5da5Sopenharmony_ci                "least 1."));
987fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID,
988fd4e5da5Sopenharmony_ci            Val(CompileSuccessfully(MakeArrayLength("-2", kSigned, width)),
989fd4e5da5Sopenharmony_ci                "OpTypeArray Length <id> '3\\[%.*\\]' default value must be at "
990fd4e5da5Sopenharmony_ci                "least 1."));
991fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID,
992fd4e5da5Sopenharmony_ci            Val(CompileSuccessfully(MakeArrayLength("-123", kSigned, width)),
993fd4e5da5Sopenharmony_ci                "OpTypeArray Length <id> '3\\[%.*\\]' default value must be at "
994fd4e5da5Sopenharmony_ci                "least 1."));
995fd4e5da5Sopenharmony_ci  const std::string neg_max = "0x8" + std::string(width / 4 - 1, '0');
996fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID,
997fd4e5da5Sopenharmony_ci            Val(CompileSuccessfully(MakeArrayLength(neg_max, kSigned, width)),
998fd4e5da5Sopenharmony_ci                "OpTypeArray Length <id> '3\\[%.*\\]' default value must be at "
999fd4e5da5Sopenharmony_ci                "least 1."));
1000fd4e5da5Sopenharmony_ci}
1001fd4e5da5Sopenharmony_ci
1002fd4e5da5Sopenharmony_ci// Returns the string form of an integer of the form 0x80....0 of the
1003fd4e5da5Sopenharmony_ci// given bit width.
1004fd4e5da5Sopenharmony_cistd::string big_num_ending_0(int bit_width) {
1005fd4e5da5Sopenharmony_ci  return "0x8" + std::string(bit_width / 4 - 1, '0');
1006fd4e5da5Sopenharmony_ci}
1007fd4e5da5Sopenharmony_ci
1008fd4e5da5Sopenharmony_ci// Returns the string form of an integer of the form 0x80..001 of the
1009fd4e5da5Sopenharmony_ci// given bit width.
1010fd4e5da5Sopenharmony_cistd::string big_num_ending_1(int bit_width) {
1011fd4e5da5Sopenharmony_ci  return "0x8" + std::string(bit_width / 4 - 2, '0') + "1";
1012fd4e5da5Sopenharmony_ci}
1013fd4e5da5Sopenharmony_ci
1014fd4e5da5Sopenharmony_ciTEST_P(OpTypeArrayLengthTest, LengthPositiveHugeEnding0InVulkan) {
1015fd4e5da5Sopenharmony_ci  env_ = SPV_ENV_VULKAN_1_0;
1016fd4e5da5Sopenharmony_ci  const int width = GetParam();
1017fd4e5da5Sopenharmony_ci  for (int max_int_width : {32, 64}) {
1018fd4e5da5Sopenharmony_ci    if (width > max_int_width) {
1019fd4e5da5Sopenharmony_ci      // Not valid to even make the OpConstant in this case.
1020fd4e5da5Sopenharmony_ci      continue;
1021fd4e5da5Sopenharmony_ci    }
1022fd4e5da5Sopenharmony_ci    const auto module = CompileSuccessfully(MakeArrayLength(
1023fd4e5da5Sopenharmony_ci        big_num_ending_0(width), kUnsigned, width, max_int_width));
1024fd4e5da5Sopenharmony_ci    EXPECT_EQ(SPV_SUCCESS, Val(module));
1025fd4e5da5Sopenharmony_ci  }
1026fd4e5da5Sopenharmony_ci}
1027fd4e5da5Sopenharmony_ci
1028fd4e5da5Sopenharmony_ciTEST_P(OpTypeArrayLengthTest, LengthPositiveHugeEnding1InVulkan) {
1029fd4e5da5Sopenharmony_ci  env_ = SPV_ENV_VULKAN_1_0;
1030fd4e5da5Sopenharmony_ci  const int width = GetParam();
1031fd4e5da5Sopenharmony_ci  for (int max_int_width : {32, 64}) {
1032fd4e5da5Sopenharmony_ci    if (width > max_int_width) {
1033fd4e5da5Sopenharmony_ci      // Not valid to even make the OpConstant in this case.
1034fd4e5da5Sopenharmony_ci      continue;
1035fd4e5da5Sopenharmony_ci    }
1036fd4e5da5Sopenharmony_ci    const auto module = CompileSuccessfully(MakeArrayLength(
1037fd4e5da5Sopenharmony_ci        big_num_ending_1(width), kUnsigned, width, max_int_width));
1038fd4e5da5Sopenharmony_ci    EXPECT_EQ(SPV_SUCCESS, Val(module));
1039fd4e5da5Sopenharmony_ci  }
1040fd4e5da5Sopenharmony_ci}
1041fd4e5da5Sopenharmony_ci
1042fd4e5da5Sopenharmony_ci// The only valid widths for integers are 8, 16, 32, and 64.
1043fd4e5da5Sopenharmony_ci// Since the Int8 capability requires the Kernel capability, and the Kernel
1044fd4e5da5Sopenharmony_ci// capability prohibits usage of signed integers, we can skip 8-bit integers
1045fd4e5da5Sopenharmony_ci// here since the purpose of these tests is to check the validity of
1046fd4e5da5Sopenharmony_ci// OpTypeArray, not OpTypeInt.
1047fd4e5da5Sopenharmony_ciINSTANTIATE_TEST_SUITE_P(Widths, OpTypeArrayLengthTest,
1048fd4e5da5Sopenharmony_ci                         ValuesIn(std::vector<int>{16, 32, 64}));
1049fd4e5da5Sopenharmony_ci
1050fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpTypeArrayLengthNull) {
1051fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1052fd4e5da5Sopenharmony_ci%i32 = OpTypeInt 32 0
1053fd4e5da5Sopenharmony_ci%len = OpConstantNull %i32
1054fd4e5da5Sopenharmony_ci%ary = OpTypeArray %i32 %len)";
1055fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1056fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1057fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1058fd4e5da5Sopenharmony_ci              HasSubstr(make_message("OpTypeArray Length <id> '2[%2]' default "
1059fd4e5da5Sopenharmony_ci                                     "value must be at least 1.")));
1060fd4e5da5Sopenharmony_ci}
1061fd4e5da5Sopenharmony_ci
1062fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpTypeArrayLengthSpecConst) {
1063fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1064fd4e5da5Sopenharmony_ci%i32 = OpTypeInt 32 0
1065fd4e5da5Sopenharmony_ci%len = OpSpecConstant %i32 2
1066fd4e5da5Sopenharmony_ci%ary = OpTypeArray %i32 %len)";
1067fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1068fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1069fd4e5da5Sopenharmony_ci}
1070fd4e5da5Sopenharmony_ci
1071fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpTypeArrayLengthSpecConstOp) {
1072fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1073fd4e5da5Sopenharmony_ci%i32 = OpTypeInt 32 0
1074fd4e5da5Sopenharmony_ci%c1 = OpConstant %i32 1
1075fd4e5da5Sopenharmony_ci%c2 = OpConstant %i32 2
1076fd4e5da5Sopenharmony_ci%len = OpSpecConstantOp %i32 IAdd %c1 %c2
1077fd4e5da5Sopenharmony_ci%ary = OpTypeArray %i32 %len)";
1078fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1079fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1080fd4e5da5Sopenharmony_ci}
1081fd4e5da5Sopenharmony_ci
1082fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpTypeRuntimeArrayGood) {
1083fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1084fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
1085fd4e5da5Sopenharmony_ci%2 = OpTypeRuntimeArray %1)";
1086fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1087fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1088fd4e5da5Sopenharmony_ci}
1089fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpTypeRuntimeArrayBad) {
1090fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1091fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
1092fd4e5da5Sopenharmony_ci%2 = OpConstant %1 0
1093fd4e5da5Sopenharmony_ci%3 = OpTypeRuntimeArray %2)";
1094fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1095fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1096fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1097fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
1098fd4e5da5Sopenharmony_ci                  "OpTypeRuntimeArray Element Type <id> '2[%uint_0]' is not a "
1099fd4e5da5Sopenharmony_ci                  "type.")));
1100fd4e5da5Sopenharmony_ci}
1101fd4e5da5Sopenharmony_ci// TODO: Object of this type can only be created with OpVariable using the
1102fd4e5da5Sopenharmony_ci// Uniform Storage Class
1103fd4e5da5Sopenharmony_ci
1104fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpTypeStructGood) {
1105fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1106fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
1107fd4e5da5Sopenharmony_ci%2 = OpTypeFloat 64
1108fd4e5da5Sopenharmony_ci%3 = OpTypePointer Input %1
1109fd4e5da5Sopenharmony_ci%4 = OpTypeStruct %1 %2 %3)";
1110fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1111fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1112fd4e5da5Sopenharmony_ci}
1113fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpTypeStructMemberTypeBad) {
1114fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1115fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
1116fd4e5da5Sopenharmony_ci%2 = OpTypeFloat 64
1117fd4e5da5Sopenharmony_ci%3 = OpConstant %2 0.0
1118fd4e5da5Sopenharmony_ci%4 = OpTypeStruct %1 %2 %3)";
1119fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1120fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1121fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1122fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
1123fd4e5da5Sopenharmony_ci                  "OpTypeStruct Member Type <id> '3[%double_0]' is not "
1124fd4e5da5Sopenharmony_ci                  "a type.")));
1125fd4e5da5Sopenharmony_ci}
1126fd4e5da5Sopenharmony_ci
1127fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpTypeStructOpaqueTypeBad) {
1128fd4e5da5Sopenharmony_ci  std::string spirv = R"(
1129fd4e5da5Sopenharmony_ci               OpCapability Shader
1130fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
1131fd4e5da5Sopenharmony_ci               OpEntryPoint Vertex %main "main"
1132fd4e5da5Sopenharmony_ci          %1 = OpTypeSampler
1133fd4e5da5Sopenharmony_ci          %2 = OpTypeStruct %1
1134fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
1135fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %void
1136fd4e5da5Sopenharmony_ci       %main = OpFunction %void None %3
1137fd4e5da5Sopenharmony_ci          %5 = OpLabel
1138fd4e5da5Sopenharmony_ci               OpReturn
1139fd4e5da5Sopenharmony_ci               OpFunctionEnd
1140fd4e5da5Sopenharmony_ci)";
1141fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_0);
1142fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
1143fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1144fd4e5da5Sopenharmony_ci              AnyVUID("VUID-StandaloneSpirv-None-04667"));
1145fd4e5da5Sopenharmony_ci  EXPECT_THAT(
1146fd4e5da5Sopenharmony_ci      getDiagnosticString(),
1147fd4e5da5Sopenharmony_ci      HasSubstr(make_message("OpTypeStruct must not contain an opaque type")));
1148fd4e5da5Sopenharmony_ci}
1149fd4e5da5Sopenharmony_ci
1150fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpTypePointerGood) {
1151fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1152fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
1153fd4e5da5Sopenharmony_ci%2 = OpTypePointer Input %1)";
1154fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1155fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1156fd4e5da5Sopenharmony_ci}
1157fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpTypePointerBad) {
1158fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1159fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
1160fd4e5da5Sopenharmony_ci%2 = OpConstant %1 0
1161fd4e5da5Sopenharmony_ci%3 = OpTypePointer Input %2)";
1162fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1163fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1164fd4e5da5Sopenharmony_ci  EXPECT_THAT(
1165fd4e5da5Sopenharmony_ci      getDiagnosticString(),
1166fd4e5da5Sopenharmony_ci      HasSubstr(make_message("OpTypePointer Type <id> '2[%uint_0]' is not a "
1167fd4e5da5Sopenharmony_ci                             "type.")));
1168fd4e5da5Sopenharmony_ci}
1169fd4e5da5Sopenharmony_ci
1170fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpTypeFunctionGood) {
1171fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1172fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
1173fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %1)";
1174fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1175fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1176fd4e5da5Sopenharmony_ci}
1177fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpTypeFunctionReturnTypeBad) {
1178fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1179fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
1180fd4e5da5Sopenharmony_ci%2 = OpConstant %1 0
1181fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %2)";
1182fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1183fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1184fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1185fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
1186fd4e5da5Sopenharmony_ci                  "OpTypeFunction Return Type <id> '2[%uint_0]' is not "
1187fd4e5da5Sopenharmony_ci                  "a type.")));
1188fd4e5da5Sopenharmony_ci}
1189fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpTypeFunctionParameterBad) {
1190fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1191fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
1192fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
1193fd4e5da5Sopenharmony_ci%3 = OpConstant %2 0
1194fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %1 %2 %3)";
1195fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1196fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1197fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1198fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
1199fd4e5da5Sopenharmony_ci                  "OpTypeFunction Parameter Type <id> '3[%uint_0]' is not a "
1200fd4e5da5Sopenharmony_ci                  "type.")));
1201fd4e5da5Sopenharmony_ci}
1202fd4e5da5Sopenharmony_ci
1203fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpTypeFunctionParameterTypeVoidBad) {
1204fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1205fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
1206fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
1207fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %1 %2 %1)";
1208fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1209fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1210fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1211fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
1212fd4e5da5Sopenharmony_ci                  "OpTypeFunction Parameter Type <id> '1[%void]' cannot "
1213fd4e5da5Sopenharmony_ci                  "be OpTypeVoid.")));
1214fd4e5da5Sopenharmony_ci}
1215fd4e5da5Sopenharmony_ci
1216fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpTypePipeGood) {
1217fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1218fd4e5da5Sopenharmony_ci%1 = OpTypeFloat 32
1219fd4e5da5Sopenharmony_ci%2 = OpTypeVector %1 16
1220fd4e5da5Sopenharmony_ci%3 = OpTypePipe ReadOnly)";
1221fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1222fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1223fd4e5da5Sopenharmony_ci}
1224fd4e5da5Sopenharmony_ci
1225fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpConstantTrueGood) {
1226fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1227fd4e5da5Sopenharmony_ci%1 = OpTypeBool
1228fd4e5da5Sopenharmony_ci%2 = OpConstantTrue %1)";
1229fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1230fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1231fd4e5da5Sopenharmony_ci}
1232fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpConstantTrueBad) {
1233fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1234fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
1235fd4e5da5Sopenharmony_ci%2 = OpConstantTrue %1)";
1236fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1237fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1238fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1239fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
1240fd4e5da5Sopenharmony_ci                  "OpConstantTrue Result Type <id> '1[%void]' is not a boolean "
1241fd4e5da5Sopenharmony_ci                  "type.")));
1242fd4e5da5Sopenharmony_ci}
1243fd4e5da5Sopenharmony_ci
1244fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpConstantFalseGood) {
1245fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1246fd4e5da5Sopenharmony_ci%1 = OpTypeBool
1247fd4e5da5Sopenharmony_ci%2 = OpConstantTrue %1)";
1248fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1249fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1250fd4e5da5Sopenharmony_ci}
1251fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpConstantFalseBad) {
1252fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1253fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
1254fd4e5da5Sopenharmony_ci%2 = OpConstantFalse %1)";
1255fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1256fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1257fd4e5da5Sopenharmony_ci  EXPECT_THAT(
1258fd4e5da5Sopenharmony_ci      getDiagnosticString(),
1259fd4e5da5Sopenharmony_ci      HasSubstr(make_message(
1260fd4e5da5Sopenharmony_ci          "OpConstantFalse Result Type <id> '1[%void]' is not a boolean "
1261fd4e5da5Sopenharmony_ci          "type.")));
1262fd4e5da5Sopenharmony_ci}
1263fd4e5da5Sopenharmony_ci
1264fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpConstantGood) {
1265fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1266fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
1267fd4e5da5Sopenharmony_ci%2 = OpConstant %1 1)";
1268fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1269fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1270fd4e5da5Sopenharmony_ci}
1271fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpConstantBad) {
1272fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1273fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
1274fd4e5da5Sopenharmony_ci%2 = OpConstant !1 !0)";
1275fd4e5da5Sopenharmony_ci  // The expected failure code is implementation dependent (currently
1276fd4e5da5Sopenharmony_ci  // INVALID_BINARY because the binary parser catches these cases) and may
1277fd4e5da5Sopenharmony_ci  // change over time, but this must always fail.
1278fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1279fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions());
1280fd4e5da5Sopenharmony_ci}
1281fd4e5da5Sopenharmony_ci
1282fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpConstantCompositeVectorGood) {
1283fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1284fd4e5da5Sopenharmony_ci%1 = OpTypeFloat 32
1285fd4e5da5Sopenharmony_ci%2 = OpTypeVector %1 4
1286fd4e5da5Sopenharmony_ci%3 = OpConstant %1 3.14
1287fd4e5da5Sopenharmony_ci%4 = OpConstantComposite %2 %3 %3 %3 %3)";
1288fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1289fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1290fd4e5da5Sopenharmony_ci}
1291fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpConstantCompositeVectorWithUndefGood) {
1292fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1293fd4e5da5Sopenharmony_ci%1 = OpTypeFloat 32
1294fd4e5da5Sopenharmony_ci%2 = OpTypeVector %1 4
1295fd4e5da5Sopenharmony_ci%3 = OpConstant %1 3.14
1296fd4e5da5Sopenharmony_ci%9 = OpUndef %1
1297fd4e5da5Sopenharmony_ci%4 = OpConstantComposite %2 %3 %3 %3 %9)";
1298fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1299fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1300fd4e5da5Sopenharmony_ci}
1301fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpConstantCompositeVectorResultTypeBad) {
1302fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1303fd4e5da5Sopenharmony_ci%1 = OpTypeFloat 32
1304fd4e5da5Sopenharmony_ci%2 = OpTypeVector %1 4
1305fd4e5da5Sopenharmony_ci%3 = OpConstant %1 3.14
1306fd4e5da5Sopenharmony_ci%4 = OpConstantComposite %1 %3 %3 %3 %3)";
1307fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1308fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1309fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1310fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
1311fd4e5da5Sopenharmony_ci                  "OpConstantComposite Result Type <id> '1[%float]' is not a "
1312fd4e5da5Sopenharmony_ci                  "composite type.")));
1313fd4e5da5Sopenharmony_ci}
1314fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpConstantCompositeVectorConstituentTypeBad) {
1315fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1316fd4e5da5Sopenharmony_ci%1 = OpTypeFloat 32
1317fd4e5da5Sopenharmony_ci%2 = OpTypeVector %1 4
1318fd4e5da5Sopenharmony_ci%4 = OpTypeInt 32 0
1319fd4e5da5Sopenharmony_ci%3 = OpConstant %1 3.14
1320fd4e5da5Sopenharmony_ci%5 = OpConstant %4 42 ; bad type for constant value
1321fd4e5da5Sopenharmony_ci%6 = OpConstantComposite %2 %3 %5 %3 %3)";
1322fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1323fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1324fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1325fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
1326fd4e5da5Sopenharmony_ci                  "OpConstantComposite Constituent <id> '5[%uint_42]'s type "
1327fd4e5da5Sopenharmony_ci                  "does not match Result Type <id> '2[%v4float]'s vector "
1328fd4e5da5Sopenharmony_ci                  "element type.")));
1329fd4e5da5Sopenharmony_ci}
1330fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage,
1331fd4e5da5Sopenharmony_ci       OpConstantCompositeVectorConstituentUndefTypeBad) {
1332fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1333fd4e5da5Sopenharmony_ci%1 = OpTypeFloat 32
1334fd4e5da5Sopenharmony_ci%2 = OpTypeVector %1 4
1335fd4e5da5Sopenharmony_ci%4 = OpTypeInt 32 0
1336fd4e5da5Sopenharmony_ci%3 = OpConstant %1 3.14
1337fd4e5da5Sopenharmony_ci%5 = OpUndef %4 ; bad type for undef value
1338fd4e5da5Sopenharmony_ci%6 = OpConstantComposite %2 %3 %5 %3 %3)";
1339fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1340fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1341fd4e5da5Sopenharmony_ci  EXPECT_THAT(
1342fd4e5da5Sopenharmony_ci      getDiagnosticString(),
1343fd4e5da5Sopenharmony_ci      HasSubstr(make_message(
1344fd4e5da5Sopenharmony_ci          "OpConstantComposite Constituent <id> '5[%5]'s type does not "
1345fd4e5da5Sopenharmony_ci          "match Result Type <id> '2[%v4float]'s vector element type.")));
1346fd4e5da5Sopenharmony_ci}
1347fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpConstantCompositeMatrixGood) {
1348fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1349fd4e5da5Sopenharmony_ci %1 = OpTypeFloat 32
1350fd4e5da5Sopenharmony_ci %2 = OpTypeVector %1 4
1351fd4e5da5Sopenharmony_ci %3 = OpTypeMatrix %2 4
1352fd4e5da5Sopenharmony_ci %4 = OpConstant %1 1.0
1353fd4e5da5Sopenharmony_ci %5 = OpConstant %1 0.0
1354fd4e5da5Sopenharmony_ci %6 = OpConstantComposite %2 %4 %5 %5 %5
1355fd4e5da5Sopenharmony_ci %7 = OpConstantComposite %2 %5 %4 %5 %5
1356fd4e5da5Sopenharmony_ci %8 = OpConstantComposite %2 %5 %5 %4 %5
1357fd4e5da5Sopenharmony_ci %9 = OpConstantComposite %2 %5 %5 %5 %4
1358fd4e5da5Sopenharmony_ci%10 = OpConstantComposite %3 %6 %7 %8 %9)";
1359fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1360fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1361fd4e5da5Sopenharmony_ci}
1362fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpConstantCompositeMatrixUndefGood) {
1363fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1364fd4e5da5Sopenharmony_ci %1 = OpTypeFloat 32
1365fd4e5da5Sopenharmony_ci %2 = OpTypeVector %1 4
1366fd4e5da5Sopenharmony_ci %3 = OpTypeMatrix %2 4
1367fd4e5da5Sopenharmony_ci %4 = OpConstant %1 1.0
1368fd4e5da5Sopenharmony_ci %5 = OpConstant %1 0.0
1369fd4e5da5Sopenharmony_ci %6 = OpConstantComposite %2 %4 %5 %5 %5
1370fd4e5da5Sopenharmony_ci %7 = OpConstantComposite %2 %5 %4 %5 %5
1371fd4e5da5Sopenharmony_ci %8 = OpConstantComposite %2 %5 %5 %4 %5
1372fd4e5da5Sopenharmony_ci %9 = OpUndef %2
1373fd4e5da5Sopenharmony_ci%10 = OpConstantComposite %3 %6 %7 %8 %9)";
1374fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1375fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1376fd4e5da5Sopenharmony_ci}
1377fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpConstantCompositeMatrixConstituentTypeBad) {
1378fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1379fd4e5da5Sopenharmony_ci %1 = OpTypeFloat 32
1380fd4e5da5Sopenharmony_ci %2 = OpTypeVector %1 4
1381fd4e5da5Sopenharmony_ci%11 = OpTypeVector %1 3
1382fd4e5da5Sopenharmony_ci %3 = OpTypeMatrix %2 4
1383fd4e5da5Sopenharmony_ci %4 = OpConstant %1 1.0
1384fd4e5da5Sopenharmony_ci %5 = OpConstant %1 0.0
1385fd4e5da5Sopenharmony_ci %6 = OpConstantComposite %2 %4 %5 %5 %5
1386fd4e5da5Sopenharmony_ci %7 = OpConstantComposite %2 %5 %4 %5 %5
1387fd4e5da5Sopenharmony_ci %8 = OpConstantComposite %2 %5 %5 %4 %5
1388fd4e5da5Sopenharmony_ci %9 = OpConstantComposite %11 %5 %5 %5
1389fd4e5da5Sopenharmony_ci%10 = OpConstantComposite %3 %6 %7 %8 %9)";
1390fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1391fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1392fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1393fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
1394fd4e5da5Sopenharmony_ci                  "OpConstantComposite Constituent <id> '10[%10]' vector "
1395fd4e5da5Sopenharmony_ci                  "component count does not match Result Type <id> "
1396fd4e5da5Sopenharmony_ci                  "'4[%mat4v4float]'s vector component count.")));
1397fd4e5da5Sopenharmony_ci}
1398fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage,
1399fd4e5da5Sopenharmony_ci       OpConstantCompositeMatrixConstituentUndefTypeBad) {
1400fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1401fd4e5da5Sopenharmony_ci %1 = OpTypeFloat 32
1402fd4e5da5Sopenharmony_ci %2 = OpTypeVector %1 4
1403fd4e5da5Sopenharmony_ci%11 = OpTypeVector %1 3
1404fd4e5da5Sopenharmony_ci %3 = OpTypeMatrix %2 4
1405fd4e5da5Sopenharmony_ci %4 = OpConstant %1 1.0
1406fd4e5da5Sopenharmony_ci %5 = OpConstant %1 0.0
1407fd4e5da5Sopenharmony_ci %6 = OpConstantComposite %2 %4 %5 %5 %5
1408fd4e5da5Sopenharmony_ci %7 = OpConstantComposite %2 %5 %4 %5 %5
1409fd4e5da5Sopenharmony_ci %8 = OpConstantComposite %2 %5 %5 %4 %5
1410fd4e5da5Sopenharmony_ci %9 = OpUndef %11
1411fd4e5da5Sopenharmony_ci%10 = OpConstantComposite %3 %6 %7 %8 %9)";
1412fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1413fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1414fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1415fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
1416fd4e5da5Sopenharmony_ci                  "OpConstantComposite Constituent <id> '10[%10]' vector "
1417fd4e5da5Sopenharmony_ci                  "component count does not match Result Type <id> "
1418fd4e5da5Sopenharmony_ci                  "'4[%mat4v4float]'s vector component count.")));
1419fd4e5da5Sopenharmony_ci}
1420fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpConstantCompositeArrayGood) {
1421fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1422fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
1423fd4e5da5Sopenharmony_ci%2 = OpConstant %1 4
1424fd4e5da5Sopenharmony_ci%3 = OpTypeArray %1 %2
1425fd4e5da5Sopenharmony_ci%4 = OpConstantComposite %3 %2 %2 %2 %2)";
1426fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1427fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1428fd4e5da5Sopenharmony_ci}
1429fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpConstantCompositeArrayWithUndefGood) {
1430fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1431fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
1432fd4e5da5Sopenharmony_ci%2 = OpConstant %1 4
1433fd4e5da5Sopenharmony_ci%9 = OpUndef %1
1434fd4e5da5Sopenharmony_ci%3 = OpTypeArray %1 %2
1435fd4e5da5Sopenharmony_ci%4 = OpConstantComposite %3 %2 %2 %2 %9)";
1436fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1437fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1438fd4e5da5Sopenharmony_ci}
1439fd4e5da5Sopenharmony_ci
1440fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpConstantCompositeArrayConstConstituentTypeBad) {
1441fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1442fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
1443fd4e5da5Sopenharmony_ci%2 = OpConstant %1 4
1444fd4e5da5Sopenharmony_ci%3 = OpTypeArray %1 %2
1445fd4e5da5Sopenharmony_ci%4 = OpConstantComposite %3 %2 %2 %2 %1)";  // Uses a type as operand
1446fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1447fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1448fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1449fd4e5da5Sopenharmony_ci              HasSubstr(make_message("Operand '1[%uint]' cannot be a "
1450fd4e5da5Sopenharmony_ci                                     "type")));
1451fd4e5da5Sopenharmony_ci}
1452fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpConstantCompositeArrayConstConstituentBad) {
1453fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1454fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
1455fd4e5da5Sopenharmony_ci%2 = OpConstant %1 4
1456fd4e5da5Sopenharmony_ci%3 = OpTypeArray %1 %2
1457fd4e5da5Sopenharmony_ci%4 = OpTypePointer Uniform %1
1458fd4e5da5Sopenharmony_ci%5 = OpVariable %4 Uniform
1459fd4e5da5Sopenharmony_ci%6 = OpConstantComposite %3 %2 %2 %2 %5)";
1460fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1461fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1462fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1463fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
1464fd4e5da5Sopenharmony_ci                  "OpConstantComposite Constituent <id> '5[%5]' is not a "
1465fd4e5da5Sopenharmony_ci                  "constant or undef.")));
1466fd4e5da5Sopenharmony_ci}
1467fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpConstantCompositeArrayConstituentTypeBad) {
1468fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1469fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
1470fd4e5da5Sopenharmony_ci%2 = OpConstant %1 4
1471fd4e5da5Sopenharmony_ci%3 = OpTypeArray %1 %2
1472fd4e5da5Sopenharmony_ci%5 = OpTypeFloat 32
1473fd4e5da5Sopenharmony_ci%6 = OpConstant %5 3.14 ; bad type for const value
1474fd4e5da5Sopenharmony_ci%4 = OpConstantComposite %3 %2 %2 %2 %6)";
1475fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1476fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1477fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1478fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
1479fd4e5da5Sopenharmony_ci                  "OpConstantComposite Constituent <id> "
1480fd4e5da5Sopenharmony_ci                  "'5[%float_3_1400001]'s type does not match Result "
1481fd4e5da5Sopenharmony_ci                  "Type <id> '3[%_arr_uint_uint_4]'s array element "
1482fd4e5da5Sopenharmony_ci                  "type.")));
1483fd4e5da5Sopenharmony_ci}
1484fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpConstantCompositeArrayConstituentUndefTypeBad) {
1485fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1486fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
1487fd4e5da5Sopenharmony_ci%2 = OpConstant %1 4
1488fd4e5da5Sopenharmony_ci%3 = OpTypeArray %1 %2
1489fd4e5da5Sopenharmony_ci%5 = OpTypeFloat 32
1490fd4e5da5Sopenharmony_ci%6 = OpUndef %5 ; bad type for undef
1491fd4e5da5Sopenharmony_ci%4 = OpConstantComposite %3 %2 %2 %2 %6)";
1492fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1493fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1494fd4e5da5Sopenharmony_ci  EXPECT_THAT(
1495fd4e5da5Sopenharmony_ci      getDiagnosticString(),
1496fd4e5da5Sopenharmony_ci      HasSubstr(make_message("OpConstantComposite Constituent <id> "
1497fd4e5da5Sopenharmony_ci                             "'5[%5]'s type does not match Result "
1498fd4e5da5Sopenharmony_ci                             "Type <id> '3[%_arr_uint_uint_4]'s array element "
1499fd4e5da5Sopenharmony_ci                             "type.")));
1500fd4e5da5Sopenharmony_ci}
1501fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpConstantCompositeStructGood) {
1502fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1503fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
1504fd4e5da5Sopenharmony_ci%2 = OpTypeInt 64 0
1505fd4e5da5Sopenharmony_ci%3 = OpTypeStruct %1 %1 %2
1506fd4e5da5Sopenharmony_ci%4 = OpConstant %1 42
1507fd4e5da5Sopenharmony_ci%5 = OpConstant %2 4300000000
1508fd4e5da5Sopenharmony_ci%6 = OpConstantComposite %3 %4 %4 %5)";
1509fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1510fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1511fd4e5da5Sopenharmony_ci}
1512fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpConstantCompositeStructUndefGood) {
1513fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1514fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
1515fd4e5da5Sopenharmony_ci%2 = OpTypeInt 64 0
1516fd4e5da5Sopenharmony_ci%3 = OpTypeStruct %1 %1 %2
1517fd4e5da5Sopenharmony_ci%4 = OpConstant %1 42
1518fd4e5da5Sopenharmony_ci%5 = OpUndef %2
1519fd4e5da5Sopenharmony_ci%6 = OpConstantComposite %3 %4 %4 %5)";
1520fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1521fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1522fd4e5da5Sopenharmony_ci}
1523fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpConstantCompositeStructMemberTypeBad) {
1524fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1525fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
1526fd4e5da5Sopenharmony_ci%2 = OpTypeInt 64 0
1527fd4e5da5Sopenharmony_ci%3 = OpTypeStruct %1 %1 %2
1528fd4e5da5Sopenharmony_ci%4 = OpConstant %1 42
1529fd4e5da5Sopenharmony_ci%5 = OpConstant %2 4300000000
1530fd4e5da5Sopenharmony_ci%6 = OpConstantComposite %3 %4 %5 %4)";
1531fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1532fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1533fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1534fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
1535fd4e5da5Sopenharmony_ci                  "OpConstantComposite Constituent <id> "
1536fd4e5da5Sopenharmony_ci                  "'5[%ulong_4300000000]' type does not match the "
1537fd4e5da5Sopenharmony_ci                  "Result Type <id> '3[%_struct_3]'s member type.")));
1538fd4e5da5Sopenharmony_ci}
1539fd4e5da5Sopenharmony_ci
1540fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpConstantCompositeStructMemberUndefTypeBad) {
1541fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1542fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
1543fd4e5da5Sopenharmony_ci%2 = OpTypeInt 64 0
1544fd4e5da5Sopenharmony_ci%3 = OpTypeStruct %1 %1 %2
1545fd4e5da5Sopenharmony_ci%4 = OpConstant %1 42
1546fd4e5da5Sopenharmony_ci%5 = OpUndef %2
1547fd4e5da5Sopenharmony_ci%6 = OpConstantComposite %3 %4 %5 %4)";
1548fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1549fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1550fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1551fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
1552fd4e5da5Sopenharmony_ci                  "OpConstantComposite Constituent <id> '5[%5]' type "
1553fd4e5da5Sopenharmony_ci                  "does not match the Result Type <id> '3[%_struct_3]'s "
1554fd4e5da5Sopenharmony_ci                  "member type.")));
1555fd4e5da5Sopenharmony_ci}
1556fd4e5da5Sopenharmony_ci
1557fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpConstantSamplerGood) {
1558fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1559fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
1560fd4e5da5Sopenharmony_ci%samplerType = OpTypeSampler
1561fd4e5da5Sopenharmony_ci%3 = OpConstantSampler %samplerType ClampToEdge 0 Nearest)";
1562fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1563fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1564fd4e5da5Sopenharmony_ci}
1565fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpConstantSamplerResultTypeBad) {
1566fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1567fd4e5da5Sopenharmony_ci%1 = OpTypeFloat 32
1568fd4e5da5Sopenharmony_ci%2 = OpConstantSampler %1 Clamp 0 Nearest)";
1569fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1570fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1571fd4e5da5Sopenharmony_ci  EXPECT_THAT(
1572fd4e5da5Sopenharmony_ci      getDiagnosticString(),
1573fd4e5da5Sopenharmony_ci      HasSubstr(make_message(
1574fd4e5da5Sopenharmony_ci          "OpConstantSampler Result Type <id> '1[%float]' is not a sampler "
1575fd4e5da5Sopenharmony_ci          "type.")));
1576fd4e5da5Sopenharmony_ci}
1577fd4e5da5Sopenharmony_ci
1578fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpConstantNullGood) {
1579fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1580fd4e5da5Sopenharmony_ci %1 = OpTypeBool
1581fd4e5da5Sopenharmony_ci %2 = OpConstantNull %1
1582fd4e5da5Sopenharmony_ci %3 = OpTypeInt 32 0
1583fd4e5da5Sopenharmony_ci %4 = OpConstantNull %3
1584fd4e5da5Sopenharmony_ci %5 = OpTypeFloat 32
1585fd4e5da5Sopenharmony_ci %6 = OpConstantNull %5
1586fd4e5da5Sopenharmony_ci %7 = OpTypePointer UniformConstant %3
1587fd4e5da5Sopenharmony_ci %8 = OpConstantNull %7
1588fd4e5da5Sopenharmony_ci %9 = OpTypeEvent
1589fd4e5da5Sopenharmony_ci%10 = OpConstantNull %9
1590fd4e5da5Sopenharmony_ci%11 = OpTypeDeviceEvent
1591fd4e5da5Sopenharmony_ci%12 = OpConstantNull %11
1592fd4e5da5Sopenharmony_ci%13 = OpTypeReserveId
1593fd4e5da5Sopenharmony_ci%14 = OpConstantNull %13
1594fd4e5da5Sopenharmony_ci%15 = OpTypeQueue
1595fd4e5da5Sopenharmony_ci%16 = OpConstantNull %15
1596fd4e5da5Sopenharmony_ci%17 = OpTypeVector %5 2
1597fd4e5da5Sopenharmony_ci%18 = OpConstantNull %17
1598fd4e5da5Sopenharmony_ci%19 = OpTypeMatrix %17 2
1599fd4e5da5Sopenharmony_ci%20 = OpConstantNull %19
1600fd4e5da5Sopenharmony_ci%25 = OpConstant %3 8
1601fd4e5da5Sopenharmony_ci%21 = OpTypeArray %3 %25
1602fd4e5da5Sopenharmony_ci%22 = OpConstantNull %21
1603fd4e5da5Sopenharmony_ci%23 = OpTypeStruct %3 %5 %1
1604fd4e5da5Sopenharmony_ci%24 = OpConstantNull %23
1605fd4e5da5Sopenharmony_ci%26 = OpTypeArray %17 %25
1606fd4e5da5Sopenharmony_ci%27 = OpConstantNull %26
1607fd4e5da5Sopenharmony_ci%28 = OpTypeStruct %7 %26 %26 %1
1608fd4e5da5Sopenharmony_ci%29 = OpConstantNull %28
1609fd4e5da5Sopenharmony_ci)";
1610fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1611fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1612fd4e5da5Sopenharmony_ci}
1613fd4e5da5Sopenharmony_ci
1614fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpConstantNullBasicBad) {
1615fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1616fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
1617fd4e5da5Sopenharmony_ci%2 = OpConstantNull %1)";
1618fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1619fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1620fd4e5da5Sopenharmony_ci  EXPECT_THAT(
1621fd4e5da5Sopenharmony_ci      getDiagnosticString(),
1622fd4e5da5Sopenharmony_ci      HasSubstr(make_message(
1623fd4e5da5Sopenharmony_ci          "OpConstantNull Result Type <id> '1[%void]' cannot have a null "
1624fd4e5da5Sopenharmony_ci          "value.")));
1625fd4e5da5Sopenharmony_ci}
1626fd4e5da5Sopenharmony_ci
1627fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpConstantNullArrayBad) {
1628fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1629fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
1630fd4e5da5Sopenharmony_ci%3 = OpTypeSampler
1631fd4e5da5Sopenharmony_ci%4 = OpConstant %2 4
1632fd4e5da5Sopenharmony_ci%5 = OpTypeArray %3 %4
1633fd4e5da5Sopenharmony_ci%6 = OpConstantNull %5)";
1634fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1635fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1636fd4e5da5Sopenharmony_ci  EXPECT_THAT(
1637fd4e5da5Sopenharmony_ci      getDiagnosticString(),
1638fd4e5da5Sopenharmony_ci      HasSubstr(make_message(
1639fd4e5da5Sopenharmony_ci          "OpConstantNull Result Type <id> '4[%_arr_2_uint_4]' cannot have a "
1640fd4e5da5Sopenharmony_ci          "null value.")));
1641fd4e5da5Sopenharmony_ci}
1642fd4e5da5Sopenharmony_ci
1643fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpConstantNullStructBad) {
1644fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1645fd4e5da5Sopenharmony_ci%2 = OpTypeSampler
1646fd4e5da5Sopenharmony_ci%3 = OpTypeStruct %2 %2
1647fd4e5da5Sopenharmony_ci%4 = OpConstantNull %3)";
1648fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1649fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1650fd4e5da5Sopenharmony_ci  EXPECT_THAT(
1651fd4e5da5Sopenharmony_ci      getDiagnosticString(),
1652fd4e5da5Sopenharmony_ci      HasSubstr(make_message("OpConstantNull Result Type <id> '2[%_struct_2]' "
1653fd4e5da5Sopenharmony_ci                             "cannot have a null value.")));
1654fd4e5da5Sopenharmony_ci}
1655fd4e5da5Sopenharmony_ci
1656fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpConstantNullRuntimeArrayBad) {
1657fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1658fd4e5da5Sopenharmony_ci%bool = OpTypeBool
1659fd4e5da5Sopenharmony_ci%array = OpTypeRuntimeArray %bool
1660fd4e5da5Sopenharmony_ci%null = OpConstantNull %array)";
1661fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1662fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1663fd4e5da5Sopenharmony_ci  EXPECT_THAT(
1664fd4e5da5Sopenharmony_ci      getDiagnosticString(),
1665fd4e5da5Sopenharmony_ci      HasSubstr(make_message(
1666fd4e5da5Sopenharmony_ci          "OpConstantNull Result Type <id> '2[%_runtimearr_bool]' cannot have "
1667fd4e5da5Sopenharmony_ci          "a null value.")));
1668fd4e5da5Sopenharmony_ci}
1669fd4e5da5Sopenharmony_ci
1670fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpSpecConstantTrueGood) {
1671fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1672fd4e5da5Sopenharmony_ci%1 = OpTypeBool
1673fd4e5da5Sopenharmony_ci%2 = OpSpecConstantTrue %1)";
1674fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1675fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1676fd4e5da5Sopenharmony_ci}
1677fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpSpecConstantTrueBad) {
1678fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1679fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
1680fd4e5da5Sopenharmony_ci%2 = OpSpecConstantTrue %1)";
1681fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1682fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1683fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1684fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
1685fd4e5da5Sopenharmony_ci                  "OpSpecConstantTrue Result Type <id> '1[%void]' is not "
1686fd4e5da5Sopenharmony_ci                  "a boolean type")));
1687fd4e5da5Sopenharmony_ci}
1688fd4e5da5Sopenharmony_ci
1689fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpSpecConstantFalseGood) {
1690fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1691fd4e5da5Sopenharmony_ci%1 = OpTypeBool
1692fd4e5da5Sopenharmony_ci%2 = OpSpecConstantFalse %1)";
1693fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1694fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1695fd4e5da5Sopenharmony_ci}
1696fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpSpecConstantFalseBad) {
1697fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1698fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
1699fd4e5da5Sopenharmony_ci%2 = OpSpecConstantFalse %1)";
1700fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1701fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1702fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1703fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
1704fd4e5da5Sopenharmony_ci                  "OpSpecConstantFalse Result Type <id> '1[%void]' is not "
1705fd4e5da5Sopenharmony_ci                  "a boolean type")));
1706fd4e5da5Sopenharmony_ci}
1707fd4e5da5Sopenharmony_ci
1708fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpSpecConstantGood) {
1709fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1710fd4e5da5Sopenharmony_ci%1 = OpTypeFloat 32
1711fd4e5da5Sopenharmony_ci%2 = OpSpecConstant %1 42)";
1712fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1713fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1714fd4e5da5Sopenharmony_ci}
1715fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpSpecConstantBad) {
1716fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1717fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
1718fd4e5da5Sopenharmony_ci%2 = OpSpecConstant !1 !4)";
1719fd4e5da5Sopenharmony_ci  // The expected failure code is implementation dependent (currently
1720fd4e5da5Sopenharmony_ci  // INVALID_BINARY because the binary parser catches these cases) and may
1721fd4e5da5Sopenharmony_ci  // change over time, but this must always fail.
1722fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1723fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions());
1724fd4e5da5Sopenharmony_ci  EXPECT_THAT(
1725fd4e5da5Sopenharmony_ci      getDiagnosticString(),
1726fd4e5da5Sopenharmony_ci      HasSubstr(make_message("Type Id 1 is not a scalar numeric type")));
1727fd4e5da5Sopenharmony_ci}
1728fd4e5da5Sopenharmony_ci
1729fd4e5da5Sopenharmony_ci// Valid: SpecConstantComposite specializes to a vector.
1730fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpSpecConstantCompositeVectorGood) {
1731fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1732fd4e5da5Sopenharmony_ci%1 = OpTypeFloat 32
1733fd4e5da5Sopenharmony_ci%2 = OpTypeVector %1 4
1734fd4e5da5Sopenharmony_ci%3 = OpSpecConstant %1 3.14
1735fd4e5da5Sopenharmony_ci%4 = OpConstant %1 3.14
1736fd4e5da5Sopenharmony_ci%5 = OpSpecConstantComposite %2 %3 %3 %4 %4)";
1737fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1738fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1739fd4e5da5Sopenharmony_ci}
1740fd4e5da5Sopenharmony_ci
1741fd4e5da5Sopenharmony_ci// Valid: Vector of floats and Undefs.
1742fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpSpecConstantCompositeVectorWithUndefGood) {
1743fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1744fd4e5da5Sopenharmony_ci%1 = OpTypeFloat 32
1745fd4e5da5Sopenharmony_ci%2 = OpTypeVector %1 4
1746fd4e5da5Sopenharmony_ci%3 = OpSpecConstant %1 3.14
1747fd4e5da5Sopenharmony_ci%5 = OpConstant %1 3.14
1748fd4e5da5Sopenharmony_ci%9 = OpUndef %1
1749fd4e5da5Sopenharmony_ci%4 = OpSpecConstantComposite %2 %3 %5 %3 %9)";
1750fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1751fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1752fd4e5da5Sopenharmony_ci}
1753fd4e5da5Sopenharmony_ci
1754fd4e5da5Sopenharmony_ci// Invalid: result type is float.
1755fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpSpecConstantCompositeVectorResultTypeBad) {
1756fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1757fd4e5da5Sopenharmony_ci%1 = OpTypeFloat 32
1758fd4e5da5Sopenharmony_ci%2 = OpTypeVector %1 4
1759fd4e5da5Sopenharmony_ci%3 = OpSpecConstant %1 3.14
1760fd4e5da5Sopenharmony_ci%4 = OpSpecConstantComposite %1 %3 %3 %3 %3)";
1761fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1762fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1763fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1764fd4e5da5Sopenharmony_ci              HasSubstr(make_message("is not a composite type")));
1765fd4e5da5Sopenharmony_ci}
1766fd4e5da5Sopenharmony_ci
1767fd4e5da5Sopenharmony_ci// Invalid: Vector contains a mix of Int and Float.
1768fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpSpecConstantCompositeVectorConstituentTypeBad) {
1769fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1770fd4e5da5Sopenharmony_ci%1 = OpTypeFloat 32
1771fd4e5da5Sopenharmony_ci%2 = OpTypeVector %1 4
1772fd4e5da5Sopenharmony_ci%4 = OpTypeInt 32 0
1773fd4e5da5Sopenharmony_ci%3 = OpSpecConstant %1 3.14
1774fd4e5da5Sopenharmony_ci%5 = OpConstant %4 42 ; bad type for constant value
1775fd4e5da5Sopenharmony_ci%6 = OpSpecConstantComposite %2 %3 %5 %3 %3)";
1776fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1777fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1778fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1779fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
1780fd4e5da5Sopenharmony_ci                  "OpSpecConstantComposite Constituent <id> "
1781fd4e5da5Sopenharmony_ci                  "'5[%uint_42]'s type does not match Result Type <id> "
1782fd4e5da5Sopenharmony_ci                  "'2[%v4float]'s vector element type.")));
1783fd4e5da5Sopenharmony_ci}
1784fd4e5da5Sopenharmony_ci
1785fd4e5da5Sopenharmony_ci// Invalid: Constituent is not a constant
1786fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage,
1787fd4e5da5Sopenharmony_ci       OpSpecConstantCompositeVectorConstituentNotConstantBad) {
1788fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1789fd4e5da5Sopenharmony_ci%1 = OpTypeFloat 32
1790fd4e5da5Sopenharmony_ci%2 = OpTypeVector %1 4
1791fd4e5da5Sopenharmony_ci%3 = OpTypeInt 32 0
1792fd4e5da5Sopenharmony_ci%4 = OpSpecConstant %1 3.14
1793fd4e5da5Sopenharmony_ci%5 = OpTypePointer Uniform %1
1794fd4e5da5Sopenharmony_ci%6 = OpVariable %5 Uniform
1795fd4e5da5Sopenharmony_ci%7 = OpSpecConstantComposite %2 %6 %4 %4 %4)";
1796fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1797fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1798fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1799fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
1800fd4e5da5Sopenharmony_ci                  "OpSpecConstantComposite Constituent <id> '6[%6]' is "
1801fd4e5da5Sopenharmony_ci                  "not a constant or undef.")));
1802fd4e5da5Sopenharmony_ci}
1803fd4e5da5Sopenharmony_ci
1804fd4e5da5Sopenharmony_ci// Invalid: Vector contains a mix of Undef-int and Float.
1805fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage,
1806fd4e5da5Sopenharmony_ci       OpSpecConstantCompositeVectorConstituentUndefTypeBad) {
1807fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1808fd4e5da5Sopenharmony_ci%1 = OpTypeFloat 32
1809fd4e5da5Sopenharmony_ci%2 = OpTypeVector %1 4
1810fd4e5da5Sopenharmony_ci%4 = OpTypeInt 32 0
1811fd4e5da5Sopenharmony_ci%3 = OpSpecConstant %1 3.14
1812fd4e5da5Sopenharmony_ci%5 = OpUndef %4 ; bad type for undef value
1813fd4e5da5Sopenharmony_ci%6 = OpSpecConstantComposite %2 %3 %5 %3 %3)";
1814fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1815fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1816fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1817fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
1818fd4e5da5Sopenharmony_ci                  "OpSpecConstantComposite Constituent <id> '5[%5]'s "
1819fd4e5da5Sopenharmony_ci                  "type does not match Result Type <id> '2[%v4float]'s "
1820fd4e5da5Sopenharmony_ci                  "vector element type.")));
1821fd4e5da5Sopenharmony_ci}
1822fd4e5da5Sopenharmony_ci
1823fd4e5da5Sopenharmony_ci// Invalid: Vector expects 3 components, but 4 specified.
1824fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpSpecConstantCompositeVectorNumComponentsBad) {
1825fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1826fd4e5da5Sopenharmony_ci%1 = OpTypeFloat 32
1827fd4e5da5Sopenharmony_ci%2 = OpTypeVector %1 3
1828fd4e5da5Sopenharmony_ci%3 = OpConstant %1 3.14
1829fd4e5da5Sopenharmony_ci%5 = OpSpecConstant %1 4.0
1830fd4e5da5Sopenharmony_ci%6 = OpSpecConstantComposite %2 %3 %5 %3 %3)";
1831fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1832fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1833fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1834fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
1835fd4e5da5Sopenharmony_ci                  "OpSpecConstantComposite Constituent <id> count does "
1836fd4e5da5Sopenharmony_ci                  "not match Result Type <id> '2[%v3float]'s vector "
1837fd4e5da5Sopenharmony_ci                  "component count.")));
1838fd4e5da5Sopenharmony_ci}
1839fd4e5da5Sopenharmony_ci
1840fd4e5da5Sopenharmony_ci// Valid: 4x4 matrix of floats
1841fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpSpecConstantCompositeMatrixGood) {
1842fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1843fd4e5da5Sopenharmony_ci %1 = OpTypeFloat 32
1844fd4e5da5Sopenharmony_ci %2 = OpTypeVector %1 4
1845fd4e5da5Sopenharmony_ci %3 = OpTypeMatrix %2 4
1846fd4e5da5Sopenharmony_ci %4 = OpConstant %1 1.0
1847fd4e5da5Sopenharmony_ci %5 = OpSpecConstant %1 0.0
1848fd4e5da5Sopenharmony_ci %6 = OpSpecConstantComposite %2 %4 %5 %5 %5
1849fd4e5da5Sopenharmony_ci %7 = OpSpecConstantComposite %2 %5 %4 %5 %5
1850fd4e5da5Sopenharmony_ci %8 = OpSpecConstantComposite %2 %5 %5 %4 %5
1851fd4e5da5Sopenharmony_ci %9 = OpSpecConstantComposite %2 %5 %5 %5 %4
1852fd4e5da5Sopenharmony_ci%10 = OpSpecConstantComposite %3 %6 %7 %8 %9)";
1853fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1854fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1855fd4e5da5Sopenharmony_ci}
1856fd4e5da5Sopenharmony_ci
1857fd4e5da5Sopenharmony_ci// Valid: Matrix in which one column is Undef
1858fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpSpecConstantCompositeMatrixUndefGood) {
1859fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1860fd4e5da5Sopenharmony_ci %1 = OpTypeFloat 32
1861fd4e5da5Sopenharmony_ci %2 = OpTypeVector %1 4
1862fd4e5da5Sopenharmony_ci %3 = OpTypeMatrix %2 4
1863fd4e5da5Sopenharmony_ci %4 = OpConstant %1 1.0
1864fd4e5da5Sopenharmony_ci %5 = OpSpecConstant %1 0.0
1865fd4e5da5Sopenharmony_ci %6 = OpSpecConstantComposite %2 %4 %5 %5 %5
1866fd4e5da5Sopenharmony_ci %7 = OpSpecConstantComposite %2 %5 %4 %5 %5
1867fd4e5da5Sopenharmony_ci %8 = OpSpecConstantComposite %2 %5 %5 %4 %5
1868fd4e5da5Sopenharmony_ci %9 = OpUndef %2
1869fd4e5da5Sopenharmony_ci%10 = OpSpecConstantComposite %3 %6 %7 %8 %9)";
1870fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1871fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
1872fd4e5da5Sopenharmony_ci}
1873fd4e5da5Sopenharmony_ci
1874fd4e5da5Sopenharmony_ci// Invalid: Matrix in which the sizes of column vectors are not equal.
1875fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpSpecConstantCompositeMatrixConstituentTypeBad) {
1876fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1877fd4e5da5Sopenharmony_ci %1 = OpTypeFloat 32
1878fd4e5da5Sopenharmony_ci %2 = OpTypeVector %1 4
1879fd4e5da5Sopenharmony_ci %3 = OpTypeVector %1 3
1880fd4e5da5Sopenharmony_ci %4 = OpTypeMatrix %2 4
1881fd4e5da5Sopenharmony_ci %5 = OpSpecConstant %1 1.0
1882fd4e5da5Sopenharmony_ci %6 = OpConstant %1 0.0
1883fd4e5da5Sopenharmony_ci %7 = OpSpecConstantComposite %2 %5 %6 %6 %6
1884fd4e5da5Sopenharmony_ci %8 = OpSpecConstantComposite %2 %6 %5 %6 %6
1885fd4e5da5Sopenharmony_ci %9 = OpSpecConstantComposite %2 %6 %6 %5 %6
1886fd4e5da5Sopenharmony_ci %10 = OpSpecConstantComposite %3 %6 %6 %6
1887fd4e5da5Sopenharmony_ci%11 = OpSpecConstantComposite %4 %7 %8 %9 %10)";
1888fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1889fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1890fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1891fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
1892fd4e5da5Sopenharmony_ci                  "OpSpecConstantComposite Constituent <id> '10[%10]' "
1893fd4e5da5Sopenharmony_ci                  "vector component count does not match Result Type "
1894fd4e5da5Sopenharmony_ci                  "<id> '4[%mat4v4float]'s vector component count.")));
1895fd4e5da5Sopenharmony_ci}
1896fd4e5da5Sopenharmony_ci
1897fd4e5da5Sopenharmony_ci// Invalid: Matrix type expects 4 columns but only 3 specified.
1898fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpSpecConstantCompositeMatrixNumColsBad) {
1899fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1900fd4e5da5Sopenharmony_ci %1 = OpTypeFloat 32
1901fd4e5da5Sopenharmony_ci %2 = OpTypeVector %1 4
1902fd4e5da5Sopenharmony_ci %3 = OpTypeMatrix %2 4
1903fd4e5da5Sopenharmony_ci %4 = OpSpecConstant %1 1.0
1904fd4e5da5Sopenharmony_ci %5 = OpConstant %1 0.0
1905fd4e5da5Sopenharmony_ci %6 = OpSpecConstantComposite %2 %4 %5 %5 %5
1906fd4e5da5Sopenharmony_ci %7 = OpSpecConstantComposite %2 %5 %4 %5 %5
1907fd4e5da5Sopenharmony_ci %8 = OpSpecConstantComposite %2 %5 %5 %4 %5
1908fd4e5da5Sopenharmony_ci%10 = OpSpecConstantComposite %3 %6 %7 %8)";
1909fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1910fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1911fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1912fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
1913fd4e5da5Sopenharmony_ci                  "OpSpecConstantComposite Constituent <id> count does "
1914fd4e5da5Sopenharmony_ci                  "not match Result Type <id> '3[%mat4v4float]'s matrix column "
1915fd4e5da5Sopenharmony_ci                  "count.")));
1916fd4e5da5Sopenharmony_ci}
1917fd4e5da5Sopenharmony_ci
1918fd4e5da5Sopenharmony_ci// Invalid: Composite contains a non-const/undef component
1919fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage,
1920fd4e5da5Sopenharmony_ci       OpSpecConstantCompositeMatrixConstituentNotConstBad) {
1921fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1922fd4e5da5Sopenharmony_ci %1 = OpTypeFloat 32
1923fd4e5da5Sopenharmony_ci %2 = OpConstant %1 0.0
1924fd4e5da5Sopenharmony_ci %3 = OpTypeVector %1 4
1925fd4e5da5Sopenharmony_ci %4 = OpTypeMatrix %3 4
1926fd4e5da5Sopenharmony_ci %5 = OpSpecConstantComposite %3 %2 %2 %2 %2
1927fd4e5da5Sopenharmony_ci %6 = OpTypePointer Uniform %1
1928fd4e5da5Sopenharmony_ci %7 = OpVariable %6 Uniform
1929fd4e5da5Sopenharmony_ci %8 = OpSpecConstantComposite %4 %5 %5 %5 %7)";
1930fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1931fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1932fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1933fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
1934fd4e5da5Sopenharmony_ci                  "OpSpecConstantComposite Constituent <id> '7[%7]' is "
1935fd4e5da5Sopenharmony_ci                  "not a constant or undef.")));
1936fd4e5da5Sopenharmony_ci}
1937fd4e5da5Sopenharmony_ci
1938fd4e5da5Sopenharmony_ci// Invalid: Composite contains a column that is *not* a vector (it's an array)
1939fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpSpecConstantCompositeMatrixColTypeBad) {
1940fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1941fd4e5da5Sopenharmony_ci %1 = OpTypeFloat 32
1942fd4e5da5Sopenharmony_ci %2 = OpTypeInt 32 0
1943fd4e5da5Sopenharmony_ci %3 = OpSpecConstant %2 4
1944fd4e5da5Sopenharmony_ci %4 = OpConstant %1 0.0
1945fd4e5da5Sopenharmony_ci %5 = OpTypeVector %1 4
1946fd4e5da5Sopenharmony_ci %6 = OpTypeArray %2 %3
1947fd4e5da5Sopenharmony_ci %7 = OpTypeMatrix %5 4
1948fd4e5da5Sopenharmony_ci %8  = OpSpecConstantComposite %6 %3 %3 %3 %3
1949fd4e5da5Sopenharmony_ci %9  = OpSpecConstantComposite %5 %4 %4 %4 %4
1950fd4e5da5Sopenharmony_ci %10 = OpSpecConstantComposite %7 %9 %9 %9 %8)";
1951fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1952fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1953fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1954fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
1955fd4e5da5Sopenharmony_ci                  "OpSpecConstantComposite Constituent <id> '8[%8]' type "
1956fd4e5da5Sopenharmony_ci                  "does not match Result Type <id> '7[%mat4v4float]'s "
1957fd4e5da5Sopenharmony_ci                  "matrix column type.")));
1958fd4e5da5Sopenharmony_ci}
1959fd4e5da5Sopenharmony_ci
1960fd4e5da5Sopenharmony_ci// Invalid: Matrix with an Undef column of the wrong size.
1961fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage,
1962fd4e5da5Sopenharmony_ci       OpSpecConstantCompositeMatrixConstituentUndefTypeBad) {
1963fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1964fd4e5da5Sopenharmony_ci %1 = OpTypeFloat 32
1965fd4e5da5Sopenharmony_ci %2 = OpTypeVector %1 4
1966fd4e5da5Sopenharmony_ci %3 = OpTypeVector %1 3
1967fd4e5da5Sopenharmony_ci %4 = OpTypeMatrix %2 4
1968fd4e5da5Sopenharmony_ci %5 = OpSpecConstant %1 1.0
1969fd4e5da5Sopenharmony_ci %6 = OpSpecConstant %1 0.0
1970fd4e5da5Sopenharmony_ci %7 = OpSpecConstantComposite %2 %5 %6 %6 %6
1971fd4e5da5Sopenharmony_ci %8 = OpSpecConstantComposite %2 %6 %5 %6 %6
1972fd4e5da5Sopenharmony_ci %9 = OpSpecConstantComposite %2 %6 %6 %5 %6
1973fd4e5da5Sopenharmony_ci %10 = OpUndef %3
1974fd4e5da5Sopenharmony_ci %11 = OpSpecConstantComposite %4 %7 %8 %9 %10)";
1975fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1976fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1977fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
1978fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
1979fd4e5da5Sopenharmony_ci                  "OpSpecConstantComposite Constituent <id> '10[%10]' "
1980fd4e5da5Sopenharmony_ci                  "vector component count does not match Result Type "
1981fd4e5da5Sopenharmony_ci                  "<id> '4[%mat4v4float]'s vector component count.")));
1982fd4e5da5Sopenharmony_ci}
1983fd4e5da5Sopenharmony_ci
1984fd4e5da5Sopenharmony_ci// Invalid: Matrix in which some columns are Int and some are Float.
1985fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpSpecConstantCompositeMatrixColumnTypeBad) {
1986fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
1987fd4e5da5Sopenharmony_ci %1 = OpTypeInt 32 0
1988fd4e5da5Sopenharmony_ci %2 = OpTypeFloat 32
1989fd4e5da5Sopenharmony_ci %3 = OpTypeVector %1 2
1990fd4e5da5Sopenharmony_ci %4 = OpTypeVector %2 2
1991fd4e5da5Sopenharmony_ci %5 = OpTypeMatrix %4 2
1992fd4e5da5Sopenharmony_ci %6 = OpSpecConstant %1 42
1993fd4e5da5Sopenharmony_ci %7 = OpConstant %2 3.14
1994fd4e5da5Sopenharmony_ci %8 = OpSpecConstantComposite %3 %6 %6
1995fd4e5da5Sopenharmony_ci %9 = OpSpecConstantComposite %4 %7 %7
1996fd4e5da5Sopenharmony_ci%10 = OpSpecConstantComposite %5 %8 %9)";
1997fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
1998fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
1999fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
2000fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
2001fd4e5da5Sopenharmony_ci                  "OpSpecConstantComposite Constituent <id> '8[%8]' "
2002fd4e5da5Sopenharmony_ci                  "component type does not match Result Type <id> "
2003fd4e5da5Sopenharmony_ci                  "'5[%mat2v2float]'s matrix column component type.")));
2004fd4e5da5Sopenharmony_ci}
2005fd4e5da5Sopenharmony_ci
2006fd4e5da5Sopenharmony_ci// Valid: Array of integers
2007fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpSpecConstantCompositeArrayGood) {
2008fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
2009fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
2010fd4e5da5Sopenharmony_ci%2 = OpSpecConstant %1 4
2011fd4e5da5Sopenharmony_ci%5 = OpConstant %1 5
2012fd4e5da5Sopenharmony_ci%3 = OpTypeArray %1 %2
2013fd4e5da5Sopenharmony_ci%6 = OpTypeArray %1 %5
2014fd4e5da5Sopenharmony_ci%4 = OpSpecConstantComposite %3 %2 %2 %2 %2
2015fd4e5da5Sopenharmony_ci%7 = OpSpecConstantComposite %3 %5 %5 %5 %5)";
2016fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
2017fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2018fd4e5da5Sopenharmony_ci}
2019fd4e5da5Sopenharmony_ci
2020fd4e5da5Sopenharmony_ci// Invalid: Expecting an array of 4 components, but 3 specified.
2021fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpSpecConstantCompositeArrayNumComponentsBad) {
2022fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
2023fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
2024fd4e5da5Sopenharmony_ci%2 = OpConstant %1 4
2025fd4e5da5Sopenharmony_ci%3 = OpTypeArray %1 %2
2026fd4e5da5Sopenharmony_ci%4 = OpSpecConstantComposite %3 %2 %2 %2)";
2027fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
2028fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2029fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
2030fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
2031fd4e5da5Sopenharmony_ci                  "OpSpecConstantComposite Constituent count does not "
2032fd4e5da5Sopenharmony_ci                  "match Result Type <id> '3[%_arr_uint_uint_4]'s array "
2033fd4e5da5Sopenharmony_ci                  "length.")));
2034fd4e5da5Sopenharmony_ci}
2035fd4e5da5Sopenharmony_ci
2036fd4e5da5Sopenharmony_ci// Valid: Array of Integers and Undef-int
2037fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpSpecConstantCompositeArrayWithUndefGood) {
2038fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
2039fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
2040fd4e5da5Sopenharmony_ci%2 = OpSpecConstant %1 4
2041fd4e5da5Sopenharmony_ci%9 = OpUndef %1
2042fd4e5da5Sopenharmony_ci%3 = OpTypeArray %1 %2
2043fd4e5da5Sopenharmony_ci%4 = OpSpecConstantComposite %3 %2 %2 %2 %9)";
2044fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
2045fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2046fd4e5da5Sopenharmony_ci}
2047fd4e5da5Sopenharmony_ci
2048fd4e5da5Sopenharmony_ci// Invalid: Array uses a type as operand.
2049fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpSpecConstantCompositeArrayConstConstituentBad) {
2050fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
2051fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
2052fd4e5da5Sopenharmony_ci%2 = OpConstant %1 4
2053fd4e5da5Sopenharmony_ci%3 = OpTypeArray %1 %2
2054fd4e5da5Sopenharmony_ci%4 = OpTypePointer Uniform %1
2055fd4e5da5Sopenharmony_ci%5 = OpVariable %4 Uniform
2056fd4e5da5Sopenharmony_ci%6 = OpSpecConstantComposite %3 %2 %2 %2 %5)";
2057fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
2058fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2059fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
2060fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
2061fd4e5da5Sopenharmony_ci                  "OpSpecConstantComposite Constituent <id> '5[%5]' is "
2062fd4e5da5Sopenharmony_ci                  "not a constant or undef.")));
2063fd4e5da5Sopenharmony_ci}
2064fd4e5da5Sopenharmony_ci
2065fd4e5da5Sopenharmony_ci// Invalid: Array has a mix of Int and Float components.
2066fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpSpecConstantCompositeArrayConstituentTypeBad) {
2067fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
2068fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
2069fd4e5da5Sopenharmony_ci%2 = OpConstant %1 4
2070fd4e5da5Sopenharmony_ci%3 = OpTypeArray %1 %2
2071fd4e5da5Sopenharmony_ci%4 = OpTypeFloat 32
2072fd4e5da5Sopenharmony_ci%5 = OpSpecConstant %4 3.14 ; bad type for const value
2073fd4e5da5Sopenharmony_ci%6 = OpSpecConstantComposite %3 %2 %2 %2 %5)";
2074fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
2075fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2076fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
2077fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
2078fd4e5da5Sopenharmony_ci                  "OpSpecConstantComposite Constituent <id> '5[%5]'s "
2079fd4e5da5Sopenharmony_ci                  "type does not match Result Type <id> "
2080fd4e5da5Sopenharmony_ci                  "'3[%_arr_uint_uint_4]'s array element type.")));
2081fd4e5da5Sopenharmony_ci}
2082fd4e5da5Sopenharmony_ci
2083fd4e5da5Sopenharmony_ci// Invalid: Array has a mix of Int and Undef-float.
2084fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage,
2085fd4e5da5Sopenharmony_ci       OpSpecConstantCompositeArrayConstituentUndefTypeBad) {
2086fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
2087fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
2088fd4e5da5Sopenharmony_ci%2 = OpSpecConstant %1 4
2089fd4e5da5Sopenharmony_ci%3 = OpTypeArray %1 %2
2090fd4e5da5Sopenharmony_ci%5 = OpTypeFloat 32
2091fd4e5da5Sopenharmony_ci%6 = OpUndef %5 ; bad type for undef
2092fd4e5da5Sopenharmony_ci%4 = OpSpecConstantComposite %3 %2 %2 %2 %6)";
2093fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
2094fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2095fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
2096fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
2097fd4e5da5Sopenharmony_ci                  "OpSpecConstantComposite Constituent <id> '5[%5]'s "
2098fd4e5da5Sopenharmony_ci                  "type does not match Result Type <id> "
2099fd4e5da5Sopenharmony_ci                  "'3[%_arr_uint_2]'s array element type.")));
2100fd4e5da5Sopenharmony_ci}
2101fd4e5da5Sopenharmony_ci
2102fd4e5da5Sopenharmony_ci// Valid: Struct of {Int32,Int32,Int64}.
2103fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpSpecConstantCompositeStructGood) {
2104fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
2105fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
2106fd4e5da5Sopenharmony_ci%2 = OpTypeInt 64 0
2107fd4e5da5Sopenharmony_ci%3 = OpTypeStruct %1 %1 %2
2108fd4e5da5Sopenharmony_ci%4 = OpConstant %1 42
2109fd4e5da5Sopenharmony_ci%5 = OpSpecConstant %2 4300000000
2110fd4e5da5Sopenharmony_ci%6 = OpSpecConstantComposite %3 %4 %4 %5)";
2111fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
2112fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2113fd4e5da5Sopenharmony_ci}
2114fd4e5da5Sopenharmony_ci
2115fd4e5da5Sopenharmony_ci// Invalid: missing one int32 struct member.
2116fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage,
2117fd4e5da5Sopenharmony_ci       OpSpecConstantCompositeStructMissingComponentBad) {
2118fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
2119fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
2120fd4e5da5Sopenharmony_ci%3 = OpTypeStruct %1 %1 %1
2121fd4e5da5Sopenharmony_ci%4 = OpConstant %1 42
2122fd4e5da5Sopenharmony_ci%5 = OpSpecConstant %1 430
2123fd4e5da5Sopenharmony_ci%6 = OpSpecConstantComposite %3 %4 %5)";
2124fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
2125fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2126fd4e5da5Sopenharmony_ci  EXPECT_THAT(
2127fd4e5da5Sopenharmony_ci      getDiagnosticString(),
2128fd4e5da5Sopenharmony_ci      HasSubstr(make_message("OpSpecConstantComposite Constituent <id> "
2129fd4e5da5Sopenharmony_ci                             "'2[%_struct_2]' count does not match Result Type "
2130fd4e5da5Sopenharmony_ci                             "<id> '2[%_struct_2]'s struct member count.")));
2131fd4e5da5Sopenharmony_ci}
2132fd4e5da5Sopenharmony_ci
2133fd4e5da5Sopenharmony_ci// Valid: Struct uses Undef-int64.
2134fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpSpecConstantCompositeStructUndefGood) {
2135fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
2136fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
2137fd4e5da5Sopenharmony_ci%2 = OpTypeInt 64 0
2138fd4e5da5Sopenharmony_ci%3 = OpTypeStruct %1 %1 %2
2139fd4e5da5Sopenharmony_ci%4 = OpSpecConstant %1 42
2140fd4e5da5Sopenharmony_ci%5 = OpUndef %2
2141fd4e5da5Sopenharmony_ci%6 = OpSpecConstantComposite %3 %4 %4 %5)";
2142fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
2143fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2144fd4e5da5Sopenharmony_ci}
2145fd4e5da5Sopenharmony_ci
2146fd4e5da5Sopenharmony_ci// Invalid: Composite contains non-const/undef component.
2147fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpSpecConstantCompositeStructNonConstBad) {
2148fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
2149fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
2150fd4e5da5Sopenharmony_ci%2 = OpTypeInt 64 0
2151fd4e5da5Sopenharmony_ci%3 = OpTypeStruct %1 %1 %2
2152fd4e5da5Sopenharmony_ci%4 = OpSpecConstant %1 42
2153fd4e5da5Sopenharmony_ci%5 = OpUndef %2
2154fd4e5da5Sopenharmony_ci%6 = OpTypePointer Uniform %1
2155fd4e5da5Sopenharmony_ci%7 = OpVariable %6 Uniform
2156fd4e5da5Sopenharmony_ci%8 = OpSpecConstantComposite %3 %4 %7 %5)";
2157fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
2158fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2159fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
2160fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
2161fd4e5da5Sopenharmony_ci                  "OpSpecConstantComposite Constituent <id> '7[%7]' is "
2162fd4e5da5Sopenharmony_ci                  "not a constant or undef.")));
2163fd4e5da5Sopenharmony_ci}
2164fd4e5da5Sopenharmony_ci
2165fd4e5da5Sopenharmony_ci// Invalid: Struct component type does not match expected specialization type.
2166fd4e5da5Sopenharmony_ci// Second component was expected to be Int32, but got Int64.
2167fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpSpecConstantCompositeStructMemberTypeBad) {
2168fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
2169fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
2170fd4e5da5Sopenharmony_ci%2 = OpTypeInt 64 0
2171fd4e5da5Sopenharmony_ci%3 = OpTypeStruct %1 %1 %2
2172fd4e5da5Sopenharmony_ci%4 = OpConstant %1 42
2173fd4e5da5Sopenharmony_ci%5 = OpSpecConstant %2 4300000000
2174fd4e5da5Sopenharmony_ci%6 = OpSpecConstantComposite %3 %4 %5 %4)";
2175fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
2176fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2177fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
2178fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
2179fd4e5da5Sopenharmony_ci                  "OpSpecConstantComposite Constituent <id> '5[%5]' type "
2180fd4e5da5Sopenharmony_ci                  "does not match the Result Type <id> '3[%_struct_3]'s "
2181fd4e5da5Sopenharmony_ci                  "member type.")));
2182fd4e5da5Sopenharmony_ci}
2183fd4e5da5Sopenharmony_ci
2184fd4e5da5Sopenharmony_ci// Invalid: Undef-int64 used when Int32 was expected.
2185fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpSpecConstantCompositeStructMemberUndefTypeBad) {
2186fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
2187fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
2188fd4e5da5Sopenharmony_ci%2 = OpTypeInt 64 0
2189fd4e5da5Sopenharmony_ci%3 = OpTypeStruct %1 %1 %2
2190fd4e5da5Sopenharmony_ci%4 = OpSpecConstant %1 42
2191fd4e5da5Sopenharmony_ci%5 = OpUndef %2
2192fd4e5da5Sopenharmony_ci%6 = OpSpecConstantComposite %3 %4 %5 %4)";
2193fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
2194fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2195fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
2196fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
2197fd4e5da5Sopenharmony_ci                  "OpSpecConstantComposite Constituent <id> '5[%5]' type "
2198fd4e5da5Sopenharmony_ci                  "does not match the Result Type <id> '3[%_struct_3]'s "
2199fd4e5da5Sopenharmony_ci                  "member type.")));
2200fd4e5da5Sopenharmony_ci}
2201fd4e5da5Sopenharmony_ci
2202fd4e5da5Sopenharmony_ci// TODO: OpSpecConstantOp
2203fd4e5da5Sopenharmony_ci
2204fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpVariableGood) {
2205fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
2206fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
2207fd4e5da5Sopenharmony_ci%2 = OpTypePointer Input %1
2208fd4e5da5Sopenharmony_ci%3 = OpVariable %2 Input)";
2209fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
2210fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2211fd4e5da5Sopenharmony_ci}
2212fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpVariableInitializerConstantGood) {
2213fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
2214fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
2215fd4e5da5Sopenharmony_ci%2 = OpTypePointer Output %1
2216fd4e5da5Sopenharmony_ci%3 = OpConstant %1 42
2217fd4e5da5Sopenharmony_ci%4 = OpVariable %2 Output %3)";
2218fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
2219fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2220fd4e5da5Sopenharmony_ci}
2221fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpVariableInitializerGlobalVariableGood) {
2222fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
2223fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
2224fd4e5da5Sopenharmony_ci%2 = OpTypePointer Uniform %1
2225fd4e5da5Sopenharmony_ci%3 = OpVariable %2 Uniform
2226fd4e5da5Sopenharmony_ci%4 = OpTypePointer Private %2 ; pointer to pointer
2227fd4e5da5Sopenharmony_ci%5 = OpVariable %4 Private %3
2228fd4e5da5Sopenharmony_ci)";
2229fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
2230fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2231fd4e5da5Sopenharmony_ci}
2232fd4e5da5Sopenharmony_ci// TODO: Positive test OpVariable with OpConstantNull of OpTypePointer
2233fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpVariableResultTypeBad) {
2234fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
2235fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
2236fd4e5da5Sopenharmony_ci%2 = OpVariable %1 Input)";
2237fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
2238fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2239fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
2240fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
2241fd4e5da5Sopenharmony_ci                  "OpVariable Result Type <id> '1[%uint]' is not a pointer "
2242fd4e5da5Sopenharmony_ci                  "type.")));
2243fd4e5da5Sopenharmony_ci}
2244fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpVariableInitializerIsTypeBad) {
2245fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
2246fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
2247fd4e5da5Sopenharmony_ci%2 = OpTypePointer Input %1
2248fd4e5da5Sopenharmony_ci%3 = OpVariable %2 Input %2)";
2249fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
2250fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2251fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
2252fd4e5da5Sopenharmony_ci              HasSubstr(make_message("Operand '2[%_ptr_Input_uint]' "
2253fd4e5da5Sopenharmony_ci                                     "cannot be a type")));
2254fd4e5da5Sopenharmony_ci}
2255fd4e5da5Sopenharmony_ci
2256fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpVariableInitializerIsFunctionVarBad) {
2257fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
2258fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
2259fd4e5da5Sopenharmony_ci%ptrint = OpTypePointer Function %int
2260fd4e5da5Sopenharmony_ci%ptrptrint = OpTypePointer Function %ptrint
2261fd4e5da5Sopenharmony_ci%void = OpTypeVoid
2262fd4e5da5Sopenharmony_ci%fnty = OpTypeFunction %void
2263fd4e5da5Sopenharmony_ci%main = OpFunction %void None %fnty
2264fd4e5da5Sopenharmony_ci%entry = OpLabel
2265fd4e5da5Sopenharmony_ci%var = OpVariable %ptrint Function
2266fd4e5da5Sopenharmony_ci%varinit = OpVariable %ptrptrint Function %var ; Can't initialize function variable.
2267fd4e5da5Sopenharmony_ciOpReturn
2268fd4e5da5Sopenharmony_ciOpFunctionEnd
2269fd4e5da5Sopenharmony_ci)";
2270fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
2271fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2272fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
2273fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
2274fd4e5da5Sopenharmony_ci                  "OpVariable Initializer <id> '8[%8]' is not a constant "
2275fd4e5da5Sopenharmony_ci                  "or module-scope variable")));
2276fd4e5da5Sopenharmony_ci}
2277fd4e5da5Sopenharmony_ci
2278fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpVariableInitializerIsModuleVarGood) {
2279fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
2280fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
2281fd4e5da5Sopenharmony_ci%ptrint = OpTypePointer Uniform %int
2282fd4e5da5Sopenharmony_ci%mvar = OpVariable %ptrint Uniform
2283fd4e5da5Sopenharmony_ci%ptrptrint = OpTypePointer Function %ptrint
2284fd4e5da5Sopenharmony_ci%void = OpTypeVoid
2285fd4e5da5Sopenharmony_ci%fnty = OpTypeFunction %void
2286fd4e5da5Sopenharmony_ci%main = OpFunction %void None %fnty
2287fd4e5da5Sopenharmony_ci%entry = OpLabel
2288fd4e5da5Sopenharmony_ci%goodvar = OpVariable %ptrptrint Function %mvar ; This is ok
2289fd4e5da5Sopenharmony_ciOpReturn
2290fd4e5da5Sopenharmony_ciOpFunctionEnd
2291fd4e5da5Sopenharmony_ci)";
2292fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
2293fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2294fd4e5da5Sopenharmony_ci}
2295fd4e5da5Sopenharmony_ci
2296fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpVariableContainsBoolBad) {
2297fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
2298fd4e5da5Sopenharmony_ci%bool = OpTypeBool
2299fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
2300fd4e5da5Sopenharmony_ci%block = OpTypeStruct %bool %int
2301fd4e5da5Sopenharmony_ci%_ptr_Uniform_block = OpTypePointer Uniform %block
2302fd4e5da5Sopenharmony_ci%var = OpVariable %_ptr_Uniform_block Uniform
2303fd4e5da5Sopenharmony_ci%void = OpTypeVoid
2304fd4e5da5Sopenharmony_ci%fnty = OpTypeFunction %void
2305fd4e5da5Sopenharmony_ci%main = OpFunction %void None %fnty
2306fd4e5da5Sopenharmony_ci%entry = OpLabel
2307fd4e5da5Sopenharmony_ci%load = OpLoad %block %var
2308fd4e5da5Sopenharmony_ciOpReturn
2309fd4e5da5Sopenharmony_ciOpFunctionEnd
2310fd4e5da5Sopenharmony_ci)";
2311fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
2312fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2313fd4e5da5Sopenharmony_ci  EXPECT_THAT(
2314fd4e5da5Sopenharmony_ci      getDiagnosticString(),
2315fd4e5da5Sopenharmony_ci      HasSubstr(make_message(
2316fd4e5da5Sopenharmony_ci          "If OpTypeBool is stored in conjunction with OpVariable, it can only "
2317fd4e5da5Sopenharmony_ci          "be used with non-externally visible shader Storage Classes: "
2318fd4e5da5Sopenharmony_ci          "Workgroup, CrossWorkgroup, Private, Function, Input, Output, "
2319fd4e5da5Sopenharmony_ci          "RayPayloadKHR, IncomingRayPayloadKHR, HitAttributeKHR, "
2320fd4e5da5Sopenharmony_ci          "CallableDataKHR, IncomingCallableDataKHR, or UniformConstant")));
2321fd4e5da5Sopenharmony_ci}
2322fd4e5da5Sopenharmony_ci
2323fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpVariableContainsBoolPrivateGood) {
2324fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
2325fd4e5da5Sopenharmony_ci%bool = OpTypeBool
2326fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
2327fd4e5da5Sopenharmony_ci%block = OpTypeStruct %bool %int
2328fd4e5da5Sopenharmony_ci%_ptr_Private_block = OpTypePointer Private %block
2329fd4e5da5Sopenharmony_ci%var = OpVariable %_ptr_Private_block Private
2330fd4e5da5Sopenharmony_ci%void = OpTypeVoid
2331fd4e5da5Sopenharmony_ci%fnty = OpTypeFunction %void
2332fd4e5da5Sopenharmony_ci%main = OpFunction %void None %fnty
2333fd4e5da5Sopenharmony_ci%entry = OpLabel
2334fd4e5da5Sopenharmony_ci%load = OpLoad %block %var
2335fd4e5da5Sopenharmony_ciOpReturn
2336fd4e5da5Sopenharmony_ciOpFunctionEnd
2337fd4e5da5Sopenharmony_ci)";
2338fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
2339fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2340fd4e5da5Sopenharmony_ci}
2341fd4e5da5Sopenharmony_ci
2342fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpVariableContainsBoolUniformConstantGood) {
2343fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
2344fd4e5da5Sopenharmony_ci%bool = OpTypeBool
2345fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
2346fd4e5da5Sopenharmony_ci%block = OpTypeStruct %bool %int
2347fd4e5da5Sopenharmony_ci%_ptr_UniformConstant_block = OpTypePointer UniformConstant %block
2348fd4e5da5Sopenharmony_ci%var = OpVariable %_ptr_UniformConstant_block UniformConstant
2349fd4e5da5Sopenharmony_ci%void = OpTypeVoid
2350fd4e5da5Sopenharmony_ci%fnty = OpTypeFunction %void
2351fd4e5da5Sopenharmony_ci%main = OpFunction %void None %fnty
2352fd4e5da5Sopenharmony_ci%entry = OpLabel
2353fd4e5da5Sopenharmony_ci%load = OpLoad %block %var
2354fd4e5da5Sopenharmony_ciOpReturn
2355fd4e5da5Sopenharmony_ciOpFunctionEnd
2356fd4e5da5Sopenharmony_ci)";
2357fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
2358fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2359fd4e5da5Sopenharmony_ci}
2360fd4e5da5Sopenharmony_ci
2361fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpVariableContainsBoolPointerGood) {
2362fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
2363fd4e5da5Sopenharmony_ci%bool = OpTypeBool
2364fd4e5da5Sopenharmony_ci%boolptr = OpTypePointer Uniform %bool
2365fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
2366fd4e5da5Sopenharmony_ci%block = OpTypeStruct %boolptr %int
2367fd4e5da5Sopenharmony_ci%_ptr_Uniform_block = OpTypePointer Uniform %block
2368fd4e5da5Sopenharmony_ci%var = OpVariable %_ptr_Uniform_block Uniform
2369fd4e5da5Sopenharmony_ci%void = OpTypeVoid
2370fd4e5da5Sopenharmony_ci%fnty = OpTypeFunction %void
2371fd4e5da5Sopenharmony_ci%main = OpFunction %void None %fnty
2372fd4e5da5Sopenharmony_ci%entry = OpLabel
2373fd4e5da5Sopenharmony_ci%load = OpLoad %block %var
2374fd4e5da5Sopenharmony_ciOpReturn
2375fd4e5da5Sopenharmony_ciOpFunctionEnd
2376fd4e5da5Sopenharmony_ci)";
2377fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
2378fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2379fd4e5da5Sopenharmony_ci}
2380fd4e5da5Sopenharmony_ci
2381fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpVariableContainsBuiltinBoolGood) {
2382fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
2383fd4e5da5Sopenharmony_ciOpMemberDecorate %input 0 BuiltIn FrontFacing
2384fd4e5da5Sopenharmony_ci%bool = OpTypeBool
2385fd4e5da5Sopenharmony_ci%input = OpTypeStruct %bool
2386fd4e5da5Sopenharmony_ci%_ptr_input = OpTypePointer Input %input
2387fd4e5da5Sopenharmony_ci%var = OpVariable %_ptr_input Input
2388fd4e5da5Sopenharmony_ci%void = OpTypeVoid
2389fd4e5da5Sopenharmony_ci%fnty = OpTypeFunction %void
2390fd4e5da5Sopenharmony_ci%main = OpFunction %void None %fnty
2391fd4e5da5Sopenharmony_ci%entry = OpLabel
2392fd4e5da5Sopenharmony_ci%load = OpLoad %input %var
2393fd4e5da5Sopenharmony_ciOpReturn
2394fd4e5da5Sopenharmony_ciOpFunctionEnd
2395fd4e5da5Sopenharmony_ci)";
2396fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
2397fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2398fd4e5da5Sopenharmony_ci}
2399fd4e5da5Sopenharmony_ci
2400fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpVariableContainsNoBuiltinBoolBad) {
2401fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
2402fd4e5da5Sopenharmony_ci%bool = OpTypeBool
2403fd4e5da5Sopenharmony_ci%input = OpTypeStruct %bool
2404fd4e5da5Sopenharmony_ci%_ptr_input = OpTypePointer Input %input
2405fd4e5da5Sopenharmony_ci%var = OpVariable %_ptr_input Input
2406fd4e5da5Sopenharmony_ci%void = OpTypeVoid
2407fd4e5da5Sopenharmony_ci%fnty = OpTypeFunction %void
2408fd4e5da5Sopenharmony_ci%main = OpFunction %void None %fnty
2409fd4e5da5Sopenharmony_ci%entry = OpLabel
2410fd4e5da5Sopenharmony_ci%load = OpLoad %input %var
2411fd4e5da5Sopenharmony_ciOpReturn
2412fd4e5da5Sopenharmony_ciOpFunctionEnd
2413fd4e5da5Sopenharmony_ci)";
2414fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
2415fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2416fd4e5da5Sopenharmony_ci  EXPECT_THAT(
2417fd4e5da5Sopenharmony_ci      getDiagnosticString(),
2418fd4e5da5Sopenharmony_ci      HasSubstr(make_message(
2419fd4e5da5Sopenharmony_ci          "If OpTypeBool is stored in conjunction with OpVariable using Input "
2420fd4e5da5Sopenharmony_ci          "or Output Storage Classes it requires a BuiltIn decoration")));
2421fd4e5da5Sopenharmony_ci}
2422fd4e5da5Sopenharmony_ci
2423fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpVariableContainsNoBuiltinBoolBadVulkan) {
2424fd4e5da5Sopenharmony_ci  std::string spirv = R"(
2425fd4e5da5Sopenharmony_ciOpCapability Shader
2426fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
2427fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" %var
2428fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft
2429fd4e5da5Sopenharmony_ci%bool = OpTypeBool
2430fd4e5da5Sopenharmony_ci%input = OpTypeStruct %bool
2431fd4e5da5Sopenharmony_ci%_ptr_input = OpTypePointer Input %input
2432fd4e5da5Sopenharmony_ci%var = OpVariable %_ptr_input Input
2433fd4e5da5Sopenharmony_ci%void = OpTypeVoid
2434fd4e5da5Sopenharmony_ci%fnty = OpTypeFunction %void
2435fd4e5da5Sopenharmony_ci%main = OpFunction %void None %fnty
2436fd4e5da5Sopenharmony_ci%entry = OpLabel
2437fd4e5da5Sopenharmony_ci%load = OpLoad %input %var
2438fd4e5da5Sopenharmony_ciOpReturn
2439fd4e5da5Sopenharmony_ciOpFunctionEnd
2440fd4e5da5Sopenharmony_ci)";
2441fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str(), SPV_ENV_VULKAN_1_0);
2442fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_VULKAN_1_0));
2443fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
2444fd4e5da5Sopenharmony_ci              AnyVUID("VUID-StandaloneSpirv-Input-07290"));
2445fd4e5da5Sopenharmony_ci  EXPECT_THAT(
2446fd4e5da5Sopenharmony_ci      getDiagnosticString(),
2447fd4e5da5Sopenharmony_ci      HasSubstr(make_message(
2448fd4e5da5Sopenharmony_ci          "If OpTypeBool is stored in conjunction with OpVariable using Input "
2449fd4e5da5Sopenharmony_ci          "or Output Storage Classes it requires a BuiltIn decoration")));
2450fd4e5da5Sopenharmony_ci}
2451fd4e5da5Sopenharmony_ci
2452fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpVariableContainsRayPayloadBoolGood) {
2453fd4e5da5Sopenharmony_ci  std::string spirv = R"(
2454fd4e5da5Sopenharmony_ciOpCapability RayTracingNV
2455fd4e5da5Sopenharmony_ciOpCapability Shader
2456fd4e5da5Sopenharmony_ciOpCapability Linkage
2457fd4e5da5Sopenharmony_ciOpExtension "SPV_NV_ray_tracing"
2458fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
2459fd4e5da5Sopenharmony_ci%bool = OpTypeBool
2460fd4e5da5Sopenharmony_ci%PerRayData = OpTypeStruct %bool
2461fd4e5da5Sopenharmony_ci%_ptr_PerRayData = OpTypePointer RayPayloadNV %PerRayData
2462fd4e5da5Sopenharmony_ci%var = OpVariable %_ptr_PerRayData RayPayloadNV
2463fd4e5da5Sopenharmony_ci%void = OpTypeVoid
2464fd4e5da5Sopenharmony_ci%fnty = OpTypeFunction %void
2465fd4e5da5Sopenharmony_ci%main = OpFunction %void None %fnty
2466fd4e5da5Sopenharmony_ci%entry = OpLabel
2467fd4e5da5Sopenharmony_ci%load = OpLoad %PerRayData %var
2468fd4e5da5Sopenharmony_ciOpReturn
2469fd4e5da5Sopenharmony_ciOpFunctionEnd
2470fd4e5da5Sopenharmony_ci)";
2471fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
2472fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2473fd4e5da5Sopenharmony_ci}
2474fd4e5da5Sopenharmony_ci
2475fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpVariablePointerNoVariablePointersBad) {
2476fd4e5da5Sopenharmony_ci  const std::string spirv = R"(
2477fd4e5da5Sopenharmony_ciOpCapability Shader
2478fd4e5da5Sopenharmony_ciOpCapability Linkage
2479fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
2480fd4e5da5Sopenharmony_ci%void = OpTypeVoid
2481fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
2482fd4e5da5Sopenharmony_ci%_ptr_workgroup_int = OpTypePointer Workgroup %int
2483fd4e5da5Sopenharmony_ci%_ptr_function_ptr = OpTypePointer Function %_ptr_workgroup_int
2484fd4e5da5Sopenharmony_ci%voidfn = OpTypeFunction %void
2485fd4e5da5Sopenharmony_ci%func = OpFunction %void None %voidfn
2486fd4e5da5Sopenharmony_ci%entry = OpLabel
2487fd4e5da5Sopenharmony_ci%var = OpVariable %_ptr_function_ptr Function
2488fd4e5da5Sopenharmony_ciOpReturn
2489fd4e5da5Sopenharmony_ciOpFunctionEnd
2490fd4e5da5Sopenharmony_ci)";
2491fd4e5da5Sopenharmony_ci
2492fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
2493fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2494fd4e5da5Sopenharmony_ci  EXPECT_THAT(
2495fd4e5da5Sopenharmony_ci      getDiagnosticString(),
2496fd4e5da5Sopenharmony_ci      HasSubstr(make_message(
2497fd4e5da5Sopenharmony_ci          "In Logical addressing, variables may not allocate a pointer type")));
2498fd4e5da5Sopenharmony_ci}
2499fd4e5da5Sopenharmony_ci
2500fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage,
2501fd4e5da5Sopenharmony_ci       OpVariablePointerNoVariablePointersRelaxedLogicalGood) {
2502fd4e5da5Sopenharmony_ci  const std::string spirv = R"(
2503fd4e5da5Sopenharmony_ciOpCapability Shader
2504fd4e5da5Sopenharmony_ciOpCapability Linkage
2505fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
2506fd4e5da5Sopenharmony_ci%void = OpTypeVoid
2507fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
2508fd4e5da5Sopenharmony_ci%_ptr_workgroup_int = OpTypePointer Workgroup %int
2509fd4e5da5Sopenharmony_ci%_ptr_function_ptr = OpTypePointer Function %_ptr_workgroup_int
2510fd4e5da5Sopenharmony_ci%voidfn = OpTypeFunction %void
2511fd4e5da5Sopenharmony_ci%func = OpFunction %void None %voidfn
2512fd4e5da5Sopenharmony_ci%entry = OpLabel
2513fd4e5da5Sopenharmony_ci%var = OpVariable %_ptr_function_ptr Function
2514fd4e5da5Sopenharmony_ciOpReturn
2515fd4e5da5Sopenharmony_ciOpFunctionEnd
2516fd4e5da5Sopenharmony_ci)";
2517fd4e5da5Sopenharmony_ci
2518fd4e5da5Sopenharmony_ci  auto options = getValidatorOptions();
2519fd4e5da5Sopenharmony_ci  options->relax_logical_pointer = true;
2520fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
2521fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2522fd4e5da5Sopenharmony_ci}
2523fd4e5da5Sopenharmony_ci
2524fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpFunctionWithNonMemoryObject) {
2525fd4e5da5Sopenharmony_ci  // DXC generates code that looks like when given something like:
2526fd4e5da5Sopenharmony_ci  //   T t;
2527fd4e5da5Sopenharmony_ci  //   t.s.fn_1();
2528fd4e5da5Sopenharmony_ci  // This needs to be accepted before legalization takes place, so we
2529fd4e5da5Sopenharmony_ci  // will include it with the relaxed logical pointer.
2530fd4e5da5Sopenharmony_ci
2531fd4e5da5Sopenharmony_ci  const std::string spirv = R"(
2532fd4e5da5Sopenharmony_ci               OpCapability Shader
2533fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
2534fd4e5da5Sopenharmony_ci               OpEntryPoint Vertex %1 "main"
2535fd4e5da5Sopenharmony_ci               OpSource HLSL 600
2536fd4e5da5Sopenharmony_ci        %int = OpTypeInt 32 1
2537fd4e5da5Sopenharmony_ci      %int_0 = OpConstant %int 0
2538fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
2539fd4e5da5Sopenharmony_ci          %9 = OpTypeFunction %void
2540fd4e5da5Sopenharmony_ci  %_struct_5 = OpTypeStruct
2541fd4e5da5Sopenharmony_ci  %_struct_6 = OpTypeStruct %_struct_5
2542fd4e5da5Sopenharmony_ci%_ptr_Function__struct_6 = OpTypePointer Function %_struct_6
2543fd4e5da5Sopenharmony_ci%_ptr_Function__struct_5 = OpTypePointer Function %_struct_5
2544fd4e5da5Sopenharmony_ci         %23 = OpTypeFunction %void %_ptr_Function__struct_5
2545fd4e5da5Sopenharmony_ci          %1 = OpFunction %void None %9
2546fd4e5da5Sopenharmony_ci         %10 = OpLabel
2547fd4e5da5Sopenharmony_ci         %11 = OpVariable %_ptr_Function__struct_6 Function
2548fd4e5da5Sopenharmony_ci         %20 = OpAccessChain %_ptr_Function__struct_5 %11 %int_0
2549fd4e5da5Sopenharmony_ci         %21 = OpFunctionCall %void %12 %20
2550fd4e5da5Sopenharmony_ci               OpReturn
2551fd4e5da5Sopenharmony_ci               OpFunctionEnd
2552fd4e5da5Sopenharmony_ci         %12 = OpFunction %void None %23
2553fd4e5da5Sopenharmony_ci         %13 = OpFunctionParameter %_ptr_Function__struct_5
2554fd4e5da5Sopenharmony_ci         %14 = OpLabel
2555fd4e5da5Sopenharmony_ci               OpReturn
2556fd4e5da5Sopenharmony_ci               OpFunctionEnd
2557fd4e5da5Sopenharmony_ci)";
2558fd4e5da5Sopenharmony_ci
2559fd4e5da5Sopenharmony_ci  auto options = getValidatorOptions();
2560fd4e5da5Sopenharmony_ci  options->relax_logical_pointer = true;
2561fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
2562fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2563fd4e5da5Sopenharmony_ci}
2564fd4e5da5Sopenharmony_ci
2565fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage,
2566fd4e5da5Sopenharmony_ci       OpVariablePointerVariablePointersStorageBufferGood) {
2567fd4e5da5Sopenharmony_ci  const std::string spirv = R"(
2568fd4e5da5Sopenharmony_ciOpCapability Shader
2569fd4e5da5Sopenharmony_ciOpCapability Linkage
2570fd4e5da5Sopenharmony_ciOpCapability VariablePointersStorageBuffer
2571fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_variable_pointers"
2572fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
2573fd4e5da5Sopenharmony_ci%void = OpTypeVoid
2574fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
2575fd4e5da5Sopenharmony_ci%_ptr_workgroup_int = OpTypePointer Workgroup %int
2576fd4e5da5Sopenharmony_ci%_ptr_function_ptr = OpTypePointer Function %_ptr_workgroup_int
2577fd4e5da5Sopenharmony_ci%voidfn = OpTypeFunction %void
2578fd4e5da5Sopenharmony_ci%func = OpFunction %void None %voidfn
2579fd4e5da5Sopenharmony_ci%entry = OpLabel
2580fd4e5da5Sopenharmony_ci%var = OpVariable %_ptr_function_ptr Function
2581fd4e5da5Sopenharmony_ciOpReturn
2582fd4e5da5Sopenharmony_ciOpFunctionEnd
2583fd4e5da5Sopenharmony_ci)";
2584fd4e5da5Sopenharmony_ci
2585fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
2586fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2587fd4e5da5Sopenharmony_ci}
2588fd4e5da5Sopenharmony_ci
2589fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpVariablePointerVariablePointersGood) {
2590fd4e5da5Sopenharmony_ci  const std::string spirv = R"(
2591fd4e5da5Sopenharmony_ciOpCapability Shader
2592fd4e5da5Sopenharmony_ciOpCapability Linkage
2593fd4e5da5Sopenharmony_ciOpCapability VariablePointers
2594fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_variable_pointers"
2595fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
2596fd4e5da5Sopenharmony_ci%void = OpTypeVoid
2597fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
2598fd4e5da5Sopenharmony_ci%_ptr_workgroup_int = OpTypePointer Workgroup %int
2599fd4e5da5Sopenharmony_ci%_ptr_function_ptr = OpTypePointer Function %_ptr_workgroup_int
2600fd4e5da5Sopenharmony_ci%voidfn = OpTypeFunction %void
2601fd4e5da5Sopenharmony_ci%func = OpFunction %void None %voidfn
2602fd4e5da5Sopenharmony_ci%entry = OpLabel
2603fd4e5da5Sopenharmony_ci%var = OpVariable %_ptr_function_ptr Function
2604fd4e5da5Sopenharmony_ciOpReturn
2605fd4e5da5Sopenharmony_ciOpFunctionEnd
2606fd4e5da5Sopenharmony_ci)";
2607fd4e5da5Sopenharmony_ci
2608fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
2609fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2610fd4e5da5Sopenharmony_ci}
2611fd4e5da5Sopenharmony_ci
2612fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpVariablePointerVariablePointersBad) {
2613fd4e5da5Sopenharmony_ci  const std::string spirv = R"(
2614fd4e5da5Sopenharmony_ciOpCapability Shader
2615fd4e5da5Sopenharmony_ciOpCapability VariablePointers
2616fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_variable_pointers"
2617fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
2618fd4e5da5Sopenharmony_ci%void = OpTypeVoid
2619fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
2620fd4e5da5Sopenharmony_ci%_ptr_workgroup_int = OpTypePointer Workgroup %int
2621fd4e5da5Sopenharmony_ci%_ptr_uniform_ptr = OpTypePointer Uniform %_ptr_workgroup_int
2622fd4e5da5Sopenharmony_ci%var = OpVariable %_ptr_uniform_ptr Uniform
2623fd4e5da5Sopenharmony_ci)";
2624fd4e5da5Sopenharmony_ci
2625fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
2626fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2627fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
2628fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
2629fd4e5da5Sopenharmony_ci                  "In Logical addressing with variable pointers, "
2630fd4e5da5Sopenharmony_ci                  "variables that allocate pointers must be in Function "
2631fd4e5da5Sopenharmony_ci                  "or Private storage classes")));
2632fd4e5da5Sopenharmony_ci}
2633fd4e5da5Sopenharmony_ci
2634fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpLoadGood) {
2635fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
2636fd4e5da5Sopenharmony_ci %1 = OpTypeVoid
2637fd4e5da5Sopenharmony_ci %2 = OpTypeInt 32 0
2638fd4e5da5Sopenharmony_ci %3 = OpTypePointer UniformConstant %2
2639fd4e5da5Sopenharmony_ci %4 = OpTypeFunction %1
2640fd4e5da5Sopenharmony_ci %5 = OpVariable %3 UniformConstant
2641fd4e5da5Sopenharmony_ci %6 = OpFunction %1 None %4
2642fd4e5da5Sopenharmony_ci %7 = OpLabel
2643fd4e5da5Sopenharmony_ci %8 = OpLoad %2 %5
2644fd4e5da5Sopenharmony_ci      OpReturn
2645fd4e5da5Sopenharmony_ci      OpFunctionEnd
2646fd4e5da5Sopenharmony_ci)";
2647fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
2648fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2649fd4e5da5Sopenharmony_ci}
2650fd4e5da5Sopenharmony_ci
2651fd4e5da5Sopenharmony_ci// TODO: Add tests that exercise VariablePointersStorageBuffer instead of
2652fd4e5da5Sopenharmony_ci// VariablePointers.
2653fd4e5da5Sopenharmony_civoid createVariablePointerSpirvProgram(std::ostringstream* spirv,
2654fd4e5da5Sopenharmony_ci                                       std::string result_strategy,
2655fd4e5da5Sopenharmony_ci                                       bool use_varptr_cap,
2656fd4e5da5Sopenharmony_ci                                       bool add_helper_function) {
2657fd4e5da5Sopenharmony_ci  *spirv << "OpCapability Shader ";
2658fd4e5da5Sopenharmony_ci  if (use_varptr_cap) {
2659fd4e5da5Sopenharmony_ci    *spirv << "OpCapability VariablePointers ";
2660fd4e5da5Sopenharmony_ci    *spirv << "OpExtension \"SPV_KHR_variable_pointers\" ";
2661fd4e5da5Sopenharmony_ci  }
2662fd4e5da5Sopenharmony_ci  *spirv << "OpExtension \"SPV_KHR_storage_buffer_storage_class\" ";
2663fd4e5da5Sopenharmony_ci  *spirv << R"(
2664fd4e5da5Sopenharmony_ci    OpMemoryModel Logical GLSL450
2665fd4e5da5Sopenharmony_ci    OpEntryPoint GLCompute %main "main"
2666fd4e5da5Sopenharmony_ci    %void      = OpTypeVoid
2667fd4e5da5Sopenharmony_ci    %voidf     = OpTypeFunction %void
2668fd4e5da5Sopenharmony_ci    %bool      = OpTypeBool
2669fd4e5da5Sopenharmony_ci    %i32       = OpTypeInt 32 1
2670fd4e5da5Sopenharmony_ci    %f32       = OpTypeFloat 32
2671fd4e5da5Sopenharmony_ci    %f32ptr    = OpTypePointer StorageBuffer %f32
2672fd4e5da5Sopenharmony_ci    %i         = OpConstant %i32 1
2673fd4e5da5Sopenharmony_ci    %zero      = OpConstant %i32 0
2674fd4e5da5Sopenharmony_ci    %float_1   = OpConstant %f32 1.0
2675fd4e5da5Sopenharmony_ci    %ptr1      = OpVariable %f32ptr StorageBuffer
2676fd4e5da5Sopenharmony_ci    %ptr2      = OpVariable %f32ptr StorageBuffer
2677fd4e5da5Sopenharmony_ci  )";
2678fd4e5da5Sopenharmony_ci  if (add_helper_function) {
2679fd4e5da5Sopenharmony_ci    *spirv << R"(
2680fd4e5da5Sopenharmony_ci      ; ////////////////////////////////////////////////////////////
2681fd4e5da5Sopenharmony_ci      ;;;; Function that returns a pointer
2682fd4e5da5Sopenharmony_ci      ; ////////////////////////////////////////////////////////////
2683fd4e5da5Sopenharmony_ci      %selector_func_type  = OpTypeFunction %f32ptr %bool %f32ptr %f32ptr
2684fd4e5da5Sopenharmony_ci      %choose_input_func   = OpFunction %f32ptr None %selector_func_type
2685fd4e5da5Sopenharmony_ci      %is_neg_param        = OpFunctionParameter %bool
2686fd4e5da5Sopenharmony_ci      %first_ptr_param     = OpFunctionParameter %f32ptr
2687fd4e5da5Sopenharmony_ci      %second_ptr_param    = OpFunctionParameter %f32ptr
2688fd4e5da5Sopenharmony_ci      %selector_func_begin = OpLabel
2689fd4e5da5Sopenharmony_ci      %result_ptr          = OpSelect %f32ptr %is_neg_param %first_ptr_param %second_ptr_param
2690fd4e5da5Sopenharmony_ci      OpReturnValue %result_ptr
2691fd4e5da5Sopenharmony_ci      OpFunctionEnd
2692fd4e5da5Sopenharmony_ci    )";
2693fd4e5da5Sopenharmony_ci  }
2694fd4e5da5Sopenharmony_ci  *spirv << R"(
2695fd4e5da5Sopenharmony_ci    %main      = OpFunction %void None %voidf
2696fd4e5da5Sopenharmony_ci    %label     = OpLabel
2697fd4e5da5Sopenharmony_ci  )";
2698fd4e5da5Sopenharmony_ci  *spirv << result_strategy;
2699fd4e5da5Sopenharmony_ci  *spirv << R"(
2700fd4e5da5Sopenharmony_ci    OpReturn
2701fd4e5da5Sopenharmony_ci    OpFunctionEnd
2702fd4e5da5Sopenharmony_ci  )";
2703fd4e5da5Sopenharmony_ci}
2704fd4e5da5Sopenharmony_ci
2705fd4e5da5Sopenharmony_ci// With the VariablePointer Capability, OpLoad should allow loading a
2706fd4e5da5Sopenharmony_ci// VaiablePointer. In this test the variable pointer is obtained by an OpSelect
2707fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpLoadVarPtrOpSelectGood) {
2708fd4e5da5Sopenharmony_ci  std::string result_strategy = R"(
2709fd4e5da5Sopenharmony_ci    %isneg     = OpSLessThan %bool %i %zero
2710fd4e5da5Sopenharmony_ci    %varptr    = OpSelect %f32ptr %isneg %ptr1 %ptr2
2711fd4e5da5Sopenharmony_ci    %result    = OpLoad %f32 %varptr
2712fd4e5da5Sopenharmony_ci  )";
2713fd4e5da5Sopenharmony_ci
2714fd4e5da5Sopenharmony_ci  std::ostringstream spirv;
2715fd4e5da5Sopenharmony_ci  createVariablePointerSpirvProgram(&spirv, result_strategy,
2716fd4e5da5Sopenharmony_ci                                    true /* Add VariablePointers Capability? */,
2717fd4e5da5Sopenharmony_ci                                    false /* Use Helper Function? */);
2718fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.str());
2719fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2720fd4e5da5Sopenharmony_ci}
2721fd4e5da5Sopenharmony_ci
2722fd4e5da5Sopenharmony_ci// Without the VariablePointers Capability, OpLoad will not allow loading
2723fd4e5da5Sopenharmony_ci// through a variable pointer.
2724fd4e5da5Sopenharmony_ci// Disabled since using OpSelect with pointers without VariablePointers will
2725fd4e5da5Sopenharmony_ci// fail LogicalsPass.
2726fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, DISABLED_OpLoadVarPtrOpSelectBad) {
2727fd4e5da5Sopenharmony_ci  std::string result_strategy = R"(
2728fd4e5da5Sopenharmony_ci    %isneg     = OpSLessThan %bool %i %zero
2729fd4e5da5Sopenharmony_ci    %varptr    = OpSelect %f32ptr %isneg %ptr1 %ptr2
2730fd4e5da5Sopenharmony_ci    %result    = OpLoad %f32 %varptr
2731fd4e5da5Sopenharmony_ci  )";
2732fd4e5da5Sopenharmony_ci
2733fd4e5da5Sopenharmony_ci  std::ostringstream spirv;
2734fd4e5da5Sopenharmony_ci  createVariablePointerSpirvProgram(&spirv, result_strategy,
2735fd4e5da5Sopenharmony_ci                                    false /* Add VariablePointers Capability?*/,
2736fd4e5da5Sopenharmony_ci                                    false /* Use Helper Function? */);
2737fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.str());
2738fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2739fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
2740fd4e5da5Sopenharmony_ci              HasSubstr(make_message("is not a logical pointer.")));
2741fd4e5da5Sopenharmony_ci}
2742fd4e5da5Sopenharmony_ci
2743fd4e5da5Sopenharmony_ci// With the VariablePointer Capability, OpLoad should allow loading a
2744fd4e5da5Sopenharmony_ci// VaiablePointer. In this test the variable pointer is obtained by an OpPhi
2745fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpLoadVarPtrOpPhiGood) {
2746fd4e5da5Sopenharmony_ci  std::string result_strategy = R"(
2747fd4e5da5Sopenharmony_ci    %is_neg      = OpSLessThan %bool %i %zero
2748fd4e5da5Sopenharmony_ci    OpSelectionMerge %end_label None
2749fd4e5da5Sopenharmony_ci    OpBranchConditional %is_neg %take_ptr_1 %take_ptr_2
2750fd4e5da5Sopenharmony_ci    %take_ptr_1 = OpLabel
2751fd4e5da5Sopenharmony_ci    OpBranch      %end_label
2752fd4e5da5Sopenharmony_ci    %take_ptr_2 = OpLabel
2753fd4e5da5Sopenharmony_ci    OpBranch      %end_label
2754fd4e5da5Sopenharmony_ci    %end_label  = OpLabel
2755fd4e5da5Sopenharmony_ci    %varptr     = OpPhi %f32ptr %ptr1 %take_ptr_1 %ptr2 %take_ptr_2
2756fd4e5da5Sopenharmony_ci    %result     = OpLoad %f32 %varptr
2757fd4e5da5Sopenharmony_ci  )";
2758fd4e5da5Sopenharmony_ci
2759fd4e5da5Sopenharmony_ci  std::ostringstream spirv;
2760fd4e5da5Sopenharmony_ci  createVariablePointerSpirvProgram(&spirv, result_strategy,
2761fd4e5da5Sopenharmony_ci                                    true /* Add VariablePointers Capability?*/,
2762fd4e5da5Sopenharmony_ci                                    false /* Use Helper Function? */);
2763fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.str());
2764fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2765fd4e5da5Sopenharmony_ci}
2766fd4e5da5Sopenharmony_ci
2767fd4e5da5Sopenharmony_ci// Without the VariablePointers Capability, OpPhi can have a pointer result
2768fd4e5da5Sopenharmony_ci// type.
2769fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpPhiBad) {
2770fd4e5da5Sopenharmony_ci  std::string result_strategy = R"(
2771fd4e5da5Sopenharmony_ci    %is_neg      = OpSLessThan %bool %i %zero
2772fd4e5da5Sopenharmony_ci    OpSelectionMerge %end_label None
2773fd4e5da5Sopenharmony_ci    OpBranchConditional %is_neg %take_ptr_1 %take_ptr_2
2774fd4e5da5Sopenharmony_ci    %take_ptr_1 = OpLabel
2775fd4e5da5Sopenharmony_ci    OpBranch      %end_label
2776fd4e5da5Sopenharmony_ci    %take_ptr_2 = OpLabel
2777fd4e5da5Sopenharmony_ci    OpBranch      %end_label
2778fd4e5da5Sopenharmony_ci    %end_label  = OpLabel
2779fd4e5da5Sopenharmony_ci    %varptr     = OpPhi %f32ptr %ptr1 %take_ptr_1 %ptr2 %take_ptr_2
2780fd4e5da5Sopenharmony_ci    %result     = OpLoad %f32 %varptr
2781fd4e5da5Sopenharmony_ci  )";
2782fd4e5da5Sopenharmony_ci
2783fd4e5da5Sopenharmony_ci  std::ostringstream spirv;
2784fd4e5da5Sopenharmony_ci  createVariablePointerSpirvProgram(&spirv, result_strategy,
2785fd4e5da5Sopenharmony_ci                                    false /* Add VariablePointers Capability?*/,
2786fd4e5da5Sopenharmony_ci                                    false /* Use Helper Function? */);
2787fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.str());
2788fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_DATA, ValidateInstructions());
2789fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
2790fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
2791fd4e5da5Sopenharmony_ci                  "Using pointers with OpPhi requires capability "
2792fd4e5da5Sopenharmony_ci                  "VariablePointers or VariablePointersStorageBuffer")));
2793fd4e5da5Sopenharmony_ci}
2794fd4e5da5Sopenharmony_ci
2795fd4e5da5Sopenharmony_ci// With the VariablePointer Capability, OpLoad should allow loading through a
2796fd4e5da5Sopenharmony_ci// VaiablePointer. In this test the variable pointer is obtained from an
2797fd4e5da5Sopenharmony_ci// OpFunctionCall (return value from a function)
2798fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpLoadVarPtrOpFunctionCallGood) {
2799fd4e5da5Sopenharmony_ci  std::ostringstream spirv;
2800fd4e5da5Sopenharmony_ci  std::string result_strategy = R"(
2801fd4e5da5Sopenharmony_ci    %isneg     = OpSLessThan %bool %i %zero
2802fd4e5da5Sopenharmony_ci    %varptr    = OpFunctionCall %f32ptr %choose_input_func %isneg %ptr1 %ptr2
2803fd4e5da5Sopenharmony_ci    %result    = OpLoad %f32 %varptr
2804fd4e5da5Sopenharmony_ci  )";
2805fd4e5da5Sopenharmony_ci
2806fd4e5da5Sopenharmony_ci  createVariablePointerSpirvProgram(&spirv, result_strategy,
2807fd4e5da5Sopenharmony_ci                                    true /* Add VariablePointers Capability?*/,
2808fd4e5da5Sopenharmony_ci                                    true /* Use Helper Function? */);
2809fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.str());
2810fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2811fd4e5da5Sopenharmony_ci}
2812fd4e5da5Sopenharmony_ci
2813fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpLoadResultTypeBad) {
2814fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
2815fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
2816fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
2817fd4e5da5Sopenharmony_ci%3 = OpTypePointer UniformConstant %2
2818fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %1
2819fd4e5da5Sopenharmony_ci%5 = OpVariable %3 UniformConstant
2820fd4e5da5Sopenharmony_ci%6 = OpFunction %1 None %4
2821fd4e5da5Sopenharmony_ci%7 = OpLabel
2822fd4e5da5Sopenharmony_ci%8 = OpLoad %3 %5
2823fd4e5da5Sopenharmony_ci     OpReturn
2824fd4e5da5Sopenharmony_ci     OpFunctionEnd
2825fd4e5da5Sopenharmony_ci)";
2826fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
2827fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2828fd4e5da5Sopenharmony_ci  EXPECT_THAT(
2829fd4e5da5Sopenharmony_ci      getDiagnosticString(),
2830fd4e5da5Sopenharmony_ci      HasSubstr(make_message("OpLoad Result Type <id> "
2831fd4e5da5Sopenharmony_ci                             "'3[%_ptr_UniformConstant_uint]' does not match "
2832fd4e5da5Sopenharmony_ci                             "Pointer <id> '5[%5]'s type.")));
2833fd4e5da5Sopenharmony_ci}
2834fd4e5da5Sopenharmony_ci
2835fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpLoadPointerBad) {
2836fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
2837fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
2838fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
2839fd4e5da5Sopenharmony_ci%3 = OpTypePointer UniformConstant %2
2840fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %1
2841fd4e5da5Sopenharmony_ci%5 = OpFunction %1 None %4
2842fd4e5da5Sopenharmony_ci%6 = OpLabel
2843fd4e5da5Sopenharmony_ci%7 = OpLoad %2 %8
2844fd4e5da5Sopenharmony_ci     OpReturn
2845fd4e5da5Sopenharmony_ci     OpFunctionEnd
2846fd4e5da5Sopenharmony_ci)";
2847fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
2848fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2849fd4e5da5Sopenharmony_ci  // Prove that SSA checks trigger for a bad Id value.
2850fd4e5da5Sopenharmony_ci  // The next test case show the not-a-logical-pointer case.
2851fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
2852fd4e5da5Sopenharmony_ci              HasSubstr(make_message("ID '8[%8]' has not been "
2853fd4e5da5Sopenharmony_ci                                     "defined")));
2854fd4e5da5Sopenharmony_ci}
2855fd4e5da5Sopenharmony_ci
2856fd4e5da5Sopenharmony_ci// Disabled as bitcasting type to object is now not valid.
2857fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, DISABLED_OpLoadLogicalPointerBad) {
2858fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
2859fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
2860fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
2861fd4e5da5Sopenharmony_ci%3 = OpTypeFloat 32
2862fd4e5da5Sopenharmony_ci%4 = OpTypePointer UniformConstant %2
2863fd4e5da5Sopenharmony_ci%5 = OpTypePointer UniformConstant %3
2864fd4e5da5Sopenharmony_ci%6 = OpTypeFunction %1
2865fd4e5da5Sopenharmony_ci%7 = OpFunction %1 None %6
2866fd4e5da5Sopenharmony_ci%8 = OpLabel
2867fd4e5da5Sopenharmony_ci%9 = OpBitcast %5 %4 ; Not valid in logical addressing
2868fd4e5da5Sopenharmony_ci%10 = OpLoad %3 %9 ; Should trigger message
2869fd4e5da5Sopenharmony_ci     OpReturn
2870fd4e5da5Sopenharmony_ci     OpFunctionEnd
2871fd4e5da5Sopenharmony_ci)";
2872fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
2873fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2874fd4e5da5Sopenharmony_ci  // Once we start checking bitcasts, we might catch that
2875fd4e5da5Sopenharmony_ci  // as the error first, instead of catching it here.
2876fd4e5da5Sopenharmony_ci  // I don't know if it's possible to generate a bad case
2877fd4e5da5Sopenharmony_ci  // if/when the validator is complete.
2878fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
2879fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
2880fd4e5da5Sopenharmony_ci                  "OpLoad Pointer <id> '9' is not a logical pointer.")));
2881fd4e5da5Sopenharmony_ci}
2882fd4e5da5Sopenharmony_ci
2883fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpStoreGood) {
2884fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
2885fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
2886fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
2887fd4e5da5Sopenharmony_ci%3 = OpTypePointer Uniform %2
2888fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %1
2889fd4e5da5Sopenharmony_ci%5 = OpConstant %2 42
2890fd4e5da5Sopenharmony_ci%6 = OpVariable %3 Uniform
2891fd4e5da5Sopenharmony_ci%7 = OpFunction %1 None %4
2892fd4e5da5Sopenharmony_ci%8 = OpLabel
2893fd4e5da5Sopenharmony_ci     OpStore %6 %5
2894fd4e5da5Sopenharmony_ci     OpReturn
2895fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
2896fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
2897fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2898fd4e5da5Sopenharmony_ci}
2899fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpStorePointerBad) {
2900fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
2901fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
2902fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
2903fd4e5da5Sopenharmony_ci%3 = OpTypePointer UniformConstant %2
2904fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %1
2905fd4e5da5Sopenharmony_ci%5 = OpConstant %2 42
2906fd4e5da5Sopenharmony_ci%6 = OpVariable %3 UniformConstant
2907fd4e5da5Sopenharmony_ci%7 = OpConstant %2 0
2908fd4e5da5Sopenharmony_ci%8 = OpFunction %1 None %4
2909fd4e5da5Sopenharmony_ci%9 = OpLabel
2910fd4e5da5Sopenharmony_ci     OpStore %7 %5
2911fd4e5da5Sopenharmony_ci     OpReturn
2912fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
2913fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
2914fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2915fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
2916fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
2917fd4e5da5Sopenharmony_ci                  "OpStore Pointer <id> '7[%uint_0]' is not a logical "
2918fd4e5da5Sopenharmony_ci                  "pointer.")));
2919fd4e5da5Sopenharmony_ci}
2920fd4e5da5Sopenharmony_ci
2921fd4e5da5Sopenharmony_ci// Disabled as bitcasting type to object is now not valid.
2922fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, DISABLED_OpStoreLogicalPointerBad) {
2923fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
2924fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
2925fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
2926fd4e5da5Sopenharmony_ci%3 = OpTypeFloat 32
2927fd4e5da5Sopenharmony_ci%4 = OpTypePointer UniformConstant %2
2928fd4e5da5Sopenharmony_ci%5 = OpTypePointer UniformConstant %3
2929fd4e5da5Sopenharmony_ci%6 = OpTypeFunction %1
2930fd4e5da5Sopenharmony_ci%7 = OpConstantNull %5
2931fd4e5da5Sopenharmony_ci%8 = OpFunction %1 None %6
2932fd4e5da5Sopenharmony_ci%9 = OpLabel
2933fd4e5da5Sopenharmony_ci%10 = OpBitcast %5 %4 ; Not valid in logical addressing
2934fd4e5da5Sopenharmony_ci%11 = OpStore %10 %7 ; Should trigger message
2935fd4e5da5Sopenharmony_ci     OpReturn
2936fd4e5da5Sopenharmony_ci     OpFunctionEnd
2937fd4e5da5Sopenharmony_ci)";
2938fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
2939fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2940fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
2941fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
2942fd4e5da5Sopenharmony_ci                  "OpStore Pointer <id> '10' is not a logical pointer.")));
2943fd4e5da5Sopenharmony_ci}
2944fd4e5da5Sopenharmony_ci
2945fd4e5da5Sopenharmony_ci// Without the VariablePointer Capability, OpStore should may not store
2946fd4e5da5Sopenharmony_ci// through a variable pointer.
2947fd4e5da5Sopenharmony_ci// Disabled since using OpSelect with pointers without VariablePointers will
2948fd4e5da5Sopenharmony_ci// fail LogicalsPass.
2949fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, DISABLED_OpStoreVarPtrBad) {
2950fd4e5da5Sopenharmony_ci  std::string result_strategy = R"(
2951fd4e5da5Sopenharmony_ci    %isneg     = OpSLessThan %bool %i %zero
2952fd4e5da5Sopenharmony_ci    %varptr    = OpSelect %f32ptr %isneg %ptr1 %ptr2
2953fd4e5da5Sopenharmony_ci                 OpStore %varptr %float_1
2954fd4e5da5Sopenharmony_ci  )";
2955fd4e5da5Sopenharmony_ci
2956fd4e5da5Sopenharmony_ci  std::ostringstream spirv;
2957fd4e5da5Sopenharmony_ci  createVariablePointerSpirvProgram(
2958fd4e5da5Sopenharmony_ci      &spirv, result_strategy, false /* Add VariablePointers Capability? */,
2959fd4e5da5Sopenharmony_ci      false /* Use Helper Function? */);
2960fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.str());
2961fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
2962fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
2963fd4e5da5Sopenharmony_ci              HasSubstr(make_message("is not a logical pointer.")));
2964fd4e5da5Sopenharmony_ci}
2965fd4e5da5Sopenharmony_ci
2966fd4e5da5Sopenharmony_ci// With the VariablePointer Capability, OpStore should allow storing through a
2967fd4e5da5Sopenharmony_ci// variable pointer.
2968fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpStoreVarPtrGood) {
2969fd4e5da5Sopenharmony_ci  std::string result_strategy = R"(
2970fd4e5da5Sopenharmony_ci    %isneg     = OpSLessThan %bool %i %zero
2971fd4e5da5Sopenharmony_ci    %varptr    = OpSelect %f32ptr %isneg %ptr1 %ptr2
2972fd4e5da5Sopenharmony_ci                 OpStore %varptr %float_1
2973fd4e5da5Sopenharmony_ci  )";
2974fd4e5da5Sopenharmony_ci
2975fd4e5da5Sopenharmony_ci  std::ostringstream spirv;
2976fd4e5da5Sopenharmony_ci  createVariablePointerSpirvProgram(&spirv, result_strategy,
2977fd4e5da5Sopenharmony_ci                                    true /* Add VariablePointers Capability? */,
2978fd4e5da5Sopenharmony_ci                                    false /* Use Helper Function? */);
2979fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.str());
2980fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
2981fd4e5da5Sopenharmony_ci}
2982fd4e5da5Sopenharmony_ci
2983fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpStoreObjectGood) {
2984fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
2985fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
2986fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
2987fd4e5da5Sopenharmony_ci%3 = OpTypePointer Uniform %2
2988fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %1
2989fd4e5da5Sopenharmony_ci%5 = OpConstant %2 42
2990fd4e5da5Sopenharmony_ci%6 = OpVariable %3 Uniform
2991fd4e5da5Sopenharmony_ci%7 = OpFunction %1 None %4
2992fd4e5da5Sopenharmony_ci%8 = OpLabel
2993fd4e5da5Sopenharmony_ci%9 = OpFunctionCall %1 %10
2994fd4e5da5Sopenharmony_ci     OpStore %6 %9
2995fd4e5da5Sopenharmony_ci     OpReturn
2996fd4e5da5Sopenharmony_ci     OpFunctionEnd
2997fd4e5da5Sopenharmony_ci%10 = OpFunction %1 None %4
2998fd4e5da5Sopenharmony_ci%11 = OpLabel
2999fd4e5da5Sopenharmony_ci      OpReturn
3000fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
3001fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
3002fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3003fd4e5da5Sopenharmony_ci  EXPECT_THAT(
3004fd4e5da5Sopenharmony_ci      getDiagnosticString(),
3005fd4e5da5Sopenharmony_ci      HasSubstr(make_message("OpStore Object <id> '9[%9]'s type is void.")));
3006fd4e5da5Sopenharmony_ci}
3007fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpStoreTypeBad) {
3008fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
3009fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
3010fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
3011fd4e5da5Sopenharmony_ci%9 = OpTypeFloat 32
3012fd4e5da5Sopenharmony_ci%3 = OpTypePointer Uniform %2
3013fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %1
3014fd4e5da5Sopenharmony_ci%5 = OpConstant %9 3.14
3015fd4e5da5Sopenharmony_ci%6 = OpVariable %3 Uniform
3016fd4e5da5Sopenharmony_ci%7 = OpFunction %1 None %4
3017fd4e5da5Sopenharmony_ci%8 = OpLabel
3018fd4e5da5Sopenharmony_ci     OpStore %6 %5
3019fd4e5da5Sopenharmony_ci     OpReturn
3020fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
3021fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
3022fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3023fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
3024fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
3025fd4e5da5Sopenharmony_ci                  "OpStore Pointer <id> '7[%7]'s type does not match "
3026fd4e5da5Sopenharmony_ci                  "Object <id> '6[%float_3_1400001]'s type.")));
3027fd4e5da5Sopenharmony_ci}
3028fd4e5da5Sopenharmony_ci
3029fd4e5da5Sopenharmony_ci// The next series of test check test a relaxation of the rules for stores to
3030fd4e5da5Sopenharmony_ci// structs.  The first test checks that we get a failure when the option is not
3031fd4e5da5Sopenharmony_ci// set to relax the rule.
3032fd4e5da5Sopenharmony_ci// TODO: Add tests for layout compatible arrays and matricies when the validator
3033fd4e5da5Sopenharmony_ci//       relaxes the rules for them as well.  Also need test to check for layout
3034fd4e5da5Sopenharmony_ci//       decorations specific to those types.
3035fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpStoreTypeBadStruct) {
3036fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
3037fd4e5da5Sopenharmony_ci     OpMemberDecorate %1 0 Offset 0
3038fd4e5da5Sopenharmony_ci     OpMemberDecorate %1 1 Offset 4
3039fd4e5da5Sopenharmony_ci     OpMemberDecorate %2 0 Offset 0
3040fd4e5da5Sopenharmony_ci     OpMemberDecorate %2 1 Offset 4
3041fd4e5da5Sopenharmony_ci%3 = OpTypeVoid
3042fd4e5da5Sopenharmony_ci%4 = OpTypeFloat 32
3043fd4e5da5Sopenharmony_ci%1 = OpTypeStruct %4 %4
3044fd4e5da5Sopenharmony_ci%5 = OpTypePointer Uniform %1
3045fd4e5da5Sopenharmony_ci%2 = OpTypeStruct %4 %4
3046fd4e5da5Sopenharmony_ci%6 = OpTypeFunction %3
3047fd4e5da5Sopenharmony_ci%7 = OpConstant %4 3.14
3048fd4e5da5Sopenharmony_ci%8 = OpVariable %5 Uniform
3049fd4e5da5Sopenharmony_ci%9 = OpFunction %3 None %6
3050fd4e5da5Sopenharmony_ci%10 = OpLabel
3051fd4e5da5Sopenharmony_ci%11 = OpCompositeConstruct %2 %7 %7
3052fd4e5da5Sopenharmony_ci      OpStore %8 %11
3053fd4e5da5Sopenharmony_ci      OpReturn
3054fd4e5da5Sopenharmony_ci      OpFunctionEnd)";
3055fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
3056fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3057fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
3058fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
3059fd4e5da5Sopenharmony_ci                  "OpStore Pointer <id> '8[%8]'s type does not match "
3060fd4e5da5Sopenharmony_ci                  "Object <id> '11[%11]'s type.")));
3061fd4e5da5Sopenharmony_ci}
3062fd4e5da5Sopenharmony_ci
3063fd4e5da5Sopenharmony_ci// Same code as the last test.  The difference is that we relax the rule.
3064fd4e5da5Sopenharmony_ci// Because the structs %3 and %5 are defined the same way.
3065fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpStoreTypeRelaxedStruct) {
3066fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
3067fd4e5da5Sopenharmony_ci     OpMemberDecorate %1 0 Offset 0
3068fd4e5da5Sopenharmony_ci     OpMemberDecorate %1 1 Offset 4
3069fd4e5da5Sopenharmony_ci     OpMemberDecorate %2 0 Offset 0
3070fd4e5da5Sopenharmony_ci     OpMemberDecorate %2 1 Offset 4
3071fd4e5da5Sopenharmony_ci%3 = OpTypeVoid
3072fd4e5da5Sopenharmony_ci%4 = OpTypeFloat 32
3073fd4e5da5Sopenharmony_ci%1 = OpTypeStruct %4 %4
3074fd4e5da5Sopenharmony_ci%5 = OpTypePointer Uniform %1
3075fd4e5da5Sopenharmony_ci%2 = OpTypeStruct %4 %4
3076fd4e5da5Sopenharmony_ci%6 = OpTypeFunction %3
3077fd4e5da5Sopenharmony_ci%7 = OpConstant %4 3.14
3078fd4e5da5Sopenharmony_ci%8 = OpVariable %5 Uniform
3079fd4e5da5Sopenharmony_ci%9 = OpFunction %3 None %6
3080fd4e5da5Sopenharmony_ci%10 = OpLabel
3081fd4e5da5Sopenharmony_ci%11 = OpCompositeConstruct %2 %7 %7
3082fd4e5da5Sopenharmony_ci      OpStore %8 %11
3083fd4e5da5Sopenharmony_ci      OpReturn
3084fd4e5da5Sopenharmony_ci      OpFunctionEnd)";
3085fd4e5da5Sopenharmony_ci  spvValidatorOptionsSetRelaxStoreStruct(options_, true);
3086fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
3087fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
3088fd4e5da5Sopenharmony_ci}
3089fd4e5da5Sopenharmony_ci
3090fd4e5da5Sopenharmony_ci// Same code as the last test except for an extra decoration on one of the
3091fd4e5da5Sopenharmony_ci// members. With the relaxed rules, the code is still valid.
3092fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpStoreTypeRelaxedStructWithExtraDecoration) {
3093fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
3094fd4e5da5Sopenharmony_ci     OpMemberDecorate %1 0 Offset 0
3095fd4e5da5Sopenharmony_ci     OpMemberDecorate %1 1 Offset 4
3096fd4e5da5Sopenharmony_ci     OpMemberDecorate %1 0 RelaxedPrecision
3097fd4e5da5Sopenharmony_ci     OpMemberDecorate %2 0 Offset 0
3098fd4e5da5Sopenharmony_ci     OpMemberDecorate %2 1 Offset 4
3099fd4e5da5Sopenharmony_ci%3 = OpTypeVoid
3100fd4e5da5Sopenharmony_ci%4 = OpTypeFloat 32
3101fd4e5da5Sopenharmony_ci%1 = OpTypeStruct %4 %4
3102fd4e5da5Sopenharmony_ci%5 = OpTypePointer Uniform %1
3103fd4e5da5Sopenharmony_ci%2 = OpTypeStruct %4 %4
3104fd4e5da5Sopenharmony_ci%6 = OpTypeFunction %3
3105fd4e5da5Sopenharmony_ci%7 = OpConstant %4 3.14
3106fd4e5da5Sopenharmony_ci%8 = OpVariable %5 Uniform
3107fd4e5da5Sopenharmony_ci%9 = OpFunction %3 None %6
3108fd4e5da5Sopenharmony_ci%10 = OpLabel
3109fd4e5da5Sopenharmony_ci%11 = OpCompositeConstruct %2 %7 %7
3110fd4e5da5Sopenharmony_ci      OpStore %8 %11
3111fd4e5da5Sopenharmony_ci      OpReturn
3112fd4e5da5Sopenharmony_ci      OpFunctionEnd)";
3113fd4e5da5Sopenharmony_ci  spvValidatorOptionsSetRelaxStoreStruct(options_, true);
3114fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
3115fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
3116fd4e5da5Sopenharmony_ci}
3117fd4e5da5Sopenharmony_ci
3118fd4e5da5Sopenharmony_ci// This test check that we recursively traverse the struct to check if they are
3119fd4e5da5Sopenharmony_ci// interchangable.
3120fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpStoreTypeRelaxedNestedStruct) {
3121fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
3122fd4e5da5Sopenharmony_ci     OpMemberDecorate %1 0 Offset 0
3123fd4e5da5Sopenharmony_ci     OpMemberDecorate %1 1 Offset 4
3124fd4e5da5Sopenharmony_ci     OpMemberDecorate %2 0 Offset 0
3125fd4e5da5Sopenharmony_ci     OpMemberDecorate %2 1 Offset 8
3126fd4e5da5Sopenharmony_ci     OpMemberDecorate %3 0 Offset 0
3127fd4e5da5Sopenharmony_ci     OpMemberDecorate %3 1 Offset 4
3128fd4e5da5Sopenharmony_ci     OpMemberDecorate %4 0 Offset 0
3129fd4e5da5Sopenharmony_ci     OpMemberDecorate %4 1 Offset 8
3130fd4e5da5Sopenharmony_ci%5 = OpTypeVoid
3131fd4e5da5Sopenharmony_ci%6 = OpTypeInt 32 0
3132fd4e5da5Sopenharmony_ci%7 = OpTypeFloat 32
3133fd4e5da5Sopenharmony_ci%1 = OpTypeStruct %7 %6
3134fd4e5da5Sopenharmony_ci%2 = OpTypeStruct %1 %1
3135fd4e5da5Sopenharmony_ci%8 = OpTypePointer Uniform %2
3136fd4e5da5Sopenharmony_ci%3 = OpTypeStruct %7 %6
3137fd4e5da5Sopenharmony_ci%4 = OpTypeStruct %3 %3
3138fd4e5da5Sopenharmony_ci%9 = OpTypeFunction %5
3139fd4e5da5Sopenharmony_ci%10 = OpConstant %6 7
3140fd4e5da5Sopenharmony_ci%11 = OpConstant %7 3.14
3141fd4e5da5Sopenharmony_ci%12 = OpConstantComposite %3 %11 %10
3142fd4e5da5Sopenharmony_ci%13 = OpVariable %8 Uniform
3143fd4e5da5Sopenharmony_ci%14 = OpFunction %5 None %9
3144fd4e5da5Sopenharmony_ci%15 = OpLabel
3145fd4e5da5Sopenharmony_ci%16 = OpCompositeConstruct %4 %12 %12
3146fd4e5da5Sopenharmony_ci      OpStore %13 %16
3147fd4e5da5Sopenharmony_ci      OpReturn
3148fd4e5da5Sopenharmony_ci      OpFunctionEnd)";
3149fd4e5da5Sopenharmony_ci  spvValidatorOptionsSetRelaxStoreStruct(options_, true);
3150fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
3151fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
3152fd4e5da5Sopenharmony_ci}
3153fd4e5da5Sopenharmony_ci
3154fd4e5da5Sopenharmony_ci// This test check that the even with the relaxed rules an error is identified
3155fd4e5da5Sopenharmony_ci// if the members of the struct are in a different order.
3156fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpStoreTypeBadRelaxedStruct1) {
3157fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
3158fd4e5da5Sopenharmony_ci     OpMemberDecorate %1 0 Offset 0
3159fd4e5da5Sopenharmony_ci     OpMemberDecorate %1 1 Offset 4
3160fd4e5da5Sopenharmony_ci     OpMemberDecorate %2 0 Offset 0
3161fd4e5da5Sopenharmony_ci     OpMemberDecorate %2 1 Offset 8
3162fd4e5da5Sopenharmony_ci     OpMemberDecorate %3 0 Offset 0
3163fd4e5da5Sopenharmony_ci     OpMemberDecorate %3 1 Offset 4
3164fd4e5da5Sopenharmony_ci     OpMemberDecorate %4 0 Offset 0
3165fd4e5da5Sopenharmony_ci     OpMemberDecorate %4 1 Offset 8
3166fd4e5da5Sopenharmony_ci%5 = OpTypeVoid
3167fd4e5da5Sopenharmony_ci%6 = OpTypeInt 32 0
3168fd4e5da5Sopenharmony_ci%7 = OpTypeFloat 32
3169fd4e5da5Sopenharmony_ci%1 = OpTypeStruct %6 %7
3170fd4e5da5Sopenharmony_ci%2 = OpTypeStruct %1 %1
3171fd4e5da5Sopenharmony_ci%8 = OpTypePointer Uniform %2
3172fd4e5da5Sopenharmony_ci%3 = OpTypeStruct %7 %6
3173fd4e5da5Sopenharmony_ci%4 = OpTypeStruct %3 %3
3174fd4e5da5Sopenharmony_ci%9 = OpTypeFunction %5
3175fd4e5da5Sopenharmony_ci%10 = OpConstant %6 7
3176fd4e5da5Sopenharmony_ci%11 = OpConstant %7 3.14
3177fd4e5da5Sopenharmony_ci%12 = OpConstantComposite %3 %11 %10
3178fd4e5da5Sopenharmony_ci%13 = OpVariable %8 Uniform
3179fd4e5da5Sopenharmony_ci%14 = OpFunction %5 None %9
3180fd4e5da5Sopenharmony_ci%15 = OpLabel
3181fd4e5da5Sopenharmony_ci%16 = OpCompositeConstruct %4 %12 %12
3182fd4e5da5Sopenharmony_ci      OpStore %13 %16
3183fd4e5da5Sopenharmony_ci      OpReturn
3184fd4e5da5Sopenharmony_ci      OpFunctionEnd)";
3185fd4e5da5Sopenharmony_ci  spvValidatorOptionsSetRelaxStoreStruct(options_, true);
3186fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
3187fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3188fd4e5da5Sopenharmony_ci  EXPECT_THAT(
3189fd4e5da5Sopenharmony_ci      getDiagnosticString(),
3190fd4e5da5Sopenharmony_ci      HasSubstr(make_message(
3191fd4e5da5Sopenharmony_ci          "OpStore Pointer <id> '13[%13]'s layout does not match Object "
3192fd4e5da5Sopenharmony_ci          "<id> '16[%16]'s layout.")));
3193fd4e5da5Sopenharmony_ci}
3194fd4e5da5Sopenharmony_ci
3195fd4e5da5Sopenharmony_ci// This test check that the even with the relaxed rules an error is identified
3196fd4e5da5Sopenharmony_ci// if the members of the struct are at different offsets.
3197fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpStoreTypeBadRelaxedStruct2) {
3198fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
3199fd4e5da5Sopenharmony_ci     OpMemberDecorate %1 0 Offset 4
3200fd4e5da5Sopenharmony_ci     OpMemberDecorate %1 1 Offset 0
3201fd4e5da5Sopenharmony_ci     OpMemberDecorate %2 0 Offset 0
3202fd4e5da5Sopenharmony_ci     OpMemberDecorate %2 1 Offset 8
3203fd4e5da5Sopenharmony_ci     OpMemberDecorate %3 0 Offset 0
3204fd4e5da5Sopenharmony_ci     OpMemberDecorate %3 1 Offset 4
3205fd4e5da5Sopenharmony_ci     OpMemberDecorate %4 0 Offset 0
3206fd4e5da5Sopenharmony_ci     OpMemberDecorate %4 1 Offset 8
3207fd4e5da5Sopenharmony_ci%5 = OpTypeVoid
3208fd4e5da5Sopenharmony_ci%6 = OpTypeInt 32 0
3209fd4e5da5Sopenharmony_ci%7 = OpTypeFloat 32
3210fd4e5da5Sopenharmony_ci%1 = OpTypeStruct %7 %6
3211fd4e5da5Sopenharmony_ci%2 = OpTypeStruct %1 %1
3212fd4e5da5Sopenharmony_ci%8 = OpTypePointer Uniform %2
3213fd4e5da5Sopenharmony_ci%3 = OpTypeStruct %7 %6
3214fd4e5da5Sopenharmony_ci%4 = OpTypeStruct %3 %3
3215fd4e5da5Sopenharmony_ci%9 = OpTypeFunction %5
3216fd4e5da5Sopenharmony_ci%10 = OpConstant %6 7
3217fd4e5da5Sopenharmony_ci%11 = OpConstant %7 3.14
3218fd4e5da5Sopenharmony_ci%12 = OpConstantComposite %3 %11 %10
3219fd4e5da5Sopenharmony_ci%13 = OpVariable %8 Uniform
3220fd4e5da5Sopenharmony_ci%14 = OpFunction %5 None %9
3221fd4e5da5Sopenharmony_ci%15 = OpLabel
3222fd4e5da5Sopenharmony_ci%16 = OpCompositeConstruct %4 %12 %12
3223fd4e5da5Sopenharmony_ci      OpStore %13 %16
3224fd4e5da5Sopenharmony_ci      OpReturn
3225fd4e5da5Sopenharmony_ci      OpFunctionEnd)";
3226fd4e5da5Sopenharmony_ci  spvValidatorOptionsSetRelaxStoreStruct(options_, true);
3227fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
3228fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3229fd4e5da5Sopenharmony_ci  EXPECT_THAT(
3230fd4e5da5Sopenharmony_ci      getDiagnosticString(),
3231fd4e5da5Sopenharmony_ci      HasSubstr(make_message(
3232fd4e5da5Sopenharmony_ci          "OpStore Pointer <id> '13[%13]'s layout does not match Object "
3233fd4e5da5Sopenharmony_ci          "<id> '16[%16]'s layout.")));
3234fd4e5da5Sopenharmony_ci}
3235fd4e5da5Sopenharmony_ci
3236fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpStoreTypeRelaxedLogicalPointerReturnPointer) {
3237fd4e5da5Sopenharmony_ci  const std::string spirv = R"(
3238fd4e5da5Sopenharmony_ci     OpCapability Shader
3239fd4e5da5Sopenharmony_ci     OpCapability Linkage
3240fd4e5da5Sopenharmony_ci     OpMemoryModel Logical GLSL450
3241fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 1
3242fd4e5da5Sopenharmony_ci%2 = OpTypePointer Function %1
3243fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %2 %2
3244fd4e5da5Sopenharmony_ci%4 = OpFunction %2 None %3
3245fd4e5da5Sopenharmony_ci%5 = OpFunctionParameter %2
3246fd4e5da5Sopenharmony_ci%6 = OpLabel
3247fd4e5da5Sopenharmony_ci     OpReturnValue %5
3248fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
3249fd4e5da5Sopenharmony_ci
3250fd4e5da5Sopenharmony_ci  spvValidatorOptionsSetRelaxLogicalPointer(options_, true);
3251fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
3252fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
3253fd4e5da5Sopenharmony_ci}
3254fd4e5da5Sopenharmony_ci
3255fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpStoreTypeRelaxedLogicalPointerAllocPointer) {
3256fd4e5da5Sopenharmony_ci  const std::string spirv = R"(
3257fd4e5da5Sopenharmony_ci      OpCapability Shader
3258fd4e5da5Sopenharmony_ci      OpCapability Linkage
3259fd4e5da5Sopenharmony_ci      OpMemoryModel Logical GLSL450
3260fd4e5da5Sopenharmony_ci %1 = OpTypeVoid
3261fd4e5da5Sopenharmony_ci %2 = OpTypeInt 32 1
3262fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %1          ; void(void)
3263fd4e5da5Sopenharmony_ci %4 = OpTypePointer Uniform %2   ; int*
3264fd4e5da5Sopenharmony_ci %5 = OpTypePointer Private %4   ; int** (Private)
3265fd4e5da5Sopenharmony_ci %6 = OpTypePointer Function %4  ; int** (Function)
3266fd4e5da5Sopenharmony_ci %7 = OpVariable %5 Private
3267fd4e5da5Sopenharmony_ci %8 = OpFunction %1 None %3
3268fd4e5da5Sopenharmony_ci %9 = OpLabel
3269fd4e5da5Sopenharmony_ci%10 = OpVariable %6 Function
3270fd4e5da5Sopenharmony_ci      OpReturn
3271fd4e5da5Sopenharmony_ci      OpFunctionEnd)";
3272fd4e5da5Sopenharmony_ci
3273fd4e5da5Sopenharmony_ci  spvValidatorOptionsSetRelaxLogicalPointer(options_, true);
3274fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
3275fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
3276fd4e5da5Sopenharmony_ci}
3277fd4e5da5Sopenharmony_ci
3278fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpStoreVoid) {
3279fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
3280fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
3281fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
3282fd4e5da5Sopenharmony_ci%3 = OpTypePointer Uniform %2
3283fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %1
3284fd4e5da5Sopenharmony_ci%6 = OpVariable %3 Uniform
3285fd4e5da5Sopenharmony_ci%7 = OpFunction %1 None %4
3286fd4e5da5Sopenharmony_ci%8 = OpLabel
3287fd4e5da5Sopenharmony_ci%9 = OpFunctionCall %1 %7
3288fd4e5da5Sopenharmony_ci     OpStore %6 %9
3289fd4e5da5Sopenharmony_ci     OpReturn
3290fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
3291fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
3292fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3293fd4e5da5Sopenharmony_ci  EXPECT_THAT(
3294fd4e5da5Sopenharmony_ci      getDiagnosticString(),
3295fd4e5da5Sopenharmony_ci      HasSubstr(make_message("OpStore Object <id> '8[%8]'s type is void.")));
3296fd4e5da5Sopenharmony_ci}
3297fd4e5da5Sopenharmony_ci
3298fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpStoreLabel) {
3299fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
3300fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
3301fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
3302fd4e5da5Sopenharmony_ci%3 = OpTypePointer Uniform %2
3303fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %1
3304fd4e5da5Sopenharmony_ci%6 = OpVariable %3 Uniform
3305fd4e5da5Sopenharmony_ci%7 = OpFunction %1 None %4
3306fd4e5da5Sopenharmony_ci%8 = OpLabel
3307fd4e5da5Sopenharmony_ci     OpStore %6 %8
3308fd4e5da5Sopenharmony_ci     OpReturn
3309fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
3310fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
3311fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3312fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
3313fd4e5da5Sopenharmony_ci              HasSubstr(make_message("Operand '7[%7]' requires a type")));
3314fd4e5da5Sopenharmony_ci}
3315fd4e5da5Sopenharmony_ci
3316fd4e5da5Sopenharmony_ci// TODO: enable when this bug is fixed:
3317fd4e5da5Sopenharmony_ci// https://cvs.khronos.org/bugzilla/show_bug.cgi?id=15404
3318fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, DISABLED_OpStoreFunction) {
3319fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
3320fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
3321fd4e5da5Sopenharmony_ci%3 = OpTypePointer UniformConstant %2
3322fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %2
3323fd4e5da5Sopenharmony_ci%5 = OpConstant %2 123
3324fd4e5da5Sopenharmony_ci%6 = OpVariable %3 UniformConstant
3325fd4e5da5Sopenharmony_ci%7 = OpFunction %2 None %4
3326fd4e5da5Sopenharmony_ci%8 = OpLabel
3327fd4e5da5Sopenharmony_ci     OpStore %6 %7
3328fd4e5da5Sopenharmony_ci     OpReturnValue %5
3329fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
3330fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
3331fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3332fd4e5da5Sopenharmony_ci}
3333fd4e5da5Sopenharmony_ci
3334fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpStoreBuiltin) {
3335fd4e5da5Sopenharmony_ci  std::string spirv = R"(
3336fd4e5da5Sopenharmony_ci               OpCapability Shader
3337fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
3338fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
3339fd4e5da5Sopenharmony_ci               OpEntryPoint GLCompute %main "main" %gl_GlobalInvocationID
3340fd4e5da5Sopenharmony_ci               OpExecutionMode %main LocalSize 1 1 1
3341fd4e5da5Sopenharmony_ci               OpSource GLSL 450
3342fd4e5da5Sopenharmony_ci               OpName %main "main"
3343fd4e5da5Sopenharmony_ci
3344fd4e5da5Sopenharmony_ci               OpName %gl_GlobalInvocationID "gl_GlobalInvocationID"
3345fd4e5da5Sopenharmony_ci               OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId
3346fd4e5da5Sopenharmony_ci
3347fd4e5da5Sopenharmony_ci        %int = OpTypeInt 32 1
3348fd4e5da5Sopenharmony_ci       %uint = OpTypeInt 32 0
3349fd4e5da5Sopenharmony_ci     %v3uint = OpTypeVector %uint 3
3350fd4e5da5Sopenharmony_ci%_ptr_Input_v3uint = OpTypePointer Input %v3uint
3351fd4e5da5Sopenharmony_ci%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input
3352fd4e5da5Sopenharmony_ci
3353fd4e5da5Sopenharmony_ci       %zero = OpConstant %uint 0
3354fd4e5da5Sopenharmony_ci %v3uint_000 = OpConstantComposite %v3uint %zero %zero %zero
3355fd4e5da5Sopenharmony_ci
3356fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
3357fd4e5da5Sopenharmony_ci   %voidfunc = OpTypeFunction %void
3358fd4e5da5Sopenharmony_ci       %main = OpFunction %void None %voidfunc
3359fd4e5da5Sopenharmony_ci      %lmain = OpLabel
3360fd4e5da5Sopenharmony_ci
3361fd4e5da5Sopenharmony_ci               OpStore %gl_GlobalInvocationID %v3uint_000
3362fd4e5da5Sopenharmony_ci
3363fd4e5da5Sopenharmony_ci               OpReturn
3364fd4e5da5Sopenharmony_ci               OpFunctionEnd
3365fd4e5da5Sopenharmony_ci  )";
3366fd4e5da5Sopenharmony_ci
3367fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
3368fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3369fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
3370fd4e5da5Sopenharmony_ci              HasSubstr(make_message("storage class is read-only")));
3371fd4e5da5Sopenharmony_ci}
3372fd4e5da5Sopenharmony_ci
3373fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpCopyMemoryGood) {
3374fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
3375fd4e5da5Sopenharmony_ci %1 = OpTypeVoid
3376fd4e5da5Sopenharmony_ci %2 = OpTypeInt 32 0
3377fd4e5da5Sopenharmony_ci %3 = OpTypePointer UniformConstant %2
3378fd4e5da5Sopenharmony_ci %4 = OpConstant %2 42
3379fd4e5da5Sopenharmony_ci %5 = OpVariable %3 UniformConstant %4
3380fd4e5da5Sopenharmony_ci %6 = OpTypePointer Function %2
3381fd4e5da5Sopenharmony_ci %7 = OpTypeFunction %1
3382fd4e5da5Sopenharmony_ci %8 = OpFunction %1 None %7
3383fd4e5da5Sopenharmony_ci %9 = OpLabel
3384fd4e5da5Sopenharmony_ci%10 = OpVariable %6 Function
3385fd4e5da5Sopenharmony_ci      OpCopyMemory %10 %5 None
3386fd4e5da5Sopenharmony_ci      OpReturn
3387fd4e5da5Sopenharmony_ci      OpFunctionEnd
3388fd4e5da5Sopenharmony_ci)";
3389fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
3390fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
3391fd4e5da5Sopenharmony_ci}
3392fd4e5da5Sopenharmony_ci
3393fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpCopyMemoryNonPointerTarget) {
3394fd4e5da5Sopenharmony_ci  const std::string spirv = kGLSL450MemoryModel + R"(
3395fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
3396fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
3397fd4e5da5Sopenharmony_ci%3 = OpTypePointer Uniform %2
3398fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %1 %2 %3
3399fd4e5da5Sopenharmony_ci%5 = OpFunction %1 None %4
3400fd4e5da5Sopenharmony_ci%6 = OpFunctionParameter %2
3401fd4e5da5Sopenharmony_ci%7 = OpFunctionParameter %3
3402fd4e5da5Sopenharmony_ci%8 = OpLabel
3403fd4e5da5Sopenharmony_ciOpCopyMemory %6 %7
3404fd4e5da5Sopenharmony_ciOpReturn
3405fd4e5da5Sopenharmony_ciOpFunctionEnd
3406fd4e5da5Sopenharmony_ci)";
3407fd4e5da5Sopenharmony_ci
3408fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
3409fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3410fd4e5da5Sopenharmony_ci  EXPECT_THAT(
3411fd4e5da5Sopenharmony_ci      getDiagnosticString(),
3412fd4e5da5Sopenharmony_ci      HasSubstr(make_message("Target operand <id> '6[%6]' is not a pointer.")));
3413fd4e5da5Sopenharmony_ci}
3414fd4e5da5Sopenharmony_ci
3415fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpCopyMemoryNonPointerSource) {
3416fd4e5da5Sopenharmony_ci  const std::string spirv = kGLSL450MemoryModel + R"(
3417fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
3418fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
3419fd4e5da5Sopenharmony_ci%3 = OpTypePointer Uniform %2
3420fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %1 %2 %3
3421fd4e5da5Sopenharmony_ci%5 = OpFunction %1 None %4
3422fd4e5da5Sopenharmony_ci%6 = OpFunctionParameter %2
3423fd4e5da5Sopenharmony_ci%7 = OpFunctionParameter %3
3424fd4e5da5Sopenharmony_ci%8 = OpLabel
3425fd4e5da5Sopenharmony_ciOpCopyMemory %7 %6
3426fd4e5da5Sopenharmony_ciOpReturn
3427fd4e5da5Sopenharmony_ciOpFunctionEnd
3428fd4e5da5Sopenharmony_ci)";
3429fd4e5da5Sopenharmony_ci
3430fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
3431fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3432fd4e5da5Sopenharmony_ci  EXPECT_THAT(
3433fd4e5da5Sopenharmony_ci      getDiagnosticString(),
3434fd4e5da5Sopenharmony_ci      HasSubstr(make_message("Source operand <id> '6[%6]' is not a pointer.")));
3435fd4e5da5Sopenharmony_ci}
3436fd4e5da5Sopenharmony_ci
3437fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpCopyMemoryBad) {
3438fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
3439fd4e5da5Sopenharmony_ci %1 = OpTypeVoid
3440fd4e5da5Sopenharmony_ci %2 = OpTypeInt 32 0
3441fd4e5da5Sopenharmony_ci %3 = OpTypePointer UniformConstant %2
3442fd4e5da5Sopenharmony_ci %4 = OpConstant %2 42
3443fd4e5da5Sopenharmony_ci %5 = OpVariable %3 UniformConstant %4
3444fd4e5da5Sopenharmony_ci%11 = OpTypeFloat 32
3445fd4e5da5Sopenharmony_ci %6 = OpTypePointer Function %11
3446fd4e5da5Sopenharmony_ci %7 = OpTypeFunction %1
3447fd4e5da5Sopenharmony_ci %8 = OpFunction %1 None %7
3448fd4e5da5Sopenharmony_ci %9 = OpLabel
3449fd4e5da5Sopenharmony_ci%10 = OpVariable %6 Function
3450fd4e5da5Sopenharmony_ci      OpCopyMemory %10 %5 None
3451fd4e5da5Sopenharmony_ci      OpReturn
3452fd4e5da5Sopenharmony_ci      OpFunctionEnd
3453fd4e5da5Sopenharmony_ci)";
3454fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
3455fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3456fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
3457fd4e5da5Sopenharmony_ci              HasSubstr(make_message("Target <id> '5[%5]'s type does not match "
3458fd4e5da5Sopenharmony_ci                                     "Source <id> '2[%uint]'s type.")));
3459fd4e5da5Sopenharmony_ci}
3460fd4e5da5Sopenharmony_ci
3461fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpCopyMemoryVoidTarget) {
3462fd4e5da5Sopenharmony_ci  const std::string spirv = kGLSL450MemoryModel + R"(
3463fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
3464fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
3465fd4e5da5Sopenharmony_ci%3 = OpTypePointer Uniform %1
3466fd4e5da5Sopenharmony_ci%4 = OpTypePointer Uniform %2
3467fd4e5da5Sopenharmony_ci%5 = OpTypeFunction %1 %3 %4
3468fd4e5da5Sopenharmony_ci%6 = OpFunction %1 None %5
3469fd4e5da5Sopenharmony_ci%7 = OpFunctionParameter %3
3470fd4e5da5Sopenharmony_ci%8 = OpFunctionParameter %4
3471fd4e5da5Sopenharmony_ci%9 = OpLabel
3472fd4e5da5Sopenharmony_ciOpCopyMemory %7 %8
3473fd4e5da5Sopenharmony_ciOpReturn
3474fd4e5da5Sopenharmony_ciOpFunctionEnd
3475fd4e5da5Sopenharmony_ci)";
3476fd4e5da5Sopenharmony_ci
3477fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
3478fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3479fd4e5da5Sopenharmony_ci  EXPECT_THAT(
3480fd4e5da5Sopenharmony_ci      getDiagnosticString(),
3481fd4e5da5Sopenharmony_ci      HasSubstr(make_message("Target operand <id> '7[%7]' cannot be a void "
3482fd4e5da5Sopenharmony_ci                             "pointer.")));
3483fd4e5da5Sopenharmony_ci}
3484fd4e5da5Sopenharmony_ci
3485fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpCopyMemoryVoidSource) {
3486fd4e5da5Sopenharmony_ci  const std::string spirv = kGLSL450MemoryModel + R"(
3487fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
3488fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
3489fd4e5da5Sopenharmony_ci%3 = OpTypePointer Uniform %1
3490fd4e5da5Sopenharmony_ci%4 = OpTypePointer Uniform %2
3491fd4e5da5Sopenharmony_ci%5 = OpTypeFunction %1 %3 %4
3492fd4e5da5Sopenharmony_ci%6 = OpFunction %1 None %5
3493fd4e5da5Sopenharmony_ci%7 = OpFunctionParameter %3
3494fd4e5da5Sopenharmony_ci%8 = OpFunctionParameter %4
3495fd4e5da5Sopenharmony_ci%9 = OpLabel
3496fd4e5da5Sopenharmony_ciOpCopyMemory %8 %7
3497fd4e5da5Sopenharmony_ciOpReturn
3498fd4e5da5Sopenharmony_ciOpFunctionEnd
3499fd4e5da5Sopenharmony_ci)";
3500fd4e5da5Sopenharmony_ci
3501fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
3502fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3503fd4e5da5Sopenharmony_ci  EXPECT_THAT(
3504fd4e5da5Sopenharmony_ci      getDiagnosticString(),
3505fd4e5da5Sopenharmony_ci      HasSubstr(make_message("Source operand <id> '7[%7]' cannot be a void "
3506fd4e5da5Sopenharmony_ci                             "pointer.")));
3507fd4e5da5Sopenharmony_ci}
3508fd4e5da5Sopenharmony_ci
3509fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpCopyMemorySizedGood) {
3510fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
3511fd4e5da5Sopenharmony_ci %1 = OpTypeVoid
3512fd4e5da5Sopenharmony_ci %2 = OpTypeInt 32 0
3513fd4e5da5Sopenharmony_ci %3 = OpTypePointer UniformConstant %2
3514fd4e5da5Sopenharmony_ci %4 = OpTypePointer Function %2
3515fd4e5da5Sopenharmony_ci %5 = OpConstant %2 4
3516fd4e5da5Sopenharmony_ci %6 = OpVariable %3 UniformConstant %5
3517fd4e5da5Sopenharmony_ci %7 = OpTypeFunction %1
3518fd4e5da5Sopenharmony_ci %8 = OpFunction %1 None %7
3519fd4e5da5Sopenharmony_ci %9 = OpLabel
3520fd4e5da5Sopenharmony_ci%10 = OpVariable %4 Function
3521fd4e5da5Sopenharmony_ci      OpCopyMemorySized %10 %6 %5 None
3522fd4e5da5Sopenharmony_ci      OpReturn
3523fd4e5da5Sopenharmony_ci      OpFunctionEnd)";
3524fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
3525fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
3526fd4e5da5Sopenharmony_ci}
3527fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpCopyMemorySizedTargetBad) {
3528fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
3529fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
3530fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
3531fd4e5da5Sopenharmony_ci%3 = OpTypePointer UniformConstant %2
3532fd4e5da5Sopenharmony_ci%4 = OpTypePointer Function %2
3533fd4e5da5Sopenharmony_ci%5 = OpConstant %2 4
3534fd4e5da5Sopenharmony_ci%6 = OpVariable %3 UniformConstant %5
3535fd4e5da5Sopenharmony_ci%7 = OpTypeFunction %1
3536fd4e5da5Sopenharmony_ci%8 = OpFunction %1 None %7
3537fd4e5da5Sopenharmony_ci%9 = OpLabel
3538fd4e5da5Sopenharmony_ci     OpCopyMemorySized %5 %5 %5 None
3539fd4e5da5Sopenharmony_ci     OpReturn
3540fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
3541fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
3542fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3543fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
3544fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
3545fd4e5da5Sopenharmony_ci                  "Target operand <id> '5[%uint_4]' is not a pointer.")));
3546fd4e5da5Sopenharmony_ci}
3547fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpCopyMemorySizedSourceBad) {
3548fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
3549fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
3550fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
3551fd4e5da5Sopenharmony_ci%3 = OpTypePointer UniformConstant %2
3552fd4e5da5Sopenharmony_ci%4 = OpTypePointer Function %2
3553fd4e5da5Sopenharmony_ci%5 = OpConstant %2 4
3554fd4e5da5Sopenharmony_ci%6 = OpTypeFunction %1
3555fd4e5da5Sopenharmony_ci%7 = OpFunction %1 None %6
3556fd4e5da5Sopenharmony_ci%8 = OpLabel
3557fd4e5da5Sopenharmony_ci%9 = OpVariable %4 Function
3558fd4e5da5Sopenharmony_ci     OpCopyMemorySized %9 %5 %5 None
3559fd4e5da5Sopenharmony_ci     OpReturn
3560fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
3561fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
3562fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3563fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
3564fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
3565fd4e5da5Sopenharmony_ci                  "Source operand <id> '5[%uint_4]' is not a pointer.")));
3566fd4e5da5Sopenharmony_ci}
3567fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpCopyMemorySizedSizeBad) {
3568fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
3569fd4e5da5Sopenharmony_ci %1 = OpTypeVoid
3570fd4e5da5Sopenharmony_ci %2 = OpTypeInt 32 0
3571fd4e5da5Sopenharmony_ci %3 = OpTypePointer UniformConstant %2
3572fd4e5da5Sopenharmony_ci %4 = OpTypePointer Function %2
3573fd4e5da5Sopenharmony_ci %5 = OpConstant %2 4
3574fd4e5da5Sopenharmony_ci %6 = OpVariable %3 UniformConstant %5
3575fd4e5da5Sopenharmony_ci %7 = OpTypeFunction %1
3576fd4e5da5Sopenharmony_ci %8 = OpFunction %1 None %7
3577fd4e5da5Sopenharmony_ci %9 = OpLabel
3578fd4e5da5Sopenharmony_ci%10 = OpVariable %4 Function
3579fd4e5da5Sopenharmony_ci      OpCopyMemorySized %10 %6 %6 None
3580fd4e5da5Sopenharmony_ci      OpReturn
3581fd4e5da5Sopenharmony_ci      OpFunctionEnd)";
3582fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
3583fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3584fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
3585fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
3586fd4e5da5Sopenharmony_ci                  "Size operand <id> '6[%6]' must be a scalar integer type.")));
3587fd4e5da5Sopenharmony_ci}
3588fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpCopyMemorySizedSizeTypeBad) {
3589fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
3590fd4e5da5Sopenharmony_ci %1 = OpTypeVoid
3591fd4e5da5Sopenharmony_ci %2 = OpTypeInt 32 0
3592fd4e5da5Sopenharmony_ci %3 = OpTypePointer UniformConstant %2
3593fd4e5da5Sopenharmony_ci %4 = OpTypePointer Function %2
3594fd4e5da5Sopenharmony_ci %5 = OpConstant %2 4
3595fd4e5da5Sopenharmony_ci %6 = OpVariable %3 UniformConstant %5
3596fd4e5da5Sopenharmony_ci %7 = OpTypeFunction %1
3597fd4e5da5Sopenharmony_ci%11 = OpTypeFloat 32
3598fd4e5da5Sopenharmony_ci%12 = OpConstant %11 1.0
3599fd4e5da5Sopenharmony_ci %8 = OpFunction %1 None %7
3600fd4e5da5Sopenharmony_ci %9 = OpLabel
3601fd4e5da5Sopenharmony_ci%10 = OpVariable %4 Function
3602fd4e5da5Sopenharmony_ci      OpCopyMemorySized %10 %6 %12 None
3603fd4e5da5Sopenharmony_ci      OpReturn
3604fd4e5da5Sopenharmony_ci      OpFunctionEnd)";
3605fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
3606fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3607fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
3608fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
3609fd4e5da5Sopenharmony_ci                  "Size operand <id> '9[%float_1]' must be a scalar integer "
3610fd4e5da5Sopenharmony_ci                  "type.")));
3611fd4e5da5Sopenharmony_ci}
3612fd4e5da5Sopenharmony_ci
3613fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpCopyMemorySizedSizeConstantNull) {
3614fd4e5da5Sopenharmony_ci  const std::string spirv = kGLSL450MemoryModel + R"(
3615fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
3616fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
3617fd4e5da5Sopenharmony_ci%3 = OpConstantNull %2
3618fd4e5da5Sopenharmony_ci%4 = OpTypePointer Uniform %2
3619fd4e5da5Sopenharmony_ci%5 = OpTypeFloat 32
3620fd4e5da5Sopenharmony_ci%6 = OpTypePointer UniformConstant %5
3621fd4e5da5Sopenharmony_ci%7 = OpTypeFunction %1 %4 %6
3622fd4e5da5Sopenharmony_ci%8 = OpFunction %1 None %7
3623fd4e5da5Sopenharmony_ci%9 = OpFunctionParameter %4
3624fd4e5da5Sopenharmony_ci%10 = OpFunctionParameter %6
3625fd4e5da5Sopenharmony_ci%11 = OpLabel
3626fd4e5da5Sopenharmony_ciOpCopyMemorySized %9 %10 %3
3627fd4e5da5Sopenharmony_ciOpReturn
3628fd4e5da5Sopenharmony_ciOpFunctionEnd
3629fd4e5da5Sopenharmony_ci)";
3630fd4e5da5Sopenharmony_ci
3631fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
3632fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3633fd4e5da5Sopenharmony_ci  EXPECT_THAT(
3634fd4e5da5Sopenharmony_ci      getDiagnosticString(),
3635fd4e5da5Sopenharmony_ci      HasSubstr(make_message("Size operand <id> '3[%3]' cannot be a constant "
3636fd4e5da5Sopenharmony_ci                             "zero.")));
3637fd4e5da5Sopenharmony_ci}
3638fd4e5da5Sopenharmony_ci
3639fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpCopyMemorySizedSizeConstantZero) {
3640fd4e5da5Sopenharmony_ci  const std::string spirv = kGLSL450MemoryModel + R"(
3641fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
3642fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
3643fd4e5da5Sopenharmony_ci%3 = OpConstant %2 0
3644fd4e5da5Sopenharmony_ci%4 = OpTypePointer Uniform %2
3645fd4e5da5Sopenharmony_ci%5 = OpTypeFloat 32
3646fd4e5da5Sopenharmony_ci%6 = OpTypePointer UniformConstant %5
3647fd4e5da5Sopenharmony_ci%7 = OpTypeFunction %1 %4 %6
3648fd4e5da5Sopenharmony_ci%8 = OpFunction %1 None %7
3649fd4e5da5Sopenharmony_ci%9 = OpFunctionParameter %4
3650fd4e5da5Sopenharmony_ci%10 = OpFunctionParameter %6
3651fd4e5da5Sopenharmony_ci%11 = OpLabel
3652fd4e5da5Sopenharmony_ciOpCopyMemorySized %9 %10 %3
3653fd4e5da5Sopenharmony_ciOpReturn
3654fd4e5da5Sopenharmony_ciOpFunctionEnd
3655fd4e5da5Sopenharmony_ci)";
3656fd4e5da5Sopenharmony_ci
3657fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
3658fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3659fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
3660fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
3661fd4e5da5Sopenharmony_ci                  "Size operand <id> '3[%uint_0]' cannot be a constant "
3662fd4e5da5Sopenharmony_ci                  "zero.")));
3663fd4e5da5Sopenharmony_ci}
3664fd4e5da5Sopenharmony_ci
3665fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpCopyMemorySizedSizeConstantZero64) {
3666fd4e5da5Sopenharmony_ci  const std::string spirv = kGLSL450MemoryModel + R"(
3667fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
3668fd4e5da5Sopenharmony_ci%2 = OpTypeInt 64 0
3669fd4e5da5Sopenharmony_ci%3 = OpConstant %2 0
3670fd4e5da5Sopenharmony_ci%4 = OpTypePointer Uniform %2
3671fd4e5da5Sopenharmony_ci%5 = OpTypeFloat 32
3672fd4e5da5Sopenharmony_ci%6 = OpTypePointer UniformConstant %5
3673fd4e5da5Sopenharmony_ci%7 = OpTypeFunction %1 %4 %6
3674fd4e5da5Sopenharmony_ci%8 = OpFunction %1 None %7
3675fd4e5da5Sopenharmony_ci%9 = OpFunctionParameter %4
3676fd4e5da5Sopenharmony_ci%10 = OpFunctionParameter %6
3677fd4e5da5Sopenharmony_ci%11 = OpLabel
3678fd4e5da5Sopenharmony_ciOpCopyMemorySized %9 %10 %3
3679fd4e5da5Sopenharmony_ciOpReturn
3680fd4e5da5Sopenharmony_ciOpFunctionEnd
3681fd4e5da5Sopenharmony_ci)";
3682fd4e5da5Sopenharmony_ci
3683fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
3684fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3685fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
3686fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
3687fd4e5da5Sopenharmony_ci                  "Size operand <id> '3[%ulong_0]' cannot be a constant "
3688fd4e5da5Sopenharmony_ci                  "zero.")));
3689fd4e5da5Sopenharmony_ci}
3690fd4e5da5Sopenharmony_ci
3691fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpCopyMemorySizedSizeConstantNegative) {
3692fd4e5da5Sopenharmony_ci  const std::string spirv = kNoKernelGLSL450MemoryModel + R"(
3693fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
3694fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 1
3695fd4e5da5Sopenharmony_ci%3 = OpConstant %2 -1
3696fd4e5da5Sopenharmony_ci%4 = OpTypePointer Uniform %2
3697fd4e5da5Sopenharmony_ci%5 = OpTypeFloat 32
3698fd4e5da5Sopenharmony_ci%6 = OpTypePointer UniformConstant %5
3699fd4e5da5Sopenharmony_ci%7 = OpTypeFunction %1 %4 %6
3700fd4e5da5Sopenharmony_ci%8 = OpFunction %1 None %7
3701fd4e5da5Sopenharmony_ci%9 = OpFunctionParameter %4
3702fd4e5da5Sopenharmony_ci%10 = OpFunctionParameter %6
3703fd4e5da5Sopenharmony_ci%11 = OpLabel
3704fd4e5da5Sopenharmony_ciOpCopyMemorySized %9 %10 %3
3705fd4e5da5Sopenharmony_ciOpReturn
3706fd4e5da5Sopenharmony_ciOpFunctionEnd
3707fd4e5da5Sopenharmony_ci)";
3708fd4e5da5Sopenharmony_ci
3709fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
3710fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3711fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
3712fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
3713fd4e5da5Sopenharmony_ci                  "Size operand <id> '3[%int_n1]' cannot have the sign bit set "
3714fd4e5da5Sopenharmony_ci                  "to 1.")));
3715fd4e5da5Sopenharmony_ci}
3716fd4e5da5Sopenharmony_ci
3717fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpCopyMemorySizedSizeConstantNegative64) {
3718fd4e5da5Sopenharmony_ci  const std::string spirv = kNoKernelGLSL450MemoryModel + R"(
3719fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
3720fd4e5da5Sopenharmony_ci%2 = OpTypeInt 64 1
3721fd4e5da5Sopenharmony_ci%3 = OpConstant %2 -1
3722fd4e5da5Sopenharmony_ci%4 = OpTypePointer Uniform %2
3723fd4e5da5Sopenharmony_ci%5 = OpTypeFloat 32
3724fd4e5da5Sopenharmony_ci%6 = OpTypePointer UniformConstant %5
3725fd4e5da5Sopenharmony_ci%7 = OpTypeFunction %1 %4 %6
3726fd4e5da5Sopenharmony_ci%8 = OpFunction %1 None %7
3727fd4e5da5Sopenharmony_ci%9 = OpFunctionParameter %4
3728fd4e5da5Sopenharmony_ci%10 = OpFunctionParameter %6
3729fd4e5da5Sopenharmony_ci%11 = OpLabel
3730fd4e5da5Sopenharmony_ciOpCopyMemorySized %9 %10 %3
3731fd4e5da5Sopenharmony_ciOpReturn
3732fd4e5da5Sopenharmony_ciOpFunctionEnd
3733fd4e5da5Sopenharmony_ci)";
3734fd4e5da5Sopenharmony_ci
3735fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
3736fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3737fd4e5da5Sopenharmony_ci  EXPECT_THAT(
3738fd4e5da5Sopenharmony_ci      getDiagnosticString(),
3739fd4e5da5Sopenharmony_ci      HasSubstr(make_message(
3740fd4e5da5Sopenharmony_ci          "Size operand <id> '3[%long_n1]' cannot have the sign bit set "
3741fd4e5da5Sopenharmony_ci          "to 1.")));
3742fd4e5da5Sopenharmony_ci}
3743fd4e5da5Sopenharmony_ci
3744fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpCopyMemorySizedSizeUnsignedNegative) {
3745fd4e5da5Sopenharmony_ci  const std::string spirv = kGLSL450MemoryModel + R"(
3746fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
3747fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
3748fd4e5da5Sopenharmony_ci%3 = OpConstant %2 2147483648
3749fd4e5da5Sopenharmony_ci%4 = OpTypePointer Uniform %2
3750fd4e5da5Sopenharmony_ci%5 = OpTypeFloat 32
3751fd4e5da5Sopenharmony_ci%6 = OpTypePointer UniformConstant %5
3752fd4e5da5Sopenharmony_ci%7 = OpTypeFunction %1 %4 %6
3753fd4e5da5Sopenharmony_ci%8 = OpFunction %1 None %7
3754fd4e5da5Sopenharmony_ci%9 = OpFunctionParameter %4
3755fd4e5da5Sopenharmony_ci%10 = OpFunctionParameter %6
3756fd4e5da5Sopenharmony_ci%11 = OpLabel
3757fd4e5da5Sopenharmony_ciOpCopyMemorySized %9 %10 %3
3758fd4e5da5Sopenharmony_ciOpReturn
3759fd4e5da5Sopenharmony_ciOpFunctionEnd
3760fd4e5da5Sopenharmony_ci)";
3761fd4e5da5Sopenharmony_ci
3762fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
3763fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
3764fd4e5da5Sopenharmony_ci}
3765fd4e5da5Sopenharmony_ci
3766fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpCopyMemorySizedSizeUnsignedNegative64) {
3767fd4e5da5Sopenharmony_ci  const std::string spirv = kGLSL450MemoryModel + R"(
3768fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
3769fd4e5da5Sopenharmony_ci%2 = OpTypeInt 64 0
3770fd4e5da5Sopenharmony_ci%3 = OpConstant %2 9223372036854775808
3771fd4e5da5Sopenharmony_ci%4 = OpTypePointer Uniform %2
3772fd4e5da5Sopenharmony_ci%5 = OpTypeFloat 32
3773fd4e5da5Sopenharmony_ci%6 = OpTypePointer UniformConstant %5
3774fd4e5da5Sopenharmony_ci%7 = OpTypeFunction %1 %4 %6
3775fd4e5da5Sopenharmony_ci%8 = OpFunction %1 None %7
3776fd4e5da5Sopenharmony_ci%9 = OpFunctionParameter %4
3777fd4e5da5Sopenharmony_ci%10 = OpFunctionParameter %6
3778fd4e5da5Sopenharmony_ci%11 = OpLabel
3779fd4e5da5Sopenharmony_ciOpCopyMemorySized %9 %10 %3
3780fd4e5da5Sopenharmony_ciOpReturn
3781fd4e5da5Sopenharmony_ciOpFunctionEnd
3782fd4e5da5Sopenharmony_ci)";
3783fd4e5da5Sopenharmony_ci
3784fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
3785fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
3786fd4e5da5Sopenharmony_ci}
3787fd4e5da5Sopenharmony_ci
3788fd4e5da5Sopenharmony_ciconst char kDeeplyNestedStructureSetup[] = R"(
3789fd4e5da5Sopenharmony_ci%void = OpTypeVoid
3790fd4e5da5Sopenharmony_ci%void_f  = OpTypeFunction %void
3791fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
3792fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
3793fd4e5da5Sopenharmony_ci%v3float = OpTypeVector %float 3
3794fd4e5da5Sopenharmony_ci%mat4x3 = OpTypeMatrix %v3float 4
3795fd4e5da5Sopenharmony_ci%_ptr_Private_mat4x3 = OpTypePointer Private %mat4x3
3796fd4e5da5Sopenharmony_ci%_ptr_Private_float = OpTypePointer Private %float
3797fd4e5da5Sopenharmony_ci%my_matrix = OpVariable %_ptr_Private_mat4x3 Private
3798fd4e5da5Sopenharmony_ci%my_float_var = OpVariable %_ptr_Private_float Private
3799fd4e5da5Sopenharmony_ci%_ptr_Function_float = OpTypePointer Function %float
3800fd4e5da5Sopenharmony_ci%int_0 = OpConstant %int 0
3801fd4e5da5Sopenharmony_ci%int_1 = OpConstant %int 1
3802fd4e5da5Sopenharmony_ci%int_2 = OpConstant %int 2
3803fd4e5da5Sopenharmony_ci%int_3 = OpConstant %int 3
3804fd4e5da5Sopenharmony_ci%int_5 = OpConstant %int 5
3805fd4e5da5Sopenharmony_ci
3806fd4e5da5Sopenharmony_ci; Making the following nested structures.
3807fd4e5da5Sopenharmony_ci;
3808fd4e5da5Sopenharmony_ci; struct S {
3809fd4e5da5Sopenharmony_ci;   bool b;
3810fd4e5da5Sopenharmony_ci;   vec4 v[5];
3811fd4e5da5Sopenharmony_ci;   int i;
3812fd4e5da5Sopenharmony_ci;   mat4x3 m[5];
3813fd4e5da5Sopenharmony_ci; }
3814fd4e5da5Sopenharmony_ci; uniform blockName {
3815fd4e5da5Sopenharmony_ci;   S s;
3816fd4e5da5Sopenharmony_ci;   bool cond;
3817fd4e5da5Sopenharmony_ci;   RunTimeArray arr;
3818fd4e5da5Sopenharmony_ci; }
3819fd4e5da5Sopenharmony_ci
3820fd4e5da5Sopenharmony_ci%f32arr = OpTypeRuntimeArray %float
3821fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
3822fd4e5da5Sopenharmony_ci%array5_mat4x3 = OpTypeArray %mat4x3 %int_5
3823fd4e5da5Sopenharmony_ci%array5_vec4 = OpTypeArray %v4float %int_5
3824fd4e5da5Sopenharmony_ci%_ptr_Uniform_float = OpTypePointer Uniform %float
3825fd4e5da5Sopenharmony_ci%_ptr_Function_vec4 = OpTypePointer Function %v4float
3826fd4e5da5Sopenharmony_ci%_ptr_Uniform_vec4 = OpTypePointer Uniform %v4float
3827fd4e5da5Sopenharmony_ci%struct_s = OpTypeStruct %int %array5_vec4 %int %array5_mat4x3
3828fd4e5da5Sopenharmony_ci%struct_blockName = OpTypeStruct %struct_s %int %f32arr
3829fd4e5da5Sopenharmony_ci%_ptr_Uniform_blockName = OpTypePointer Uniform %struct_blockName
3830fd4e5da5Sopenharmony_ci%_ptr_Uniform_struct_s = OpTypePointer Uniform %struct_s
3831fd4e5da5Sopenharmony_ci%_ptr_Uniform_array5_mat4x3 = OpTypePointer Uniform %array5_mat4x3
3832fd4e5da5Sopenharmony_ci%_ptr_Uniform_mat4x3 = OpTypePointer Uniform %mat4x3
3833fd4e5da5Sopenharmony_ci%_ptr_Uniform_v3float = OpTypePointer Uniform %v3float
3834fd4e5da5Sopenharmony_ci%blockName_var = OpVariable %_ptr_Uniform_blockName Uniform
3835fd4e5da5Sopenharmony_ci%spec_int = OpSpecConstant %int 2
3836fd4e5da5Sopenharmony_ci%float_0 = OpConstant %float 0
3837fd4e5da5Sopenharmony_ci%func = OpFunction %void None %void_f
3838fd4e5da5Sopenharmony_ci%my_label = OpLabel
3839fd4e5da5Sopenharmony_ci)";
3840fd4e5da5Sopenharmony_ci
3841fd4e5da5Sopenharmony_ci// In what follows, Access Chain Instruction refers to one of the following:
3842fd4e5da5Sopenharmony_ci// OpAccessChain, OpInBoundsAccessChain, OpPtrAccessChain, and
3843fd4e5da5Sopenharmony_ci// OpInBoundsPtrAccessChain
3844fd4e5da5Sopenharmony_ciusing AccessChainInstructionTest = spvtest::ValidateBase<std::string>;
3845fd4e5da5Sopenharmony_ci
3846fd4e5da5Sopenharmony_ci// Determines whether the access chain instruction requires the 'element id'
3847fd4e5da5Sopenharmony_ci// argument.
3848fd4e5da5Sopenharmony_cibool AccessChainRequiresElemId(const std::string& instr) {
3849fd4e5da5Sopenharmony_ci  return (instr == "OpPtrAccessChain" || instr == "OpInBoundsPtrAccessChain");
3850fd4e5da5Sopenharmony_ci}
3851fd4e5da5Sopenharmony_ci
3852fd4e5da5Sopenharmony_ci// Valid: Access a float in a matrix using an access chain instruction.
3853fd4e5da5Sopenharmony_ciTEST_P(AccessChainInstructionTest, AccessChainGood) {
3854fd4e5da5Sopenharmony_ci  const std::string instr = GetParam();
3855fd4e5da5Sopenharmony_ci  const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : "";
3856fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup +
3857fd4e5da5Sopenharmony_ci                      "%float_entry = " + instr +
3858fd4e5da5Sopenharmony_ci                      R"( %_ptr_Private_float %my_matrix )" + elem +
3859fd4e5da5Sopenharmony_ci                      R"(%int_0 %int_1
3860fd4e5da5Sopenharmony_ci              OpReturn
3861fd4e5da5Sopenharmony_ci              OpFunctionEnd
3862fd4e5da5Sopenharmony_ci          )";
3863fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
3864fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
3865fd4e5da5Sopenharmony_ci}
3866fd4e5da5Sopenharmony_ci
3867fd4e5da5Sopenharmony_ci// Invalid. The result type of an access chain instruction must be a pointer.
3868fd4e5da5Sopenharmony_ciTEST_P(AccessChainInstructionTest, AccessChainResultTypeBad) {
3869fd4e5da5Sopenharmony_ci  const std::string instr = GetParam();
3870fd4e5da5Sopenharmony_ci  const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : "";
3871fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"(
3872fd4e5da5Sopenharmony_ci%float_entry = )" +
3873fd4e5da5Sopenharmony_ci                      instr +
3874fd4e5da5Sopenharmony_ci                      R"( %float %my_matrix )" + elem +
3875fd4e5da5Sopenharmony_ci                      R"(%int_0 %int_1
3876fd4e5da5Sopenharmony_ciOpReturn
3877fd4e5da5Sopenharmony_ciOpFunctionEnd
3878fd4e5da5Sopenharmony_ci  )";
3879fd4e5da5Sopenharmony_ci
3880fd4e5da5Sopenharmony_ci  const std::string expected_err = "The Result Type of " + instr +
3881fd4e5da5Sopenharmony_ci                                   " <id> '36[%36]' must be "
3882fd4e5da5Sopenharmony_ci                                   "OpTypePointer. Found OpTypeFloat.";
3883fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
3884fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3885fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err));
3886fd4e5da5Sopenharmony_ci}
3887fd4e5da5Sopenharmony_ci
3888fd4e5da5Sopenharmony_ci// Invalid. The base type of an access chain instruction must be a pointer.
3889fd4e5da5Sopenharmony_ciTEST_P(AccessChainInstructionTest, AccessChainBaseTypeVoidBad) {
3890fd4e5da5Sopenharmony_ci  const std::string instr = GetParam();
3891fd4e5da5Sopenharmony_ci  const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : "";
3892fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"(
3893fd4e5da5Sopenharmony_ci%float_entry = )" +
3894fd4e5da5Sopenharmony_ci                      instr + " %_ptr_Private_float %void " + elem +
3895fd4e5da5Sopenharmony_ci                      R"(%int_0 %int_1
3896fd4e5da5Sopenharmony_ciOpReturn
3897fd4e5da5Sopenharmony_ciOpFunctionEnd
3898fd4e5da5Sopenharmony_ci  )";
3899fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
3900fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3901fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr("Operand '1[%void]' cannot be a "
3902fd4e5da5Sopenharmony_ci                                               "type"));
3903fd4e5da5Sopenharmony_ci}
3904fd4e5da5Sopenharmony_ci
3905fd4e5da5Sopenharmony_ci// Invalid. The base type of an access chain instruction must be a pointer.
3906fd4e5da5Sopenharmony_ciTEST_P(AccessChainInstructionTest, AccessChainBaseTypeNonPtrVariableBad) {
3907fd4e5da5Sopenharmony_ci  const std::string instr = GetParam();
3908fd4e5da5Sopenharmony_ci  const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : "";
3909fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"(
3910fd4e5da5Sopenharmony_ci%entry = )" +
3911fd4e5da5Sopenharmony_ci                      instr + R"( %_ptr_Private_float %_ptr_Private_float )" +
3912fd4e5da5Sopenharmony_ci                      elem +
3913fd4e5da5Sopenharmony_ci                      R"(%int_0 %int_1
3914fd4e5da5Sopenharmony_ciOpReturn
3915fd4e5da5Sopenharmony_ciOpFunctionEnd
3916fd4e5da5Sopenharmony_ci  )";
3917fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
3918fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3919fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
3920fd4e5da5Sopenharmony_ci              HasSubstr("Operand '8[%_ptr_Private_float]' cannot be a type"));
3921fd4e5da5Sopenharmony_ci}
3922fd4e5da5Sopenharmony_ci
3923fd4e5da5Sopenharmony_ci// Invalid: The storage class of Base and Result do not match.
3924fd4e5da5Sopenharmony_ciTEST_P(AccessChainInstructionTest,
3925fd4e5da5Sopenharmony_ci       AccessChainResultAndBaseStorageClassDoesntMatchBad) {
3926fd4e5da5Sopenharmony_ci  const std::string instr = GetParam();
3927fd4e5da5Sopenharmony_ci  const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : "";
3928fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"(
3929fd4e5da5Sopenharmony_ci%entry = )" +
3930fd4e5da5Sopenharmony_ci                      instr + R"( %_ptr_Function_float %my_matrix )" + elem +
3931fd4e5da5Sopenharmony_ci                      R"(%int_0 %int_1
3932fd4e5da5Sopenharmony_ciOpReturn
3933fd4e5da5Sopenharmony_ciOpFunctionEnd
3934fd4e5da5Sopenharmony_ci  )";
3935fd4e5da5Sopenharmony_ci  const std::string expected_err =
3936fd4e5da5Sopenharmony_ci      "The result pointer storage class and base pointer storage class in " +
3937fd4e5da5Sopenharmony_ci      instr + " do not match.";
3938fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
3939fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3940fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err));
3941fd4e5da5Sopenharmony_ci}
3942fd4e5da5Sopenharmony_ci
3943fd4e5da5Sopenharmony_ci// Invalid. The base type of an access chain instruction must point to a
3944fd4e5da5Sopenharmony_ci// composite object.
3945fd4e5da5Sopenharmony_ciTEST_P(AccessChainInstructionTest,
3946fd4e5da5Sopenharmony_ci       AccessChainBasePtrNotPointingToCompositeBad) {
3947fd4e5da5Sopenharmony_ci  const std::string instr = GetParam();
3948fd4e5da5Sopenharmony_ci  const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : "";
3949fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"(
3950fd4e5da5Sopenharmony_ci%entry = )" +
3951fd4e5da5Sopenharmony_ci                      instr + R"( %_ptr_Private_float %my_float_var )" + elem +
3952fd4e5da5Sopenharmony_ci                      R"(%int_0
3953fd4e5da5Sopenharmony_ciOpReturn
3954fd4e5da5Sopenharmony_ciOpFunctionEnd
3955fd4e5da5Sopenharmony_ci  )";
3956fd4e5da5Sopenharmony_ci  const std::string expected_err = instr +
3957fd4e5da5Sopenharmony_ci                                   " reached non-composite type while "
3958fd4e5da5Sopenharmony_ci                                   "indexes still remain to be traversed.";
3959fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
3960fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3961fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err));
3962fd4e5da5Sopenharmony_ci}
3963fd4e5da5Sopenharmony_ci
3964fd4e5da5Sopenharmony_ci// Valid. No Indexes were passed to the access chain instruction. The Result
3965fd4e5da5Sopenharmony_ci// Type is the same as the Base type.
3966fd4e5da5Sopenharmony_ciTEST_P(AccessChainInstructionTest, AccessChainNoIndexesGood) {
3967fd4e5da5Sopenharmony_ci  const std::string instr = GetParam();
3968fd4e5da5Sopenharmony_ci  const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : "";
3969fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"(
3970fd4e5da5Sopenharmony_ci%entry = )" +
3971fd4e5da5Sopenharmony_ci                      instr + R"( %_ptr_Private_float %my_float_var )" + elem +
3972fd4e5da5Sopenharmony_ci                      R"(
3973fd4e5da5Sopenharmony_ciOpReturn
3974fd4e5da5Sopenharmony_ciOpFunctionEnd
3975fd4e5da5Sopenharmony_ci  )";
3976fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
3977fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
3978fd4e5da5Sopenharmony_ci}
3979fd4e5da5Sopenharmony_ci
3980fd4e5da5Sopenharmony_ci// Invalid. No Indexes were passed to the access chain instruction, but the
3981fd4e5da5Sopenharmony_ci// Result Type is different from the Base type.
3982fd4e5da5Sopenharmony_ciTEST_P(AccessChainInstructionTest, AccessChainNoIndexesBad) {
3983fd4e5da5Sopenharmony_ci  const std::string instr = GetParam();
3984fd4e5da5Sopenharmony_ci  const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : "";
3985fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"(
3986fd4e5da5Sopenharmony_ci%entry = )" +
3987fd4e5da5Sopenharmony_ci                      instr + R"( %_ptr_Private_mat4x3 %my_float_var )" + elem +
3988fd4e5da5Sopenharmony_ci                      R"(
3989fd4e5da5Sopenharmony_ciOpReturn
3990fd4e5da5Sopenharmony_ciOpFunctionEnd
3991fd4e5da5Sopenharmony_ci  )";
3992fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
3993fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
3994fd4e5da5Sopenharmony_ci  EXPECT_THAT(
3995fd4e5da5Sopenharmony_ci      getDiagnosticString(),
3996fd4e5da5Sopenharmony_ci      HasSubstr("result type (OpTypeMatrix) does not match the type that "
3997fd4e5da5Sopenharmony_ci                "results from indexing into the base <id> (OpTypeFloat)."));
3998fd4e5da5Sopenharmony_ci}
3999fd4e5da5Sopenharmony_ci
4000fd4e5da5Sopenharmony_ci// Valid: 255 indexes passed to the access chain instruction. Limit is 255.
4001fd4e5da5Sopenharmony_ciTEST_P(AccessChainInstructionTest, AccessChainTooManyIndexesGood) {
4002fd4e5da5Sopenharmony_ci  const std::string instr = GetParam();
4003fd4e5da5Sopenharmony_ci  const std::string elem = AccessChainRequiresElemId(instr) ? " %int_0 " : "";
4004fd4e5da5Sopenharmony_ci  const std::string arrayStride =
4005fd4e5da5Sopenharmony_ci      " OpDecorate %_ptr_Uniform_deep_struct ArrayStride 8 ";
4006fd4e5da5Sopenharmony_ci  int depth = 255;
4007fd4e5da5Sopenharmony_ci  std::string header =
4008fd4e5da5Sopenharmony_ci      kGLSL450MemoryModel + arrayStride + kDeeplyNestedStructureSetup;
4009fd4e5da5Sopenharmony_ci  header.erase(header.find("%func"));
4010fd4e5da5Sopenharmony_ci  std::ostringstream spirv;
4011fd4e5da5Sopenharmony_ci  spirv << header << "\n";
4012fd4e5da5Sopenharmony_ci
4013fd4e5da5Sopenharmony_ci  // Build nested structures. Struct 'i' contains struct 'i-1'
4014fd4e5da5Sopenharmony_ci  spirv << "%s_depth_1 = OpTypeStruct %float\n";
4015fd4e5da5Sopenharmony_ci  for (int i = 2; i <= depth; ++i) {
4016fd4e5da5Sopenharmony_ci    spirv << "%s_depth_" << i << " = OpTypeStruct %s_depth_" << i - 1 << "\n";
4017fd4e5da5Sopenharmony_ci  }
4018fd4e5da5Sopenharmony_ci
4019fd4e5da5Sopenharmony_ci  // Define Pointer and Variable to use for the AccessChain instruction.
4020fd4e5da5Sopenharmony_ci  spirv << "%_ptr_Uniform_deep_struct = OpTypePointer Uniform %s_depth_"
4021fd4e5da5Sopenharmony_ci        << depth << "\n";
4022fd4e5da5Sopenharmony_ci  spirv << "%deep_var = OpVariable %_ptr_Uniform_deep_struct Uniform\n";
4023fd4e5da5Sopenharmony_ci
4024fd4e5da5Sopenharmony_ci  // Function Start
4025fd4e5da5Sopenharmony_ci  spirv << R"(
4026fd4e5da5Sopenharmony_ci  %func = OpFunction %void None %void_f
4027fd4e5da5Sopenharmony_ci  %my_label = OpLabel
4028fd4e5da5Sopenharmony_ci  )";
4029fd4e5da5Sopenharmony_ci
4030fd4e5da5Sopenharmony_ci  // AccessChain with 'n' indexes (n = depth)
4031fd4e5da5Sopenharmony_ci  spirv << "%entry = " << instr << " %_ptr_Uniform_float %deep_var" << elem;
4032fd4e5da5Sopenharmony_ci  for (int i = 0; i < depth; ++i) {
4033fd4e5da5Sopenharmony_ci    spirv << " %int_0";
4034fd4e5da5Sopenharmony_ci  }
4035fd4e5da5Sopenharmony_ci
4036fd4e5da5Sopenharmony_ci  // Function end
4037fd4e5da5Sopenharmony_ci  spirv << R"(
4038fd4e5da5Sopenharmony_ci    OpReturn
4039fd4e5da5Sopenharmony_ci    OpFunctionEnd
4040fd4e5da5Sopenharmony_ci  )";
4041fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.str());
4042fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
4043fd4e5da5Sopenharmony_ci}
4044fd4e5da5Sopenharmony_ci
4045fd4e5da5Sopenharmony_ci// Invalid: 256 indexes passed to the access chain instruction. Limit is 255.
4046fd4e5da5Sopenharmony_ciTEST_P(AccessChainInstructionTest, AccessChainTooManyIndexesBad) {
4047fd4e5da5Sopenharmony_ci  const std::string instr = GetParam();
4048fd4e5da5Sopenharmony_ci  const std::string elem = AccessChainRequiresElemId(instr) ? " %int_0 " : "";
4049fd4e5da5Sopenharmony_ci  std::ostringstream spirv;
4050fd4e5da5Sopenharmony_ci  spirv << kGLSL450MemoryModel << kDeeplyNestedStructureSetup;
4051fd4e5da5Sopenharmony_ci  spirv << "%entry = " << instr << " %_ptr_Private_float %my_matrix" << elem;
4052fd4e5da5Sopenharmony_ci  for (int i = 0; i < 256; ++i) {
4053fd4e5da5Sopenharmony_ci    spirv << " %int_0";
4054fd4e5da5Sopenharmony_ci  }
4055fd4e5da5Sopenharmony_ci  spirv << R"(
4056fd4e5da5Sopenharmony_ci    OpReturn
4057fd4e5da5Sopenharmony_ci    OpFunctionEnd
4058fd4e5da5Sopenharmony_ci  )";
4059fd4e5da5Sopenharmony_ci  const std::string expected_err = "The number of indexes in " + instr +
4060fd4e5da5Sopenharmony_ci                                   " may not exceed 255. Found 256 indexes.";
4061fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.str());
4062fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4063fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err));
4064fd4e5da5Sopenharmony_ci}
4065fd4e5da5Sopenharmony_ci
4066fd4e5da5Sopenharmony_ci// Valid: 10 indexes passed to the access chain instruction. (Custom limit: 10)
4067fd4e5da5Sopenharmony_ciTEST_P(AccessChainInstructionTest, CustomizedAccessChainTooManyIndexesGood) {
4068fd4e5da5Sopenharmony_ci  const std::string instr = GetParam();
4069fd4e5da5Sopenharmony_ci  const std::string elem = AccessChainRequiresElemId(instr) ? " %int_0 " : "";
4070fd4e5da5Sopenharmony_ci  const std::string arrayStride =
4071fd4e5da5Sopenharmony_ci      " OpDecorate %_ptr_Uniform_deep_struct ArrayStride 8 ";
4072fd4e5da5Sopenharmony_ci  int depth = 10;
4073fd4e5da5Sopenharmony_ci  std::string header =
4074fd4e5da5Sopenharmony_ci      kGLSL450MemoryModel + arrayStride + kDeeplyNestedStructureSetup;
4075fd4e5da5Sopenharmony_ci  header.erase(header.find("%func"));
4076fd4e5da5Sopenharmony_ci  std::ostringstream spirv;
4077fd4e5da5Sopenharmony_ci  spirv << header << "\n";
4078fd4e5da5Sopenharmony_ci
4079fd4e5da5Sopenharmony_ci  // Build nested structures. Struct 'i' contains struct 'i-1'
4080fd4e5da5Sopenharmony_ci  spirv << "%s_depth_1 = OpTypeStruct %float\n";
4081fd4e5da5Sopenharmony_ci  for (int i = 2; i <= depth; ++i) {
4082fd4e5da5Sopenharmony_ci    spirv << "%s_depth_" << i << " = OpTypeStruct %s_depth_" << i - 1 << "\n";
4083fd4e5da5Sopenharmony_ci  }
4084fd4e5da5Sopenharmony_ci
4085fd4e5da5Sopenharmony_ci  // Define Pointer and Variable to use for the AccessChain instruction.
4086fd4e5da5Sopenharmony_ci  spirv << "%_ptr_Uniform_deep_struct = OpTypePointer Uniform %s_depth_"
4087fd4e5da5Sopenharmony_ci        << depth << "\n";
4088fd4e5da5Sopenharmony_ci  spirv << "%deep_var = OpVariable %_ptr_Uniform_deep_struct Uniform\n";
4089fd4e5da5Sopenharmony_ci
4090fd4e5da5Sopenharmony_ci  // Function Start
4091fd4e5da5Sopenharmony_ci  spirv << R"(
4092fd4e5da5Sopenharmony_ci  %func = OpFunction %void None %void_f
4093fd4e5da5Sopenharmony_ci  %my_label = OpLabel
4094fd4e5da5Sopenharmony_ci  )";
4095fd4e5da5Sopenharmony_ci
4096fd4e5da5Sopenharmony_ci  // AccessChain with 'n' indexes (n = depth)
4097fd4e5da5Sopenharmony_ci  spirv << "%entry = " << instr << " %_ptr_Uniform_float %deep_var" << elem;
4098fd4e5da5Sopenharmony_ci  for (int i = 0; i < depth; ++i) {
4099fd4e5da5Sopenharmony_ci    spirv << " %int_0";
4100fd4e5da5Sopenharmony_ci  }
4101fd4e5da5Sopenharmony_ci
4102fd4e5da5Sopenharmony_ci  // Function end
4103fd4e5da5Sopenharmony_ci  spirv << R"(
4104fd4e5da5Sopenharmony_ci    OpReturn
4105fd4e5da5Sopenharmony_ci    OpFunctionEnd
4106fd4e5da5Sopenharmony_ci  )";
4107fd4e5da5Sopenharmony_ci
4108fd4e5da5Sopenharmony_ci  spvValidatorOptionsSetUniversalLimit(
4109fd4e5da5Sopenharmony_ci      options_, spv_validator_limit_max_access_chain_indexes, 10u);
4110fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.str());
4111fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
4112fd4e5da5Sopenharmony_ci}
4113fd4e5da5Sopenharmony_ci
4114fd4e5da5Sopenharmony_ci// Invalid: 11 indexes passed to the access chain instruction. Custom Limit:10
4115fd4e5da5Sopenharmony_ciTEST_P(AccessChainInstructionTest, CustomizedAccessChainTooManyIndexesBad) {
4116fd4e5da5Sopenharmony_ci  const std::string instr = GetParam();
4117fd4e5da5Sopenharmony_ci  const std::string elem = AccessChainRequiresElemId(instr) ? " %int_0 " : "";
4118fd4e5da5Sopenharmony_ci  std::ostringstream spirv;
4119fd4e5da5Sopenharmony_ci  spirv << kGLSL450MemoryModel << kDeeplyNestedStructureSetup;
4120fd4e5da5Sopenharmony_ci  spirv << "%entry = " << instr << " %_ptr_Private_float %my_matrix" << elem;
4121fd4e5da5Sopenharmony_ci  for (int i = 0; i < 11; ++i) {
4122fd4e5da5Sopenharmony_ci    spirv << " %int_0";
4123fd4e5da5Sopenharmony_ci  }
4124fd4e5da5Sopenharmony_ci  spirv << R"(
4125fd4e5da5Sopenharmony_ci    OpReturn
4126fd4e5da5Sopenharmony_ci    OpFunctionEnd
4127fd4e5da5Sopenharmony_ci  )";
4128fd4e5da5Sopenharmony_ci  const std::string expected_err = "The number of indexes in " + instr +
4129fd4e5da5Sopenharmony_ci                                   " may not exceed 10. Found 11 indexes.";
4130fd4e5da5Sopenharmony_ci  spvValidatorOptionsSetUniversalLimit(
4131fd4e5da5Sopenharmony_ci      options_, spv_validator_limit_max_access_chain_indexes, 10u);
4132fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.str());
4133fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4134fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err));
4135fd4e5da5Sopenharmony_ci}
4136fd4e5da5Sopenharmony_ci
4137fd4e5da5Sopenharmony_ci// Invalid: Index passed to the access chain instruction is float (must be
4138fd4e5da5Sopenharmony_ci// integer).
4139fd4e5da5Sopenharmony_ciTEST_P(AccessChainInstructionTest, AccessChainUndefinedIndexBad) {
4140fd4e5da5Sopenharmony_ci  const std::string instr = GetParam();
4141fd4e5da5Sopenharmony_ci  const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : "";
4142fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"(
4143fd4e5da5Sopenharmony_ci%entry = )" +
4144fd4e5da5Sopenharmony_ci                      instr + R"( %_ptr_Private_float %my_matrix )" + elem +
4145fd4e5da5Sopenharmony_ci                      R"(%float_0 %int_1
4146fd4e5da5Sopenharmony_ciOpReturn
4147fd4e5da5Sopenharmony_ciOpFunctionEnd
4148fd4e5da5Sopenharmony_ci  )";
4149fd4e5da5Sopenharmony_ci  const std::string expected_err =
4150fd4e5da5Sopenharmony_ci      "Indexes passed to " + instr + " must be of type integer.";
4151fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
4152fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4153fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err));
4154fd4e5da5Sopenharmony_ci}
4155fd4e5da5Sopenharmony_ci
4156fd4e5da5Sopenharmony_ci// Invalid: The index argument that indexes into a struct must be of type
4157fd4e5da5Sopenharmony_ci// OpConstant.
4158fd4e5da5Sopenharmony_ciTEST_P(AccessChainInstructionTest, AccessChainStructIndexNotConstantBad) {
4159fd4e5da5Sopenharmony_ci  const std::string instr = GetParam();
4160fd4e5da5Sopenharmony_ci  const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : "";
4161fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"(
4162fd4e5da5Sopenharmony_ci%f = )" +
4163fd4e5da5Sopenharmony_ci                      instr + R"( %_ptr_Uniform_float %blockName_var )" + elem +
4164fd4e5da5Sopenharmony_ci                      R"(%int_0 %spec_int %int_2
4165fd4e5da5Sopenharmony_ciOpReturn
4166fd4e5da5Sopenharmony_ciOpFunctionEnd
4167fd4e5da5Sopenharmony_ci  )";
4168fd4e5da5Sopenharmony_ci  const std::string expected_err =
4169fd4e5da5Sopenharmony_ci      "The <id> passed to " + instr +
4170fd4e5da5Sopenharmony_ci      " to index into a structure must be an OpConstant.";
4171fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
4172fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4173fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err));
4174fd4e5da5Sopenharmony_ci}
4175fd4e5da5Sopenharmony_ci
4176fd4e5da5Sopenharmony_ci// Invalid: Indexing up to a vec4 granularity, but result type expected float.
4177fd4e5da5Sopenharmony_ciTEST_P(AccessChainInstructionTest,
4178fd4e5da5Sopenharmony_ci       AccessChainStructResultTypeDoesntMatchIndexedTypeBad) {
4179fd4e5da5Sopenharmony_ci  const std::string instr = GetParam();
4180fd4e5da5Sopenharmony_ci  const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : "";
4181fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"(
4182fd4e5da5Sopenharmony_ci%entry = )" +
4183fd4e5da5Sopenharmony_ci                      instr + R"( %_ptr_Uniform_float %blockName_var )" + elem +
4184fd4e5da5Sopenharmony_ci                      R"(%int_0 %int_1 %int_2
4185fd4e5da5Sopenharmony_ciOpReturn
4186fd4e5da5Sopenharmony_ciOpFunctionEnd
4187fd4e5da5Sopenharmony_ci  )";
4188fd4e5da5Sopenharmony_ci  const std::string expected_err = instr +
4189fd4e5da5Sopenharmony_ci                                   " result type (OpTypeFloat) does not match "
4190fd4e5da5Sopenharmony_ci                                   "the type that results from indexing into "
4191fd4e5da5Sopenharmony_ci                                   "the base <id> (OpTypeVector).";
4192fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
4193fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4194fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err));
4195fd4e5da5Sopenharmony_ci}
4196fd4e5da5Sopenharmony_ci
4197fd4e5da5Sopenharmony_ci// Invalid: Reach non-composite type (bool) when unused indexes remain.
4198fd4e5da5Sopenharmony_ciTEST_P(AccessChainInstructionTest, AccessChainStructTooManyIndexesBad) {
4199fd4e5da5Sopenharmony_ci  const std::string instr = GetParam();
4200fd4e5da5Sopenharmony_ci  const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : "";
4201fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"(
4202fd4e5da5Sopenharmony_ci%entry = )" +
4203fd4e5da5Sopenharmony_ci                      instr + R"( %_ptr_Uniform_float %blockName_var )" + elem +
4204fd4e5da5Sopenharmony_ci                      R"(%int_0 %int_2 %int_2
4205fd4e5da5Sopenharmony_ciOpReturn
4206fd4e5da5Sopenharmony_ciOpFunctionEnd
4207fd4e5da5Sopenharmony_ci  )";
4208fd4e5da5Sopenharmony_ci  const std::string expected_err = instr +
4209fd4e5da5Sopenharmony_ci                                   " reached non-composite type while "
4210fd4e5da5Sopenharmony_ci                                   "indexes still remain to be traversed.";
4211fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
4212fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4213fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err));
4214fd4e5da5Sopenharmony_ci}
4215fd4e5da5Sopenharmony_ci
4216fd4e5da5Sopenharmony_ci// Invalid: Trying to find index 3 of the struct that has only 3 members.
4217fd4e5da5Sopenharmony_ciTEST_P(AccessChainInstructionTest, AccessChainStructIndexOutOfBoundBad) {
4218fd4e5da5Sopenharmony_ci  const std::string instr = GetParam();
4219fd4e5da5Sopenharmony_ci  const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : "";
4220fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"(
4221fd4e5da5Sopenharmony_ci%entry = )" +
4222fd4e5da5Sopenharmony_ci                      instr + R"( %_ptr_Uniform_float %blockName_var )" + elem +
4223fd4e5da5Sopenharmony_ci                      R"(%int_3 %int_2 %int_2
4224fd4e5da5Sopenharmony_ciOpReturn
4225fd4e5da5Sopenharmony_ciOpFunctionEnd
4226fd4e5da5Sopenharmony_ci  )";
4227fd4e5da5Sopenharmony_ci  const std::string expected_err = "Index is out of bounds: " + instr +
4228fd4e5da5Sopenharmony_ci                                   " can not find index 3 into the structure "
4229fd4e5da5Sopenharmony_ci                                   "<id> '25[%_struct_25]'. This structure "
4230fd4e5da5Sopenharmony_ci                                   "has 3 members. Largest valid index is 2.";
4231fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
4232fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4233fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err));
4234fd4e5da5Sopenharmony_ci}
4235fd4e5da5Sopenharmony_ci
4236fd4e5da5Sopenharmony_ci// Valid: Tests that we can index into Struct, Array, Matrix, and Vector!
4237fd4e5da5Sopenharmony_ciTEST_P(AccessChainInstructionTest, AccessChainIndexIntoAllTypesGood) {
4238fd4e5da5Sopenharmony_ci  // indexes that we are passing are: 0, 3, 1, 2, 0
4239fd4e5da5Sopenharmony_ci  // 0 will select the struct_s within the base struct (blockName)
4240fd4e5da5Sopenharmony_ci  // 3 will select the Array that contains 5 matrices
4241fd4e5da5Sopenharmony_ci  // 1 will select the Matrix that is at index 1 of the array
4242fd4e5da5Sopenharmony_ci  // 2 will select the column (which is a vector) within the matrix at index 2
4243fd4e5da5Sopenharmony_ci  // 0 will select the element at the index 0 of the vector. (which is a float).
4244fd4e5da5Sopenharmony_ci  const std::string instr = GetParam();
4245fd4e5da5Sopenharmony_ci  const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : "";
4246fd4e5da5Sopenharmony_ci  const std::string arrayStride =
4247fd4e5da5Sopenharmony_ci      " OpDecorate %_ptr_Uniform_blockName ArrayStride 8 ";
4248fd4e5da5Sopenharmony_ci  std::ostringstream spirv;
4249fd4e5da5Sopenharmony_ci  spirv << kGLSL450MemoryModel << arrayStride << kDeeplyNestedStructureSetup
4250fd4e5da5Sopenharmony_ci        << std::endl;
4251fd4e5da5Sopenharmony_ci  spirv << "%ss = " << instr << " %_ptr_Uniform_struct_s %blockName_var "
4252fd4e5da5Sopenharmony_ci        << elem << "%int_0" << std::endl;
4253fd4e5da5Sopenharmony_ci  spirv << "%sa = " << instr << " %_ptr_Uniform_array5_mat4x3 %blockName_var "
4254fd4e5da5Sopenharmony_ci        << elem << "%int_0 %int_3" << std::endl;
4255fd4e5da5Sopenharmony_ci  spirv << "%sm = " << instr << " %_ptr_Uniform_mat4x3 %blockName_var " << elem
4256fd4e5da5Sopenharmony_ci        << "%int_0 %int_3 %int_1" << std::endl;
4257fd4e5da5Sopenharmony_ci  spirv << "%sc = " << instr << " %_ptr_Uniform_v3float %blockName_var " << elem
4258fd4e5da5Sopenharmony_ci        << "%int_0 %int_3 %int_1 %int_2" << std::endl;
4259fd4e5da5Sopenharmony_ci  spirv << "%entry = " << instr << " %_ptr_Uniform_float %blockName_var "
4260fd4e5da5Sopenharmony_ci        << elem << "%int_0 %int_3 %int_1 %int_2 %int_0" << std::endl;
4261fd4e5da5Sopenharmony_ci  spirv << R"(
4262fd4e5da5Sopenharmony_ciOpReturn
4263fd4e5da5Sopenharmony_ciOpFunctionEnd
4264fd4e5da5Sopenharmony_ci  )";
4265fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.str());
4266fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
4267fd4e5da5Sopenharmony_ci}
4268fd4e5da5Sopenharmony_ci
4269fd4e5da5Sopenharmony_ci// Valid: Access an element of OpTypeRuntimeArray.
4270fd4e5da5Sopenharmony_ciTEST_P(AccessChainInstructionTest, AccessChainIndexIntoRuntimeArrayGood) {
4271fd4e5da5Sopenharmony_ci  const std::string instr = GetParam();
4272fd4e5da5Sopenharmony_ci  const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : "";
4273fd4e5da5Sopenharmony_ci  const std::string arrayStride =
4274fd4e5da5Sopenharmony_ci      " OpDecorate %_ptr_Uniform_blockName ArrayStride 8 ";
4275fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + arrayStride +
4276fd4e5da5Sopenharmony_ci                      kDeeplyNestedStructureSetup + R"(
4277fd4e5da5Sopenharmony_ci%runtime_arr_entry = )" + instr +
4278fd4e5da5Sopenharmony_ci                      R"( %_ptr_Uniform_float %blockName_var )" + elem +
4279fd4e5da5Sopenharmony_ci                      R"(%int_2 %int_0
4280fd4e5da5Sopenharmony_ciOpReturn
4281fd4e5da5Sopenharmony_ciOpFunctionEnd
4282fd4e5da5Sopenharmony_ci  )";
4283fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
4284fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
4285fd4e5da5Sopenharmony_ci}
4286fd4e5da5Sopenharmony_ci
4287fd4e5da5Sopenharmony_ci// Invalid: Unused index when accessing OpTypeRuntimeArray.
4288fd4e5da5Sopenharmony_ciTEST_P(AccessChainInstructionTest, AccessChainIndexIntoRuntimeArrayBad) {
4289fd4e5da5Sopenharmony_ci  const std::string instr = GetParam();
4290fd4e5da5Sopenharmony_ci  const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : "";
4291fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"(
4292fd4e5da5Sopenharmony_ci%runtime_arr_entry = )" +
4293fd4e5da5Sopenharmony_ci                      instr + R"( %_ptr_Uniform_float %blockName_var )" + elem +
4294fd4e5da5Sopenharmony_ci                      R"(%int_2 %int_0 %int_1
4295fd4e5da5Sopenharmony_ciOpReturn
4296fd4e5da5Sopenharmony_ciOpFunctionEnd
4297fd4e5da5Sopenharmony_ci  )";
4298fd4e5da5Sopenharmony_ci  const std::string expected_err =
4299fd4e5da5Sopenharmony_ci      instr +
4300fd4e5da5Sopenharmony_ci      " reached non-composite type while indexes still remain to be traversed.";
4301fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
4302fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4303fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err));
4304fd4e5da5Sopenharmony_ci}
4305fd4e5da5Sopenharmony_ci
4306fd4e5da5Sopenharmony_ci// Invalid: Reached scalar type before arguments to the access chain instruction
4307fd4e5da5Sopenharmony_ci// finished.
4308fd4e5da5Sopenharmony_ciTEST_P(AccessChainInstructionTest, AccessChainMatrixMoreArgsThanNeededBad) {
4309fd4e5da5Sopenharmony_ci  const std::string instr = GetParam();
4310fd4e5da5Sopenharmony_ci  const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : "";
4311fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"(
4312fd4e5da5Sopenharmony_ci%entry = )" +
4313fd4e5da5Sopenharmony_ci                      instr + R"( %_ptr_Private_float %my_matrix )" + elem +
4314fd4e5da5Sopenharmony_ci                      R"(%int_0 %int_1 %int_0
4315fd4e5da5Sopenharmony_ciOpReturn
4316fd4e5da5Sopenharmony_ciOpFunctionEnd
4317fd4e5da5Sopenharmony_ci  )";
4318fd4e5da5Sopenharmony_ci  const std::string expected_err = instr +
4319fd4e5da5Sopenharmony_ci                                   " reached non-composite type while "
4320fd4e5da5Sopenharmony_ci                                   "indexes still remain to be traversed.";
4321fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
4322fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4323fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err));
4324fd4e5da5Sopenharmony_ci}
4325fd4e5da5Sopenharmony_ci
4326fd4e5da5Sopenharmony_ci// Invalid: The result type and the type indexed into do not match.
4327fd4e5da5Sopenharmony_ciTEST_P(AccessChainInstructionTest,
4328fd4e5da5Sopenharmony_ci       AccessChainResultTypeDoesntMatchIndexedTypeBad) {
4329fd4e5da5Sopenharmony_ci  const std::string instr = GetParam();
4330fd4e5da5Sopenharmony_ci  const std::string elem = AccessChainRequiresElemId(instr) ? "%int_0 " : "";
4331fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + kDeeplyNestedStructureSetup + R"(
4332fd4e5da5Sopenharmony_ci%entry = )" +
4333fd4e5da5Sopenharmony_ci                      instr + R"( %_ptr_Private_mat4x3 %my_matrix )" + elem +
4334fd4e5da5Sopenharmony_ci                      R"(%int_0 %int_1
4335fd4e5da5Sopenharmony_ciOpReturn
4336fd4e5da5Sopenharmony_ciOpFunctionEnd
4337fd4e5da5Sopenharmony_ci  )";
4338fd4e5da5Sopenharmony_ci  const std::string expected_err = instr +
4339fd4e5da5Sopenharmony_ci                                   " result type (OpTypeMatrix) does not match "
4340fd4e5da5Sopenharmony_ci                                   "the type that results from indexing into "
4341fd4e5da5Sopenharmony_ci                                   "the base <id> (OpTypeFloat).";
4342fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
4343fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4344fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(), HasSubstr(expected_err));
4345fd4e5da5Sopenharmony_ci}
4346fd4e5da5Sopenharmony_ci
4347fd4e5da5Sopenharmony_ci// Run tests for Access Chain Instructions.
4348fd4e5da5Sopenharmony_ciINSTANTIATE_TEST_SUITE_P(
4349fd4e5da5Sopenharmony_ci    CheckAccessChainInstructions, AccessChainInstructionTest,
4350fd4e5da5Sopenharmony_ci    ::testing::Values("OpAccessChain", "OpInBoundsAccessChain",
4351fd4e5da5Sopenharmony_ci                      "OpPtrAccessChain", "OpInBoundsPtrAccessChain"));
4352fd4e5da5Sopenharmony_ci
4353fd4e5da5Sopenharmony_ci// TODO: OpArrayLength
4354fd4e5da5Sopenharmony_ci// TODO: OpImagePointer
4355fd4e5da5Sopenharmony_ci// TODO: OpGenericPtrMemSemantics
4356fd4e5da5Sopenharmony_ci
4357fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpFunctionGood) {
4358fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
4359fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
4360fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
4361fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %1 %2 %2
4362fd4e5da5Sopenharmony_ci%4 = OpFunction %1 None %3
4363fd4e5da5Sopenharmony_ci%5 = OpLabel
4364fd4e5da5Sopenharmony_ci     OpReturn
4365fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
4366fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
4367fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
4368fd4e5da5Sopenharmony_ci}
4369fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpFunctionResultTypeBad) {
4370fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
4371fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
4372fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
4373fd4e5da5Sopenharmony_ci%3 = OpConstant %2 42
4374fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %1 %2 %2
4375fd4e5da5Sopenharmony_ci%5 = OpFunction %2 None %4
4376fd4e5da5Sopenharmony_ci%6 = OpLabel
4377fd4e5da5Sopenharmony_ci     OpReturnValue %3
4378fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
4379fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
4380fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4381fd4e5da5Sopenharmony_ci  EXPECT_THAT(
4382fd4e5da5Sopenharmony_ci      getDiagnosticString(),
4383fd4e5da5Sopenharmony_ci      HasSubstr(make_message("OpFunction Result Type <id> '2[%uint]' does not "
4384fd4e5da5Sopenharmony_ci                             "match the Function Type's return type <id> "
4385fd4e5da5Sopenharmony_ci                             "'1[%void]'.")));
4386fd4e5da5Sopenharmony_ci}
4387fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpReturnValueTypeBad) {
4388fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
4389fd4e5da5Sopenharmony_ci%1 = OpTypeInt 32 0
4390fd4e5da5Sopenharmony_ci%2 = OpTypeFloat 32
4391fd4e5da5Sopenharmony_ci%3 = OpConstant %2 0
4392fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %1
4393fd4e5da5Sopenharmony_ci%5 = OpFunction %1 None %4
4394fd4e5da5Sopenharmony_ci%6 = OpLabel
4395fd4e5da5Sopenharmony_ci     OpReturnValue %3
4396fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
4397fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
4398fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4399fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
4400fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
4401fd4e5da5Sopenharmony_ci                  "OpReturnValue Value <id> '3[%float_0]'s type does "
4402fd4e5da5Sopenharmony_ci                  "not match OpFunction's return type.")));
4403fd4e5da5Sopenharmony_ci}
4404fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpFunctionFunctionTypeBad) {
4405fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
4406fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
4407fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
4408fd4e5da5Sopenharmony_ci%4 = OpFunction %1 None %2
4409fd4e5da5Sopenharmony_ci%5 = OpLabel
4410fd4e5da5Sopenharmony_ci     OpReturn
4411fd4e5da5Sopenharmony_ciOpFunctionEnd)";
4412fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
4413fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4414fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
4415fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
4416fd4e5da5Sopenharmony_ci                  "OpFunction Function Type <id> '2[%uint]' is not a function "
4417fd4e5da5Sopenharmony_ci                  "type.")));
4418fd4e5da5Sopenharmony_ci}
4419fd4e5da5Sopenharmony_ci
4420fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpFunctionUseBad) {
4421fd4e5da5Sopenharmony_ci  const std::string spirv = kGLSL450MemoryModel + R"(
4422fd4e5da5Sopenharmony_ci%1 = OpTypeFloat 32
4423fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %1
4424fd4e5da5Sopenharmony_ci%3 = OpFunction %1 None %2
4425fd4e5da5Sopenharmony_ci%4 = OpLabel
4426fd4e5da5Sopenharmony_ciOpReturnValue %3
4427fd4e5da5Sopenharmony_ciOpFunctionEnd
4428fd4e5da5Sopenharmony_ci)";
4429fd4e5da5Sopenharmony_ci
4430fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
4431fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4432fd4e5da5Sopenharmony_ci  EXPECT_THAT(
4433fd4e5da5Sopenharmony_ci      getDiagnosticString(),
4434fd4e5da5Sopenharmony_ci      HasSubstr(make_message("Invalid use of function result id '3[%3]'.")));
4435fd4e5da5Sopenharmony_ci}
4436fd4e5da5Sopenharmony_ci
4437fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpFunctionParameterGood) {
4438fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
4439fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
4440fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
4441fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %1 %2
4442fd4e5da5Sopenharmony_ci%4 = OpFunction %1 None %3
4443fd4e5da5Sopenharmony_ci%5 = OpFunctionParameter %2
4444fd4e5da5Sopenharmony_ci%6 = OpLabel
4445fd4e5da5Sopenharmony_ci     OpReturn
4446fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
4447fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
4448fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
4449fd4e5da5Sopenharmony_ci}
4450fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpFunctionParameterMultipleGood) {
4451fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
4452fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
4453fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
4454fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %1 %2 %2
4455fd4e5da5Sopenharmony_ci%4 = OpFunction %1 None %3
4456fd4e5da5Sopenharmony_ci%5 = OpFunctionParameter %2
4457fd4e5da5Sopenharmony_ci%6 = OpFunctionParameter %2
4458fd4e5da5Sopenharmony_ci%7 = OpLabel
4459fd4e5da5Sopenharmony_ci     OpReturn
4460fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
4461fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
4462fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
4463fd4e5da5Sopenharmony_ci}
4464fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpFunctionParameterResultTypeBad) {
4465fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
4466fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
4467fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
4468fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %1 %2
4469fd4e5da5Sopenharmony_ci%4 = OpFunction %1 None %3
4470fd4e5da5Sopenharmony_ci%5 = OpFunctionParameter %1
4471fd4e5da5Sopenharmony_ci%6 = OpLabel
4472fd4e5da5Sopenharmony_ci     OpReturn
4473fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
4474fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
4475fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4476fd4e5da5Sopenharmony_ci  EXPECT_THAT(
4477fd4e5da5Sopenharmony_ci      getDiagnosticString(),
4478fd4e5da5Sopenharmony_ci      HasSubstr(make_message(
4479fd4e5da5Sopenharmony_ci          "OpFunctionParameter Result Type <id> '1[%void]' does not "
4480fd4e5da5Sopenharmony_ci          "match the OpTypeFunction parameter type of the same index.")));
4481fd4e5da5Sopenharmony_ci}
4482fd4e5da5Sopenharmony_ci
4483fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpFunctionCallGood) {
4484fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
4485fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
4486fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
4487fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %2 %2
4488fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %1
4489fd4e5da5Sopenharmony_ci%5 = OpConstant %2 42 ;21
4490fd4e5da5Sopenharmony_ci
4491fd4e5da5Sopenharmony_ci%6 = OpFunction %2 None %3
4492fd4e5da5Sopenharmony_ci%7 = OpFunctionParameter %2
4493fd4e5da5Sopenharmony_ci%8 = OpLabel
4494fd4e5da5Sopenharmony_ci     OpReturnValue %7
4495fd4e5da5Sopenharmony_ci     OpFunctionEnd
4496fd4e5da5Sopenharmony_ci
4497fd4e5da5Sopenharmony_ci%10 = OpFunction %1 None %4
4498fd4e5da5Sopenharmony_ci%11 = OpLabel
4499fd4e5da5Sopenharmony_ci%12 = OpFunctionCall %2 %6 %5
4500fd4e5da5Sopenharmony_ci      OpReturn
4501fd4e5da5Sopenharmony_ci      OpFunctionEnd)";
4502fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
4503fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
4504fd4e5da5Sopenharmony_ci}
4505fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpFunctionCallResultTypeBad) {
4506fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
4507fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
4508fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
4509fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %2 %2
4510fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %1
4511fd4e5da5Sopenharmony_ci%5 = OpConstant %2 42 ;21
4512fd4e5da5Sopenharmony_ci
4513fd4e5da5Sopenharmony_ci%6 = OpFunction %2 None %3
4514fd4e5da5Sopenharmony_ci%7 = OpFunctionParameter %2
4515fd4e5da5Sopenharmony_ci%8 = OpLabel
4516fd4e5da5Sopenharmony_ci%9 = OpIAdd %2 %7 %7
4517fd4e5da5Sopenharmony_ci     OpReturnValue %9
4518fd4e5da5Sopenharmony_ci     OpFunctionEnd
4519fd4e5da5Sopenharmony_ci
4520fd4e5da5Sopenharmony_ci%10 = OpFunction %1 None %4
4521fd4e5da5Sopenharmony_ci%11 = OpLabel
4522fd4e5da5Sopenharmony_ci%12 = OpFunctionCall %1 %6 %5
4523fd4e5da5Sopenharmony_ci      OpReturn
4524fd4e5da5Sopenharmony_ci      OpFunctionEnd)";
4525fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
4526fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4527fd4e5da5Sopenharmony_ci  EXPECT_THAT(
4528fd4e5da5Sopenharmony_ci      getDiagnosticString(),
4529fd4e5da5Sopenharmony_ci      HasSubstr(make_message("OpFunctionCall Result Type <id> '1[%void]'s type "
4530fd4e5da5Sopenharmony_ci                             "does not match Function <id> '2[%uint]'s return "
4531fd4e5da5Sopenharmony_ci                             "type.")));
4532fd4e5da5Sopenharmony_ci}
4533fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpFunctionCallFunctionBad) {
4534fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
4535fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
4536fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
4537fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %2 %2
4538fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %1
4539fd4e5da5Sopenharmony_ci%5 = OpConstant %2 42 ;21
4540fd4e5da5Sopenharmony_ci
4541fd4e5da5Sopenharmony_ci%10 = OpFunction %1 None %4
4542fd4e5da5Sopenharmony_ci%11 = OpLabel
4543fd4e5da5Sopenharmony_ci%12 = OpFunctionCall %2 %5 %5
4544fd4e5da5Sopenharmony_ci      OpReturn
4545fd4e5da5Sopenharmony_ci      OpFunctionEnd)";
4546fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
4547fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4548fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
4549fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
4550fd4e5da5Sopenharmony_ci                  "OpFunctionCall Function <id> '5[%uint_42]' is not a "
4551fd4e5da5Sopenharmony_ci                  "function.")));
4552fd4e5da5Sopenharmony_ci}
4553fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpFunctionCallArgumentTypeBad) {
4554fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
4555fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
4556fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
4557fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %2 %2
4558fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %1
4559fd4e5da5Sopenharmony_ci%5 = OpConstant %2 42
4560fd4e5da5Sopenharmony_ci
4561fd4e5da5Sopenharmony_ci%13 = OpTypeFloat 32
4562fd4e5da5Sopenharmony_ci%14 = OpConstant %13 3.14
4563fd4e5da5Sopenharmony_ci
4564fd4e5da5Sopenharmony_ci%6 = OpFunction %2 None %3
4565fd4e5da5Sopenharmony_ci%7 = OpFunctionParameter %2
4566fd4e5da5Sopenharmony_ci%8 = OpLabel
4567fd4e5da5Sopenharmony_ci%9 = OpIAdd %2 %7 %7
4568fd4e5da5Sopenharmony_ci     OpReturnValue %9
4569fd4e5da5Sopenharmony_ci     OpFunctionEnd
4570fd4e5da5Sopenharmony_ci
4571fd4e5da5Sopenharmony_ci%10 = OpFunction %1 None %4
4572fd4e5da5Sopenharmony_ci%11 = OpLabel
4573fd4e5da5Sopenharmony_ci%12 = OpFunctionCall %2 %6 %14
4574fd4e5da5Sopenharmony_ci      OpReturn
4575fd4e5da5Sopenharmony_ci      OpFunctionEnd)";
4576fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
4577fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4578fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
4579fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
4580fd4e5da5Sopenharmony_ci                  "OpFunctionCall Argument <id> '7[%float_3_1400001]'s "
4581fd4e5da5Sopenharmony_ci                  "type does not match Function <id> '2[%uint]'s "
4582fd4e5da5Sopenharmony_ci                  "parameter type.")));
4583fd4e5da5Sopenharmony_ci}
4584fd4e5da5Sopenharmony_ci
4585fd4e5da5Sopenharmony_ci// Valid: OpSampledImage result <id> is used in the same block by
4586fd4e5da5Sopenharmony_ci// OpImageSampleImplictLod
4587fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpSampledImageGood) {
4588fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + sampledImageSetup + R"(
4589fd4e5da5Sopenharmony_ci%smpld_img = OpSampledImage %sampled_image_type %image_inst %sampler_inst
4590fd4e5da5Sopenharmony_ci%si_lod    = OpImageSampleImplicitLod %v4float %smpld_img %const_vec_1_1
4591fd4e5da5Sopenharmony_ci    OpReturn
4592fd4e5da5Sopenharmony_ci    OpFunctionEnd)";
4593fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
4594fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
4595fd4e5da5Sopenharmony_ci}
4596fd4e5da5Sopenharmony_ci
4597fd4e5da5Sopenharmony_ci// Invalid: OpSampledImage result <id> is defined in one block and used in a
4598fd4e5da5Sopenharmony_ci// different block.
4599fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpSampledImageUsedInDifferentBlockBad) {
4600fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + sampledImageSetup + R"(
4601fd4e5da5Sopenharmony_ci%smpld_img = OpSampledImage %sampled_image_type %image_inst %sampler_inst
4602fd4e5da5Sopenharmony_ciOpBranch %label_2
4603fd4e5da5Sopenharmony_ci%label_2 = OpLabel
4604fd4e5da5Sopenharmony_ci%si_lod  = OpImageSampleImplicitLod %v4float %smpld_img %const_vec_1_1
4605fd4e5da5Sopenharmony_ciOpReturn
4606fd4e5da5Sopenharmony_ciOpFunctionEnd)";
4607fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
4608fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4609fd4e5da5Sopenharmony_ci  EXPECT_THAT(
4610fd4e5da5Sopenharmony_ci      getDiagnosticString(),
4611fd4e5da5Sopenharmony_ci      HasSubstr(make_message(
4612fd4e5da5Sopenharmony_ci          "All OpSampledImage instructions must be in the same block in "
4613fd4e5da5Sopenharmony_ci          "which their Result <id> are consumed. OpSampledImage Result "
4614fd4e5da5Sopenharmony_ci          "Type <id> '23[%23]' has a consumer in a different basic "
4615fd4e5da5Sopenharmony_ci          "block. The consumer instruction <id> is '25[%25]'.")));
4616fd4e5da5Sopenharmony_ci}
4617fd4e5da5Sopenharmony_ci
4618fd4e5da5Sopenharmony_ci// Invalid: OpSampledImage result <id> is used by OpSelect
4619fd4e5da5Sopenharmony_ci// Note: According to the Spec, OpSelect parameters must be either a scalar or a
4620fd4e5da5Sopenharmony_ci// vector. Therefore, OpTypeSampledImage is an illegal parameter for OpSelect.
4621fd4e5da5Sopenharmony_ci// However, the OpSelect validation does not catch this today. Therefore, it is
4622fd4e5da5Sopenharmony_ci// caught by the OpSampledImage validation. If the OpSelect validation code is
4623fd4e5da5Sopenharmony_ci// updated, the error message for this test may change.
4624fd4e5da5Sopenharmony_ci//
4625fd4e5da5Sopenharmony_ci// Disabled since OpSelect catches this now.
4626fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, DISABLED_OpSampledImageUsedInOpSelectBad) {
4627fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + sampledImageSetup + R"(
4628fd4e5da5Sopenharmony_ci%smpld_img  = OpSampledImage %sampled_image_type %image_inst %sampler_inst
4629fd4e5da5Sopenharmony_ci%select_img = OpSelect %sampled_image_type %spec_true %smpld_img %smpld_img
4630fd4e5da5Sopenharmony_ciOpReturn
4631fd4e5da5Sopenharmony_ciOpFunctionEnd)";
4632fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
4633fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4634fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
4635fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
4636fd4e5da5Sopenharmony_ci                  "Result <id> from OpSampledImage instruction must not "
4637fd4e5da5Sopenharmony_ci                  "appear as operands of OpSelect. Found result <id> "
4638fd4e5da5Sopenharmony_ci                  "'23' as an operand of <id> '24'.")));
4639fd4e5da5Sopenharmony_ci}
4640fd4e5da5Sopenharmony_ci
4641fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpCopyObjectSampledImageGood) {
4642fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + sampledImageSetup + R"(
4643fd4e5da5Sopenharmony_ci%smpld_img  = OpSampledImage %sampled_image_type %image_inst %sampler_inst
4644fd4e5da5Sopenharmony_ci%smpld_img2 = OpCopyObject %sampled_image_type %smpld_img
4645fd4e5da5Sopenharmony_ci%image_inst2 = OpCopyObject %image_type %image_inst
4646fd4e5da5Sopenharmony_ciOpReturn
4647fd4e5da5Sopenharmony_ciOpFunctionEnd)";
4648fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
4649fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
4650fd4e5da5Sopenharmony_ci}
4651fd4e5da5Sopenharmony_ci
4652fd4e5da5Sopenharmony_ci// Valid: Get a float in a matrix using CompositeExtract.
4653fd4e5da5Sopenharmony_ci// Valid: Insert float into a matrix using CompositeInsert.
4654fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, CompositeExtractInsertGood) {
4655fd4e5da5Sopenharmony_ci  std::ostringstream spirv;
4656fd4e5da5Sopenharmony_ci  spirv << kGLSL450MemoryModel << kDeeplyNestedStructureSetup << std::endl;
4657fd4e5da5Sopenharmony_ci  spirv << "%matrix = OpLoad %mat4x3 %my_matrix" << std::endl;
4658fd4e5da5Sopenharmony_ci  spirv << "%float_entry = OpCompositeExtract  %float %matrix 0 1" << std::endl;
4659fd4e5da5Sopenharmony_ci
4660fd4e5da5Sopenharmony_ci  // To test CompositeInsert, insert the object back in after extraction.
4661fd4e5da5Sopenharmony_ci  spirv << "%new_composite = OpCompositeInsert %mat4x3 %float_entry %matrix 0 1"
4662fd4e5da5Sopenharmony_ci        << std::endl;
4663fd4e5da5Sopenharmony_ci  spirv << R"(OpReturn
4664fd4e5da5Sopenharmony_ci              OpFunctionEnd)";
4665fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.str());
4666fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
4667fd4e5da5Sopenharmony_ci}
4668fd4e5da5Sopenharmony_ci
4669fd4e5da5Sopenharmony_ci#if 0
4670fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpFunctionCallArgumentCountBar) {
4671fd4e5da5Sopenharmony_ci  const char *spirv = R"(
4672fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
4673fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
4674fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %2 %2
4675fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %1
4676fd4e5da5Sopenharmony_ci%5 = OpConstant %2 42 ;21
4677fd4e5da5Sopenharmony_ci
4678fd4e5da5Sopenharmony_ci%6 = OpFunction %2 None %3
4679fd4e5da5Sopenharmony_ci%7 = OpFunctionParameter %2
4680fd4e5da5Sopenharmony_ci%8 = OpLabel
4681fd4e5da5Sopenharmony_ci%9 = OpLoad %2 %7
4682fd4e5da5Sopenharmony_ci     OpReturnValue %9
4683fd4e5da5Sopenharmony_ci     OpFunctionEnd
4684fd4e5da5Sopenharmony_ci
4685fd4e5da5Sopenharmony_ci%10 = OpFunction %1 None %4
4686fd4e5da5Sopenharmony_ci%11 = OpLabel
4687fd4e5da5Sopenharmony_ci      OpReturn
4688fd4e5da5Sopenharmony_ci%12 = OpFunctionCall %2 %6 %5
4689fd4e5da5Sopenharmony_ci      OpFunctionEnd)";
4690fd4e5da5Sopenharmony_ci  CHECK(spirv, SPV_ERROR_INVALID_ID);
4691fd4e5da5Sopenharmony_ci}
4692fd4e5da5Sopenharmony_ci#endif
4693fd4e5da5Sopenharmony_ci
4694fd4e5da5Sopenharmony_ci// TODO: The many things that changed with how images are used.
4695fd4e5da5Sopenharmony_ci// TODO: OpTextureSample
4696fd4e5da5Sopenharmony_ci// TODO: OpTextureSampleDref
4697fd4e5da5Sopenharmony_ci// TODO: OpTextureSampleLod
4698fd4e5da5Sopenharmony_ci// TODO: OpTextureSampleProj
4699fd4e5da5Sopenharmony_ci// TODO: OpTextureSampleGrad
4700fd4e5da5Sopenharmony_ci// TODO: OpTextureSampleOffset
4701fd4e5da5Sopenharmony_ci// TODO: OpTextureSampleProjLod
4702fd4e5da5Sopenharmony_ci// TODO: OpTextureSampleProjGrad
4703fd4e5da5Sopenharmony_ci// TODO: OpTextureSampleLodOffset
4704fd4e5da5Sopenharmony_ci// TODO: OpTextureSampleProjOffset
4705fd4e5da5Sopenharmony_ci// TODO: OpTextureSampleGradOffset
4706fd4e5da5Sopenharmony_ci// TODO: OpTextureSampleProjLodOffset
4707fd4e5da5Sopenharmony_ci// TODO: OpTextureSampleProjGradOffset
4708fd4e5da5Sopenharmony_ci// TODO: OpTextureFetchTexelLod
4709fd4e5da5Sopenharmony_ci// TODO: OpTextureFetchTexelOffset
4710fd4e5da5Sopenharmony_ci// TODO: OpTextureFetchSample
4711fd4e5da5Sopenharmony_ci// TODO: OpTextureFetchTexel
4712fd4e5da5Sopenharmony_ci// TODO: OpTextureGather
4713fd4e5da5Sopenharmony_ci// TODO: OpTextureGatherOffset
4714fd4e5da5Sopenharmony_ci// TODO: OpTextureGatherOffsets
4715fd4e5da5Sopenharmony_ci// TODO: OpTextureQuerySizeLod
4716fd4e5da5Sopenharmony_ci// TODO: OpTextureQuerySize
4717fd4e5da5Sopenharmony_ci// TODO: OpTextureQueryLevels
4718fd4e5da5Sopenharmony_ci// TODO: OpTextureQuerySamples
4719fd4e5da5Sopenharmony_ci// TODO: OpConvertUToF
4720fd4e5da5Sopenharmony_ci// TODO: OpConvertFToS
4721fd4e5da5Sopenharmony_ci// TODO: OpConvertSToF
4722fd4e5da5Sopenharmony_ci// TODO: OpConvertUToF
4723fd4e5da5Sopenharmony_ci// TODO: OpUConvert
4724fd4e5da5Sopenharmony_ci// TODO: OpSConvert
4725fd4e5da5Sopenharmony_ci// TODO: OpFConvert
4726fd4e5da5Sopenharmony_ci// TODO: OpConvertPtrToU
4727fd4e5da5Sopenharmony_ci// TODO: OpConvertUToPtr
4728fd4e5da5Sopenharmony_ci// TODO: OpPtrCastToGeneric
4729fd4e5da5Sopenharmony_ci// TODO: OpGenericCastToPtr
4730fd4e5da5Sopenharmony_ci// TODO: OpBitcast
4731fd4e5da5Sopenharmony_ci// TODO: OpGenericCastToPtrExplicit
4732fd4e5da5Sopenharmony_ci// TODO: OpSatConvertSToU
4733fd4e5da5Sopenharmony_ci// TODO: OpSatConvertUToS
4734fd4e5da5Sopenharmony_ci// TODO: OpVectorExtractDynamic
4735fd4e5da5Sopenharmony_ci// TODO: OpVectorInsertDynamic
4736fd4e5da5Sopenharmony_ci
4737fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpVectorShuffleIntGood) {
4738fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
4739fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
4740fd4e5da5Sopenharmony_ci%ivec3 = OpTypeVector %int 3
4741fd4e5da5Sopenharmony_ci%ivec4 = OpTypeVector %int 4
4742fd4e5da5Sopenharmony_ci%ptr_ivec3 = OpTypePointer Function %ivec3
4743fd4e5da5Sopenharmony_ci%undef = OpUndef %ivec4
4744fd4e5da5Sopenharmony_ci%int_42 = OpConstant %int 42
4745fd4e5da5Sopenharmony_ci%int_0 = OpConstant %int 0
4746fd4e5da5Sopenharmony_ci%int_2 = OpConstant %int 2
4747fd4e5da5Sopenharmony_ci%1 = OpConstantComposite %ivec3 %int_42 %int_0 %int_2
4748fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %ivec3
4749fd4e5da5Sopenharmony_ci%3 = OpFunction %ivec3 None %2
4750fd4e5da5Sopenharmony_ci%4 = OpLabel
4751fd4e5da5Sopenharmony_ci%var = OpVariable %ptr_ivec3 Function %1
4752fd4e5da5Sopenharmony_ci%5 = OpLoad %ivec3 %var
4753fd4e5da5Sopenharmony_ci%6 = OpVectorShuffle %ivec3 %5 %undef 2 1 0
4754fd4e5da5Sopenharmony_ci     OpReturnValue %6
4755fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
4756fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
4757fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
4758fd4e5da5Sopenharmony_ci}
4759fd4e5da5Sopenharmony_ci
4760fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpVectorShuffleFloatGood) {
4761fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
4762fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
4763fd4e5da5Sopenharmony_ci%vec2 = OpTypeVector %float 2
4764fd4e5da5Sopenharmony_ci%vec3 = OpTypeVector %float 3
4765fd4e5da5Sopenharmony_ci%vec4 = OpTypeVector %float 4
4766fd4e5da5Sopenharmony_ci%ptr_vec2 = OpTypePointer Function %vec2
4767fd4e5da5Sopenharmony_ci%ptr_vec3 = OpTypePointer Function %vec3
4768fd4e5da5Sopenharmony_ci%float_1 = OpConstant %float 1
4769fd4e5da5Sopenharmony_ci%float_2 = OpConstant %float 2
4770fd4e5da5Sopenharmony_ci%1 = OpConstantComposite %vec2 %float_2 %float_1
4771fd4e5da5Sopenharmony_ci%2 = OpConstantComposite %vec3 %float_1 %float_2 %float_2
4772fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %vec4
4773fd4e5da5Sopenharmony_ci%4 = OpFunction %vec4 None %3
4774fd4e5da5Sopenharmony_ci%5 = OpLabel
4775fd4e5da5Sopenharmony_ci%var = OpVariable %ptr_vec2 Function %1
4776fd4e5da5Sopenharmony_ci%var2 = OpVariable %ptr_vec3 Function %2
4777fd4e5da5Sopenharmony_ci%6 = OpLoad %vec2 %var
4778fd4e5da5Sopenharmony_ci%7 = OpLoad %vec3 %var2
4779fd4e5da5Sopenharmony_ci%8 = OpVectorShuffle %vec4 %6 %7 4 3 1 0xffffffff
4780fd4e5da5Sopenharmony_ci     OpReturnValue %8
4781fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
4782fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
4783fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
4784fd4e5da5Sopenharmony_ci}
4785fd4e5da5Sopenharmony_ci
4786fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpVectorShuffleScalarResultType) {
4787fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
4788fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
4789fd4e5da5Sopenharmony_ci%vec2 = OpTypeVector %float 2
4790fd4e5da5Sopenharmony_ci%ptr_vec2 = OpTypePointer Function %vec2
4791fd4e5da5Sopenharmony_ci%float_1 = OpConstant %float 1
4792fd4e5da5Sopenharmony_ci%float_2 = OpConstant %float 2
4793fd4e5da5Sopenharmony_ci%1 = OpConstantComposite %vec2 %float_2 %float_1
4794fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %float
4795fd4e5da5Sopenharmony_ci%3 = OpFunction %float None %2
4796fd4e5da5Sopenharmony_ci%4 = OpLabel
4797fd4e5da5Sopenharmony_ci%var = OpVariable %ptr_vec2 Function %1
4798fd4e5da5Sopenharmony_ci%5 = OpLoad %vec2 %var
4799fd4e5da5Sopenharmony_ci%6 = OpVectorShuffle %float %5 %5 0
4800fd4e5da5Sopenharmony_ci     OpReturnValue %6
4801fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
4802fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
4803fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4804fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
4805fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
4806fd4e5da5Sopenharmony_ci                  "Result Type of OpVectorShuffle must be OpTypeVector.")));
4807fd4e5da5Sopenharmony_ci}
4808fd4e5da5Sopenharmony_ci
4809fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpVectorShuffleComponentCount) {
4810fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
4811fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
4812fd4e5da5Sopenharmony_ci%ivec3 = OpTypeVector %int 3
4813fd4e5da5Sopenharmony_ci%ptr_ivec3 = OpTypePointer Function %ivec3
4814fd4e5da5Sopenharmony_ci%int_42 = OpConstant %int 42
4815fd4e5da5Sopenharmony_ci%int_0 = OpConstant %int 0
4816fd4e5da5Sopenharmony_ci%int_2 = OpConstant %int 2
4817fd4e5da5Sopenharmony_ci%1 = OpConstantComposite %ivec3 %int_42 %int_0 %int_2
4818fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %ivec3
4819fd4e5da5Sopenharmony_ci%3 = OpFunction %ivec3 None %2
4820fd4e5da5Sopenharmony_ci%4 = OpLabel
4821fd4e5da5Sopenharmony_ci%var = OpVariable %ptr_ivec3 Function %1
4822fd4e5da5Sopenharmony_ci%5 = OpLoad %ivec3 %var
4823fd4e5da5Sopenharmony_ci%6 = OpVectorShuffle %ivec3 %5 %5 0 1
4824fd4e5da5Sopenharmony_ci     OpReturnValue %6
4825fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
4826fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
4827fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4828fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
4829fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
4830fd4e5da5Sopenharmony_ci                  "OpVectorShuffle component literals count does not match "
4831fd4e5da5Sopenharmony_ci                  "Result Type <id> '2[%v3uint]'s vector component count.")));
4832fd4e5da5Sopenharmony_ci}
4833fd4e5da5Sopenharmony_ci
4834fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpVectorShuffleVector1Type) {
4835fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
4836fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
4837fd4e5da5Sopenharmony_ci%ivec2 = OpTypeVector %int 2
4838fd4e5da5Sopenharmony_ci%ptr_int = OpTypePointer Function %int
4839fd4e5da5Sopenharmony_ci%undef = OpUndef %ivec2
4840fd4e5da5Sopenharmony_ci%int_42 = OpConstant %int 42
4841fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %ivec2
4842fd4e5da5Sopenharmony_ci%3 = OpFunction %ivec2 None %2
4843fd4e5da5Sopenharmony_ci%4 = OpLabel
4844fd4e5da5Sopenharmony_ci%var = OpVariable %ptr_int Function %int_42
4845fd4e5da5Sopenharmony_ci%5 = OpLoad %int %var
4846fd4e5da5Sopenharmony_ci%6 = OpVectorShuffle %ivec2 %5 %undef 0 0
4847fd4e5da5Sopenharmony_ci     OpReturnValue %6
4848fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
4849fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
4850fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4851fd4e5da5Sopenharmony_ci  EXPECT_THAT(
4852fd4e5da5Sopenharmony_ci      getDiagnosticString(),
4853fd4e5da5Sopenharmony_ci      HasSubstr(make_message("The type of Vector 1 must be OpTypeVector.")));
4854fd4e5da5Sopenharmony_ci}
4855fd4e5da5Sopenharmony_ci
4856fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpVectorShuffleVector2Type) {
4857fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
4858fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
4859fd4e5da5Sopenharmony_ci%ivec2 = OpTypeVector %int 2
4860fd4e5da5Sopenharmony_ci%ptr_ivec2 = OpTypePointer Function %ivec2
4861fd4e5da5Sopenharmony_ci%undef = OpUndef %int
4862fd4e5da5Sopenharmony_ci%int_42 = OpConstant %int 42
4863fd4e5da5Sopenharmony_ci%1 = OpConstantComposite %ivec2 %int_42 %int_42
4864fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %ivec2
4865fd4e5da5Sopenharmony_ci%3 = OpFunction %ivec2 None %2
4866fd4e5da5Sopenharmony_ci%4 = OpLabel
4867fd4e5da5Sopenharmony_ci%var = OpVariable %ptr_ivec2 Function %1
4868fd4e5da5Sopenharmony_ci%5 = OpLoad %ivec2 %var
4869fd4e5da5Sopenharmony_ci%6 = OpVectorShuffle %ivec2 %5 %undef 0 1
4870fd4e5da5Sopenharmony_ci     OpReturnValue %6
4871fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
4872fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
4873fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4874fd4e5da5Sopenharmony_ci  EXPECT_THAT(
4875fd4e5da5Sopenharmony_ci      getDiagnosticString(),
4876fd4e5da5Sopenharmony_ci      HasSubstr(make_message("The type of Vector 2 must be OpTypeVector.")));
4877fd4e5da5Sopenharmony_ci}
4878fd4e5da5Sopenharmony_ci
4879fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpVectorShuffleVector1ComponentType) {
4880fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
4881fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
4882fd4e5da5Sopenharmony_ci%ivec3 = OpTypeVector %int 3
4883fd4e5da5Sopenharmony_ci%ptr_ivec3 = OpTypePointer Function %ivec3
4884fd4e5da5Sopenharmony_ci%int_42 = OpConstant %int 42
4885fd4e5da5Sopenharmony_ci%int_0 = OpConstant %int 0
4886fd4e5da5Sopenharmony_ci%int_2 = OpConstant %int 2
4887fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
4888fd4e5da5Sopenharmony_ci%vec3 = OpTypeVector %float 3
4889fd4e5da5Sopenharmony_ci%vec4 = OpTypeVector %float 4
4890fd4e5da5Sopenharmony_ci%ptr_vec3 = OpTypePointer Function %vec3
4891fd4e5da5Sopenharmony_ci%float_1 = OpConstant %float 1
4892fd4e5da5Sopenharmony_ci%float_2 = OpConstant %float 2
4893fd4e5da5Sopenharmony_ci%1 = OpConstantComposite %ivec3 %int_42 %int_0 %int_2
4894fd4e5da5Sopenharmony_ci%2 = OpConstantComposite %vec3 %float_1 %float_2 %float_2
4895fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %vec4
4896fd4e5da5Sopenharmony_ci%4 = OpFunction %vec4 None %3
4897fd4e5da5Sopenharmony_ci%5 = OpLabel
4898fd4e5da5Sopenharmony_ci%var = OpVariable %ptr_ivec3 Function %1
4899fd4e5da5Sopenharmony_ci%var2 = OpVariable %ptr_vec3 Function %2
4900fd4e5da5Sopenharmony_ci%6 = OpLoad %ivec3 %var
4901fd4e5da5Sopenharmony_ci%7 = OpLoad %vec3 %var2
4902fd4e5da5Sopenharmony_ci%8 = OpVectorShuffle %vec4 %6 %7 4 3 1 0
4903fd4e5da5Sopenharmony_ci     OpReturnValue %8
4904fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
4905fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
4906fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4907fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
4908fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
4909fd4e5da5Sopenharmony_ci                  "The Component Type of Vector 1 must be the same as "
4910fd4e5da5Sopenharmony_ci                  "ResultType.")));
4911fd4e5da5Sopenharmony_ci}
4912fd4e5da5Sopenharmony_ci
4913fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpVectorShuffleVector2ComponentType) {
4914fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
4915fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
4916fd4e5da5Sopenharmony_ci%ivec3 = OpTypeVector %int 3
4917fd4e5da5Sopenharmony_ci%ptr_ivec3 = OpTypePointer Function %ivec3
4918fd4e5da5Sopenharmony_ci%int_42 = OpConstant %int 42
4919fd4e5da5Sopenharmony_ci%int_0 = OpConstant %int 0
4920fd4e5da5Sopenharmony_ci%int_2 = OpConstant %int 2
4921fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
4922fd4e5da5Sopenharmony_ci%vec3 = OpTypeVector %float 3
4923fd4e5da5Sopenharmony_ci%vec4 = OpTypeVector %float 4
4924fd4e5da5Sopenharmony_ci%ptr_vec3 = OpTypePointer Function %vec3
4925fd4e5da5Sopenharmony_ci%float_1 = OpConstant %float 1
4926fd4e5da5Sopenharmony_ci%float_2 = OpConstant %float 2
4927fd4e5da5Sopenharmony_ci%1 = OpConstantComposite %ivec3 %int_42 %int_0 %int_2
4928fd4e5da5Sopenharmony_ci%2 = OpConstantComposite %vec3 %float_1 %float_2 %float_2
4929fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %vec4
4930fd4e5da5Sopenharmony_ci%4 = OpFunction %vec4 None %3
4931fd4e5da5Sopenharmony_ci%5 = OpLabel
4932fd4e5da5Sopenharmony_ci%var = OpVariable %ptr_ivec3 Function %1
4933fd4e5da5Sopenharmony_ci%var2 = OpVariable %ptr_vec3 Function %2
4934fd4e5da5Sopenharmony_ci%6 = OpLoad %vec3 %var2
4935fd4e5da5Sopenharmony_ci%7 = OpLoad %ivec3 %var
4936fd4e5da5Sopenharmony_ci%8 = OpVectorShuffle %vec4 %6 %7 4 3 1 0
4937fd4e5da5Sopenharmony_ci     OpReturnValue %8
4938fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
4939fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
4940fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4941fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
4942fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
4943fd4e5da5Sopenharmony_ci                  "The Component Type of Vector 2 must be the same as "
4944fd4e5da5Sopenharmony_ci                  "ResultType.")));
4945fd4e5da5Sopenharmony_ci}
4946fd4e5da5Sopenharmony_ci
4947fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpVectorShuffleLiterals) {
4948fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
4949fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
4950fd4e5da5Sopenharmony_ci%vec2 = OpTypeVector %float 2
4951fd4e5da5Sopenharmony_ci%vec3 = OpTypeVector %float 3
4952fd4e5da5Sopenharmony_ci%vec4 = OpTypeVector %float 4
4953fd4e5da5Sopenharmony_ci%ptr_vec2 = OpTypePointer Function %vec2
4954fd4e5da5Sopenharmony_ci%ptr_vec3 = OpTypePointer Function %vec3
4955fd4e5da5Sopenharmony_ci%float_1 = OpConstant %float 1
4956fd4e5da5Sopenharmony_ci%float_2 = OpConstant %float 2
4957fd4e5da5Sopenharmony_ci%1 = OpConstantComposite %vec2 %float_2 %float_1
4958fd4e5da5Sopenharmony_ci%2 = OpConstantComposite %vec3 %float_1 %float_2 %float_2
4959fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %vec4
4960fd4e5da5Sopenharmony_ci%4 = OpFunction %vec4 None %3
4961fd4e5da5Sopenharmony_ci%5 = OpLabel
4962fd4e5da5Sopenharmony_ci%var = OpVariable %ptr_vec2 Function %1
4963fd4e5da5Sopenharmony_ci%var2 = OpVariable %ptr_vec3 Function %2
4964fd4e5da5Sopenharmony_ci%6 = OpLoad %vec2 %var
4965fd4e5da5Sopenharmony_ci%7 = OpLoad %vec3 %var2
4966fd4e5da5Sopenharmony_ci%8 = OpVectorShuffle %vec4 %6 %7 0 8 2 6
4967fd4e5da5Sopenharmony_ci     OpReturnValue %8
4968fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
4969fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
4970fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
4971fd4e5da5Sopenharmony_ci  EXPECT_THAT(
4972fd4e5da5Sopenharmony_ci      getDiagnosticString(),
4973fd4e5da5Sopenharmony_ci      HasSubstr(make_message(
4974fd4e5da5Sopenharmony_ci          "Component index 8 is out of bounds for combined (Vector1 + Vector2) "
4975fd4e5da5Sopenharmony_ci          "size of 5.")));
4976fd4e5da5Sopenharmony_ci}
4977fd4e5da5Sopenharmony_ci
4978fd4e5da5Sopenharmony_ci// TODO: OpCompositeConstruct
4979fd4e5da5Sopenharmony_ci// TODO: OpCompositeExtract
4980fd4e5da5Sopenharmony_ci// TODO: OpCompositeInsert
4981fd4e5da5Sopenharmony_ci// TODO: OpCopyObject
4982fd4e5da5Sopenharmony_ci// TODO: OpTranspose
4983fd4e5da5Sopenharmony_ci// TODO: OpSNegate
4984fd4e5da5Sopenharmony_ci// TODO: OpFNegate
4985fd4e5da5Sopenharmony_ci// TODO: OpNot
4986fd4e5da5Sopenharmony_ci// TODO: OpIAdd
4987fd4e5da5Sopenharmony_ci// TODO: OpFAdd
4988fd4e5da5Sopenharmony_ci// TODO: OpISub
4989fd4e5da5Sopenharmony_ci// TODO: OpFSub
4990fd4e5da5Sopenharmony_ci// TODO: OpIMul
4991fd4e5da5Sopenharmony_ci// TODO: OpFMul
4992fd4e5da5Sopenharmony_ci// TODO: OpUDiv
4993fd4e5da5Sopenharmony_ci// TODO: OpSDiv
4994fd4e5da5Sopenharmony_ci// TODO: OpFDiv
4995fd4e5da5Sopenharmony_ci// TODO: OpUMod
4996fd4e5da5Sopenharmony_ci// TODO: OpSRem
4997fd4e5da5Sopenharmony_ci// TODO: OpSMod
4998fd4e5da5Sopenharmony_ci// TODO: OpFRem
4999fd4e5da5Sopenharmony_ci// TODO: OpFMod
5000fd4e5da5Sopenharmony_ci// TODO: OpVectorTimesScalar
5001fd4e5da5Sopenharmony_ci// TODO: OpMatrixTimesScalar
5002fd4e5da5Sopenharmony_ci// TODO: OpVectorTimesMatrix
5003fd4e5da5Sopenharmony_ci// TODO: OpMatrixTimesVector
5004fd4e5da5Sopenharmony_ci// TODO: OpMatrixTimesMatrix
5005fd4e5da5Sopenharmony_ci// TODO: OpOuterProduct
5006fd4e5da5Sopenharmony_ci// TODO: OpDot
5007fd4e5da5Sopenharmony_ci// TODO: OpShiftRightLogical
5008fd4e5da5Sopenharmony_ci// TODO: OpShiftRightArithmetic
5009fd4e5da5Sopenharmony_ci// TODO: OpShiftLeftLogical
5010fd4e5da5Sopenharmony_ci// TODO: OpBitwiseOr
5011fd4e5da5Sopenharmony_ci// TODO: OpBitwiseXor
5012fd4e5da5Sopenharmony_ci// TODO: OpBitwiseAnd
5013fd4e5da5Sopenharmony_ci// TODO: OpAny
5014fd4e5da5Sopenharmony_ci// TODO: OpAll
5015fd4e5da5Sopenharmony_ci// TODO: OpIsNan
5016fd4e5da5Sopenharmony_ci// TODO: OpIsInf
5017fd4e5da5Sopenharmony_ci// TODO: OpIsFinite
5018fd4e5da5Sopenharmony_ci// TODO: OpIsNormal
5019fd4e5da5Sopenharmony_ci// TODO: OpSignBitSet
5020fd4e5da5Sopenharmony_ci// TODO: OpLessOrGreater
5021fd4e5da5Sopenharmony_ci// TODO: OpOrdered
5022fd4e5da5Sopenharmony_ci// TODO: OpUnordered
5023fd4e5da5Sopenharmony_ci// TODO: OpLogicalOr
5024fd4e5da5Sopenharmony_ci// TODO: OpLogicalXor
5025fd4e5da5Sopenharmony_ci// TODO: OpLogicalAnd
5026fd4e5da5Sopenharmony_ci// TODO: OpSelect
5027fd4e5da5Sopenharmony_ci// TODO: OpIEqual
5028fd4e5da5Sopenharmony_ci// TODO: OpFOrdEqual
5029fd4e5da5Sopenharmony_ci// TODO: OpFUnordEqual
5030fd4e5da5Sopenharmony_ci// TODO: OpINotEqual
5031fd4e5da5Sopenharmony_ci// TODO: OpFOrdNotEqual
5032fd4e5da5Sopenharmony_ci// TODO: OpFUnordNotEqual
5033fd4e5da5Sopenharmony_ci// TODO: OpULessThan
5034fd4e5da5Sopenharmony_ci// TODO: OpSLessThan
5035fd4e5da5Sopenharmony_ci// TODO: OpFOrdLessThan
5036fd4e5da5Sopenharmony_ci// TODO: OpFUnordLessThan
5037fd4e5da5Sopenharmony_ci// TODO: OpUGreaterThan
5038fd4e5da5Sopenharmony_ci// TODO: OpSGreaterThan
5039fd4e5da5Sopenharmony_ci// TODO: OpFOrdGreaterThan
5040fd4e5da5Sopenharmony_ci// TODO: OpFUnordGreaterThan
5041fd4e5da5Sopenharmony_ci// TODO: OpULessThanEqual
5042fd4e5da5Sopenharmony_ci// TODO: OpSLessThanEqual
5043fd4e5da5Sopenharmony_ci// TODO: OpFOrdLessThanEqual
5044fd4e5da5Sopenharmony_ci// TODO: OpFUnordLessThanEqual
5045fd4e5da5Sopenharmony_ci// TODO: OpUGreaterThanEqual
5046fd4e5da5Sopenharmony_ci// TODO: OpSGreaterThanEqual
5047fd4e5da5Sopenharmony_ci// TODO: OpFOrdGreaterThanEqual
5048fd4e5da5Sopenharmony_ci// TODO: OpFUnordGreaterThanEqual
5049fd4e5da5Sopenharmony_ci// TODO: OpDPdx
5050fd4e5da5Sopenharmony_ci// TODO: OpDPdy
5051fd4e5da5Sopenharmony_ci// TODO: OpFWidth
5052fd4e5da5Sopenharmony_ci// TODO: OpDPdxFine
5053fd4e5da5Sopenharmony_ci// TODO: OpDPdyFine
5054fd4e5da5Sopenharmony_ci// TODO: OpFwidthFine
5055fd4e5da5Sopenharmony_ci// TODO: OpDPdxCoarse
5056fd4e5da5Sopenharmony_ci// TODO: OpDPdyCoarse
5057fd4e5da5Sopenharmony_ci// TODO: OpFwidthCoarse
5058fd4e5da5Sopenharmony_ci// TODO: OpLoopMerge
5059fd4e5da5Sopenharmony_ci// TODO: OpSelectionMerge
5060fd4e5da5Sopenharmony_ci// TODO: OpBranch
5061fd4e5da5Sopenharmony_ci
5062fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpPhiNotAType) {
5063fd4e5da5Sopenharmony_ci  std::string spirv = kOpenCLMemoryModel32 + R"(
5064fd4e5da5Sopenharmony_ci%2 = OpTypeBool
5065fd4e5da5Sopenharmony_ci%3 = OpConstantTrue %2
5066fd4e5da5Sopenharmony_ci%4 = OpTypeVoid
5067fd4e5da5Sopenharmony_ci%5 = OpTypeFunction %4
5068fd4e5da5Sopenharmony_ci%6 = OpFunction %4 None %5
5069fd4e5da5Sopenharmony_ci%7 = OpLabel
5070fd4e5da5Sopenharmony_ciOpBranch %8
5071fd4e5da5Sopenharmony_ci%8 = OpLabel
5072fd4e5da5Sopenharmony_ci%9 = OpPhi %3 %3 %7
5073fd4e5da5Sopenharmony_ciOpReturn
5074fd4e5da5Sopenharmony_ciOpFunctionEnd
5075fd4e5da5Sopenharmony_ci  )";
5076fd4e5da5Sopenharmony_ci
5077fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5078fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5079fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
5080fd4e5da5Sopenharmony_ci              HasSubstr(make_message("ID '3[%true]' is not a type "
5081fd4e5da5Sopenharmony_ci                                     "id")));
5082fd4e5da5Sopenharmony_ci}
5083fd4e5da5Sopenharmony_ci
5084fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpPhiSamePredecessor) {
5085fd4e5da5Sopenharmony_ci  std::string spirv = kOpenCLMemoryModel32 + R"(
5086fd4e5da5Sopenharmony_ci%2 = OpTypeBool
5087fd4e5da5Sopenharmony_ci%3 = OpConstantTrue %2
5088fd4e5da5Sopenharmony_ci%4 = OpTypeVoid
5089fd4e5da5Sopenharmony_ci%5 = OpTypeFunction %4
5090fd4e5da5Sopenharmony_ci%6 = OpFunction %4 None %5
5091fd4e5da5Sopenharmony_ci%7 = OpLabel
5092fd4e5da5Sopenharmony_ciOpBranchConditional %3 %8 %8
5093fd4e5da5Sopenharmony_ci%8 = OpLabel
5094fd4e5da5Sopenharmony_ci%9 = OpPhi %2 %3 %7
5095fd4e5da5Sopenharmony_ciOpReturn
5096fd4e5da5Sopenharmony_ciOpFunctionEnd
5097fd4e5da5Sopenharmony_ci  )";
5098fd4e5da5Sopenharmony_ci
5099fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5100fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5101fd4e5da5Sopenharmony_ci}
5102fd4e5da5Sopenharmony_ci
5103fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpPhiOddArgumentNumber) {
5104fd4e5da5Sopenharmony_ci  std::string spirv = kOpenCLMemoryModel32 + R"(
5105fd4e5da5Sopenharmony_ci%2 = OpTypeBool
5106fd4e5da5Sopenharmony_ci%3 = OpConstantTrue %2
5107fd4e5da5Sopenharmony_ci%4 = OpTypeVoid
5108fd4e5da5Sopenharmony_ci%5 = OpTypeFunction %4
5109fd4e5da5Sopenharmony_ci%6 = OpFunction %4 None %5
5110fd4e5da5Sopenharmony_ci%7 = OpLabel
5111fd4e5da5Sopenharmony_ciOpBranch %8
5112fd4e5da5Sopenharmony_ci%8 = OpLabel
5113fd4e5da5Sopenharmony_ci%9 = OpPhi %2 %3
5114fd4e5da5Sopenharmony_ciOpReturn
5115fd4e5da5Sopenharmony_ciOpFunctionEnd
5116fd4e5da5Sopenharmony_ci  )";
5117fd4e5da5Sopenharmony_ci
5118fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5119fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5120fd4e5da5Sopenharmony_ci  EXPECT_THAT(
5121fd4e5da5Sopenharmony_ci      getDiagnosticString(),
5122fd4e5da5Sopenharmony_ci      HasSubstr(make_message("OpPhi does not have an equal number of incoming "
5123fd4e5da5Sopenharmony_ci                             "values and basic blocks.")));
5124fd4e5da5Sopenharmony_ci}
5125fd4e5da5Sopenharmony_ci
5126fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpPhiTooFewPredecessors) {
5127fd4e5da5Sopenharmony_ci  std::string spirv = kOpenCLMemoryModel32 + R"(
5128fd4e5da5Sopenharmony_ci%2 = OpTypeBool
5129fd4e5da5Sopenharmony_ci%3 = OpConstantTrue %2
5130fd4e5da5Sopenharmony_ci%4 = OpTypeVoid
5131fd4e5da5Sopenharmony_ci%5 = OpTypeFunction %4
5132fd4e5da5Sopenharmony_ci%6 = OpFunction %4 None %5
5133fd4e5da5Sopenharmony_ci%7 = OpLabel
5134fd4e5da5Sopenharmony_ciOpBranch %8
5135fd4e5da5Sopenharmony_ci%8 = OpLabel
5136fd4e5da5Sopenharmony_ci%9 = OpPhi %2
5137fd4e5da5Sopenharmony_ciOpReturn
5138fd4e5da5Sopenharmony_ciOpFunctionEnd
5139fd4e5da5Sopenharmony_ci  )";
5140fd4e5da5Sopenharmony_ci
5141fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5142fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5143fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
5144fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
5145fd4e5da5Sopenharmony_ci                  "OpPhi's number of incoming blocks (0) does not match "
5146fd4e5da5Sopenharmony_ci                  "block's predecessor count (1).")));
5147fd4e5da5Sopenharmony_ci}
5148fd4e5da5Sopenharmony_ci
5149fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpPhiTooManyPredecessors) {
5150fd4e5da5Sopenharmony_ci  std::string spirv = kOpenCLMemoryModel32 + R"(
5151fd4e5da5Sopenharmony_ci%2 = OpTypeBool
5152fd4e5da5Sopenharmony_ci%3 = OpConstantTrue %2
5153fd4e5da5Sopenharmony_ci%4 = OpTypeVoid
5154fd4e5da5Sopenharmony_ci%5 = OpTypeFunction %4
5155fd4e5da5Sopenharmony_ci%6 = OpFunction %4 None %5
5156fd4e5da5Sopenharmony_ci%7 = OpLabel
5157fd4e5da5Sopenharmony_ciOpBranch %8
5158fd4e5da5Sopenharmony_ci%9 = OpLabel
5159fd4e5da5Sopenharmony_ciOpReturn
5160fd4e5da5Sopenharmony_ci%8 = OpLabel
5161fd4e5da5Sopenharmony_ci%10 = OpPhi %2 %3 %7 %3 %9
5162fd4e5da5Sopenharmony_ciOpReturn
5163fd4e5da5Sopenharmony_ciOpFunctionEnd
5164fd4e5da5Sopenharmony_ci  )";
5165fd4e5da5Sopenharmony_ci
5166fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5167fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5168fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
5169fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
5170fd4e5da5Sopenharmony_ci                  "OpPhi's number of incoming blocks (2) does not match "
5171fd4e5da5Sopenharmony_ci                  "block's predecessor count (1).")));
5172fd4e5da5Sopenharmony_ci}
5173fd4e5da5Sopenharmony_ci
5174fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpPhiMismatchedTypes) {
5175fd4e5da5Sopenharmony_ci  std::string spirv = kOpenCLMemoryModel32 + R"(
5176fd4e5da5Sopenharmony_ci%2 = OpTypeBool
5177fd4e5da5Sopenharmony_ci%3 = OpConstantTrue %2
5178fd4e5da5Sopenharmony_ci%4 = OpTypeVoid
5179fd4e5da5Sopenharmony_ci%5 = OpTypeInt 32 0
5180fd4e5da5Sopenharmony_ci%6 = OpConstant %5 0
5181fd4e5da5Sopenharmony_ci%7 = OpTypeFunction %4
5182fd4e5da5Sopenharmony_ci%8 = OpFunction %4 None %7
5183fd4e5da5Sopenharmony_ci%9 = OpLabel
5184fd4e5da5Sopenharmony_ciOpBranchConditional %3 %10 %11
5185fd4e5da5Sopenharmony_ci%11 = OpLabel
5186fd4e5da5Sopenharmony_ciOpBranch %10
5187fd4e5da5Sopenharmony_ci%10 = OpLabel
5188fd4e5da5Sopenharmony_ci%12 = OpPhi %2 %3 %9 %6 %11
5189fd4e5da5Sopenharmony_ciOpReturn
5190fd4e5da5Sopenharmony_ciOpFunctionEnd
5191fd4e5da5Sopenharmony_ci  )";
5192fd4e5da5Sopenharmony_ci
5193fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5194fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5195fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
5196fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
5197fd4e5da5Sopenharmony_ci                  "OpPhi's result type <id> '2[%bool]' does not match "
5198fd4e5da5Sopenharmony_ci                  "incoming value <id> '6[%uint_0]' type <id> "
5199fd4e5da5Sopenharmony_ci                  "'5[%uint]'.")));
5200fd4e5da5Sopenharmony_ci}
5201fd4e5da5Sopenharmony_ci
5202fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpPhiPredecessorNotABlock) {
5203fd4e5da5Sopenharmony_ci  std::string spirv = kOpenCLMemoryModel32 + R"(
5204fd4e5da5Sopenharmony_ci%2 = OpTypeBool
5205fd4e5da5Sopenharmony_ci%3 = OpConstantTrue %2
5206fd4e5da5Sopenharmony_ci%4 = OpTypeVoid
5207fd4e5da5Sopenharmony_ci%5 = OpTypeFunction %4
5208fd4e5da5Sopenharmony_ci%6 = OpFunction %4 None %5
5209fd4e5da5Sopenharmony_ci%7 = OpLabel
5210fd4e5da5Sopenharmony_ciOpBranchConditional %3 %8 %9
5211fd4e5da5Sopenharmony_ci%9 = OpLabel
5212fd4e5da5Sopenharmony_ciOpBranch %11
5213fd4e5da5Sopenharmony_ci%11 = OpLabel
5214fd4e5da5Sopenharmony_ciOpBranch %8
5215fd4e5da5Sopenharmony_ci%8 = OpLabel
5216fd4e5da5Sopenharmony_ci%10 = OpPhi %2 %3 %7 %3 %3
5217fd4e5da5Sopenharmony_ciOpReturn
5218fd4e5da5Sopenharmony_ciOpFunctionEnd
5219fd4e5da5Sopenharmony_ci  )";
5220fd4e5da5Sopenharmony_ci
5221fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5222fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5223fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
5224fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
5225fd4e5da5Sopenharmony_ci                  "OpPhi's incoming basic block <id> '3[%true]' is not an "
5226fd4e5da5Sopenharmony_ci                  "OpLabel.")));
5227fd4e5da5Sopenharmony_ci}
5228fd4e5da5Sopenharmony_ci
5229fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpPhiNotAPredecessor) {
5230fd4e5da5Sopenharmony_ci  std::string spirv = kOpenCLMemoryModel32 + R"(
5231fd4e5da5Sopenharmony_ci%2 = OpTypeBool
5232fd4e5da5Sopenharmony_ci%3 = OpConstantTrue %2
5233fd4e5da5Sopenharmony_ci%4 = OpTypeVoid
5234fd4e5da5Sopenharmony_ci%5 = OpTypeFunction %4
5235fd4e5da5Sopenharmony_ci%6 = OpFunction %4 None %5
5236fd4e5da5Sopenharmony_ci%7 = OpLabel
5237fd4e5da5Sopenharmony_ciOpBranchConditional %3 %8 %9
5238fd4e5da5Sopenharmony_ci%9 = OpLabel
5239fd4e5da5Sopenharmony_ciOpBranch %11
5240fd4e5da5Sopenharmony_ci%11 = OpLabel
5241fd4e5da5Sopenharmony_ciOpBranch %8
5242fd4e5da5Sopenharmony_ci%8 = OpLabel
5243fd4e5da5Sopenharmony_ci%10 = OpPhi %2 %3 %7 %3 %9
5244fd4e5da5Sopenharmony_ciOpReturn
5245fd4e5da5Sopenharmony_ciOpFunctionEnd
5246fd4e5da5Sopenharmony_ci  )";
5247fd4e5da5Sopenharmony_ci
5248fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5249fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5250fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
5251fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
5252fd4e5da5Sopenharmony_ci                  "OpPhi's incoming basic block <id> '9[%9]' is not a "
5253fd4e5da5Sopenharmony_ci                  "predecessor of <id> '8[%8]'.")));
5254fd4e5da5Sopenharmony_ci}
5255fd4e5da5Sopenharmony_ci
5256fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpBranchConditionalGood) {
5257fd4e5da5Sopenharmony_ci  std::string spirv = BranchConditionalSetup + R"(
5258fd4e5da5Sopenharmony_ci    %branch_cond = OpINotEqual %bool %i0 %i1
5259fd4e5da5Sopenharmony_ci                   OpSelectionMerge %end None
5260fd4e5da5Sopenharmony_ci                   OpBranchConditional %branch_cond %target_t %target_f
5261fd4e5da5Sopenharmony_ci  )" + BranchConditionalTail;
5262fd4e5da5Sopenharmony_ci
5263fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5264fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
5265fd4e5da5Sopenharmony_ci}
5266fd4e5da5Sopenharmony_ci
5267fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpBranchConditionalWithWeightsGood) {
5268fd4e5da5Sopenharmony_ci  std::string spirv = BranchConditionalSetup + R"(
5269fd4e5da5Sopenharmony_ci    %branch_cond = OpINotEqual %bool %i0 %i1
5270fd4e5da5Sopenharmony_ci                   OpSelectionMerge %end None
5271fd4e5da5Sopenharmony_ci                   OpBranchConditional %branch_cond %target_t %target_f 1 1
5272fd4e5da5Sopenharmony_ci  )" + BranchConditionalTail;
5273fd4e5da5Sopenharmony_ci
5274fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5275fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
5276fd4e5da5Sopenharmony_ci}
5277fd4e5da5Sopenharmony_ci
5278fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpBranchConditional_CondIsScalarInt) {
5279fd4e5da5Sopenharmony_ci  std::string spirv = BranchConditionalSetup + R"(
5280fd4e5da5Sopenharmony_ci                   OpSelectionMerge %end None
5281fd4e5da5Sopenharmony_ci                   OpBranchConditional %i0 %target_t %target_f
5282fd4e5da5Sopenharmony_ci  )" + BranchConditionalTail;
5283fd4e5da5Sopenharmony_ci
5284fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5285fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5286fd4e5da5Sopenharmony_ci  EXPECT_THAT(
5287fd4e5da5Sopenharmony_ci      getDiagnosticString(),
5288fd4e5da5Sopenharmony_ci      HasSubstr(make_message("Condition operand for OpBranchConditional must "
5289fd4e5da5Sopenharmony_ci                             "be of boolean type")));
5290fd4e5da5Sopenharmony_ci}
5291fd4e5da5Sopenharmony_ci
5292fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpBranchConditional_TrueTargetIsNotLabel) {
5293fd4e5da5Sopenharmony_ci  std::string spirv = BranchConditionalSetup + R"(
5294fd4e5da5Sopenharmony_ci                   OpSelectionMerge %end None
5295fd4e5da5Sopenharmony_ci                   OpBranchConditional %true %i0 %target_f
5296fd4e5da5Sopenharmony_ci  )" + BranchConditionalTail;
5297fd4e5da5Sopenharmony_ci
5298fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5299fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5300fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
5301fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
5302fd4e5da5Sopenharmony_ci                  "The 'True Label' operand for OpBranchConditional must "
5303fd4e5da5Sopenharmony_ci                  "be the ID of an OpLabel instruction")));
5304fd4e5da5Sopenharmony_ci}
5305fd4e5da5Sopenharmony_ci
5306fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpBranchConditional_FalseTargetIsNotLabel) {
5307fd4e5da5Sopenharmony_ci  std::string spirv = BranchConditionalSetup + R"(
5308fd4e5da5Sopenharmony_ci                   OpSelectionMerge %end None
5309fd4e5da5Sopenharmony_ci                   OpBranchConditional %true %target_t %i0
5310fd4e5da5Sopenharmony_ci  )" + BranchConditionalTail;
5311fd4e5da5Sopenharmony_ci
5312fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5313fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5314fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
5315fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
5316fd4e5da5Sopenharmony_ci                  "The 'False Label' operand for OpBranchConditional "
5317fd4e5da5Sopenharmony_ci                  "must be the ID of an OpLabel instruction")));
5318fd4e5da5Sopenharmony_ci}
5319fd4e5da5Sopenharmony_ci
5320fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpBranchConditional_NotEnoughWeights) {
5321fd4e5da5Sopenharmony_ci  std::string spirv = BranchConditionalSetup + R"(
5322fd4e5da5Sopenharmony_ci    %branch_cond = OpINotEqual %bool %i0 %i1
5323fd4e5da5Sopenharmony_ci                   OpSelectionMerge %end None
5324fd4e5da5Sopenharmony_ci                   OpBranchConditional %branch_cond %target_t %target_f 1
5325fd4e5da5Sopenharmony_ci  )" + BranchConditionalTail;
5326fd4e5da5Sopenharmony_ci
5327fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5328fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5329fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
5330fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
5331fd4e5da5Sopenharmony_ci                  "OpBranchConditional requires either 3 or 5 parameters")));
5332fd4e5da5Sopenharmony_ci}
5333fd4e5da5Sopenharmony_ci
5334fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpBranchConditional_TooManyWeights) {
5335fd4e5da5Sopenharmony_ci  std::string spirv = BranchConditionalSetup + R"(
5336fd4e5da5Sopenharmony_ci    %branch_cond = OpINotEqual %bool %i0 %i1
5337fd4e5da5Sopenharmony_ci                   OpSelectionMerge %end None
5338fd4e5da5Sopenharmony_ci                   OpBranchConditional %branch_cond %target_t %target_f 1 2 3
5339fd4e5da5Sopenharmony_ci  )" + BranchConditionalTail;
5340fd4e5da5Sopenharmony_ci
5341fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5342fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5343fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
5344fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
5345fd4e5da5Sopenharmony_ci                  "OpBranchConditional requires either 3 or 5 parameters")));
5346fd4e5da5Sopenharmony_ci}
5347fd4e5da5Sopenharmony_ci
5348fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpBranchConditional_ConditionIsAType) {
5349fd4e5da5Sopenharmony_ci  std::string spirv = BranchConditionalSetup + R"(
5350fd4e5da5Sopenharmony_ciOpBranchConditional %bool %target_t %target_f
5351fd4e5da5Sopenharmony_ci)" + BranchConditionalTail;
5352fd4e5da5Sopenharmony_ci
5353fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5354fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5355fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
5356fd4e5da5Sopenharmony_ci              HasSubstr(make_message("Operand '3[%bool]' cannot be a "
5357fd4e5da5Sopenharmony_ci                                     "type")));
5358fd4e5da5Sopenharmony_ci}
5359fd4e5da5Sopenharmony_ci
5360fd4e5da5Sopenharmony_ci// TODO: OpSwitch
5361fd4e5da5Sopenharmony_ci
5362fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpReturnValueConstantGood) {
5363fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
5364fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
5365fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
5366fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %2
5367fd4e5da5Sopenharmony_ci%4 = OpConstant %2 42
5368fd4e5da5Sopenharmony_ci%5 = OpFunction %2 None %3
5369fd4e5da5Sopenharmony_ci%6 = OpLabel
5370fd4e5da5Sopenharmony_ci     OpReturnValue %4
5371fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
5372fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5373fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5374fd4e5da5Sopenharmony_ci}
5375fd4e5da5Sopenharmony_ci
5376fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpReturnValueVariableGood) {
5377fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
5378fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
5379fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0 ;10
5380fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %2
5381fd4e5da5Sopenharmony_ci%8 = OpTypePointer Function %2 ;18
5382fd4e5da5Sopenharmony_ci%4 = OpConstant %2 42 ;22
5383fd4e5da5Sopenharmony_ci%5 = OpFunction %2 None %3 ;27
5384fd4e5da5Sopenharmony_ci%6 = OpLabel ;29
5385fd4e5da5Sopenharmony_ci%7 = OpVariable %8 Function %4 ;34
5386fd4e5da5Sopenharmony_ci%9 = OpLoad %2 %7
5387fd4e5da5Sopenharmony_ci     OpReturnValue %9 ;36
5388fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
5389fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5390fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5391fd4e5da5Sopenharmony_ci}
5392fd4e5da5Sopenharmony_ci
5393fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpReturnValueExpressionGood) {
5394fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
5395fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
5396fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
5397fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %2
5398fd4e5da5Sopenharmony_ci%4 = OpConstant %2 42
5399fd4e5da5Sopenharmony_ci%5 = OpFunction %2 None %3
5400fd4e5da5Sopenharmony_ci%6 = OpLabel
5401fd4e5da5Sopenharmony_ci%7 = OpIAdd %2 %4 %4
5402fd4e5da5Sopenharmony_ci     OpReturnValue %7
5403fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
5404fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5405fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5406fd4e5da5Sopenharmony_ci}
5407fd4e5da5Sopenharmony_ci
5408fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpReturnValueIsType) {
5409fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
5410fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
5411fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
5412fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %2
5413fd4e5da5Sopenharmony_ci%5 = OpFunction %2 None %3
5414fd4e5da5Sopenharmony_ci%6 = OpLabel
5415fd4e5da5Sopenharmony_ci     OpReturnValue %1
5416fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
5417fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5418fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5419fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
5420fd4e5da5Sopenharmony_ci              HasSubstr(make_message("Operand '1[%void]' cannot be a "
5421fd4e5da5Sopenharmony_ci                                     "type")));
5422fd4e5da5Sopenharmony_ci}
5423fd4e5da5Sopenharmony_ci
5424fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpReturnValueIsLabel) {
5425fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
5426fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
5427fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
5428fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %2
5429fd4e5da5Sopenharmony_ci%5 = OpFunction %2 None %3
5430fd4e5da5Sopenharmony_ci%6 = OpLabel
5431fd4e5da5Sopenharmony_ci     OpReturnValue %6
5432fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
5433fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5434fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5435fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
5436fd4e5da5Sopenharmony_ci              HasSubstr(make_message("Operand '5[%5]' requires a type")));
5437fd4e5da5Sopenharmony_ci}
5438fd4e5da5Sopenharmony_ci
5439fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpReturnValueIsVoid) {
5440fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
5441fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
5442fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
5443fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %1
5444fd4e5da5Sopenharmony_ci%5 = OpFunction %1 None %3
5445fd4e5da5Sopenharmony_ci%6 = OpLabel
5446fd4e5da5Sopenharmony_ci%7 = OpFunctionCall %1 %5
5447fd4e5da5Sopenharmony_ci     OpReturnValue %7
5448fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
5449fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5450fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5451fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
5452fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
5453fd4e5da5Sopenharmony_ci                  "OpReturnValue value's type <id> '1[%void]' is missing or "
5454fd4e5da5Sopenharmony_ci                  "void.")));
5455fd4e5da5Sopenharmony_ci}
5456fd4e5da5Sopenharmony_ci
5457fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpReturnValueIsVariableInPhysical) {
5458fd4e5da5Sopenharmony_ci  // It's valid to return a pointer in a physical addressing model.
5459fd4e5da5Sopenharmony_ci  std::string spirv = kOpCapabilitySetup + R"(
5460fd4e5da5Sopenharmony_ci     OpMemoryModel Physical32 OpenCL
5461fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
5462fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
5463fd4e5da5Sopenharmony_ci%3 = OpTypePointer Function %2
5464fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %3
5465fd4e5da5Sopenharmony_ci%5 = OpFunction %3 None %4
5466fd4e5da5Sopenharmony_ci%6 = OpLabel
5467fd4e5da5Sopenharmony_ci%7 = OpVariable %3 Function
5468fd4e5da5Sopenharmony_ci     OpReturnValue %7
5469fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
5470fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5471fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5472fd4e5da5Sopenharmony_ci}
5473fd4e5da5Sopenharmony_ci
5474fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpReturnValueIsVariableInLogical) {
5475fd4e5da5Sopenharmony_ci  // It's invalid to return a pointer in a physical addressing model.
5476fd4e5da5Sopenharmony_ci  std::string spirv = kOpCapabilitySetup + R"(
5477fd4e5da5Sopenharmony_ci     OpMemoryModel Logical GLSL450
5478fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
5479fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
5480fd4e5da5Sopenharmony_ci%3 = OpTypePointer Function %2
5481fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %3
5482fd4e5da5Sopenharmony_ci%5 = OpFunction %3 None %4
5483fd4e5da5Sopenharmony_ci%6 = OpLabel
5484fd4e5da5Sopenharmony_ci%7 = OpVariable %3 Function
5485fd4e5da5Sopenharmony_ci     OpReturnValue %7
5486fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
5487fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5488fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5489fd4e5da5Sopenharmony_ci  EXPECT_THAT(
5490fd4e5da5Sopenharmony_ci      getDiagnosticString(),
5491fd4e5da5Sopenharmony_ci      HasSubstr(make_message("OpReturnValue value's type <id> "
5492fd4e5da5Sopenharmony_ci                             "'3[%_ptr_Function_uint]' is a pointer, which is "
5493fd4e5da5Sopenharmony_ci                             "invalid in the Logical addressing model.")));
5494fd4e5da5Sopenharmony_ci}
5495fd4e5da5Sopenharmony_ci
5496fd4e5da5Sopenharmony_ci// With the VariablePointer Capability, the return value of a function is
5497fd4e5da5Sopenharmony_ci// allowed to be a pointer.
5498fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpReturnValueVarPtrGood) {
5499fd4e5da5Sopenharmony_ci  std::ostringstream spirv;
5500fd4e5da5Sopenharmony_ci  createVariablePointerSpirvProgram(&spirv,
5501fd4e5da5Sopenharmony_ci                                    "" /* Instructions to add to "main" */,
5502fd4e5da5Sopenharmony_ci                                    true /* Add VariablePointers Capability?*/,
5503fd4e5da5Sopenharmony_ci                                    true /* Use Helper Function? */);
5504fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.str());
5505fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5506fd4e5da5Sopenharmony_ci}
5507fd4e5da5Sopenharmony_ci
5508fd4e5da5Sopenharmony_ci// Without the VariablePointer Capability, the return value of a function is
5509fd4e5da5Sopenharmony_ci// *not* allowed to be a pointer.
5510fd4e5da5Sopenharmony_ci// Disabled since using OpSelect with pointers without VariablePointers will
5511fd4e5da5Sopenharmony_ci// fail LogicalsPass.
5512fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, DISABLED_OpReturnValueVarPtrBad) {
5513fd4e5da5Sopenharmony_ci  std::ostringstream spirv;
5514fd4e5da5Sopenharmony_ci  createVariablePointerSpirvProgram(&spirv,
5515fd4e5da5Sopenharmony_ci                                    "" /* Instructions to add to "main" */,
5516fd4e5da5Sopenharmony_ci                                    false /* Add VariablePointers Capability?*/,
5517fd4e5da5Sopenharmony_ci                                    true /* Use Helper Function? */);
5518fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.str());
5519fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5520fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
5521fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
5522fd4e5da5Sopenharmony_ci                  "OpReturnValue value's type <id> '7' is a pointer, "
5523fd4e5da5Sopenharmony_ci                  "which is invalid in the Logical addressing model.")));
5524fd4e5da5Sopenharmony_ci}
5525fd4e5da5Sopenharmony_ci
5526fd4e5da5Sopenharmony_ci// TODO: enable when this bug is fixed:
5527fd4e5da5Sopenharmony_ci// https://cvs.khronos.org/bugzilla/show_bug.cgi?id=15404
5528fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, DISABLED_OpReturnValueIsFunction) {
5529fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
5530fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
5531fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
5532fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %2
5533fd4e5da5Sopenharmony_ci%5 = OpFunction %2 None %3
5534fd4e5da5Sopenharmony_ci%6 = OpLabel
5535fd4e5da5Sopenharmony_ci     OpReturnValue %5
5536fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
5537fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5538fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5539fd4e5da5Sopenharmony_ci}
5540fd4e5da5Sopenharmony_ci
5541fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, UndefinedTypeId) {
5542fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
5543fd4e5da5Sopenharmony_ci%s = OpTypeStruct %i32
5544fd4e5da5Sopenharmony_ci)";
5545fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5546fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5547fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
5548fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
5549fd4e5da5Sopenharmony_ci                  "Operand '2[%2]' requires a previous definition")));
5550fd4e5da5Sopenharmony_ci}
5551fd4e5da5Sopenharmony_ci
5552fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, UndefinedIdScope) {
5553fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
5554fd4e5da5Sopenharmony_ci%u32    = OpTypeInt 32 0
5555fd4e5da5Sopenharmony_ci%memsem = OpConstant %u32 0
5556fd4e5da5Sopenharmony_ci%void   = OpTypeVoid
5557fd4e5da5Sopenharmony_ci%void_f = OpTypeFunction %void
5558fd4e5da5Sopenharmony_ci%f      = OpFunction %void None %void_f
5559fd4e5da5Sopenharmony_ci%l      = OpLabel
5560fd4e5da5Sopenharmony_ci          OpMemoryBarrier %undef %memsem
5561fd4e5da5Sopenharmony_ci          OpReturn
5562fd4e5da5Sopenharmony_ci          OpFunctionEnd
5563fd4e5da5Sopenharmony_ci)";
5564fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5565fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5566fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
5567fd4e5da5Sopenharmony_ci              HasSubstr(make_message("ID '7[%7]' has not been "
5568fd4e5da5Sopenharmony_ci                                     "defined")));
5569fd4e5da5Sopenharmony_ci}
5570fd4e5da5Sopenharmony_ci
5571fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, UndefinedIdMemSem) {
5572fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
5573fd4e5da5Sopenharmony_ci%u32    = OpTypeInt 32 0
5574fd4e5da5Sopenharmony_ci%scope  = OpConstant %u32 0
5575fd4e5da5Sopenharmony_ci%void   = OpTypeVoid
5576fd4e5da5Sopenharmony_ci%void_f = OpTypeFunction %void
5577fd4e5da5Sopenharmony_ci%f      = OpFunction %void None %void_f
5578fd4e5da5Sopenharmony_ci%l      = OpLabel
5579fd4e5da5Sopenharmony_ci          OpMemoryBarrier %scope %undef
5580fd4e5da5Sopenharmony_ci          OpReturn
5581fd4e5da5Sopenharmony_ci          OpFunctionEnd
5582fd4e5da5Sopenharmony_ci)";
5583fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5584fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5585fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
5586fd4e5da5Sopenharmony_ci              HasSubstr(make_message("ID '7[%7]' has not been "
5587fd4e5da5Sopenharmony_ci                                     "defined")));
5588fd4e5da5Sopenharmony_ci}
5589fd4e5da5Sopenharmony_ci
5590fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage,
5591fd4e5da5Sopenharmony_ci       KernelOpEntryPointAndOpInBoundsPtrAccessChainGood) {
5592fd4e5da5Sopenharmony_ci  std::string spirv = kOpenCLMemoryModel32 + R"(
5593fd4e5da5Sopenharmony_ci      OpEntryPoint Kernel %2 "simple_kernel"
5594fd4e5da5Sopenharmony_ci      OpSource OpenCL_C 200000
5595fd4e5da5Sopenharmony_ci      OpDecorate %3 BuiltIn GlobalInvocationId
5596fd4e5da5Sopenharmony_ci      OpDecorate %3 Constant
5597fd4e5da5Sopenharmony_ci      OpDecorate %4 FuncParamAttr NoCapture
5598fd4e5da5Sopenharmony_ci      OpDecorate %3 LinkageAttributes "__spirv_GlobalInvocationId" Import
5599fd4e5da5Sopenharmony_ci %5 = OpTypeInt 32 0
5600fd4e5da5Sopenharmony_ci %6 = OpTypeVector %5 3
5601fd4e5da5Sopenharmony_ci %7 = OpTypePointer UniformConstant %6
5602fd4e5da5Sopenharmony_ci %3 = OpVariable %7 UniformConstant
5603fd4e5da5Sopenharmony_ci %8 = OpTypeVoid
5604fd4e5da5Sopenharmony_ci %9 = OpTypeStruct %5
5605fd4e5da5Sopenharmony_ci%10 = OpTypePointer CrossWorkgroup %9
5606fd4e5da5Sopenharmony_ci%11 = OpTypeFunction %8 %10
5607fd4e5da5Sopenharmony_ci%12 = OpConstant %5 0
5608fd4e5da5Sopenharmony_ci%13 = OpTypePointer CrossWorkgroup %5
5609fd4e5da5Sopenharmony_ci%14 = OpConstant %5 42
5610fd4e5da5Sopenharmony_ci %2 = OpFunction %8 None %11
5611fd4e5da5Sopenharmony_ci %4 = OpFunctionParameter %10
5612fd4e5da5Sopenharmony_ci%15 = OpLabel
5613fd4e5da5Sopenharmony_ci%16 = OpLoad %6 %3 Aligned 0
5614fd4e5da5Sopenharmony_ci%17 = OpCompositeExtract %5 %16 0
5615fd4e5da5Sopenharmony_ci%18 = OpInBoundsPtrAccessChain %13 %4 %17 %12
5616fd4e5da5Sopenharmony_ci      OpStore %18 %14 Aligned 4
5617fd4e5da5Sopenharmony_ci      OpReturn
5618fd4e5da5Sopenharmony_ci      OpFunctionEnd)";
5619fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5620fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5621fd4e5da5Sopenharmony_ci}
5622fd4e5da5Sopenharmony_ci
5623fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpPtrAccessChainGood) {
5624fd4e5da5Sopenharmony_ci  std::string spirv = kOpenCLMemoryModel64 + R"(
5625fd4e5da5Sopenharmony_ci      OpEntryPoint Kernel %2 "another_kernel"
5626fd4e5da5Sopenharmony_ci      OpSource OpenCL_C 200000
5627fd4e5da5Sopenharmony_ci      OpDecorate %3 BuiltIn GlobalInvocationId
5628fd4e5da5Sopenharmony_ci      OpDecorate %3 Constant
5629fd4e5da5Sopenharmony_ci      OpDecorate %4 FuncParamAttr NoCapture
5630fd4e5da5Sopenharmony_ci      OpDecorate %3 LinkageAttributes "__spirv_GlobalInvocationId" Import
5631fd4e5da5Sopenharmony_ci %5 = OpTypeInt 64 0
5632fd4e5da5Sopenharmony_ci %6 = OpTypeVector %5 3
5633fd4e5da5Sopenharmony_ci %7 = OpTypePointer UniformConstant %6
5634fd4e5da5Sopenharmony_ci %3 = OpVariable %7 UniformConstant
5635fd4e5da5Sopenharmony_ci %8 = OpTypeVoid
5636fd4e5da5Sopenharmony_ci %9 = OpTypeInt 32 0
5637fd4e5da5Sopenharmony_ci%10 = OpTypeStruct %9
5638fd4e5da5Sopenharmony_ci%11 = OpTypePointer CrossWorkgroup %10
5639fd4e5da5Sopenharmony_ci%12 = OpTypeFunction %8 %11
5640fd4e5da5Sopenharmony_ci%13 = OpConstant %5 4294967295
5641fd4e5da5Sopenharmony_ci%14 = OpConstant %9 0
5642fd4e5da5Sopenharmony_ci%15 = OpTypePointer CrossWorkgroup %9
5643fd4e5da5Sopenharmony_ci%16 = OpConstant %9 42
5644fd4e5da5Sopenharmony_ci %2 = OpFunction %8 None %12
5645fd4e5da5Sopenharmony_ci %4 = OpFunctionParameter %11
5646fd4e5da5Sopenharmony_ci%17 = OpLabel
5647fd4e5da5Sopenharmony_ci%18 = OpLoad %6 %3 Aligned 0
5648fd4e5da5Sopenharmony_ci%19 = OpCompositeExtract %5 %18 0
5649fd4e5da5Sopenharmony_ci%20 = OpBitwiseAnd %5 %19 %13
5650fd4e5da5Sopenharmony_ci%21 = OpPtrAccessChain %15 %4 %20 %14
5651fd4e5da5Sopenharmony_ci      OpStore %21 %16 Aligned 4
5652fd4e5da5Sopenharmony_ci      OpReturn
5653fd4e5da5Sopenharmony_ci      OpFunctionEnd)";
5654fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5655fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5656fd4e5da5Sopenharmony_ci}
5657fd4e5da5Sopenharmony_ci
5658fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, StgBufOpPtrAccessChainGood) {
5659fd4e5da5Sopenharmony_ci  std::string spirv = R"(
5660fd4e5da5Sopenharmony_ci     OpCapability Shader
5661fd4e5da5Sopenharmony_ci     OpCapability Linkage
5662fd4e5da5Sopenharmony_ci     OpCapability VariablePointersStorageBuffer
5663fd4e5da5Sopenharmony_ci     OpExtension "SPV_KHR_variable_pointers"
5664fd4e5da5Sopenharmony_ci     OpMemoryModel Logical GLSL450
5665fd4e5da5Sopenharmony_ci     OpEntryPoint GLCompute %3 ""
5666fd4e5da5Sopenharmony_ci     OpDecorate %ptr ArrayStride 8
5667fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
5668fd4e5da5Sopenharmony_ci%int_2 = OpConstant %int 2
5669fd4e5da5Sopenharmony_ci%int_4 = OpConstant %int 4
5670fd4e5da5Sopenharmony_ci%struct = OpTypeStruct %int
5671fd4e5da5Sopenharmony_ci%array = OpTypeArray %struct %int_4
5672fd4e5da5Sopenharmony_ci%ptr = OpTypePointer StorageBuffer %array
5673fd4e5da5Sopenharmony_ci%var = OpVariable %ptr StorageBuffer
5674fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
5675fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %1
5676fd4e5da5Sopenharmony_ci%3 = OpFunction %1 None %2
5677fd4e5da5Sopenharmony_ci%4 = OpLabel
5678fd4e5da5Sopenharmony_ci%5 = OpPtrAccessChain %ptr %var %int_2
5679fd4e5da5Sopenharmony_ci     OpReturn
5680fd4e5da5Sopenharmony_ci     OpFunctionEnd
5681fd4e5da5Sopenharmony_ci)";
5682fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5683fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5684fd4e5da5Sopenharmony_ci}
5685fd4e5da5Sopenharmony_ci
5686fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpLoadBitcastPointerGood) {
5687fd4e5da5Sopenharmony_ci  std::string spirv = kOpenCLMemoryModel64 + R"(
5688fd4e5da5Sopenharmony_ci%2  = OpTypeVoid
5689fd4e5da5Sopenharmony_ci%3  = OpTypeInt 32 0
5690fd4e5da5Sopenharmony_ci%4  = OpTypeFloat 32
5691fd4e5da5Sopenharmony_ci%5  = OpTypePointer UniformConstant %3
5692fd4e5da5Sopenharmony_ci%6  = OpTypePointer UniformConstant %4
5693fd4e5da5Sopenharmony_ci%7  = OpVariable %5 UniformConstant
5694fd4e5da5Sopenharmony_ci%8  = OpTypeFunction %2
5695fd4e5da5Sopenharmony_ci%9  = OpFunction %2 None %8
5696fd4e5da5Sopenharmony_ci%10 = OpLabel
5697fd4e5da5Sopenharmony_ci%11 = OpBitcast %6 %7
5698fd4e5da5Sopenharmony_ci%12 = OpLoad %4 %11
5699fd4e5da5Sopenharmony_ci      OpReturn
5700fd4e5da5Sopenharmony_ci      OpFunctionEnd)";
5701fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5702fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5703fd4e5da5Sopenharmony_ci}
5704fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpLoadBitcastNonPointerBad) {
5705fd4e5da5Sopenharmony_ci  std::string spirv = kOpenCLMemoryModel64 + R"(
5706fd4e5da5Sopenharmony_ci%2  = OpTypeVoid
5707fd4e5da5Sopenharmony_ci%3  = OpTypeInt 32 0
5708fd4e5da5Sopenharmony_ci%4  = OpTypeFloat 32
5709fd4e5da5Sopenharmony_ci%5  = OpTypePointer UniformConstant %3
5710fd4e5da5Sopenharmony_ci%6  = OpTypeFunction %2
5711fd4e5da5Sopenharmony_ci%7  = OpVariable %5 UniformConstant
5712fd4e5da5Sopenharmony_ci%8  = OpFunction %2 None %6
5713fd4e5da5Sopenharmony_ci%9  = OpLabel
5714fd4e5da5Sopenharmony_ci%10 = OpLoad %3 %7
5715fd4e5da5Sopenharmony_ci%11 = OpBitcast %4 %10
5716fd4e5da5Sopenharmony_ci%12 = OpLoad %3 %11
5717fd4e5da5Sopenharmony_ci      OpReturn
5718fd4e5da5Sopenharmony_ci      OpFunctionEnd)";
5719fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5720fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5721fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
5722fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
5723fd4e5da5Sopenharmony_ci                  "OpLoad type for pointer <id> '11[%11]' is not a pointer "
5724fd4e5da5Sopenharmony_ci                  "type.")));
5725fd4e5da5Sopenharmony_ci}
5726fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpStoreBitcastPointerGood) {
5727fd4e5da5Sopenharmony_ci  std::string spirv = kOpenCLMemoryModel64 + R"(
5728fd4e5da5Sopenharmony_ci%2  = OpTypeVoid
5729fd4e5da5Sopenharmony_ci%3  = OpTypeInt 32 0
5730fd4e5da5Sopenharmony_ci%4  = OpTypeFloat 32
5731fd4e5da5Sopenharmony_ci%5  = OpTypePointer Function %3
5732fd4e5da5Sopenharmony_ci%6  = OpTypePointer Function %4
5733fd4e5da5Sopenharmony_ci%7  = OpTypeFunction %2
5734fd4e5da5Sopenharmony_ci%8  = OpConstant %3 42
5735fd4e5da5Sopenharmony_ci%9  = OpFunction %2 None %7
5736fd4e5da5Sopenharmony_ci%10 = OpLabel
5737fd4e5da5Sopenharmony_ci%11 = OpVariable %6 Function
5738fd4e5da5Sopenharmony_ci%12 = OpBitcast %5 %11
5739fd4e5da5Sopenharmony_ci      OpStore %12 %8
5740fd4e5da5Sopenharmony_ci      OpReturn
5741fd4e5da5Sopenharmony_ci      OpFunctionEnd)";
5742fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5743fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
5744fd4e5da5Sopenharmony_ci}
5745fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpStoreBitcastNonPointerBad) {
5746fd4e5da5Sopenharmony_ci  std::string spirv = kOpenCLMemoryModel64 + R"(
5747fd4e5da5Sopenharmony_ci%2  = OpTypeVoid
5748fd4e5da5Sopenharmony_ci%3  = OpTypeInt 32 0
5749fd4e5da5Sopenharmony_ci%4  = OpTypeFloat 32
5750fd4e5da5Sopenharmony_ci%5  = OpTypePointer Function %4
5751fd4e5da5Sopenharmony_ci%6  = OpTypeFunction %2
5752fd4e5da5Sopenharmony_ci%7  = OpConstant %4 42
5753fd4e5da5Sopenharmony_ci%8  = OpFunction %2 None %6
5754fd4e5da5Sopenharmony_ci%9  = OpLabel
5755fd4e5da5Sopenharmony_ci%10 = OpVariable %5 Function
5756fd4e5da5Sopenharmony_ci%11 = OpBitcast %3 %7
5757fd4e5da5Sopenharmony_ci      OpStore %11 %7
5758fd4e5da5Sopenharmony_ci      OpReturn
5759fd4e5da5Sopenharmony_ci      OpFunctionEnd)";
5760fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5761fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5762fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
5763fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
5764fd4e5da5Sopenharmony_ci                  "OpStore type for pointer <id> '11[%11]' is not a pointer "
5765fd4e5da5Sopenharmony_ci                  "type.")));
5766fd4e5da5Sopenharmony_ci}
5767fd4e5da5Sopenharmony_ci
5768fd4e5da5Sopenharmony_ci// Result <id> resulting from an instruction within a function may not be used
5769fd4e5da5Sopenharmony_ci// outside that function.
5770fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, ResultIdUsedOutsideOfFunctionBad) {
5771fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
5772fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
5773fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %1
5774fd4e5da5Sopenharmony_ci%3 = OpTypeInt 32 0
5775fd4e5da5Sopenharmony_ci%4 = OpTypePointer Function %3
5776fd4e5da5Sopenharmony_ci%5 = OpFunction %1 None %2
5777fd4e5da5Sopenharmony_ci%6 = OpLabel
5778fd4e5da5Sopenharmony_ci%7 = OpVariable %4 Function
5779fd4e5da5Sopenharmony_ciOpReturn
5780fd4e5da5Sopenharmony_ciOpFunctionEnd
5781fd4e5da5Sopenharmony_ci%8 = OpFunction %1 None %2
5782fd4e5da5Sopenharmony_ci%9 = OpLabel
5783fd4e5da5Sopenharmony_ci%10 = OpLoad %3 %7
5784fd4e5da5Sopenharmony_ciOpReturn
5785fd4e5da5Sopenharmony_ciOpFunctionEnd
5786fd4e5da5Sopenharmony_ci  )";
5787fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5788fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5789fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
5790fd4e5da5Sopenharmony_ci              HasSubstr(make_message("ID '7[%7]' defined in block '6[%6]' does "
5791fd4e5da5Sopenharmony_ci                                     "not dominate its use in block "
5792fd4e5da5Sopenharmony_ci                                     "'9[%9]'")));
5793fd4e5da5Sopenharmony_ci}
5794fd4e5da5Sopenharmony_ci
5795fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, SpecIdTargetNotSpecializationConstant) {
5796fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
5797fd4e5da5Sopenharmony_ciOpDecorate %1 SpecId 200
5798fd4e5da5Sopenharmony_ci%void = OpTypeVoid
5799fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %void
5800fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
5801fd4e5da5Sopenharmony_ci%1 = OpConstant %int 3
5802fd4e5da5Sopenharmony_ci%main = OpFunction %void None %2
5803fd4e5da5Sopenharmony_ci%4 = OpLabel
5804fd4e5da5Sopenharmony_ciOpReturnValue %1
5805fd4e5da5Sopenharmony_ciOpFunctionEnd
5806fd4e5da5Sopenharmony_ci  )";
5807fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5808fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5809fd4e5da5Sopenharmony_ci  EXPECT_THAT(
5810fd4e5da5Sopenharmony_ci      getDiagnosticString(),
5811fd4e5da5Sopenharmony_ci      HasSubstr(make_message("SpecId decoration on target <id> "
5812fd4e5da5Sopenharmony_ci                             "'1[%uint_3]' must be a scalar specialization "
5813fd4e5da5Sopenharmony_ci                             "constant")));
5814fd4e5da5Sopenharmony_ci}
5815fd4e5da5Sopenharmony_ci
5816fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, SpecIdTargetOpSpecConstantOpBad) {
5817fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
5818fd4e5da5Sopenharmony_ciOpDecorate %1 SpecId 200
5819fd4e5da5Sopenharmony_ci%void = OpTypeVoid
5820fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %void
5821fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
5822fd4e5da5Sopenharmony_ci%3 = OpConstant %int 1
5823fd4e5da5Sopenharmony_ci%4 = OpConstant %int 2
5824fd4e5da5Sopenharmony_ci%1 = OpSpecConstantOp %int IAdd %3 %4
5825fd4e5da5Sopenharmony_ci%main = OpFunction %void None %2
5826fd4e5da5Sopenharmony_ci%6 = OpLabel
5827fd4e5da5Sopenharmony_ciOpReturnValue %3
5828fd4e5da5Sopenharmony_ciOpFunctionEnd
5829fd4e5da5Sopenharmony_ci  )";
5830fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5831fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5832fd4e5da5Sopenharmony_ci  EXPECT_THAT(
5833fd4e5da5Sopenharmony_ci      getDiagnosticString(),
5834fd4e5da5Sopenharmony_ci      HasSubstr(make_message("SpecId decoration on target <id> '1[%1]' "
5835fd4e5da5Sopenharmony_ci                             "must be a scalar specialization constant")));
5836fd4e5da5Sopenharmony_ci}
5837fd4e5da5Sopenharmony_ci
5838fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, SpecIdTargetOpSpecConstantCompositeBad) {
5839fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
5840fd4e5da5Sopenharmony_ciOpDecorate %1 SpecId 200
5841fd4e5da5Sopenharmony_ci%void = OpTypeVoid
5842fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %void
5843fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
5844fd4e5da5Sopenharmony_ci%3 = OpConstant %int 1
5845fd4e5da5Sopenharmony_ci%1 = OpSpecConstantComposite %int
5846fd4e5da5Sopenharmony_ci%main = OpFunction %void None %2
5847fd4e5da5Sopenharmony_ci%4 = OpLabel
5848fd4e5da5Sopenharmony_ciOpReturnValue %3
5849fd4e5da5Sopenharmony_ciOpFunctionEnd
5850fd4e5da5Sopenharmony_ci  )";
5851fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5852fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5853fd4e5da5Sopenharmony_ci  EXPECT_THAT(
5854fd4e5da5Sopenharmony_ci      getDiagnosticString(),
5855fd4e5da5Sopenharmony_ci      HasSubstr(make_message("SpecId decoration on target <id> '1[%1]' "
5856fd4e5da5Sopenharmony_ci                             "must be a scalar specialization constant")));
5857fd4e5da5Sopenharmony_ci}
5858fd4e5da5Sopenharmony_ci
5859fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, SpecIdTargetGood) {
5860fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
5861fd4e5da5Sopenharmony_ciOpDecorate %3 SpecId 200
5862fd4e5da5Sopenharmony_ciOpDecorate %4 SpecId 201
5863fd4e5da5Sopenharmony_ciOpDecorate %5 SpecId 202
5864fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
5865fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %1
5866fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 0
5867fd4e5da5Sopenharmony_ci%bool = OpTypeBool
5868fd4e5da5Sopenharmony_ci%3 = OpSpecConstant %int 3
5869fd4e5da5Sopenharmony_ci%4 = OpSpecConstantTrue %bool
5870fd4e5da5Sopenharmony_ci%5 = OpSpecConstantFalse %bool
5871fd4e5da5Sopenharmony_ci%main = OpFunction %1 None %2
5872fd4e5da5Sopenharmony_ci%6 = OpLabel
5873fd4e5da5Sopenharmony_ciOpReturn
5874fd4e5da5Sopenharmony_ciOpFunctionEnd
5875fd4e5da5Sopenharmony_ci  )";
5876fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5877fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
5878fd4e5da5Sopenharmony_ci}
5879fd4e5da5Sopenharmony_ci
5880fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, CorrectErrorForShuffle) {
5881fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
5882fd4e5da5Sopenharmony_ci   %uint = OpTypeInt 32 0
5883fd4e5da5Sopenharmony_ci  %float = OpTypeFloat 32
5884fd4e5da5Sopenharmony_ci%v4float = OpTypeVector %float 4
5885fd4e5da5Sopenharmony_ci%v2float = OpTypeVector %float 2
5886fd4e5da5Sopenharmony_ci   %void = OpTypeVoid
5887fd4e5da5Sopenharmony_ci    %548 = OpTypeFunction %void
5888fd4e5da5Sopenharmony_ci     %CS = OpFunction %void None %548
5889fd4e5da5Sopenharmony_ci    %550 = OpLabel
5890fd4e5da5Sopenharmony_ci   %6275 = OpUndef %v2float
5891fd4e5da5Sopenharmony_ci   %6280 = OpUndef %v2float
5892fd4e5da5Sopenharmony_ci   %6282 = OpVectorShuffle %v4float %6275 %6280 0 1 4 5
5893fd4e5da5Sopenharmony_ci           OpReturn
5894fd4e5da5Sopenharmony_ci           OpFunctionEnd
5895fd4e5da5Sopenharmony_ci  )";
5896fd4e5da5Sopenharmony_ci
5897fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv.c_str());
5898fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5899fd4e5da5Sopenharmony_ci  EXPECT_THAT(
5900fd4e5da5Sopenharmony_ci      getDiagnosticString(),
5901fd4e5da5Sopenharmony_ci      HasSubstr(make_message(
5902fd4e5da5Sopenharmony_ci          "Component index 4 is out of bounds for combined (Vector1 + Vector2) "
5903fd4e5da5Sopenharmony_ci          "size of 4.")));
5904fd4e5da5Sopenharmony_ci  EXPECT_EQ(25, getErrorPosition().index);
5905fd4e5da5Sopenharmony_ci}
5906fd4e5da5Sopenharmony_ci
5907fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, VoidStructMember) {
5908fd4e5da5Sopenharmony_ci  const std::string spirv = kGLSL450MemoryModel + R"(
5909fd4e5da5Sopenharmony_ci%void = OpTypeVoid
5910fd4e5da5Sopenharmony_ci%struct = OpTypeStruct %void
5911fd4e5da5Sopenharmony_ci)";
5912fd4e5da5Sopenharmony_ci
5913fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
5914fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5915fd4e5da5Sopenharmony_ci  EXPECT_THAT(
5916fd4e5da5Sopenharmony_ci      getDiagnosticString(),
5917fd4e5da5Sopenharmony_ci      HasSubstr(make_message("Structures cannot contain a void type.")));
5918fd4e5da5Sopenharmony_ci}
5919fd4e5da5Sopenharmony_ci
5920fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, TypeFunctionBadUse) {
5921fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
5922fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
5923fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %1
5924fd4e5da5Sopenharmony_ci%3 = OpTypePointer Function %2
5925fd4e5da5Sopenharmony_ci%4 = OpFunction %1 None %2
5926fd4e5da5Sopenharmony_ci%5 = OpLabel
5927fd4e5da5Sopenharmony_ci     OpReturn
5928fd4e5da5Sopenharmony_ci     OpFunctionEnd)";
5929fd4e5da5Sopenharmony_ci
5930fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
5931fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5932fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
5933fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
5934fd4e5da5Sopenharmony_ci                  "Invalid use of function type result id '2[%2]'.")));
5935fd4e5da5Sopenharmony_ci}
5936fd4e5da5Sopenharmony_ci
5937fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, BadTypeId) {
5938fd4e5da5Sopenharmony_ci  std::string spirv = kGLSL450MemoryModel + R"(
5939fd4e5da5Sopenharmony_ci          %1 = OpTypeVoid
5940fd4e5da5Sopenharmony_ci          %2 = OpTypeFunction %1
5941fd4e5da5Sopenharmony_ci          %3 = OpTypeFloat 32
5942fd4e5da5Sopenharmony_ci          %4 = OpConstant %3 0
5943fd4e5da5Sopenharmony_ci          %5 = OpFunction %1 None %2
5944fd4e5da5Sopenharmony_ci          %6 = OpLabel
5945fd4e5da5Sopenharmony_ci          %7 = OpUndef %4
5946fd4e5da5Sopenharmony_ci               OpReturn
5947fd4e5da5Sopenharmony_ci               OpFunctionEnd
5948fd4e5da5Sopenharmony_ci)";
5949fd4e5da5Sopenharmony_ci
5950fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
5951fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
5952fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
5953fd4e5da5Sopenharmony_ci              HasSubstr(make_message("ID '4[%float_0]' is not a type "
5954fd4e5da5Sopenharmony_ci                                     "id")));
5955fd4e5da5Sopenharmony_ci}
5956fd4e5da5Sopenharmony_ci
5957fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, VulkanMemoryModelLoadMakePointerVisibleGood) {
5958fd4e5da5Sopenharmony_ci  std::string spirv = R"(
5959fd4e5da5Sopenharmony_ciOpCapability Shader
5960fd4e5da5Sopenharmony_ciOpCapability VulkanMemoryModelKHR
5961fd4e5da5Sopenharmony_ciOpCapability Linkage
5962fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_vulkan_memory_model"
5963fd4e5da5Sopenharmony_ciOpMemoryModel Logical VulkanKHR
5964fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
5965fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
5966fd4e5da5Sopenharmony_ci%3 = OpTypePointer Workgroup %2
5967fd4e5da5Sopenharmony_ci%4 = OpVariable %3 Workgroup
5968fd4e5da5Sopenharmony_ci%5 = OpTypeFunction %1
5969fd4e5da5Sopenharmony_ci%6 = OpConstant %2 2
5970fd4e5da5Sopenharmony_ci%7 = OpFunction %1 None %5
5971fd4e5da5Sopenharmony_ci%8 = OpLabel
5972fd4e5da5Sopenharmony_ci%9 = OpLoad %2 %4 NonPrivatePointerKHR|MakePointerVisibleKHR %6
5973fd4e5da5Sopenharmony_ciOpReturn
5974fd4e5da5Sopenharmony_ciOpFunctionEnd
5975fd4e5da5Sopenharmony_ci)";
5976fd4e5da5Sopenharmony_ci
5977fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
5978fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
5979fd4e5da5Sopenharmony_ci}
5980fd4e5da5Sopenharmony_ci
5981fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage,
5982fd4e5da5Sopenharmony_ci       VulkanMemoryModelLoadMakePointerVisibleMissingNonPrivatePointer) {
5983fd4e5da5Sopenharmony_ci  std::string spirv = R"(
5984fd4e5da5Sopenharmony_ciOpCapability Shader
5985fd4e5da5Sopenharmony_ciOpCapability VulkanMemoryModelKHR
5986fd4e5da5Sopenharmony_ciOpCapability Linkage
5987fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_vulkan_memory_model"
5988fd4e5da5Sopenharmony_ciOpMemoryModel Logical VulkanKHR
5989fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
5990fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
5991fd4e5da5Sopenharmony_ci%3 = OpTypePointer Workgroup %2
5992fd4e5da5Sopenharmony_ci%4 = OpVariable %3 Workgroup
5993fd4e5da5Sopenharmony_ci%5 = OpTypeFunction %1
5994fd4e5da5Sopenharmony_ci%6 = OpConstant %2 2
5995fd4e5da5Sopenharmony_ci%7 = OpFunction %1 None %5
5996fd4e5da5Sopenharmony_ci%8 = OpLabel
5997fd4e5da5Sopenharmony_ci%9 = OpLoad %2 %4 MakePointerVisibleKHR %6
5998fd4e5da5Sopenharmony_ciOpReturn
5999fd4e5da5Sopenharmony_ciOpFunctionEnd
6000fd4e5da5Sopenharmony_ci)";
6001fd4e5da5Sopenharmony_ci
6002fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6003fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6004fd4e5da5Sopenharmony_ci  EXPECT_THAT(
6005fd4e5da5Sopenharmony_ci      getDiagnosticString(),
6006fd4e5da5Sopenharmony_ci      HasSubstr(make_message("NonPrivatePointerKHR must be specified if "
6007fd4e5da5Sopenharmony_ci                             "MakePointerVisibleKHR is specified.")));
6008fd4e5da5Sopenharmony_ci}
6009fd4e5da5Sopenharmony_ci
6010fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage,
6011fd4e5da5Sopenharmony_ci       VulkanMemoryModelLoadNonPrivatePointerBadStorageClass) {
6012fd4e5da5Sopenharmony_ci  std::string spirv = R"(
6013fd4e5da5Sopenharmony_ciOpCapability Shader
6014fd4e5da5Sopenharmony_ciOpCapability VulkanMemoryModelKHR
6015fd4e5da5Sopenharmony_ciOpCapability Linkage
6016fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_vulkan_memory_model"
6017fd4e5da5Sopenharmony_ciOpMemoryModel Logical VulkanKHR
6018fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
6019fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
6020fd4e5da5Sopenharmony_ci%3 = OpTypePointer Private %2
6021fd4e5da5Sopenharmony_ci%4 = OpVariable %3 Private
6022fd4e5da5Sopenharmony_ci%5 = OpTypeFunction %1
6023fd4e5da5Sopenharmony_ci%6 = OpConstant %2 2
6024fd4e5da5Sopenharmony_ci%7 = OpFunction %1 None %5
6025fd4e5da5Sopenharmony_ci%8 = OpLabel
6026fd4e5da5Sopenharmony_ci%9 = OpLoad %2 %4 NonPrivatePointerKHR
6027fd4e5da5Sopenharmony_ciOpReturn
6028fd4e5da5Sopenharmony_ciOpFunctionEnd
6029fd4e5da5Sopenharmony_ci)";
6030fd4e5da5Sopenharmony_ci
6031fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6032fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6033fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
6034fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
6035fd4e5da5Sopenharmony_ci                  "NonPrivatePointerKHR requires a pointer in Uniform, "
6036fd4e5da5Sopenharmony_ci                  "Workgroup, CrossWorkgroup, Generic, Image or "
6037fd4e5da5Sopenharmony_ci                  "StorageBuffer storage classes.")));
6038fd4e5da5Sopenharmony_ci}
6039fd4e5da5Sopenharmony_ci
6040fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage,
6041fd4e5da5Sopenharmony_ci       VulkanMemoryModelLoadMakePointerAvailableCannotBeUsed) {
6042fd4e5da5Sopenharmony_ci  std::string spirv = R"(
6043fd4e5da5Sopenharmony_ciOpCapability Shader
6044fd4e5da5Sopenharmony_ciOpCapability VulkanMemoryModelKHR
6045fd4e5da5Sopenharmony_ciOpCapability Linkage
6046fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_vulkan_memory_model"
6047fd4e5da5Sopenharmony_ciOpMemoryModel Logical VulkanKHR
6048fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
6049fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
6050fd4e5da5Sopenharmony_ci%3 = OpTypePointer Workgroup %2
6051fd4e5da5Sopenharmony_ci%4 = OpVariable %3 Workgroup
6052fd4e5da5Sopenharmony_ci%5 = OpTypeFunction %1
6053fd4e5da5Sopenharmony_ci%6 = OpConstant %2 2
6054fd4e5da5Sopenharmony_ci%7 = OpFunction %1 None %5
6055fd4e5da5Sopenharmony_ci%8 = OpLabel
6056fd4e5da5Sopenharmony_ci%9 = OpLoad %2 %4 NonPrivatePointerKHR|MakePointerAvailableKHR %6
6057fd4e5da5Sopenharmony_ciOpReturn
6058fd4e5da5Sopenharmony_ciOpFunctionEnd
6059fd4e5da5Sopenharmony_ci)";
6060fd4e5da5Sopenharmony_ci
6061fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6062fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6063fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
6064fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
6065fd4e5da5Sopenharmony_ci                  "MakePointerAvailableKHR cannot be used with OpLoad")));
6066fd4e5da5Sopenharmony_ci}
6067fd4e5da5Sopenharmony_ci
6068fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, VulkanMemoryModelStoreMakePointerAvailableGood) {
6069fd4e5da5Sopenharmony_ci  std::string spirv = R"(
6070fd4e5da5Sopenharmony_ciOpCapability Shader
6071fd4e5da5Sopenharmony_ciOpCapability VulkanMemoryModelKHR
6072fd4e5da5Sopenharmony_ciOpCapability Linkage
6073fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_vulkan_memory_model"
6074fd4e5da5Sopenharmony_ciOpMemoryModel Logical VulkanKHR
6075fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
6076fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
6077fd4e5da5Sopenharmony_ci%3 = OpTypePointer Uniform %2
6078fd4e5da5Sopenharmony_ci%4 = OpVariable %3 Uniform
6079fd4e5da5Sopenharmony_ci%5 = OpTypeFunction %1
6080fd4e5da5Sopenharmony_ci%6 = OpConstant %2 5
6081fd4e5da5Sopenharmony_ci%7 = OpFunction %1 None %5
6082fd4e5da5Sopenharmony_ci%8 = OpLabel
6083fd4e5da5Sopenharmony_ciOpStore %4 %6 NonPrivatePointerKHR|MakePointerAvailableKHR %6
6084fd4e5da5Sopenharmony_ciOpReturn
6085fd4e5da5Sopenharmony_ciOpFunctionEnd
6086fd4e5da5Sopenharmony_ci)";
6087fd4e5da5Sopenharmony_ci
6088fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6089fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6090fd4e5da5Sopenharmony_ci}
6091fd4e5da5Sopenharmony_ci
6092fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage,
6093fd4e5da5Sopenharmony_ci       VulkanMemoryModelStoreMakePointerAvailableMissingNonPrivatePointer) {
6094fd4e5da5Sopenharmony_ci  std::string spirv = R"(
6095fd4e5da5Sopenharmony_ciOpCapability Shader
6096fd4e5da5Sopenharmony_ciOpCapability VulkanMemoryModelKHR
6097fd4e5da5Sopenharmony_ciOpCapability Linkage
6098fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_vulkan_memory_model"
6099fd4e5da5Sopenharmony_ciOpMemoryModel Logical VulkanKHR
6100fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
6101fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
6102fd4e5da5Sopenharmony_ci%3 = OpTypePointer Uniform %2
6103fd4e5da5Sopenharmony_ci%4 = OpVariable %3 Uniform
6104fd4e5da5Sopenharmony_ci%5 = OpTypeFunction %1
6105fd4e5da5Sopenharmony_ci%6 = OpConstant %2 5
6106fd4e5da5Sopenharmony_ci%7 = OpFunction %1 None %5
6107fd4e5da5Sopenharmony_ci%8 = OpLabel
6108fd4e5da5Sopenharmony_ciOpStore %4 %6 MakePointerAvailableKHR %6
6109fd4e5da5Sopenharmony_ciOpReturn
6110fd4e5da5Sopenharmony_ciOpFunctionEnd
6111fd4e5da5Sopenharmony_ci)";
6112fd4e5da5Sopenharmony_ci
6113fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6114fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6115fd4e5da5Sopenharmony_ci  EXPECT_THAT(
6116fd4e5da5Sopenharmony_ci      getDiagnosticString(),
6117fd4e5da5Sopenharmony_ci      HasSubstr(make_message("NonPrivatePointerKHR must be specified if "
6118fd4e5da5Sopenharmony_ci                             "MakePointerAvailableKHR is specified.")));
6119fd4e5da5Sopenharmony_ci}
6120fd4e5da5Sopenharmony_ci
6121fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage,
6122fd4e5da5Sopenharmony_ci       VulkanMemoryModelStoreNonPrivatePointerBadStorageClass) {
6123fd4e5da5Sopenharmony_ci  std::string spirv = R"(
6124fd4e5da5Sopenharmony_ciOpCapability Shader
6125fd4e5da5Sopenharmony_ciOpCapability VulkanMemoryModelKHR
6126fd4e5da5Sopenharmony_ciOpCapability Linkage
6127fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_vulkan_memory_model"
6128fd4e5da5Sopenharmony_ciOpMemoryModel Logical VulkanKHR
6129fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
6130fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
6131fd4e5da5Sopenharmony_ci%3 = OpTypePointer Output %2
6132fd4e5da5Sopenharmony_ci%4 = OpVariable %3 Output
6133fd4e5da5Sopenharmony_ci%5 = OpTypeFunction %1
6134fd4e5da5Sopenharmony_ci%6 = OpConstant %2 5
6135fd4e5da5Sopenharmony_ci%7 = OpFunction %1 None %5
6136fd4e5da5Sopenharmony_ci%8 = OpLabel
6137fd4e5da5Sopenharmony_ciOpStore %4 %6 NonPrivatePointerKHR
6138fd4e5da5Sopenharmony_ciOpReturn
6139fd4e5da5Sopenharmony_ciOpFunctionEnd
6140fd4e5da5Sopenharmony_ci)";
6141fd4e5da5Sopenharmony_ci
6142fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6143fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6144fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
6145fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
6146fd4e5da5Sopenharmony_ci                  "NonPrivatePointerKHR requires a pointer in Uniform, "
6147fd4e5da5Sopenharmony_ci                  "Workgroup, CrossWorkgroup, Generic, Image or "
6148fd4e5da5Sopenharmony_ci                  "StorageBuffer storage classes.")));
6149fd4e5da5Sopenharmony_ci}
6150fd4e5da5Sopenharmony_ci
6151fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage,
6152fd4e5da5Sopenharmony_ci       VulkanMemoryModelStoreMakePointerVisibleCannotBeUsed) {
6153fd4e5da5Sopenharmony_ci  std::string spirv = R"(
6154fd4e5da5Sopenharmony_ciOpCapability Shader
6155fd4e5da5Sopenharmony_ciOpCapability VulkanMemoryModelKHR
6156fd4e5da5Sopenharmony_ciOpCapability Linkage
6157fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_vulkan_memory_model"
6158fd4e5da5Sopenharmony_ciOpMemoryModel Logical VulkanKHR
6159fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
6160fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
6161fd4e5da5Sopenharmony_ci%3 = OpTypePointer Uniform %2
6162fd4e5da5Sopenharmony_ci%4 = OpVariable %3 Uniform
6163fd4e5da5Sopenharmony_ci%5 = OpTypeFunction %1
6164fd4e5da5Sopenharmony_ci%6 = OpConstant %2 5
6165fd4e5da5Sopenharmony_ci%7 = OpFunction %1 None %5
6166fd4e5da5Sopenharmony_ci%8 = OpLabel
6167fd4e5da5Sopenharmony_ciOpStore %4 %6 NonPrivatePointerKHR|MakePointerVisibleKHR %6
6168fd4e5da5Sopenharmony_ciOpReturn
6169fd4e5da5Sopenharmony_ciOpFunctionEnd
6170fd4e5da5Sopenharmony_ci)";
6171fd4e5da5Sopenharmony_ci
6172fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6173fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6174fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
6175fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
6176fd4e5da5Sopenharmony_ci                  "MakePointerVisibleKHR cannot be used with OpStore.")));
6177fd4e5da5Sopenharmony_ci}
6178fd4e5da5Sopenharmony_ci
6179fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, VulkanMemoryModelCopyMemoryAvailable) {
6180fd4e5da5Sopenharmony_ci  std::string spirv = R"(
6181fd4e5da5Sopenharmony_ciOpCapability Shader
6182fd4e5da5Sopenharmony_ciOpCapability Linkage
6183fd4e5da5Sopenharmony_ciOpCapability VulkanMemoryModelKHR
6184fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_vulkan_memory_model"
6185fd4e5da5Sopenharmony_ciOpMemoryModel Logical VulkanKHR
6186fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
6187fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
6188fd4e5da5Sopenharmony_ci%3 = OpTypePointer Workgroup %2
6189fd4e5da5Sopenharmony_ci%4 = OpVariable %3 Workgroup
6190fd4e5da5Sopenharmony_ci%5 = OpTypePointer Uniform %2
6191fd4e5da5Sopenharmony_ci%6 = OpVariable %5 Uniform
6192fd4e5da5Sopenharmony_ci%7 = OpConstant %2 2
6193fd4e5da5Sopenharmony_ci%8 = OpConstant %2 5
6194fd4e5da5Sopenharmony_ci%9 = OpTypeFunction %1
6195fd4e5da5Sopenharmony_ci%10 = OpFunction %1 None %9
6196fd4e5da5Sopenharmony_ci%11 = OpLabel
6197fd4e5da5Sopenharmony_ciOpCopyMemory %4 %6 NonPrivatePointerKHR|MakePointerAvailableKHR %7
6198fd4e5da5Sopenharmony_ciOpReturn
6199fd4e5da5Sopenharmony_ciOpFunctionEnd
6200fd4e5da5Sopenharmony_ci)";
6201fd4e5da5Sopenharmony_ci
6202fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6203fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6204fd4e5da5Sopenharmony_ci}
6205fd4e5da5Sopenharmony_ci
6206fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, VulkanMemoryModelCopyMemoryVisible) {
6207fd4e5da5Sopenharmony_ci  std::string spirv = R"(
6208fd4e5da5Sopenharmony_ciOpCapability Shader
6209fd4e5da5Sopenharmony_ciOpCapability Linkage
6210fd4e5da5Sopenharmony_ciOpCapability VulkanMemoryModelKHR
6211fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_vulkan_memory_model"
6212fd4e5da5Sopenharmony_ciOpMemoryModel Logical VulkanKHR
6213fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
6214fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
6215fd4e5da5Sopenharmony_ci%3 = OpTypePointer Workgroup %2
6216fd4e5da5Sopenharmony_ci%4 = OpVariable %3 Workgroup
6217fd4e5da5Sopenharmony_ci%5 = OpTypePointer Uniform %2
6218fd4e5da5Sopenharmony_ci%6 = OpVariable %5 Uniform
6219fd4e5da5Sopenharmony_ci%7 = OpConstant %2 2
6220fd4e5da5Sopenharmony_ci%8 = OpConstant %2 5
6221fd4e5da5Sopenharmony_ci%9 = OpTypeFunction %1
6222fd4e5da5Sopenharmony_ci%10 = OpFunction %1 None %9
6223fd4e5da5Sopenharmony_ci%11 = OpLabel
6224fd4e5da5Sopenharmony_ciOpCopyMemory %4 %6 NonPrivatePointerKHR|MakePointerVisibleKHR %8
6225fd4e5da5Sopenharmony_ciOpReturn
6226fd4e5da5Sopenharmony_ciOpFunctionEnd
6227fd4e5da5Sopenharmony_ci)";
6228fd4e5da5Sopenharmony_ci
6229fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6230fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6231fd4e5da5Sopenharmony_ci}
6232fd4e5da5Sopenharmony_ci
6233fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, VulkanMemoryModelCopyMemoryAvailableAndVisible) {
6234fd4e5da5Sopenharmony_ci  std::string spirv = R"(
6235fd4e5da5Sopenharmony_ciOpCapability Shader
6236fd4e5da5Sopenharmony_ciOpCapability Linkage
6237fd4e5da5Sopenharmony_ciOpCapability VulkanMemoryModelKHR
6238fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_vulkan_memory_model"
6239fd4e5da5Sopenharmony_ciOpMemoryModel Logical VulkanKHR
6240fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
6241fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
6242fd4e5da5Sopenharmony_ci%3 = OpTypePointer Workgroup %2
6243fd4e5da5Sopenharmony_ci%4 = OpVariable %3 Workgroup
6244fd4e5da5Sopenharmony_ci%5 = OpTypePointer Uniform %2
6245fd4e5da5Sopenharmony_ci%6 = OpVariable %5 Uniform
6246fd4e5da5Sopenharmony_ci%7 = OpConstant %2 2
6247fd4e5da5Sopenharmony_ci%8 = OpConstant %2 5
6248fd4e5da5Sopenharmony_ci%9 = OpTypeFunction %1
6249fd4e5da5Sopenharmony_ci%10 = OpFunction %1 None %9
6250fd4e5da5Sopenharmony_ci%11 = OpLabel
6251fd4e5da5Sopenharmony_ciOpCopyMemory %4 %6 NonPrivatePointerKHR|MakePointerAvailableKHR|MakePointerVisibleKHR %7 %8
6252fd4e5da5Sopenharmony_ciOpReturn
6253fd4e5da5Sopenharmony_ciOpFunctionEnd
6254fd4e5da5Sopenharmony_ci)";
6255fd4e5da5Sopenharmony_ci
6256fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6257fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6258fd4e5da5Sopenharmony_ci}
6259fd4e5da5Sopenharmony_ci
6260fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage,
6261fd4e5da5Sopenharmony_ci       VulkanMemoryModelCopyMemoryAvailableMissingNonPrivatePointer) {
6262fd4e5da5Sopenharmony_ci  std::string spirv = R"(
6263fd4e5da5Sopenharmony_ciOpCapability Shader
6264fd4e5da5Sopenharmony_ciOpCapability Linkage
6265fd4e5da5Sopenharmony_ciOpCapability VulkanMemoryModelKHR
6266fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_vulkan_memory_model"
6267fd4e5da5Sopenharmony_ciOpMemoryModel Logical VulkanKHR
6268fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
6269fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
6270fd4e5da5Sopenharmony_ci%3 = OpTypePointer Workgroup %2
6271fd4e5da5Sopenharmony_ci%4 = OpVariable %3 Workgroup
6272fd4e5da5Sopenharmony_ci%5 = OpTypePointer Uniform %2
6273fd4e5da5Sopenharmony_ci%6 = OpVariable %5 Uniform
6274fd4e5da5Sopenharmony_ci%7 = OpConstant %2 2
6275fd4e5da5Sopenharmony_ci%8 = OpConstant %2 5
6276fd4e5da5Sopenharmony_ci%9 = OpTypeFunction %1
6277fd4e5da5Sopenharmony_ci%10 = OpFunction %1 None %9
6278fd4e5da5Sopenharmony_ci%11 = OpLabel
6279fd4e5da5Sopenharmony_ciOpCopyMemory %4 %6 MakePointerAvailableKHR %7
6280fd4e5da5Sopenharmony_ciOpReturn
6281fd4e5da5Sopenharmony_ciOpFunctionEnd
6282fd4e5da5Sopenharmony_ci)";
6283fd4e5da5Sopenharmony_ci
6284fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6285fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6286fd4e5da5Sopenharmony_ci  EXPECT_THAT(
6287fd4e5da5Sopenharmony_ci      getDiagnosticString(),
6288fd4e5da5Sopenharmony_ci      HasSubstr(make_message("NonPrivatePointerKHR must be specified if "
6289fd4e5da5Sopenharmony_ci                             "MakePointerAvailableKHR is specified.")));
6290fd4e5da5Sopenharmony_ci}
6291fd4e5da5Sopenharmony_ci
6292fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage,
6293fd4e5da5Sopenharmony_ci       VulkanMemoryModelCopyMemoryVisibleMissingNonPrivatePointer) {
6294fd4e5da5Sopenharmony_ci  std::string spirv = R"(
6295fd4e5da5Sopenharmony_ciOpCapability Shader
6296fd4e5da5Sopenharmony_ciOpCapability Linkage
6297fd4e5da5Sopenharmony_ciOpCapability VulkanMemoryModelKHR
6298fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_vulkan_memory_model"
6299fd4e5da5Sopenharmony_ciOpMemoryModel Logical VulkanKHR
6300fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
6301fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
6302fd4e5da5Sopenharmony_ci%3 = OpTypePointer Workgroup %2
6303fd4e5da5Sopenharmony_ci%4 = OpVariable %3 Workgroup
6304fd4e5da5Sopenharmony_ci%5 = OpTypePointer Uniform %2
6305fd4e5da5Sopenharmony_ci%6 = OpVariable %5 Uniform
6306fd4e5da5Sopenharmony_ci%7 = OpConstant %2 2
6307fd4e5da5Sopenharmony_ci%8 = OpConstant %2 5
6308fd4e5da5Sopenharmony_ci%9 = OpTypeFunction %1
6309fd4e5da5Sopenharmony_ci%10 = OpFunction %1 None %9
6310fd4e5da5Sopenharmony_ci%11 = OpLabel
6311fd4e5da5Sopenharmony_ciOpCopyMemory %4 %6 MakePointerVisibleKHR %8
6312fd4e5da5Sopenharmony_ciOpReturn
6313fd4e5da5Sopenharmony_ciOpFunctionEnd
6314fd4e5da5Sopenharmony_ci)";
6315fd4e5da5Sopenharmony_ci
6316fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6317fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6318fd4e5da5Sopenharmony_ci  EXPECT_THAT(
6319fd4e5da5Sopenharmony_ci      getDiagnosticString(),
6320fd4e5da5Sopenharmony_ci      HasSubstr(make_message("NonPrivatePointerKHR must be specified if "
6321fd4e5da5Sopenharmony_ci                             "MakePointerVisibleKHR is specified.")));
6322fd4e5da5Sopenharmony_ci}
6323fd4e5da5Sopenharmony_ci
6324fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage,
6325fd4e5da5Sopenharmony_ci       VulkanMemoryModelCopyMemoryAvailableBadStorageClass) {
6326fd4e5da5Sopenharmony_ci  std::string spirv = R"(
6327fd4e5da5Sopenharmony_ciOpCapability Shader
6328fd4e5da5Sopenharmony_ciOpCapability Linkage
6329fd4e5da5Sopenharmony_ciOpCapability VulkanMemoryModelKHR
6330fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_vulkan_memory_model"
6331fd4e5da5Sopenharmony_ciOpMemoryModel Logical VulkanKHR
6332fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
6333fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
6334fd4e5da5Sopenharmony_ci%3 = OpTypePointer Output %2
6335fd4e5da5Sopenharmony_ci%4 = OpVariable %3 Output
6336fd4e5da5Sopenharmony_ci%5 = OpTypePointer Uniform %2
6337fd4e5da5Sopenharmony_ci%6 = OpVariable %5 Uniform
6338fd4e5da5Sopenharmony_ci%7 = OpConstant %2 2
6339fd4e5da5Sopenharmony_ci%8 = OpConstant %2 5
6340fd4e5da5Sopenharmony_ci%9 = OpTypeFunction %1
6341fd4e5da5Sopenharmony_ci%10 = OpFunction %1 None %9
6342fd4e5da5Sopenharmony_ci%11 = OpLabel
6343fd4e5da5Sopenharmony_ciOpCopyMemory %4 %6 NonPrivatePointerKHR
6344fd4e5da5Sopenharmony_ciOpReturn
6345fd4e5da5Sopenharmony_ciOpFunctionEnd
6346fd4e5da5Sopenharmony_ci)";
6347fd4e5da5Sopenharmony_ci
6348fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6349fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6350fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
6351fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
6352fd4e5da5Sopenharmony_ci                  "NonPrivatePointerKHR requires a pointer in Uniform, "
6353fd4e5da5Sopenharmony_ci                  "Workgroup, CrossWorkgroup, Generic, Image or "
6354fd4e5da5Sopenharmony_ci                  "StorageBuffer storage classes.")));
6355fd4e5da5Sopenharmony_ci}
6356fd4e5da5Sopenharmony_ci
6357fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage,
6358fd4e5da5Sopenharmony_ci       VulkanMemoryModelCopyMemoryVisibleBadStorageClass) {
6359fd4e5da5Sopenharmony_ci  std::string spirv = R"(
6360fd4e5da5Sopenharmony_ciOpCapability Shader
6361fd4e5da5Sopenharmony_ciOpCapability Linkage
6362fd4e5da5Sopenharmony_ciOpCapability VulkanMemoryModelKHR
6363fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_vulkan_memory_model"
6364fd4e5da5Sopenharmony_ciOpMemoryModel Logical VulkanKHR
6365fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
6366fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
6367fd4e5da5Sopenharmony_ci%3 = OpTypePointer Workgroup %2
6368fd4e5da5Sopenharmony_ci%4 = OpVariable %3 Workgroup
6369fd4e5da5Sopenharmony_ci%5 = OpTypePointer Input %2
6370fd4e5da5Sopenharmony_ci%6 = OpVariable %5 Input
6371fd4e5da5Sopenharmony_ci%7 = OpConstant %2 2
6372fd4e5da5Sopenharmony_ci%8 = OpConstant %2 5
6373fd4e5da5Sopenharmony_ci%9 = OpTypeFunction %1
6374fd4e5da5Sopenharmony_ci%10 = OpFunction %1 None %9
6375fd4e5da5Sopenharmony_ci%11 = OpLabel
6376fd4e5da5Sopenharmony_ciOpCopyMemory %4 %6 NonPrivatePointerKHR
6377fd4e5da5Sopenharmony_ciOpReturn
6378fd4e5da5Sopenharmony_ciOpFunctionEnd
6379fd4e5da5Sopenharmony_ci)";
6380fd4e5da5Sopenharmony_ci
6381fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6382fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6383fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
6384fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
6385fd4e5da5Sopenharmony_ci                  "NonPrivatePointerKHR requires a pointer in Uniform, "
6386fd4e5da5Sopenharmony_ci                  "Workgroup, CrossWorkgroup, Generic, Image or "
6387fd4e5da5Sopenharmony_ci                  "StorageBuffer storage classes.")));
6388fd4e5da5Sopenharmony_ci}
6389fd4e5da5Sopenharmony_ci
6390fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, VulkanMemoryModelCopyMemorySizedAvailable) {
6391fd4e5da5Sopenharmony_ci  std::string spirv = R"(
6392fd4e5da5Sopenharmony_ciOpCapability Shader
6393fd4e5da5Sopenharmony_ciOpCapability Linkage
6394fd4e5da5Sopenharmony_ciOpCapability Addresses
6395fd4e5da5Sopenharmony_ciOpCapability VulkanMemoryModelKHR
6396fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_vulkan_memory_model"
6397fd4e5da5Sopenharmony_ciOpMemoryModel Logical VulkanKHR
6398fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
6399fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
6400fd4e5da5Sopenharmony_ci%3 = OpTypePointer Workgroup %2
6401fd4e5da5Sopenharmony_ci%4 = OpVariable %3 Workgroup
6402fd4e5da5Sopenharmony_ci%5 = OpTypePointer Uniform %2
6403fd4e5da5Sopenharmony_ci%6 = OpVariable %5 Uniform
6404fd4e5da5Sopenharmony_ci%7 = OpConstant %2 2
6405fd4e5da5Sopenharmony_ci%8 = OpConstant %2 5
6406fd4e5da5Sopenharmony_ci%9 = OpTypeFunction %1
6407fd4e5da5Sopenharmony_ci%10 = OpFunction %1 None %9
6408fd4e5da5Sopenharmony_ci%11 = OpLabel
6409fd4e5da5Sopenharmony_ciOpCopyMemorySized %4 %6 %7 NonPrivatePointerKHR|MakePointerAvailableKHR %7
6410fd4e5da5Sopenharmony_ciOpReturn
6411fd4e5da5Sopenharmony_ciOpFunctionEnd
6412fd4e5da5Sopenharmony_ci)";
6413fd4e5da5Sopenharmony_ci
6414fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6415fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6416fd4e5da5Sopenharmony_ci}
6417fd4e5da5Sopenharmony_ci
6418fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, VulkanMemoryModelCopyMemorySizedVisible) {
6419fd4e5da5Sopenharmony_ci  std::string spirv = R"(
6420fd4e5da5Sopenharmony_ciOpCapability Shader
6421fd4e5da5Sopenharmony_ciOpCapability Linkage
6422fd4e5da5Sopenharmony_ciOpCapability Addresses
6423fd4e5da5Sopenharmony_ciOpCapability VulkanMemoryModelKHR
6424fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_vulkan_memory_model"
6425fd4e5da5Sopenharmony_ciOpMemoryModel Logical VulkanKHR
6426fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
6427fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
6428fd4e5da5Sopenharmony_ci%3 = OpTypePointer Workgroup %2
6429fd4e5da5Sopenharmony_ci%4 = OpVariable %3 Workgroup
6430fd4e5da5Sopenharmony_ci%5 = OpTypePointer Uniform %2
6431fd4e5da5Sopenharmony_ci%6 = OpVariable %5 Uniform
6432fd4e5da5Sopenharmony_ci%7 = OpConstant %2 2
6433fd4e5da5Sopenharmony_ci%8 = OpConstant %2 5
6434fd4e5da5Sopenharmony_ci%9 = OpTypeFunction %1
6435fd4e5da5Sopenharmony_ci%10 = OpFunction %1 None %9
6436fd4e5da5Sopenharmony_ci%11 = OpLabel
6437fd4e5da5Sopenharmony_ciOpCopyMemorySized %4 %6 %7 NonPrivatePointerKHR|MakePointerVisibleKHR %8
6438fd4e5da5Sopenharmony_ciOpReturn
6439fd4e5da5Sopenharmony_ciOpFunctionEnd
6440fd4e5da5Sopenharmony_ci)";
6441fd4e5da5Sopenharmony_ci
6442fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6443fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6444fd4e5da5Sopenharmony_ci}
6445fd4e5da5Sopenharmony_ci
6446fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage,
6447fd4e5da5Sopenharmony_ci       VulkanMemoryModelCopyMemorySizedAvailableAndVisible) {
6448fd4e5da5Sopenharmony_ci  std::string spirv = R"(
6449fd4e5da5Sopenharmony_ciOpCapability Shader
6450fd4e5da5Sopenharmony_ciOpCapability Linkage
6451fd4e5da5Sopenharmony_ciOpCapability Addresses
6452fd4e5da5Sopenharmony_ciOpCapability VulkanMemoryModelKHR
6453fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_vulkan_memory_model"
6454fd4e5da5Sopenharmony_ciOpMemoryModel Logical VulkanKHR
6455fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
6456fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
6457fd4e5da5Sopenharmony_ci%3 = OpTypePointer Workgroup %2
6458fd4e5da5Sopenharmony_ci%4 = OpVariable %3 Workgroup
6459fd4e5da5Sopenharmony_ci%5 = OpTypePointer Uniform %2
6460fd4e5da5Sopenharmony_ci%6 = OpVariable %5 Uniform
6461fd4e5da5Sopenharmony_ci%7 = OpConstant %2 2
6462fd4e5da5Sopenharmony_ci%8 = OpConstant %2 5
6463fd4e5da5Sopenharmony_ci%9 = OpTypeFunction %1
6464fd4e5da5Sopenharmony_ci%10 = OpFunction %1 None %9
6465fd4e5da5Sopenharmony_ci%11 = OpLabel
6466fd4e5da5Sopenharmony_ciOpCopyMemorySized %4 %6 %7 NonPrivatePointerKHR|MakePointerAvailableKHR|MakePointerVisibleKHR %7 %8
6467fd4e5da5Sopenharmony_ciOpReturn
6468fd4e5da5Sopenharmony_ciOpFunctionEnd
6469fd4e5da5Sopenharmony_ci)";
6470fd4e5da5Sopenharmony_ci
6471fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6472fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6473fd4e5da5Sopenharmony_ci}
6474fd4e5da5Sopenharmony_ci
6475fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage,
6476fd4e5da5Sopenharmony_ci       VulkanMemoryModelCopyMemorySizedAvailableMissingNonPrivatePointer) {
6477fd4e5da5Sopenharmony_ci  std::string spirv = R"(
6478fd4e5da5Sopenharmony_ciOpCapability Shader
6479fd4e5da5Sopenharmony_ciOpCapability Linkage
6480fd4e5da5Sopenharmony_ciOpCapability Addresses
6481fd4e5da5Sopenharmony_ciOpCapability VulkanMemoryModelKHR
6482fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_vulkan_memory_model"
6483fd4e5da5Sopenharmony_ciOpMemoryModel Logical VulkanKHR
6484fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
6485fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
6486fd4e5da5Sopenharmony_ci%3 = OpTypePointer Workgroup %2
6487fd4e5da5Sopenharmony_ci%4 = OpVariable %3 Workgroup
6488fd4e5da5Sopenharmony_ci%5 = OpTypePointer Uniform %2
6489fd4e5da5Sopenharmony_ci%6 = OpVariable %5 Uniform
6490fd4e5da5Sopenharmony_ci%7 = OpConstant %2 2
6491fd4e5da5Sopenharmony_ci%8 = OpConstant %2 5
6492fd4e5da5Sopenharmony_ci%9 = OpTypeFunction %1
6493fd4e5da5Sopenharmony_ci%10 = OpFunction %1 None %9
6494fd4e5da5Sopenharmony_ci%11 = OpLabel
6495fd4e5da5Sopenharmony_ciOpCopyMemorySized %4 %6 %7 MakePointerAvailableKHR %7
6496fd4e5da5Sopenharmony_ciOpReturn
6497fd4e5da5Sopenharmony_ciOpFunctionEnd
6498fd4e5da5Sopenharmony_ci)";
6499fd4e5da5Sopenharmony_ci
6500fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6501fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6502fd4e5da5Sopenharmony_ci  EXPECT_THAT(
6503fd4e5da5Sopenharmony_ci      getDiagnosticString(),
6504fd4e5da5Sopenharmony_ci      HasSubstr(make_message("NonPrivatePointerKHR must be specified if "
6505fd4e5da5Sopenharmony_ci                             "MakePointerAvailableKHR is specified.")));
6506fd4e5da5Sopenharmony_ci}
6507fd4e5da5Sopenharmony_ci
6508fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage,
6509fd4e5da5Sopenharmony_ci       VulkanMemoryModelCopyMemorySizedVisibleMissingNonPrivatePointer) {
6510fd4e5da5Sopenharmony_ci  std::string spirv = R"(
6511fd4e5da5Sopenharmony_ciOpCapability Shader
6512fd4e5da5Sopenharmony_ciOpCapability Linkage
6513fd4e5da5Sopenharmony_ciOpCapability Addresses
6514fd4e5da5Sopenharmony_ciOpCapability VulkanMemoryModelKHR
6515fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_vulkan_memory_model"
6516fd4e5da5Sopenharmony_ciOpMemoryModel Logical VulkanKHR
6517fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
6518fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
6519fd4e5da5Sopenharmony_ci%3 = OpTypePointer Workgroup %2
6520fd4e5da5Sopenharmony_ci%4 = OpVariable %3 Workgroup
6521fd4e5da5Sopenharmony_ci%5 = OpTypePointer Uniform %2
6522fd4e5da5Sopenharmony_ci%6 = OpVariable %5 Uniform
6523fd4e5da5Sopenharmony_ci%7 = OpConstant %2 2
6524fd4e5da5Sopenharmony_ci%8 = OpConstant %2 5
6525fd4e5da5Sopenharmony_ci%9 = OpTypeFunction %1
6526fd4e5da5Sopenharmony_ci%10 = OpFunction %1 None %9
6527fd4e5da5Sopenharmony_ci%11 = OpLabel
6528fd4e5da5Sopenharmony_ciOpCopyMemorySized %4 %6 %7 MakePointerVisibleKHR %8
6529fd4e5da5Sopenharmony_ciOpReturn
6530fd4e5da5Sopenharmony_ciOpFunctionEnd
6531fd4e5da5Sopenharmony_ci)";
6532fd4e5da5Sopenharmony_ci
6533fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6534fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6535fd4e5da5Sopenharmony_ci  EXPECT_THAT(
6536fd4e5da5Sopenharmony_ci      getDiagnosticString(),
6537fd4e5da5Sopenharmony_ci      HasSubstr(make_message("NonPrivatePointerKHR must be specified if "
6538fd4e5da5Sopenharmony_ci                             "MakePointerVisibleKHR is specified.")));
6539fd4e5da5Sopenharmony_ci}
6540fd4e5da5Sopenharmony_ci
6541fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage,
6542fd4e5da5Sopenharmony_ci       VulkanMemoryModelCopyMemorySizedAvailableBadStorageClass) {
6543fd4e5da5Sopenharmony_ci  std::string spirv = R"(
6544fd4e5da5Sopenharmony_ciOpCapability Shader
6545fd4e5da5Sopenharmony_ciOpCapability Linkage
6546fd4e5da5Sopenharmony_ciOpCapability Addresses
6547fd4e5da5Sopenharmony_ciOpCapability VulkanMemoryModelKHR
6548fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_vulkan_memory_model"
6549fd4e5da5Sopenharmony_ciOpMemoryModel Logical VulkanKHR
6550fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
6551fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
6552fd4e5da5Sopenharmony_ci%3 = OpTypePointer Output %2
6553fd4e5da5Sopenharmony_ci%4 = OpVariable %3 Output
6554fd4e5da5Sopenharmony_ci%5 = OpTypePointer Uniform %2
6555fd4e5da5Sopenharmony_ci%6 = OpVariable %5 Uniform
6556fd4e5da5Sopenharmony_ci%7 = OpConstant %2 2
6557fd4e5da5Sopenharmony_ci%8 = OpConstant %2 5
6558fd4e5da5Sopenharmony_ci%9 = OpTypeFunction %1
6559fd4e5da5Sopenharmony_ci%10 = OpFunction %1 None %9
6560fd4e5da5Sopenharmony_ci%11 = OpLabel
6561fd4e5da5Sopenharmony_ciOpCopyMemorySized %4 %6 %7 NonPrivatePointerKHR
6562fd4e5da5Sopenharmony_ciOpReturn
6563fd4e5da5Sopenharmony_ciOpFunctionEnd
6564fd4e5da5Sopenharmony_ci)";
6565fd4e5da5Sopenharmony_ci
6566fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6567fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6568fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
6569fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
6570fd4e5da5Sopenharmony_ci                  "NonPrivatePointerKHR requires a pointer in Uniform, "
6571fd4e5da5Sopenharmony_ci                  "Workgroup, CrossWorkgroup, Generic, Image or "
6572fd4e5da5Sopenharmony_ci                  "StorageBuffer storage classes.")));
6573fd4e5da5Sopenharmony_ci}
6574fd4e5da5Sopenharmony_ci
6575fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage,
6576fd4e5da5Sopenharmony_ci       VulkanMemoryModelCopyMemorySizedVisibleBadStorageClass) {
6577fd4e5da5Sopenharmony_ci  std::string spirv = R"(
6578fd4e5da5Sopenharmony_ciOpCapability Shader
6579fd4e5da5Sopenharmony_ciOpCapability Linkage
6580fd4e5da5Sopenharmony_ciOpCapability Addresses
6581fd4e5da5Sopenharmony_ciOpCapability VulkanMemoryModelKHR
6582fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_vulkan_memory_model"
6583fd4e5da5Sopenharmony_ciOpMemoryModel Logical VulkanKHR
6584fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
6585fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 0
6586fd4e5da5Sopenharmony_ci%3 = OpTypePointer Workgroup %2
6587fd4e5da5Sopenharmony_ci%4 = OpVariable %3 Workgroup
6588fd4e5da5Sopenharmony_ci%5 = OpTypePointer Input %2
6589fd4e5da5Sopenharmony_ci%6 = OpVariable %5 Input
6590fd4e5da5Sopenharmony_ci%7 = OpConstant %2 2
6591fd4e5da5Sopenharmony_ci%8 = OpConstant %2 5
6592fd4e5da5Sopenharmony_ci%9 = OpTypeFunction %1
6593fd4e5da5Sopenharmony_ci%10 = OpFunction %1 None %9
6594fd4e5da5Sopenharmony_ci%11 = OpLabel
6595fd4e5da5Sopenharmony_ciOpCopyMemorySized %4 %6 %7 NonPrivatePointerKHR
6596fd4e5da5Sopenharmony_ciOpReturn
6597fd4e5da5Sopenharmony_ciOpFunctionEnd
6598fd4e5da5Sopenharmony_ci)";
6599fd4e5da5Sopenharmony_ci
6600fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6601fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6602fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
6603fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
6604fd4e5da5Sopenharmony_ci                  "NonPrivatePointerKHR requires a pointer in Uniform, "
6605fd4e5da5Sopenharmony_ci                  "Workgroup, CrossWorkgroup, Generic, Image or "
6606fd4e5da5Sopenharmony_ci                  "StorageBuffer storage classes.")));
6607fd4e5da5Sopenharmony_ci}
6608fd4e5da5Sopenharmony_ci
6609fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, IdDefInUnreachableBlock1) {
6610fd4e5da5Sopenharmony_ci  const std::string spirv = kNoKernelGLSL450MemoryModel + R"(
6611fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
6612fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %1
6613fd4e5da5Sopenharmony_ci%3 = OpTypeFloat 32
6614fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %3
6615fd4e5da5Sopenharmony_ci%5 = OpFunction %1 None %2
6616fd4e5da5Sopenharmony_ci%6 = OpLabel
6617fd4e5da5Sopenharmony_ciOpReturn
6618fd4e5da5Sopenharmony_ci%7 = OpLabel
6619fd4e5da5Sopenharmony_ci%8 = OpFunctionCall %3 %9
6620fd4e5da5Sopenharmony_ciOpUnreachable
6621fd4e5da5Sopenharmony_ciOpFunctionEnd
6622fd4e5da5Sopenharmony_ci%9 = OpFunction %3 None %4
6623fd4e5da5Sopenharmony_ci%10 = OpLabel
6624fd4e5da5Sopenharmony_ciOpReturnValue %8
6625fd4e5da5Sopenharmony_ciOpFunctionEnd
6626fd4e5da5Sopenharmony_ci)";
6627fd4e5da5Sopenharmony_ci
6628fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6629fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6630fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
6631fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
6632fd4e5da5Sopenharmony_ci                  "ID '8[%8]' defined in block '7[%7]' does not dominate its "
6633fd4e5da5Sopenharmony_ci                  "use in block '10[%10]'\n  %10 = OpLabel")));
6634fd4e5da5Sopenharmony_ci}
6635fd4e5da5Sopenharmony_ci
6636fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, IdDefInUnreachableBlock2) {
6637fd4e5da5Sopenharmony_ci  const std::string spirv = kNoKernelGLSL450MemoryModel + R"(
6638fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
6639fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %1
6640fd4e5da5Sopenharmony_ci%3 = OpTypeFloat 32
6641fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %3
6642fd4e5da5Sopenharmony_ci%5 = OpFunction %1 None %2
6643fd4e5da5Sopenharmony_ci%6 = OpLabel
6644fd4e5da5Sopenharmony_ciOpReturn
6645fd4e5da5Sopenharmony_ci%7 = OpLabel
6646fd4e5da5Sopenharmony_ci%8 = OpFunctionCall %3 %9
6647fd4e5da5Sopenharmony_ciOpUnreachable
6648fd4e5da5Sopenharmony_ciOpFunctionEnd
6649fd4e5da5Sopenharmony_ci%9 = OpFunction %3 None %4
6650fd4e5da5Sopenharmony_ci%10 = OpLabel
6651fd4e5da5Sopenharmony_ciOpReturnValue %8
6652fd4e5da5Sopenharmony_ciOpFunctionEnd
6653fd4e5da5Sopenharmony_ci)";
6654fd4e5da5Sopenharmony_ci
6655fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6656fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6657fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
6658fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
6659fd4e5da5Sopenharmony_ci                  "ID '8[%8]' defined in block '7[%7]' does not dominate its "
6660fd4e5da5Sopenharmony_ci                  "use in block '10[%10]'\n  %10 = OpLabel")));
6661fd4e5da5Sopenharmony_ci}
6662fd4e5da5Sopenharmony_ci
6663fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, IdDefInUnreachableBlock3) {
6664fd4e5da5Sopenharmony_ci  const std::string spirv = kNoKernelGLSL450MemoryModel + R"(
6665fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
6666fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %1
6667fd4e5da5Sopenharmony_ci%3 = OpTypeFloat 32
6668fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %3
6669fd4e5da5Sopenharmony_ci%5 = OpFunction %1 None %2
6670fd4e5da5Sopenharmony_ci%6 = OpLabel
6671fd4e5da5Sopenharmony_ciOpReturn
6672fd4e5da5Sopenharmony_ci%7 = OpLabel
6673fd4e5da5Sopenharmony_ci%8 = OpFunctionCall %3 %9
6674fd4e5da5Sopenharmony_ciOpReturn
6675fd4e5da5Sopenharmony_ciOpFunctionEnd
6676fd4e5da5Sopenharmony_ci%9 = OpFunction %3 None %4
6677fd4e5da5Sopenharmony_ci%10 = OpLabel
6678fd4e5da5Sopenharmony_ciOpReturnValue %8
6679fd4e5da5Sopenharmony_ciOpFunctionEnd
6680fd4e5da5Sopenharmony_ci)";
6681fd4e5da5Sopenharmony_ci
6682fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6683fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6684fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
6685fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
6686fd4e5da5Sopenharmony_ci                  "ID '8[%8]' defined in block '7[%7]' does not dominate its "
6687fd4e5da5Sopenharmony_ci                  "use in block '10[%10]'\n  %10 = OpLabel")));
6688fd4e5da5Sopenharmony_ci}
6689fd4e5da5Sopenharmony_ci
6690fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, IdDefInUnreachableBlock4) {
6691fd4e5da5Sopenharmony_ci  const std::string spirv = kNoKernelGLSL450MemoryModel + R"(
6692fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
6693fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %1
6694fd4e5da5Sopenharmony_ci%3 = OpTypeFloat 32
6695fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %3
6696fd4e5da5Sopenharmony_ci%5 = OpFunction %1 None %2
6697fd4e5da5Sopenharmony_ci%6 = OpLabel
6698fd4e5da5Sopenharmony_ciOpReturn
6699fd4e5da5Sopenharmony_ci%7 = OpLabel
6700fd4e5da5Sopenharmony_ci%8 = OpUndef %3
6701fd4e5da5Sopenharmony_ci%9 = OpCopyObject %3 %8
6702fd4e5da5Sopenharmony_ciOpReturn
6703fd4e5da5Sopenharmony_ciOpFunctionEnd
6704fd4e5da5Sopenharmony_ci)";
6705fd4e5da5Sopenharmony_ci
6706fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6707fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6708fd4e5da5Sopenharmony_ci}
6709fd4e5da5Sopenharmony_ci
6710fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, IdDefInUnreachableBlock5) {
6711fd4e5da5Sopenharmony_ci  const std::string spirv = kNoKernelGLSL450MemoryModel + R"(
6712fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
6713fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %1
6714fd4e5da5Sopenharmony_ci%3 = OpTypeFloat 32
6715fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %3
6716fd4e5da5Sopenharmony_ci%5 = OpFunction %1 None %2
6717fd4e5da5Sopenharmony_ci%6 = OpLabel
6718fd4e5da5Sopenharmony_ciOpReturn
6719fd4e5da5Sopenharmony_ci%7 = OpLabel
6720fd4e5da5Sopenharmony_ci%8 = OpUndef %3
6721fd4e5da5Sopenharmony_ciOpBranch %9
6722fd4e5da5Sopenharmony_ci%9 = OpLabel
6723fd4e5da5Sopenharmony_ci%10 = OpCopyObject %3 %8
6724fd4e5da5Sopenharmony_ciOpReturn
6725fd4e5da5Sopenharmony_ciOpFunctionEnd
6726fd4e5da5Sopenharmony_ci)";
6727fd4e5da5Sopenharmony_ci
6728fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6729fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6730fd4e5da5Sopenharmony_ci}
6731fd4e5da5Sopenharmony_ci
6732fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, IdDefInUnreachableBlock6) {
6733fd4e5da5Sopenharmony_ci  const std::string spirv = kNoKernelGLSL450MemoryModel + R"(
6734fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
6735fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %1
6736fd4e5da5Sopenharmony_ci%3 = OpTypeFloat 32
6737fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %3
6738fd4e5da5Sopenharmony_ci%5 = OpFunction %1 None %2
6739fd4e5da5Sopenharmony_ci%6 = OpLabel
6740fd4e5da5Sopenharmony_ciOpBranch %7
6741fd4e5da5Sopenharmony_ci%8 = OpLabel
6742fd4e5da5Sopenharmony_ci%9 = OpUndef %3
6743fd4e5da5Sopenharmony_ciOpBranch %7
6744fd4e5da5Sopenharmony_ci%7 = OpLabel
6745fd4e5da5Sopenharmony_ci%10 = OpCopyObject %3 %9
6746fd4e5da5Sopenharmony_ciOpReturn
6747fd4e5da5Sopenharmony_ciOpFunctionEnd
6748fd4e5da5Sopenharmony_ci)";
6749fd4e5da5Sopenharmony_ci
6750fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6751fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6752fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
6753fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
6754fd4e5da5Sopenharmony_ci                  "ID '9[%9]' defined in block '8[%8]' does not dominate its "
6755fd4e5da5Sopenharmony_ci                  "use in block '7[%7]'\n  %7 = OpLabel")));
6756fd4e5da5Sopenharmony_ci}
6757fd4e5da5Sopenharmony_ci
6758fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, ReachableDefUnreachableUse) {
6759fd4e5da5Sopenharmony_ci  const std::string spirv = kNoKernelGLSL450MemoryModel + R"(
6760fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
6761fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %1
6762fd4e5da5Sopenharmony_ci%3 = OpTypeFloat 32
6763fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %3
6764fd4e5da5Sopenharmony_ci%5 = OpFunction %1 None %2
6765fd4e5da5Sopenharmony_ci%6 = OpLabel
6766fd4e5da5Sopenharmony_ci%7 = OpUndef %3
6767fd4e5da5Sopenharmony_ciOpReturn
6768fd4e5da5Sopenharmony_ci%8 = OpLabel
6769fd4e5da5Sopenharmony_ci%9 = OpCopyObject %3 %7
6770fd4e5da5Sopenharmony_ciOpReturn
6771fd4e5da5Sopenharmony_ciOpFunctionEnd
6772fd4e5da5Sopenharmony_ci)";
6773fd4e5da5Sopenharmony_ci
6774fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6775fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6776fd4e5da5Sopenharmony_ci}
6777fd4e5da5Sopenharmony_ci
6778fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, UnreachableDefUsedInPhi) {
6779fd4e5da5Sopenharmony_ci  const std::string spirv = kNoKernelGLSL450MemoryModel + R"(
6780fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
6781fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %void
6782fd4e5da5Sopenharmony_ci      %float = OpTypeFloat 32
6783fd4e5da5Sopenharmony_ci       %bool = OpTypeBool
6784fd4e5da5Sopenharmony_ci          %6 = OpTypeFunction %float
6785fd4e5da5Sopenharmony_ci          %1 = OpFunction %void None %3
6786fd4e5da5Sopenharmony_ci          %7 = OpLabel
6787fd4e5da5Sopenharmony_ci          %8 = OpUndef %bool
6788fd4e5da5Sopenharmony_ci               OpSelectionMerge %9 None
6789fd4e5da5Sopenharmony_ci               OpBranchConditional %8 %10 %9
6790fd4e5da5Sopenharmony_ci         %10 = OpLabel
6791fd4e5da5Sopenharmony_ci         %11 = OpUndef %float
6792fd4e5da5Sopenharmony_ci               OpBranch %9
6793fd4e5da5Sopenharmony_ci         %12 = OpLabel
6794fd4e5da5Sopenharmony_ci         %13 = OpUndef %float
6795fd4e5da5Sopenharmony_ci               OpUnreachable
6796fd4e5da5Sopenharmony_ci          %9 = OpLabel
6797fd4e5da5Sopenharmony_ci         %14 = OpPhi %float %11 %10 %13 %7
6798fd4e5da5Sopenharmony_ci               OpReturn
6799fd4e5da5Sopenharmony_ci               OpFunctionEnd
6800fd4e5da5Sopenharmony_ci)";
6801fd4e5da5Sopenharmony_ci
6802fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6803fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6804fd4e5da5Sopenharmony_ci  EXPECT_THAT(
6805fd4e5da5Sopenharmony_ci      getDiagnosticString(),
6806fd4e5da5Sopenharmony_ci      HasSubstr(make_message(
6807fd4e5da5Sopenharmony_ci          "In OpPhi instruction '14[%14]', ID '13[%13]' definition does not "
6808fd4e5da5Sopenharmony_ci          "dominate its parent '7[%7]'\n  %14 = OpPhi %float %11 %10 %13 "
6809fd4e5da5Sopenharmony_ci          "%7")));
6810fd4e5da5Sopenharmony_ci}
6811fd4e5da5Sopenharmony_ci
6812fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpTypeForwardPointerNotAPointerType) {
6813fd4e5da5Sopenharmony_ci  std::string spirv = R"(
6814fd4e5da5Sopenharmony_ci     OpCapability GenericPointer
6815fd4e5da5Sopenharmony_ci     OpCapability VariablePointersStorageBuffer
6816fd4e5da5Sopenharmony_ci     OpMemoryModel Logical GLSL450
6817fd4e5da5Sopenharmony_ci     OpEntryPoint Fragment %1 "main"
6818fd4e5da5Sopenharmony_ci     OpExecutionMode %1 OriginLowerLeft
6819fd4e5da5Sopenharmony_ci     OpTypeForwardPointer %2 CrossWorkgroup
6820fd4e5da5Sopenharmony_ci%2 = OpTypeVoid
6821fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %2
6822fd4e5da5Sopenharmony_ci%1 = OpFunction %2 DontInline %3
6823fd4e5da5Sopenharmony_ci%4 = OpLabel
6824fd4e5da5Sopenharmony_ci     OpReturn
6825fd4e5da5Sopenharmony_ci     OpFunctionEnd
6826fd4e5da5Sopenharmony_ci)";
6827fd4e5da5Sopenharmony_ci
6828fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6829fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6830fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
6831fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
6832fd4e5da5Sopenharmony_ci                  "Pointer type in OpTypeForwardPointer is not a pointer "
6833fd4e5da5Sopenharmony_ci                  "type.\n  OpTypeForwardPointer %void CrossWorkgroup")));
6834fd4e5da5Sopenharmony_ci}
6835fd4e5da5Sopenharmony_ci
6836fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, OpTypeForwardPointerWrongStorageClass) {
6837fd4e5da5Sopenharmony_ci  std::string spirv = R"(
6838fd4e5da5Sopenharmony_ci     OpCapability GenericPointer
6839fd4e5da5Sopenharmony_ci     OpCapability VariablePointersStorageBuffer
6840fd4e5da5Sopenharmony_ci     OpMemoryModel Logical GLSL450
6841fd4e5da5Sopenharmony_ci     OpEntryPoint Fragment %1 "main"
6842fd4e5da5Sopenharmony_ci     OpExecutionMode %1 OriginLowerLeft
6843fd4e5da5Sopenharmony_ci     OpTypeForwardPointer %2 CrossWorkgroup
6844fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1
6845fd4e5da5Sopenharmony_ci%2 = OpTypePointer Function %int
6846fd4e5da5Sopenharmony_ci%void = OpTypeVoid
6847fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %void
6848fd4e5da5Sopenharmony_ci%1 = OpFunction %void None %3
6849fd4e5da5Sopenharmony_ci%4 = OpLabel
6850fd4e5da5Sopenharmony_ci     OpReturn
6851fd4e5da5Sopenharmony_ci     OpFunctionEnd
6852fd4e5da5Sopenharmony_ci)";
6853fd4e5da5Sopenharmony_ci
6854fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6855fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6856fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
6857fd4e5da5Sopenharmony_ci              HasSubstr(make_message(
6858fd4e5da5Sopenharmony_ci                  "Storage class in OpTypeForwardPointer does not match the "
6859fd4e5da5Sopenharmony_ci                  "pointer definition.\n  OpTypeForwardPointer "
6860fd4e5da5Sopenharmony_ci                  "%_ptr_Function_int CrossWorkgroup")));
6861fd4e5da5Sopenharmony_ci}
6862fd4e5da5Sopenharmony_ci
6863fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, MissingForwardPointer) {
6864fd4e5da5Sopenharmony_ci  const std::string spirv = R"(
6865fd4e5da5Sopenharmony_ci               OpCapability Linkage
6866fd4e5da5Sopenharmony_ci               OpCapability Shader
6867fd4e5da5Sopenharmony_ci               OpMemoryModel Logical Simple
6868fd4e5da5Sopenharmony_ci      %float = OpTypeFloat 32
6869fd4e5da5Sopenharmony_ci  %_struct_9 = OpTypeStruct %float %_ptr_Uniform__struct_9
6870fd4e5da5Sopenharmony_ci%_ptr_Uniform__struct_9 = OpTypePointer Uniform %_struct_9
6871fd4e5da5Sopenharmony_ci       %1278 = OpVariable %_ptr_Uniform__struct_9 Uniform
6872fd4e5da5Sopenharmony_ci)";
6873fd4e5da5Sopenharmony_ci
6874fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv);
6875fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
6876fd4e5da5Sopenharmony_ci  EXPECT_THAT(getDiagnosticString(),
6877fd4e5da5Sopenharmony_ci              HasSubstr(make_message("Operand '3[%_ptr_Uniform__struct_2]' "
6878fd4e5da5Sopenharmony_ci                                     "requires a previous definition")));
6879fd4e5da5Sopenharmony_ci}
6880fd4e5da5Sopenharmony_ci
6881fd4e5da5Sopenharmony_ciTEST_P(ValidateIdWithMessage, NVBindlessSamplerInStruct) {
6882fd4e5da5Sopenharmony_ci  std::string spirv = R"(
6883fd4e5da5Sopenharmony_ci            OpCapability Shader
6884fd4e5da5Sopenharmony_ci            OpCapability BindlessTextureNV
6885fd4e5da5Sopenharmony_ci            OpExtension "SPV_NV_bindless_texture"
6886fd4e5da5Sopenharmony_ci            OpMemoryModel Logical GLSL450
6887fd4e5da5Sopenharmony_ci            OpSamplerImageAddressingModeNV 64
6888fd4e5da5Sopenharmony_ci            OpEntryPoint Fragment %main "main"
6889fd4e5da5Sopenharmony_ci            OpExecutionMode %main OriginUpperLeft
6890fd4e5da5Sopenharmony_ci    %void = OpTypeVoid
6891fd4e5da5Sopenharmony_ci       %3 = OpTypeFunction %void
6892fd4e5da5Sopenharmony_ci   %float = OpTypeFloat 32
6893fd4e5da5Sopenharmony_ci       %7 = OpTypeImage %float 2D 0 0 0 1 Unknown
6894fd4e5da5Sopenharmony_ci       %8 = OpTypeSampledImage %7
6895fd4e5da5Sopenharmony_ci       %9 = OpTypeImage %float 2D 0 0 0 2 Rgba32f
6896fd4e5da5Sopenharmony_ci      %10 = OpTypeSampler
6897fd4e5da5Sopenharmony_ci     %UBO = OpTypeStruct %8 %9 %10
6898fd4e5da5Sopenharmony_ci%_ptr_Uniform_UBO = OpTypePointer Uniform %UBO
6899fd4e5da5Sopenharmony_ci       %_ = OpVariable %_ptr_Uniform_UBO Uniform
6900fd4e5da5Sopenharmony_ci    %main = OpFunction %void None %3
6901fd4e5da5Sopenharmony_ci       %5 = OpLabel
6902fd4e5da5Sopenharmony_ci            OpReturn
6903fd4e5da5Sopenharmony_ci            OpFunctionEnd
6904fd4e5da5Sopenharmony_ci)";
6905fd4e5da5Sopenharmony_ci
6906fd4e5da5Sopenharmony_ci  CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_3);
6907fd4e5da5Sopenharmony_ci  EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
6908fd4e5da5Sopenharmony_ci}
6909fd4e5da5Sopenharmony_ci
6910fd4e5da5Sopenharmony_ciINSTANTIATE_TEST_SUITE_P(, ValidateIdWithMessage, ::testing::Bool());
6911fd4e5da5Sopenharmony_ci
6912fd4e5da5Sopenharmony_ci}  // namespace
6913fd4e5da5Sopenharmony_ci}  // namespace val
6914fd4e5da5Sopenharmony_ci}  // namespace spvtools
6915