1 // Copyright (c) 2015-2016 The Khronos Group Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Validation tests for OpVariable storage class 16 17 #include <sstream> 18 #include <string> 19 #include <tuple> 20 21 #include "gmock/gmock.h" 22 #include "test/val/val_fixtures.h" 23 24 namespace spvtools { 25 namespace val { 26 namespace { 27 28 using ::testing::HasSubstr; 29 using ValidateStorage = spvtest::ValidateBase<std::string>; 30 31 TEST_F(ValidateStorage, FunctionStorageInsideFunction) { 32 char str[] = R"( 33 OpCapability Shader 34 OpCapability Linkage 35 OpMemoryModel Logical GLSL450 36 %intt = OpTypeInt 32 1 37 %voidt = OpTypeVoid 38 %vfunct = OpTypeFunction %voidt 39 %ptrt = OpTypePointer Function %intt 40 %func = OpFunction %voidt None %vfunct 41 %funcl = OpLabel 42 %var = OpVariable %ptrt Function 43 OpReturn 44 OpFunctionEnd 45 )"; 46 47 CompileSuccessfully(str); 48 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); 49 } 50 51 TEST_F(ValidateStorage, FunctionStorageOutsideFunction) { 52 char str[] = R"( 53 OpCapability Shader 54 OpCapability Linkage 55 OpMemoryModel Logical GLSL450 56 %intt = OpTypeInt 32 1 57 %voidt = OpTypeVoid 58 %vfunct = OpTypeFunction %voidt 59 %ptrt = OpTypePointer Function %intt 60 %var = OpVariable %ptrt Function 61 %func = OpFunction %voidt None %vfunct 62 %funcl = OpLabel 63 OpReturn 64 OpFunctionEnd 65 )"; 66 67 CompileSuccessfully(str); 68 ASSERT_EQ(SPV_ERROR_INVALID_LAYOUT, ValidateInstructions()); 69 EXPECT_THAT(getDiagnosticString(), 70 HasSubstr("Variables can not have a function[7] storage class " 71 "outside of a function")); 72 } 73 74 TEST_F(ValidateStorage, OtherStorageOutsideFunction) { 75 char str[] = R"( 76 OpCapability Shader 77 OpCapability Kernel 78 OpCapability AtomicStorage 79 OpCapability Linkage 80 OpMemoryModel Logical GLSL450 81 %intt = OpTypeInt 32 0 82 %voidt = OpTypeVoid 83 %vfunct = OpTypeFunction %voidt 84 %uniconptrt = OpTypePointer UniformConstant %intt 85 %unicon = OpVariable %uniconptrt UniformConstant 86 %inputptrt = OpTypePointer Input %intt 87 %input = OpVariable %inputptrt Input 88 %unifptrt = OpTypePointer Uniform %intt 89 %unif = OpVariable %unifptrt Uniform 90 %outputptrt = OpTypePointer Output %intt 91 %output = OpVariable %outputptrt Output 92 %wgroupptrt = OpTypePointer Workgroup %intt 93 %wgroup = OpVariable %wgroupptrt Workgroup 94 %xwgrpptrt = OpTypePointer CrossWorkgroup %intt 95 %xwgrp = OpVariable %xwgrpptrt CrossWorkgroup 96 %privptrt = OpTypePointer Private %intt 97 %priv = OpVariable %privptrt Private 98 %pushcoptrt = OpTypePointer PushConstant %intt 99 %pushco = OpVariable %pushcoptrt PushConstant 100 %atomcptrt = OpTypePointer AtomicCounter %intt 101 %atomct = OpVariable %atomcptrt AtomicCounter 102 %imageptrt = OpTypePointer Image %intt 103 %image = OpVariable %imageptrt Image 104 %func = OpFunction %voidt None %vfunct 105 %funcl = OpLabel 106 OpReturn 107 OpFunctionEnd 108 )"; 109 110 CompileSuccessfully(str); 111 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions()); 112 } 113 114 // clang-format off 115 TEST_P(ValidateStorage, OtherStorageInsideFunction) { 116 std::stringstream ss; 117 ss << R"( 118 OpCapability Shader 119 OpCapability Kernel 120 OpCapability AtomicStorage 121 OpCapability Linkage 122 OpMemoryModel Logical GLSL450 123 %intt = OpTypeInt 32 0 124 %voidt = OpTypeVoid 125 %vfunct = OpTypeFunction %voidt 126 %ptrt = OpTypePointer Function %intt 127 %func = OpFunction %voidt None %vfunct 128 %funcl = OpLabel 129 %var = OpVariable %ptrt )" << GetParam() << R"( 130 OpReturn 131 OpFunctionEnd 132 )"; 133 134 CompileSuccessfully(ss.str()); 135 ASSERT_EQ(SPV_ERROR_INVALID_LAYOUT, ValidateInstructions()); 136 EXPECT_THAT(getDiagnosticString(), HasSubstr( 137 "Variables must have a function[7] storage class inside of a function")); 138 } 139 140 INSTANTIATE_TEST_CASE_P(MatrixOp, ValidateStorage, 141 ::testing::Values( 142 "Input", 143 "Uniform", 144 "Output", 145 "Workgroup", 146 "CrossWorkgroup", 147 "Private", 148 "PushConstant", 149 "AtomicCounter", 150 "Image"),); 151 // clang-format on 152 153 TEST_F(ValidateStorage, GenericVariableOutsideFunction) { 154 const auto str = R"( 155 OpCapability Kernel 156 OpCapability Linkage 157 OpMemoryModel Logical OpenCL 158 %intt = OpTypeInt 32 0 159 %ptrt = OpTypePointer Function %intt 160 %var = OpVariable %ptrt Generic 161 )"; 162 CompileSuccessfully(str); 163 ASSERT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions()); 164 EXPECT_THAT(getDiagnosticString(), 165 HasSubstr("OpVariable storage class cannot be Generic")); 166 } 167 168 TEST_F(ValidateStorage, GenericVariableInsideFunction) { 169 const auto str = R"( 170 OpCapability Shader 171 OpCapability Linkage 172 OpMemoryModel Logical GLSL450 173 %intt = OpTypeInt 32 1 174 %voidt = OpTypeVoid 175 %vfunct = OpTypeFunction %voidt 176 %ptrt = OpTypePointer Function %intt 177 %func = OpFunction %voidt None %vfunct 178 %funcl = OpLabel 179 %var = OpVariable %ptrt Generic 180 OpReturn 181 OpFunctionEnd 182 )"; 183 CompileSuccessfully(str); 184 ASSERT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions()); 185 EXPECT_THAT(getDiagnosticString(), 186 HasSubstr("OpVariable storage class cannot be Generic")); 187 } 188 189 } // namespace 190 } // namespace val 191 } // namespace spvtools 192