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