1 // Copyright (c) 2018 Google LLC.
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 #include <string>
16
17 #include "gmock/gmock.h"
18 #include "test/unit_spirv.h"
19 #include "test/val/val_fixtures.h"
20
21 namespace spvtools {
22 namespace val {
23 namespace {
24
25 using ::testing::HasSubstr;
26
27 using ValidateInterfacesTest = spvtest::ValidateBase<bool>;
28
TEST_F(ValidateInterfacesTest,EntryPointMissingInput)29 TEST_F(ValidateInterfacesTest, EntryPointMissingInput) {
30 std::string text = R"(
31 OpCapability Shader
32 OpMemoryModel Logical GLSL450
33 OpEntryPoint Fragment %1 "func"
34 OpExecutionMode %1 OriginUpperLeft
35 %2 = OpTypeVoid
36 %3 = OpTypeInt 32 0
37 %4 = OpTypePointer Input %3
38 %5 = OpVariable %4 Input
39 %6 = OpTypeFunction %2
40 %1 = OpFunction %2 None %6
41 %7 = OpLabel
42 %8 = OpLoad %3 %5
43 OpReturn
44 OpFunctionEnd
45 )";
46
47 CompileSuccessfully(text);
48 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
49 EXPECT_THAT(
50 getDiagnosticString(),
51 HasSubstr("Input variable id <5> is used by entry point 'func' id <1>, "
52 "but is not listed as an interface"));
53 }
54
TEST_F(ValidateInterfacesTest,EntryPointMissingOutput)55 TEST_F(ValidateInterfacesTest, EntryPointMissingOutput) {
56 std::string text = R"(
57 OpCapability Shader
58 OpMemoryModel Logical GLSL450
59 OpEntryPoint Fragment %1 "func"
60 OpExecutionMode %1 OriginUpperLeft
61 %2 = OpTypeVoid
62 %3 = OpTypeInt 32 0
63 %4 = OpTypePointer Output %3
64 %5 = OpVariable %4 Output
65 %6 = OpTypeFunction %2
66 %1 = OpFunction %2 None %6
67 %7 = OpLabel
68 %8 = OpLoad %3 %5
69 OpReturn
70 OpFunctionEnd
71 )";
72
73 CompileSuccessfully(text);
74 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
75 EXPECT_THAT(
76 getDiagnosticString(),
77 HasSubstr("Output variable id <5> is used by entry point 'func' id <1>, "
78 "but is not listed as an interface"));
79 }
80
TEST_F(ValidateInterfacesTest,InterfaceMissingUseInSubfunction)81 TEST_F(ValidateInterfacesTest, InterfaceMissingUseInSubfunction) {
82 std::string text = R"(
83 OpCapability Shader
84 OpMemoryModel Logical GLSL450
85 OpEntryPoint Fragment %1 "func"
86 OpExecutionMode %1 OriginUpperLeft
87 %2 = OpTypeVoid
88 %3 = OpTypeInt 32 0
89 %4 = OpTypePointer Input %3
90 %5 = OpVariable %4 Input
91 %6 = OpTypeFunction %2
92 %1 = OpFunction %2 None %6
93 %7 = OpLabel
94 %8 = OpFunctionCall %2 %9
95 OpReturn
96 OpFunctionEnd
97 %9 = OpFunction %2 None %6
98 %10 = OpLabel
99 %11 = OpLoad %3 %5
100 OpReturn
101 OpFunctionEnd
102 )";
103
104 CompileSuccessfully(text);
105 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
106 EXPECT_THAT(
107 getDiagnosticString(),
108 HasSubstr("Input variable id <5> is used by entry point 'func' id <1>, "
109 "but is not listed as an interface"));
110 }
111
TEST_F(ValidateInterfacesTest,TwoEntryPointsOneFunction)112 TEST_F(ValidateInterfacesTest, TwoEntryPointsOneFunction) {
113 std::string text = R"(
114 OpCapability Shader
115 OpMemoryModel Logical GLSL450
116 OpEntryPoint Fragment %1 "func" %2
117 OpEntryPoint Fragment %1 "func2"
118 OpExecutionMode %1 OriginUpperLeft
119 %3 = OpTypeVoid
120 %4 = OpTypeInt 32 0
121 %5 = OpTypePointer Input %4
122 %2 = OpVariable %5 Input
123 %6 = OpTypeFunction %3
124 %1 = OpFunction %3 None %6
125 %7 = OpLabel
126 %8 = OpLoad %4 %2
127 OpReturn
128 OpFunctionEnd
129 )";
130
131 CompileSuccessfully(text);
132 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
133 EXPECT_THAT(
134 getDiagnosticString(),
135 HasSubstr("Input variable id <2> is used by entry point 'func2' id <1>, "
136 "but is not listed as an interface"));
137 }
138
TEST_F(ValidateInterfacesTest,MissingInterfaceThroughInitializer)139 TEST_F(ValidateInterfacesTest, MissingInterfaceThroughInitializer) {
140 const std::string text = R"(
141 OpCapability Shader
142 OpCapability VariablePointers
143 OpMemoryModel Logical GLSL450
144 OpEntryPoint Fragment %1 "func"
145 OpExecutionMode %1 OriginUpperLeft
146 %2 = OpTypeVoid
147 %3 = OpTypeInt 32 0
148 %4 = OpTypePointer Input %3
149 %5 = OpTypePointer Function %4
150 %6 = OpVariable %4 Input
151 %7 = OpTypeFunction %2
152 %1 = OpFunction %2 None %7
153 %8 = OpLabel
154 %9 = OpVariable %5 Function %6
155 OpReturn
156 OpFunctionEnd
157 )";
158
159 CompileSuccessfully(text, SPV_ENV_UNIVERSAL_1_3);
160 ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions(SPV_ENV_UNIVERSAL_1_3));
161 EXPECT_THAT(
162 getDiagnosticString(),
163 HasSubstr("Input variable id <6> is used by entry point 'func' id <1>, "
164 "but is not listed as an interface"));
165 }
166
167 } // namespace
168 } // namespace val
169 } // namespace spvtools
170