blob: ffd7bb9b6c3c3175e95750ae7daba72ec9430c22 [file] [log] [blame]
dan sinclairb7edc4c2020-04-07 12:46:30 +00001// 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
Ben Clayton5f0ea112021-03-09 10:54:37 +000015#include "src/resolver/resolver.h"
dan sinclairb7edc4c2020-04-07 12:46:30 +000016
Antonio Maioranobe0fc4e2021-03-16 13:26:03 +000017#include <tuple>
18
Ben Clayton47c4d182021-02-10 21:42:35 +000019#include "gmock/gmock.h"
Ben Clayton6fcefe42021-04-19 19:16:12 +000020#include "gtest/gtest-spi.h"
dan sinclair6c498fc2020-04-07 12:47:23 +000021#include "src/ast/assignment_statement.h"
dan sinclaira7d498e2020-09-22 22:07:13 +000022#include "src/ast/bitcast_expression.h"
Ben Clayton9430cb42021-03-09 15:06:37 +000023#include "src/ast/break_statement.h"
dan sinclair50080b72020-07-21 13:42:13 +000024#include "src/ast/call_statement.h"
dan sinclairaec965e2020-04-07 12:54:29 +000025#include "src/ast/continue_statement.h"
dan sinclair91c44a52020-04-07 12:55:25 +000026#include "src/ast/if_statement.h"
Ben Clayton3ea3c992020-11-18 21:19:22 +000027#include "src/ast/intrinsic_texture_helper_test.h"
dan sinclairbc71eda2020-04-07 12:55:51 +000028#include "src/ast/loop_statement.h"
dan sinclairbf0fff82020-04-07 12:56:24 +000029#include "src/ast/return_statement.h"
dan sinclair05926432020-09-21 17:51:31 +000030#include "src/ast/stage_decoration.h"
Ben Clayton85bfea62021-04-19 20:20:33 +000031#include "src/ast/struct_block_decoration.h"
dan sinclair18b32852020-04-07 12:56:45 +000032#include "src/ast/switch_statement.h"
dan sinclair327ed1b2020-04-07 19:27:21 +000033#include "src/ast/unary_op_expression.h"
dan sinclairca893e32020-04-07 12:57:12 +000034#include "src/ast/variable_decl_statement.h"
Ben Clayton786cea42021-03-09 15:10:27 +000035#include "src/resolver/resolver_test_helper.h"
Antonio Maiorano5cd71b82021-04-16 19:07:51 +000036#include "src/sem/call.h"
37#include "src/sem/function.h"
38#include "src/sem/member_accessor_expression.h"
39#include "src/sem/statement.h"
40#include "src/sem/variable.h"
Ben Claytonfaca02d2021-02-10 21:34:25 +000041#include "src/type/access_control_type.h"
Ben Clayton207b5e22021-01-21 15:42:10 +000042#include "src/type/sampled_texture_type.h"
dan sinclairb7edc4c2020-04-07 12:46:30 +000043
Ben Clayton6d612ad2021-02-24 14:15:02 +000044using ::testing::ElementsAre;
Ben Clayton47c4d182021-02-10 21:42:35 +000045using ::testing::HasSubstr;
46
dan sinclairb7edc4c2020-04-07 12:46:30 +000047namespace tint {
Ben Claytonc7dcbae2021-03-09 15:08:48 +000048namespace resolver {
dan sinclairb7edc4c2020-04-07 12:46:30 +000049namespace {
50
Ben Clayton1222c152021-03-16 21:58:23 +000051// Helpers and typedefs
52using i32 = ProgramBuilder::i32;
53using u32 = ProgramBuilder::u32;
54using f32 = ProgramBuilder::f32;
55using Op = ast::BinaryOp;
56
Ben Clayton5f0ea112021-03-09 10:54:37 +000057TEST_F(ResolverTest, Stmt_Assign) {
Ben Clayton6b2fc052021-03-18 21:14:44 +000058 auto* v = Var("v", ty.f32(), ast::StorageClass::kFunction);
59 auto* lhs = Expr("v");
Ben Clayton7eaf4b52020-12-14 22:08:27 +000060 auto* rhs = Expr(2.3f);
dan sinclair6c498fc2020-04-07 12:47:23 +000061
Ben Clayton7eaf4b52020-12-14 22:08:27 +000062 auto* assign = create<ast::AssignmentStatement>(lhs, rhs);
Ben Clayton6b2fc052021-03-18 21:14:44 +000063 WrapInFunction(v, assign);
dan sinclair6c498fc2020-04-07 12:47:23 +000064
Ben Clayton5f0ea112021-03-09 10:54:37 +000065 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton401b96b2021-02-03 17:19:59 +000066
Ben Clayton33352542021-01-29 16:43:41 +000067 ASSERT_NE(TypeOf(lhs), nullptr);
68 ASSERT_NE(TypeOf(rhs), nullptr);
dan sinclair6c498fc2020-04-07 12:47:23 +000069
Ben Clayton6b2fc052021-03-18 21:14:44 +000070 EXPECT_TRUE(TypeOf(lhs)->UnwrapAll()->Is<type::F32>());
Ben Clayton33352542021-01-29 16:43:41 +000071 EXPECT_TRUE(TypeOf(rhs)->Is<type::F32>());
Ben Claytonf97b9c92021-02-16 18:45:45 +000072 EXPECT_EQ(StmtOf(lhs), assign);
73 EXPECT_EQ(StmtOf(rhs), assign);
dan sinclair6c498fc2020-04-07 12:47:23 +000074}
75
Ben Clayton5f0ea112021-03-09 10:54:37 +000076TEST_F(ResolverTest, Stmt_Case) {
Ben Clayton6b2fc052021-03-18 21:14:44 +000077 auto* v = Var("v", ty.f32(), ast::StorageClass::kFunction);
78 auto* lhs = Expr("v");
Ben Clayton7eaf4b52020-12-14 22:08:27 +000079 auto* rhs = Expr(2.3f);
dan sinclair6010b292020-04-07 12:54:20 +000080
Ben Claytonf97b9c92021-02-16 18:45:45 +000081 auto* assign = create<ast::AssignmentStatement>(lhs, rhs);
Ben Claytondba65b72021-03-31 20:35:46 +000082 auto* block = Block(assign);
dan sinclair1aadbd42020-06-01 16:56:46 +000083 ast::CaseSelectorList lit;
Ben Clayton8d391f72021-01-26 16:57:10 +000084 lit.push_back(create<ast::SintLiteral>(ty.i32(), 3));
Ben Claytondba65b72021-03-31 20:35:46 +000085 auto* cse = create<ast::CaseStatement>(lit, block);
Ben Clayton6b2fc052021-03-18 21:14:44 +000086 WrapInFunction(v, cse);
dan sinclair6010b292020-04-07 12:54:20 +000087
Ben Clayton5f0ea112021-03-09 10:54:37 +000088 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton401b96b2021-02-03 17:19:59 +000089
Ben Clayton33352542021-01-29 16:43:41 +000090 ASSERT_NE(TypeOf(lhs), nullptr);
91 ASSERT_NE(TypeOf(rhs), nullptr);
Ben Clayton6b2fc052021-03-18 21:14:44 +000092 EXPECT_TRUE(TypeOf(lhs)->UnwrapAll()->Is<type::F32>());
Ben Clayton33352542021-01-29 16:43:41 +000093 EXPECT_TRUE(TypeOf(rhs)->Is<type::F32>());
Ben Claytonf97b9c92021-02-16 18:45:45 +000094 EXPECT_EQ(StmtOf(lhs), assign);
95 EXPECT_EQ(StmtOf(rhs), assign);
Ben Claytondba65b72021-03-31 20:35:46 +000096 EXPECT_EQ(BlockOf(assign), block);
dan sinclair6010b292020-04-07 12:54:20 +000097}
98
Ben Clayton5f0ea112021-03-09 10:54:37 +000099TEST_F(ResolverTest, Stmt_Block) {
Ben Clayton6b2fc052021-03-18 21:14:44 +0000100 auto* v = Var("v", ty.f32(), ast::StorageClass::kFunction);
101 auto* lhs = Expr("v");
Ben Clayton7eaf4b52020-12-14 22:08:27 +0000102 auto* rhs = Expr(2.3f);
dan sinclair0975dd52020-07-27 15:25:00 +0000103
Ben Claytonf97b9c92021-02-16 18:45:45 +0000104 auto* assign = create<ast::AssignmentStatement>(lhs, rhs);
Ben Clayton6b2fc052021-03-18 21:14:44 +0000105 auto* block = Block(assign);
106 WrapInFunction(v, block);
dan sinclair0975dd52020-07-27 15:25:00 +0000107
Ben Clayton5f0ea112021-03-09 10:54:37 +0000108 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton401b96b2021-02-03 17:19:59 +0000109
Ben Clayton33352542021-01-29 16:43:41 +0000110 ASSERT_NE(TypeOf(lhs), nullptr);
111 ASSERT_NE(TypeOf(rhs), nullptr);
Ben Clayton6b2fc052021-03-18 21:14:44 +0000112 EXPECT_TRUE(TypeOf(lhs)->UnwrapAll()->Is<type::F32>());
Ben Clayton33352542021-01-29 16:43:41 +0000113 EXPECT_TRUE(TypeOf(rhs)->Is<type::F32>());
Ben Claytonf97b9c92021-02-16 18:45:45 +0000114 EXPECT_EQ(StmtOf(lhs), assign);
115 EXPECT_EQ(StmtOf(rhs), assign);
Ben Claytondba65b72021-03-31 20:35:46 +0000116 EXPECT_EQ(BlockOf(lhs), block);
117 EXPECT_EQ(BlockOf(rhs), block);
118 EXPECT_EQ(BlockOf(assign), block);
dan sinclair0cf685f2020-04-07 12:54:37 +0000119}
120
Ben Clayton5f0ea112021-03-09 10:54:37 +0000121TEST_F(ResolverTest, Stmt_If) {
Ben Clayton6b2fc052021-03-18 21:14:44 +0000122 auto* v = Var("v", ty.f32(), ast::StorageClass::kFunction);
123 auto* else_lhs = Expr("v");
Ben Clayton7eaf4b52020-12-14 22:08:27 +0000124 auto* else_rhs = Expr(2.3f);
dan sinclair91c44a52020-04-07 12:55:25 +0000125
Ben Clayton6b2fc052021-03-18 21:14:44 +0000126 auto* else_body = Block(create<ast::AssignmentStatement>(else_lhs, else_rhs));
dan sinclair91c44a52020-04-07 12:55:25 +0000127
Ben Claytonf97b9c92021-02-16 18:45:45 +0000128 auto* else_cond = Expr(3);
129 auto* else_stmt = create<ast::ElseStatement>(else_cond, else_body);
dan sinclair91c44a52020-04-07 12:55:25 +0000130
Ben Clayton6b2fc052021-03-18 21:14:44 +0000131 auto* lhs = Expr("v");
Ben Clayton7eaf4b52020-12-14 22:08:27 +0000132 auto* rhs = Expr(2.3f);
dan sinclair91c44a52020-04-07 12:55:25 +0000133
Ben Claytonf97b9c92021-02-16 18:45:45 +0000134 auto* assign = create<ast::AssignmentStatement>(lhs, rhs);
Ben Clayton6b2fc052021-03-18 21:14:44 +0000135 auto* body = Block(assign);
Ben Clayton5fb87dd2021-03-09 15:17:28 +0000136 auto* cond = Expr(true);
Ben Claytonf97b9c92021-02-16 18:45:45 +0000137 auto* stmt =
138 create<ast::IfStatement>(cond, body, ast::ElseStatementList{else_stmt});
Ben Clayton6b2fc052021-03-18 21:14:44 +0000139 WrapInFunction(v, stmt);
dan sinclair91c44a52020-04-07 12:55:25 +0000140
Ben Clayton5f0ea112021-03-09 10:54:37 +0000141 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton401b96b2021-02-03 17:19:59 +0000142
Ben Clayton33352542021-01-29 16:43:41 +0000143 ASSERT_NE(TypeOf(stmt->condition()), nullptr);
144 ASSERT_NE(TypeOf(else_lhs), nullptr);
145 ASSERT_NE(TypeOf(else_rhs), nullptr);
146 ASSERT_NE(TypeOf(lhs), nullptr);
147 ASSERT_NE(TypeOf(rhs), nullptr);
Ben Clayton5fb87dd2021-03-09 15:17:28 +0000148 EXPECT_TRUE(TypeOf(stmt->condition())->Is<type::Bool>());
Ben Clayton6b2fc052021-03-18 21:14:44 +0000149 EXPECT_TRUE(TypeOf(else_lhs)->UnwrapAll()->Is<type::F32>());
Ben Clayton33352542021-01-29 16:43:41 +0000150 EXPECT_TRUE(TypeOf(else_rhs)->Is<type::F32>());
Ben Clayton6b2fc052021-03-18 21:14:44 +0000151 EXPECT_TRUE(TypeOf(lhs)->UnwrapAll()->Is<type::F32>());
Ben Clayton33352542021-01-29 16:43:41 +0000152 EXPECT_TRUE(TypeOf(rhs)->Is<type::F32>());
Ben Claytonf97b9c92021-02-16 18:45:45 +0000153 EXPECT_EQ(StmtOf(lhs), assign);
154 EXPECT_EQ(StmtOf(rhs), assign);
155 EXPECT_EQ(StmtOf(cond), stmt);
156 EXPECT_EQ(StmtOf(else_cond), else_stmt);
Ben Claytondba65b72021-03-31 20:35:46 +0000157 EXPECT_EQ(BlockOf(lhs), body);
158 EXPECT_EQ(BlockOf(rhs), body);
159 EXPECT_EQ(BlockOf(else_lhs), else_body);
160 EXPECT_EQ(BlockOf(else_rhs), else_body);
dan sinclair91c44a52020-04-07 12:55:25 +0000161}
162
Ben Clayton5f0ea112021-03-09 10:54:37 +0000163TEST_F(ResolverTest, Stmt_Loop) {
Ben Clayton6b2fc052021-03-18 21:14:44 +0000164 auto* v = Var("v", ty.f32(), ast::StorageClass::kFunction);
165 auto* body_lhs = Expr("v");
Ben Clayton7eaf4b52020-12-14 22:08:27 +0000166 auto* body_rhs = Expr(2.3f);
dan sinclairbc71eda2020-04-07 12:55:51 +0000167
Ben Clayton6b2fc052021-03-18 21:14:44 +0000168 auto* body = Block(create<ast::AssignmentStatement>(body_lhs, body_rhs));
169 auto* continuing_lhs = Expr("v");
Ben Clayton7eaf4b52020-12-14 22:08:27 +0000170 auto* continuing_rhs = Expr(2.3f);
dan sinclairbc71eda2020-04-07 12:55:51 +0000171
Ben Clayton6b2fc052021-03-18 21:14:44 +0000172 auto* continuing = create<ast::BlockStatement>(ast::StatementList{
173 create<ast::AssignmentStatement>(continuing_lhs, continuing_rhs),
174 });
Ben Clayton7eaf4b52020-12-14 22:08:27 +0000175 auto* stmt = create<ast::LoopStatement>(body, continuing);
Ben Clayton6b2fc052021-03-18 21:14:44 +0000176 WrapInFunction(v, stmt);
Ben Clayton7eaf4b52020-12-14 22:08:27 +0000177
Ben Clayton5f0ea112021-03-09 10:54:37 +0000178 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton401b96b2021-02-03 17:19:59 +0000179
Ben Clayton33352542021-01-29 16:43:41 +0000180 ASSERT_NE(TypeOf(body_lhs), nullptr);
181 ASSERT_NE(TypeOf(body_rhs), nullptr);
182 ASSERT_NE(TypeOf(continuing_lhs), nullptr);
183 ASSERT_NE(TypeOf(continuing_rhs), nullptr);
Ben Clayton6b2fc052021-03-18 21:14:44 +0000184 EXPECT_TRUE(TypeOf(body_lhs)->UnwrapAll()->Is<type::F32>());
Ben Clayton33352542021-01-29 16:43:41 +0000185 EXPECT_TRUE(TypeOf(body_rhs)->Is<type::F32>());
Ben Clayton6b2fc052021-03-18 21:14:44 +0000186 EXPECT_TRUE(TypeOf(continuing_lhs)->UnwrapAll()->Is<type::F32>());
Ben Clayton33352542021-01-29 16:43:41 +0000187 EXPECT_TRUE(TypeOf(continuing_rhs)->Is<type::F32>());
Ben Claytondba65b72021-03-31 20:35:46 +0000188 EXPECT_EQ(BlockOf(body_lhs), body);
189 EXPECT_EQ(BlockOf(body_rhs), body);
190 EXPECT_EQ(BlockOf(continuing_lhs), continuing);
191 EXPECT_EQ(BlockOf(continuing_rhs), continuing);
dan sinclairbc71eda2020-04-07 12:55:51 +0000192}
193
Ben Clayton5f0ea112021-03-09 10:54:37 +0000194TEST_F(ResolverTest, Stmt_Return) {
Ben Clayton7eaf4b52020-12-14 22:08:27 +0000195 auto* cond = Expr(2);
dan sinclairbf0fff82020-04-07 12:56:24 +0000196
Ben Clayton7eaf4b52020-12-14 22:08:27 +0000197 auto* ret = create<ast::ReturnStatement>(cond);
Antonio Maiorano2e974352021-03-22 23:20:17 +0000198 Func("test", {}, ty.i32(), {ret}, {});
dan sinclairbf0fff82020-04-07 12:56:24 +0000199
Ben Clayton5f0ea112021-03-09 10:54:37 +0000200 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton401b96b2021-02-03 17:19:59 +0000201
Ben Clayton33352542021-01-29 16:43:41 +0000202 ASSERT_NE(TypeOf(cond), nullptr);
203 EXPECT_TRUE(TypeOf(cond)->Is<type::I32>());
dan sinclairbf0fff82020-04-07 12:56:24 +0000204}
205
Ben Clayton5f0ea112021-03-09 10:54:37 +0000206TEST_F(ResolverTest, Stmt_Return_WithoutValue) {
Ben Clayton7eaf4b52020-12-14 22:08:27 +0000207 auto* ret = create<ast::ReturnStatement>();
Ben Clayton401b96b2021-02-03 17:19:59 +0000208 WrapInFunction(ret);
209
Ben Clayton5f0ea112021-03-09 10:54:37 +0000210 EXPECT_TRUE(r()->Resolve()) << r()->error();
dan sinclair327ed1b2020-04-07 19:27:21 +0000211}
212
Ben Clayton5f0ea112021-03-09 10:54:37 +0000213TEST_F(ResolverTest, Stmt_Switch) {
Ben Clayton6b2fc052021-03-18 21:14:44 +0000214 auto* v = Var("v", ty.f32(), ast::StorageClass::kFunction);
215 auto* lhs = Expr("v");
Ben Clayton7eaf4b52020-12-14 22:08:27 +0000216 auto* rhs = Expr(2.3f);
Ben Claytondba65b72021-03-31 20:35:46 +0000217 auto* case_block = Block(Assign(lhs, rhs));
218 auto* stmt = Switch(Expr(2), Case(Literal(3), case_block), DefaultCase());
Ben Clayton6b2fc052021-03-18 21:14:44 +0000219 WrapInFunction(v, stmt);
dan sinclair18b32852020-04-07 12:56:45 +0000220
Ben Clayton5f0ea112021-03-09 10:54:37 +0000221 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton401b96b2021-02-03 17:19:59 +0000222
Ben Clayton33352542021-01-29 16:43:41 +0000223 ASSERT_NE(TypeOf(stmt->condition()), nullptr);
224 ASSERT_NE(TypeOf(lhs), nullptr);
225 ASSERT_NE(TypeOf(rhs), nullptr);
dan sinclair18b32852020-04-07 12:56:45 +0000226
Ben Clayton33352542021-01-29 16:43:41 +0000227 EXPECT_TRUE(TypeOf(stmt->condition())->Is<type::I32>());
Ben Clayton6b2fc052021-03-18 21:14:44 +0000228 EXPECT_TRUE(TypeOf(lhs)->UnwrapAll()->Is<type::F32>());
Ben Clayton33352542021-01-29 16:43:41 +0000229 EXPECT_TRUE(TypeOf(rhs)->Is<type::F32>());
Ben Claytondba65b72021-03-31 20:35:46 +0000230 EXPECT_EQ(BlockOf(lhs), case_block);
231 EXPECT_EQ(BlockOf(rhs), case_block);
dan sinclair18b32852020-04-07 12:56:45 +0000232}
233
Ben Clayton5f0ea112021-03-09 10:54:37 +0000234TEST_F(ResolverTest, Stmt_Call) {
dan sinclair50080b72020-07-21 13:42:13 +0000235 ast::VariableList params;
Antonio Maiorano03c01b52021-03-19 14:04:51 +0000236 Func("my_func", params, ty.f32(), ast::StatementList{Return(Expr(0.0f))},
James Price95d40772021-03-11 17:39:32 +0000237 ast::DecorationList{});
dan sinclair50080b72020-07-21 13:42:13 +0000238
Ben Clayton7eaf4b52020-12-14 22:08:27 +0000239 auto* expr = Call("my_func");
dan sinclair50080b72020-07-21 13:42:13 +0000240
Ben Clayton7eaf4b52020-12-14 22:08:27 +0000241 auto* call = create<ast::CallStatement>(expr);
Ben Clayton401b96b2021-02-03 17:19:59 +0000242 WrapInFunction(call);
243
Ben Clayton5f0ea112021-03-09 10:54:37 +0000244 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton401b96b2021-02-03 17:19:59 +0000245
Ben Clayton33352542021-01-29 16:43:41 +0000246 ASSERT_NE(TypeOf(expr), nullptr);
247 EXPECT_TRUE(TypeOf(expr)->Is<type::F32>());
Ben Claytonf97b9c92021-02-16 18:45:45 +0000248 EXPECT_EQ(StmtOf(expr), call);
dan sinclair50080b72020-07-21 13:42:13 +0000249}
250
Ben Clayton5f0ea112021-03-09 10:54:37 +0000251TEST_F(ResolverTest, Stmt_VariableDecl) {
Ben Clayton81a29fe2021-02-17 00:26:52 +0000252 auto* var = Var("my_var", ty.i32(), ast::StorageClass::kNone, Expr(2));
Ben Clayton4bfe4612020-11-16 16:41:47 +0000253 auto* init = var->constructor();
dan sinclairca893e32020-04-07 12:57:12 +0000254
Ben Clayton7eaf4b52020-12-14 22:08:27 +0000255 auto* decl = create<ast::VariableDeclStatement>(var);
Ben Clayton401b96b2021-02-03 17:19:59 +0000256 WrapInFunction(decl);
dan sinclairca893e32020-04-07 12:57:12 +0000257
Ben Clayton5f0ea112021-03-09 10:54:37 +0000258 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton401b96b2021-02-03 17:19:59 +0000259
Ben Clayton33352542021-01-29 16:43:41 +0000260 ASSERT_NE(TypeOf(init), nullptr);
261 EXPECT_TRUE(TypeOf(init)->Is<type::I32>());
dan sinclairca893e32020-04-07 12:57:12 +0000262}
263
Ben Clayton5f0ea112021-03-09 10:54:37 +0000264TEST_F(ResolverTest, Stmt_VariableDecl_Alias) {
Antonio Maiorano6ce2edf2021-02-26 18:25:56 +0000265 auto* my_int = ty.alias("MyInt", ty.i32());
266 auto* var = Var("my_var", my_int, ast::StorageClass::kNone, Expr(2));
267 auto* init = var->constructor();
268
269 auto* decl = create<ast::VariableDeclStatement>(var);
270 WrapInFunction(decl);
271
Ben Clayton5f0ea112021-03-09 10:54:37 +0000272 EXPECT_TRUE(r()->Resolve()) << r()->error();
Antonio Maiorano6ce2edf2021-02-26 18:25:56 +0000273
274 ASSERT_NE(TypeOf(init), nullptr);
275 EXPECT_TRUE(TypeOf(init)->Is<type::I32>());
276}
277
Ben Clayton5f0ea112021-03-09 10:54:37 +0000278TEST_F(ResolverTest, Stmt_VariableDecl_ModuleScope) {
Ben Claytonf97b9c92021-02-16 18:45:45 +0000279 auto* init = Expr(2);
Antonio Maioranobbbb0ed2021-04-06 20:18:57 +0000280 Global("my_var", ty.i32(), ast::StorageClass::kInput, init);
dan sinclair7be237a2020-06-15 20:55:09 +0000281
Ben Clayton5f0ea112021-03-09 10:54:37 +0000282 EXPECT_TRUE(r()->Resolve()) << r()->error();
dan sinclair7be237a2020-06-15 20:55:09 +0000283
Ben Clayton33352542021-01-29 16:43:41 +0000284 ASSERT_NE(TypeOf(init), nullptr);
285 EXPECT_TRUE(TypeOf(init)->Is<type::I32>());
Ben Claytonf97b9c92021-02-16 18:45:45 +0000286 EXPECT_EQ(StmtOf(init), nullptr);
dan sinclair7be237a2020-06-15 20:55:09 +0000287}
288
Ben Clayton5f0ea112021-03-09 10:54:37 +0000289TEST_F(ResolverTest, Stmt_VariableDecl_OuterScopeAfterInnerScope) {
Ben Clayton9328d942021-04-08 14:39:47 +0000290 // fn func_i32() {
James Price77f4f022021-02-04 16:33:20 +0000291 // {
292 // var foo : i32 = 2;
293 // var bar : i32 = foo;
294 // }
295 // var foo : f32 = 2.0;
296 // var bar : f32 = foo;
297 // }
298
299 ast::VariableList params;
300
301 // Declare i32 "foo" inside a block
Ben Clayton81a29fe2021-02-17 00:26:52 +0000302 auto* foo_i32 = Var("foo", ty.i32(), ast::StorageClass::kNone, Expr(2));
James Price77f4f022021-02-04 16:33:20 +0000303 auto* foo_i32_init = foo_i32->constructor();
304 auto* foo_i32_decl = create<ast::VariableDeclStatement>(foo_i32);
305
306 // Reference "foo" inside the block
Ben Clayton81a29fe2021-02-17 00:26:52 +0000307 auto* bar_i32 = Var("bar", ty.i32(), ast::StorageClass::kNone, Expr("foo"));
James Price77f4f022021-02-04 16:33:20 +0000308 auto* bar_i32_init = bar_i32->constructor();
309 auto* bar_i32_decl = create<ast::VariableDeclStatement>(bar_i32);
310
311 auto* inner = create<ast::BlockStatement>(
312 ast::StatementList{foo_i32_decl, bar_i32_decl});
313
314 // Declare f32 "foo" at function scope
Ben Clayton81a29fe2021-02-17 00:26:52 +0000315 auto* foo_f32 = Var("foo", ty.f32(), ast::StorageClass::kNone, Expr(2.f));
James Price77f4f022021-02-04 16:33:20 +0000316 auto* foo_f32_init = foo_f32->constructor();
317 auto* foo_f32_decl = create<ast::VariableDeclStatement>(foo_f32);
318
319 // Reference "foo" at function scope
Ben Clayton81a29fe2021-02-17 00:26:52 +0000320 auto* bar_f32 = Var("bar", ty.f32(), ast::StorageClass::kNone, Expr("foo"));
James Price77f4f022021-02-04 16:33:20 +0000321 auto* bar_f32_init = bar_f32->constructor();
322 auto* bar_f32_decl = create<ast::VariableDeclStatement>(bar_f32);
323
Antonio Maiorano03c01b52021-03-19 14:04:51 +0000324 Func("func", params, ty.void_(),
James Price77f4f022021-02-04 16:33:20 +0000325 ast::StatementList{inner, foo_f32_decl, bar_f32_decl},
James Price95d40772021-03-11 17:39:32 +0000326 ast::DecorationList{});
James Price77f4f022021-02-04 16:33:20 +0000327
Antonio Maiorano03c01b52021-03-19 14:04:51 +0000328 EXPECT_TRUE(r()->Resolve()) << r()->error();
James Price77f4f022021-02-04 16:33:20 +0000329 ASSERT_NE(TypeOf(foo_i32_init), nullptr);
330 EXPECT_TRUE(TypeOf(foo_i32_init)->Is<type::I32>());
331 ASSERT_NE(TypeOf(foo_f32_init), nullptr);
332 EXPECT_TRUE(TypeOf(foo_f32_init)->Is<type::F32>());
333 ASSERT_NE(TypeOf(bar_i32_init), nullptr);
334 EXPECT_TRUE(TypeOf(bar_i32_init)->UnwrapAll()->Is<type::I32>());
335 ASSERT_NE(TypeOf(bar_f32_init), nullptr);
336 EXPECT_TRUE(TypeOf(bar_f32_init)->UnwrapAll()->Is<type::F32>());
Ben Claytonf97b9c92021-02-16 18:45:45 +0000337 EXPECT_EQ(StmtOf(foo_i32_init), foo_i32_decl);
338 EXPECT_EQ(StmtOf(bar_i32_init), bar_i32_decl);
339 EXPECT_EQ(StmtOf(foo_f32_init), foo_f32_decl);
340 EXPECT_EQ(StmtOf(bar_f32_init), bar_f32_decl);
James Pricec9af5972021-02-16 21:15:01 +0000341 EXPECT_TRUE(CheckVarUsers(foo_i32, {bar_i32->constructor()}));
342 EXPECT_TRUE(CheckVarUsers(foo_f32, {bar_f32->constructor()}));
Ben Clayton86c2cbf2021-04-07 08:09:01 +0000343 ASSERT_NE(VarOf(bar_i32->constructor()), nullptr);
344 EXPECT_EQ(VarOf(bar_i32->constructor())->Declaration(), foo_i32);
345 ASSERT_NE(VarOf(bar_f32->constructor()), nullptr);
346 EXPECT_EQ(VarOf(bar_f32->constructor())->Declaration(), foo_f32);
James Price77f4f022021-02-04 16:33:20 +0000347}
348
Ben Clayton5f0ea112021-03-09 10:54:37 +0000349TEST_F(ResolverTest, Stmt_VariableDecl_ModuleScopeAfterFunctionScope) {
Ben Clayton9328d942021-04-08 14:39:47 +0000350 // fn func_i32() {
James Price77f4f022021-02-04 16:33:20 +0000351 // var foo : i32 = 2;
352 // }
353 // var foo : f32 = 2.0;
Ben Clayton9328d942021-04-08 14:39:47 +0000354 // fn func_f32() {
James Price77f4f022021-02-04 16:33:20 +0000355 // var bar : f32 = foo;
356 // }
357
358 ast::VariableList params;
359
360 // Declare i32 "foo" inside a function
Antonio Maioranobbbb0ed2021-04-06 20:18:57 +0000361 auto* fn_i32 = Var("foo", ty.i32(), ast::StorageClass::kFunction, Expr(2));
James Price77f4f022021-02-04 16:33:20 +0000362 auto* fn_i32_init = fn_i32->constructor();
363 auto* fn_i32_decl = create<ast::VariableDeclStatement>(fn_i32);
Antonio Maiorano03c01b52021-03-19 14:04:51 +0000364 Func("func_i32", params, ty.void_(), ast::StatementList{fn_i32_decl},
James Price95d40772021-03-11 17:39:32 +0000365 ast::DecorationList{});
James Price77f4f022021-02-04 16:33:20 +0000366
367 // Declare f32 "foo" at module scope
Antonio Maioranobbbb0ed2021-04-06 20:18:57 +0000368 auto* mod_f32 = Var("foo", ty.f32(), ast::StorageClass::kInput, Expr(2.f));
James Price77f4f022021-02-04 16:33:20 +0000369 auto* mod_init = mod_f32->constructor();
370 AST().AddGlobalVariable(mod_f32);
371
372 // Reference "foo" in another function
Antonio Maioranobbbb0ed2021-04-06 20:18:57 +0000373 auto* fn_f32 =
374 Var("bar", ty.f32(), ast::StorageClass::kFunction, Expr("foo"));
James Price77f4f022021-02-04 16:33:20 +0000375 auto* fn_f32_init = fn_f32->constructor();
376 auto* fn_f32_decl = create<ast::VariableDeclStatement>(fn_f32);
Antonio Maiorano03c01b52021-03-19 14:04:51 +0000377 Func("func_f32", params, ty.void_(), ast::StatementList{fn_f32_decl},
James Price95d40772021-03-11 17:39:32 +0000378 ast::DecorationList{});
James Price77f4f022021-02-04 16:33:20 +0000379
Antonio Maiorano03c01b52021-03-19 14:04:51 +0000380 EXPECT_TRUE(r()->Resolve()) << r()->error();
James Price77f4f022021-02-04 16:33:20 +0000381 ASSERT_NE(TypeOf(mod_init), nullptr);
382 EXPECT_TRUE(TypeOf(mod_init)->Is<type::F32>());
383 ASSERT_NE(TypeOf(fn_i32_init), nullptr);
384 EXPECT_TRUE(TypeOf(fn_i32_init)->Is<type::I32>());
385 ASSERT_NE(TypeOf(fn_f32_init), nullptr);
386 EXPECT_TRUE(TypeOf(fn_f32_init)->UnwrapAll()->Is<type::F32>());
Ben Claytonf97b9c92021-02-16 18:45:45 +0000387 EXPECT_EQ(StmtOf(fn_i32_init), fn_i32_decl);
388 EXPECT_EQ(StmtOf(mod_init), nullptr);
389 EXPECT_EQ(StmtOf(fn_f32_init), fn_f32_decl);
James Pricec9af5972021-02-16 21:15:01 +0000390 EXPECT_TRUE(CheckVarUsers(fn_i32, {}));
391 EXPECT_TRUE(CheckVarUsers(mod_f32, {fn_f32->constructor()}));
Ben Clayton86c2cbf2021-04-07 08:09:01 +0000392 ASSERT_NE(VarOf(fn_f32->constructor()), nullptr);
393 EXPECT_EQ(VarOf(fn_f32->constructor())->Declaration(), mod_f32);
James Price77f4f022021-02-04 16:33:20 +0000394}
395
Ben Clayton5f0ea112021-03-09 10:54:37 +0000396TEST_F(ResolverTest, Expr_ArrayAccessor_Array) {
Ben Clayton7eaf4b52020-12-14 22:08:27 +0000397 auto* idx = Expr(2);
Ben Clayton37571bc2021-02-16 23:57:01 +0000398 Global("my_var", ty.array<f32, 3>(), ast::StorageClass::kFunction);
dan sinclair8eddb782020-04-23 22:26:52 +0000399
dan sinclair8b40a672020-12-16 11:49:10 +0000400 auto* acc = IndexAccessor("my_var", idx);
Ben Clayton401b96b2021-02-03 17:19:59 +0000401 WrapInFunction(acc);
402
Ben Clayton5f0ea112021-03-09 10:54:37 +0000403 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton401b96b2021-02-03 17:19:59 +0000404
Ben Clayton33352542021-01-29 16:43:41 +0000405 ASSERT_NE(TypeOf(acc), nullptr);
406 ASSERT_TRUE(TypeOf(acc)->Is<type::Pointer>());
dan sinclair8eddb782020-04-23 22:26:52 +0000407
Ben Clayton33352542021-01-29 16:43:41 +0000408 auto* ptr = TypeOf(acc)->As<type::Pointer>();
Ben Clayton207b5e22021-01-21 15:42:10 +0000409 EXPECT_TRUE(ptr->type()->Is<type::F32>());
dan sinclair8eddb782020-04-23 22:26:52 +0000410}
411
Ben Clayton5f0ea112021-03-09 10:54:37 +0000412TEST_F(ResolverTest, Expr_ArrayAccessor_Alias_Array) {
Ben Clayton1637cbb2021-01-05 15:44:39 +0000413 auto* aary = ty.alias("myarrty", ty.array<f32, 3>());
David Neto9c88ea52020-06-22 20:33:12 +0000414
Ben Clayton37571bc2021-02-16 23:57:01 +0000415 Global("my_var", aary, ast::StorageClass::kFunction);
David Neto9c88ea52020-06-22 20:33:12 +0000416
dan sinclair8b40a672020-12-16 11:49:10 +0000417 auto* acc = IndexAccessor("my_var", 2);
Ben Clayton401b96b2021-02-03 17:19:59 +0000418 WrapInFunction(acc);
419
Ben Clayton5f0ea112021-03-09 10:54:37 +0000420 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton401b96b2021-02-03 17:19:59 +0000421
Ben Clayton33352542021-01-29 16:43:41 +0000422 ASSERT_NE(TypeOf(acc), nullptr);
423 ASSERT_TRUE(TypeOf(acc)->Is<type::Pointer>());
David Neto9c88ea52020-06-22 20:33:12 +0000424
Ben Clayton33352542021-01-29 16:43:41 +0000425 auto* ptr = TypeOf(acc)->As<type::Pointer>();
Ben Clayton207b5e22021-01-21 15:42:10 +0000426 EXPECT_TRUE(ptr->type()->Is<type::F32>());
David Neto9c88ea52020-06-22 20:33:12 +0000427}
428
Ben Clayton5f0ea112021-03-09 10:54:37 +0000429TEST_F(ResolverTest, Expr_ArrayAccessor_Array_Constant) {
Ben Clayton81a29fe2021-02-17 00:26:52 +0000430 GlobalConst("my_var", ty.array<f32, 3>());
dan sinclair973bd6a2020-04-07 12:57:42 +0000431
dan sinclair8b40a672020-12-16 11:49:10 +0000432 auto* acc = IndexAccessor("my_var", 2);
Ben Clayton401b96b2021-02-03 17:19:59 +0000433 WrapInFunction(acc);
434
Ben Clayton5f0ea112021-03-09 10:54:37 +0000435 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton401b96b2021-02-03 17:19:59 +0000436
Ben Clayton33352542021-01-29 16:43:41 +0000437 ASSERT_NE(TypeOf(acc), nullptr);
438 EXPECT_TRUE(TypeOf(acc)->Is<type::F32>()) << TypeOf(acc)->type_name();
dan sinclair973bd6a2020-04-07 12:57:42 +0000439}
440
Ben Clayton5f0ea112021-03-09 10:54:37 +0000441TEST_F(ResolverTest, Expr_ArrayAccessor_Matrix) {
Antonio Maioranobbbb0ed2021-04-06 20:18:57 +0000442 Global("my_var", ty.mat2x3<f32>(), ast::StorageClass::kInput);
dan sinclair973bd6a2020-04-07 12:57:42 +0000443
dan sinclair8b40a672020-12-16 11:49:10 +0000444 auto* acc = IndexAccessor("my_var", 2);
Ben Clayton401b96b2021-02-03 17:19:59 +0000445 WrapInFunction(acc);
446
Ben Clayton5f0ea112021-03-09 10:54:37 +0000447 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton401b96b2021-02-03 17:19:59 +0000448
Ben Clayton33352542021-01-29 16:43:41 +0000449 ASSERT_NE(TypeOf(acc), nullptr);
450 ASSERT_TRUE(TypeOf(acc)->Is<type::Pointer>());
dan sinclair8eddb782020-04-23 22:26:52 +0000451
Ben Clayton33352542021-01-29 16:43:41 +0000452 auto* ptr = TypeOf(acc)->As<type::Pointer>();
Ben Clayton207b5e22021-01-21 15:42:10 +0000453 ASSERT_TRUE(ptr->type()->Is<type::Vector>());
454 EXPECT_EQ(ptr->type()->As<type::Vector>()->size(), 3u);
dan sinclair973bd6a2020-04-07 12:57:42 +0000455}
456
Ben Clayton5f0ea112021-03-09 10:54:37 +0000457TEST_F(ResolverTest, Expr_ArrayAccessor_Matrix_BothDimensions) {
Antonio Maioranobbbb0ed2021-04-06 20:18:57 +0000458 Global("my_var", ty.mat2x3<f32>(), ast::StorageClass::kInput);
dan sinclair973bd6a2020-04-07 12:57:42 +0000459
dan sinclair8b40a672020-12-16 11:49:10 +0000460 auto* acc = IndexAccessor(IndexAccessor("my_var", 2), 1);
Ben Clayton401b96b2021-02-03 17:19:59 +0000461 WrapInFunction(acc);
dan sinclair973bd6a2020-04-07 12:57:42 +0000462
Ben Clayton5f0ea112021-03-09 10:54:37 +0000463 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton401b96b2021-02-03 17:19:59 +0000464
Ben Clayton33352542021-01-29 16:43:41 +0000465 ASSERT_NE(TypeOf(acc), nullptr);
466 ASSERT_TRUE(TypeOf(acc)->Is<type::Pointer>());
dan sinclair8eddb782020-04-23 22:26:52 +0000467
Ben Clayton33352542021-01-29 16:43:41 +0000468 auto* ptr = TypeOf(acc)->As<type::Pointer>();
Ben Clayton207b5e22021-01-21 15:42:10 +0000469 EXPECT_TRUE(ptr->type()->Is<type::F32>());
dan sinclair973bd6a2020-04-07 12:57:42 +0000470}
471
Ben Clayton5f0ea112021-03-09 10:54:37 +0000472TEST_F(ResolverTest, Expr_ArrayAccessor_Vector) {
Antonio Maioranobbbb0ed2021-04-06 20:18:57 +0000473 Global("my_var", ty.vec3<f32>(), ast::StorageClass::kInput);
dan sinclair973bd6a2020-04-07 12:57:42 +0000474
dan sinclair8b40a672020-12-16 11:49:10 +0000475 auto* acc = IndexAccessor("my_var", 2);
Ben Clayton401b96b2021-02-03 17:19:59 +0000476 WrapInFunction(acc);
477
Ben Clayton5f0ea112021-03-09 10:54:37 +0000478 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton401b96b2021-02-03 17:19:59 +0000479
Ben Clayton33352542021-01-29 16:43:41 +0000480 ASSERT_NE(TypeOf(acc), nullptr);
481 ASSERT_TRUE(TypeOf(acc)->Is<type::Pointer>());
dan sinclair8eddb782020-04-23 22:26:52 +0000482
Ben Clayton33352542021-01-29 16:43:41 +0000483 auto* ptr = TypeOf(acc)->As<type::Pointer>();
Ben Clayton207b5e22021-01-21 15:42:10 +0000484 EXPECT_TRUE(ptr->type()->Is<type::F32>());
dan sinclair973bd6a2020-04-07 12:57:42 +0000485}
486
Ben Clayton5f0ea112021-03-09 10:54:37 +0000487TEST_F(ResolverTest, Expr_Bitcast) {
Antonio Maioranobb5617f2021-03-19 18:45:30 +0000488 Global("name", ty.f32(), ast::StorageClass::kPrivate);
489
Ben Clayton8d391f72021-01-26 16:57:10 +0000490 auto* bitcast = create<ast::BitcastExpression>(ty.f32(), Expr("name"));
Ben Clayton401b96b2021-02-03 17:19:59 +0000491 WrapInFunction(bitcast);
dan sinclaira01777c2020-04-07 12:57:52 +0000492
Ben Clayton5f0ea112021-03-09 10:54:37 +0000493 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton401b96b2021-02-03 17:19:59 +0000494
Ben Clayton33352542021-01-29 16:43:41 +0000495 ASSERT_NE(TypeOf(bitcast), nullptr);
496 EXPECT_TRUE(TypeOf(bitcast)->Is<type::F32>());
dan sinclaira01777c2020-04-07 12:57:52 +0000497}
498
Ben Clayton5f0ea112021-03-09 10:54:37 +0000499TEST_F(ResolverTest, Expr_Call) {
dan sinclair3ca87462020-04-07 16:41:10 +0000500 ast::VariableList params;
Antonio Maiorano03c01b52021-03-19 14:04:51 +0000501 Func("my_func", params, ty.f32(), ast::StatementList{Return(Expr(0.0f))},
James Price95d40772021-03-11 17:39:32 +0000502 ast::DecorationList{});
dan sinclair3ca87462020-04-07 16:41:10 +0000503
Ben Clayton7eaf4b52020-12-14 22:08:27 +0000504 auto* call = Call("my_func");
Ben Clayton401b96b2021-02-03 17:19:59 +0000505 WrapInFunction(call);
506
Ben Clayton5f0ea112021-03-09 10:54:37 +0000507 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton401b96b2021-02-03 17:19:59 +0000508
Ben Clayton33352542021-01-29 16:43:41 +0000509 ASSERT_NE(TypeOf(call), nullptr);
510 EXPECT_TRUE(TypeOf(call)->Is<type::F32>());
dan sinclair3ca87462020-04-07 16:41:10 +0000511}
512
Ben Clayton5f0ea112021-03-09 10:54:37 +0000513TEST_F(ResolverTest, Expr_Call_InBinaryOp) {
Ben Clayton7b7d6982021-02-09 17:38:05 +0000514 ast::VariableList params;
Antonio Maiorano03c01b52021-03-19 14:04:51 +0000515 Func("func", params, ty.f32(), ast::StatementList{Return(Expr(0.0f))},
516 ast::DecorationList{});
Ben Clayton7b7d6982021-02-09 17:38:05 +0000517
518 auto* expr = Add(Call("func"), Call("func"));
519 WrapInFunction(expr);
520
Ben Clayton5f0ea112021-03-09 10:54:37 +0000521 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton7b7d6982021-02-09 17:38:05 +0000522
523 ASSERT_NE(TypeOf(expr), nullptr);
524 EXPECT_TRUE(TypeOf(expr)->Is<type::F32>());
525}
526
Ben Clayton5f0ea112021-03-09 10:54:37 +0000527TEST_F(ResolverTest, Expr_Call_WithParams) {
dan sinclairccb52dc2020-04-20 14:18:54 +0000528 ast::VariableList params;
Antonio Maiorano03c01b52021-03-19 14:04:51 +0000529 Func("my_func", params, ty.void_(), ast::StatementList{},
James Price95d40772021-03-11 17:39:32 +0000530 ast::DecorationList{});
dan sinclairccb52dc2020-04-20 14:18:54 +0000531
Ben Clayton7eaf4b52020-12-14 22:08:27 +0000532 auto* param = Expr(2.4f);
dan sinclairccb52dc2020-04-20 14:18:54 +0000533
Ben Clayton7eaf4b52020-12-14 22:08:27 +0000534 auto* call = Call("my_func", param);
Ben Clayton401b96b2021-02-03 17:19:59 +0000535 WrapInFunction(call);
536
Ben Clayton5f0ea112021-03-09 10:54:37 +0000537 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton401b96b2021-02-03 17:19:59 +0000538
Ben Clayton33352542021-01-29 16:43:41 +0000539 ASSERT_NE(TypeOf(param), nullptr);
540 EXPECT_TRUE(TypeOf(param)->Is<type::F32>());
dan sinclairccb52dc2020-04-20 14:18:54 +0000541}
542
Ben Clayton5f0ea112021-03-09 10:54:37 +0000543TEST_F(ResolverTest, Expr_Call_Intrinsic) {
Ben Clayton7eaf4b52020-12-14 22:08:27 +0000544 auto* call = Call("round", 2.4f);
Ben Clayton401b96b2021-02-03 17:19:59 +0000545 WrapInFunction(call);
dan sinclairfd5d4ca2020-04-20 15:46:18 +0000546
Ben Clayton5f0ea112021-03-09 10:54:37 +0000547 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton401b96b2021-02-03 17:19:59 +0000548
Ben Clayton33352542021-01-29 16:43:41 +0000549 ASSERT_NE(TypeOf(call), nullptr);
550 EXPECT_TRUE(TypeOf(call)->Is<type::F32>());
dan sinclairfd5d4ca2020-04-20 15:46:18 +0000551}
552
Ben Clayton5f0ea112021-03-09 10:54:37 +0000553TEST_F(ResolverTest, Expr_Cast) {
Ben Clayton37571bc2021-02-16 23:57:01 +0000554 Global("name", ty.f32(), ast::StorageClass::kPrivate);
Ben Clayton401b96b2021-02-03 17:19:59 +0000555
Ben Clayton8d391f72021-01-26 16:57:10 +0000556 auto* cast = Construct(ty.f32(), "name");
Ben Clayton401b96b2021-02-03 17:19:59 +0000557 WrapInFunction(cast);
dan sinclair3c025922020-09-24 14:38:44 +0000558
Ben Clayton5f0ea112021-03-09 10:54:37 +0000559 EXPECT_TRUE(r()->Resolve()) << r()->error();
dan sinclair4e807952020-04-07 16:41:23 +0000560
Ben Clayton33352542021-01-29 16:43:41 +0000561 ASSERT_NE(TypeOf(cast), nullptr);
562 EXPECT_TRUE(TypeOf(cast)->Is<type::F32>());
dan sinclair4e807952020-04-07 16:41:23 +0000563}
564
Ben Clayton5f0ea112021-03-09 10:54:37 +0000565TEST_F(ResolverTest, Expr_Constructor_Scalar) {
Ben Clayton1637cbb2021-01-05 15:44:39 +0000566 auto* s = Expr(1.0f);
Ben Clayton401b96b2021-02-03 17:19:59 +0000567 WrapInFunction(s);
568
Ben Clayton5f0ea112021-03-09 10:54:37 +0000569 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton401b96b2021-02-03 17:19:59 +0000570
Ben Clayton33352542021-01-29 16:43:41 +0000571 ASSERT_NE(TypeOf(s), nullptr);
572 EXPECT_TRUE(TypeOf(s)->Is<type::F32>());
dan sinclairb7edc4c2020-04-07 12:46:30 +0000573}
574
Arman Uguray3549e2e2021-03-15 21:21:33 +0000575TEST_F(ResolverTest, Expr_Constructor_Type_Vec2) {
576 auto* tc = vec2<f32>(1.0f, 1.0f);
577 WrapInFunction(tc);
578
579 EXPECT_TRUE(r()->Resolve()) << r()->error();
580
581 ASSERT_NE(TypeOf(tc), nullptr);
582 ASSERT_TRUE(TypeOf(tc)->Is<type::Vector>());
583 EXPECT_TRUE(TypeOf(tc)->As<type::Vector>()->type()->Is<type::F32>());
584 EXPECT_EQ(TypeOf(tc)->As<type::Vector>()->size(), 2u);
585}
586
587TEST_F(ResolverTest, Expr_Constructor_Type_Vec3) {
588 auto* tc = vec3<f32>(1.0f, 1.0f, 1.0f);
Ben Clayton401b96b2021-02-03 17:19:59 +0000589 WrapInFunction(tc);
dan sinclairb7edc4c2020-04-07 12:46:30 +0000590
Ben Clayton5f0ea112021-03-09 10:54:37 +0000591 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton401b96b2021-02-03 17:19:59 +0000592
Ben Clayton33352542021-01-29 16:43:41 +0000593 ASSERT_NE(TypeOf(tc), nullptr);
594 ASSERT_TRUE(TypeOf(tc)->Is<type::Vector>());
595 EXPECT_TRUE(TypeOf(tc)->As<type::Vector>()->type()->Is<type::F32>());
596 EXPECT_EQ(TypeOf(tc)->As<type::Vector>()->size(), 3u);
dan sinclairb7edc4c2020-04-07 12:46:30 +0000597}
598
Arman Uguray3549e2e2021-03-15 21:21:33 +0000599TEST_F(ResolverTest, Expr_Constructor_Type_Vec4) {
600 auto* tc = vec4<f32>(1.0f, 1.0f, 1.0f, 1.0f);
601 WrapInFunction(tc);
602
603 EXPECT_TRUE(r()->Resolve()) << r()->error();
604
605 ASSERT_NE(TypeOf(tc), nullptr);
606 ASSERT_TRUE(TypeOf(tc)->Is<type::Vector>());
607 EXPECT_TRUE(TypeOf(tc)->As<type::Vector>()->type()->Is<type::F32>());
608 EXPECT_EQ(TypeOf(tc)->As<type::Vector>()->size(), 4u);
609}
610
Ben Clayton5f0ea112021-03-09 10:54:37 +0000611TEST_F(ResolverTest, Expr_Identifier_GlobalVariable) {
Antonio Maioranobbbb0ed2021-04-06 20:18:57 +0000612 auto* my_var = Global("my_var", ty.f32(), ast::StorageClass::kInput);
dan sinclaircab0e732020-04-07 12:57:27 +0000613
Ben Clayton7eaf4b52020-12-14 22:08:27 +0000614 auto* ident = Expr("my_var");
Ben Clayton401b96b2021-02-03 17:19:59 +0000615 WrapInFunction(ident);
616
Ben Clayton5f0ea112021-03-09 10:54:37 +0000617 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton401b96b2021-02-03 17:19:59 +0000618
Ben Clayton33352542021-01-29 16:43:41 +0000619 ASSERT_NE(TypeOf(ident), nullptr);
620 EXPECT_TRUE(TypeOf(ident)->Is<type::Pointer>());
621 EXPECT_TRUE(TypeOf(ident)->As<type::Pointer>()->type()->Is<type::F32>());
James Pricec9af5972021-02-16 21:15:01 +0000622 EXPECT_TRUE(CheckVarUsers(my_var, {ident}));
Ben Clayton86c2cbf2021-04-07 08:09:01 +0000623 ASSERT_NE(VarOf(ident), nullptr);
624 EXPECT_EQ(VarOf(ident)->Declaration(), my_var);
dan sinclair8eddb782020-04-23 22:26:52 +0000625}
626
Ben Clayton5f0ea112021-03-09 10:54:37 +0000627TEST_F(ResolverTest, Expr_Identifier_GlobalConstant) {
Ben Clayton81a29fe2021-02-17 00:26:52 +0000628 auto* my_var = GlobalConst("my_var", ty.f32());
dan sinclair8eddb782020-04-23 22:26:52 +0000629
Ben Clayton7eaf4b52020-12-14 22:08:27 +0000630 auto* ident = Expr("my_var");
Ben Clayton401b96b2021-02-03 17:19:59 +0000631 WrapInFunction(ident);
632
Ben Clayton5f0ea112021-03-09 10:54:37 +0000633 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton401b96b2021-02-03 17:19:59 +0000634
Ben Clayton33352542021-01-29 16:43:41 +0000635 ASSERT_NE(TypeOf(ident), nullptr);
636 EXPECT_TRUE(TypeOf(ident)->Is<type::F32>());
James Pricec9af5972021-02-16 21:15:01 +0000637 EXPECT_TRUE(CheckVarUsers(my_var, {ident}));
Ben Clayton86c2cbf2021-04-07 08:09:01 +0000638 ASSERT_NE(VarOf(ident), nullptr);
639 EXPECT_EQ(VarOf(ident)->Declaration(), my_var);
dan sinclaircab0e732020-04-07 12:57:27 +0000640}
641
Ben Clayton5f0ea112021-03-09 10:54:37 +0000642TEST_F(ResolverTest, Expr_Identifier_FunctionVariable_Const) {
Ben Claytonf97b9c92021-02-16 18:45:45 +0000643 auto* my_var_a = Expr("my_var");
Ben Clayton81a29fe2021-02-17 00:26:52 +0000644 auto* var = Const("my_var", ty.f32());
Antonio Maioranoe09989a2021-03-31 13:26:43 +0000645 auto* decl = Decl(Var("b", ty.f32(), ast::StorageClass::kFunction, my_var_a));
dan sinclair8eddb782020-04-23 22:26:52 +0000646
Antonio Maiorano03c01b52021-03-19 14:04:51 +0000647 Func("my_func", ast::VariableList{}, ty.void_(),
Ben Clayton401b96b2021-02-03 17:19:59 +0000648 ast::StatementList{
649 create<ast::VariableDeclStatement>(var),
Antonio Maioranoe09989a2021-03-31 13:26:43 +0000650 decl,
Ben Clayton401b96b2021-02-03 17:19:59 +0000651 },
James Price95d40772021-03-11 17:39:32 +0000652 ast::DecorationList{});
dan sinclair8eddb782020-04-23 22:26:52 +0000653
Ben Clayton5f0ea112021-03-09 10:54:37 +0000654 EXPECT_TRUE(r()->Resolve()) << r()->error();
dan sinclair8eddb782020-04-23 22:26:52 +0000655
Ben Claytonf97b9c92021-02-16 18:45:45 +0000656 ASSERT_NE(TypeOf(my_var_a), nullptr);
657 EXPECT_TRUE(TypeOf(my_var_a)->Is<type::F32>());
Antonio Maioranoe09989a2021-03-31 13:26:43 +0000658 EXPECT_EQ(StmtOf(my_var_a), decl);
659 EXPECT_TRUE(CheckVarUsers(var, {my_var_a}));
Ben Clayton86c2cbf2021-04-07 08:09:01 +0000660 ASSERT_NE(VarOf(my_var_a), nullptr);
661 EXPECT_EQ(VarOf(my_var_a)->Declaration(), var);
dan sinclair8eddb782020-04-23 22:26:52 +0000662}
663
Ben Clayton5f0ea112021-03-09 10:54:37 +0000664TEST_F(ResolverTest, Expr_Identifier_FunctionVariable) {
Ben Claytonf97b9c92021-02-16 18:45:45 +0000665 auto* my_var_a = Expr("my_var");
666 auto* my_var_b = Expr("my_var");
667 auto* assign = create<ast::AssignmentStatement>(my_var_a, my_var_b);
dan sinclaircab0e732020-04-07 12:57:27 +0000668
Ben Clayton37571bc2021-02-16 23:57:01 +0000669 auto* var = Var("my_var", ty.f32(), ast::StorageClass::kNone);
James Pricec9af5972021-02-16 21:15:01 +0000670
Antonio Maiorano03c01b52021-03-19 14:04:51 +0000671 Func("my_func", ast::VariableList{}, ty.void_(),
Ben Clayton401b96b2021-02-03 17:19:59 +0000672 ast::StatementList{
James Pricec9af5972021-02-16 21:15:01 +0000673 create<ast::VariableDeclStatement>(var),
Ben Claytonf97b9c92021-02-16 18:45:45 +0000674 assign,
Ben Clayton401b96b2021-02-03 17:19:59 +0000675 },
James Price95d40772021-03-11 17:39:32 +0000676 ast::DecorationList{});
dan sinclaircab0e732020-04-07 12:57:27 +0000677
Ben Clayton5f0ea112021-03-09 10:54:37 +0000678 EXPECT_TRUE(r()->Resolve()) << r()->error();
dan sinclaircab0e732020-04-07 12:57:27 +0000679
Ben Claytonf97b9c92021-02-16 18:45:45 +0000680 ASSERT_NE(TypeOf(my_var_a), nullptr);
681 EXPECT_TRUE(TypeOf(my_var_a)->Is<type::Pointer>());
682 EXPECT_TRUE(TypeOf(my_var_a)->As<type::Pointer>()->type()->Is<type::F32>());
683 EXPECT_EQ(StmtOf(my_var_a), assign);
684 ASSERT_NE(TypeOf(my_var_b), nullptr);
685 EXPECT_TRUE(TypeOf(my_var_b)->Is<type::Pointer>());
686 EXPECT_TRUE(TypeOf(my_var_b)->As<type::Pointer>()->type()->Is<type::F32>());
687 EXPECT_EQ(StmtOf(my_var_b), assign);
James Pricec9af5972021-02-16 21:15:01 +0000688 EXPECT_TRUE(CheckVarUsers(var, {my_var_a, my_var_b}));
Ben Clayton86c2cbf2021-04-07 08:09:01 +0000689 ASSERT_NE(VarOf(my_var_a), nullptr);
690 EXPECT_EQ(VarOf(my_var_a)->Declaration(), var);
691 ASSERT_NE(VarOf(my_var_b), nullptr);
692 EXPECT_EQ(VarOf(my_var_b)->Declaration(), var);
dan sinclaircab0e732020-04-07 12:57:27 +0000693}
694
Ben Clayton5f0ea112021-03-09 10:54:37 +0000695TEST_F(ResolverTest, Expr_Identifier_Function_Ptr) {
Ben Claytonf97b9c92021-02-16 18:45:45 +0000696 auto* my_var_a = Expr("my_var");
697 auto* my_var_b = Expr("my_var");
698 auto* assign = create<ast::AssignmentStatement>(my_var_a, my_var_b);
dan sinclair5e989302020-09-16 21:20:36 +0000699
Antonio Maiorano03c01b52021-03-19 14:04:51 +0000700 Func("my_func", ast::VariableList{}, ty.void_(),
Ben Clayton401b96b2021-02-03 17:19:59 +0000701 ast::StatementList{
702 create<ast::VariableDeclStatement>(
Ben Clayton37571bc2021-02-16 23:57:01 +0000703 Var("my_var", ty.pointer<f32>(ast::StorageClass::kFunction),
704 ast::StorageClass::kNone)),
Ben Claytonf97b9c92021-02-16 18:45:45 +0000705 assign,
Ben Clayton401b96b2021-02-03 17:19:59 +0000706 },
James Price95d40772021-03-11 17:39:32 +0000707 ast::DecorationList{});
dan sinclair5e989302020-09-16 21:20:36 +0000708
Ben Clayton5f0ea112021-03-09 10:54:37 +0000709 EXPECT_TRUE(r()->Resolve()) << r()->error();
dan sinclair5e989302020-09-16 21:20:36 +0000710
Ben Claytonf97b9c92021-02-16 18:45:45 +0000711 ASSERT_NE(TypeOf(my_var_a), nullptr);
712 EXPECT_TRUE(TypeOf(my_var_a)->Is<type::Pointer>());
713 EXPECT_TRUE(TypeOf(my_var_a)->As<type::Pointer>()->type()->Is<type::F32>());
714 EXPECT_EQ(StmtOf(my_var_a), assign);
715 ASSERT_NE(TypeOf(my_var_b), nullptr);
716 EXPECT_TRUE(TypeOf(my_var_b)->Is<type::Pointer>());
717 EXPECT_TRUE(TypeOf(my_var_b)->As<type::Pointer>()->type()->Is<type::F32>());
718 EXPECT_EQ(StmtOf(my_var_b), assign);
dan sinclair5e989302020-09-16 21:20:36 +0000719}
720
Ben Clayton5f0ea112021-03-09 10:54:37 +0000721TEST_F(ResolverTest, Expr_Call_Function) {
Antonio Maiorano03c01b52021-03-19 14:04:51 +0000722 Func("my_func", ast::VariableList{}, ty.f32(),
723 ast::StatementList{Return(Expr(0.0f))}, ast::DecorationList{});
dan sinclaircab0e732020-04-07 12:57:27 +0000724
Ben Clayton1618f4b2021-02-03 21:02:25 +0000725 auto* call = Call("my_func");
726 WrapInFunction(call);
Ben Clayton401b96b2021-02-03 17:19:59 +0000727
Ben Clayton5f0ea112021-03-09 10:54:37 +0000728 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton401b96b2021-02-03 17:19:59 +0000729
Ben Clayton1618f4b2021-02-03 21:02:25 +0000730 ASSERT_NE(TypeOf(call), nullptr);
731 EXPECT_TRUE(TypeOf(call)->Is<type::F32>());
dan sinclaircab0e732020-04-07 12:57:27 +0000732}
733
Ben Clayton5f0ea112021-03-09 10:54:37 +0000734TEST_F(ResolverTest, Expr_Identifier_Unknown) {
Ben Clayton7eaf4b52020-12-14 22:08:27 +0000735 auto* a = Expr("a");
Ben Clayton401b96b2021-02-03 17:19:59 +0000736 WrapInFunction(a);
737
Ben Clayton5f0ea112021-03-09 10:54:37 +0000738 EXPECT_FALSE(r()->Resolve());
dan sinclairff267ca2020-10-14 18:26:31 +0000739}
740
Ben Claytone9c49842021-04-09 13:56:08 +0000741TEST_F(ResolverTest, Function_Parameters) {
742 auto* param_a = Param("a", ty.f32());
743 auto* param_b = Param("b", ty.i32());
744 auto* param_c = Param("c", ty.u32());
745
746 auto* func = Func("my_func",
747 ast::VariableList{
748 param_a,
749 param_b,
750 param_c,
751 },
752 ty.void_(), {});
753
754 EXPECT_TRUE(r()->Resolve()) << r()->error();
755
756 auto* func_sem = Sem().Get(func);
757 ASSERT_NE(func_sem, nullptr);
758 EXPECT_EQ(func_sem->Parameters().size(), 3u);
759 EXPECT_EQ(func_sem->Parameters()[0]->Type(), ty.f32());
760 EXPECT_EQ(func_sem->Parameters()[1]->Type(), ty.i32());
761 EXPECT_EQ(func_sem->Parameters()[2]->Type(), ty.u32());
762 EXPECT_EQ(func_sem->Parameters()[0]->Declaration(), param_a);
763 EXPECT_EQ(func_sem->Parameters()[1]->Declaration(), param_b);
764 EXPECT_EQ(func_sem->Parameters()[2]->Declaration(), param_c);
765}
766
Ben Clayton5f0ea112021-03-09 10:54:37 +0000767TEST_F(ResolverTest, Function_RegisterInputOutputVariables) {
Ben Clayton85bfea62021-04-19 20:20:33 +0000768 auto* s = Structure("S", {Member("m", ty.u32())},
769 {create<ast::StructBlockDecoration>()});
Ben Clayton17735352021-04-16 09:26:14 +0000770 auto* a = ty.access(ast::AccessControl::kReadOnly, s);
771
Ben Clayton37571bc2021-02-16 23:57:01 +0000772 auto* in_var = Global("in_var", ty.f32(), ast::StorageClass::kInput);
773 auto* out_var = Global("out_var", ty.f32(), ast::StorageClass::kOutput);
Ben Clayton17735352021-04-16 09:26:14 +0000774 auto* sb_var = Global("sb_var", a, ast::StorageClass::kStorage);
Ben Clayton37571bc2021-02-16 23:57:01 +0000775 auto* wg_var = Global("wg_var", ty.f32(), ast::StorageClass::kWorkgroup);
776 auto* priv_var = Global("priv_var", ty.f32(), ast::StorageClass::kPrivate);
dan sinclair13d2a3b2020-06-22 20:52:24 +0000777
dan sinclair181d8ba2020-12-16 15:15:40 +0000778 auto* func = Func(
Antonio Maiorano03c01b52021-03-19 14:04:51 +0000779 "my_func", ast::VariableList{}, ty.void_(),
dan sinclair181d8ba2020-12-16 15:15:40 +0000780 ast::StatementList{
781 create<ast::AssignmentStatement>(Expr("out_var"), Expr("in_var")),
782 create<ast::AssignmentStatement>(Expr("wg_var"), Expr("wg_var")),
783 create<ast::AssignmentStatement>(Expr("sb_var"), Expr("sb_var")),
784 create<ast::AssignmentStatement>(Expr("priv_var"), Expr("priv_var")),
785 },
James Price95d40772021-03-11 17:39:32 +0000786 ast::DecorationList{});
dan sinclair13d2a3b2020-06-22 20:52:24 +0000787
Ben Clayton5f0ea112021-03-09 10:54:37 +0000788 EXPECT_TRUE(r()->Resolve()) << r()->error();
dan sinclair13d2a3b2020-06-22 20:52:24 +0000789
Ben Clayton87c78dd2021-02-03 16:43:20 +0000790 auto* func_sem = Sem().Get(func);
791 ASSERT_NE(func_sem, nullptr);
Ben Claytone9c49842021-04-09 13:56:08 +0000792 EXPECT_EQ(func_sem->Parameters().size(), 0u);
Ben Clayton87c78dd2021-02-03 16:43:20 +0000793
794 const auto& vars = func_sem->ReferencedModuleVariables();
Ryan Harrison9a452c12020-06-23 16:38:47 +0000795 ASSERT_EQ(vars.size(), 5u);
Ben Claytonb17aea12021-02-03 17:51:09 +0000796 EXPECT_EQ(vars[0]->Declaration(), out_var);
797 EXPECT_EQ(vars[1]->Declaration(), in_var);
798 EXPECT_EQ(vars[2]->Declaration(), wg_var);
799 EXPECT_EQ(vars[3]->Declaration(), sb_var);
800 EXPECT_EQ(vars[4]->Declaration(), priv_var);
dan sinclair13d2a3b2020-06-22 20:52:24 +0000801}
802
Ben Clayton5f0ea112021-03-09 10:54:37 +0000803TEST_F(ResolverTest, Function_RegisterInputOutputVariables_SubFunction) {
Ben Clayton85bfea62021-04-19 20:20:33 +0000804 auto* s = Structure("S", {Member("m", ty.u32())},
805 {create<ast::StructBlockDecoration>()});
Ben Clayton17735352021-04-16 09:26:14 +0000806 auto* a = ty.access(ast::AccessControl::kReadOnly, s);
807
Ben Clayton37571bc2021-02-16 23:57:01 +0000808 auto* in_var = Global("in_var", ty.f32(), ast::StorageClass::kInput);
809 auto* out_var = Global("out_var", ty.f32(), ast::StorageClass::kOutput);
Ben Clayton17735352021-04-16 09:26:14 +0000810 auto* sb_var = Global("sb_var", a, ast::StorageClass::kStorage);
Ben Clayton37571bc2021-02-16 23:57:01 +0000811 auto* wg_var = Global("wg_var", ty.f32(), ast::StorageClass::kWorkgroup);
812 auto* priv_var = Global("priv_var", ty.f32(), ast::StorageClass::kPrivate);
dan sinclairde2dd682020-07-14 20:37:28 +0000813
Ben Clayton42d1e092021-02-02 14:29:15 +0000814 Func("my_func", ast::VariableList{}, ty.f32(),
815 ast::StatementList{
816 create<ast::AssignmentStatement>(Expr("out_var"), Expr("in_var")),
817 create<ast::AssignmentStatement>(Expr("wg_var"), Expr("wg_var")),
818 create<ast::AssignmentStatement>(Expr("sb_var"), Expr("sb_var")),
819 create<ast::AssignmentStatement>(Expr("priv_var"), Expr("priv_var")),
Antonio Maiorano03c01b52021-03-19 14:04:51 +0000820 Return(Expr(0.0f))},
James Price95d40772021-03-11 17:39:32 +0000821 ast::DecorationList{});
dan sinclairde2dd682020-07-14 20:37:28 +0000822
dan sinclair181d8ba2020-12-16 15:15:40 +0000823 auto* func2 = Func(
Antonio Maiorano03c01b52021-03-19 14:04:51 +0000824 "func", ast::VariableList{}, ty.void_(),
dan sinclair181d8ba2020-12-16 15:15:40 +0000825 ast::StatementList{
826 create<ast::AssignmentStatement>(Expr("out_var"), Call("my_func")),
827 },
James Price95d40772021-03-11 17:39:32 +0000828 ast::DecorationList{});
dan sinclairde2dd682020-07-14 20:37:28 +0000829
Ben Clayton5f0ea112021-03-09 10:54:37 +0000830 EXPECT_TRUE(r()->Resolve()) << r()->error();
dan sinclairde2dd682020-07-14 20:37:28 +0000831
Ben Clayton87c78dd2021-02-03 16:43:20 +0000832 auto* func2_sem = Sem().Get(func2);
833 ASSERT_NE(func2_sem, nullptr);
Ben Claytone9c49842021-04-09 13:56:08 +0000834 EXPECT_EQ(func2_sem->Parameters().size(), 0u);
Ben Clayton87c78dd2021-02-03 16:43:20 +0000835
836 const auto& vars = func2_sem->ReferencedModuleVariables();
dan sinclairde2dd682020-07-14 20:37:28 +0000837 ASSERT_EQ(vars.size(), 5u);
Ben Claytonb17aea12021-02-03 17:51:09 +0000838 EXPECT_EQ(vars[0]->Declaration(), out_var);
839 EXPECT_EQ(vars[1]->Declaration(), in_var);
840 EXPECT_EQ(vars[2]->Declaration(), wg_var);
841 EXPECT_EQ(vars[3]->Declaration(), sb_var);
842 EXPECT_EQ(vars[4]->Declaration(), priv_var);
dan sinclairde2dd682020-07-14 20:37:28 +0000843}
844
Ben Clayton5f0ea112021-03-09 10:54:37 +0000845TEST_F(ResolverTest, Function_NotRegisterFunctionVariable) {
Ben Clayton37571bc2021-02-16 23:57:01 +0000846 auto* var = Var("in_var", ty.f32(), ast::StorageClass::kFunction);
Antonio Maioranobb5617f2021-03-19 18:45:30 +0000847 Global("var", ty.f32(), ast::StorageClass::kFunction);
dan sinclair13d2a3b2020-06-22 20:52:24 +0000848
dan sinclair181d8ba2020-12-16 15:15:40 +0000849 auto* func =
Antonio Maiorano03c01b52021-03-19 14:04:51 +0000850 Func("my_func", ast::VariableList{}, ty.void_(),
dan sinclair181d8ba2020-12-16 15:15:40 +0000851 ast::StatementList{
852 create<ast::VariableDeclStatement>(var),
Ben Clayton1637cbb2021-01-05 15:44:39 +0000853 create<ast::AssignmentStatement>(Expr("var"), Expr(1.f)),
dan sinclair181d8ba2020-12-16 15:15:40 +0000854 },
James Price95d40772021-03-11 17:39:32 +0000855 ast::DecorationList{});
dan sinclair13d2a3b2020-06-22 20:52:24 +0000856
Ben Clayton5f0ea112021-03-09 10:54:37 +0000857 EXPECT_TRUE(r()->Resolve()) << r()->error();
dan sinclair13d2a3b2020-06-22 20:52:24 +0000858
Ben Clayton87c78dd2021-02-03 16:43:20 +0000859 auto* func_sem = Sem().Get(func);
860 ASSERT_NE(func_sem, nullptr);
861
862 EXPECT_EQ(func_sem->ReferencedModuleVariables().size(), 0u);
dan sinclair13d2a3b2020-06-22 20:52:24 +0000863}
864
James Price4ffd3e22021-03-17 14:24:04 +0000865TEST_F(ResolverTest, Function_ReturnStatements) {
866 auto* var = Var("foo", ty.f32(), ast::StorageClass::kFunction);
867
868 auto* ret_1 = create<ast::ReturnStatement>(Expr(1.f));
869 auto* ret_foo = create<ast::ReturnStatement>(Expr("foo"));
870
871 auto* func = Func("my_func", ast::VariableList{}, ty.f32(),
872 ast::StatementList{
873 create<ast::VariableDeclStatement>(var),
874 If(Expr(true), Block(ret_1)),
875 ret_foo,
876 },
877 ast::DecorationList{});
878
879 EXPECT_TRUE(r()->Resolve()) << r()->error();
880
881 auto* func_sem = Sem().Get(func);
882 ASSERT_NE(func_sem, nullptr);
Ben Claytone9c49842021-04-09 13:56:08 +0000883 EXPECT_EQ(func_sem->Parameters().size(), 0u);
James Price4ffd3e22021-03-17 14:24:04 +0000884
885 EXPECT_EQ(func_sem->ReturnStatements().size(), 2u);
886 EXPECT_EQ(func_sem->ReturnStatements()[0], ret_1);
887 EXPECT_EQ(func_sem->ReturnStatements()[1], ret_foo);
888}
889
Ben Clayton5f0ea112021-03-09 10:54:37 +0000890TEST_F(ResolverTest, Expr_MemberAccessor_Struct) {
dan sinclair5e5e36e2020-12-16 14:41:00 +0000891 auto* strct = create<ast::Struct>(
Ben Clayton8d391f72021-01-26 16:57:10 +0000892 ast::StructMemberList{Member("first_member", ty.i32()),
893 Member("second_member", ty.f32())},
James Price95d40772021-03-11 17:39:32 +0000894 ast::DecorationList{});
dan sinclair8ee1d222020-04-07 16:41:33 +0000895
dan sinclairb5839932020-12-16 21:38:40 +0000896 auto* st = ty.struct_("S", strct);
Antonio Maioranobbbb0ed2021-04-06 20:18:57 +0000897 Global("my_struct", st, ast::StorageClass::kInput);
dan sinclair8ee1d222020-04-07 16:41:33 +0000898
dan sinclair8b40a672020-12-16 11:49:10 +0000899 auto* mem = MemberAccessor("my_struct", "second_member");
Ben Clayton401b96b2021-02-03 17:19:59 +0000900 WrapInFunction(mem);
901
Ben Clayton5f0ea112021-03-09 10:54:37 +0000902 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton401b96b2021-02-03 17:19:59 +0000903
Ben Clayton33352542021-01-29 16:43:41 +0000904 ASSERT_NE(TypeOf(mem), nullptr);
905 ASSERT_TRUE(TypeOf(mem)->Is<type::Pointer>());
dan sinclair8ee1d222020-04-07 16:41:33 +0000906
Ben Clayton33352542021-01-29 16:43:41 +0000907 auto* ptr = TypeOf(mem)->As<type::Pointer>();
Ben Clayton207b5e22021-01-21 15:42:10 +0000908 EXPECT_TRUE(ptr->type()->Is<type::F32>());
Antonio Maiorano5cd71b82021-04-16 19:07:51 +0000909 ASSERT_TRUE(Sem().Get(mem)->Is<sem::StructMemberAccess>());
Ben Claytone9c49842021-04-09 13:56:08 +0000910 EXPECT_EQ(Sem()
911 .Get(mem)
Antonio Maiorano5cd71b82021-04-16 19:07:51 +0000912 ->As<sem::StructMemberAccess>()
Ben Claytone9c49842021-04-09 13:56:08 +0000913 ->Member()
914 ->Declaration()
915 ->symbol(),
916 Symbols().Get("second_member"));
dan sinclair8ee1d222020-04-07 16:41:33 +0000917}
918
Ben Clayton5f0ea112021-03-09 10:54:37 +0000919TEST_F(ResolverTest, Expr_MemberAccessor_Struct_Alias) {
dan sinclair5e5e36e2020-12-16 14:41:00 +0000920 auto* strct = create<ast::Struct>(
Ben Clayton8d391f72021-01-26 16:57:10 +0000921 ast::StructMemberList{Member("first_member", ty.i32()),
922 Member("second_member", ty.f32())},
James Price95d40772021-03-11 17:39:32 +0000923 ast::DecorationList{});
dan sinclairb445a9b2020-04-24 00:40:45 +0000924
dan sinclairb5839932020-12-16 21:38:40 +0000925 auto* st = ty.struct_("alias", strct);
926 auto* alias = ty.alias("alias", st);
Antonio Maioranobbbb0ed2021-04-06 20:18:57 +0000927 Global("my_struct", alias, ast::StorageClass::kInput);
dan sinclairb445a9b2020-04-24 00:40:45 +0000928
dan sinclair8b40a672020-12-16 11:49:10 +0000929 auto* mem = MemberAccessor("my_struct", "second_member");
Ben Clayton401b96b2021-02-03 17:19:59 +0000930 WrapInFunction(mem);
931
Ben Clayton5f0ea112021-03-09 10:54:37 +0000932 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton401b96b2021-02-03 17:19:59 +0000933
Ben Clayton33352542021-01-29 16:43:41 +0000934 ASSERT_NE(TypeOf(mem), nullptr);
935 ASSERT_TRUE(TypeOf(mem)->Is<type::Pointer>());
dan sinclairb445a9b2020-04-24 00:40:45 +0000936
Ben Clayton33352542021-01-29 16:43:41 +0000937 auto* ptr = TypeOf(mem)->As<type::Pointer>();
Ben Clayton207b5e22021-01-21 15:42:10 +0000938 EXPECT_TRUE(ptr->type()->Is<type::F32>());
Antonio Maiorano5cd71b82021-04-16 19:07:51 +0000939 ASSERT_TRUE(Sem().Get(mem)->Is<sem::StructMemberAccess>());
dan sinclairb445a9b2020-04-24 00:40:45 +0000940}
941
Ben Clayton5f0ea112021-03-09 10:54:37 +0000942TEST_F(ResolverTest, Expr_MemberAccessor_VectorSwizzle) {
Antonio Maioranobbbb0ed2021-04-06 20:18:57 +0000943 Global("my_vec", ty.vec3<f32>(), ast::StorageClass::kInput);
dan sinclair8ee1d222020-04-07 16:41:33 +0000944
Ben Clayton6d612ad2021-02-24 14:15:02 +0000945 auto* mem = MemberAccessor("my_vec", "xzyw");
Ben Clayton401b96b2021-02-03 17:19:59 +0000946 WrapInFunction(mem);
947
Ben Clayton5f0ea112021-03-09 10:54:37 +0000948 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton401b96b2021-02-03 17:19:59 +0000949
Ben Clayton33352542021-01-29 16:43:41 +0000950 ASSERT_NE(TypeOf(mem), nullptr);
951 ASSERT_TRUE(TypeOf(mem)->Is<type::Vector>());
952 EXPECT_TRUE(TypeOf(mem)->As<type::Vector>()->type()->Is<type::F32>());
Ben Clayton6d612ad2021-02-24 14:15:02 +0000953 EXPECT_EQ(TypeOf(mem)->As<type::Vector>()->size(), 4u);
Antonio Maiorano5cd71b82021-04-16 19:07:51 +0000954 ASSERT_TRUE(Sem().Get(mem)->Is<sem::Swizzle>());
955 EXPECT_THAT(Sem().Get(mem)->As<sem::Swizzle>()->Indices(),
Ben Claytone9c49842021-04-09 13:56:08 +0000956 ElementsAre(0, 2, 1, 3));
dan sinclair8ee1d222020-04-07 16:41:33 +0000957}
958
Ben Clayton5f0ea112021-03-09 10:54:37 +0000959TEST_F(ResolverTest, Expr_MemberAccessor_VectorSwizzle_SingleElement) {
Antonio Maioranobbbb0ed2021-04-06 20:18:57 +0000960 Global("my_vec", ty.vec3<f32>(), ast::StorageClass::kInput);
dan sinclairaac58652020-04-21 13:05:34 +0000961
Ben Clayton6d612ad2021-02-24 14:15:02 +0000962 auto* mem = MemberAccessor("my_vec", "b");
Ben Clayton401b96b2021-02-03 17:19:59 +0000963 WrapInFunction(mem);
964
Ben Clayton5f0ea112021-03-09 10:54:37 +0000965 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton401b96b2021-02-03 17:19:59 +0000966
Ben Clayton33352542021-01-29 16:43:41 +0000967 ASSERT_NE(TypeOf(mem), nullptr);
968 ASSERT_TRUE(TypeOf(mem)->Is<type::Pointer>());
dan sinclairaac58652020-04-21 13:05:34 +0000969
Ben Clayton33352542021-01-29 16:43:41 +0000970 auto* ptr = TypeOf(mem)->As<type::Pointer>();
Ben Clayton207b5e22021-01-21 15:42:10 +0000971 ASSERT_TRUE(ptr->type()->Is<type::F32>());
Antonio Maiorano5cd71b82021-04-16 19:07:51 +0000972 ASSERT_TRUE(Sem().Get(mem)->Is<sem::Swizzle>());
973 EXPECT_THAT(Sem().Get(mem)->As<sem::Swizzle>()->Indices(), ElementsAre(2));
Ben Clayton6d612ad2021-02-24 14:15:02 +0000974}
975
Ben Clayton5f0ea112021-03-09 10:54:37 +0000976TEST_F(ResolverTest, Expr_Accessor_MultiLevel) {
dan sinclair8ee1d222020-04-07 16:41:33 +0000977 // struct b {
978 // vec4<f32> foo
979 // }
980 // struct A {
981 // vec3<struct b> mem
982 // }
983 // var c : A
984 // c.mem[0].foo.yx
985 // -> vec2<f32>
986 //
987 // MemberAccessor{
988 // MemberAccessor{
989 // ArrayAccessor{
990 // MemberAccessor{
991 // Identifier{c}
992 // Identifier{mem}
993 // }
994 // ScalarConstructor{0}
995 // }
996 // Identifier{foo}
997 // }
998 // Identifier{yx}
999 // }
1000 //
dan sinclair8ee1d222020-04-07 16:41:33 +00001001
dan sinclair5e5e36e2020-12-16 14:41:00 +00001002 auto* strctB =
1003 create<ast::Struct>(ast::StructMemberList{Member("foo", ty.vec4<f32>())},
James Price95d40772021-03-11 17:39:32 +00001004 ast::DecorationList{});
dan sinclairb5839932020-12-16 21:38:40 +00001005 auto* stB = ty.struct_("B", strctB);
dan sinclair8ee1d222020-04-07 16:41:33 +00001006
Ben Clayton207b5e22021-01-21 15:42:10 +00001007 type::Vector vecB(stB, 3);
dan sinclair5e5e36e2020-12-16 14:41:00 +00001008 auto* strctA = create<ast::Struct>(
James Price95d40772021-03-11 17:39:32 +00001009 ast::StructMemberList{Member("mem", &vecB)}, ast::DecorationList{});
dan sinclair8ee1d222020-04-07 16:41:33 +00001010
dan sinclairb5839932020-12-16 21:38:40 +00001011 auto* stA = ty.struct_("A", strctA);
Antonio Maioranobbbb0ed2021-04-06 20:18:57 +00001012 Global("c", stA, ast::StorageClass::kInput);
dan sinclair8ee1d222020-04-07 16:41:33 +00001013
dan sinclair8b40a672020-12-16 11:49:10 +00001014 auto* mem = MemberAccessor(
1015 MemberAccessor(IndexAccessor(MemberAccessor("c", "mem"), 0), "foo"),
1016 "yx");
Ben Clayton401b96b2021-02-03 17:19:59 +00001017 WrapInFunction(mem);
1018
Ben Clayton5f0ea112021-03-09 10:54:37 +00001019 EXPECT_TRUE(r()->Resolve()) << r()->error();
dan sinclair8ee1d222020-04-07 16:41:33 +00001020
Ben Clayton33352542021-01-29 16:43:41 +00001021 ASSERT_NE(TypeOf(mem), nullptr);
1022 ASSERT_TRUE(TypeOf(mem)->Is<type::Vector>());
1023 EXPECT_TRUE(TypeOf(mem)->As<type::Vector>()->type()->Is<type::F32>());
1024 EXPECT_EQ(TypeOf(mem)->As<type::Vector>()->size(), 2u);
Antonio Maiorano5cd71b82021-04-16 19:07:51 +00001025 ASSERT_TRUE(Sem().Get(mem)->Is<sem::Swizzle>());
dan sinclair8ee1d222020-04-07 16:41:33 +00001026}
1027
Ben Clayton5f0ea112021-03-09 10:54:37 +00001028TEST_F(ResolverTest, Expr_MemberAccessor_InBinaryOp) {
Ben Clayton7b7d6982021-02-09 17:38:05 +00001029 auto* strct = create<ast::Struct>(
1030 ast::StructMemberList{Member("first_member", ty.f32()),
1031 Member("second_member", ty.f32())},
James Price95d40772021-03-11 17:39:32 +00001032 ast::DecorationList{});
Ben Clayton7b7d6982021-02-09 17:38:05 +00001033
1034 auto* st = ty.struct_("S", strct);
Antonio Maioranobbbb0ed2021-04-06 20:18:57 +00001035 Global("my_struct", st, ast::StorageClass::kInput);
Ben Clayton7b7d6982021-02-09 17:38:05 +00001036
1037 auto* expr = Add(MemberAccessor("my_struct", "first_member"),
1038 MemberAccessor("my_struct", "second_member"));
1039 WrapInFunction(expr);
1040
Ben Clayton5f0ea112021-03-09 10:54:37 +00001041 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton7b7d6982021-02-09 17:38:05 +00001042
1043 ASSERT_NE(TypeOf(expr), nullptr);
1044 EXPECT_TRUE(TypeOf(expr)->Is<type::F32>());
1045}
1046
Antonio Maioranobe0fc4e2021-03-16 13:26:03 +00001047namespace ExprBinaryTest {
dan sinclair9b978022020-04-07 19:26:39 +00001048
Antonio Maioranobe0fc4e2021-03-16 13:26:03 +00001049struct Params {
1050 ast::BinaryOp op;
1051 create_type_func_ptr create_lhs_type;
1052 create_type_func_ptr create_rhs_type;
1053 create_type_func_ptr create_result_type;
1054};
dan sinclair9b978022020-04-07 19:26:39 +00001055
Antonio Maioranobe0fc4e2021-03-16 13:26:03 +00001056static constexpr create_type_func_ptr all_create_type_funcs[] = {
1057 ty_bool_, ty_u32, ty_i32, ty_f32,
1058 ty_vec3<bool>, ty_vec3<i32>, ty_vec3<u32>, ty_vec3<f32>,
1059 ty_mat3x3<i32>, ty_mat3x3<u32>, ty_mat3x3<f32>};
1060
1061// A list of all valid test cases for 'lhs op rhs', except that for vecN and
1062// matNxN, we only test N=3.
1063static constexpr Params all_valid_cases[] = {
1064 // Logical expressions
1065 // https://gpuweb.github.io/gpuweb/wgsl.html#logical-expr
1066
1067 // Binary logical expressions
1068 Params{Op::kLogicalAnd, ty_bool_, ty_bool_, ty_bool_},
1069 Params{Op::kLogicalOr, ty_bool_, ty_bool_, ty_bool_},
1070
1071 Params{Op::kAnd, ty_bool_, ty_bool_, ty_bool_},
1072 Params{Op::kOr, ty_bool_, ty_bool_, ty_bool_},
1073 Params{Op::kAnd, ty_vec3<bool>, ty_vec3<bool>, ty_vec3<bool>},
1074 Params{Op::kOr, ty_vec3<bool>, ty_vec3<bool>, ty_vec3<bool>},
1075
1076 // Arithmetic expressions
1077 // https://gpuweb.github.io/gpuweb/wgsl.html#arithmetic-expr
1078
1079 // Binary arithmetic expressions over scalars
1080 Params{Op::kAdd, ty_i32, ty_i32, ty_i32},
1081 Params{Op::kSubtract, ty_i32, ty_i32, ty_i32},
1082 Params{Op::kMultiply, ty_i32, ty_i32, ty_i32},
1083 Params{Op::kDivide, ty_i32, ty_i32, ty_i32},
1084 Params{Op::kModulo, ty_i32, ty_i32, ty_i32},
1085
1086 Params{Op::kAdd, ty_u32, ty_u32, ty_u32},
1087 Params{Op::kSubtract, ty_u32, ty_u32, ty_u32},
1088 Params{Op::kMultiply, ty_u32, ty_u32, ty_u32},
1089 Params{Op::kDivide, ty_u32, ty_u32, ty_u32},
1090 Params{Op::kModulo, ty_u32, ty_u32, ty_u32},
1091
1092 Params{Op::kAdd, ty_f32, ty_f32, ty_f32},
1093 Params{Op::kSubtract, ty_f32, ty_f32, ty_f32},
1094 Params{Op::kMultiply, ty_f32, ty_f32, ty_f32},
1095 Params{Op::kDivide, ty_f32, ty_f32, ty_f32},
1096 Params{Op::kModulo, ty_f32, ty_f32, ty_f32},
1097
1098 // Binary arithmetic expressions over vectors
1099 Params{Op::kAdd, ty_vec3<i32>, ty_vec3<i32>, ty_vec3<i32>},
1100 Params{Op::kSubtract, ty_vec3<i32>, ty_vec3<i32>, ty_vec3<i32>},
1101 Params{Op::kMultiply, ty_vec3<i32>, ty_vec3<i32>, ty_vec3<i32>},
1102 Params{Op::kDivide, ty_vec3<i32>, ty_vec3<i32>, ty_vec3<i32>},
1103 Params{Op::kModulo, ty_vec3<i32>, ty_vec3<i32>, ty_vec3<i32>},
1104
1105 Params{Op::kAdd, ty_vec3<u32>, ty_vec3<u32>, ty_vec3<u32>},
1106 Params{Op::kSubtract, ty_vec3<u32>, ty_vec3<u32>, ty_vec3<u32>},
1107 Params{Op::kMultiply, ty_vec3<u32>, ty_vec3<u32>, ty_vec3<u32>},
1108 Params{Op::kDivide, ty_vec3<u32>, ty_vec3<u32>, ty_vec3<u32>},
1109 Params{Op::kModulo, ty_vec3<u32>, ty_vec3<u32>, ty_vec3<u32>},
1110
1111 Params{Op::kAdd, ty_vec3<f32>, ty_vec3<f32>, ty_vec3<f32>},
1112 Params{Op::kSubtract, ty_vec3<f32>, ty_vec3<f32>, ty_vec3<f32>},
1113 Params{Op::kMultiply, ty_vec3<f32>, ty_vec3<f32>, ty_vec3<f32>},
1114 Params{Op::kDivide, ty_vec3<f32>, ty_vec3<f32>, ty_vec3<f32>},
1115 Params{Op::kModulo, ty_vec3<f32>, ty_vec3<f32>, ty_vec3<f32>},
1116
1117 // Binary arithmetic expressions with mixed scalar, vector, and matrix
1118 // operands
1119 Params{Op::kMultiply, ty_vec3<f32>, ty_f32, ty_vec3<f32>},
1120 Params{Op::kMultiply, ty_f32, ty_vec3<f32>, ty_vec3<f32>},
1121
1122 Params{Op::kMultiply, ty_mat3x3<f32>, ty_f32, ty_mat3x3<f32>},
1123 Params{Op::kMultiply, ty_f32, ty_mat3x3<f32>, ty_mat3x3<f32>},
1124
1125 Params{Op::kMultiply, ty_vec3<f32>, ty_mat3x3<f32>, ty_vec3<f32>},
1126 Params{Op::kMultiply, ty_mat3x3<f32>, ty_vec3<f32>, ty_vec3<f32>},
1127 Params{Op::kMultiply, ty_mat3x3<f32>, ty_mat3x3<f32>, ty_mat3x3<f32>},
1128
1129 // Comparison expressions
1130 // https://gpuweb.github.io/gpuweb/wgsl.html#comparison-expr
1131
1132 // Comparisons over scalars
1133 Params{Op::kEqual, ty_bool_, ty_bool_, ty_bool_},
1134 Params{Op::kNotEqual, ty_bool_, ty_bool_, ty_bool_},
1135
1136 Params{Op::kEqual, ty_i32, ty_i32, ty_bool_},
1137 Params{Op::kNotEqual, ty_i32, ty_i32, ty_bool_},
1138 Params{Op::kLessThan, ty_i32, ty_i32, ty_bool_},
1139 Params{Op::kLessThanEqual, ty_i32, ty_i32, ty_bool_},
1140 Params{Op::kGreaterThan, ty_i32, ty_i32, ty_bool_},
1141 Params{Op::kGreaterThanEqual, ty_i32, ty_i32, ty_bool_},
1142
1143 Params{Op::kEqual, ty_u32, ty_u32, ty_bool_},
1144 Params{Op::kNotEqual, ty_u32, ty_u32, ty_bool_},
1145 Params{Op::kLessThan, ty_u32, ty_u32, ty_bool_},
1146 Params{Op::kLessThanEqual, ty_u32, ty_u32, ty_bool_},
1147 Params{Op::kGreaterThan, ty_u32, ty_u32, ty_bool_},
1148 Params{Op::kGreaterThanEqual, ty_u32, ty_u32, ty_bool_},
1149
1150 Params{Op::kEqual, ty_f32, ty_f32, ty_bool_},
1151 Params{Op::kNotEqual, ty_f32, ty_f32, ty_bool_},
1152 Params{Op::kLessThan, ty_f32, ty_f32, ty_bool_},
1153 Params{Op::kLessThanEqual, ty_f32, ty_f32, ty_bool_},
1154 Params{Op::kGreaterThan, ty_f32, ty_f32, ty_bool_},
1155 Params{Op::kGreaterThanEqual, ty_f32, ty_f32, ty_bool_},
1156
1157 // Comparisons over vectors
1158 Params{Op::kEqual, ty_vec3<bool>, ty_vec3<bool>, ty_vec3<bool>},
1159 Params{Op::kNotEqual, ty_vec3<bool>, ty_vec3<bool>, ty_vec3<bool>},
1160
1161 Params{Op::kEqual, ty_vec3<i32>, ty_vec3<i32>, ty_vec3<bool>},
1162 Params{Op::kNotEqual, ty_vec3<i32>, ty_vec3<i32>, ty_vec3<bool>},
1163 Params{Op::kLessThan, ty_vec3<i32>, ty_vec3<i32>, ty_vec3<bool>},
1164 Params{Op::kLessThanEqual, ty_vec3<i32>, ty_vec3<i32>, ty_vec3<bool>},
1165 Params{Op::kGreaterThan, ty_vec3<i32>, ty_vec3<i32>, ty_vec3<bool>},
1166 Params{Op::kGreaterThanEqual, ty_vec3<i32>, ty_vec3<i32>, ty_vec3<bool>},
1167
1168 Params{Op::kEqual, ty_vec3<u32>, ty_vec3<u32>, ty_vec3<bool>},
1169 Params{Op::kNotEqual, ty_vec3<u32>, ty_vec3<u32>, ty_vec3<bool>},
1170 Params{Op::kLessThan, ty_vec3<u32>, ty_vec3<u32>, ty_vec3<bool>},
1171 Params{Op::kLessThanEqual, ty_vec3<u32>, ty_vec3<u32>, ty_vec3<bool>},
1172 Params{Op::kGreaterThan, ty_vec3<u32>, ty_vec3<u32>, ty_vec3<bool>},
1173 Params{Op::kGreaterThanEqual, ty_vec3<u32>, ty_vec3<u32>, ty_vec3<bool>},
1174
1175 Params{Op::kEqual, ty_vec3<f32>, ty_vec3<f32>, ty_vec3<bool>},
1176 Params{Op::kNotEqual, ty_vec3<f32>, ty_vec3<f32>, ty_vec3<bool>},
1177 Params{Op::kLessThan, ty_vec3<f32>, ty_vec3<f32>, ty_vec3<bool>},
1178 Params{Op::kLessThanEqual, ty_vec3<f32>, ty_vec3<f32>, ty_vec3<bool>},
1179 Params{Op::kGreaterThan, ty_vec3<f32>, ty_vec3<f32>, ty_vec3<bool>},
1180 Params{Op::kGreaterThanEqual, ty_vec3<f32>, ty_vec3<f32>, ty_vec3<bool>},
1181
1182 // Bit expressions
1183 // https://gpuweb.github.io/gpuweb/wgsl.html#bit-expr
1184
1185 // Binary bitwise operations
1186 Params{Op::kOr, ty_i32, ty_i32, ty_i32},
1187 Params{Op::kAnd, ty_i32, ty_i32, ty_i32},
1188 Params{Op::kXor, ty_i32, ty_i32, ty_i32},
1189
1190 Params{Op::kOr, ty_u32, ty_u32, ty_u32},
1191 Params{Op::kAnd, ty_u32, ty_u32, ty_u32},
1192 Params{Op::kXor, ty_u32, ty_u32, ty_u32},
1193
1194 // Bit shift expressions
1195 Params{Op::kShiftLeft, ty_i32, ty_u32, ty_i32},
1196 Params{Op::kShiftLeft, ty_vec3<i32>, ty_vec3<u32>, ty_vec3<i32>},
1197
1198 Params{Op::kShiftLeft, ty_u32, ty_u32, ty_u32},
1199 Params{Op::kShiftLeft, ty_vec3<u32>, ty_vec3<u32>, ty_vec3<u32>},
1200
1201 Params{Op::kShiftRight, ty_i32, ty_u32, ty_i32},
1202 Params{Op::kShiftRight, ty_vec3<i32>, ty_vec3<u32>, ty_vec3<i32>},
1203
1204 Params{Op::kShiftRight, ty_u32, ty_u32, ty_u32},
1205 Params{Op::kShiftRight, ty_vec3<u32>, ty_vec3<u32>, ty_vec3<u32>}};
1206
1207using Expr_Binary_Test_Valid = ResolverTestWithParam<Params>;
1208TEST_P(Expr_Binary_Test_Valid, All) {
1209 auto& params = GetParam();
1210
1211 auto* lhs_type = params.create_lhs_type(ty);
1212 auto* rhs_type = params.create_rhs_type(ty);
1213 auto* result_type = params.create_result_type(ty);
1214
Antonio Maiorano15c6ed02021-04-01 14:59:27 +00001215 std::stringstream ss;
1216 ss << lhs_type->FriendlyName(Symbols()) << " " << params.op << " "
1217 << rhs_type->FriendlyName(Symbols());
1218 SCOPED_TRACE(ss.str());
1219
Antonio Maioranobbbb0ed2021-04-06 20:18:57 +00001220 Global("lhs", lhs_type, ast::StorageClass::kInput);
1221 Global("rhs", rhs_type, ast::StorageClass::kInput);
Antonio Maioranobe0fc4e2021-03-16 13:26:03 +00001222
1223 auto* expr =
1224 create<ast::BinaryExpression>(params.op, Expr("lhs"), Expr("rhs"));
Ben Clayton401b96b2021-02-03 17:19:59 +00001225 WrapInFunction(expr);
dan sinclair9b978022020-04-07 19:26:39 +00001226
Ben Clayton5f0ea112021-03-09 10:54:37 +00001227 ASSERT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton33352542021-01-29 16:43:41 +00001228 ASSERT_NE(TypeOf(expr), nullptr);
Antonio Maioranobe0fc4e2021-03-16 13:26:03 +00001229 ASSERT_TRUE(TypeOf(expr) == result_type);
dan sinclair9b978022020-04-07 19:26:39 +00001230}
Ben Clayton5f0ea112021-03-09 10:54:37 +00001231INSTANTIATE_TEST_SUITE_P(ResolverTest,
Antonio Maioranobe0fc4e2021-03-16 13:26:03 +00001232 Expr_Binary_Test_Valid,
1233 testing::ValuesIn(all_valid_cases));
dan sinclair9b978022020-04-07 19:26:39 +00001234
Antonio Maiorano15c6ed02021-04-01 14:59:27 +00001235enum class BinaryExprSide { Left, Right, Both };
1236using Expr_Binary_Test_WithAlias_Valid =
1237 ResolverTestWithParam<std::tuple<Params, BinaryExprSide>>;
1238TEST_P(Expr_Binary_Test_WithAlias_Valid, All) {
1239 const Params& params = std::get<0>(GetParam());
1240 BinaryExprSide side = std::get<1>(GetParam());
1241
1242 auto* lhs_type = params.create_lhs_type(ty);
1243 auto* rhs_type = params.create_rhs_type(ty);
1244
1245 std::stringstream ss;
1246 ss << lhs_type->FriendlyName(Symbols()) << " " << params.op << " "
1247 << rhs_type->FriendlyName(Symbols());
1248
1249 // For vectors and matrices, wrap the sub type in an alias
1250 auto make_alias = [this](type::Type* type) -> type::Type* {
1251 type::Type* result;
1252 if (auto* v = type->As<type::Vector>()) {
1253 result = create<type::Vector>(
1254 create<type::Alias>(Symbols().New(), v->type()), v->size());
1255 } else if (auto* m = type->As<type::Matrix>()) {
1256 result =
1257 create<type::Matrix>(create<type::Alias>(Symbols().New(), m->type()),
1258 m->rows(), m->columns());
1259 } else {
1260 result = create<type::Alias>(Symbols().New(), type);
1261 }
1262 return result;
1263 };
1264
1265 // Wrap in alias
1266 if (side == BinaryExprSide::Left || side == BinaryExprSide::Both) {
1267 lhs_type = make_alias(lhs_type);
1268 }
1269 if (side == BinaryExprSide::Right || side == BinaryExprSide::Both) {
1270 rhs_type = make_alias(rhs_type);
1271 }
1272
1273 ss << ", After aliasing: " << lhs_type->FriendlyName(Symbols()) << " "
1274 << params.op << " " << rhs_type->FriendlyName(Symbols());
1275 SCOPED_TRACE(ss.str());
1276
Antonio Maioranobbbb0ed2021-04-06 20:18:57 +00001277 Global("lhs", lhs_type, ast::StorageClass::kInput);
1278 Global("rhs", rhs_type, ast::StorageClass::kInput);
Antonio Maiorano15c6ed02021-04-01 14:59:27 +00001279
1280 auto* expr =
1281 create<ast::BinaryExpression>(params.op, Expr("lhs"), Expr("rhs"));
1282 WrapInFunction(expr);
1283
1284 ASSERT_TRUE(r()->Resolve()) << r()->error();
1285 ASSERT_NE(TypeOf(expr), nullptr);
1286 // TODO(amaiorano): Bring this back once we have a way to get the canonical
1287 // type
1288 // auto* result_type = params.create_result_type(ty);
1289 // ASSERT_TRUE(TypeOf(expr) == result_type);
1290}
1291INSTANTIATE_TEST_SUITE_P(
1292 ResolverTest,
1293 Expr_Binary_Test_WithAlias_Valid,
1294 testing::Combine(testing::ValuesIn(all_valid_cases),
1295 testing::Values(BinaryExprSide::Left,
1296 BinaryExprSide::Right,
1297 BinaryExprSide::Both)));
1298
Antonio Maioranobe0fc4e2021-03-16 13:26:03 +00001299using Expr_Binary_Test_Invalid =
1300 ResolverTestWithParam<std::tuple<Params, create_type_func_ptr>>;
1301TEST_P(Expr_Binary_Test_Invalid, All) {
1302 const Params& params = std::get<0>(GetParam());
1303 const create_type_func_ptr& create_type_func = std::get<1>(GetParam());
dan sinclair9b978022020-04-07 19:26:39 +00001304
Antonio Maioranobe0fc4e2021-03-16 13:26:03 +00001305 // Currently, for most operations, for a given lhs type, there is exactly one
1306 // rhs type allowed. The only exception is for multiplication, which allows
1307 // any permutation of f32, vecN<f32>, and matNxN<f32>. We are fed valid inputs
1308 // only via `params`, and all possible types via `create_type_func`, so we
1309 // test invalid combinations by testing every other rhs type, modulo
1310 // exceptions.
dan sinclair9b978022020-04-07 19:26:39 +00001311
Antonio Maioranobe0fc4e2021-03-16 13:26:03 +00001312 // Skip valid rhs type
1313 if (params.create_rhs_type == create_type_func) {
1314 return;
1315 }
1316
1317 auto* lhs_type = params.create_lhs_type(ty);
1318 auto* rhs_type = create_type_func(ty);
1319
1320 // Skip exceptions: multiplication of f32, vecN<f32>, and matNxN<f32>
1321 if (params.op == Op::kMultiply &&
1322 lhs_type->is_float_scalar_or_vector_or_matrix() &&
1323 rhs_type->is_float_scalar_or_vector_or_matrix()) {
1324 return;
1325 }
1326
Antonio Maiorano15c6ed02021-04-01 14:59:27 +00001327 std::stringstream ss;
1328 ss << lhs_type->FriendlyName(Symbols()) << " " << params.op << " "
1329 << rhs_type->FriendlyName(Symbols());
1330 SCOPED_TRACE(ss.str());
1331
Antonio Maioranobbbb0ed2021-04-06 20:18:57 +00001332 Global("lhs", lhs_type, ast::StorageClass::kInput);
1333 Global("rhs", rhs_type, ast::StorageClass::kInput);
Antonio Maioranobe0fc4e2021-03-16 13:26:03 +00001334
Antonio Maiorano61dabab2021-04-01 19:58:37 +00001335 auto* expr = create<ast::BinaryExpression>(Source{{12, 34}}, params.op,
1336 Expr("lhs"), Expr("rhs"));
Ben Clayton401b96b2021-02-03 17:19:59 +00001337 WrapInFunction(expr);
dan sinclair9b978022020-04-07 19:26:39 +00001338
Antonio Maiorano61dabab2021-04-01 19:58:37 +00001339 ASSERT_FALSE(r()->Resolve());
Antonio Maioranobe0fc4e2021-03-16 13:26:03 +00001340 ASSERT_EQ(r()->error(),
1341 "12:34 error: Binary expression operand types are invalid for "
Antonio Maioranof1b643e2021-04-01 19:40:37 +00001342 "this operation: " +
1343 lhs_type->FriendlyName(Symbols()) + " " +
1344 FriendlyName(expr->op()) + " " +
1345 rhs_type->FriendlyName(Symbols()));
dan sinclair9b978022020-04-07 19:26:39 +00001346}
Antonio Maioranobe0fc4e2021-03-16 13:26:03 +00001347INSTANTIATE_TEST_SUITE_P(
1348 ResolverTest,
1349 Expr_Binary_Test_Invalid,
1350 testing::Combine(testing::ValuesIn(all_valid_cases),
1351 testing::ValuesIn(all_create_type_funcs)));
Antonio Maiorano61dabab2021-04-01 19:58:37 +00001352
1353using Expr_Binary_Test_Invalid_VectorMatrixMultiply =
1354 ResolverTestWithParam<std::tuple<bool, uint32_t, uint32_t, uint32_t>>;
1355TEST_P(Expr_Binary_Test_Invalid_VectorMatrixMultiply, All) {
1356 bool vec_by_mat = std::get<0>(GetParam());
1357 uint32_t vec_size = std::get<1>(GetParam());
1358 uint32_t mat_rows = std::get<2>(GetParam());
1359 uint32_t mat_cols = std::get<3>(GetParam());
1360
1361 type::Type* lhs_type;
1362 type::Type* rhs_type;
1363 type::Type* result_type;
1364 bool is_valid_expr;
1365
1366 if (vec_by_mat) {
1367 lhs_type = create<type::Vector>(ty.f32(), vec_size);
1368 rhs_type = create<type::Matrix>(ty.f32(), mat_rows, mat_cols);
1369 result_type = create<type::Vector>(ty.f32(), mat_cols);
1370 is_valid_expr = vec_size == mat_rows;
1371 } else {
1372 lhs_type = create<type::Matrix>(ty.f32(), mat_rows, mat_cols);
1373 rhs_type = create<type::Vector>(ty.f32(), vec_size);
1374 result_type = create<type::Vector>(ty.f32(), mat_rows);
1375 is_valid_expr = vec_size == mat_cols;
1376 }
1377
Antonio Maioranobbbb0ed2021-04-06 20:18:57 +00001378 Global("lhs", lhs_type, ast::StorageClass::kInput);
1379 Global("rhs", rhs_type, ast::StorageClass::kInput);
Antonio Maiorano61dabab2021-04-01 19:58:37 +00001380
1381 auto* expr = Mul(Source{{12, 34}}, Expr("lhs"), Expr("rhs"));
1382 WrapInFunction(expr);
1383
1384 if (is_valid_expr) {
1385 ASSERT_TRUE(r()->Resolve()) << r()->error();
1386 ASSERT_TRUE(TypeOf(expr) == result_type);
1387 } else {
1388 ASSERT_FALSE(r()->Resolve());
1389 ASSERT_EQ(r()->error(),
1390 "12:34 error: Binary expression operand types are invalid for "
1391 "this operation: " +
1392 lhs_type->FriendlyName(Symbols()) + " " +
1393 FriendlyName(expr->op()) + " " +
1394 rhs_type->FriendlyName(Symbols()));
1395 }
1396}
1397auto all_dimension_values = testing::Values(2u, 3u, 4u);
1398INSTANTIATE_TEST_SUITE_P(ResolverTest,
1399 Expr_Binary_Test_Invalid_VectorMatrixMultiply,
1400 testing::Combine(testing::Values(true, false),
1401 all_dimension_values,
1402 all_dimension_values,
1403 all_dimension_values));
1404
1405using Expr_Binary_Test_Invalid_MatrixMatrixMultiply =
1406 ResolverTestWithParam<std::tuple<uint32_t, uint32_t, uint32_t, uint32_t>>;
1407TEST_P(Expr_Binary_Test_Invalid_MatrixMatrixMultiply, All) {
1408 uint32_t lhs_mat_rows = std::get<0>(GetParam());
1409 uint32_t lhs_mat_cols = std::get<1>(GetParam());
1410 uint32_t rhs_mat_rows = std::get<2>(GetParam());
1411 uint32_t rhs_mat_cols = std::get<3>(GetParam());
1412
1413 auto* lhs_type = create<type::Matrix>(ty.f32(), lhs_mat_rows, lhs_mat_cols);
1414 auto* rhs_type = create<type::Matrix>(ty.f32(), rhs_mat_rows, rhs_mat_cols);
1415 auto* result_type =
1416 create<type::Matrix>(ty.f32(), lhs_mat_rows, rhs_mat_cols);
1417
Antonio Maioranobbbb0ed2021-04-06 20:18:57 +00001418 Global("lhs", lhs_type, ast::StorageClass::kInput);
1419 Global("rhs", rhs_type, ast::StorageClass::kInput);
Antonio Maiorano61dabab2021-04-01 19:58:37 +00001420
1421 auto* expr = Mul(Source{{12, 34}}, Expr("lhs"), Expr("rhs"));
1422 WrapInFunction(expr);
1423
1424 bool is_valid_expr = lhs_mat_cols == rhs_mat_rows;
1425 if (is_valid_expr) {
1426 ASSERT_TRUE(r()->Resolve()) << r()->error();
1427 ASSERT_TRUE(TypeOf(expr) == result_type);
1428 } else {
1429 ASSERT_FALSE(r()->Resolve());
1430 ASSERT_EQ(r()->error(),
1431 "12:34 error: Binary expression operand types are invalid for "
1432 "this operation: " +
1433 lhs_type->FriendlyName(Symbols()) + " " +
1434 FriendlyName(expr->op()) + " " +
1435 rhs_type->FriendlyName(Symbols()));
1436 }
1437}
1438INSTANTIATE_TEST_SUITE_P(ResolverTest,
1439 Expr_Binary_Test_Invalid_MatrixMatrixMultiply,
1440 testing::Combine(all_dimension_values,
1441 all_dimension_values,
1442 all_dimension_values,
1443 all_dimension_values));
1444
Antonio Maioranobe0fc4e2021-03-16 13:26:03 +00001445} // namespace ExprBinaryTest
dan sinclair9b978022020-04-07 19:26:39 +00001446
Ben Clayton5f0ea112021-03-09 10:54:37 +00001447using UnaryOpExpressionTest = ResolverTestWithParam<ast::UnaryOp>;
dan sinclair0e257622020-04-07 19:27:11 +00001448TEST_P(UnaryOpExpressionTest, Expr_UnaryOp) {
1449 auto op = GetParam();
1450
Antonio Maioranobbbb0ed2021-04-06 20:18:57 +00001451 Global("ident", ty.vec4<f32>(), ast::StorageClass::kInput);
Ben Clayton7eaf4b52020-12-14 22:08:27 +00001452 auto* der = create<ast::UnaryOpExpression>(op, Expr("ident"));
Ben Clayton401b96b2021-02-03 17:19:59 +00001453 WrapInFunction(der);
1454
Ben Clayton5f0ea112021-03-09 10:54:37 +00001455 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton401b96b2021-02-03 17:19:59 +00001456
Ben Clayton33352542021-01-29 16:43:41 +00001457 ASSERT_NE(TypeOf(der), nullptr);
1458 ASSERT_TRUE(TypeOf(der)->Is<type::Vector>());
1459 EXPECT_TRUE(TypeOf(der)->As<type::Vector>()->type()->Is<type::F32>());
1460 EXPECT_EQ(TypeOf(der)->As<type::Vector>()->size(), 4u);
dan sinclair0e257622020-04-07 19:27:11 +00001461}
Ben Clayton5f0ea112021-03-09 10:54:37 +00001462INSTANTIATE_TEST_SUITE_P(ResolverTest,
dan sinclair0e257622020-04-07 19:27:11 +00001463 UnaryOpExpressionTest,
1464 testing::Values(ast::UnaryOp::kNegation,
1465 ast::UnaryOp::kNot));
1466
Ben Clayton5f0ea112021-03-09 10:54:37 +00001467TEST_F(ResolverTest, StorageClass_SetsIfMissing) {
Ben Clayton37571bc2021-02-16 23:57:01 +00001468 auto* var = Var("var", ty.i32(), ast::StorageClass::kNone);
dan sinclairee8ae042020-04-08 19:58:20 +00001469
Ben Clayton7eaf4b52020-12-14 22:08:27 +00001470 auto* stmt = create<ast::VariableDeclStatement>(var);
Antonio Maiorano03c01b52021-03-19 14:04:51 +00001471 Func("func", ast::VariableList{}, ty.void_(), ast::StatementList{stmt},
James Price95d40772021-03-11 17:39:32 +00001472 ast::DecorationList{});
dan sinclairee8ae042020-04-08 19:58:20 +00001473
Ben Clayton5f0ea112021-03-09 10:54:37 +00001474 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton401b96b2021-02-03 17:19:59 +00001475
Ben Claytonb17aea12021-02-03 17:51:09 +00001476 EXPECT_EQ(Sem().Get(var)->StorageClass(), ast::StorageClass::kFunction);
dan sinclairee8ae042020-04-08 19:58:20 +00001477}
1478
Ben Clayton5f0ea112021-03-09 10:54:37 +00001479TEST_F(ResolverTest, StorageClass_DoesNotSetOnConst) {
Ben Clayton81a29fe2021-02-17 00:26:52 +00001480 auto* var = Const("var", ty.i32());
Ben Clayton7eaf4b52020-12-14 22:08:27 +00001481 auto* stmt = create<ast::VariableDeclStatement>(var);
Antonio Maiorano03c01b52021-03-19 14:04:51 +00001482 Func("func", ast::VariableList{}, ty.void_(), ast::StatementList{stmt},
James Price95d40772021-03-11 17:39:32 +00001483 ast::DecorationList{});
dan sinclairee8ae042020-04-08 19:58:20 +00001484
Ben Clayton5f0ea112021-03-09 10:54:37 +00001485 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton401b96b2021-02-03 17:19:59 +00001486
Ben Claytonb17aea12021-02-03 17:51:09 +00001487 EXPECT_EQ(Sem().Get(var)->StorageClass(), ast::StorageClass::kNone);
dan sinclairee8ae042020-04-08 19:58:20 +00001488}
1489
Ben Clayton5f0ea112021-03-09 10:54:37 +00001490TEST_F(ResolverTest, Function_EntryPoints_StageDecoration) {
dan sinclair05926432020-09-21 17:51:31 +00001491 // fn b() {}
1492 // fn c() { b(); }
1493 // fn a() { c(); }
1494 // fn ep_1() { a(); b(); }
1495 // fn ep_2() { c();}
1496 //
1497 // c -> {ep_1, ep_2}
1498 // a -> {ep_1}
1499 // b -> {ep_1, ep_2}
1500 // ep_1 -> {}
1501 // ep_2 -> {}
1502
Antonio Maioranobb5617f2021-03-19 18:45:30 +00001503 Global("first", ty.f32(), ast::StorageClass::kPrivate);
1504 Global("second", ty.f32(), ast::StorageClass::kPrivate);
1505 Global("call_a", ty.f32(), ast::StorageClass::kPrivate);
1506 Global("call_b", ty.f32(), ast::StorageClass::kPrivate);
1507 Global("call_c", ty.f32(), ast::StorageClass::kPrivate);
1508
dan sinclair05926432020-09-21 17:51:31 +00001509 ast::VariableList params;
James Price95d40772021-03-11 17:39:32 +00001510 auto* func_b =
Antonio Maiorano03c01b52021-03-19 14:04:51 +00001511 Func("b", params, ty.f32(), ast::StatementList{Return(Expr(0.0f))},
James Price95d40772021-03-11 17:39:32 +00001512 ast::DecorationList{});
Antonio Maiorano03c01b52021-03-19 14:04:51 +00001513 auto* func_c = Func("c", params, ty.f32(),
1514 ast::StatementList{create<ast::AssignmentStatement>(
1515 Expr("second"), Call("b")),
1516 Return(Expr(0.0f))},
1517 ast::DecorationList{});
dan sinclair05926432020-09-21 17:51:31 +00001518
Antonio Maiorano03c01b52021-03-19 14:04:51 +00001519 auto* func_a = Func("a", params, ty.f32(),
1520 ast::StatementList{create<ast::AssignmentStatement>(
1521 Expr("first"), Call("c")),
1522 Return(Expr(0.0f))},
1523 ast::DecorationList{});
dan sinclair05926432020-09-21 17:51:31 +00001524
dan sinclair181d8ba2020-12-16 15:15:40 +00001525 auto* ep_1 =
Antonio Maiorano03c01b52021-03-19 14:04:51 +00001526 Func("ep_1", params, ty.void_(),
dan sinclair181d8ba2020-12-16 15:15:40 +00001527 ast::StatementList{
1528 create<ast::AssignmentStatement>(Expr("call_a"), Call("a")),
1529 create<ast::AssignmentStatement>(Expr("call_b"), Call("b")),
1530 },
James Price95d40772021-03-11 17:39:32 +00001531 ast::DecorationList{
dan sinclair181d8ba2020-12-16 15:15:40 +00001532 create<ast::StageDecoration>(ast::PipelineStage::kVertex),
1533 });
Ben Clayton7eaf4b52020-12-14 22:08:27 +00001534
dan sinclair181d8ba2020-12-16 15:15:40 +00001535 auto* ep_2 =
Antonio Maiorano03c01b52021-03-19 14:04:51 +00001536 Func("ep_2", params, ty.void_(),
dan sinclair181d8ba2020-12-16 15:15:40 +00001537 ast::StatementList{
1538 create<ast::AssignmentStatement>(Expr("call_c"), Call("c")),
1539 },
James Price95d40772021-03-11 17:39:32 +00001540 ast::DecorationList{
dan sinclair181d8ba2020-12-16 15:15:40 +00001541 create<ast::StageDecoration>(ast::PipelineStage::kVertex),
1542 });
dan sinclair05926432020-09-21 17:51:31 +00001543
Ben Clayton5f0ea112021-03-09 10:54:37 +00001544 ASSERT_TRUE(r()->Resolve()) << r()->error();
dan sinclair05926432020-09-21 17:51:31 +00001545
Ben Clayton87c78dd2021-02-03 16:43:20 +00001546 auto* func_b_sem = Sem().Get(func_b);
1547 auto* func_a_sem = Sem().Get(func_a);
1548 auto* func_c_sem = Sem().Get(func_c);
1549 auto* ep_1_sem = Sem().Get(ep_1);
1550 auto* ep_2_sem = Sem().Get(ep_2);
1551 ASSERT_NE(func_b_sem, nullptr);
1552 ASSERT_NE(func_a_sem, nullptr);
1553 ASSERT_NE(func_c_sem, nullptr);
1554 ASSERT_NE(ep_1_sem, nullptr);
1555 ASSERT_NE(ep_2_sem, nullptr);
1556
Ben Claytone9c49842021-04-09 13:56:08 +00001557 EXPECT_EQ(func_b_sem->Parameters().size(), 0u);
1558 EXPECT_EQ(func_a_sem->Parameters().size(), 0u);
1559 EXPECT_EQ(func_c_sem->Parameters().size(), 0u);
1560
Ben Clayton87c78dd2021-02-03 16:43:20 +00001561 const auto& b_eps = func_b_sem->AncestorEntryPoints();
dan sinclair05926432020-09-21 17:51:31 +00001562 ASSERT_EQ(2u, b_eps.size());
Ben Clayton1f7e18b2021-01-26 16:57:10 +00001563 EXPECT_EQ(Symbols().Register("ep_1"), b_eps[0]);
1564 EXPECT_EQ(Symbols().Register("ep_2"), b_eps[1]);
dan sinclair05926432020-09-21 17:51:31 +00001565
Ben Clayton87c78dd2021-02-03 16:43:20 +00001566 const auto& a_eps = func_a_sem->AncestorEntryPoints();
dan sinclair05926432020-09-21 17:51:31 +00001567 ASSERT_EQ(1u, a_eps.size());
Ben Clayton1f7e18b2021-01-26 16:57:10 +00001568 EXPECT_EQ(Symbols().Register("ep_1"), a_eps[0]);
dan sinclair05926432020-09-21 17:51:31 +00001569
Ben Clayton87c78dd2021-02-03 16:43:20 +00001570 const auto& c_eps = func_c_sem->AncestorEntryPoints();
dan sinclair05926432020-09-21 17:51:31 +00001571 ASSERT_EQ(2u, c_eps.size());
Ben Clayton1f7e18b2021-01-26 16:57:10 +00001572 EXPECT_EQ(Symbols().Register("ep_1"), c_eps[0]);
1573 EXPECT_EQ(Symbols().Register("ep_2"), c_eps[1]);
dan sinclair05926432020-09-21 17:51:31 +00001574
Ben Clayton87c78dd2021-02-03 16:43:20 +00001575 EXPECT_TRUE(ep_1_sem->AncestorEntryPoints().empty());
1576 EXPECT_TRUE(ep_2_sem->AncestorEntryPoints().empty());
dan sinclair05926432020-09-21 17:51:31 +00001577}
1578
Ben Clayton5a132582021-03-03 19:54:44 +00001579// Check for linear-time traversal of functions reachable from entry points.
1580// See: crbug.com/tint/245
Ben Clayton5f0ea112021-03-09 10:54:37 +00001581TEST_F(ResolverTest, Function_EntryPoints_LinearTime) {
Ben Clayton5a132582021-03-03 19:54:44 +00001582 // fn lNa() { }
1583 // fn lNb() { }
1584 // ...
1585 // fn l2a() { l3a(); l3b(); }
1586 // fn l2b() { l3a(); l3b(); }
1587 // fn l1a() { l2a(); l2b(); }
1588 // fn l1b() { l2a(); l2b(); }
1589 // fn main() { l1a(); l1b(); }
1590
1591 static constexpr int levels = 64;
1592
1593 auto fn_a = [](int level) { return "l" + std::to_string(level + 1) + "a"; };
1594 auto fn_b = [](int level) { return "l" + std::to_string(level + 1) + "b"; };
1595
1596 Func(fn_a(levels), {}, ty.void_(), {}, {});
1597 Func(fn_b(levels), {}, ty.void_(), {}, {});
1598
1599 for (int i = levels - 1; i >= 0; i--) {
1600 Func(fn_a(i), {}, ty.void_(),
1601 {
1602 create<ast::CallStatement>(Call(fn_a(i + 1))),
1603 create<ast::CallStatement>(Call(fn_b(i + 1))),
1604 },
1605 {});
1606 Func(fn_b(i), {}, ty.void_(),
1607 {
1608 create<ast::CallStatement>(Call(fn_a(i + 1))),
1609 create<ast::CallStatement>(Call(fn_b(i + 1))),
1610 },
1611 {});
1612 }
1613
1614 Func("main", {}, ty.void_(),
1615 {
1616 create<ast::CallStatement>(Call(fn_a(0))),
1617 create<ast::CallStatement>(Call(fn_b(0))),
1618 },
1619 {
1620 create<ast::StageDecoration>(ast::PipelineStage::kVertex),
1621 });
1622
Ben Clayton5f0ea112021-03-09 10:54:37 +00001623 ASSERT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton5a132582021-03-03 19:54:44 +00001624}
1625
Ben Clayton6fcefe42021-04-19 19:16:12 +00001626TEST_F(ResolverTest, ASTNodeNotReached) {
1627 EXPECT_FATAL_FAILURE(
1628 {
1629 ProgramBuilder builder;
1630 builder.Expr("1");
1631 Resolver(&builder).Resolve();
1632 },
1633 "internal compiler error: AST node 'tint::ast::IdentifierExpression' was "
1634 "not reached by the resolver");
1635}
1636
1637TEST_F(ResolverTest, ASTNodeReachedTwice) {
1638 EXPECT_FATAL_FAILURE(
1639 {
1640 ProgramBuilder builder;
1641 auto* expr = builder.Expr("1");
1642 auto* usesExprTwice = builder.Add(expr, expr);
1643 builder.Global("g", builder.ty.i32(), ast::StorageClass::kPrivate,
1644 usesExprTwice);
1645 Resolver(&builder).Resolve();
1646 },
1647 "internal compiler error: AST node 'tint::ast::IdentifierExpression' was "
1648 "encountered twice in the same AST of a Program");
1649}
1650
dan sinclairb7edc4c2020-04-07 12:46:30 +00001651} // namespace
Ben Claytonc7dcbae2021-03-09 15:08:48 +00001652} // namespace resolver
dan sinclairb7edc4c2020-04-07 12:46:30 +00001653} // namespace tint