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 ::testing::Values;
30 using ValidateStorage = spvtest::ValidateBase<std::string>;
31 using ValidateStorageClass =
32 spvtest::ValidateBase<std::tuple<std::string, bool, bool, std::string>>;
33
TEST_F(ValidateStorage,FunctionStorageInsideFunction)34 TEST_F(ValidateStorage, FunctionStorageInsideFunction) {
35 char str[] = R"(
36 OpCapability Shader
37 OpCapability Linkage
38 OpMemoryModel Logical GLSL450
39 %intt = OpTypeInt 32 1
40 %voidt = OpTypeVoid
41 %vfunct = OpTypeFunction %voidt
42 %ptrt = OpTypePointer Function %intt
43 %func = OpFunction %voidt None %vfunct
44 %funcl = OpLabel
45 %var = OpVariable %ptrt Function
46 OpReturn
47 OpFunctionEnd
48 )";
49
50 CompileSuccessfully(str);
51 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
52 }
53
TEST_F(ValidateStorage,FunctionStorageOutsideFunction)54 TEST_F(ValidateStorage, FunctionStorageOutsideFunction) {
55 char str[] = R"(
56 OpCapability Shader
57 OpCapability Linkage
58 OpMemoryModel Logical GLSL450
59 %intt = OpTypeInt 32 1
60 %voidt = OpTypeVoid
61 %vfunct = OpTypeFunction %voidt
62 %ptrt = OpTypePointer Function %intt
63 %var = OpVariable %ptrt Function
64 %func = OpFunction %voidt None %vfunct
65 %funcl = OpLabel
66 OpReturn
67 OpFunctionEnd
68 )";
69
70 CompileSuccessfully(str);
71 ASSERT_EQ(SPV_ERROR_INVALID_LAYOUT, ValidateInstructions());
72 EXPECT_THAT(getDiagnosticString(),
73 HasSubstr("Variables can not have a function[7] storage class "
74 "outside of a function"));
75 }
76
TEST_F(ValidateStorage,OtherStorageOutsideFunction)77 TEST_F(ValidateStorage, OtherStorageOutsideFunction) {
78 char str[] = R"(
79 OpCapability Shader
80 OpCapability Kernel
81 OpCapability AtomicStorage
82 OpCapability Linkage
83 OpMemoryModel Logical GLSL450
84 %intt = OpTypeInt 32 0
85 %voidt = OpTypeVoid
86 %vfunct = OpTypeFunction %voidt
87 %uniconptrt = OpTypePointer UniformConstant %intt
88 %unicon = OpVariable %uniconptrt UniformConstant
89 %inputptrt = OpTypePointer Input %intt
90 %input = OpVariable %inputptrt Input
91 %unifptrt = OpTypePointer Uniform %intt
92 %unif = OpVariable %unifptrt Uniform
93 %outputptrt = OpTypePointer Output %intt
94 %output = OpVariable %outputptrt Output
95 %wgroupptrt = OpTypePointer Workgroup %intt
96 %wgroup = OpVariable %wgroupptrt Workgroup
97 %xwgrpptrt = OpTypePointer CrossWorkgroup %intt
98 %xwgrp = OpVariable %xwgrpptrt CrossWorkgroup
99 %privptrt = OpTypePointer Private %intt
100 %priv = OpVariable %privptrt Private
101 %pushcoptrt = OpTypePointer PushConstant %intt
102 %pushco = OpVariable %pushcoptrt PushConstant
103 %atomcptrt = OpTypePointer AtomicCounter %intt
104 %atomct = OpVariable %atomcptrt AtomicCounter
105 %imageptrt = OpTypePointer Image %intt
106 %image = OpVariable %imageptrt Image
107 %func = OpFunction %voidt None %vfunct
108 %funcl = OpLabel
109 OpReturn
110 OpFunctionEnd
111 )";
112
113 CompileSuccessfully(str);
114 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
115 }
116
117 // clang-format off
TEST_P(ValidateStorage,OtherStorageInsideFunction)118 TEST_P(ValidateStorage, OtherStorageInsideFunction) {
119 std::stringstream ss;
120 ss << R"(
121 OpCapability Shader
122 OpCapability Kernel
123 OpCapability AtomicStorage
124 OpCapability Linkage
125 OpMemoryModel Logical GLSL450
126 %intt = OpTypeInt 32 0
127 %voidt = OpTypeVoid
128 %vfunct = OpTypeFunction %voidt
129 %ptrt = OpTypePointer Function %intt
130 %func = OpFunction %voidt None %vfunct
131 %funcl = OpLabel
132 %var = OpVariable %ptrt )" << GetParam() << R"(
133 OpReturn
134 OpFunctionEnd
135 )";
136
137 CompileSuccessfully(ss.str());
138 ASSERT_EQ(SPV_ERROR_INVALID_LAYOUT, ValidateInstructions());
139 EXPECT_THAT(getDiagnosticString(), HasSubstr(
140 "Variables must have a function[7] storage class inside of a function"));
141 }
142
143 INSTANTIATE_TEST_SUITE_P(MatrixOp, ValidateStorage,
144 ::testing::Values(
145 "Input",
146 "Uniform",
147 "Output",
148 "Workgroup",
149 "CrossWorkgroup",
150 "Private",
151 "PushConstant",
152 "AtomicCounter",
153 "Image"));
154 // clang-format on
155
TEST_F(ValidateStorage,GenericVariableOutsideFunction)156 TEST_F(ValidateStorage, GenericVariableOutsideFunction) {
157 const auto str = R"(
158 OpCapability Kernel
159 OpCapability Linkage
160 OpCapability GenericPointer
161 OpMemoryModel Logical OpenCL
162 %intt = OpTypeInt 32 0
163 %ptrt = OpTypePointer Function %intt
164 %var = OpVariable %ptrt Generic
165 )";
166 CompileSuccessfully(str);
167 ASSERT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions());
168 EXPECT_THAT(getDiagnosticString(),
169 HasSubstr("OpVariable storage class cannot be Generic"));
170 }
171
TEST_F(ValidateStorage,GenericVariableInsideFunction)172 TEST_F(ValidateStorage, GenericVariableInsideFunction) {
173 const auto str = R"(
174 OpCapability Shader
175 OpCapability Linkage
176 OpCapability GenericPointer
177 OpMemoryModel Logical GLSL450
178 %intt = OpTypeInt 32 1
179 %voidt = OpTypeVoid
180 %vfunct = OpTypeFunction %voidt
181 %ptrt = OpTypePointer Function %intt
182 %func = OpFunction %voidt None %vfunct
183 %funcl = OpLabel
184 %var = OpVariable %ptrt Generic
185 OpReturn
186 OpFunctionEnd
187 )";
188 CompileSuccessfully(str);
189 EXPECT_EQ(SPV_ERROR_INVALID_BINARY, ValidateInstructions());
190 EXPECT_THAT(getDiagnosticString(),
191 HasSubstr("OpVariable storage class cannot be Generic"));
192 }
193
TEST_F(ValidateStorage,RelaxedLogicalPointerFunctionParam)194 TEST_F(ValidateStorage, RelaxedLogicalPointerFunctionParam) {
195 const auto str = R"(
196 OpCapability Shader
197 OpCapability Linkage
198 OpMemoryModel Logical GLSL450
199 %intt = OpTypeInt 32 1
200 %voidt = OpTypeVoid
201 %ptrt = OpTypePointer Function %intt
202 %vfunct = OpTypeFunction %voidt
203 %vifunct = OpTypeFunction %voidt %ptrt
204 %wgroupptrt = OpTypePointer Workgroup %intt
205 %wgroup = OpVariable %wgroupptrt Workgroup
206 %main = OpFunction %voidt None %vfunct
207 %mainl = OpLabel
208 %ret = OpFunctionCall %voidt %func %wgroup
209 OpReturn
210 OpFunctionEnd
211 %func = OpFunction %voidt None %vifunct
212 %arg = OpFunctionParameter %ptrt
213 %funcl = OpLabel
214 OpReturn
215 OpFunctionEnd
216 )";
217 CompileSuccessfully(str);
218 getValidatorOptions()->before_hlsl_legalization = true;
219 ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
220 }
221
TEST_F(ValidateStorage,RelaxedLogicalPointerFunctionParamBad)222 TEST_F(ValidateStorage, RelaxedLogicalPointerFunctionParamBad) {
223 const auto str = R"(
224 OpCapability Shader
225 OpCapability Linkage
226 OpMemoryModel Logical GLSL450
227 %floatt = OpTypeFloat 32
228 %intt = OpTypeInt 32 1
229 %voidt = OpTypeVoid
230 %ptrt = OpTypePointer Function %intt
231 %vfunct = OpTypeFunction %voidt
232 %vifunct = OpTypeFunction %voidt %ptrt
233 %wgroupptrt = OpTypePointer Workgroup %floatt
234 %wgroup = OpVariable %wgroupptrt Workgroup
235 %main = OpFunction %voidt None %vfunct
236 %mainl = OpLabel
237 %ret = OpFunctionCall %voidt %func %wgroup
238 OpReturn
239 OpFunctionEnd
240 %func = OpFunction %voidt None %vifunct
241 %arg = OpFunctionParameter %ptrt
242 %funcl = OpLabel
243 OpReturn
244 OpFunctionEnd
245 )";
246 CompileSuccessfully(str);
247 getValidatorOptions()->relax_logical_pointer = true;
248 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
249 EXPECT_THAT(getDiagnosticString(),
250 HasSubstr("OpFunctionCall Argument <id> '"));
251 }
252
253 } // namespace
254 } // namespace val
255 } // namespace spvtools
256