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// Validation tests for SSA 16fd4e5da5Sopenharmony_ci 17fd4e5da5Sopenharmony_ci#include <sstream> 18fd4e5da5Sopenharmony_ci#include <string> 19fd4e5da5Sopenharmony_ci#include <utility> 20fd4e5da5Sopenharmony_ci 21fd4e5da5Sopenharmony_ci#include "gmock/gmock.h" 22fd4e5da5Sopenharmony_ci#include "test/unit_spirv.h" 23fd4e5da5Sopenharmony_ci#include "test/val/val_fixtures.h" 24fd4e5da5Sopenharmony_ci 25fd4e5da5Sopenharmony_cinamespace spvtools { 26fd4e5da5Sopenharmony_cinamespace val { 27fd4e5da5Sopenharmony_cinamespace { 28fd4e5da5Sopenharmony_ci 29fd4e5da5Sopenharmony_ciusing ::testing::HasSubstr; 30fd4e5da5Sopenharmony_ciusing ::testing::MatchesRegex; 31fd4e5da5Sopenharmony_ci 32fd4e5da5Sopenharmony_ciusing ValidateSSA = spvtest::ValidateBase<std::pair<std::string, bool>>; 33fd4e5da5Sopenharmony_ci 34fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, Default) { 35fd4e5da5Sopenharmony_ci char str[] = R"( 36fd4e5da5Sopenharmony_ci OpCapability Shader 37fd4e5da5Sopenharmony_ci OpCapability Linkage 38fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 39fd4e5da5Sopenharmony_ci OpEntryPoint GLCompute %3 "" 40fd4e5da5Sopenharmony_ci OpExecutionMode %3 LocalSize 1 1 1 41fd4e5da5Sopenharmony_ci%1 = OpTypeVoid 42fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %1 43fd4e5da5Sopenharmony_ci%3 = OpFunction %1 None %2 44fd4e5da5Sopenharmony_ci%4 = OpLabel 45fd4e5da5Sopenharmony_ci OpReturn 46fd4e5da5Sopenharmony_ci OpFunctionEnd 47fd4e5da5Sopenharmony_ci)"; 48fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 49fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); 50fd4e5da5Sopenharmony_ci} 51fd4e5da5Sopenharmony_ci 52fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, IdUndefinedBad) { 53fd4e5da5Sopenharmony_ci char str[] = R"( 54fd4e5da5Sopenharmony_ci OpCapability Shader 55fd4e5da5Sopenharmony_ci OpCapability Linkage 56fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 57fd4e5da5Sopenharmony_ci OpName %missing "missing" 58fd4e5da5Sopenharmony_ci%voidt = OpTypeVoid 59fd4e5da5Sopenharmony_ci%vfunct = OpTypeFunction %voidt 60fd4e5da5Sopenharmony_ci%func = OpFunction %vfunct None %missing 61fd4e5da5Sopenharmony_ci%flabel = OpLabel 62fd4e5da5Sopenharmony_ci OpReturn 63fd4e5da5Sopenharmony_ci OpFunctionEnd 64fd4e5da5Sopenharmony_ci )"; 65fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 66fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 67fd4e5da5Sopenharmony_ci EXPECT_THAT(getDiagnosticString(), HasSubstr("missing")); 68fd4e5da5Sopenharmony_ci} 69fd4e5da5Sopenharmony_ci 70fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, IdRedefinedBad) { 71fd4e5da5Sopenharmony_ci char str[] = R"( 72fd4e5da5Sopenharmony_ci OpCapability Shader 73fd4e5da5Sopenharmony_ci OpCapability Linkage 74fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 75fd4e5da5Sopenharmony_ci OpName %2 "redefined" 76fd4e5da5Sopenharmony_ci%1 = OpTypeVoid 77fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %1 78fd4e5da5Sopenharmony_ci%2 = OpFunction %1 None %2 79fd4e5da5Sopenharmony_ci%4 = OpLabel 80fd4e5da5Sopenharmony_ci OpReturn 81fd4e5da5Sopenharmony_ci OpFunctionEnd 82fd4e5da5Sopenharmony_ci)"; 83fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 84fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 85fd4e5da5Sopenharmony_ci} 86fd4e5da5Sopenharmony_ci 87fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, DominateUsageBad) { 88fd4e5da5Sopenharmony_ci char str[] = R"( 89fd4e5da5Sopenharmony_ci OpCapability Shader 90fd4e5da5Sopenharmony_ci OpCapability Linkage 91fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 92fd4e5da5Sopenharmony_ci OpName %1 "not_dominant" 93fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %1 ; uses %1 before it's definition 94fd4e5da5Sopenharmony_ci%1 = OpTypeVoid 95fd4e5da5Sopenharmony_ci)"; 96fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 97fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 98fd4e5da5Sopenharmony_ci EXPECT_THAT(getDiagnosticString(), HasSubstr("not_dominant")); 99fd4e5da5Sopenharmony_ci} 100fd4e5da5Sopenharmony_ci 101fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, DominateUsageWithinBlockBad) { 102fd4e5da5Sopenharmony_ci char str[] = R"( 103fd4e5da5Sopenharmony_ci OpCapability Shader 104fd4e5da5Sopenharmony_ci OpCapability Linkage 105fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 106fd4e5da5Sopenharmony_ci OpName %bad "bad" 107fd4e5da5Sopenharmony_ci%voidt = OpTypeVoid 108fd4e5da5Sopenharmony_ci%funct = OpTypeFunction %voidt 109fd4e5da5Sopenharmony_ci%uintt = OpTypeInt 32 0 110fd4e5da5Sopenharmony_ci%one = OpConstant %uintt 1 111fd4e5da5Sopenharmony_ci%func = OpFunction %voidt None %funct 112fd4e5da5Sopenharmony_ci%entry = OpLabel 113fd4e5da5Sopenharmony_ci%sum = OpIAdd %uintt %one %bad 114fd4e5da5Sopenharmony_ci%bad = OpCopyObject %uintt %sum 115fd4e5da5Sopenharmony_ci OpReturn 116fd4e5da5Sopenharmony_ci OpFunctionEnd 117fd4e5da5Sopenharmony_ci)"; 118fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 119fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 120fd4e5da5Sopenharmony_ci EXPECT_THAT(getDiagnosticString(), 121fd4e5da5Sopenharmony_ci MatchesRegex("ID '.\\[%bad\\]' has not been defined\n" 122fd4e5da5Sopenharmony_ci " %8 = OpIAdd %uint %uint_1 %bad\n")); 123fd4e5da5Sopenharmony_ci} 124fd4e5da5Sopenharmony_ci 125fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, DominateUsageSameInstructionBad) { 126fd4e5da5Sopenharmony_ci char str[] = R"( 127fd4e5da5Sopenharmony_ci OpCapability Shader 128fd4e5da5Sopenharmony_ci OpCapability Linkage 129fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 130fd4e5da5Sopenharmony_ci OpName %sum "sum" 131fd4e5da5Sopenharmony_ci%voidt = OpTypeVoid 132fd4e5da5Sopenharmony_ci%funct = OpTypeFunction %voidt 133fd4e5da5Sopenharmony_ci%uintt = OpTypeInt 32 0 134fd4e5da5Sopenharmony_ci%one = OpConstant %uintt 1 135fd4e5da5Sopenharmony_ci%func = OpFunction %voidt None %funct 136fd4e5da5Sopenharmony_ci%entry = OpLabel 137fd4e5da5Sopenharmony_ci%sum = OpIAdd %uintt %one %sum 138fd4e5da5Sopenharmony_ci OpReturn 139fd4e5da5Sopenharmony_ci OpFunctionEnd 140fd4e5da5Sopenharmony_ci)"; 141fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 142fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 143fd4e5da5Sopenharmony_ci EXPECT_THAT(getDiagnosticString(), 144fd4e5da5Sopenharmony_ci MatchesRegex("ID '.\\[%sum\\]' has not been defined\n" 145fd4e5da5Sopenharmony_ci " %sum = OpIAdd %uint %uint_1 %sum\n")); 146fd4e5da5Sopenharmony_ci} 147fd4e5da5Sopenharmony_ci 148fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardNameGood) { 149fd4e5da5Sopenharmony_ci char str[] = R"( 150fd4e5da5Sopenharmony_ci OpCapability Shader 151fd4e5da5Sopenharmony_ci OpCapability Linkage 152fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 153fd4e5da5Sopenharmony_ci OpName %3 "main" 154fd4e5da5Sopenharmony_ci%1 = OpTypeVoid 155fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %1 156fd4e5da5Sopenharmony_ci%3 = OpFunction %1 None %2 157fd4e5da5Sopenharmony_ci%4 = OpLabel 158fd4e5da5Sopenharmony_ci OpReturn 159fd4e5da5Sopenharmony_ci OpFunctionEnd 160fd4e5da5Sopenharmony_ci)"; 161fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 162fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); 163fd4e5da5Sopenharmony_ci} 164fd4e5da5Sopenharmony_ci 165fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardNameMissingTargetBad) { 166fd4e5da5Sopenharmony_ci char str[] = R"( 167fd4e5da5Sopenharmony_ci OpCapability Shader 168fd4e5da5Sopenharmony_ci OpCapability Linkage 169fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 170fd4e5da5Sopenharmony_ci OpName %5 "main" ; Target never defined 171fd4e5da5Sopenharmony_ci)"; 172fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 173fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 174fd4e5da5Sopenharmony_ci EXPECT_THAT(getDiagnosticString(), HasSubstr("main")); 175fd4e5da5Sopenharmony_ci} 176fd4e5da5Sopenharmony_ci 177fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardMemberNameGood) { 178fd4e5da5Sopenharmony_ci char str[] = R"( 179fd4e5da5Sopenharmony_ci OpCapability Shader 180fd4e5da5Sopenharmony_ci OpCapability Linkage 181fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 182fd4e5da5Sopenharmony_ci OpMemberName %struct 0 "value" 183fd4e5da5Sopenharmony_ci OpMemberName %struct 1 "size" 184fd4e5da5Sopenharmony_ci%intt = OpTypeInt 32 1 185fd4e5da5Sopenharmony_ci%uintt = OpTypeInt 32 0 186fd4e5da5Sopenharmony_ci%struct = OpTypeStruct %intt %uintt 187fd4e5da5Sopenharmony_ci)"; 188fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 189fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); 190fd4e5da5Sopenharmony_ci} 191fd4e5da5Sopenharmony_ci 192fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardMemberNameMissingTargetBad) { 193fd4e5da5Sopenharmony_ci char str[] = R"( 194fd4e5da5Sopenharmony_ci OpCapability Shader 195fd4e5da5Sopenharmony_ci OpCapability Linkage 196fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 197fd4e5da5Sopenharmony_ci OpMemberName %struct 0 "value" 198fd4e5da5Sopenharmony_ci OpMemberName %bad 1 "size" ; Target is not defined 199fd4e5da5Sopenharmony_ci%intt = OpTypeInt 32 1 200fd4e5da5Sopenharmony_ci%uintt = OpTypeInt 32 0 201fd4e5da5Sopenharmony_ci%struct = OpTypeStruct %intt %uintt 202fd4e5da5Sopenharmony_ci)"; 203fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 204fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 205fd4e5da5Sopenharmony_ci EXPECT_THAT(getDiagnosticString(), 206fd4e5da5Sopenharmony_ci HasSubstr("The following forward referenced IDs have not been " 207fd4e5da5Sopenharmony_ci "defined:\n'2[%2]'")); 208fd4e5da5Sopenharmony_ci} 209fd4e5da5Sopenharmony_ci 210fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardDecorateGood) { 211fd4e5da5Sopenharmony_ci char str[] = R"( 212fd4e5da5Sopenharmony_ci OpCapability Shader 213fd4e5da5Sopenharmony_ci OpCapability Linkage 214fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 215fd4e5da5Sopenharmony_ci OpDecorate %var Restrict 216fd4e5da5Sopenharmony_ci%intt = OpTypeInt 32 1 217fd4e5da5Sopenharmony_ci%ptrt = OpTypePointer UniformConstant %intt 218fd4e5da5Sopenharmony_ci%var = OpVariable %ptrt UniformConstant 219fd4e5da5Sopenharmony_ci)"; 220fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 221fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); 222fd4e5da5Sopenharmony_ci} 223fd4e5da5Sopenharmony_ci 224fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardDecorateInvalidIDBad) { 225fd4e5da5Sopenharmony_ci char str[] = R"( 226fd4e5da5Sopenharmony_ci OpCapability Shader 227fd4e5da5Sopenharmony_ci OpCapability Linkage 228fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 229fd4e5da5Sopenharmony_ci OpName %missing "missing" 230fd4e5da5Sopenharmony_ci OpDecorate %missing Restrict ;Missing ID 231fd4e5da5Sopenharmony_ci%voidt = OpTypeVoid 232fd4e5da5Sopenharmony_ci%intt = OpTypeInt 32 1 233fd4e5da5Sopenharmony_ci%ptrt = OpTypePointer UniformConstant %intt 234fd4e5da5Sopenharmony_ci%var = OpVariable %ptrt UniformConstant 235fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %voidt 236fd4e5da5Sopenharmony_ci%3 = OpFunction %voidt None %2 237fd4e5da5Sopenharmony_ci%4 = OpLabel 238fd4e5da5Sopenharmony_ci OpReturn 239fd4e5da5Sopenharmony_ci OpFunctionEnd 240fd4e5da5Sopenharmony_ci)"; 241fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 242fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 243fd4e5da5Sopenharmony_ci EXPECT_THAT(getDiagnosticString(), HasSubstr("missing")); 244fd4e5da5Sopenharmony_ci} 245fd4e5da5Sopenharmony_ci 246fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardMemberDecorateGood) { 247fd4e5da5Sopenharmony_ci char str[] = R"( 248fd4e5da5Sopenharmony_ci OpCapability Shader 249fd4e5da5Sopenharmony_ci OpCapability Linkage 250fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 251fd4e5da5Sopenharmony_ci OpMemberDecorate %struct 1 RowMajor 252fd4e5da5Sopenharmony_ci%intt = OpTypeInt 32 1 253fd4e5da5Sopenharmony_ci%f32 = OpTypeFloat 32 254fd4e5da5Sopenharmony_ci%vec3 = OpTypeVector %f32 3 255fd4e5da5Sopenharmony_ci%mat33 = OpTypeMatrix %vec3 3 256fd4e5da5Sopenharmony_ci%struct = OpTypeStruct %intt %mat33 257fd4e5da5Sopenharmony_ci)"; 258fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 259fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); 260fd4e5da5Sopenharmony_ci} 261fd4e5da5Sopenharmony_ci 262fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardMemberDecorateInvalidIdBad) { 263fd4e5da5Sopenharmony_ci char str[] = R"( 264fd4e5da5Sopenharmony_ci OpCapability Shader 265fd4e5da5Sopenharmony_ci OpCapability Linkage 266fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 267fd4e5da5Sopenharmony_ci OpName %missing "missing" 268fd4e5da5Sopenharmony_ci OpMemberDecorate %missing 1 RowMajor ; Target not defined 269fd4e5da5Sopenharmony_ci%intt = OpTypeInt 32 1 270fd4e5da5Sopenharmony_ci%f32 = OpTypeFloat 32 271fd4e5da5Sopenharmony_ci%vec3 = OpTypeVector %f32 3 272fd4e5da5Sopenharmony_ci%mat33 = OpTypeMatrix %vec3 3 273fd4e5da5Sopenharmony_ci%struct = OpTypeStruct %intt %mat33 274fd4e5da5Sopenharmony_ci)"; 275fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 276fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 277fd4e5da5Sopenharmony_ci EXPECT_THAT(getDiagnosticString(), HasSubstr("missing")); 278fd4e5da5Sopenharmony_ci} 279fd4e5da5Sopenharmony_ci 280fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardGroupDecorateGood) { 281fd4e5da5Sopenharmony_ci char str[] = R"( 282fd4e5da5Sopenharmony_ci OpCapability Shader 283fd4e5da5Sopenharmony_ci OpCapability Linkage 284fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 285fd4e5da5Sopenharmony_ci OpDecorate %dgrp RowMajor 286fd4e5da5Sopenharmony_ci%dgrp = OpDecorationGroup 287fd4e5da5Sopenharmony_ci OpGroupDecorate %dgrp %mat33 %mat44 288fd4e5da5Sopenharmony_ci%f32 = OpTypeFloat 32 289fd4e5da5Sopenharmony_ci%vec3 = OpTypeVector %f32 3 290fd4e5da5Sopenharmony_ci%vec4 = OpTypeVector %f32 4 291fd4e5da5Sopenharmony_ci%mat33 = OpTypeMatrix %vec3 3 292fd4e5da5Sopenharmony_ci%mat44 = OpTypeMatrix %vec4 4 293fd4e5da5Sopenharmony_ci)"; 294fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 295fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); 296fd4e5da5Sopenharmony_ci} 297fd4e5da5Sopenharmony_ci 298fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardGroupDecorateMissingGroupBad) { 299fd4e5da5Sopenharmony_ci char str[] = R"( 300fd4e5da5Sopenharmony_ci OpCapability Shader 301fd4e5da5Sopenharmony_ci OpCapability Linkage 302fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 303fd4e5da5Sopenharmony_ci OpName %missing "missing" 304fd4e5da5Sopenharmony_ci OpDecorate %dgrp RowMajor 305fd4e5da5Sopenharmony_ci%dgrp = OpDecorationGroup 306fd4e5da5Sopenharmony_ci OpGroupDecorate %missing %mat33 %mat44 ; Target not defined 307fd4e5da5Sopenharmony_ci%intt = OpTypeInt 32 1 308fd4e5da5Sopenharmony_ci%vec3 = OpTypeVector %intt 3 309fd4e5da5Sopenharmony_ci%vec4 = OpTypeVector %intt 4 310fd4e5da5Sopenharmony_ci%mat33 = OpTypeMatrix %vec3 3 311fd4e5da5Sopenharmony_ci%mat44 = OpTypeMatrix %vec4 4 312fd4e5da5Sopenharmony_ci)"; 313fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 314fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 315fd4e5da5Sopenharmony_ci EXPECT_THAT(getDiagnosticString(), HasSubstr("missing")); 316fd4e5da5Sopenharmony_ci} 317fd4e5da5Sopenharmony_ci 318fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardGroupDecorateMissingTargetBad) { 319fd4e5da5Sopenharmony_ci char str[] = R"( 320fd4e5da5Sopenharmony_ci OpCapability Shader 321fd4e5da5Sopenharmony_ci OpCapability Linkage 322fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 323fd4e5da5Sopenharmony_ci OpName %missing "missing" 324fd4e5da5Sopenharmony_ci OpDecorate %dgrp RowMajor 325fd4e5da5Sopenharmony_ci%dgrp = OpDecorationGroup 326fd4e5da5Sopenharmony_ci OpGroupDecorate %dgrp %missing %mat44 ; Target not defined 327fd4e5da5Sopenharmony_ci%f32 = OpTypeFloat 32 328fd4e5da5Sopenharmony_ci%vec3 = OpTypeVector %f32 3 329fd4e5da5Sopenharmony_ci%vec4 = OpTypeVector %f32 4 330fd4e5da5Sopenharmony_ci%mat33 = OpTypeMatrix %vec3 3 331fd4e5da5Sopenharmony_ci%mat44 = OpTypeMatrix %vec4 4 332fd4e5da5Sopenharmony_ci)"; 333fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 334fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 335fd4e5da5Sopenharmony_ci EXPECT_THAT(getDiagnosticString(), HasSubstr("missing")); 336fd4e5da5Sopenharmony_ci} 337fd4e5da5Sopenharmony_ci 338fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardGroupDecorateDecorationGroupDominateBad) { 339fd4e5da5Sopenharmony_ci char str[] = R"( 340fd4e5da5Sopenharmony_ci OpCapability Shader 341fd4e5da5Sopenharmony_ci OpCapability Linkage 342fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 343fd4e5da5Sopenharmony_ci OpName %dgrp "group" 344fd4e5da5Sopenharmony_ci OpDecorate %dgrp RowMajor 345fd4e5da5Sopenharmony_ci OpGroupDecorate %dgrp %mat33 %mat44 ; Decoration group does not dominate usage 346fd4e5da5Sopenharmony_ci%dgrp = OpDecorationGroup 347fd4e5da5Sopenharmony_ci%intt = OpTypeInt 32 1 348fd4e5da5Sopenharmony_ci%vec3 = OpTypeVector %intt 3 349fd4e5da5Sopenharmony_ci%vec4 = OpTypeVector %intt 4 350fd4e5da5Sopenharmony_ci%mat33 = OpTypeMatrix %vec3 3 351fd4e5da5Sopenharmony_ci%mat44 = OpTypeMatrix %vec4 4 352fd4e5da5Sopenharmony_ci)"; 353fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 354fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 355fd4e5da5Sopenharmony_ci EXPECT_THAT(getDiagnosticString(), HasSubstr("group")); 356fd4e5da5Sopenharmony_ci} 357fd4e5da5Sopenharmony_ci 358fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardDecorateInvalidIdBad) { 359fd4e5da5Sopenharmony_ci char str[] = R"( 360fd4e5da5Sopenharmony_ci OpCapability Shader 361fd4e5da5Sopenharmony_ci OpCapability Linkage 362fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 363fd4e5da5Sopenharmony_ci OpName %missing "missing" 364fd4e5da5Sopenharmony_ci OpDecorate %missing Restrict ; Missing target 365fd4e5da5Sopenharmony_ci%voidt = OpTypeVoid 366fd4e5da5Sopenharmony_ci%intt = OpTypeInt 32 1 367fd4e5da5Sopenharmony_ci%ptrt = OpTypePointer UniformConstant %intt 368fd4e5da5Sopenharmony_ci%var = OpVariable %ptrt UniformConstant 369fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %voidt 370fd4e5da5Sopenharmony_ci%3 = OpFunction %voidt None %2 371fd4e5da5Sopenharmony_ci%4 = OpLabel 372fd4e5da5Sopenharmony_ci OpReturn 373fd4e5da5Sopenharmony_ci OpFunctionEnd 374fd4e5da5Sopenharmony_ci)"; 375fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 376fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 377fd4e5da5Sopenharmony_ci EXPECT_THAT(getDiagnosticString(), HasSubstr("missing")); 378fd4e5da5Sopenharmony_ci} 379fd4e5da5Sopenharmony_ci 380fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, FunctionCallGood) { 381fd4e5da5Sopenharmony_ci char str[] = R"( 382fd4e5da5Sopenharmony_ci OpCapability Shader 383fd4e5da5Sopenharmony_ci OpCapability Linkage 384fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 385fd4e5da5Sopenharmony_ci%1 = OpTypeVoid 386fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 1 387fd4e5da5Sopenharmony_ci%3 = OpTypeInt 32 0 388fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %1 389fd4e5da5Sopenharmony_ci%8 = OpTypeFunction %1 %2 %3 390fd4e5da5Sopenharmony_ci%four = OpConstant %2 4 391fd4e5da5Sopenharmony_ci%five = OpConstant %3 5 392fd4e5da5Sopenharmony_ci%9 = OpFunction %1 None %8 393fd4e5da5Sopenharmony_ci%10 = OpFunctionParameter %2 394fd4e5da5Sopenharmony_ci%11 = OpFunctionParameter %3 395fd4e5da5Sopenharmony_ci%12 = OpLabel 396fd4e5da5Sopenharmony_ci OpReturn 397fd4e5da5Sopenharmony_ci OpFunctionEnd 398fd4e5da5Sopenharmony_ci%5 = OpFunction %1 None %4 399fd4e5da5Sopenharmony_ci%6 = OpLabel 400fd4e5da5Sopenharmony_ci%7 = OpFunctionCall %1 %9 %four %five 401fd4e5da5Sopenharmony_ci OpReturn 402fd4e5da5Sopenharmony_ci OpFunctionEnd 403fd4e5da5Sopenharmony_ci)"; 404fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 405fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); 406fd4e5da5Sopenharmony_ci} 407fd4e5da5Sopenharmony_ci 408fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardFunctionCallGood) { 409fd4e5da5Sopenharmony_ci char str[] = R"( 410fd4e5da5Sopenharmony_ci OpCapability Shader 411fd4e5da5Sopenharmony_ci OpCapability Linkage 412fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 413fd4e5da5Sopenharmony_ci%1 = OpTypeVoid 414fd4e5da5Sopenharmony_ci%2 = OpTypeInt 32 1 415fd4e5da5Sopenharmony_ci%3 = OpTypeInt 32 0 416fd4e5da5Sopenharmony_ci%four = OpConstant %2 4 417fd4e5da5Sopenharmony_ci%five = OpConstant %3 5 418fd4e5da5Sopenharmony_ci%8 = OpTypeFunction %1 %2 %3 419fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %1 420fd4e5da5Sopenharmony_ci%5 = OpFunction %1 None %4 421fd4e5da5Sopenharmony_ci%6 = OpLabel 422fd4e5da5Sopenharmony_ci%7 = OpFunctionCall %1 %9 %four %five 423fd4e5da5Sopenharmony_ci OpReturn 424fd4e5da5Sopenharmony_ci OpFunctionEnd 425fd4e5da5Sopenharmony_ci%9 = OpFunction %1 None %8 426fd4e5da5Sopenharmony_ci%10 = OpFunctionParameter %2 427fd4e5da5Sopenharmony_ci%11 = OpFunctionParameter %3 428fd4e5da5Sopenharmony_ci%12 = OpLabel 429fd4e5da5Sopenharmony_ci OpReturn 430fd4e5da5Sopenharmony_ci OpFunctionEnd 431fd4e5da5Sopenharmony_ci)"; 432fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 433fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); 434fd4e5da5Sopenharmony_ci} 435fd4e5da5Sopenharmony_ci 436fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardBranchConditionalGood) { 437fd4e5da5Sopenharmony_ci char str[] = R"( 438fd4e5da5Sopenharmony_ci OpCapability Shader 439fd4e5da5Sopenharmony_ci OpCapability Linkage 440fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 441fd4e5da5Sopenharmony_ci%voidt = OpTypeVoid 442fd4e5da5Sopenharmony_ci%boolt = OpTypeBool 443fd4e5da5Sopenharmony_ci%vfunct = OpTypeFunction %voidt 444fd4e5da5Sopenharmony_ci%true = OpConstantTrue %boolt 445fd4e5da5Sopenharmony_ci%main = OpFunction %voidt None %vfunct 446fd4e5da5Sopenharmony_ci%mainl = OpLabel 447fd4e5da5Sopenharmony_ci OpSelectionMerge %endl None 448fd4e5da5Sopenharmony_ci OpBranchConditional %true %truel %falsel 449fd4e5da5Sopenharmony_ci%truel = OpLabel 450fd4e5da5Sopenharmony_ci OpNop 451fd4e5da5Sopenharmony_ci OpBranch %endl 452fd4e5da5Sopenharmony_ci%falsel = OpLabel 453fd4e5da5Sopenharmony_ci OpNop 454fd4e5da5Sopenharmony_ci OpBranch %endl 455fd4e5da5Sopenharmony_ci%endl = OpLabel 456fd4e5da5Sopenharmony_ci OpReturn 457fd4e5da5Sopenharmony_ci OpFunctionEnd 458fd4e5da5Sopenharmony_ci)"; 459fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 460fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); 461fd4e5da5Sopenharmony_ci} 462fd4e5da5Sopenharmony_ci 463fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardBranchConditionalWithWeightsGood) { 464fd4e5da5Sopenharmony_ci char str[] = R"( 465fd4e5da5Sopenharmony_ci OpCapability Shader 466fd4e5da5Sopenharmony_ci OpCapability Linkage 467fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 468fd4e5da5Sopenharmony_ci%voidt = OpTypeVoid 469fd4e5da5Sopenharmony_ci%boolt = OpTypeBool 470fd4e5da5Sopenharmony_ci%vfunct = OpTypeFunction %voidt 471fd4e5da5Sopenharmony_ci%true = OpConstantTrue %boolt 472fd4e5da5Sopenharmony_ci%main = OpFunction %voidt None %vfunct 473fd4e5da5Sopenharmony_ci%mainl = OpLabel 474fd4e5da5Sopenharmony_ci OpSelectionMerge %endl None 475fd4e5da5Sopenharmony_ci OpBranchConditional %true %truel %falsel 1 9 476fd4e5da5Sopenharmony_ci%truel = OpLabel 477fd4e5da5Sopenharmony_ci OpNop 478fd4e5da5Sopenharmony_ci OpBranch %endl 479fd4e5da5Sopenharmony_ci%falsel = OpLabel 480fd4e5da5Sopenharmony_ci OpNop 481fd4e5da5Sopenharmony_ci OpBranch %endl 482fd4e5da5Sopenharmony_ci%endl = OpLabel 483fd4e5da5Sopenharmony_ci OpReturn 484fd4e5da5Sopenharmony_ci OpFunctionEnd 485fd4e5da5Sopenharmony_ci)"; 486fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 487fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); 488fd4e5da5Sopenharmony_ci} 489fd4e5da5Sopenharmony_ci 490fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardBranchConditionalNonDominantConditionBad) { 491fd4e5da5Sopenharmony_ci char str[] = R"( 492fd4e5da5Sopenharmony_ci OpCapability Shader 493fd4e5da5Sopenharmony_ci OpCapability Linkage 494fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 495fd4e5da5Sopenharmony_ci OpName %tcpy "conditional" 496fd4e5da5Sopenharmony_ci%voidt = OpTypeVoid 497fd4e5da5Sopenharmony_ci%boolt = OpTypeBool 498fd4e5da5Sopenharmony_ci%vfunct = OpTypeFunction %voidt 499fd4e5da5Sopenharmony_ci%true = OpConstantTrue %boolt 500fd4e5da5Sopenharmony_ci%main = OpFunction %voidt None %vfunct 501fd4e5da5Sopenharmony_ci%mainl = OpLabel 502fd4e5da5Sopenharmony_ci OpSelectionMerge %endl None 503fd4e5da5Sopenharmony_ci OpBranchConditional %tcpy %truel %falsel ; 504fd4e5da5Sopenharmony_ci%truel = OpLabel 505fd4e5da5Sopenharmony_ci OpNop 506fd4e5da5Sopenharmony_ci OpBranch %endl 507fd4e5da5Sopenharmony_ci%falsel = OpLabel 508fd4e5da5Sopenharmony_ci OpNop 509fd4e5da5Sopenharmony_ci OpBranch %endl 510fd4e5da5Sopenharmony_ci%endl = OpLabel 511fd4e5da5Sopenharmony_ci%tcpy = OpCopyObject %boolt %true 512fd4e5da5Sopenharmony_ci OpReturn 513fd4e5da5Sopenharmony_ci OpFunctionEnd 514fd4e5da5Sopenharmony_ci)"; 515fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 516fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 517fd4e5da5Sopenharmony_ci EXPECT_THAT(getDiagnosticString(), HasSubstr("conditional")); 518fd4e5da5Sopenharmony_ci} 519fd4e5da5Sopenharmony_ci 520fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardBranchConditionalMissingTargetBad) { 521fd4e5da5Sopenharmony_ci char str[] = R"( 522fd4e5da5Sopenharmony_ci OpCapability Shader 523fd4e5da5Sopenharmony_ci OpCapability Linkage 524fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 525fd4e5da5Sopenharmony_ci OpName %missing "missing" 526fd4e5da5Sopenharmony_ci%voidt = OpTypeVoid 527fd4e5da5Sopenharmony_ci%boolt = OpTypeBool 528fd4e5da5Sopenharmony_ci%vfunct = OpTypeFunction %voidt 529fd4e5da5Sopenharmony_ci%true = OpConstantTrue %boolt 530fd4e5da5Sopenharmony_ci%main = OpFunction %voidt None %vfunct 531fd4e5da5Sopenharmony_ci%mainl = OpLabel 532fd4e5da5Sopenharmony_ci OpSelectionMerge %endl None 533fd4e5da5Sopenharmony_ci OpBranchConditional %true %missing %falsel 534fd4e5da5Sopenharmony_ci%truel = OpLabel 535fd4e5da5Sopenharmony_ci OpNop 536fd4e5da5Sopenharmony_ci OpBranch %endl 537fd4e5da5Sopenharmony_ci%falsel = OpLabel 538fd4e5da5Sopenharmony_ci OpNop 539fd4e5da5Sopenharmony_ci OpBranch %endl 540fd4e5da5Sopenharmony_ci%endl = OpLabel 541fd4e5da5Sopenharmony_ci OpReturn 542fd4e5da5Sopenharmony_ci OpFunctionEnd 543fd4e5da5Sopenharmony_ci)"; 544fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 545fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 546fd4e5da5Sopenharmony_ci EXPECT_THAT(getDiagnosticString(), HasSubstr("missing")); 547fd4e5da5Sopenharmony_ci} 548fd4e5da5Sopenharmony_ci 549fd4e5da5Sopenharmony_ci// Since Int8 requires the Kernel capability, the signedness of int types may 550fd4e5da5Sopenharmony_ci// not be "1". 551fd4e5da5Sopenharmony_ciconst std::string kHeader = R"( 552fd4e5da5Sopenharmony_ciOpCapability Int8 553fd4e5da5Sopenharmony_ciOpCapability DeviceEnqueue 554fd4e5da5Sopenharmony_ciOpCapability Linkage 555fd4e5da5Sopenharmony_ciOpMemoryModel Logical OpenCL 556fd4e5da5Sopenharmony_ci)"; 557fd4e5da5Sopenharmony_ci 558fd4e5da5Sopenharmony_ciconst std::string kBasicTypes = R"( 559fd4e5da5Sopenharmony_ci%voidt = OpTypeVoid 560fd4e5da5Sopenharmony_ci%boolt = OpTypeBool 561fd4e5da5Sopenharmony_ci%int8t = OpTypeInt 8 0 562fd4e5da5Sopenharmony_ci%uintt = OpTypeInt 32 0 563fd4e5da5Sopenharmony_ci%vfunct = OpTypeFunction %voidt 564fd4e5da5Sopenharmony_ci%intptrt = OpTypePointer UniformConstant %uintt 565fd4e5da5Sopenharmony_ci%zero = OpConstant %uintt 0 566fd4e5da5Sopenharmony_ci%one = OpConstant %uintt 1 567fd4e5da5Sopenharmony_ci%ten = OpConstant %uintt 10 568fd4e5da5Sopenharmony_ci%false = OpConstantFalse %boolt 569fd4e5da5Sopenharmony_ci)"; 570fd4e5da5Sopenharmony_ci 571fd4e5da5Sopenharmony_ciconst std::string kKernelTypesAndConstants = R"( 572fd4e5da5Sopenharmony_ci%queuet = OpTypeQueue 573fd4e5da5Sopenharmony_ci 574fd4e5da5Sopenharmony_ci%three = OpConstant %uintt 3 575fd4e5da5Sopenharmony_ci%arr3t = OpTypeArray %uintt %three 576fd4e5da5Sopenharmony_ci%ndt = OpTypeStruct %uintt %arr3t %arr3t %arr3t 577fd4e5da5Sopenharmony_ci 578fd4e5da5Sopenharmony_ci%eventt = OpTypeEvent 579fd4e5da5Sopenharmony_ci 580fd4e5da5Sopenharmony_ci%offset = OpConstant %uintt 0 581fd4e5da5Sopenharmony_ci%local = OpConstant %uintt 1 582fd4e5da5Sopenharmony_ci%gl = OpConstant %uintt 1 583fd4e5da5Sopenharmony_ci 584fd4e5da5Sopenharmony_ci%nevent = OpConstant %uintt 0 585fd4e5da5Sopenharmony_ci%event = OpConstantNull %eventt 586fd4e5da5Sopenharmony_ci 587fd4e5da5Sopenharmony_ci%firstp = OpConstant %int8t 0 588fd4e5da5Sopenharmony_ci%psize = OpConstant %uintt 0 589fd4e5da5Sopenharmony_ci%palign = OpConstant %uintt 32 590fd4e5da5Sopenharmony_ci%lsize = OpConstant %uintt 1 591fd4e5da5Sopenharmony_ci%flags = OpConstant %uintt 0 ; NoWait 592fd4e5da5Sopenharmony_ci 593fd4e5da5Sopenharmony_ci%kfunct = OpTypeFunction %voidt %intptrt 594fd4e5da5Sopenharmony_ci)"; 595fd4e5da5Sopenharmony_ci 596fd4e5da5Sopenharmony_ciconst std::string kKernelSetup = R"( 597fd4e5da5Sopenharmony_ci%dqueue = OpGetDefaultQueue %queuet 598fd4e5da5Sopenharmony_ci%ndval = OpBuildNDRange %ndt %gl %local %offset 599fd4e5da5Sopenharmony_ci%revent = OpUndef %eventt 600fd4e5da5Sopenharmony_ci 601fd4e5da5Sopenharmony_ci)"; 602fd4e5da5Sopenharmony_ci 603fd4e5da5Sopenharmony_ciconst std::string kKernelDefinition = R"( 604fd4e5da5Sopenharmony_ci%kfunc = OpFunction %voidt None %kfunct 605fd4e5da5Sopenharmony_ci%iparam = OpFunctionParameter %intptrt 606fd4e5da5Sopenharmony_ci%kfuncl = OpLabel 607fd4e5da5Sopenharmony_ci OpNop 608fd4e5da5Sopenharmony_ci OpReturn 609fd4e5da5Sopenharmony_ci OpFunctionEnd 610fd4e5da5Sopenharmony_ci)"; 611fd4e5da5Sopenharmony_ci 612fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, EnqueueKernelGood) { 613fd4e5da5Sopenharmony_ci std::string str = kHeader + kBasicTypes + kKernelTypesAndConstants + 614fd4e5da5Sopenharmony_ci kKernelDefinition + R"( 615fd4e5da5Sopenharmony_ci %main = OpFunction %voidt None %vfunct 616fd4e5da5Sopenharmony_ci %mainl = OpLabel 617fd4e5da5Sopenharmony_ci )" + kKernelSetup + R"( 618fd4e5da5Sopenharmony_ci %err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent 619fd4e5da5Sopenharmony_ci %event %revent %kfunc %firstp %psize 620fd4e5da5Sopenharmony_ci %palign %lsize 621fd4e5da5Sopenharmony_ci OpReturn 622fd4e5da5Sopenharmony_ci OpFunctionEnd 623fd4e5da5Sopenharmony_ci )"; 624fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 625fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); 626fd4e5da5Sopenharmony_ci} 627fd4e5da5Sopenharmony_ci 628fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardEnqueueKernelGood) { 629fd4e5da5Sopenharmony_ci std::string str = kHeader + kBasicTypes + kKernelTypesAndConstants + R"( 630fd4e5da5Sopenharmony_ci %main = OpFunction %voidt None %vfunct 631fd4e5da5Sopenharmony_ci %mainl = OpLabel 632fd4e5da5Sopenharmony_ci )" + 633fd4e5da5Sopenharmony_ci kKernelSetup + R"( 634fd4e5da5Sopenharmony_ci %err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent 635fd4e5da5Sopenharmony_ci %event %revent %kfunc %firstp %psize 636fd4e5da5Sopenharmony_ci %palign %lsize 637fd4e5da5Sopenharmony_ci OpReturn 638fd4e5da5Sopenharmony_ci OpFunctionEnd 639fd4e5da5Sopenharmony_ci )" + kKernelDefinition; 640fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 641fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); 642fd4e5da5Sopenharmony_ci} 643fd4e5da5Sopenharmony_ci 644fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, EnqueueMissingFunctionBad) { 645fd4e5da5Sopenharmony_ci std::string str = kHeader + "OpName %kfunc \"kfunc\"" + kBasicTypes + 646fd4e5da5Sopenharmony_ci kKernelTypesAndConstants + R"( 647fd4e5da5Sopenharmony_ci %main = OpFunction %voidt None %vfunct 648fd4e5da5Sopenharmony_ci %mainl = OpLabel 649fd4e5da5Sopenharmony_ci )" + kKernelSetup + R"( 650fd4e5da5Sopenharmony_ci %err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent 651fd4e5da5Sopenharmony_ci %event %revent %kfunc %firstp %psize 652fd4e5da5Sopenharmony_ci %palign %lsize 653fd4e5da5Sopenharmony_ci OpReturn 654fd4e5da5Sopenharmony_ci OpFunctionEnd 655fd4e5da5Sopenharmony_ci )"; 656fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 657fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 658fd4e5da5Sopenharmony_ci EXPECT_THAT(getDiagnosticString(), HasSubstr("kfunc")); 659fd4e5da5Sopenharmony_ci} 660fd4e5da5Sopenharmony_ci 661fd4e5da5Sopenharmony_cistd::string forwardKernelNonDominantParameterBaseCode( 662fd4e5da5Sopenharmony_ci std::string name = std::string()) { 663fd4e5da5Sopenharmony_ci std::string op_name; 664fd4e5da5Sopenharmony_ci if (name.empty()) { 665fd4e5da5Sopenharmony_ci op_name = ""; 666fd4e5da5Sopenharmony_ci } else { 667fd4e5da5Sopenharmony_ci op_name = "\nOpName %" + name + " \"" + name + "\"\n"; 668fd4e5da5Sopenharmony_ci } 669fd4e5da5Sopenharmony_ci std::string out = kHeader + op_name + kBasicTypes + kKernelTypesAndConstants + 670fd4e5da5Sopenharmony_ci kKernelDefinition + 671fd4e5da5Sopenharmony_ci R"( 672fd4e5da5Sopenharmony_ci %main = OpFunction %voidt None %vfunct 673fd4e5da5Sopenharmony_ci %mainl = OpLabel 674fd4e5da5Sopenharmony_ci )" + kKernelSetup; 675fd4e5da5Sopenharmony_ci return out; 676fd4e5da5Sopenharmony_ci} 677fd4e5da5Sopenharmony_ci 678fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardEnqueueKernelMissingParameter1Bad) { 679fd4e5da5Sopenharmony_ci std::string str = forwardKernelNonDominantParameterBaseCode("missing") + R"( 680fd4e5da5Sopenharmony_ci %err = OpEnqueueKernel %missing %dqueue %flags %ndval 681fd4e5da5Sopenharmony_ci %nevent %event %revent %kfunc %firstp 682fd4e5da5Sopenharmony_ci %psize %palign %lsize 683fd4e5da5Sopenharmony_ci OpReturn 684fd4e5da5Sopenharmony_ci OpFunctionEnd 685fd4e5da5Sopenharmony_ci )"; 686fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 687fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 688fd4e5da5Sopenharmony_ci EXPECT_THAT(getDiagnosticString(), HasSubstr("missing")); 689fd4e5da5Sopenharmony_ci} 690fd4e5da5Sopenharmony_ci 691fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardEnqueueKernelNonDominantParameter2Bad) { 692fd4e5da5Sopenharmony_ci std::string str = forwardKernelNonDominantParameterBaseCode("dqueue2") + R"( 693fd4e5da5Sopenharmony_ci %err = OpEnqueueKernel %uintt %dqueue2 %flags %ndval 694fd4e5da5Sopenharmony_ci %nevent %event %revent %kfunc 695fd4e5da5Sopenharmony_ci %firstp %psize %palign %lsize 696fd4e5da5Sopenharmony_ci %dqueue2 = OpGetDefaultQueue %queuet 697fd4e5da5Sopenharmony_ci OpReturn 698fd4e5da5Sopenharmony_ci OpFunctionEnd 699fd4e5da5Sopenharmony_ci )"; 700fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 701fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 702fd4e5da5Sopenharmony_ci EXPECT_THAT(getDiagnosticString(), HasSubstr("dqueue2")); 703fd4e5da5Sopenharmony_ci} 704fd4e5da5Sopenharmony_ci 705fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardEnqueueKernelNonDominantParameter3Bad) { 706fd4e5da5Sopenharmony_ci std::string str = forwardKernelNonDominantParameterBaseCode("ndval2") + R"( 707fd4e5da5Sopenharmony_ci %err = OpEnqueueKernel %uintt %dqueue %flags %ndval2 708fd4e5da5Sopenharmony_ci %nevent %event %revent %kfunc %firstp 709fd4e5da5Sopenharmony_ci %psize %palign %lsize 710fd4e5da5Sopenharmony_ci %ndval2 = OpBuildNDRange %ndt %gl %local %offset 711fd4e5da5Sopenharmony_ci OpReturn 712fd4e5da5Sopenharmony_ci OpFunctionEnd 713fd4e5da5Sopenharmony_ci )"; 714fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 715fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 716fd4e5da5Sopenharmony_ci EXPECT_THAT(getDiagnosticString(), HasSubstr("ndval2")); 717fd4e5da5Sopenharmony_ci} 718fd4e5da5Sopenharmony_ci 719fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardEnqueueKernelNonDominantParameter4Bad) { 720fd4e5da5Sopenharmony_ci std::string str = forwardKernelNonDominantParameterBaseCode("nevent2") + R"( 721fd4e5da5Sopenharmony_ci %err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent2 722fd4e5da5Sopenharmony_ci %event %revent %kfunc %firstp %psize 723fd4e5da5Sopenharmony_ci %palign %lsize 724fd4e5da5Sopenharmony_ci %nevent2 = OpCopyObject %uintt %nevent 725fd4e5da5Sopenharmony_ci OpReturn 726fd4e5da5Sopenharmony_ci OpFunctionEnd 727fd4e5da5Sopenharmony_ci )"; 728fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 729fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 730fd4e5da5Sopenharmony_ci EXPECT_THAT(getDiagnosticString(), HasSubstr("nevent2")); 731fd4e5da5Sopenharmony_ci} 732fd4e5da5Sopenharmony_ci 733fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardEnqueueKernelNonDominantParameter5Bad) { 734fd4e5da5Sopenharmony_ci std::string str = forwardKernelNonDominantParameterBaseCode("event2") + R"( 735fd4e5da5Sopenharmony_ci %err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent 736fd4e5da5Sopenharmony_ci %event2 %revent %kfunc %firstp %psize 737fd4e5da5Sopenharmony_ci %palign %lsize 738fd4e5da5Sopenharmony_ci %event2 = OpCopyObject %eventt %event 739fd4e5da5Sopenharmony_ci OpReturn 740fd4e5da5Sopenharmony_ci OpFunctionEnd 741fd4e5da5Sopenharmony_ci )"; 742fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 743fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 744fd4e5da5Sopenharmony_ci EXPECT_THAT(getDiagnosticString(), HasSubstr("event2")); 745fd4e5da5Sopenharmony_ci} 746fd4e5da5Sopenharmony_ci 747fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardEnqueueKernelNonDominantParameter6Bad) { 748fd4e5da5Sopenharmony_ci std::string str = forwardKernelNonDominantParameterBaseCode("revent2") + R"( 749fd4e5da5Sopenharmony_ci %err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent 750fd4e5da5Sopenharmony_ci %event %revent2 %kfunc %firstp %psize 751fd4e5da5Sopenharmony_ci %palign %lsize 752fd4e5da5Sopenharmony_ci %revent2 = OpCopyObject %eventt %revent 753fd4e5da5Sopenharmony_ci OpReturn 754fd4e5da5Sopenharmony_ci OpFunctionEnd 755fd4e5da5Sopenharmony_ci )"; 756fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 757fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 758fd4e5da5Sopenharmony_ci EXPECT_THAT(getDiagnosticString(), HasSubstr("revent2")); 759fd4e5da5Sopenharmony_ci} 760fd4e5da5Sopenharmony_ci 761fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardEnqueueKernelNonDominantParameter8Bad) { 762fd4e5da5Sopenharmony_ci std::string str = forwardKernelNonDominantParameterBaseCode("firstp2") + R"( 763fd4e5da5Sopenharmony_ci %err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent 764fd4e5da5Sopenharmony_ci %event %revent %kfunc %firstp2 %psize 765fd4e5da5Sopenharmony_ci %palign %lsize 766fd4e5da5Sopenharmony_ci %firstp2 = OpCopyObject %int8t %firstp 767fd4e5da5Sopenharmony_ci OpReturn 768fd4e5da5Sopenharmony_ci OpFunctionEnd 769fd4e5da5Sopenharmony_ci )"; 770fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 771fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 772fd4e5da5Sopenharmony_ci EXPECT_THAT(getDiagnosticString(), HasSubstr("firstp2")); 773fd4e5da5Sopenharmony_ci} 774fd4e5da5Sopenharmony_ci 775fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardEnqueueKernelNonDominantParameter9Bad) { 776fd4e5da5Sopenharmony_ci std::string str = forwardKernelNonDominantParameterBaseCode("psize2") + R"( 777fd4e5da5Sopenharmony_ci %err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent 778fd4e5da5Sopenharmony_ci %event %revent %kfunc %firstp %psize2 779fd4e5da5Sopenharmony_ci %palign %lsize 780fd4e5da5Sopenharmony_ci %psize2 = OpCopyObject %uintt %psize 781fd4e5da5Sopenharmony_ci OpReturn 782fd4e5da5Sopenharmony_ci OpFunctionEnd 783fd4e5da5Sopenharmony_ci )"; 784fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 785fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 786fd4e5da5Sopenharmony_ci EXPECT_THAT(getDiagnosticString(), HasSubstr("psize2")); 787fd4e5da5Sopenharmony_ci} 788fd4e5da5Sopenharmony_ci 789fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardEnqueueKernelNonDominantParameter10Bad) { 790fd4e5da5Sopenharmony_ci std::string str = forwardKernelNonDominantParameterBaseCode("palign2") + R"( 791fd4e5da5Sopenharmony_ci %err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent 792fd4e5da5Sopenharmony_ci %event %revent %kfunc %firstp %psize 793fd4e5da5Sopenharmony_ci %palign2 %lsize 794fd4e5da5Sopenharmony_ci %palign2 = OpCopyObject %uintt %palign 795fd4e5da5Sopenharmony_ci OpReturn 796fd4e5da5Sopenharmony_ci OpFunctionEnd 797fd4e5da5Sopenharmony_ci )"; 798fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 799fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 800fd4e5da5Sopenharmony_ci EXPECT_THAT(getDiagnosticString(), HasSubstr("palign2")); 801fd4e5da5Sopenharmony_ci} 802fd4e5da5Sopenharmony_ci 803fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, ForwardEnqueueKernelNonDominantParameter11Bad) { 804fd4e5da5Sopenharmony_ci std::string str = forwardKernelNonDominantParameterBaseCode("lsize2") + R"( 805fd4e5da5Sopenharmony_ci %err = OpEnqueueKernel %uintt %dqueue %flags %ndval %nevent 806fd4e5da5Sopenharmony_ci %event %revent %kfunc %firstp %psize 807fd4e5da5Sopenharmony_ci %palign %lsize2 808fd4e5da5Sopenharmony_ci %lsize2 = OpCopyObject %uintt %lsize 809fd4e5da5Sopenharmony_ci OpReturn 810fd4e5da5Sopenharmony_ci OpFunctionEnd 811fd4e5da5Sopenharmony_ci )"; 812fd4e5da5Sopenharmony_ci 813fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 814fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 815fd4e5da5Sopenharmony_ci EXPECT_THAT(getDiagnosticString(), HasSubstr("lsize2")); 816fd4e5da5Sopenharmony_ci} 817fd4e5da5Sopenharmony_ci 818fd4e5da5Sopenharmony_cistatic const bool kWithNDrange = true; 819fd4e5da5Sopenharmony_cistatic const bool kNoNDrange = false; 820fd4e5da5Sopenharmony_cistd::pair<std::string, bool> cases[] = { 821fd4e5da5Sopenharmony_ci {"OpGetKernelNDrangeSubGroupCount", kWithNDrange}, 822fd4e5da5Sopenharmony_ci {"OpGetKernelNDrangeMaxSubGroupSize", kWithNDrange}, 823fd4e5da5Sopenharmony_ci {"OpGetKernelWorkGroupSize", kNoNDrange}, 824fd4e5da5Sopenharmony_ci {"OpGetKernelPreferredWorkGroupSizeMultiple", kNoNDrange}}; 825fd4e5da5Sopenharmony_ci 826fd4e5da5Sopenharmony_ciINSTANTIATE_TEST_SUITE_P(KernelArgs, ValidateSSA, ::testing::ValuesIn(cases)); 827fd4e5da5Sopenharmony_ci 828fd4e5da5Sopenharmony_cistatic const std::string return_instructions = R"( 829fd4e5da5Sopenharmony_ci OpReturn 830fd4e5da5Sopenharmony_ci OpFunctionEnd 831fd4e5da5Sopenharmony_ci)"; 832fd4e5da5Sopenharmony_ci 833fd4e5da5Sopenharmony_ciTEST_P(ValidateSSA, GetKernelGood) { 834fd4e5da5Sopenharmony_ci std::string instruction = GetParam().first; 835fd4e5da5Sopenharmony_ci bool with_ndrange = GetParam().second; 836fd4e5da5Sopenharmony_ci std::string ndrange_param = with_ndrange ? " %ndval " : " "; 837fd4e5da5Sopenharmony_ci 838fd4e5da5Sopenharmony_ci std::stringstream ss; 839fd4e5da5Sopenharmony_ci // clang-format off 840fd4e5da5Sopenharmony_ci ss << forwardKernelNonDominantParameterBaseCode() + " %numsg = " 841fd4e5da5Sopenharmony_ci << instruction + " %uintt" + ndrange_param + "%kfunc %firstp %psize %palign" 842fd4e5da5Sopenharmony_ci << return_instructions; 843fd4e5da5Sopenharmony_ci // clang-format on 844fd4e5da5Sopenharmony_ci 845fd4e5da5Sopenharmony_ci CompileSuccessfully(ss.str()); 846fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); 847fd4e5da5Sopenharmony_ci} 848fd4e5da5Sopenharmony_ci 849fd4e5da5Sopenharmony_ciTEST_P(ValidateSSA, ForwardGetKernelGood) { 850fd4e5da5Sopenharmony_ci std::string instruction = GetParam().first; 851fd4e5da5Sopenharmony_ci bool with_ndrange = GetParam().second; 852fd4e5da5Sopenharmony_ci std::string ndrange_param = with_ndrange ? " %ndval " : " "; 853fd4e5da5Sopenharmony_ci 854fd4e5da5Sopenharmony_ci // clang-format off 855fd4e5da5Sopenharmony_ci std::string str = kHeader + kBasicTypes + kKernelTypesAndConstants + 856fd4e5da5Sopenharmony_ci R"( 857fd4e5da5Sopenharmony_ci %main = OpFunction %voidt None %vfunct 858fd4e5da5Sopenharmony_ci %mainl = OpLabel 859fd4e5da5Sopenharmony_ci )" 860fd4e5da5Sopenharmony_ci + kKernelSetup + " %numsg = " 861fd4e5da5Sopenharmony_ci + instruction + " %uintt" + ndrange_param + "%kfunc %firstp %psize %palign" 862fd4e5da5Sopenharmony_ci + return_instructions + kKernelDefinition; 863fd4e5da5Sopenharmony_ci // clang-format on 864fd4e5da5Sopenharmony_ci 865fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 866fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); 867fd4e5da5Sopenharmony_ci} 868fd4e5da5Sopenharmony_ci 869fd4e5da5Sopenharmony_ciTEST_P(ValidateSSA, ForwardGetKernelMissingDefinitionBad) { 870fd4e5da5Sopenharmony_ci std::string instruction = GetParam().first; 871fd4e5da5Sopenharmony_ci bool with_ndrange = GetParam().second; 872fd4e5da5Sopenharmony_ci std::string ndrange_param = with_ndrange ? " %ndval " : " "; 873fd4e5da5Sopenharmony_ci 874fd4e5da5Sopenharmony_ci std::stringstream ss; 875fd4e5da5Sopenharmony_ci // clang-format off 876fd4e5da5Sopenharmony_ci ss << forwardKernelNonDominantParameterBaseCode("missing") + " %numsg = " 877fd4e5da5Sopenharmony_ci << instruction + " %uintt" + ndrange_param + "%missing %firstp %psize %palign" 878fd4e5da5Sopenharmony_ci << return_instructions; 879fd4e5da5Sopenharmony_ci // clang-format on 880fd4e5da5Sopenharmony_ci 881fd4e5da5Sopenharmony_ci CompileSuccessfully(ss.str()); 882fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 883fd4e5da5Sopenharmony_ci EXPECT_THAT(getDiagnosticString(), HasSubstr("missing")); 884fd4e5da5Sopenharmony_ci} 885fd4e5da5Sopenharmony_ci 886fd4e5da5Sopenharmony_ciTEST_P(ValidateSSA, ForwardGetKernelNDrangeSubGroupCountMissingParameter1Bad) { 887fd4e5da5Sopenharmony_ci std::string instruction = GetParam().first; 888fd4e5da5Sopenharmony_ci bool with_ndrange = GetParam().second; 889fd4e5da5Sopenharmony_ci std::string ndrange_param = with_ndrange ? " %ndval " : " "; 890fd4e5da5Sopenharmony_ci 891fd4e5da5Sopenharmony_ci std::stringstream ss; 892fd4e5da5Sopenharmony_ci // clang-format off 893fd4e5da5Sopenharmony_ci ss << forwardKernelNonDominantParameterBaseCode("missing") + " %numsg = " 894fd4e5da5Sopenharmony_ci << instruction + " %missing" + ndrange_param + "%kfunc %firstp %psize %palign" 895fd4e5da5Sopenharmony_ci << return_instructions; 896fd4e5da5Sopenharmony_ci // clang-format on 897fd4e5da5Sopenharmony_ci 898fd4e5da5Sopenharmony_ci CompileSuccessfully(ss.str()); 899fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 900fd4e5da5Sopenharmony_ci EXPECT_THAT(getDiagnosticString(), HasSubstr("missing")); 901fd4e5da5Sopenharmony_ci} 902fd4e5da5Sopenharmony_ci 903fd4e5da5Sopenharmony_ciTEST_P(ValidateSSA, 904fd4e5da5Sopenharmony_ci ForwardGetKernelNDrangeSubGroupCountNonDominantParameter2Bad) { 905fd4e5da5Sopenharmony_ci std::string instruction = GetParam().first; 906fd4e5da5Sopenharmony_ci bool with_ndrange = GetParam().second; 907fd4e5da5Sopenharmony_ci std::string ndrange_param = with_ndrange ? " %ndval2 " : " "; 908fd4e5da5Sopenharmony_ci 909fd4e5da5Sopenharmony_ci std::stringstream ss; 910fd4e5da5Sopenharmony_ci // clang-format off 911fd4e5da5Sopenharmony_ci ss << forwardKernelNonDominantParameterBaseCode("ndval2") + " %numsg = " 912fd4e5da5Sopenharmony_ci << instruction + " %uintt" + ndrange_param + "%kfunc %firstp %psize %palign" 913fd4e5da5Sopenharmony_ci << "\n %ndval2 = OpBuildNDRange %ndt %gl %local %offset" 914fd4e5da5Sopenharmony_ci << return_instructions; 915fd4e5da5Sopenharmony_ci // clang-format on 916fd4e5da5Sopenharmony_ci 917fd4e5da5Sopenharmony_ci if (GetParam().second) { 918fd4e5da5Sopenharmony_ci CompileSuccessfully(ss.str()); 919fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 920fd4e5da5Sopenharmony_ci EXPECT_THAT(getDiagnosticString(), HasSubstr("ndval2")); 921fd4e5da5Sopenharmony_ci } 922fd4e5da5Sopenharmony_ci} 923fd4e5da5Sopenharmony_ci 924fd4e5da5Sopenharmony_ciTEST_P(ValidateSSA, 925fd4e5da5Sopenharmony_ci ForwardGetKernelNDrangeSubGroupCountNonDominantParameter4Bad) { 926fd4e5da5Sopenharmony_ci std::string instruction = GetParam().first; 927fd4e5da5Sopenharmony_ci bool with_ndrange = GetParam().second; 928fd4e5da5Sopenharmony_ci std::string ndrange_param = with_ndrange ? " %ndval " : " "; 929fd4e5da5Sopenharmony_ci 930fd4e5da5Sopenharmony_ci std::stringstream ss; 931fd4e5da5Sopenharmony_ci // clang-format off 932fd4e5da5Sopenharmony_ci ss << forwardKernelNonDominantParameterBaseCode("firstp2") + " %numsg = " 933fd4e5da5Sopenharmony_ci << instruction + " %uintt" + ndrange_param + "%kfunc %firstp2 %psize %palign" 934fd4e5da5Sopenharmony_ci << "\n %firstp2 = OpCopyObject %int8t %firstp" 935fd4e5da5Sopenharmony_ci << return_instructions; 936fd4e5da5Sopenharmony_ci // clang-format on 937fd4e5da5Sopenharmony_ci 938fd4e5da5Sopenharmony_ci CompileSuccessfully(ss.str()); 939fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 940fd4e5da5Sopenharmony_ci EXPECT_THAT(getDiagnosticString(), HasSubstr("firstp2")); 941fd4e5da5Sopenharmony_ci} 942fd4e5da5Sopenharmony_ci 943fd4e5da5Sopenharmony_ciTEST_P(ValidateSSA, 944fd4e5da5Sopenharmony_ci ForwardGetKernelNDrangeSubGroupCountNonDominantParameter5Bad) { 945fd4e5da5Sopenharmony_ci std::string instruction = GetParam().first; 946fd4e5da5Sopenharmony_ci bool with_ndrange = GetParam().second; 947fd4e5da5Sopenharmony_ci std::string ndrange_param = with_ndrange ? " %ndval " : " "; 948fd4e5da5Sopenharmony_ci 949fd4e5da5Sopenharmony_ci std::stringstream ss; 950fd4e5da5Sopenharmony_ci // clang-format off 951fd4e5da5Sopenharmony_ci ss << forwardKernelNonDominantParameterBaseCode("psize2") + " %numsg = " 952fd4e5da5Sopenharmony_ci << instruction + " %uintt" + ndrange_param + "%kfunc %firstp %psize2 %palign" 953fd4e5da5Sopenharmony_ci << "\n %psize2 = OpCopyObject %uintt %psize" 954fd4e5da5Sopenharmony_ci << return_instructions; 955fd4e5da5Sopenharmony_ci // clang-format on 956fd4e5da5Sopenharmony_ci 957fd4e5da5Sopenharmony_ci CompileSuccessfully(ss.str()); 958fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 959fd4e5da5Sopenharmony_ci EXPECT_THAT(getDiagnosticString(), HasSubstr("psize2")); 960fd4e5da5Sopenharmony_ci} 961fd4e5da5Sopenharmony_ci 962fd4e5da5Sopenharmony_ciTEST_P(ValidateSSA, 963fd4e5da5Sopenharmony_ci ForwardGetKernelNDrangeSubGroupCountNonDominantParameter6Bad) { 964fd4e5da5Sopenharmony_ci std::string instruction = GetParam().first; 965fd4e5da5Sopenharmony_ci bool with_ndrange = GetParam().second; 966fd4e5da5Sopenharmony_ci std::string ndrange_param = with_ndrange ? " %ndval " : " "; 967fd4e5da5Sopenharmony_ci 968fd4e5da5Sopenharmony_ci std::stringstream ss; 969fd4e5da5Sopenharmony_ci // clang-format off 970fd4e5da5Sopenharmony_ci ss << forwardKernelNonDominantParameterBaseCode("palign2") + " %numsg = " 971fd4e5da5Sopenharmony_ci << instruction + " %uintt" + ndrange_param + "%kfunc %firstp %psize %palign2" 972fd4e5da5Sopenharmony_ci << "\n %palign2 = OpCopyObject %uintt %palign" 973fd4e5da5Sopenharmony_ci << return_instructions; 974fd4e5da5Sopenharmony_ci // clang-format on 975fd4e5da5Sopenharmony_ci 976fd4e5da5Sopenharmony_ci if (GetParam().second) { 977fd4e5da5Sopenharmony_ci CompileSuccessfully(ss.str()); 978fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 979fd4e5da5Sopenharmony_ci EXPECT_THAT(getDiagnosticString(), HasSubstr("palign2")); 980fd4e5da5Sopenharmony_ci } 981fd4e5da5Sopenharmony_ci} 982fd4e5da5Sopenharmony_ci 983fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, PhiGood) { 984fd4e5da5Sopenharmony_ci std::string str = kHeader + kBasicTypes + 985fd4e5da5Sopenharmony_ci R"( 986fd4e5da5Sopenharmony_ci%func = OpFunction %voidt None %vfunct 987fd4e5da5Sopenharmony_ci%preheader = OpLabel 988fd4e5da5Sopenharmony_ci%init = OpCopyObject %uintt %zero 989fd4e5da5Sopenharmony_ci OpBranch %loop 990fd4e5da5Sopenharmony_ci%loop = OpLabel 991fd4e5da5Sopenharmony_ci%i = OpPhi %uintt %init %preheader %loopi %loop 992fd4e5da5Sopenharmony_ci%loopi = OpIAdd %uintt %i %one 993fd4e5da5Sopenharmony_ci OpNop 994fd4e5da5Sopenharmony_ci%cond = OpSLessThan %boolt %i %ten 995fd4e5da5Sopenharmony_ci OpLoopMerge %endl %loop None 996fd4e5da5Sopenharmony_ci OpBranchConditional %cond %loop %endl 997fd4e5da5Sopenharmony_ci%endl = OpLabel 998fd4e5da5Sopenharmony_ci OpReturn 999fd4e5da5Sopenharmony_ci OpFunctionEnd 1000fd4e5da5Sopenharmony_ci)"; 1001fd4e5da5Sopenharmony_ci 1002fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 1003fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); 1004fd4e5da5Sopenharmony_ci} 1005fd4e5da5Sopenharmony_ci 1006fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, PhiMissingTypeBad) { 1007fd4e5da5Sopenharmony_ci std::string str = kHeader + "OpName %missing \"missing\"" + kBasicTypes + 1008fd4e5da5Sopenharmony_ci R"( 1009fd4e5da5Sopenharmony_ci%func = OpFunction %voidt None %vfunct 1010fd4e5da5Sopenharmony_ci%preheader = OpLabel 1011fd4e5da5Sopenharmony_ci%init = OpCopyObject %uintt %zero 1012fd4e5da5Sopenharmony_ci OpBranch %loop 1013fd4e5da5Sopenharmony_ci%loop = OpLabel 1014fd4e5da5Sopenharmony_ci%i = OpPhi %missing %init %preheader %loopi %loop 1015fd4e5da5Sopenharmony_ci%loopi = OpIAdd %uintt %i %one 1016fd4e5da5Sopenharmony_ci OpNop 1017fd4e5da5Sopenharmony_ci%cond = OpSLessThan %boolt %i %ten 1018fd4e5da5Sopenharmony_ci OpLoopMerge %endl %loop None 1019fd4e5da5Sopenharmony_ci OpBranchConditional %cond %loop %endl 1020fd4e5da5Sopenharmony_ci%endl = OpLabel 1021fd4e5da5Sopenharmony_ci OpReturn 1022fd4e5da5Sopenharmony_ci OpFunctionEnd 1023fd4e5da5Sopenharmony_ci)"; 1024fd4e5da5Sopenharmony_ci 1025fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 1026fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 1027fd4e5da5Sopenharmony_ci EXPECT_THAT(getDiagnosticString(), HasSubstr("missing")); 1028fd4e5da5Sopenharmony_ci} 1029fd4e5da5Sopenharmony_ci 1030fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, PhiMissingIdBad) { 1031fd4e5da5Sopenharmony_ci std::string str = kHeader + "OpName %missing \"missing\"" + kBasicTypes + 1032fd4e5da5Sopenharmony_ci R"( 1033fd4e5da5Sopenharmony_ci%func = OpFunction %voidt None %vfunct 1034fd4e5da5Sopenharmony_ci%preheader = OpLabel 1035fd4e5da5Sopenharmony_ci%init = OpCopyObject %uintt %zero 1036fd4e5da5Sopenharmony_ci OpBranch %loop 1037fd4e5da5Sopenharmony_ci%loop = OpLabel 1038fd4e5da5Sopenharmony_ci%i = OpPhi %uintt %missing %preheader %loopi %loop 1039fd4e5da5Sopenharmony_ci%loopi = OpIAdd %uintt %i %one 1040fd4e5da5Sopenharmony_ci OpNop 1041fd4e5da5Sopenharmony_ci%cond = OpSLessThan %boolt %i %ten 1042fd4e5da5Sopenharmony_ci OpLoopMerge %endl %loop None 1043fd4e5da5Sopenharmony_ci OpBranchConditional %cond %loop %endl 1044fd4e5da5Sopenharmony_ci%endl = OpLabel 1045fd4e5da5Sopenharmony_ci OpReturn 1046fd4e5da5Sopenharmony_ci OpFunctionEnd 1047fd4e5da5Sopenharmony_ci)"; 1048fd4e5da5Sopenharmony_ci 1049fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 1050fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 1051fd4e5da5Sopenharmony_ci EXPECT_THAT(getDiagnosticString(), HasSubstr("missing")); 1052fd4e5da5Sopenharmony_ci} 1053fd4e5da5Sopenharmony_ci 1054fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, PhiMissingLabelBad) { 1055fd4e5da5Sopenharmony_ci std::string str = kHeader + "OpName %missing \"missing\"" + kBasicTypes + 1056fd4e5da5Sopenharmony_ci R"( 1057fd4e5da5Sopenharmony_ci%func = OpFunction %voidt None %vfunct 1058fd4e5da5Sopenharmony_ci%preheader = OpLabel 1059fd4e5da5Sopenharmony_ci%init = OpCopyObject %uintt %zero 1060fd4e5da5Sopenharmony_ci OpBranch %loop 1061fd4e5da5Sopenharmony_ci%loop = OpLabel 1062fd4e5da5Sopenharmony_ci%i = OpPhi %uintt %init %missing %loopi %loop 1063fd4e5da5Sopenharmony_ci%loopi = OpIAdd %uintt %i %one 1064fd4e5da5Sopenharmony_ci OpNop 1065fd4e5da5Sopenharmony_ci%cond = OpSLessThan %boolt %i %ten 1066fd4e5da5Sopenharmony_ci OpLoopMerge %endl %loop None 1067fd4e5da5Sopenharmony_ci OpBranchConditional %cond %loop %endl 1068fd4e5da5Sopenharmony_ci%endl = OpLabel 1069fd4e5da5Sopenharmony_ci OpReturn 1070fd4e5da5Sopenharmony_ci OpFunctionEnd 1071fd4e5da5Sopenharmony_ci)"; 1072fd4e5da5Sopenharmony_ci 1073fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 1074fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 1075fd4e5da5Sopenharmony_ci EXPECT_THAT(getDiagnosticString(), HasSubstr("missing")); 1076fd4e5da5Sopenharmony_ci} 1077fd4e5da5Sopenharmony_ci 1078fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, IdDominatesItsUseGood) { 1079fd4e5da5Sopenharmony_ci std::string str = kHeader + kBasicTypes + 1080fd4e5da5Sopenharmony_ci R"( 1081fd4e5da5Sopenharmony_ci%func = OpFunction %voidt None %vfunct 1082fd4e5da5Sopenharmony_ci%entry = OpLabel 1083fd4e5da5Sopenharmony_ci%cond = OpSLessThan %boolt %one %ten 1084fd4e5da5Sopenharmony_ci%eleven = OpIAdd %uintt %one %ten 1085fd4e5da5Sopenharmony_ci OpSelectionMerge %merge None 1086fd4e5da5Sopenharmony_ci OpBranchConditional %cond %t %f 1087fd4e5da5Sopenharmony_ci%t = OpLabel 1088fd4e5da5Sopenharmony_ci%twelve = OpIAdd %uintt %eleven %one 1089fd4e5da5Sopenharmony_ci OpBranch %merge 1090fd4e5da5Sopenharmony_ci%f = OpLabel 1091fd4e5da5Sopenharmony_ci%twentytwo = OpIAdd %uintt %eleven %ten 1092fd4e5da5Sopenharmony_ci OpBranch %merge 1093fd4e5da5Sopenharmony_ci%merge = OpLabel 1094fd4e5da5Sopenharmony_ci OpReturn 1095fd4e5da5Sopenharmony_ci OpFunctionEnd 1096fd4e5da5Sopenharmony_ci)"; 1097fd4e5da5Sopenharmony_ci 1098fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 1099fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); 1100fd4e5da5Sopenharmony_ci} 1101fd4e5da5Sopenharmony_ci 1102fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, IdDoesNotDominateItsUseBad) { 1103fd4e5da5Sopenharmony_ci std::string str = kHeader + 1104fd4e5da5Sopenharmony_ci "OpName %eleven \"eleven\"\n" 1105fd4e5da5Sopenharmony_ci "OpName %true_block \"true_block\"\n" 1106fd4e5da5Sopenharmony_ci "OpName %false_block \"false_block\"" + 1107fd4e5da5Sopenharmony_ci kBasicTypes + 1108fd4e5da5Sopenharmony_ci R"( 1109fd4e5da5Sopenharmony_ci%func = OpFunction %voidt None %vfunct 1110fd4e5da5Sopenharmony_ci%entry = OpLabel 1111fd4e5da5Sopenharmony_ci%cond = OpSLessThan %boolt %one %ten 1112fd4e5da5Sopenharmony_ci OpSelectionMerge %merge None 1113fd4e5da5Sopenharmony_ci OpBranchConditional %cond %true_block %false_block 1114fd4e5da5Sopenharmony_ci%true_block = OpLabel 1115fd4e5da5Sopenharmony_ci%eleven = OpIAdd %uintt %one %ten 1116fd4e5da5Sopenharmony_ci%twelve = OpIAdd %uintt %eleven %one 1117fd4e5da5Sopenharmony_ci OpBranch %merge 1118fd4e5da5Sopenharmony_ci%false_block = OpLabel 1119fd4e5da5Sopenharmony_ci%twentytwo = OpIAdd %uintt %eleven %ten 1120fd4e5da5Sopenharmony_ci OpBranch %merge 1121fd4e5da5Sopenharmony_ci%merge = OpLabel 1122fd4e5da5Sopenharmony_ci OpReturn 1123fd4e5da5Sopenharmony_ci OpFunctionEnd 1124fd4e5da5Sopenharmony_ci)"; 1125fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 1126fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 1127fd4e5da5Sopenharmony_ci EXPECT_THAT( 1128fd4e5da5Sopenharmony_ci getDiagnosticString(), 1129fd4e5da5Sopenharmony_ci MatchesRegex("ID '.\\[%eleven\\]' defined in block '.\\[%true_block\\]' " 1130fd4e5da5Sopenharmony_ci "does not dominate its use in block '.\\[%false_block\\]'\n" 1131fd4e5da5Sopenharmony_ci " %false_block = OpLabel\n")); 1132fd4e5da5Sopenharmony_ci} 1133fd4e5da5Sopenharmony_ci 1134fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, PhiUseDoesntDominateDefinitionGood) { 1135fd4e5da5Sopenharmony_ci std::string str = kHeader + kBasicTypes + 1136fd4e5da5Sopenharmony_ci R"( 1137fd4e5da5Sopenharmony_ci%funcintptrt = OpTypePointer Function %uintt 1138fd4e5da5Sopenharmony_ci%func = OpFunction %voidt None %vfunct 1139fd4e5da5Sopenharmony_ci%entry = OpLabel 1140fd4e5da5Sopenharmony_ci%var_one = OpVariable %funcintptrt Function %one 1141fd4e5da5Sopenharmony_ci%one_val = OpLoad %uintt %var_one 1142fd4e5da5Sopenharmony_ci OpBranch %loop 1143fd4e5da5Sopenharmony_ci%loop = OpLabel 1144fd4e5da5Sopenharmony_ci%i = OpPhi %uintt %one_val %entry %inew %cont 1145fd4e5da5Sopenharmony_ci%cond = OpSLessThan %boolt %one %ten 1146fd4e5da5Sopenharmony_ci OpLoopMerge %merge %cont None 1147fd4e5da5Sopenharmony_ci OpBranchConditional %cond %body %merge 1148fd4e5da5Sopenharmony_ci%body = OpLabel 1149fd4e5da5Sopenharmony_ci OpBranch %cont 1150fd4e5da5Sopenharmony_ci%cont = OpLabel 1151fd4e5da5Sopenharmony_ci%inew = OpIAdd %uintt %i %one 1152fd4e5da5Sopenharmony_ci OpBranch %loop 1153fd4e5da5Sopenharmony_ci%merge = OpLabel 1154fd4e5da5Sopenharmony_ci OpReturn 1155fd4e5da5Sopenharmony_ci OpFunctionEnd 1156fd4e5da5Sopenharmony_ci)"; 1157fd4e5da5Sopenharmony_ci 1158fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 1159fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); 1160fd4e5da5Sopenharmony_ci} 1161fd4e5da5Sopenharmony_ci 1162fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, 1163fd4e5da5Sopenharmony_ci PhiUseDoesntDominateUseOfPhiOperandUsedBeforeDefinitionBad) { 1164fd4e5da5Sopenharmony_ci std::string str = kHeader + "OpName %inew \"inew\"" + kBasicTypes + 1165fd4e5da5Sopenharmony_ci R"( 1166fd4e5da5Sopenharmony_ci%func = OpFunction %voidt None %vfunct 1167fd4e5da5Sopenharmony_ci%entry = OpLabel 1168fd4e5da5Sopenharmony_ci%var_one = OpVariable %intptrt Function %one 1169fd4e5da5Sopenharmony_ci%one_val = OpLoad %uintt %var_one 1170fd4e5da5Sopenharmony_ci OpBranch %loop 1171fd4e5da5Sopenharmony_ci%loop = OpLabel 1172fd4e5da5Sopenharmony_ci%i = OpPhi %uintt %one_val %entry %inew %cont 1173fd4e5da5Sopenharmony_ci%bad = OpIAdd %uintt %inew %one 1174fd4e5da5Sopenharmony_ci%cond = OpSLessThan %boolt %one %ten 1175fd4e5da5Sopenharmony_ci OpLoopMerge %merge %cont None 1176fd4e5da5Sopenharmony_ci OpBranchConditional %cond %body %merge 1177fd4e5da5Sopenharmony_ci%body = OpLabel 1178fd4e5da5Sopenharmony_ci OpBranch %cont 1179fd4e5da5Sopenharmony_ci%cont = OpLabel 1180fd4e5da5Sopenharmony_ci%inew = OpIAdd %uintt %i %one 1181fd4e5da5Sopenharmony_ci OpBranch %loop 1182fd4e5da5Sopenharmony_ci%merge = OpLabel 1183fd4e5da5Sopenharmony_ci OpReturn 1184fd4e5da5Sopenharmony_ci OpFunctionEnd 1185fd4e5da5Sopenharmony_ci)"; 1186fd4e5da5Sopenharmony_ci 1187fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 1188fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 1189fd4e5da5Sopenharmony_ci EXPECT_THAT(getDiagnosticString(), 1190fd4e5da5Sopenharmony_ci MatchesRegex("ID '.\\[%inew\\]' has not been defined\n" 1191fd4e5da5Sopenharmony_ci " %19 = OpIAdd %uint %inew %uint_1\n")); 1192fd4e5da5Sopenharmony_ci} 1193fd4e5da5Sopenharmony_ci 1194fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, PhiUseMayComeFromNonDominatingBlockGood) { 1195fd4e5da5Sopenharmony_ci std::string str = kHeader + "OpName %if_true \"if_true\"\n" + 1196fd4e5da5Sopenharmony_ci "OpName %exit \"exit\"\n" + "OpName %copy \"copy\"\n" + 1197fd4e5da5Sopenharmony_ci kBasicTypes + 1198fd4e5da5Sopenharmony_ci R"( 1199fd4e5da5Sopenharmony_ci%func = OpFunction %voidt None %vfunct 1200fd4e5da5Sopenharmony_ci%entry = OpLabel 1201fd4e5da5Sopenharmony_ci OpBranchConditional %false %if_true %exit 1202fd4e5da5Sopenharmony_ci 1203fd4e5da5Sopenharmony_ci%if_true = OpLabel 1204fd4e5da5Sopenharmony_ci%copy = OpCopyObject %boolt %false 1205fd4e5da5Sopenharmony_ci OpBranch %exit 1206fd4e5da5Sopenharmony_ci 1207fd4e5da5Sopenharmony_ci; The use of %copy here is ok, even though it was defined 1208fd4e5da5Sopenharmony_ci; in a block that does not dominate %exit. That's the point 1209fd4e5da5Sopenharmony_ci; of an OpPhi. 1210fd4e5da5Sopenharmony_ci%exit = OpLabel 1211fd4e5da5Sopenharmony_ci%value = OpPhi %boolt %false %entry %copy %if_true 1212fd4e5da5Sopenharmony_ci OpReturn 1213fd4e5da5Sopenharmony_ci OpFunctionEnd 1214fd4e5da5Sopenharmony_ci)"; 1215fd4e5da5Sopenharmony_ci 1216fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 1217fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()) << getDiagnosticString(); 1218fd4e5da5Sopenharmony_ci} 1219fd4e5da5Sopenharmony_ci 1220fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, PhiUsesItsOwnDefinitionGood) { 1221fd4e5da5Sopenharmony_ci // See https://github.com/KhronosGroup/SPIRV-Tools/issues/415 1222fd4e5da5Sopenharmony_ci // 1223fd4e5da5Sopenharmony_ci // Non-phi instructions can't use their own definitions, as 1224fd4e5da5Sopenharmony_ci // already checked in test DominateUsageSameInstructionBad. 1225fd4e5da5Sopenharmony_ci std::string str = kHeader + "OpName %loop \"loop\"\n" + 1226fd4e5da5Sopenharmony_ci "OpName %value \"value\"\n" + kBasicTypes + 1227fd4e5da5Sopenharmony_ci R"( 1228fd4e5da5Sopenharmony_ci%func = OpFunction %voidt None %vfunct 1229fd4e5da5Sopenharmony_ci%entry = OpLabel 1230fd4e5da5Sopenharmony_ci OpBranch %loop 1231fd4e5da5Sopenharmony_ci 1232fd4e5da5Sopenharmony_ci%loop = OpLabel 1233fd4e5da5Sopenharmony_ci%value = OpPhi %boolt %false %entry %value %loop 1234fd4e5da5Sopenharmony_ci OpBranch %loop 1235fd4e5da5Sopenharmony_ci 1236fd4e5da5Sopenharmony_ci OpFunctionEnd 1237fd4e5da5Sopenharmony_ci)"; 1238fd4e5da5Sopenharmony_ci 1239fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 1240fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()) << getDiagnosticString(); 1241fd4e5da5Sopenharmony_ci} 1242fd4e5da5Sopenharmony_ci 1243fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, PhiVariableDefNotDominatedByParentBlockBad) { 1244fd4e5da5Sopenharmony_ci std::string str = kHeader + "OpName %if_true \"if_true\"\n" + 1245fd4e5da5Sopenharmony_ci "OpName %if_false \"if_false\"\n" + 1246fd4e5da5Sopenharmony_ci "OpName %exit \"exit\"\n" + "OpName %value \"phi\"\n" + 1247fd4e5da5Sopenharmony_ci "OpName %true_copy \"true_copy\"\n" + 1248fd4e5da5Sopenharmony_ci "OpName %false_copy \"false_copy\"\n" + kBasicTypes + 1249fd4e5da5Sopenharmony_ci R"( 1250fd4e5da5Sopenharmony_ci%func = OpFunction %voidt None %vfunct 1251fd4e5da5Sopenharmony_ci%entry = OpLabel 1252fd4e5da5Sopenharmony_ci OpBranchConditional %false %if_true %if_false 1253fd4e5da5Sopenharmony_ci 1254fd4e5da5Sopenharmony_ci%if_true = OpLabel 1255fd4e5da5Sopenharmony_ci%true_copy = OpCopyObject %boolt %false 1256fd4e5da5Sopenharmony_ci OpBranch %exit 1257fd4e5da5Sopenharmony_ci 1258fd4e5da5Sopenharmony_ci%if_false = OpLabel 1259fd4e5da5Sopenharmony_ci%false_copy = OpCopyObject %boolt %false 1260fd4e5da5Sopenharmony_ci OpBranch %exit 1261fd4e5da5Sopenharmony_ci 1262fd4e5da5Sopenharmony_ci; The (variable,Id) pairs are swapped. 1263fd4e5da5Sopenharmony_ci%exit = OpLabel 1264fd4e5da5Sopenharmony_ci%value = OpPhi %boolt %true_copy %if_false %false_copy %if_true 1265fd4e5da5Sopenharmony_ci OpReturn 1266fd4e5da5Sopenharmony_ci OpFunctionEnd 1267fd4e5da5Sopenharmony_ci)"; 1268fd4e5da5Sopenharmony_ci 1269fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 1270fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 1271fd4e5da5Sopenharmony_ci EXPECT_THAT(getDiagnosticString(), 1272fd4e5da5Sopenharmony_ci MatchesRegex( 1273fd4e5da5Sopenharmony_ci "In OpPhi instruction '.\\[%phi\\]', ID '.\\[%true_copy\\]' " 1274fd4e5da5Sopenharmony_ci "definition does not dominate its parent '.\\[%if_false\\]'\n" 1275fd4e5da5Sopenharmony_ci " %phi = OpPhi %bool %true_copy %if_false %false_copy " 1276fd4e5da5Sopenharmony_ci "%if_true\n")); 1277fd4e5da5Sopenharmony_ci} 1278fd4e5da5Sopenharmony_ci 1279fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, PhiVariableDefDominatesButNotDefinedInParentBlock) { 1280fd4e5da5Sopenharmony_ci std::string str = kHeader + "OpName %if_true \"if_true\"\n" + kBasicTypes + 1281fd4e5da5Sopenharmony_ci R"( 1282fd4e5da5Sopenharmony_ci%func = OpFunction %voidt None %vfunct 1283fd4e5da5Sopenharmony_ci%entry = OpLabel 1284fd4e5da5Sopenharmony_ci OpBranchConditional %false %if_true %if_false 1285fd4e5da5Sopenharmony_ci 1286fd4e5da5Sopenharmony_ci%if_true = OpLabel 1287fd4e5da5Sopenharmony_ci%true_copy = OpCopyObject %boolt %false 1288fd4e5da5Sopenharmony_ci OpBranch %if_tnext 1289fd4e5da5Sopenharmony_ci%if_tnext = OpLabel 1290fd4e5da5Sopenharmony_ci OpBranch %exit 1291fd4e5da5Sopenharmony_ci 1292fd4e5da5Sopenharmony_ci%if_false = OpLabel 1293fd4e5da5Sopenharmony_ci%false_copy = OpCopyObject %boolt %false 1294fd4e5da5Sopenharmony_ci OpBranch %if_fnext 1295fd4e5da5Sopenharmony_ci%if_fnext = OpLabel 1296fd4e5da5Sopenharmony_ci OpBranch %exit 1297fd4e5da5Sopenharmony_ci 1298fd4e5da5Sopenharmony_ci%exit = OpLabel 1299fd4e5da5Sopenharmony_ci%value = OpPhi %boolt %true_copy %if_tnext %false_copy %if_fnext 1300fd4e5da5Sopenharmony_ci OpReturn 1301fd4e5da5Sopenharmony_ci OpFunctionEnd 1302fd4e5da5Sopenharmony_ci)"; 1303fd4e5da5Sopenharmony_ci 1304fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 1305fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); 1306fd4e5da5Sopenharmony_ci} 1307fd4e5da5Sopenharmony_ci 1308fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, 1309fd4e5da5Sopenharmony_ci DominanceCheckIgnoresUsesInUnreachableBlocksDefInBlockGood) { 1310fd4e5da5Sopenharmony_ci std::string str = kHeader + kBasicTypes + 1311fd4e5da5Sopenharmony_ci R"( 1312fd4e5da5Sopenharmony_ci%func = OpFunction %voidt None %vfunct 1313fd4e5da5Sopenharmony_ci%entry = OpLabel 1314fd4e5da5Sopenharmony_ci%def = OpCopyObject %boolt %false 1315fd4e5da5Sopenharmony_ci OpReturn 1316fd4e5da5Sopenharmony_ci 1317fd4e5da5Sopenharmony_ci%unreach = OpLabel 1318fd4e5da5Sopenharmony_ci%use = OpCopyObject %boolt %def 1319fd4e5da5Sopenharmony_ci OpReturn 1320fd4e5da5Sopenharmony_ci OpFunctionEnd 1321fd4e5da5Sopenharmony_ci)"; 1322fd4e5da5Sopenharmony_ci 1323fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 1324fd4e5da5Sopenharmony_ci EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()) << getDiagnosticString(); 1325fd4e5da5Sopenharmony_ci} 1326fd4e5da5Sopenharmony_ci 1327fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, PhiVariableUnreachableDefNotInParentBlock) { 1328fd4e5da5Sopenharmony_ci std::string str = kHeader + "OpName %unreachable \"unreachable\"\n" + 1329fd4e5da5Sopenharmony_ci kBasicTypes + 1330fd4e5da5Sopenharmony_ci R"( 1331fd4e5da5Sopenharmony_ci%func = OpFunction %voidt None %vfunct 1332fd4e5da5Sopenharmony_ci%entry = OpLabel 1333fd4e5da5Sopenharmony_ci OpBranch %if_false 1334fd4e5da5Sopenharmony_ci 1335fd4e5da5Sopenharmony_ci%unreachable = OpLabel 1336fd4e5da5Sopenharmony_ci%copy = OpCopyObject %boolt %false 1337fd4e5da5Sopenharmony_ci OpBranch %if_tnext 1338fd4e5da5Sopenharmony_ci%if_tnext = OpLabel 1339fd4e5da5Sopenharmony_ci OpBranch %exit 1340fd4e5da5Sopenharmony_ci 1341fd4e5da5Sopenharmony_ci%if_false = OpLabel 1342fd4e5da5Sopenharmony_ci%false_copy = OpCopyObject %boolt %false 1343fd4e5da5Sopenharmony_ci OpBranch %if_fnext 1344fd4e5da5Sopenharmony_ci%if_fnext = OpLabel 1345fd4e5da5Sopenharmony_ci OpBranch %exit 1346fd4e5da5Sopenharmony_ci 1347fd4e5da5Sopenharmony_ci%exit = OpLabel 1348fd4e5da5Sopenharmony_ci%value = OpPhi %boolt %copy %if_tnext %false_copy %if_fnext 1349fd4e5da5Sopenharmony_ci OpReturn 1350fd4e5da5Sopenharmony_ci OpFunctionEnd 1351fd4e5da5Sopenharmony_ci)"; 1352fd4e5da5Sopenharmony_ci 1353fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 1354fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); 1355fd4e5da5Sopenharmony_ci} 1356fd4e5da5Sopenharmony_ci 1357fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, 1358fd4e5da5Sopenharmony_ci DominanceCheckIgnoresUsesInUnreachableBlocksDefIsParamGood) { 1359fd4e5da5Sopenharmony_ci std::string str = kHeader + kBasicTypes + 1360fd4e5da5Sopenharmony_ci R"( 1361fd4e5da5Sopenharmony_ci%void_fn_int = OpTypeFunction %voidt %uintt 1362fd4e5da5Sopenharmony_ci%func = OpFunction %voidt None %void_fn_int 1363fd4e5da5Sopenharmony_ci%int_param = OpFunctionParameter %uintt 1364fd4e5da5Sopenharmony_ci%entry = OpLabel 1365fd4e5da5Sopenharmony_ci OpReturn 1366fd4e5da5Sopenharmony_ci 1367fd4e5da5Sopenharmony_ci%unreach = OpLabel 1368fd4e5da5Sopenharmony_ci%use = OpCopyObject %uintt %int_param 1369fd4e5da5Sopenharmony_ci OpReturn 1370fd4e5da5Sopenharmony_ci OpFunctionEnd 1371fd4e5da5Sopenharmony_ci)"; 1372fd4e5da5Sopenharmony_ci 1373fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 1374fd4e5da5Sopenharmony_ci EXPECT_EQ(SPV_SUCCESS, ValidateInstructions()) << getDiagnosticString(); 1375fd4e5da5Sopenharmony_ci} 1376fd4e5da5Sopenharmony_ci 1377fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, UseFunctionParameterFromOtherFunctionBad) { 1378fd4e5da5Sopenharmony_ci std::string str = kHeader + 1379fd4e5da5Sopenharmony_ci "OpName %first \"first\"\n" 1380fd4e5da5Sopenharmony_ci "OpName %func \"func\"\n" + 1381fd4e5da5Sopenharmony_ci "OpName %func2 \"func2\"\n" + kBasicTypes + 1382fd4e5da5Sopenharmony_ci R"( 1383fd4e5da5Sopenharmony_ci%viifunct = OpTypeFunction %voidt %uintt %uintt 1384fd4e5da5Sopenharmony_ci%func = OpFunction %voidt None %viifunct 1385fd4e5da5Sopenharmony_ci%first = OpFunctionParameter %uintt 1386fd4e5da5Sopenharmony_ci%second = OpFunctionParameter %uintt 1387fd4e5da5Sopenharmony_ci OpFunctionEnd 1388fd4e5da5Sopenharmony_ci%func2 = OpFunction %voidt None %viifunct 1389fd4e5da5Sopenharmony_ci%first2 = OpFunctionParameter %uintt 1390fd4e5da5Sopenharmony_ci%second2 = OpFunctionParameter %uintt 1391fd4e5da5Sopenharmony_ci%entry2 = OpLabel 1392fd4e5da5Sopenharmony_ci%baduse = OpIAdd %uintt %first %first2 1393fd4e5da5Sopenharmony_ci OpReturn 1394fd4e5da5Sopenharmony_ci OpFunctionEnd 1395fd4e5da5Sopenharmony_ci)"; 1396fd4e5da5Sopenharmony_ci 1397fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 1398fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions()); 1399fd4e5da5Sopenharmony_ci EXPECT_THAT(getDiagnosticString(), 1400fd4e5da5Sopenharmony_ci MatchesRegex( 1401fd4e5da5Sopenharmony_ci "ID '.\\[%first\\]' used in function '.\\[%func2\\]' is used " 1402fd4e5da5Sopenharmony_ci "outside of it's defining function '.\\[%func\\]'\n" 1403fd4e5da5Sopenharmony_ci " %func = OpFunction %void None %14\n")); 1404fd4e5da5Sopenharmony_ci} 1405fd4e5da5Sopenharmony_ci 1406fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, TypeForwardPointerForwardReference) { 1407fd4e5da5Sopenharmony_ci // See https://github.com/KhronosGroup/SPIRV-Tools/issues/429 1408fd4e5da5Sopenharmony_ci // 1409fd4e5da5Sopenharmony_ci // ForwardPointers can references instructions that have not been defined 1410fd4e5da5Sopenharmony_ci std::string str = R"( 1411fd4e5da5Sopenharmony_ci OpCapability Kernel 1412fd4e5da5Sopenharmony_ci OpCapability Addresses 1413fd4e5da5Sopenharmony_ci OpCapability Linkage 1414fd4e5da5Sopenharmony_ci OpMemoryModel Logical OpenCL 1415fd4e5da5Sopenharmony_ci OpName %intptrt "intptrt" 1416fd4e5da5Sopenharmony_ci OpTypeForwardPointer %intptrt UniformConstant 1417fd4e5da5Sopenharmony_ci %uint = OpTypeInt 32 0 1418fd4e5da5Sopenharmony_ci %struct = OpTypeStruct %uint 1419fd4e5da5Sopenharmony_ci %intptrt = OpTypePointer UniformConstant %struct 1420fd4e5da5Sopenharmony_ci)"; 1421fd4e5da5Sopenharmony_ci 1422fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 1423fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); 1424fd4e5da5Sopenharmony_ci} 1425fd4e5da5Sopenharmony_ci 1426fd4e5da5Sopenharmony_ciTEST_F(ValidateSSA, TypeStructForwardReference) { 1427fd4e5da5Sopenharmony_ci std::string str = R"( 1428fd4e5da5Sopenharmony_ci OpCapability Kernel 1429fd4e5da5Sopenharmony_ci OpCapability Addresses 1430fd4e5da5Sopenharmony_ci OpCapability Linkage 1431fd4e5da5Sopenharmony_ci OpMemoryModel Logical OpenCL 1432fd4e5da5Sopenharmony_ci OpName %structptr "structptr" 1433fd4e5da5Sopenharmony_ci OpTypeForwardPointer %structptr UniformConstant 1434fd4e5da5Sopenharmony_ci %uint = OpTypeInt 32 0 1435fd4e5da5Sopenharmony_ci %structt1 = OpTypeStruct %structptr %uint 1436fd4e5da5Sopenharmony_ci %structt2 = OpTypeStruct %uint %structptr 1437fd4e5da5Sopenharmony_ci %structt3 = OpTypeStruct %uint %uint %structptr 1438fd4e5da5Sopenharmony_ci %structt4 = OpTypeStruct %uint %uint %uint %structptr 1439fd4e5da5Sopenharmony_ci %structptr = OpTypePointer UniformConstant %structt1 1440fd4e5da5Sopenharmony_ci)"; 1441fd4e5da5Sopenharmony_ci 1442fd4e5da5Sopenharmony_ci CompileSuccessfully(str); 1443fd4e5da5Sopenharmony_ci ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); 1444fd4e5da5Sopenharmony_ci} 1445fd4e5da5Sopenharmony_ci 1446fd4e5da5Sopenharmony_ci// TODO(umar): OpGroupMemberDecorate 1447fd4e5da5Sopenharmony_ci 1448fd4e5da5Sopenharmony_ci} // namespace 1449fd4e5da5Sopenharmony_ci} // namespace val 1450fd4e5da5Sopenharmony_ci} // namespace spvtools 1451