1 // Copyright 2020 The Tint Authors.
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 "src/ast/workgroup_decoration.h"
16 #include "src/reader/wgsl/parser_impl_test_helper.h"
17
18 namespace tint {
19 namespace reader {
20 namespace wgsl {
21 namespace {
22
TEST_F(ParserImplTest,FunctionDecl)23 TEST_F(ParserImplTest, FunctionDecl) {
24 auto p = parser("fn main(a : i32, b : f32) { return; }");
25 auto decos = p->decoration_list();
26 EXPECT_FALSE(p->has_error()) << p->error();
27 ASSERT_FALSE(decos.errored);
28 EXPECT_FALSE(decos.matched);
29 auto f = p->function_decl(decos.value);
30 EXPECT_FALSE(p->has_error()) << p->error();
31 EXPECT_FALSE(f.errored);
32 EXPECT_TRUE(f.matched);
33 ASSERT_NE(f.value, nullptr);
34
35 EXPECT_EQ(f->symbol, p->builder().Symbols().Get("main"));
36 ASSERT_NE(f->return_type, nullptr);
37 EXPECT_TRUE(f->return_type->Is<ast::Void>());
38
39 ASSERT_EQ(f->params.size(), 2u);
40 EXPECT_EQ(f->params[0]->symbol, p->builder().Symbols().Get("a"));
41 EXPECT_EQ(f->params[1]->symbol, p->builder().Symbols().Get("b"));
42
43 ASSERT_NE(f->return_type, nullptr);
44 EXPECT_TRUE(f->return_type->Is<ast::Void>());
45
46 auto* body = f->body;
47 ASSERT_EQ(body->statements.size(), 1u);
48 EXPECT_TRUE(body->statements[0]->Is<ast::ReturnStatement>());
49 }
50
TEST_F(ParserImplTest,FunctionDecl_DecorationList)51 TEST_F(ParserImplTest, FunctionDecl_DecorationList) {
52 auto p = parser("[[workgroup_size(2, 3, 4)]] fn main() { return; }");
53 auto decos = p->decoration_list();
54 EXPECT_FALSE(p->has_error()) << p->error();
55 ASSERT_FALSE(decos.errored);
56 ASSERT_TRUE(decos.matched);
57 auto f = p->function_decl(decos.value);
58 EXPECT_FALSE(p->has_error()) << p->error();
59 EXPECT_FALSE(f.errored);
60 EXPECT_TRUE(f.matched);
61 ASSERT_NE(f.value, nullptr);
62
63 EXPECT_EQ(f->symbol, p->builder().Symbols().Get("main"));
64 ASSERT_NE(f->return_type, nullptr);
65 EXPECT_TRUE(f->return_type->Is<ast::Void>());
66 ASSERT_EQ(f->params.size(), 0u);
67
68 auto& decorations = f->decorations;
69 ASSERT_EQ(decorations.size(), 1u);
70 ASSERT_TRUE(decorations[0]->Is<ast::WorkgroupDecoration>());
71
72 auto values = decorations[0]->As<ast::WorkgroupDecoration>()->Values();
73
74 ASSERT_TRUE(values[0]->Is<ast::IntLiteralExpression>());
75 EXPECT_EQ(values[0]->As<ast::IntLiteralExpression>()->ValueAsU32(), 2u);
76
77 ASSERT_TRUE(values[1]->Is<ast::IntLiteralExpression>());
78 EXPECT_EQ(values[1]->As<ast::IntLiteralExpression>()->ValueAsU32(), 3u);
79
80 ASSERT_TRUE(values[2]->Is<ast::IntLiteralExpression>());
81 EXPECT_EQ(values[2]->As<ast::IntLiteralExpression>()->ValueAsU32(), 4u);
82
83 auto* body = f->body;
84 ASSERT_EQ(body->statements.size(), 1u);
85 EXPECT_TRUE(body->statements[0]->Is<ast::ReturnStatement>());
86 }
87
TEST_F(ParserImplTest,FunctionDecl_DecorationList_MultipleEntries)88 TEST_F(ParserImplTest, FunctionDecl_DecorationList_MultipleEntries) {
89 auto p = parser(R"(
90 [[workgroup_size(2, 3, 4), stage(compute)]]
91 fn main() { return; })");
92 auto decos = p->decoration_list();
93 EXPECT_FALSE(p->has_error()) << p->error();
94 ASSERT_FALSE(decos.errored);
95 ASSERT_TRUE(decos.matched);
96 auto f = p->function_decl(decos.value);
97 EXPECT_FALSE(p->has_error()) << p->error();
98 EXPECT_FALSE(f.errored);
99 EXPECT_TRUE(f.matched);
100 ASSERT_NE(f.value, nullptr);
101
102 EXPECT_EQ(f->symbol, p->builder().Symbols().Get("main"));
103 ASSERT_NE(f->return_type, nullptr);
104 EXPECT_TRUE(f->return_type->Is<ast::Void>());
105 ASSERT_EQ(f->params.size(), 0u);
106
107 auto& decorations = f->decorations;
108 ASSERT_EQ(decorations.size(), 2u);
109
110 ASSERT_TRUE(decorations[0]->Is<ast::WorkgroupDecoration>());
111 auto values = decorations[0]->As<ast::WorkgroupDecoration>()->Values();
112
113 ASSERT_TRUE(values[0]->Is<ast::IntLiteralExpression>());
114 EXPECT_EQ(values[0]->As<ast::IntLiteralExpression>()->ValueAsU32(), 2u);
115
116 ASSERT_TRUE(values[1]->Is<ast::IntLiteralExpression>());
117 EXPECT_EQ(values[1]->As<ast::IntLiteralExpression>()->ValueAsU32(), 3u);
118
119 ASSERT_TRUE(values[2]->Is<ast::IntLiteralExpression>());
120 EXPECT_EQ(values[2]->As<ast::IntLiteralExpression>()->ValueAsU32(), 4u);
121
122 ASSERT_TRUE(decorations[1]->Is<ast::StageDecoration>());
123 EXPECT_EQ(decorations[1]->As<ast::StageDecoration>()->stage,
124 ast::PipelineStage::kCompute);
125
126 auto* body = f->body;
127 ASSERT_EQ(body->statements.size(), 1u);
128 EXPECT_TRUE(body->statements[0]->Is<ast::ReturnStatement>());
129 }
130
TEST_F(ParserImplTest,FunctionDecl_DecorationList_MultipleLists)131 TEST_F(ParserImplTest, FunctionDecl_DecorationList_MultipleLists) {
132 auto p = parser(R"(
133 [[workgroup_size(2, 3, 4)]]
134 [[stage(compute)]]
135 fn main() { return; })");
136 auto decorations = p->decoration_list();
137 EXPECT_FALSE(p->has_error()) << p->error();
138 ASSERT_FALSE(decorations.errored);
139 ASSERT_TRUE(decorations.matched);
140 auto f = p->function_decl(decorations.value);
141 EXPECT_FALSE(p->has_error()) << p->error();
142 EXPECT_FALSE(f.errored);
143 EXPECT_TRUE(f.matched);
144 ASSERT_NE(f.value, nullptr);
145
146 EXPECT_EQ(f->symbol, p->builder().Symbols().Get("main"));
147 ASSERT_NE(f->return_type, nullptr);
148 EXPECT_TRUE(f->return_type->Is<ast::Void>());
149 ASSERT_EQ(f->params.size(), 0u);
150
151 auto& decos = f->decorations;
152 ASSERT_EQ(decos.size(), 2u);
153
154 ASSERT_TRUE(decos[0]->Is<ast::WorkgroupDecoration>());
155 auto values = decos[0]->As<ast::WorkgroupDecoration>()->Values();
156
157 ASSERT_TRUE(values[0]->Is<ast::IntLiteralExpression>());
158 EXPECT_EQ(values[0]->As<ast::IntLiteralExpression>()->ValueAsU32(), 2u);
159
160 ASSERT_TRUE(values[1]->Is<ast::IntLiteralExpression>());
161 EXPECT_EQ(values[1]->As<ast::IntLiteralExpression>()->ValueAsU32(), 3u);
162
163 ASSERT_TRUE(values[2]->Is<ast::IntLiteralExpression>());
164 EXPECT_EQ(values[2]->As<ast::IntLiteralExpression>()->ValueAsU32(), 4u);
165
166 ASSERT_TRUE(decos[1]->Is<ast::StageDecoration>());
167 EXPECT_EQ(decos[1]->As<ast::StageDecoration>()->stage,
168 ast::PipelineStage::kCompute);
169
170 auto* body = f->body;
171 ASSERT_EQ(body->statements.size(), 1u);
172 EXPECT_TRUE(body->statements[0]->Is<ast::ReturnStatement>());
173 }
174
TEST_F(ParserImplTest,FunctionDecl_ReturnTypeDecorationList)175 TEST_F(ParserImplTest, FunctionDecl_ReturnTypeDecorationList) {
176 auto p = parser("fn main() -> [[location(1)]] f32 { return 1.0; }");
177 auto decos = p->decoration_list();
178 EXPECT_FALSE(p->has_error()) << p->error();
179 ASSERT_FALSE(decos.errored);
180 EXPECT_FALSE(decos.matched);
181 auto f = p->function_decl(decos.value);
182 EXPECT_FALSE(p->has_error()) << p->error();
183 EXPECT_FALSE(f.errored);
184 EXPECT_TRUE(f.matched);
185 ASSERT_NE(f.value, nullptr);
186
187 EXPECT_EQ(f->symbol, p->builder().Symbols().Get("main"));
188 ASSERT_NE(f->return_type, nullptr);
189 EXPECT_TRUE(f->return_type->Is<ast::F32>());
190 ASSERT_EQ(f->params.size(), 0u);
191
192 auto& decorations = f->decorations;
193 EXPECT_EQ(decorations.size(), 0u);
194
195 auto& ret_type_decorations = f->return_type_decorations;
196 ASSERT_EQ(ret_type_decorations.size(), 1u);
197 auto* loc = ret_type_decorations[0]->As<ast::LocationDecoration>();
198 ASSERT_TRUE(loc != nullptr);
199 EXPECT_EQ(loc->value, 1u);
200
201 auto* body = f->body;
202 ASSERT_EQ(body->statements.size(), 1u);
203 EXPECT_TRUE(body->statements[0]->Is<ast::ReturnStatement>());
204 }
205
TEST_F(ParserImplTest,FunctionDecl_InvalidHeader)206 TEST_F(ParserImplTest, FunctionDecl_InvalidHeader) {
207 auto p = parser("fn main() -> { }");
208 auto decos = p->decoration_list();
209 EXPECT_FALSE(p->has_error()) << p->error();
210 ASSERT_FALSE(decos.errored);
211 EXPECT_FALSE(decos.matched);
212 auto f = p->function_decl(decos.value);
213 EXPECT_TRUE(f.errored);
214 EXPECT_FALSE(f.matched);
215 EXPECT_TRUE(p->has_error());
216 EXPECT_EQ(f.value, nullptr);
217 EXPECT_EQ(p->error(), "1:14: unable to determine function return type");
218 }
219
TEST_F(ParserImplTest,FunctionDecl_InvalidBody)220 TEST_F(ParserImplTest, FunctionDecl_InvalidBody) {
221 auto p = parser("fn main() { return }");
222 auto decos = p->decoration_list();
223 EXPECT_FALSE(p->has_error()) << p->error();
224 ASSERT_FALSE(decos.errored);
225 EXPECT_FALSE(decos.matched);
226 auto f = p->function_decl(decos.value);
227 EXPECT_TRUE(f.errored);
228 EXPECT_FALSE(f.matched);
229 EXPECT_TRUE(p->has_error());
230 EXPECT_EQ(f.value, nullptr);
231 EXPECT_EQ(p->error(), "1:20: expected ';' for return statement");
232 }
233
TEST_F(ParserImplTest,FunctionDecl_MissingLeftBrace)234 TEST_F(ParserImplTest, FunctionDecl_MissingLeftBrace) {
235 auto p = parser("fn main() return; }");
236 auto decos = p->decoration_list();
237 EXPECT_FALSE(p->has_error()) << p->error();
238 ASSERT_FALSE(decos.errored);
239 EXPECT_FALSE(decos.matched);
240 auto f = p->function_decl(decos.value);
241 EXPECT_TRUE(f.errored);
242 EXPECT_FALSE(f.matched);
243 EXPECT_TRUE(p->has_error());
244 EXPECT_EQ(f.value, nullptr);
245 EXPECT_EQ(p->error(), "1:11: expected '{'");
246 }
247
248 } // namespace
249 } // namespace wgsl
250 } // namespace reader
251 } // namespace tint
252