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