blob: 38e7d62a8e6cc7a038b78e61539bc218b656820f [file] [log] [blame]
James Pricedfd17142021-02-10 15:34:37 +00001// Copyright 2021 The Tint Authors.
dan sinclaird9e9ff32020-03-12 12:40:01 +00002//
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/writer/wgsl/generator_impl.h"
16
Ben Clayton22a9f172021-02-10 16:41:23 +000017#include <algorithm>
dan sinclaird9e9ff32020-03-12 12:40:01 +000018
Ben Clayton93e8f522021-06-04 20:41:47 +000019#include "src/ast/access.h"
Ben Clayton083b5912021-04-30 16:01:29 +000020#include "src/ast/alias.h"
21#include "src/ast/array.h"
Ben Clayton0a32a722021-06-18 18:56:13 +000022#include "src/ast/atomic.h"
Ben Clayton083b5912021-04-30 16:01:29 +000023#include "src/ast/bool.h"
dan sinclair9d9d7cd2020-03-18 20:05:44 +000024#include "src/ast/bool_literal.h"
dan sinclairb44fe3c2020-07-21 13:44:27 +000025#include "src/ast/call_statement.h"
Ben Clayton083b5912021-04-30 16:01:29 +000026#include "src/ast/depth_texture.h"
Ben Claytonf5163d02021-06-02 20:12:34 +000027#include "src/ast/external_texture.h"
Ben Clayton083b5912021-04-30 16:01:29 +000028#include "src/ast/f32.h"
dan sinclair9d9d7cd2020-03-18 20:05:44 +000029#include "src/ast/float_literal.h"
Ben Clayton083b5912021-04-30 16:01:29 +000030#include "src/ast/i32.h"
Ben Claytonb502fdf2021-04-07 08:09:21 +000031#include "src/ast/internal_decoration.h"
James Price545f4e02021-06-28 23:04:43 +000032#include "src/ast/interpolate_decoration.h"
James Pricefcc0de02021-07-12 12:28:52 +000033#include "src/ast/invariant_decoration.h"
Ben Clayton083b5912021-04-30 16:01:29 +000034#include "src/ast/matrix.h"
Ben Claytona6b9a8e2021-01-26 16:57:10 +000035#include "src/ast/module.h"
Ben Clayton083b5912021-04-30 16:01:29 +000036#include "src/ast/multisampled_texture.h"
James Pricee87ded82021-04-30 17:14:19 +000037#include "src/ast/override_decoration.h"
Ben Clayton083b5912021-04-30 16:01:29 +000038#include "src/ast/pointer.h"
39#include "src/ast/sampled_texture.h"
dan sinclairc6f29472020-06-02 20:11:44 +000040#include "src/ast/sint_literal.h"
dan sinclair48d08d22020-09-21 17:59:51 +000041#include "src/ast/stage_decoration.h"
Ben Clayton083b5912021-04-30 16:01:29 +000042#include "src/ast/storage_texture.h"
dan sinclaireb5d3e12020-10-08 19:34:25 +000043#include "src/ast/stride_decoration.h"
Ben Clayton688fe442021-05-13 12:38:12 +000044#include "src/ast/struct_block_decoration.h"
Ben Claytond614dd52021-03-15 10:43:11 +000045#include "src/ast/struct_member_align_decoration.h"
dan sinclaird9e9ff32020-03-12 12:40:01 +000046#include "src/ast/struct_member_offset_decoration.h"
Ben Claytond614dd52021-03-15 10:43:11 +000047#include "src/ast/struct_member_size_decoration.h"
Ben Clayton083b5912021-04-30 16:01:29 +000048#include "src/ast/type_name.h"
49#include "src/ast/u32.h"
dan sinclair9d9d7cd2020-03-18 20:05:44 +000050#include "src/ast/uint_literal.h"
dan sinclaire49bd5e2020-03-30 22:46:48 +000051#include "src/ast/variable_decl_statement.h"
Ben Clayton083b5912021-04-30 16:01:29 +000052#include "src/ast/vector.h"
53#include "src/ast/void.h"
dan sinclair64382792020-09-21 00:28:58 +000054#include "src/ast/workgroup_decoration.h"
Antonio Maiorano5cd71b82021-04-16 19:07:51 +000055#include "src/sem/struct.h"
Ben Clayton822fa542021-03-15 20:25:12 +000056#include "src/utils/math.h"
Ben Claytone1f30f12021-07-02 22:17:25 +000057#include "src/utils/scoped_assignment.h"
Ben Clayton2da833d2020-11-20 10:04:44 +000058#include "src/writer/float_to_string.h"
dan sinclaird9e9ff32020-03-12 12:40:01 +000059
60namespace tint {
61namespace writer {
62namespace wgsl {
63
Ben Claytonf2ec7f32021-06-29 11:53:15 +000064GeneratorImpl::GeneratorImpl(const Program* program) : TextGenerator(program) {}
dan sinclaird9e9ff32020-03-12 12:40:01 +000065
66GeneratorImpl::~GeneratorImpl() = default;
67
Ben Clayton688fe442021-05-13 12:38:12 +000068bool GeneratorImpl::Generate() {
James Pricedfd17142021-02-10 15:34:37 +000069 // Generate global declarations in the order they appear in the module.
70 for (auto* decl : program_->AST().GlobalDeclarations()) {
Ben Clayton8758f102021-06-09 14:32:14 +000071 if (auto* td = decl->As<ast::TypeDecl>()) {
Ben Clayton950809f2021-06-09 14:32:14 +000072 if (!EmitTypeDecl(td)) {
James Pricedfd17142021-02-10 15:34:37 +000073 return false;
74 }
75 } else if (auto* func = decl->As<ast::Function>()) {
James Pricedfd17142021-02-10 15:34:37 +000076 if (!EmitFunction(func)) {
77 return false;
78 }
79 } else if (auto* var = decl->As<ast::Variable>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +000080 if (!EmitVariable(line(), var)) {
James Pricedfd17142021-02-10 15:34:37 +000081 return false;
82 }
83 } else {
Ben Claytonffd28e22021-06-24 11:27:36 +000084 TINT_UNREACHABLE(Writer, diagnostics_);
Ben Clayton6b4924f2021-02-17 20:13:34 +000085 return false;
dan sinclaird9e9ff32020-03-12 12:40:01 +000086 }
dan sinclaird9e9ff32020-03-12 12:40:01 +000087
James Pricedfd17142021-02-10 15:34:37 +000088 if (decl != program_->AST().GlobalDeclarations().back()) {
Ben Claytone1f30f12021-07-02 22:17:25 +000089 line();
dan sinclaird9e9ff32020-03-12 12:40:01 +000090 }
91 }
dan sinclair3740fd22020-03-20 19:09:04 +000092
dan sinclaird9e9ff32020-03-12 12:40:01 +000093 return true;
94}
95
Ben Clayton950809f2021-06-09 14:32:14 +000096bool GeneratorImpl::EmitTypeDecl(const ast::TypeDecl* ty) {
Ben Claytonfb13f022021-05-07 15:05:44 +000097 if (auto* alias = ty->As<ast::Alias>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +000098 auto out = line();
99 out << "type " << program_->Symbols().NameFor(alias->symbol()) << " = ";
100 if (!EmitType(out, alias->type())) {
dan sinclair0ce07042020-10-21 19:15:20 +0000101 return false;
dan sinclair7156d3e2020-10-19 15:31:47 +0000102 }
Ben Claytone1f30f12021-07-02 22:17:25 +0000103 out << ";";
Ben Claytonfb13f022021-05-07 15:05:44 +0000104 } else if (auto* str = ty->As<ast::Struct>()) {
105 if (!EmitStructType(str)) {
Ben Clayton083b5912021-04-30 16:01:29 +0000106 return false;
107 }
Ben Claytonfb13f022021-05-07 15:05:44 +0000108 } else {
Ben Claytonffd28e22021-06-24 11:27:36 +0000109 diagnostics_.add_error(
110 diag::System::Writer,
111 "unknown declared type: " + std::string(ty->TypeInfo().name));
Ben Claytonfb13f022021-05-07 15:05:44 +0000112 return false;
Ben Clayton083b5912021-04-30 16:01:29 +0000113 }
Ben Claytonfb13f022021-05-07 15:05:44 +0000114 return true;
dan sinclaird9e9ff32020-03-12 12:40:01 +0000115}
116
Ben Claytone1f30f12021-07-02 22:17:25 +0000117bool GeneratorImpl::EmitExpression(std::ostream& out, ast::Expression* expr) {
Ben Claytond6ae9902020-11-30 23:30:58 +0000118 if (auto* a = expr->As<ast::ArrayAccessorExpression>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000119 return EmitArrayAccessor(out, a);
dan sinclair9d9d7cd2020-03-18 20:05:44 +0000120 }
Ben Claytond6ae9902020-11-30 23:30:58 +0000121 if (auto* b = expr->As<ast::BinaryExpression>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000122 return EmitBinary(out, b);
dan sinclair1c9b4862020-04-07 19:27:41 +0000123 }
Ben Claytond6ae9902020-11-30 23:30:58 +0000124 if (auto* b = expr->As<ast::BitcastExpression>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000125 return EmitBitcast(out, b);
dan sinclaira7d498e2020-09-22 22:07:13 +0000126 }
Ben Claytond6ae9902020-11-30 23:30:58 +0000127 if (auto* c = expr->As<ast::CallExpression>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000128 return EmitCall(out, c);
dan sinclairc80d5ed2020-03-19 02:51:27 +0000129 }
Ben Claytond6ae9902020-11-30 23:30:58 +0000130 if (auto* i = expr->As<ast::IdentifierExpression>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000131 return EmitIdentifier(out, i);
dan sinclair9d9d7cd2020-03-18 20:05:44 +0000132 }
Ben Claytond6ae9902020-11-30 23:30:58 +0000133 if (auto* c = expr->As<ast::ConstructorExpression>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000134 return EmitConstructor(out, c);
dan sinclair9d9d7cd2020-03-18 20:05:44 +0000135 }
Ben Claytond6ae9902020-11-30 23:30:58 +0000136 if (auto* m = expr->As<ast::MemberAccessorExpression>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000137 return EmitMemberAccessor(out, m);
dan sinclair2c56dd92020-03-19 02:55:19 +0000138 }
Ben Claytond6ae9902020-11-30 23:30:58 +0000139 if (auto* u = expr->As<ast::UnaryOpExpression>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000140 return EmitUnaryOp(out, u);
dan sinclairdaff3e22020-03-20 19:01:47 +0000141 }
dan sinclair9d9d7cd2020-03-18 20:05:44 +0000142
Ben Claytonffd28e22021-06-24 11:27:36 +0000143 diagnostics_.add_error(diag::System::Writer, "unknown expression type");
dan sinclair9d9d7cd2020-03-18 20:05:44 +0000144 return false;
145}
146
Ben Claytone1f30f12021-07-02 22:17:25 +0000147bool GeneratorImpl::EmitArrayAccessor(std::ostream& out,
148 ast::ArrayAccessorExpression* expr) {
James Priceb487c712021-06-01 12:18:10 +0000149 bool paren_lhs =
150 !expr->array()
151 ->IsAnyOf<ast::ArrayAccessorExpression, ast::CallExpression,
152 ast::IdentifierExpression, ast::MemberAccessorExpression,
153 ast::TypeConstructorExpression>();
154 if (paren_lhs) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000155 out << "(";
James Priceb487c712021-06-01 12:18:10 +0000156 }
Ben Claytone1f30f12021-07-02 22:17:25 +0000157 if (!EmitExpression(out, expr->array())) {
dan sinclair306a2f82020-03-12 12:43:05 +0000158 return false;
159 }
James Priceb487c712021-06-01 12:18:10 +0000160 if (paren_lhs) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000161 out << ")";
James Priceb487c712021-06-01 12:18:10 +0000162 }
Ben Claytone1f30f12021-07-02 22:17:25 +0000163 out << "[";
dan sinclair9d9d7cd2020-03-18 20:05:44 +0000164
Ben Claytone1f30f12021-07-02 22:17:25 +0000165 if (!EmitExpression(out, expr->idx_expr())) {
dan sinclair9d9d7cd2020-03-18 20:05:44 +0000166 return false;
167 }
Ben Claytone1f30f12021-07-02 22:17:25 +0000168 out << "]";
dan sinclair9d9d7cd2020-03-18 20:05:44 +0000169
170 return true;
171}
172
Ben Claytone1f30f12021-07-02 22:17:25 +0000173bool GeneratorImpl::EmitMemberAccessor(std::ostream& out,
174 ast::MemberAccessorExpression* expr) {
Ben Claytonee449e22021-05-19 08:29:58 +0000175 bool paren_lhs =
176 !expr->structure()
177 ->IsAnyOf<ast::ArrayAccessorExpression, ast::CallExpression,
178 ast::IdentifierExpression, ast::MemberAccessorExpression,
179 ast::TypeConstructorExpression>();
180 if (paren_lhs) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000181 out << "(";
Ben Claytonee449e22021-05-19 08:29:58 +0000182 }
Ben Claytone1f30f12021-07-02 22:17:25 +0000183 if (!EmitExpression(out, expr->structure())) {
dan sinclair2c56dd92020-03-19 02:55:19 +0000184 return false;
185 }
Ben Claytonee449e22021-05-19 08:29:58 +0000186 if (paren_lhs) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000187 out << ")";
Ben Claytonee449e22021-05-19 08:29:58 +0000188 }
dan sinclair2c56dd92020-03-19 02:55:19 +0000189
Ben Claytone1f30f12021-07-02 22:17:25 +0000190 out << ".";
dan sinclair2c56dd92020-03-19 02:55:19 +0000191
Ben Claytone1f30f12021-07-02 22:17:25 +0000192 return EmitExpression(out, expr->member());
dan sinclair2c56dd92020-03-19 02:55:19 +0000193}
194
Ben Claytone1f30f12021-07-02 22:17:25 +0000195bool GeneratorImpl::EmitBitcast(std::ostream& out,
196 ast::BitcastExpression* expr) {
197 out << "bitcast<";
198 if (!EmitType(out, expr->type())) {
dan sinclaircd49b592020-03-18 20:33:00 +0000199 return false;
200 }
201
Ben Claytone1f30f12021-07-02 22:17:25 +0000202 out << ">(";
203 if (!EmitExpression(out, expr->expr())) {
dan sinclaircd49b592020-03-18 20:33:00 +0000204 return false;
205 }
206
Ben Claytone1f30f12021-07-02 22:17:25 +0000207 out << ")";
dan sinclaircd49b592020-03-18 20:33:00 +0000208 return true;
209}
210
Ben Claytone1f30f12021-07-02 22:17:25 +0000211bool GeneratorImpl::EmitCall(std::ostream& out, ast::CallExpression* expr) {
212 if (!EmitExpression(out, expr->func())) {
dan sinclairc80d5ed2020-03-19 02:51:27 +0000213 return false;
214 }
Ben Claytone1f30f12021-07-02 22:17:25 +0000215 out << "(";
dan sinclairc80d5ed2020-03-19 02:51:27 +0000216
217 bool first = true;
218 const auto& params = expr->params();
Ben Claytonb053acf2020-11-16 16:31:07 +0000219 for (auto* param : params) {
dan sinclairc80d5ed2020-03-19 02:51:27 +0000220 if (!first) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000221 out << ", ";
dan sinclairc80d5ed2020-03-19 02:51:27 +0000222 }
223 first = false;
224
Ben Claytone1f30f12021-07-02 22:17:25 +0000225 if (!EmitExpression(out, param)) {
dan sinclairc80d5ed2020-03-19 02:51:27 +0000226 return false;
227 }
228 }
229
Ben Claytone1f30f12021-07-02 22:17:25 +0000230 out << ")";
dan sinclairc80d5ed2020-03-19 02:51:27 +0000231
232 return true;
233}
234
Ben Claytone1f30f12021-07-02 22:17:25 +0000235bool GeneratorImpl::EmitConstructor(std::ostream& out,
236 ast::ConstructorExpression* expr) {
Ben Clayton19fe0722020-11-30 23:30:58 +0000237 if (auto* scalar = expr->As<ast::ScalarConstructorExpression>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000238 return EmitScalarConstructor(out, scalar);
dan sinclair9d9d7cd2020-03-18 20:05:44 +0000239 }
Ben Claytone1f30f12021-07-02 22:17:25 +0000240 return EmitTypeConstructor(out, expr->As<ast::TypeConstructorExpression>());
dan sinclair9d9d7cd2020-03-18 20:05:44 +0000241}
242
Ben Claytone1f30f12021-07-02 22:17:25 +0000243bool GeneratorImpl::EmitTypeConstructor(std::ostream& out,
244 ast::TypeConstructorExpression* expr) {
245 if (!EmitType(out, expr->type())) {
dan sinclair9d9d7cd2020-03-18 20:05:44 +0000246 return false;
247 }
248
Ben Claytone1f30f12021-07-02 22:17:25 +0000249 out << "(";
dan sinclair9d9d7cd2020-03-18 20:05:44 +0000250
251 bool first = true;
Ben Claytonb053acf2020-11-16 16:31:07 +0000252 for (auto* e : expr->values()) {
dan sinclair9d9d7cd2020-03-18 20:05:44 +0000253 if (!first) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000254 out << ", ";
dan sinclair9d9d7cd2020-03-18 20:05:44 +0000255 }
256 first = false;
257
Ben Claytone1f30f12021-07-02 22:17:25 +0000258 if (!EmitExpression(out, e)) {
dan sinclair9d9d7cd2020-03-18 20:05:44 +0000259 return false;
260 }
261 }
262
Ben Claytone1f30f12021-07-02 22:17:25 +0000263 out << ")";
dan sinclair9d9d7cd2020-03-18 20:05:44 +0000264 return true;
265}
266
dan sinclaira322f5d2020-03-30 22:46:06 +0000267bool GeneratorImpl::EmitScalarConstructor(
Ben Claytone1f30f12021-07-02 22:17:25 +0000268 std::ostream& out,
dan sinclaira322f5d2020-03-30 22:46:06 +0000269 ast::ScalarConstructorExpression* expr) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000270 return EmitLiteral(out, expr->literal());
dan sinclair37f4fb02020-03-20 19:04:45 +0000271}
272
Ben Claytone1f30f12021-07-02 22:17:25 +0000273bool GeneratorImpl::EmitLiteral(std::ostream& out, ast::Literal* lit) {
Ben Clayton1b6a8ce2020-12-01 21:07:27 +0000274 if (auto* bl = lit->As<ast::BoolLiteral>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000275 out << (bl->IsTrue() ? "true" : "false");
Ben Clayton1b6a8ce2020-12-01 21:07:27 +0000276 } else if (auto* fl = lit->As<ast::FloatLiteral>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000277 out << FloatToBitPreservingString(fl->value());
Ben Clayton1b6a8ce2020-12-01 21:07:27 +0000278 } else if (auto* sl = lit->As<ast::SintLiteral>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000279 out << sl->value();
Ben Clayton1b6a8ce2020-12-01 21:07:27 +0000280 } else if (auto* ul = lit->As<ast::UintLiteral>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000281 out << ul->value() << "u";
dan sinclair9d9d7cd2020-03-18 20:05:44 +0000282 } else {
Ben Claytonffd28e22021-06-24 11:27:36 +0000283 diagnostics_.add_error(diag::System::Writer, "unknown literal type");
dan sinclair9d9d7cd2020-03-18 20:05:44 +0000284 return false;
285 }
286 return true;
287}
288
Ben Claytone1f30f12021-07-02 22:17:25 +0000289bool GeneratorImpl::EmitIdentifier(std::ostream& out,
290 ast::IdentifierExpression* expr) {
291 out << program_->Symbols().NameFor(expr->symbol());
dan sinclair306a2f82020-03-12 12:43:05 +0000292 return true;
293}
294
dan sinclair3740fd22020-03-20 19:09:04 +0000295bool GeneratorImpl::EmitFunction(ast::Function* func) {
Ben Clayton451f2cc2021-05-12 12:54:21 +0000296 if (func->decorations().size()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000297 if (!EmitDecorations(line(), func->decorations())) {
dan sinclair3740fd22020-03-20 19:09:04 +0000298 return false;
299 }
300 }
Ben Claytone1f30f12021-07-02 22:17:25 +0000301 {
302 auto out = line();
303 out << "fn " << program_->Symbols().NameFor(func->symbol()) << "(";
dan sinclair3740fd22020-03-20 19:09:04 +0000304
Ben Claytone1f30f12021-07-02 22:17:25 +0000305 bool first = true;
306 for (auto* v : func->params()) {
307 if (!first) {
308 out << ", ";
309 }
310 first = false;
dan sinclair3740fd22020-03-20 19:09:04 +0000311
Ben Claytone1f30f12021-07-02 22:17:25 +0000312 if (!v->decorations().empty()) {
313 if (!EmitDecorations(out, v->decorations())) {
314 return false;
315 }
316 out << " ";
317 }
Ben Clayton9328d942021-04-08 14:39:47 +0000318
Ben Claytone1f30f12021-07-02 22:17:25 +0000319 out << program_->Symbols().NameFor(v->symbol()) << " : ";
320
321 if (!EmitType(out, v->type())) {
Ben Clayton9328d942021-04-08 14:39:47 +0000322 return false;
323 }
Ben Clayton9328d942021-04-08 14:39:47 +0000324 }
325
Ben Claytone1f30f12021-07-02 22:17:25 +0000326 out << ")";
327
328 if (!func->return_type()->Is<ast::Void>() ||
329 !func->return_type_decorations().empty()) {
330 out << " -> ";
331
332 if (!func->return_type_decorations().empty()) {
333 if (!EmitDecorations(out, func->return_type_decorations())) {
334 return false;
335 }
336 out << " ";
337 }
338
339 if (!EmitType(out, func->return_type())) {
340 return false;
341 }
342 }
343
344 if (func->body()) {
345 out << " {";
James Pricecc193de2021-03-15 17:15:23 +0000346 }
dan sinclair3740fd22020-03-20 19:09:04 +0000347 }
348
Ben Claytonb502fdf2021-04-07 08:09:21 +0000349 if (func->body()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000350 if (!EmitStatementsWithIndent(func->body()->statements())) {
351 return false;
352 }
353 line() << "}";
Ben Claytonb502fdf2021-04-07 08:09:21 +0000354 }
355
356 return true;
dan sinclair3740fd22020-03-20 19:09:04 +0000357}
358
Ben Claytone1f30f12021-07-02 22:17:25 +0000359bool GeneratorImpl::EmitImageFormat(std::ostream& out,
360 const ast::ImageFormat fmt) {
dan sinclair83ed2cc2020-09-17 02:51:03 +0000361 switch (fmt) {
Ben Claytonfec63b72021-04-21 13:47:12 +0000362 case ast::ImageFormat::kNone:
Ben Claytonffd28e22021-06-24 11:27:36 +0000363 diagnostics_.add_error(diag::System::Writer, "unknown image format");
dan sinclair83ed2cc2020-09-17 02:51:03 +0000364 return false;
dan sinclairb5e5b802020-10-05 19:55:56 +0000365 default:
Ben Claytone1f30f12021-07-02 22:17:25 +0000366 out << fmt;
dan sinclair83ed2cc2020-09-17 02:51:03 +0000367 }
368 return true;
369}
370
Ben Claytone1f30f12021-07-02 22:17:25 +0000371bool GeneratorImpl::EmitAccess(std::ostream& out, const ast::Access access) {
Ben Clayton93e8f522021-06-04 20:41:47 +0000372 switch (access) {
373 case ast::Access::kRead:
Ben Claytone1f30f12021-07-02 22:17:25 +0000374 out << "read";
Ben Clayton93e8f522021-06-04 20:41:47 +0000375 return true;
376 case ast::Access::kWrite:
Ben Claytone1f30f12021-07-02 22:17:25 +0000377 out << "write";
Ben Clayton93e8f522021-06-04 20:41:47 +0000378 return true;
379 case ast::Access::kReadWrite:
Ben Claytone1f30f12021-07-02 22:17:25 +0000380 out << "read_write";
Ben Clayton93e8f522021-06-04 20:41:47 +0000381 return true;
382 default:
383 break;
384 }
Ben Claytonffd28e22021-06-24 11:27:36 +0000385 diagnostics_.add_error(diag::System::Writer, "unknown access");
Ben Clayton93e8f522021-06-04 20:41:47 +0000386 return false;
387}
388
Ben Claytone1f30f12021-07-02 22:17:25 +0000389bool GeneratorImpl::EmitType(std::ostream& out, const ast::Type* ty) {
Ben Clayton8758f102021-06-09 14:32:14 +0000390 if (auto* ary = ty->As<ast::Array>()) {
Ben Claytonfb13f022021-05-07 15:05:44 +0000391 for (auto* deco : ary->decorations()) {
392 if (auto* stride = deco->As<ast::StrideDecoration>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000393 out << "[[stride(" << stride->stride() << ")]] ";
Ben Claytonfb13f022021-05-07 15:05:44 +0000394 }
395 }
dan sinclaird9e9ff32020-03-12 12:40:01 +0000396
Ben Claytone1f30f12021-07-02 22:17:25 +0000397 out << "array<";
398 if (!EmitType(out, ary->type())) {
Ben Clayton083b5912021-04-30 16:01:29 +0000399 return false;
400 }
Ben Clayton083b5912021-04-30 16:01:29 +0000401
Ben Claytonfb13f022021-05-07 15:05:44 +0000402 if (!ary->IsRuntimeArray())
Ben Claytone1f30f12021-07-02 22:17:25 +0000403 out << ", " << ary->size();
Ben Claytonfb13f022021-05-07 15:05:44 +0000404
Ben Claytone1f30f12021-07-02 22:17:25 +0000405 out << ">";
Ben Claytonfb13f022021-05-07 15:05:44 +0000406 } else if (ty->Is<ast::Bool>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000407 out << "bool";
Ben Claytonfb13f022021-05-07 15:05:44 +0000408 } else if (ty->Is<ast::F32>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000409 out << "f32";
Ben Claytonfb13f022021-05-07 15:05:44 +0000410 } else if (ty->Is<ast::I32>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000411 out << "i32";
Ben Claytonfb13f022021-05-07 15:05:44 +0000412 } else if (auto* mat = ty->As<ast::Matrix>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000413 out << "mat" << mat->columns() << "x" << mat->rows() << "<";
414 if (!EmitType(out, mat->type())) {
Ben Claytonfb13f022021-05-07 15:05:44 +0000415 return false;
416 }
Ben Claytone1f30f12021-07-02 22:17:25 +0000417 out << ">";
Ben Claytonfb13f022021-05-07 15:05:44 +0000418 } else if (auto* ptr = ty->As<ast::Pointer>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000419 out << "ptr<" << ptr->storage_class() << ", ";
420 if (!EmitType(out, ptr->type())) {
Ben Claytonfb13f022021-05-07 15:05:44 +0000421 return false;
422 }
Ben Claytone1f30f12021-07-02 22:17:25 +0000423 out << ">";
Ben Clayton0a32a722021-06-18 18:56:13 +0000424 } else if (auto* atomic = ty->As<ast::Atomic>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000425 out << "atomic<";
426 if (!EmitType(out, atomic->type())) {
Ben Clayton0a32a722021-06-18 18:56:13 +0000427 return false;
428 }
Ben Claytone1f30f12021-07-02 22:17:25 +0000429 out << ">";
Ben Claytonfb13f022021-05-07 15:05:44 +0000430 } else if (auto* sampler = ty->As<ast::Sampler>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000431 out << "sampler";
Ben Claytonfb13f022021-05-07 15:05:44 +0000432
433 if (sampler->IsComparison()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000434 out << "_comparison";
Ben Claytonfb13f022021-05-07 15:05:44 +0000435 }
Ben Claytonf5163d02021-06-02 20:12:34 +0000436 } else if (ty->Is<ast::ExternalTexture>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000437 out << "external_texture";
Ben Claytonfb13f022021-05-07 15:05:44 +0000438 } else if (auto* texture = ty->As<ast::Texture>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000439 out << "texture_";
Ben Claytonfb13f022021-05-07 15:05:44 +0000440 if (texture->Is<ast::DepthTexture>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000441 out << "depth_";
Ben Claytonfb13f022021-05-07 15:05:44 +0000442 } else if (texture->Is<ast::SampledTexture>()) {
443 /* nothing to emit */
444 } else if (texture->Is<ast::MultisampledTexture>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000445 out << "multisampled_";
Ben Claytonfb13f022021-05-07 15:05:44 +0000446 } else if (texture->Is<ast::StorageTexture>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000447 out << "storage_";
Ben Claytonfb13f022021-05-07 15:05:44 +0000448 } else {
Ben Claytonffd28e22021-06-24 11:27:36 +0000449 diagnostics_.add_error(diag::System::Writer, "unknown texture type");
Ben Claytonfb13f022021-05-07 15:05:44 +0000450 return false;
451 }
452
453 switch (texture->dim()) {
454 case ast::TextureDimension::k1d:
Ben Claytone1f30f12021-07-02 22:17:25 +0000455 out << "1d";
Ben Claytonfb13f022021-05-07 15:05:44 +0000456 break;
457 case ast::TextureDimension::k2d:
Ben Claytone1f30f12021-07-02 22:17:25 +0000458 out << "2d";
Ben Claytonfb13f022021-05-07 15:05:44 +0000459 break;
460 case ast::TextureDimension::k2dArray:
Ben Claytone1f30f12021-07-02 22:17:25 +0000461 out << "2d_array";
Ben Claytonfb13f022021-05-07 15:05:44 +0000462 break;
463 case ast::TextureDimension::k3d:
Ben Claytone1f30f12021-07-02 22:17:25 +0000464 out << "3d";
Ben Claytonfb13f022021-05-07 15:05:44 +0000465 break;
466 case ast::TextureDimension::kCube:
Ben Claytone1f30f12021-07-02 22:17:25 +0000467 out << "cube";
Ben Claytonfb13f022021-05-07 15:05:44 +0000468 break;
469 case ast::TextureDimension::kCubeArray:
Ben Claytone1f30f12021-07-02 22:17:25 +0000470 out << "cube_array";
Ben Claytonfb13f022021-05-07 15:05:44 +0000471 break;
472 default:
Ben Claytonffd28e22021-06-24 11:27:36 +0000473 diagnostics_.add_error(diag::System::Writer,
474 "unknown texture dimension");
Ben Claytonfb13f022021-05-07 15:05:44 +0000475 return false;
476 }
477
478 if (auto* sampled = texture->As<ast::SampledTexture>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000479 out << "<";
480 if (!EmitType(out, sampled->type())) {
Ben Claytonfb13f022021-05-07 15:05:44 +0000481 return false;
482 }
Ben Claytone1f30f12021-07-02 22:17:25 +0000483 out << ">";
Ben Claytonfb13f022021-05-07 15:05:44 +0000484 } else if (auto* ms = texture->As<ast::MultisampledTexture>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000485 out << "<";
486 if (!EmitType(out, ms->type())) {
Ben Claytonfb13f022021-05-07 15:05:44 +0000487 return false;
488 }
Ben Claytone1f30f12021-07-02 22:17:25 +0000489 out << ">";
Ben Claytonfb13f022021-05-07 15:05:44 +0000490 } else if (auto* storage = texture->As<ast::StorageTexture>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000491 out << "<";
492 if (!EmitImageFormat(out, storage->image_format())) {
Ben Claytonfb13f022021-05-07 15:05:44 +0000493 return false;
494 }
Ben Claytone1f30f12021-07-02 22:17:25 +0000495 out << ", ";
496 if (!EmitAccess(out, storage->access())) {
Ben Clayton93e8f522021-06-04 20:41:47 +0000497 return false;
498 }
Ben Claytone1f30f12021-07-02 22:17:25 +0000499 out << ">";
Ben Claytonfb13f022021-05-07 15:05:44 +0000500 }
501
502 } else if (ty->Is<ast::U32>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000503 out << "u32";
Ben Claytonfb13f022021-05-07 15:05:44 +0000504 } else if (auto* vec = ty->As<ast::Vector>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000505 out << "vec" << vec->size() << "<";
506 if (!EmitType(out, vec->type())) {
Ben Claytonfb13f022021-05-07 15:05:44 +0000507 return false;
508 }
Ben Claytone1f30f12021-07-02 22:17:25 +0000509 out << ">";
Ben Claytonfb13f022021-05-07 15:05:44 +0000510 } else if (ty->Is<ast::Void>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000511 out << "void";
Ben Claytonfb13f022021-05-07 15:05:44 +0000512 } else if (auto* tn = ty->As<ast::TypeName>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000513 out << program_->Symbols().NameFor(tn->name());
Ben Claytonfb13f022021-05-07 15:05:44 +0000514 } else {
Ben Claytonffd28e22021-06-24 11:27:36 +0000515 diagnostics_.add_error(diag::System::Writer,
516 "unknown type in EmitType: " + ty->type_name());
Ben Claytonfb13f022021-05-07 15:05:44 +0000517 return false;
518 }
519 return true;
dan sinclaird9e9ff32020-03-12 12:40:01 +0000520}
521
Ben Clayton083b5912021-04-30 16:01:29 +0000522bool GeneratorImpl::EmitStructType(const ast::Struct* str) {
Ben Clayton688fe442021-05-13 12:38:12 +0000523 if (str->decorations().size()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000524 if (!EmitDecorations(line(), str->decorations())) {
Ben Clayton688fe442021-05-13 12:38:12 +0000525 return false;
526 }
dan sinclair7156d3e2020-10-19 15:31:47 +0000527 }
Ben Claytone1f30f12021-07-02 22:17:25 +0000528 line() << "struct " << program_->Symbols().NameFor(str->name()) << " {";
dan sinclair7156d3e2020-10-19 15:31:47 +0000529
Ben Clayton822fa542021-03-15 20:25:12 +0000530 auto add_padding = [&](uint32_t size) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000531 line() << "[[size(" << size << ")]]";
532
Ben Clayton822fa542021-03-15 20:25:12 +0000533 // Note: u32 is the smallest primitive we currently support. When WGSL
534 // supports smaller types, this will need to be updated.
Ben Claytone1f30f12021-07-02 22:17:25 +0000535 line() << UniqueIdentifier("padding") << " : u32;";
Ben Clayton822fa542021-03-15 20:25:12 +0000536 };
537
dan sinclair7156d3e2020-10-19 15:31:47 +0000538 increment_indent();
Ben Clayton822fa542021-03-15 20:25:12 +0000539 uint32_t offset = 0;
Ben Clayton083b5912021-04-30 16:01:29 +0000540 for (auto* mem : str->members()) {
Ben Clayton688fe442021-05-13 12:38:12 +0000541 // TODO(crbug.com/tint/798) move the [[offset]] decoration handling to the
542 // transform::Wgsl sanitizer.
543 if (auto* mem_sem = program_->Sem().Get(mem)) {
544 offset = utils::RoundUp(mem_sem->Align(), offset);
545 if (uint32_t padding = mem_sem->Offset() - offset) {
546 add_padding(padding);
547 offset += padding;
548 }
549 offset += mem_sem->Size();
Ben Clayton822fa542021-03-15 20:25:12 +0000550 }
Ben Clayton822fa542021-03-15 20:25:12 +0000551
552 // Offset decorations no longer exist in the WGSL spec, but are emitted
553 // by the SPIR-V reader and are consumed by the Resolver(). These should not
554 // be emitted, but instead struct padding fields should be emitted.
555 ast::DecorationList decorations_sanitized;
556 decorations_sanitized.reserve(mem->decorations().size());
557 for (auto* deco : mem->decorations()) {
558 if (!deco->Is<ast::StructMemberOffsetDecoration>()) {
559 decorations_sanitized.emplace_back(deco);
560 }
561 }
562
563 if (!decorations_sanitized.empty()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000564 if (!EmitDecorations(line(), decorations_sanitized)) {
James Priced3e36812021-03-11 17:47:52 +0000565 return false;
566 }
dan sinclair7156d3e2020-10-19 15:31:47 +0000567 }
James Priced3e36812021-03-11 17:47:52 +0000568
Ben Claytone1f30f12021-07-02 22:17:25 +0000569 auto out = line();
570 out << program_->Symbols().NameFor(mem->symbol()) << " : ";
571 if (!EmitType(out, mem->type())) {
dan sinclair7156d3e2020-10-19 15:31:47 +0000572 return false;
573 }
Ben Claytone1f30f12021-07-02 22:17:25 +0000574 out << ";";
dan sinclair7156d3e2020-10-19 15:31:47 +0000575 }
576 decrement_indent();
dan sinclair7156d3e2020-10-19 15:31:47 +0000577
Ben Claytone1f30f12021-07-02 22:17:25 +0000578 line() << "};";
dan sinclair7156d3e2020-10-19 15:31:47 +0000579 return true;
580}
581
Ben Claytone1f30f12021-07-02 22:17:25 +0000582bool GeneratorImpl::EmitVariable(std::ostream& out, ast::Variable* var) {
James Priced3e36812021-03-11 17:47:52 +0000583 if (!var->decorations().empty()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000584 if (!EmitDecorations(out, var->decorations())) {
James Priced3e36812021-03-11 17:47:52 +0000585 return false;
586 }
Ben Claytone1f30f12021-07-02 22:17:25 +0000587 out << " ";
dan sinclaird9e9ff32020-03-12 12:40:01 +0000588 }
589
590 if (var->is_const()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000591 out << "let";
dan sinclaird9e9ff32020-03-12 12:40:01 +0000592 } else {
Ben Claytone1f30f12021-07-02 22:17:25 +0000593 out << "var";
Ben Clayton688fe442021-05-13 12:38:12 +0000594 auto sc = var->declared_storage_class();
Ben Clayton93e8f522021-06-04 20:41:47 +0000595 auto ac = var->declared_access();
596 if (sc != ast::StorageClass::kNone || ac != ast::Access::kUndefined) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000597 out << "<" << sc;
Ben Clayton93e8f522021-06-04 20:41:47 +0000598 if (ac != ast::Access::kUndefined) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000599 out << ", ";
600 if (!EmitAccess(out, ac)) {
Ben Clayton93e8f522021-06-04 20:41:47 +0000601 return false;
602 }
603 }
Ben Claytone1f30f12021-07-02 22:17:25 +0000604 out << ">";
dan sinclaird9e9ff32020-03-12 12:40:01 +0000605 }
606 }
607
Ben Claytone1f30f12021-07-02 22:17:25 +0000608 out << " " << program_->Symbols().NameFor(var->symbol());
Ben Clayton8198d572021-04-19 14:37:49 +0000609
Ben Clayton02ebf0d2021-05-05 09:09:41 +0000610 if (auto* ty = var->type()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000611 out << " : ";
612 if (!EmitType(out, ty)) {
Ben Clayton8198d572021-04-19 14:37:49 +0000613 return false;
614 }
dan sinclaird9e9ff32020-03-12 12:40:01 +0000615 }
616
dan sinclaira322f5d2020-03-30 22:46:06 +0000617 if (var->constructor() != nullptr) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000618 out << " = ";
619 if (!EmitExpression(out, var->constructor())) {
dan sinclair306a2f82020-03-12 12:43:05 +0000620 return false;
621 }
dan sinclaird9e9ff32020-03-12 12:40:01 +0000622 }
Ben Claytone1f30f12021-07-02 22:17:25 +0000623 out << ";";
dan sinclaird9e9ff32020-03-12 12:40:01 +0000624
625 return true;
626}
627
Ben Claytone1f30f12021-07-02 22:17:25 +0000628bool GeneratorImpl::EmitDecorations(std::ostream& out,
629 const ast::DecorationList& decos) {
630 out << "[[";
dan sinclaird9e9ff32020-03-12 12:40:01 +0000631 bool first = true;
James Priced3e36812021-03-11 17:47:52 +0000632 for (auto* deco : decos) {
dan sinclaird9e9ff32020-03-12 12:40:01 +0000633 if (!first) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000634 out << ", ";
dan sinclaird9e9ff32020-03-12 12:40:01 +0000635 }
636 first = false;
637
Ben Clayton451f2cc2021-05-12 12:54:21 +0000638 if (auto* workgroup = deco->As<ast::WorkgroupDecoration>()) {
James Price70f80bb2021-05-19 13:40:08 +0000639 auto values = workgroup->values();
Ben Claytone1f30f12021-07-02 22:17:25 +0000640 out << "workgroup_size(";
James Price70f80bb2021-05-19 13:40:08 +0000641 for (int i = 0; i < 3; i++) {
642 if (values[i]) {
643 if (i > 0) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000644 out << ", ";
James Price70f80bb2021-05-19 13:40:08 +0000645 }
646 if (auto* ident = values[i]->As<ast::IdentifierExpression>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000647 if (!EmitIdentifier(out, ident)) {
James Price70f80bb2021-05-19 13:40:08 +0000648 return false;
649 }
650 } else if (auto* scalar =
651 values[i]->As<ast::ScalarConstructorExpression>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000652 if (!EmitScalarConstructor(out, scalar)) {
James Price70f80bb2021-05-19 13:40:08 +0000653 return false;
654 }
655 } else {
Ben Claytonffd28e22021-06-24 11:27:36 +0000656 TINT_ICE(Writer, diagnostics_)
657 << "Unsupported workgroup_size expression";
James Price70f80bb2021-05-19 13:40:08 +0000658 }
659 }
660 }
Ben Claytone1f30f12021-07-02 22:17:25 +0000661 out << ")";
Ben Clayton688fe442021-05-13 12:38:12 +0000662 } else if (deco->Is<ast::StructBlockDecoration>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000663 out << "block";
Ben Clayton451f2cc2021-05-12 12:54:21 +0000664 } else if (auto* stage = deco->As<ast::StageDecoration>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000665 out << "stage(" << stage->value() << ")";
Ben Clayton451f2cc2021-05-12 12:54:21 +0000666 } else if (auto* binding = deco->As<ast::BindingDecoration>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000667 out << "binding(" << binding->value() << ")";
dan sinclairc068cfc2021-01-15 12:22:16 +0000668 } else if (auto* group = deco->As<ast::GroupDecoration>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000669 out << "group(" << group->value() << ")";
Ben Clayton2c1d7d52020-11-30 23:30:58 +0000670 } else if (auto* location = deco->As<ast::LocationDecoration>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000671 out << "location(" << location->value() << ")";
Ben Claytonc0eb9ae2020-11-30 23:30:58 +0000672 } else if (auto* builtin = deco->As<ast::BuiltinDecoration>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000673 out << "builtin(" << builtin->value() << ")";
James Price545f4e02021-06-28 23:04:43 +0000674 } else if (auto* interpolate = deco->As<ast::InterpolateDecoration>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000675 out << "interpolate(" << interpolate->type();
James Price545f4e02021-06-28 23:04:43 +0000676 if (interpolate->sampling() != ast::InterpolationSampling::kNone) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000677 out << ", " << interpolate->sampling();
James Price545f4e02021-06-28 23:04:43 +0000678 }
Ben Claytone1f30f12021-07-02 22:17:25 +0000679 out << ")";
James Pricefcc0de02021-07-12 12:28:52 +0000680 } else if (deco->Is<ast::InvariantDecoration>()) {
681 out << "invariant";
James Pricee87ded82021-04-30 17:14:19 +0000682 } else if (auto* override_deco = deco->As<ast::OverrideDecoration>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000683 out << "override";
James Price26e03122021-05-13 21:35:42 +0000684 if (override_deco->HasValue()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000685 out << "(" << override_deco->value() << ")";
James Price26e03122021-05-13 21:35:42 +0000686 }
Ben Claytond614dd52021-03-15 10:43:11 +0000687 } else if (auto* size = deco->As<ast::StructMemberSizeDecoration>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000688 out << "size(" << size->size() << ")";
Ben Claytond614dd52021-03-15 10:43:11 +0000689 } else if (auto* align = deco->As<ast::StructMemberAlignDecoration>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000690 out << "align(" << align->align() << ")";
Ben Clayton451f2cc2021-05-12 12:54:21 +0000691 } else if (auto* internal = deco->As<ast::InternalDecoration>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000692 out << "internal(" << internal->InternalName() << ")";
dan sinclaird9e9ff32020-03-12 12:40:01 +0000693 } else {
Ben Claytonffd28e22021-06-24 11:27:36 +0000694 TINT_ICE(Writer, diagnostics_)
Ben Clayton822fa542021-03-15 20:25:12 +0000695 << "Unsupported decoration '" << deco->TypeInfo().name << "'";
dan sinclaird9e9ff32020-03-12 12:40:01 +0000696 return false;
697 }
698 }
Ben Claytone1f30f12021-07-02 22:17:25 +0000699 out << "]]";
dan sinclaird9e9ff32020-03-12 12:40:01 +0000700
701 return true;
702}
703
Ben Claytone1f30f12021-07-02 22:17:25 +0000704bool GeneratorImpl::EmitBinary(std::ostream& out, ast::BinaryExpression* expr) {
705 out << "(";
dan sinclair49568e12020-03-20 19:01:19 +0000706
Ben Claytone1f30f12021-07-02 22:17:25 +0000707 if (!EmitExpression(out, expr->lhs())) {
dan sinclair49568e12020-03-20 19:01:19 +0000708 return false;
709 }
Ben Claytone1f30f12021-07-02 22:17:25 +0000710 out << " ";
dan sinclair49568e12020-03-20 19:01:19 +0000711
dan sinclair1c9b4862020-04-07 19:27:41 +0000712 switch (expr->op()) {
713 case ast::BinaryOp::kAnd:
Ben Claytone1f30f12021-07-02 22:17:25 +0000714 out << "&";
dan sinclair49568e12020-03-20 19:01:19 +0000715 break;
dan sinclair1c9b4862020-04-07 19:27:41 +0000716 case ast::BinaryOp::kOr:
Ben Claytone1f30f12021-07-02 22:17:25 +0000717 out << "|";
dan sinclair49568e12020-03-20 19:01:19 +0000718 break;
dan sinclair1c9b4862020-04-07 19:27:41 +0000719 case ast::BinaryOp::kXor:
Ben Claytone1f30f12021-07-02 22:17:25 +0000720 out << "^";
dan sinclair49568e12020-03-20 19:01:19 +0000721 break;
dan sinclair1c9b4862020-04-07 19:27:41 +0000722 case ast::BinaryOp::kLogicalAnd:
Ben Claytone1f30f12021-07-02 22:17:25 +0000723 out << "&&";
dan sinclair49568e12020-03-20 19:01:19 +0000724 break;
dan sinclair1c9b4862020-04-07 19:27:41 +0000725 case ast::BinaryOp::kLogicalOr:
Ben Claytone1f30f12021-07-02 22:17:25 +0000726 out << "||";
dan sinclair49568e12020-03-20 19:01:19 +0000727 break;
dan sinclair1c9b4862020-04-07 19:27:41 +0000728 case ast::BinaryOp::kEqual:
Ben Claytone1f30f12021-07-02 22:17:25 +0000729 out << "==";
dan sinclair49568e12020-03-20 19:01:19 +0000730 break;
dan sinclair1c9b4862020-04-07 19:27:41 +0000731 case ast::BinaryOp::kNotEqual:
Ben Claytone1f30f12021-07-02 22:17:25 +0000732 out << "!=";
dan sinclair49568e12020-03-20 19:01:19 +0000733 break;
dan sinclair1c9b4862020-04-07 19:27:41 +0000734 case ast::BinaryOp::kLessThan:
Ben Claytone1f30f12021-07-02 22:17:25 +0000735 out << "<";
dan sinclair49568e12020-03-20 19:01:19 +0000736 break;
dan sinclair1c9b4862020-04-07 19:27:41 +0000737 case ast::BinaryOp::kGreaterThan:
Ben Claytone1f30f12021-07-02 22:17:25 +0000738 out << ">";
dan sinclair49568e12020-03-20 19:01:19 +0000739 break;
dan sinclair1c9b4862020-04-07 19:27:41 +0000740 case ast::BinaryOp::kLessThanEqual:
Ben Claytone1f30f12021-07-02 22:17:25 +0000741 out << "<=";
dan sinclair49568e12020-03-20 19:01:19 +0000742 break;
dan sinclair1c9b4862020-04-07 19:27:41 +0000743 case ast::BinaryOp::kGreaterThanEqual:
Ben Claytone1f30f12021-07-02 22:17:25 +0000744 out << ">=";
dan sinclair49568e12020-03-20 19:01:19 +0000745 break;
dan sinclair1c9b4862020-04-07 19:27:41 +0000746 case ast::BinaryOp::kShiftLeft:
Ben Claytone1f30f12021-07-02 22:17:25 +0000747 out << "<<";
dan sinclair49568e12020-03-20 19:01:19 +0000748 break;
dan sinclair1c9b4862020-04-07 19:27:41 +0000749 case ast::BinaryOp::kShiftRight:
Ben Claytone1f30f12021-07-02 22:17:25 +0000750 out << ">>";
dan sinclair49568e12020-03-20 19:01:19 +0000751 break;
dan sinclair1c9b4862020-04-07 19:27:41 +0000752 case ast::BinaryOp::kAdd:
Ben Claytone1f30f12021-07-02 22:17:25 +0000753 out << "+";
dan sinclair49568e12020-03-20 19:01:19 +0000754 break;
dan sinclair1c9b4862020-04-07 19:27:41 +0000755 case ast::BinaryOp::kSubtract:
Ben Claytone1f30f12021-07-02 22:17:25 +0000756 out << "-";
dan sinclair49568e12020-03-20 19:01:19 +0000757 break;
dan sinclair1c9b4862020-04-07 19:27:41 +0000758 case ast::BinaryOp::kMultiply:
Ben Claytone1f30f12021-07-02 22:17:25 +0000759 out << "*";
dan sinclair49568e12020-03-20 19:01:19 +0000760 break;
dan sinclair1c9b4862020-04-07 19:27:41 +0000761 case ast::BinaryOp::kDivide:
Ben Claytone1f30f12021-07-02 22:17:25 +0000762 out << "/";
dan sinclair49568e12020-03-20 19:01:19 +0000763 break;
dan sinclair1c9b4862020-04-07 19:27:41 +0000764 case ast::BinaryOp::kModulo:
Ben Claytone1f30f12021-07-02 22:17:25 +0000765 out << "%";
dan sinclair49568e12020-03-20 19:01:19 +0000766 break;
dan sinclair1c9b4862020-04-07 19:27:41 +0000767 case ast::BinaryOp::kNone:
Ben Claytonffd28e22021-06-24 11:27:36 +0000768 diagnostics_.add_error(diag::System::Writer,
769 "missing binary operation type");
dan sinclair49568e12020-03-20 19:01:19 +0000770 return false;
771 }
Ben Claytone1f30f12021-07-02 22:17:25 +0000772 out << " ";
dan sinclair49568e12020-03-20 19:01:19 +0000773
Ben Claytone1f30f12021-07-02 22:17:25 +0000774 if (!EmitExpression(out, expr->rhs())) {
dan sinclair49568e12020-03-20 19:01:19 +0000775 return false;
776 }
777
Ben Claytone1f30f12021-07-02 22:17:25 +0000778 out << ")";
dan sinclair49568e12020-03-20 19:01:19 +0000779 return true;
780}
781
Ben Claytone1f30f12021-07-02 22:17:25 +0000782bool GeneratorImpl::EmitUnaryOp(std::ostream& out,
783 ast::UnaryOpExpression* expr) {
dan sinclairdaff3e22020-03-20 19:01:47 +0000784 switch (expr->op()) {
Ben Clayton52b06fb2021-05-13 13:36:32 +0000785 case ast::UnaryOp::kAddressOf:
Ben Claytone1f30f12021-07-02 22:17:25 +0000786 out << "&";
Ben Clayton52b06fb2021-05-13 13:36:32 +0000787 break;
James Pricec932b552021-06-17 08:35:54 +0000788 case ast::UnaryOp::kComplement:
Ben Claytone1f30f12021-07-02 22:17:25 +0000789 out << "~";
James Pricec932b552021-06-17 08:35:54 +0000790 break;
Ben Clayton85bdf172021-05-17 14:48:37 +0000791 case ast::UnaryOp::kIndirection:
Ben Claytone1f30f12021-07-02 22:17:25 +0000792 out << "*";
Ben Clayton85bdf172021-05-17 14:48:37 +0000793 break;
dan sinclairdaff3e22020-03-20 19:01:47 +0000794 case ast::UnaryOp::kNot:
Ben Claytone1f30f12021-07-02 22:17:25 +0000795 out << "!";
dan sinclairdaff3e22020-03-20 19:01:47 +0000796 break;
797 case ast::UnaryOp::kNegation:
Ben Claytone1f30f12021-07-02 22:17:25 +0000798 out << "-";
dan sinclairdaff3e22020-03-20 19:01:47 +0000799 break;
800 }
Ben Claytone1f30f12021-07-02 22:17:25 +0000801 out << "(";
dan sinclairdaff3e22020-03-20 19:01:47 +0000802
Ben Claytone1f30f12021-07-02 22:17:25 +0000803 if (!EmitExpression(out, expr->expr())) {
dan sinclairdaff3e22020-03-20 19:01:47 +0000804 return false;
805 }
806
Ben Claytone1f30f12021-07-02 22:17:25 +0000807 out << ")";
dan sinclairdaff3e22020-03-20 19:01:47 +0000808
809 return true;
810}
811
dan sinclair7c2fa1e2020-07-27 15:25:00 +0000812bool GeneratorImpl::EmitBlock(const ast::BlockStatement* stmt) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000813 line() << "{";
814 if (!EmitStatementsWithIndent(stmt->statements())) {
815 return false;
dan sinclair21f8e252020-07-27 15:25:00 +0000816 }
Ben Claytone1f30f12021-07-02 22:17:25 +0000817 line() << "}";
dan sinclair21f8e252020-07-27 15:25:00 +0000818
819 return true;
820}
821
dan sinclair7f9d5702020-03-20 19:01:57 +0000822bool GeneratorImpl::EmitStatement(ast::Statement* stmt) {
Ben Clayton1d8098a2020-11-30 23:30:58 +0000823 if (auto* a = stmt->As<ast::AssignmentStatement>()) {
824 return EmitAssign(a);
dan sinclair7f9d5702020-03-20 19:01:57 +0000825 }
Ben Clayton1d8098a2020-11-30 23:30:58 +0000826 if (auto* b = stmt->As<ast::BlockStatement>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000827 return EmitBlock(b);
dan sinclair21f8e252020-07-27 15:25:00 +0000828 }
Ben Clayton1d8098a2020-11-30 23:30:58 +0000829 if (auto* b = stmt->As<ast::BreakStatement>()) {
830 return EmitBreak(b);
dan sinclairbf5ab652020-03-20 19:02:05 +0000831 }
Ben Clayton1d8098a2020-11-30 23:30:58 +0000832 if (auto* c = stmt->As<ast::CallStatement>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000833 auto out = line();
834 if (!EmitCall(out, c->expr())) {
835 return false;
836 }
837 out << ";";
838 return true;
dan sinclairb44fe3c2020-07-21 13:44:27 +0000839 }
Ben Clayton1d8098a2020-11-30 23:30:58 +0000840 if (auto* c = stmt->As<ast::ContinueStatement>()) {
841 return EmitContinue(c);
dan sinclair17686fc2020-03-20 19:04:54 +0000842 }
Ben Clayton1d8098a2020-11-30 23:30:58 +0000843 if (auto* d = stmt->As<ast::DiscardStatement>()) {
844 return EmitDiscard(d);
dan sinclaird81bebc2020-07-25 14:33:04 +0000845 }
Ben Clayton1d8098a2020-11-30 23:30:58 +0000846 if (auto* f = stmt->As<ast::FallthroughStatement>()) {
847 return EmitFallthrough(f);
dan sinclairc083af82020-03-20 19:05:02 +0000848 }
Ben Clayton1d8098a2020-11-30 23:30:58 +0000849 if (auto* i = stmt->As<ast::IfStatement>()) {
850 return EmitIf(i);
dan sinclairc5742952020-03-20 19:08:56 +0000851 }
Ben Clayton1d8098a2020-11-30 23:30:58 +0000852 if (auto* l = stmt->As<ast::LoopStatement>()) {
853 return EmitLoop(l);
dan sinclair0d004022020-03-20 19:07:00 +0000854 }
Ben Claytonefc46c12021-07-02 19:27:42 +0000855 if (auto* l = stmt->As<ast::ForLoopStatement>()) {
856 return EmitForLoop(l);
857 }
Ben Clayton1d8098a2020-11-30 23:30:58 +0000858 if (auto* r = stmt->As<ast::ReturnStatement>()) {
859 return EmitReturn(r);
dan sinclair2a6e2752020-03-20 19:05:10 +0000860 }
Ben Clayton1d8098a2020-11-30 23:30:58 +0000861 if (auto* s = stmt->As<ast::SwitchStatement>()) {
862 return EmitSwitch(s);
dan sinclair5f64aee2020-03-20 19:06:52 +0000863 }
Ben Clayton1d8098a2020-11-30 23:30:58 +0000864 if (auto* v = stmt->As<ast::VariableDeclStatement>()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000865 return EmitVariable(line(), v->variable());
dan sinclair4202d7d2020-03-20 19:06:45 +0000866 }
dan sinclair7f9d5702020-03-20 19:01:57 +0000867
Ben Claytonffd28e22021-06-24 11:27:36 +0000868 diagnostics_.add_error(diag::System::Writer,
869 "unknown statement type: " + program_->str(stmt));
dan sinclair7f9d5702020-03-20 19:01:57 +0000870 return false;
871}
872
Ben Claytone1f30f12021-07-02 22:17:25 +0000873bool GeneratorImpl::EmitStatements(const ast::StatementList& stmts) {
874 for (auto* s : stmts) {
875 if (!EmitStatement(s)) {
876 return false;
877 }
878 }
879 return true;
880}
881
882bool GeneratorImpl::EmitStatementsWithIndent(const ast::StatementList& stmts) {
883 ScopedIndent si(this);
884 return EmitStatements(stmts);
885}
886
dan sinclair7f9d5702020-03-20 19:01:57 +0000887bool GeneratorImpl::EmitAssign(ast::AssignmentStatement* stmt) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000888 auto out = line();
889
890 if (!EmitExpression(out, stmt->lhs())) {
dan sinclair7f9d5702020-03-20 19:01:57 +0000891 return false;
892 }
893
Ben Claytone1f30f12021-07-02 22:17:25 +0000894 out << " = ";
dan sinclair7f9d5702020-03-20 19:01:57 +0000895
Ben Claytone1f30f12021-07-02 22:17:25 +0000896 if (!EmitExpression(out, stmt->rhs())) {
dan sinclair7f9d5702020-03-20 19:01:57 +0000897 return false;
898 }
899
Ben Claytone1f30f12021-07-02 22:17:25 +0000900 out << ";";
901
dan sinclair7f9d5702020-03-20 19:01:57 +0000902 return true;
903}
904
dan sinclair6bd70612020-06-03 16:11:28 +0000905bool GeneratorImpl::EmitBreak(ast::BreakStatement*) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000906 line() << "break;";
dan sinclair37f4fb02020-03-20 19:04:45 +0000907 return true;
908}
909
910bool GeneratorImpl::EmitCase(ast::CaseStatement* stmt) {
dan sinclair37f4fb02020-03-20 19:04:45 +0000911 if (stmt->IsDefault()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000912 line() << "default: {";
dan sinclair37f4fb02020-03-20 19:04:45 +0000913 } else {
Ben Claytone1f30f12021-07-02 22:17:25 +0000914 auto out = line();
915 out << "case ";
dan sinclair37f4fb02020-03-20 19:04:45 +0000916
dan sinclair1aadbd42020-06-01 16:56:46 +0000917 bool first = true;
Ben Claytonb053acf2020-11-16 16:31:07 +0000918 for (auto* selector : stmt->selectors()) {
dan sinclair1aadbd42020-06-01 16:56:46 +0000919 if (!first) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000920 out << ", ";
dan sinclair1aadbd42020-06-01 16:56:46 +0000921 }
922
923 first = false;
Ben Claytone1f30f12021-07-02 22:17:25 +0000924 if (!EmitLiteral(out, selector)) {
dan sinclair1aadbd42020-06-01 16:56:46 +0000925 return false;
926 }
dan sinclair37f4fb02020-03-20 19:04:45 +0000927 }
Ben Claytone1f30f12021-07-02 22:17:25 +0000928 out << ": {";
dan sinclair37f4fb02020-03-20 19:04:45 +0000929 }
dan sinclair37f4fb02020-03-20 19:04:45 +0000930
Ben Claytone1f30f12021-07-02 22:17:25 +0000931 if (!EmitStatementsWithIndent(stmt->body()->statements())) {
932 return false;
933 }
dan sinclairbf5ab652020-03-20 19:02:05 +0000934
Ben Claytone1f30f12021-07-02 22:17:25 +0000935 line() << "}";
dan sinclair17686fc2020-03-20 19:04:54 +0000936 return true;
937}
938
Ben Claytone1f30f12021-07-02 22:17:25 +0000939bool GeneratorImpl::EmitContinue(ast::ContinueStatement*) {
940 line() << "continue;";
941 return true;
dan sinclaireaf26892020-03-20 19:08:07 +0000942}
943
dan sinclairc083af82020-03-20 19:05:02 +0000944bool GeneratorImpl::EmitFallthrough(ast::FallthroughStatement*) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000945 line() << "fallthrough;";
dan sinclairc083af82020-03-20 19:05:02 +0000946 return true;
947}
948
dan sinclairc5742952020-03-20 19:08:56 +0000949bool GeneratorImpl::EmitIf(ast::IfStatement* stmt) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000950 {
951 auto out = line();
952 out << "if (";
953 if (!EmitExpression(out, stmt->condition())) {
954 return false;
955 }
956 out << ") {";
dan sinclairc5742952020-03-20 19:08:56 +0000957 }
dan sinclairc5742952020-03-20 19:08:56 +0000958
Ben Claytone1f30f12021-07-02 22:17:25 +0000959 if (!EmitStatementsWithIndent(stmt->body()->statements())) {
dan sinclair09842142020-03-25 18:54:01 +0000960 return false;
dan sinclairc5742952020-03-20 19:08:56 +0000961 }
962
Ben Claytonb053acf2020-11-16 16:31:07 +0000963 for (auto* e : stmt->else_statements()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000964 if (e->HasCondition()) {
965 auto out = line();
966 out << "} elseif (";
967 if (!EmitExpression(out, e->condition())) {
968 return false;
969 }
970 out << ") {";
971 } else {
972 line() << "} else {";
973 }
974
975 if (!EmitStatementsWithIndent(e->body()->statements())) {
dan sinclairc5742952020-03-20 19:08:56 +0000976 return false;
977 }
978 }
Ben Claytone1f30f12021-07-02 22:17:25 +0000979
980 line() << "}";
dan sinclairc5742952020-03-20 19:08:56 +0000981
dan sinclairc5742952020-03-20 19:08:56 +0000982 return true;
983}
984
dan sinclaird81bebc2020-07-25 14:33:04 +0000985bool GeneratorImpl::EmitDiscard(ast::DiscardStatement*) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000986 line() << "discard;";
dan sinclaird81bebc2020-07-25 14:33:04 +0000987 return true;
988}
989
dan sinclair0d004022020-03-20 19:07:00 +0000990bool GeneratorImpl::EmitLoop(ast::LoopStatement* stmt) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000991 line() << "loop {";
dan sinclair0d004022020-03-20 19:07:00 +0000992 increment_indent();
993
Ben Claytone1f30f12021-07-02 22:17:25 +0000994 if (!EmitStatements(stmt->body()->statements())) {
995 return false;
dan sinclair0d004022020-03-20 19:07:00 +0000996 }
997
998 if (stmt->has_continuing()) {
Ben Claytone1f30f12021-07-02 22:17:25 +0000999 line();
1000 line() << "continuing {";
1001 if (!EmitStatementsWithIndent(stmt->continuing()->statements())) {
dan sinclair09842142020-03-25 18:54:01 +00001002 return false;
dan sinclair0d004022020-03-20 19:07:00 +00001003 }
Ben Claytone1f30f12021-07-02 22:17:25 +00001004 line() << "}";
dan sinclair0d004022020-03-20 19:07:00 +00001005 }
1006
1007 decrement_indent();
Ben Claytone1f30f12021-07-02 22:17:25 +00001008 line() << "}";
dan sinclair0d004022020-03-20 19:07:00 +00001009
1010 return true;
1011}
1012
Ben Claytonefc46c12021-07-02 19:27:42 +00001013bool GeneratorImpl::EmitForLoop(ast::ForLoopStatement* stmt) {
Ben Claytone1f30f12021-07-02 22:17:25 +00001014 TextBuffer init_buf;
1015 if (auto* init = stmt->initializer()) {
1016 TINT_SCOPED_ASSIGNMENT(current_buffer_, &init_buf);
1017 if (!EmitStatement(init)) {
1018 return false;
Ben Claytonefc46c12021-07-02 19:27:42 +00001019 }
1020 }
1021
Ben Claytone1f30f12021-07-02 22:17:25 +00001022 TextBuffer cont_buf;
1023 if (auto* cont = stmt->continuing()) {
1024 TINT_SCOPED_ASSIGNMENT(current_buffer_, &cont_buf);
1025 if (!EmitStatement(cont)) {
1026 return false;
1027 }
1028 }
1029
1030 {
1031 auto out = line();
1032 out << "for";
1033 {
1034 ScopedParen sp(out);
1035 switch (init_buf.lines.size()) {
1036 case 0: // No initializer
1037 out << ";";
1038 break;
1039 case 1: // Single line initializer statement
1040 out << init_buf.lines[0].content;
1041 break;
1042 default: // Block initializer statement
1043 current_buffer_->Append(init_buf);
1044 break;
1045 }
1046
1047 out << " ";
1048
1049 if (auto* cond = stmt->condition()) {
1050 if (!EmitExpression(out, cond)) {
1051 return false;
1052 }
1053 }
1054
1055 out << "; ";
1056
1057 switch (cont_buf.lines.size()) {
1058 case 0: // No continuing
1059 out << ";";
1060 break;
1061 case 1: // Single line continuing statement
1062 out << TrimSuffix(cont_buf.lines[0].content, ";");
1063 break;
1064 default: // Block continuing statement
1065 current_buffer_->Append(cont_buf);
1066 break;
1067 }
1068 }
1069 out << " {";
1070 }
1071
1072 if (!EmitStatementsWithIndent(stmt->body()->statements())) {
1073 return false;
1074 }
1075
1076 line() << "}";
Ben Claytonefc46c12021-07-02 19:27:42 +00001077
1078 return true;
1079}
1080
1081bool GeneratorImpl::EmitReturn(ast::ReturnStatement* stmt) {
Ben Claytone1f30f12021-07-02 22:17:25 +00001082 auto out = line();
1083 out << "return";
dan sinclair2a6e2752020-03-20 19:05:10 +00001084 if (stmt->has_value()) {
Ben Claytone1f30f12021-07-02 22:17:25 +00001085 out << " ";
1086 if (!EmitExpression(out, stmt->value())) {
dan sinclair2a6e2752020-03-20 19:05:10 +00001087 return false;
1088 }
1089 }
Ben Claytone1f30f12021-07-02 22:17:25 +00001090 out << ";";
dan sinclair2a6e2752020-03-20 19:05:10 +00001091 return true;
1092}
1093
dan sinclair5f64aee2020-03-20 19:06:52 +00001094bool GeneratorImpl::EmitSwitch(ast::SwitchStatement* stmt) {
Ben Claytone1f30f12021-07-02 22:17:25 +00001095 {
1096 auto out = line();
1097 out << "switch(";
1098 if (!EmitExpression(out, stmt->condition())) {
dan sinclair5f64aee2020-03-20 19:06:52 +00001099 return false;
1100 }
Ben Claytone1f30f12021-07-02 22:17:25 +00001101 out << ") {";
1102 }
1103
1104 {
1105 ScopedIndent si(this);
1106 for (auto* s : stmt->body()) {
1107 if (!EmitCase(s)) {
1108 return false;
1109 }
1110 }
dan sinclair5f64aee2020-03-20 19:06:52 +00001111 }
1112
Ben Claytone1f30f12021-07-02 22:17:25 +00001113 line() << "}";
dan sinclair5f64aee2020-03-20 19:06:52 +00001114 return true;
1115}
1116
dan sinclaird9e9ff32020-03-12 12:40:01 +00001117} // namespace wgsl
1118} // namespace writer
1119} // namespace tint