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
TEST_F(ValidateStorage,FunctionStorageInsideFunction)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
TEST_F(ValidateStorage,FunctionStorageOutsideFunction)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
TEST_F(ValidateStorage,OtherStorageOutsideFunction)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
TEST_P(ValidateStorage,OtherStorageInsideFunction)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
TEST_F(ValidateStorage,GenericVariableOutsideFunction)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
TEST_F(ValidateStorage,GenericVariableInsideFunction)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