• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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