James Price | dfd1714 | 2021-02-10 15:34:37 +0000 | [diff] [blame] | 1 | // Copyright 2021 The Tint Authors. |
dan sinclair | d9e9ff3 | 2020-03-12 12:40:01 +0000 | [diff] [blame] | 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | |
| 15 | #include "src/writer/wgsl/generator_impl.h" |
| 16 | |
Ben Clayton | 22a9f17 | 2021-02-10 16:41:23 +0000 | [diff] [blame] | 17 | #include <algorithm> |
dan sinclair | d9e9ff3 | 2020-03-12 12:40:01 +0000 | [diff] [blame] | 18 | |
Ben Clayton | 93e8f52 | 2021-06-04 20:41:47 +0000 | [diff] [blame] | 19 | #include "src/ast/access.h" |
Ben Clayton | 083b591 | 2021-04-30 16:01:29 +0000 | [diff] [blame] | 20 | #include "src/ast/alias.h" |
| 21 | #include "src/ast/array.h" |
Ben Clayton | 0a32a72 | 2021-06-18 18:56:13 +0000 | [diff] [blame] | 22 | #include "src/ast/atomic.h" |
Ben Clayton | 083b591 | 2021-04-30 16:01:29 +0000 | [diff] [blame] | 23 | #include "src/ast/bool.h" |
dan sinclair | 9d9d7cd | 2020-03-18 20:05:44 +0000 | [diff] [blame] | 24 | #include "src/ast/bool_literal.h" |
dan sinclair | b44fe3c | 2020-07-21 13:44:27 +0000 | [diff] [blame] | 25 | #include "src/ast/call_statement.h" |
Ben Clayton | 083b591 | 2021-04-30 16:01:29 +0000 | [diff] [blame] | 26 | #include "src/ast/depth_texture.h" |
Ben Clayton | f5163d0 | 2021-06-02 20:12:34 +0000 | [diff] [blame] | 27 | #include "src/ast/external_texture.h" |
Ben Clayton | 083b591 | 2021-04-30 16:01:29 +0000 | [diff] [blame] | 28 | #include "src/ast/f32.h" |
dan sinclair | 9d9d7cd | 2020-03-18 20:05:44 +0000 | [diff] [blame] | 29 | #include "src/ast/float_literal.h" |
Ben Clayton | 083b591 | 2021-04-30 16:01:29 +0000 | [diff] [blame] | 30 | #include "src/ast/i32.h" |
Ben Clayton | b502fdf | 2021-04-07 08:09:21 +0000 | [diff] [blame] | 31 | #include "src/ast/internal_decoration.h" |
James Price | 545f4e0 | 2021-06-28 23:04:43 +0000 | [diff] [blame] | 32 | #include "src/ast/interpolate_decoration.h" |
James Price | fcc0de0 | 2021-07-12 12:28:52 +0000 | [diff] [blame] | 33 | #include "src/ast/invariant_decoration.h" |
Ben Clayton | 083b591 | 2021-04-30 16:01:29 +0000 | [diff] [blame] | 34 | #include "src/ast/matrix.h" |
Ben Clayton | a6b9a8e | 2021-01-26 16:57:10 +0000 | [diff] [blame] | 35 | #include "src/ast/module.h" |
Ben Clayton | 083b591 | 2021-04-30 16:01:29 +0000 | [diff] [blame] | 36 | #include "src/ast/multisampled_texture.h" |
James Price | e87ded8 | 2021-04-30 17:14:19 +0000 | [diff] [blame] | 37 | #include "src/ast/override_decoration.h" |
Ben Clayton | 083b591 | 2021-04-30 16:01:29 +0000 | [diff] [blame] | 38 | #include "src/ast/pointer.h" |
| 39 | #include "src/ast/sampled_texture.h" |
dan sinclair | c6f2947 | 2020-06-02 20:11:44 +0000 | [diff] [blame] | 40 | #include "src/ast/sint_literal.h" |
dan sinclair | 48d08d2 | 2020-09-21 17:59:51 +0000 | [diff] [blame] | 41 | #include "src/ast/stage_decoration.h" |
Ben Clayton | 083b591 | 2021-04-30 16:01:29 +0000 | [diff] [blame] | 42 | #include "src/ast/storage_texture.h" |
dan sinclair | eb5d3e1 | 2020-10-08 19:34:25 +0000 | [diff] [blame] | 43 | #include "src/ast/stride_decoration.h" |
Ben Clayton | 688fe44 | 2021-05-13 12:38:12 +0000 | [diff] [blame] | 44 | #include "src/ast/struct_block_decoration.h" |
Ben Clayton | d614dd5 | 2021-03-15 10:43:11 +0000 | [diff] [blame] | 45 | #include "src/ast/struct_member_align_decoration.h" |
dan sinclair | d9e9ff3 | 2020-03-12 12:40:01 +0000 | [diff] [blame] | 46 | #include "src/ast/struct_member_offset_decoration.h" |
Ben Clayton | d614dd5 | 2021-03-15 10:43:11 +0000 | [diff] [blame] | 47 | #include "src/ast/struct_member_size_decoration.h" |
Ben Clayton | 083b591 | 2021-04-30 16:01:29 +0000 | [diff] [blame] | 48 | #include "src/ast/type_name.h" |
| 49 | #include "src/ast/u32.h" |
dan sinclair | 9d9d7cd | 2020-03-18 20:05:44 +0000 | [diff] [blame] | 50 | #include "src/ast/uint_literal.h" |
dan sinclair | e49bd5e | 2020-03-30 22:46:48 +0000 | [diff] [blame] | 51 | #include "src/ast/variable_decl_statement.h" |
Ben Clayton | 083b591 | 2021-04-30 16:01:29 +0000 | [diff] [blame] | 52 | #include "src/ast/vector.h" |
| 53 | #include "src/ast/void.h" |
dan sinclair | 6438279 | 2020-09-21 00:28:58 +0000 | [diff] [blame] | 54 | #include "src/ast/workgroup_decoration.h" |
Antonio Maiorano | 5cd71b8 | 2021-04-16 19:07:51 +0000 | [diff] [blame] | 55 | #include "src/sem/struct.h" |
Ben Clayton | 822fa54 | 2021-03-15 20:25:12 +0000 | [diff] [blame] | 56 | #include "src/utils/math.h" |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 57 | #include "src/utils/scoped_assignment.h" |
Ben Clayton | 2da833d | 2020-11-20 10:04:44 +0000 | [diff] [blame] | 58 | #include "src/writer/float_to_string.h" |
dan sinclair | d9e9ff3 | 2020-03-12 12:40:01 +0000 | [diff] [blame] | 59 | |
| 60 | namespace tint { |
| 61 | namespace writer { |
| 62 | namespace wgsl { |
| 63 | |
Ben Clayton | f2ec7f3 | 2021-06-29 11:53:15 +0000 | [diff] [blame] | 64 | GeneratorImpl::GeneratorImpl(const Program* program) : TextGenerator(program) {} |
dan sinclair | d9e9ff3 | 2020-03-12 12:40:01 +0000 | [diff] [blame] | 65 | |
| 66 | GeneratorImpl::~GeneratorImpl() = default; |
| 67 | |
Ben Clayton | 688fe44 | 2021-05-13 12:38:12 +0000 | [diff] [blame] | 68 | bool GeneratorImpl::Generate() { |
James Price | dfd1714 | 2021-02-10 15:34:37 +0000 | [diff] [blame] | 69 | // Generate global declarations in the order they appear in the module. |
| 70 | for (auto* decl : program_->AST().GlobalDeclarations()) { |
Ben Clayton | 8758f10 | 2021-06-09 14:32:14 +0000 | [diff] [blame] | 71 | if (auto* td = decl->As<ast::TypeDecl>()) { |
Ben Clayton | 950809f | 2021-06-09 14:32:14 +0000 | [diff] [blame] | 72 | if (!EmitTypeDecl(td)) { |
James Price | dfd1714 | 2021-02-10 15:34:37 +0000 | [diff] [blame] | 73 | return false; |
| 74 | } |
| 75 | } else if (auto* func = decl->As<ast::Function>()) { |
James Price | dfd1714 | 2021-02-10 15:34:37 +0000 | [diff] [blame] | 76 | if (!EmitFunction(func)) { |
| 77 | return false; |
| 78 | } |
| 79 | } else if (auto* var = decl->As<ast::Variable>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 80 | if (!EmitVariable(line(), var)) { |
James Price | dfd1714 | 2021-02-10 15:34:37 +0000 | [diff] [blame] | 81 | return false; |
| 82 | } |
| 83 | } else { |
Ben Clayton | ffd28e2 | 2021-06-24 11:27:36 +0000 | [diff] [blame] | 84 | TINT_UNREACHABLE(Writer, diagnostics_); |
Ben Clayton | 6b4924f | 2021-02-17 20:13:34 +0000 | [diff] [blame] | 85 | return false; |
dan sinclair | d9e9ff3 | 2020-03-12 12:40:01 +0000 | [diff] [blame] | 86 | } |
dan sinclair | d9e9ff3 | 2020-03-12 12:40:01 +0000 | [diff] [blame] | 87 | |
James Price | dfd1714 | 2021-02-10 15:34:37 +0000 | [diff] [blame] | 88 | if (decl != program_->AST().GlobalDeclarations().back()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 89 | line(); |
dan sinclair | d9e9ff3 | 2020-03-12 12:40:01 +0000 | [diff] [blame] | 90 | } |
| 91 | } |
dan sinclair | 3740fd2 | 2020-03-20 19:09:04 +0000 | [diff] [blame] | 92 | |
dan sinclair | d9e9ff3 | 2020-03-12 12:40:01 +0000 | [diff] [blame] | 93 | return true; |
| 94 | } |
| 95 | |
Ben Clayton | 950809f | 2021-06-09 14:32:14 +0000 | [diff] [blame] | 96 | bool GeneratorImpl::EmitTypeDecl(const ast::TypeDecl* ty) { |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 97 | if (auto* alias = ty->As<ast::Alias>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 98 | auto out = line(); |
| 99 | out << "type " << program_->Symbols().NameFor(alias->symbol()) << " = "; |
| 100 | if (!EmitType(out, alias->type())) { |
dan sinclair | 0ce0704 | 2020-10-21 19:15:20 +0000 | [diff] [blame] | 101 | return false; |
dan sinclair | 7156d3e | 2020-10-19 15:31:47 +0000 | [diff] [blame] | 102 | } |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 103 | out << ";"; |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 104 | } else if (auto* str = ty->As<ast::Struct>()) { |
| 105 | if (!EmitStructType(str)) { |
Ben Clayton | 083b591 | 2021-04-30 16:01:29 +0000 | [diff] [blame] | 106 | return false; |
| 107 | } |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 108 | } else { |
Ben Clayton | ffd28e2 | 2021-06-24 11:27:36 +0000 | [diff] [blame] | 109 | diagnostics_.add_error( |
| 110 | diag::System::Writer, |
| 111 | "unknown declared type: " + std::string(ty->TypeInfo().name)); |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 112 | return false; |
Ben Clayton | 083b591 | 2021-04-30 16:01:29 +0000 | [diff] [blame] | 113 | } |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 114 | return true; |
dan sinclair | d9e9ff3 | 2020-03-12 12:40:01 +0000 | [diff] [blame] | 115 | } |
| 116 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 117 | bool GeneratorImpl::EmitExpression(std::ostream& out, ast::Expression* expr) { |
Ben Clayton | d6ae990 | 2020-11-30 23:30:58 +0000 | [diff] [blame] | 118 | if (auto* a = expr->As<ast::ArrayAccessorExpression>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 119 | return EmitArrayAccessor(out, a); |
dan sinclair | 9d9d7cd | 2020-03-18 20:05:44 +0000 | [diff] [blame] | 120 | } |
Ben Clayton | d6ae990 | 2020-11-30 23:30:58 +0000 | [diff] [blame] | 121 | if (auto* b = expr->As<ast::BinaryExpression>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 122 | return EmitBinary(out, b); |
dan sinclair | 1c9b486 | 2020-04-07 19:27:41 +0000 | [diff] [blame] | 123 | } |
Ben Clayton | d6ae990 | 2020-11-30 23:30:58 +0000 | [diff] [blame] | 124 | if (auto* b = expr->As<ast::BitcastExpression>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 125 | return EmitBitcast(out, b); |
dan sinclair | a7d498e | 2020-09-22 22:07:13 +0000 | [diff] [blame] | 126 | } |
Ben Clayton | d6ae990 | 2020-11-30 23:30:58 +0000 | [diff] [blame] | 127 | if (auto* c = expr->As<ast::CallExpression>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 128 | return EmitCall(out, c); |
dan sinclair | c80d5ed | 2020-03-19 02:51:27 +0000 | [diff] [blame] | 129 | } |
Ben Clayton | d6ae990 | 2020-11-30 23:30:58 +0000 | [diff] [blame] | 130 | if (auto* i = expr->As<ast::IdentifierExpression>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 131 | return EmitIdentifier(out, i); |
dan sinclair | 9d9d7cd | 2020-03-18 20:05:44 +0000 | [diff] [blame] | 132 | } |
Ben Clayton | d6ae990 | 2020-11-30 23:30:58 +0000 | [diff] [blame] | 133 | if (auto* c = expr->As<ast::ConstructorExpression>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 134 | return EmitConstructor(out, c); |
dan sinclair | 9d9d7cd | 2020-03-18 20:05:44 +0000 | [diff] [blame] | 135 | } |
Ben Clayton | d6ae990 | 2020-11-30 23:30:58 +0000 | [diff] [blame] | 136 | if (auto* m = expr->As<ast::MemberAccessorExpression>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 137 | return EmitMemberAccessor(out, m); |
dan sinclair | 2c56dd9 | 2020-03-19 02:55:19 +0000 | [diff] [blame] | 138 | } |
Ben Clayton | d6ae990 | 2020-11-30 23:30:58 +0000 | [diff] [blame] | 139 | if (auto* u = expr->As<ast::UnaryOpExpression>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 140 | return EmitUnaryOp(out, u); |
dan sinclair | daff3e2 | 2020-03-20 19:01:47 +0000 | [diff] [blame] | 141 | } |
dan sinclair | 9d9d7cd | 2020-03-18 20:05:44 +0000 | [diff] [blame] | 142 | |
Ben Clayton | ffd28e2 | 2021-06-24 11:27:36 +0000 | [diff] [blame] | 143 | diagnostics_.add_error(diag::System::Writer, "unknown expression type"); |
dan sinclair | 9d9d7cd | 2020-03-18 20:05:44 +0000 | [diff] [blame] | 144 | return false; |
| 145 | } |
| 146 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 147 | bool GeneratorImpl::EmitArrayAccessor(std::ostream& out, |
| 148 | ast::ArrayAccessorExpression* expr) { |
James Price | b487c71 | 2021-06-01 12:18:10 +0000 | [diff] [blame] | 149 | 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 Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 155 | out << "("; |
James Price | b487c71 | 2021-06-01 12:18:10 +0000 | [diff] [blame] | 156 | } |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 157 | if (!EmitExpression(out, expr->array())) { |
dan sinclair | 306a2f8 | 2020-03-12 12:43:05 +0000 | [diff] [blame] | 158 | return false; |
| 159 | } |
James Price | b487c71 | 2021-06-01 12:18:10 +0000 | [diff] [blame] | 160 | if (paren_lhs) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 161 | out << ")"; |
James Price | b487c71 | 2021-06-01 12:18:10 +0000 | [diff] [blame] | 162 | } |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 163 | out << "["; |
dan sinclair | 9d9d7cd | 2020-03-18 20:05:44 +0000 | [diff] [blame] | 164 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 165 | if (!EmitExpression(out, expr->idx_expr())) { |
dan sinclair | 9d9d7cd | 2020-03-18 20:05:44 +0000 | [diff] [blame] | 166 | return false; |
| 167 | } |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 168 | out << "]"; |
dan sinclair | 9d9d7cd | 2020-03-18 20:05:44 +0000 | [diff] [blame] | 169 | |
| 170 | return true; |
| 171 | } |
| 172 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 173 | bool GeneratorImpl::EmitMemberAccessor(std::ostream& out, |
| 174 | ast::MemberAccessorExpression* expr) { |
Ben Clayton | ee449e2 | 2021-05-19 08:29:58 +0000 | [diff] [blame] | 175 | 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 Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 181 | out << "("; |
Ben Clayton | ee449e2 | 2021-05-19 08:29:58 +0000 | [diff] [blame] | 182 | } |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 183 | if (!EmitExpression(out, expr->structure())) { |
dan sinclair | 2c56dd9 | 2020-03-19 02:55:19 +0000 | [diff] [blame] | 184 | return false; |
| 185 | } |
Ben Clayton | ee449e2 | 2021-05-19 08:29:58 +0000 | [diff] [blame] | 186 | if (paren_lhs) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 187 | out << ")"; |
Ben Clayton | ee449e2 | 2021-05-19 08:29:58 +0000 | [diff] [blame] | 188 | } |
dan sinclair | 2c56dd9 | 2020-03-19 02:55:19 +0000 | [diff] [blame] | 189 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 190 | out << "."; |
dan sinclair | 2c56dd9 | 2020-03-19 02:55:19 +0000 | [diff] [blame] | 191 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 192 | return EmitExpression(out, expr->member()); |
dan sinclair | 2c56dd9 | 2020-03-19 02:55:19 +0000 | [diff] [blame] | 193 | } |
| 194 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 195 | bool GeneratorImpl::EmitBitcast(std::ostream& out, |
| 196 | ast::BitcastExpression* expr) { |
| 197 | out << "bitcast<"; |
| 198 | if (!EmitType(out, expr->type())) { |
dan sinclair | cd49b59 | 2020-03-18 20:33:00 +0000 | [diff] [blame] | 199 | return false; |
| 200 | } |
| 201 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 202 | out << ">("; |
| 203 | if (!EmitExpression(out, expr->expr())) { |
dan sinclair | cd49b59 | 2020-03-18 20:33:00 +0000 | [diff] [blame] | 204 | return false; |
| 205 | } |
| 206 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 207 | out << ")"; |
dan sinclair | cd49b59 | 2020-03-18 20:33:00 +0000 | [diff] [blame] | 208 | return true; |
| 209 | } |
| 210 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 211 | bool GeneratorImpl::EmitCall(std::ostream& out, ast::CallExpression* expr) { |
| 212 | if (!EmitExpression(out, expr->func())) { |
dan sinclair | c80d5ed | 2020-03-19 02:51:27 +0000 | [diff] [blame] | 213 | return false; |
| 214 | } |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 215 | out << "("; |
dan sinclair | c80d5ed | 2020-03-19 02:51:27 +0000 | [diff] [blame] | 216 | |
| 217 | bool first = true; |
| 218 | const auto& params = expr->params(); |
Ben Clayton | b053acf | 2020-11-16 16:31:07 +0000 | [diff] [blame] | 219 | for (auto* param : params) { |
dan sinclair | c80d5ed | 2020-03-19 02:51:27 +0000 | [diff] [blame] | 220 | if (!first) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 221 | out << ", "; |
dan sinclair | c80d5ed | 2020-03-19 02:51:27 +0000 | [diff] [blame] | 222 | } |
| 223 | first = false; |
| 224 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 225 | if (!EmitExpression(out, param)) { |
dan sinclair | c80d5ed | 2020-03-19 02:51:27 +0000 | [diff] [blame] | 226 | return false; |
| 227 | } |
| 228 | } |
| 229 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 230 | out << ")"; |
dan sinclair | c80d5ed | 2020-03-19 02:51:27 +0000 | [diff] [blame] | 231 | |
| 232 | return true; |
| 233 | } |
| 234 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 235 | bool GeneratorImpl::EmitConstructor(std::ostream& out, |
| 236 | ast::ConstructorExpression* expr) { |
Ben Clayton | 19fe072 | 2020-11-30 23:30:58 +0000 | [diff] [blame] | 237 | if (auto* scalar = expr->As<ast::ScalarConstructorExpression>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 238 | return EmitScalarConstructor(out, scalar); |
dan sinclair | 9d9d7cd | 2020-03-18 20:05:44 +0000 | [diff] [blame] | 239 | } |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 240 | return EmitTypeConstructor(out, expr->As<ast::TypeConstructorExpression>()); |
dan sinclair | 9d9d7cd | 2020-03-18 20:05:44 +0000 | [diff] [blame] | 241 | } |
| 242 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 243 | bool GeneratorImpl::EmitTypeConstructor(std::ostream& out, |
| 244 | ast::TypeConstructorExpression* expr) { |
| 245 | if (!EmitType(out, expr->type())) { |
dan sinclair | 9d9d7cd | 2020-03-18 20:05:44 +0000 | [diff] [blame] | 246 | return false; |
| 247 | } |
| 248 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 249 | out << "("; |
dan sinclair | 9d9d7cd | 2020-03-18 20:05:44 +0000 | [diff] [blame] | 250 | |
| 251 | bool first = true; |
Ben Clayton | b053acf | 2020-11-16 16:31:07 +0000 | [diff] [blame] | 252 | for (auto* e : expr->values()) { |
dan sinclair | 9d9d7cd | 2020-03-18 20:05:44 +0000 | [diff] [blame] | 253 | if (!first) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 254 | out << ", "; |
dan sinclair | 9d9d7cd | 2020-03-18 20:05:44 +0000 | [diff] [blame] | 255 | } |
| 256 | first = false; |
| 257 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 258 | if (!EmitExpression(out, e)) { |
dan sinclair | 9d9d7cd | 2020-03-18 20:05:44 +0000 | [diff] [blame] | 259 | return false; |
| 260 | } |
| 261 | } |
| 262 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 263 | out << ")"; |
dan sinclair | 9d9d7cd | 2020-03-18 20:05:44 +0000 | [diff] [blame] | 264 | return true; |
| 265 | } |
| 266 | |
dan sinclair | a322f5d | 2020-03-30 22:46:06 +0000 | [diff] [blame] | 267 | bool GeneratorImpl::EmitScalarConstructor( |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 268 | std::ostream& out, |
dan sinclair | a322f5d | 2020-03-30 22:46:06 +0000 | [diff] [blame] | 269 | ast::ScalarConstructorExpression* expr) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 270 | return EmitLiteral(out, expr->literal()); |
dan sinclair | 37f4fb0 | 2020-03-20 19:04:45 +0000 | [diff] [blame] | 271 | } |
| 272 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 273 | bool GeneratorImpl::EmitLiteral(std::ostream& out, ast::Literal* lit) { |
Ben Clayton | 1b6a8ce | 2020-12-01 21:07:27 +0000 | [diff] [blame] | 274 | if (auto* bl = lit->As<ast::BoolLiteral>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 275 | out << (bl->IsTrue() ? "true" : "false"); |
Ben Clayton | 1b6a8ce | 2020-12-01 21:07:27 +0000 | [diff] [blame] | 276 | } else if (auto* fl = lit->As<ast::FloatLiteral>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 277 | out << FloatToBitPreservingString(fl->value()); |
Ben Clayton | 1b6a8ce | 2020-12-01 21:07:27 +0000 | [diff] [blame] | 278 | } else if (auto* sl = lit->As<ast::SintLiteral>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 279 | out << sl->value(); |
Ben Clayton | 1b6a8ce | 2020-12-01 21:07:27 +0000 | [diff] [blame] | 280 | } else if (auto* ul = lit->As<ast::UintLiteral>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 281 | out << ul->value() << "u"; |
dan sinclair | 9d9d7cd | 2020-03-18 20:05:44 +0000 | [diff] [blame] | 282 | } else { |
Ben Clayton | ffd28e2 | 2021-06-24 11:27:36 +0000 | [diff] [blame] | 283 | diagnostics_.add_error(diag::System::Writer, "unknown literal type"); |
dan sinclair | 9d9d7cd | 2020-03-18 20:05:44 +0000 | [diff] [blame] | 284 | return false; |
| 285 | } |
| 286 | return true; |
| 287 | } |
| 288 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 289 | bool GeneratorImpl::EmitIdentifier(std::ostream& out, |
| 290 | ast::IdentifierExpression* expr) { |
| 291 | out << program_->Symbols().NameFor(expr->symbol()); |
dan sinclair | 306a2f8 | 2020-03-12 12:43:05 +0000 | [diff] [blame] | 292 | return true; |
| 293 | } |
| 294 | |
dan sinclair | 3740fd2 | 2020-03-20 19:09:04 +0000 | [diff] [blame] | 295 | bool GeneratorImpl::EmitFunction(ast::Function* func) { |
Ben Clayton | 451f2cc | 2021-05-12 12:54:21 +0000 | [diff] [blame] | 296 | if (func->decorations().size()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 297 | if (!EmitDecorations(line(), func->decorations())) { |
dan sinclair | 3740fd2 | 2020-03-20 19:09:04 +0000 | [diff] [blame] | 298 | return false; |
| 299 | } |
| 300 | } |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 301 | { |
| 302 | auto out = line(); |
| 303 | out << "fn " << program_->Symbols().NameFor(func->symbol()) << "("; |
dan sinclair | 3740fd2 | 2020-03-20 19:09:04 +0000 | [diff] [blame] | 304 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 305 | bool first = true; |
| 306 | for (auto* v : func->params()) { |
| 307 | if (!first) { |
| 308 | out << ", "; |
| 309 | } |
| 310 | first = false; |
dan sinclair | 3740fd2 | 2020-03-20 19:09:04 +0000 | [diff] [blame] | 311 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 312 | if (!v->decorations().empty()) { |
| 313 | if (!EmitDecorations(out, v->decorations())) { |
| 314 | return false; |
| 315 | } |
| 316 | out << " "; |
| 317 | } |
Ben Clayton | 9328d94 | 2021-04-08 14:39:47 +0000 | [diff] [blame] | 318 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 319 | out << program_->Symbols().NameFor(v->symbol()) << " : "; |
| 320 | |
| 321 | if (!EmitType(out, v->type())) { |
Ben Clayton | 9328d94 | 2021-04-08 14:39:47 +0000 | [diff] [blame] | 322 | return false; |
| 323 | } |
Ben Clayton | 9328d94 | 2021-04-08 14:39:47 +0000 | [diff] [blame] | 324 | } |
| 325 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 326 | 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 Price | cc193de | 2021-03-15 17:15:23 +0000 | [diff] [blame] | 346 | } |
dan sinclair | 3740fd2 | 2020-03-20 19:09:04 +0000 | [diff] [blame] | 347 | } |
| 348 | |
Ben Clayton | b502fdf | 2021-04-07 08:09:21 +0000 | [diff] [blame] | 349 | if (func->body()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 350 | if (!EmitStatementsWithIndent(func->body()->statements())) { |
| 351 | return false; |
| 352 | } |
| 353 | line() << "}"; |
Ben Clayton | b502fdf | 2021-04-07 08:09:21 +0000 | [diff] [blame] | 354 | } |
| 355 | |
| 356 | return true; |
dan sinclair | 3740fd2 | 2020-03-20 19:09:04 +0000 | [diff] [blame] | 357 | } |
| 358 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 359 | bool GeneratorImpl::EmitImageFormat(std::ostream& out, |
| 360 | const ast::ImageFormat fmt) { |
dan sinclair | 83ed2cc | 2020-09-17 02:51:03 +0000 | [diff] [blame] | 361 | switch (fmt) { |
Ben Clayton | fec63b7 | 2021-04-21 13:47:12 +0000 | [diff] [blame] | 362 | case ast::ImageFormat::kNone: |
Ben Clayton | ffd28e2 | 2021-06-24 11:27:36 +0000 | [diff] [blame] | 363 | diagnostics_.add_error(diag::System::Writer, "unknown image format"); |
dan sinclair | 83ed2cc | 2020-09-17 02:51:03 +0000 | [diff] [blame] | 364 | return false; |
dan sinclair | b5e5b80 | 2020-10-05 19:55:56 +0000 | [diff] [blame] | 365 | default: |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 366 | out << fmt; |
dan sinclair | 83ed2cc | 2020-09-17 02:51:03 +0000 | [diff] [blame] | 367 | } |
| 368 | return true; |
| 369 | } |
| 370 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 371 | bool GeneratorImpl::EmitAccess(std::ostream& out, const ast::Access access) { |
Ben Clayton | 93e8f52 | 2021-06-04 20:41:47 +0000 | [diff] [blame] | 372 | switch (access) { |
| 373 | case ast::Access::kRead: |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 374 | out << "read"; |
Ben Clayton | 93e8f52 | 2021-06-04 20:41:47 +0000 | [diff] [blame] | 375 | return true; |
| 376 | case ast::Access::kWrite: |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 377 | out << "write"; |
Ben Clayton | 93e8f52 | 2021-06-04 20:41:47 +0000 | [diff] [blame] | 378 | return true; |
| 379 | case ast::Access::kReadWrite: |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 380 | out << "read_write"; |
Ben Clayton | 93e8f52 | 2021-06-04 20:41:47 +0000 | [diff] [blame] | 381 | return true; |
| 382 | default: |
| 383 | break; |
| 384 | } |
Ben Clayton | ffd28e2 | 2021-06-24 11:27:36 +0000 | [diff] [blame] | 385 | diagnostics_.add_error(diag::System::Writer, "unknown access"); |
Ben Clayton | 93e8f52 | 2021-06-04 20:41:47 +0000 | [diff] [blame] | 386 | return false; |
| 387 | } |
| 388 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 389 | bool GeneratorImpl::EmitType(std::ostream& out, const ast::Type* ty) { |
Ben Clayton | 8758f10 | 2021-06-09 14:32:14 +0000 | [diff] [blame] | 390 | if (auto* ary = ty->As<ast::Array>()) { |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 391 | for (auto* deco : ary->decorations()) { |
| 392 | if (auto* stride = deco->As<ast::StrideDecoration>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 393 | out << "[[stride(" << stride->stride() << ")]] "; |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 394 | } |
| 395 | } |
dan sinclair | d9e9ff3 | 2020-03-12 12:40:01 +0000 | [diff] [blame] | 396 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 397 | out << "array<"; |
| 398 | if (!EmitType(out, ary->type())) { |
Ben Clayton | 083b591 | 2021-04-30 16:01:29 +0000 | [diff] [blame] | 399 | return false; |
| 400 | } |
Ben Clayton | 083b591 | 2021-04-30 16:01:29 +0000 | [diff] [blame] | 401 | |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 402 | if (!ary->IsRuntimeArray()) |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 403 | out << ", " << ary->size(); |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 404 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 405 | out << ">"; |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 406 | } else if (ty->Is<ast::Bool>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 407 | out << "bool"; |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 408 | } else if (ty->Is<ast::F32>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 409 | out << "f32"; |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 410 | } else if (ty->Is<ast::I32>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 411 | out << "i32"; |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 412 | } else if (auto* mat = ty->As<ast::Matrix>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 413 | out << "mat" << mat->columns() << "x" << mat->rows() << "<"; |
| 414 | if (!EmitType(out, mat->type())) { |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 415 | return false; |
| 416 | } |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 417 | out << ">"; |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 418 | } else if (auto* ptr = ty->As<ast::Pointer>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 419 | out << "ptr<" << ptr->storage_class() << ", "; |
| 420 | if (!EmitType(out, ptr->type())) { |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 421 | return false; |
| 422 | } |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 423 | out << ">"; |
Ben Clayton | 0a32a72 | 2021-06-18 18:56:13 +0000 | [diff] [blame] | 424 | } else if (auto* atomic = ty->As<ast::Atomic>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 425 | out << "atomic<"; |
| 426 | if (!EmitType(out, atomic->type())) { |
Ben Clayton | 0a32a72 | 2021-06-18 18:56:13 +0000 | [diff] [blame] | 427 | return false; |
| 428 | } |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 429 | out << ">"; |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 430 | } else if (auto* sampler = ty->As<ast::Sampler>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 431 | out << "sampler"; |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 432 | |
| 433 | if (sampler->IsComparison()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 434 | out << "_comparison"; |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 435 | } |
Ben Clayton | f5163d0 | 2021-06-02 20:12:34 +0000 | [diff] [blame] | 436 | } else if (ty->Is<ast::ExternalTexture>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 437 | out << "external_texture"; |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 438 | } else if (auto* texture = ty->As<ast::Texture>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 439 | out << "texture_"; |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 440 | if (texture->Is<ast::DepthTexture>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 441 | out << "depth_"; |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 442 | } else if (texture->Is<ast::SampledTexture>()) { |
| 443 | /* nothing to emit */ |
| 444 | } else if (texture->Is<ast::MultisampledTexture>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 445 | out << "multisampled_"; |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 446 | } else if (texture->Is<ast::StorageTexture>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 447 | out << "storage_"; |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 448 | } else { |
Ben Clayton | ffd28e2 | 2021-06-24 11:27:36 +0000 | [diff] [blame] | 449 | diagnostics_.add_error(diag::System::Writer, "unknown texture type"); |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 450 | return false; |
| 451 | } |
| 452 | |
| 453 | switch (texture->dim()) { |
| 454 | case ast::TextureDimension::k1d: |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 455 | out << "1d"; |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 456 | break; |
| 457 | case ast::TextureDimension::k2d: |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 458 | out << "2d"; |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 459 | break; |
| 460 | case ast::TextureDimension::k2dArray: |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 461 | out << "2d_array"; |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 462 | break; |
| 463 | case ast::TextureDimension::k3d: |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 464 | out << "3d"; |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 465 | break; |
| 466 | case ast::TextureDimension::kCube: |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 467 | out << "cube"; |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 468 | break; |
| 469 | case ast::TextureDimension::kCubeArray: |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 470 | out << "cube_array"; |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 471 | break; |
| 472 | default: |
Ben Clayton | ffd28e2 | 2021-06-24 11:27:36 +0000 | [diff] [blame] | 473 | diagnostics_.add_error(diag::System::Writer, |
| 474 | "unknown texture dimension"); |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 475 | return false; |
| 476 | } |
| 477 | |
| 478 | if (auto* sampled = texture->As<ast::SampledTexture>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 479 | out << "<"; |
| 480 | if (!EmitType(out, sampled->type())) { |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 481 | return false; |
| 482 | } |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 483 | out << ">"; |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 484 | } else if (auto* ms = texture->As<ast::MultisampledTexture>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 485 | out << "<"; |
| 486 | if (!EmitType(out, ms->type())) { |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 487 | return false; |
| 488 | } |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 489 | out << ">"; |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 490 | } else if (auto* storage = texture->As<ast::StorageTexture>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 491 | out << "<"; |
| 492 | if (!EmitImageFormat(out, storage->image_format())) { |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 493 | return false; |
| 494 | } |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 495 | out << ", "; |
| 496 | if (!EmitAccess(out, storage->access())) { |
Ben Clayton | 93e8f52 | 2021-06-04 20:41:47 +0000 | [diff] [blame] | 497 | return false; |
| 498 | } |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 499 | out << ">"; |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 500 | } |
| 501 | |
| 502 | } else if (ty->Is<ast::U32>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 503 | out << "u32"; |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 504 | } else if (auto* vec = ty->As<ast::Vector>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 505 | out << "vec" << vec->size() << "<"; |
| 506 | if (!EmitType(out, vec->type())) { |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 507 | return false; |
| 508 | } |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 509 | out << ">"; |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 510 | } else if (ty->Is<ast::Void>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 511 | out << "void"; |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 512 | } else if (auto* tn = ty->As<ast::TypeName>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 513 | out << program_->Symbols().NameFor(tn->name()); |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 514 | } else { |
Ben Clayton | ffd28e2 | 2021-06-24 11:27:36 +0000 | [diff] [blame] | 515 | diagnostics_.add_error(diag::System::Writer, |
| 516 | "unknown type in EmitType: " + ty->type_name()); |
Ben Clayton | fb13f02 | 2021-05-07 15:05:44 +0000 | [diff] [blame] | 517 | return false; |
| 518 | } |
| 519 | return true; |
dan sinclair | d9e9ff3 | 2020-03-12 12:40:01 +0000 | [diff] [blame] | 520 | } |
| 521 | |
Ben Clayton | 083b591 | 2021-04-30 16:01:29 +0000 | [diff] [blame] | 522 | bool GeneratorImpl::EmitStructType(const ast::Struct* str) { |
Ben Clayton | 688fe44 | 2021-05-13 12:38:12 +0000 | [diff] [blame] | 523 | if (str->decorations().size()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 524 | if (!EmitDecorations(line(), str->decorations())) { |
Ben Clayton | 688fe44 | 2021-05-13 12:38:12 +0000 | [diff] [blame] | 525 | return false; |
| 526 | } |
dan sinclair | 7156d3e | 2020-10-19 15:31:47 +0000 | [diff] [blame] | 527 | } |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 528 | line() << "struct " << program_->Symbols().NameFor(str->name()) << " {"; |
dan sinclair | 7156d3e | 2020-10-19 15:31:47 +0000 | [diff] [blame] | 529 | |
Ben Clayton | 822fa54 | 2021-03-15 20:25:12 +0000 | [diff] [blame] | 530 | auto add_padding = [&](uint32_t size) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 531 | line() << "[[size(" << size << ")]]"; |
| 532 | |
Ben Clayton | 822fa54 | 2021-03-15 20:25:12 +0000 | [diff] [blame] | 533 | // Note: u32 is the smallest primitive we currently support. When WGSL |
| 534 | // supports smaller types, this will need to be updated. |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 535 | line() << UniqueIdentifier("padding") << " : u32;"; |
Ben Clayton | 822fa54 | 2021-03-15 20:25:12 +0000 | [diff] [blame] | 536 | }; |
| 537 | |
dan sinclair | 7156d3e | 2020-10-19 15:31:47 +0000 | [diff] [blame] | 538 | increment_indent(); |
Ben Clayton | 822fa54 | 2021-03-15 20:25:12 +0000 | [diff] [blame] | 539 | uint32_t offset = 0; |
Ben Clayton | 083b591 | 2021-04-30 16:01:29 +0000 | [diff] [blame] | 540 | for (auto* mem : str->members()) { |
Ben Clayton | 688fe44 | 2021-05-13 12:38:12 +0000 | [diff] [blame] | 541 | // 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 Clayton | 822fa54 | 2021-03-15 20:25:12 +0000 | [diff] [blame] | 550 | } |
Ben Clayton | 822fa54 | 2021-03-15 20:25:12 +0000 | [diff] [blame] | 551 | |
| 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 Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 564 | if (!EmitDecorations(line(), decorations_sanitized)) { |
James Price | d3e3681 | 2021-03-11 17:47:52 +0000 | [diff] [blame] | 565 | return false; |
| 566 | } |
dan sinclair | 7156d3e | 2020-10-19 15:31:47 +0000 | [diff] [blame] | 567 | } |
James Price | d3e3681 | 2021-03-11 17:47:52 +0000 | [diff] [blame] | 568 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 569 | auto out = line(); |
| 570 | out << program_->Symbols().NameFor(mem->symbol()) << " : "; |
| 571 | if (!EmitType(out, mem->type())) { |
dan sinclair | 7156d3e | 2020-10-19 15:31:47 +0000 | [diff] [blame] | 572 | return false; |
| 573 | } |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 574 | out << ";"; |
dan sinclair | 7156d3e | 2020-10-19 15:31:47 +0000 | [diff] [blame] | 575 | } |
| 576 | decrement_indent(); |
dan sinclair | 7156d3e | 2020-10-19 15:31:47 +0000 | [diff] [blame] | 577 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 578 | line() << "};"; |
dan sinclair | 7156d3e | 2020-10-19 15:31:47 +0000 | [diff] [blame] | 579 | return true; |
| 580 | } |
| 581 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 582 | bool GeneratorImpl::EmitVariable(std::ostream& out, ast::Variable* var) { |
James Price | d3e3681 | 2021-03-11 17:47:52 +0000 | [diff] [blame] | 583 | if (!var->decorations().empty()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 584 | if (!EmitDecorations(out, var->decorations())) { |
James Price | d3e3681 | 2021-03-11 17:47:52 +0000 | [diff] [blame] | 585 | return false; |
| 586 | } |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 587 | out << " "; |
dan sinclair | d9e9ff3 | 2020-03-12 12:40:01 +0000 | [diff] [blame] | 588 | } |
| 589 | |
| 590 | if (var->is_const()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 591 | out << "let"; |
dan sinclair | d9e9ff3 | 2020-03-12 12:40:01 +0000 | [diff] [blame] | 592 | } else { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 593 | out << "var"; |
Ben Clayton | 688fe44 | 2021-05-13 12:38:12 +0000 | [diff] [blame] | 594 | auto sc = var->declared_storage_class(); |
Ben Clayton | 93e8f52 | 2021-06-04 20:41:47 +0000 | [diff] [blame] | 595 | auto ac = var->declared_access(); |
| 596 | if (sc != ast::StorageClass::kNone || ac != ast::Access::kUndefined) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 597 | out << "<" << sc; |
Ben Clayton | 93e8f52 | 2021-06-04 20:41:47 +0000 | [diff] [blame] | 598 | if (ac != ast::Access::kUndefined) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 599 | out << ", "; |
| 600 | if (!EmitAccess(out, ac)) { |
Ben Clayton | 93e8f52 | 2021-06-04 20:41:47 +0000 | [diff] [blame] | 601 | return false; |
| 602 | } |
| 603 | } |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 604 | out << ">"; |
dan sinclair | d9e9ff3 | 2020-03-12 12:40:01 +0000 | [diff] [blame] | 605 | } |
| 606 | } |
| 607 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 608 | out << " " << program_->Symbols().NameFor(var->symbol()); |
Ben Clayton | 8198d57 | 2021-04-19 14:37:49 +0000 | [diff] [blame] | 609 | |
Ben Clayton | 02ebf0d | 2021-05-05 09:09:41 +0000 | [diff] [blame] | 610 | if (auto* ty = var->type()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 611 | out << " : "; |
| 612 | if (!EmitType(out, ty)) { |
Ben Clayton | 8198d57 | 2021-04-19 14:37:49 +0000 | [diff] [blame] | 613 | return false; |
| 614 | } |
dan sinclair | d9e9ff3 | 2020-03-12 12:40:01 +0000 | [diff] [blame] | 615 | } |
| 616 | |
dan sinclair | a322f5d | 2020-03-30 22:46:06 +0000 | [diff] [blame] | 617 | if (var->constructor() != nullptr) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 618 | out << " = "; |
| 619 | if (!EmitExpression(out, var->constructor())) { |
dan sinclair | 306a2f8 | 2020-03-12 12:43:05 +0000 | [diff] [blame] | 620 | return false; |
| 621 | } |
dan sinclair | d9e9ff3 | 2020-03-12 12:40:01 +0000 | [diff] [blame] | 622 | } |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 623 | out << ";"; |
dan sinclair | d9e9ff3 | 2020-03-12 12:40:01 +0000 | [diff] [blame] | 624 | |
| 625 | return true; |
| 626 | } |
| 627 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 628 | bool GeneratorImpl::EmitDecorations(std::ostream& out, |
| 629 | const ast::DecorationList& decos) { |
| 630 | out << "[["; |
dan sinclair | d9e9ff3 | 2020-03-12 12:40:01 +0000 | [diff] [blame] | 631 | bool first = true; |
James Price | d3e3681 | 2021-03-11 17:47:52 +0000 | [diff] [blame] | 632 | for (auto* deco : decos) { |
dan sinclair | d9e9ff3 | 2020-03-12 12:40:01 +0000 | [diff] [blame] | 633 | if (!first) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 634 | out << ", "; |
dan sinclair | d9e9ff3 | 2020-03-12 12:40:01 +0000 | [diff] [blame] | 635 | } |
| 636 | first = false; |
| 637 | |
Ben Clayton | 451f2cc | 2021-05-12 12:54:21 +0000 | [diff] [blame] | 638 | if (auto* workgroup = deco->As<ast::WorkgroupDecoration>()) { |
James Price | 70f80bb | 2021-05-19 13:40:08 +0000 | [diff] [blame] | 639 | auto values = workgroup->values(); |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 640 | out << "workgroup_size("; |
James Price | 70f80bb | 2021-05-19 13:40:08 +0000 | [diff] [blame] | 641 | for (int i = 0; i < 3; i++) { |
| 642 | if (values[i]) { |
| 643 | if (i > 0) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 644 | out << ", "; |
James Price | 70f80bb | 2021-05-19 13:40:08 +0000 | [diff] [blame] | 645 | } |
| 646 | if (auto* ident = values[i]->As<ast::IdentifierExpression>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 647 | if (!EmitIdentifier(out, ident)) { |
James Price | 70f80bb | 2021-05-19 13:40:08 +0000 | [diff] [blame] | 648 | return false; |
| 649 | } |
| 650 | } else if (auto* scalar = |
| 651 | values[i]->As<ast::ScalarConstructorExpression>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 652 | if (!EmitScalarConstructor(out, scalar)) { |
James Price | 70f80bb | 2021-05-19 13:40:08 +0000 | [diff] [blame] | 653 | return false; |
| 654 | } |
| 655 | } else { |
Ben Clayton | ffd28e2 | 2021-06-24 11:27:36 +0000 | [diff] [blame] | 656 | TINT_ICE(Writer, diagnostics_) |
| 657 | << "Unsupported workgroup_size expression"; |
James Price | 70f80bb | 2021-05-19 13:40:08 +0000 | [diff] [blame] | 658 | } |
| 659 | } |
| 660 | } |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 661 | out << ")"; |
Ben Clayton | 688fe44 | 2021-05-13 12:38:12 +0000 | [diff] [blame] | 662 | } else if (deco->Is<ast::StructBlockDecoration>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 663 | out << "block"; |
Ben Clayton | 451f2cc | 2021-05-12 12:54:21 +0000 | [diff] [blame] | 664 | } else if (auto* stage = deco->As<ast::StageDecoration>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 665 | out << "stage(" << stage->value() << ")"; |
Ben Clayton | 451f2cc | 2021-05-12 12:54:21 +0000 | [diff] [blame] | 666 | } else if (auto* binding = deco->As<ast::BindingDecoration>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 667 | out << "binding(" << binding->value() << ")"; |
dan sinclair | c068cfc | 2021-01-15 12:22:16 +0000 | [diff] [blame] | 668 | } else if (auto* group = deco->As<ast::GroupDecoration>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 669 | out << "group(" << group->value() << ")"; |
Ben Clayton | 2c1d7d5 | 2020-11-30 23:30:58 +0000 | [diff] [blame] | 670 | } else if (auto* location = deco->As<ast::LocationDecoration>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 671 | out << "location(" << location->value() << ")"; |
Ben Clayton | c0eb9ae | 2020-11-30 23:30:58 +0000 | [diff] [blame] | 672 | } else if (auto* builtin = deco->As<ast::BuiltinDecoration>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 673 | out << "builtin(" << builtin->value() << ")"; |
James Price | 545f4e0 | 2021-06-28 23:04:43 +0000 | [diff] [blame] | 674 | } else if (auto* interpolate = deco->As<ast::InterpolateDecoration>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 675 | out << "interpolate(" << interpolate->type(); |
James Price | 545f4e0 | 2021-06-28 23:04:43 +0000 | [diff] [blame] | 676 | if (interpolate->sampling() != ast::InterpolationSampling::kNone) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 677 | out << ", " << interpolate->sampling(); |
James Price | 545f4e0 | 2021-06-28 23:04:43 +0000 | [diff] [blame] | 678 | } |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 679 | out << ")"; |
James Price | fcc0de0 | 2021-07-12 12:28:52 +0000 | [diff] [blame] | 680 | } else if (deco->Is<ast::InvariantDecoration>()) { |
| 681 | out << "invariant"; |
James Price | e87ded8 | 2021-04-30 17:14:19 +0000 | [diff] [blame] | 682 | } else if (auto* override_deco = deco->As<ast::OverrideDecoration>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 683 | out << "override"; |
James Price | 26e0312 | 2021-05-13 21:35:42 +0000 | [diff] [blame] | 684 | if (override_deco->HasValue()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 685 | out << "(" << override_deco->value() << ")"; |
James Price | 26e0312 | 2021-05-13 21:35:42 +0000 | [diff] [blame] | 686 | } |
Ben Clayton | d614dd5 | 2021-03-15 10:43:11 +0000 | [diff] [blame] | 687 | } else if (auto* size = deco->As<ast::StructMemberSizeDecoration>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 688 | out << "size(" << size->size() << ")"; |
Ben Clayton | d614dd5 | 2021-03-15 10:43:11 +0000 | [diff] [blame] | 689 | } else if (auto* align = deco->As<ast::StructMemberAlignDecoration>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 690 | out << "align(" << align->align() << ")"; |
Ben Clayton | 451f2cc | 2021-05-12 12:54:21 +0000 | [diff] [blame] | 691 | } else if (auto* internal = deco->As<ast::InternalDecoration>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 692 | out << "internal(" << internal->InternalName() << ")"; |
dan sinclair | d9e9ff3 | 2020-03-12 12:40:01 +0000 | [diff] [blame] | 693 | } else { |
Ben Clayton | ffd28e2 | 2021-06-24 11:27:36 +0000 | [diff] [blame] | 694 | TINT_ICE(Writer, diagnostics_) |
Ben Clayton | 822fa54 | 2021-03-15 20:25:12 +0000 | [diff] [blame] | 695 | << "Unsupported decoration '" << deco->TypeInfo().name << "'"; |
dan sinclair | d9e9ff3 | 2020-03-12 12:40:01 +0000 | [diff] [blame] | 696 | return false; |
| 697 | } |
| 698 | } |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 699 | out << "]]"; |
dan sinclair | d9e9ff3 | 2020-03-12 12:40:01 +0000 | [diff] [blame] | 700 | |
| 701 | return true; |
| 702 | } |
| 703 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 704 | bool GeneratorImpl::EmitBinary(std::ostream& out, ast::BinaryExpression* expr) { |
| 705 | out << "("; |
dan sinclair | 49568e1 | 2020-03-20 19:01:19 +0000 | [diff] [blame] | 706 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 707 | if (!EmitExpression(out, expr->lhs())) { |
dan sinclair | 49568e1 | 2020-03-20 19:01:19 +0000 | [diff] [blame] | 708 | return false; |
| 709 | } |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 710 | out << " "; |
dan sinclair | 49568e1 | 2020-03-20 19:01:19 +0000 | [diff] [blame] | 711 | |
dan sinclair | 1c9b486 | 2020-04-07 19:27:41 +0000 | [diff] [blame] | 712 | switch (expr->op()) { |
| 713 | case ast::BinaryOp::kAnd: |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 714 | out << "&"; |
dan sinclair | 49568e1 | 2020-03-20 19:01:19 +0000 | [diff] [blame] | 715 | break; |
dan sinclair | 1c9b486 | 2020-04-07 19:27:41 +0000 | [diff] [blame] | 716 | case ast::BinaryOp::kOr: |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 717 | out << "|"; |
dan sinclair | 49568e1 | 2020-03-20 19:01:19 +0000 | [diff] [blame] | 718 | break; |
dan sinclair | 1c9b486 | 2020-04-07 19:27:41 +0000 | [diff] [blame] | 719 | case ast::BinaryOp::kXor: |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 720 | out << "^"; |
dan sinclair | 49568e1 | 2020-03-20 19:01:19 +0000 | [diff] [blame] | 721 | break; |
dan sinclair | 1c9b486 | 2020-04-07 19:27:41 +0000 | [diff] [blame] | 722 | case ast::BinaryOp::kLogicalAnd: |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 723 | out << "&&"; |
dan sinclair | 49568e1 | 2020-03-20 19:01:19 +0000 | [diff] [blame] | 724 | break; |
dan sinclair | 1c9b486 | 2020-04-07 19:27:41 +0000 | [diff] [blame] | 725 | case ast::BinaryOp::kLogicalOr: |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 726 | out << "||"; |
dan sinclair | 49568e1 | 2020-03-20 19:01:19 +0000 | [diff] [blame] | 727 | break; |
dan sinclair | 1c9b486 | 2020-04-07 19:27:41 +0000 | [diff] [blame] | 728 | case ast::BinaryOp::kEqual: |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 729 | out << "=="; |
dan sinclair | 49568e1 | 2020-03-20 19:01:19 +0000 | [diff] [blame] | 730 | break; |
dan sinclair | 1c9b486 | 2020-04-07 19:27:41 +0000 | [diff] [blame] | 731 | case ast::BinaryOp::kNotEqual: |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 732 | out << "!="; |
dan sinclair | 49568e1 | 2020-03-20 19:01:19 +0000 | [diff] [blame] | 733 | break; |
dan sinclair | 1c9b486 | 2020-04-07 19:27:41 +0000 | [diff] [blame] | 734 | case ast::BinaryOp::kLessThan: |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 735 | out << "<"; |
dan sinclair | 49568e1 | 2020-03-20 19:01:19 +0000 | [diff] [blame] | 736 | break; |
dan sinclair | 1c9b486 | 2020-04-07 19:27:41 +0000 | [diff] [blame] | 737 | case ast::BinaryOp::kGreaterThan: |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 738 | out << ">"; |
dan sinclair | 49568e1 | 2020-03-20 19:01:19 +0000 | [diff] [blame] | 739 | break; |
dan sinclair | 1c9b486 | 2020-04-07 19:27:41 +0000 | [diff] [blame] | 740 | case ast::BinaryOp::kLessThanEqual: |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 741 | out << "<="; |
dan sinclair | 49568e1 | 2020-03-20 19:01:19 +0000 | [diff] [blame] | 742 | break; |
dan sinclair | 1c9b486 | 2020-04-07 19:27:41 +0000 | [diff] [blame] | 743 | case ast::BinaryOp::kGreaterThanEqual: |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 744 | out << ">="; |
dan sinclair | 49568e1 | 2020-03-20 19:01:19 +0000 | [diff] [blame] | 745 | break; |
dan sinclair | 1c9b486 | 2020-04-07 19:27:41 +0000 | [diff] [blame] | 746 | case ast::BinaryOp::kShiftLeft: |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 747 | out << "<<"; |
dan sinclair | 49568e1 | 2020-03-20 19:01:19 +0000 | [diff] [blame] | 748 | break; |
dan sinclair | 1c9b486 | 2020-04-07 19:27:41 +0000 | [diff] [blame] | 749 | case ast::BinaryOp::kShiftRight: |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 750 | out << ">>"; |
dan sinclair | 49568e1 | 2020-03-20 19:01:19 +0000 | [diff] [blame] | 751 | break; |
dan sinclair | 1c9b486 | 2020-04-07 19:27:41 +0000 | [diff] [blame] | 752 | case ast::BinaryOp::kAdd: |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 753 | out << "+"; |
dan sinclair | 49568e1 | 2020-03-20 19:01:19 +0000 | [diff] [blame] | 754 | break; |
dan sinclair | 1c9b486 | 2020-04-07 19:27:41 +0000 | [diff] [blame] | 755 | case ast::BinaryOp::kSubtract: |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 756 | out << "-"; |
dan sinclair | 49568e1 | 2020-03-20 19:01:19 +0000 | [diff] [blame] | 757 | break; |
dan sinclair | 1c9b486 | 2020-04-07 19:27:41 +0000 | [diff] [blame] | 758 | case ast::BinaryOp::kMultiply: |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 759 | out << "*"; |
dan sinclair | 49568e1 | 2020-03-20 19:01:19 +0000 | [diff] [blame] | 760 | break; |
dan sinclair | 1c9b486 | 2020-04-07 19:27:41 +0000 | [diff] [blame] | 761 | case ast::BinaryOp::kDivide: |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 762 | out << "/"; |
dan sinclair | 49568e1 | 2020-03-20 19:01:19 +0000 | [diff] [blame] | 763 | break; |
dan sinclair | 1c9b486 | 2020-04-07 19:27:41 +0000 | [diff] [blame] | 764 | case ast::BinaryOp::kModulo: |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 765 | out << "%"; |
dan sinclair | 49568e1 | 2020-03-20 19:01:19 +0000 | [diff] [blame] | 766 | break; |
dan sinclair | 1c9b486 | 2020-04-07 19:27:41 +0000 | [diff] [blame] | 767 | case ast::BinaryOp::kNone: |
Ben Clayton | ffd28e2 | 2021-06-24 11:27:36 +0000 | [diff] [blame] | 768 | diagnostics_.add_error(diag::System::Writer, |
| 769 | "missing binary operation type"); |
dan sinclair | 49568e1 | 2020-03-20 19:01:19 +0000 | [diff] [blame] | 770 | return false; |
| 771 | } |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 772 | out << " "; |
dan sinclair | 49568e1 | 2020-03-20 19:01:19 +0000 | [diff] [blame] | 773 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 774 | if (!EmitExpression(out, expr->rhs())) { |
dan sinclair | 49568e1 | 2020-03-20 19:01:19 +0000 | [diff] [blame] | 775 | return false; |
| 776 | } |
| 777 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 778 | out << ")"; |
dan sinclair | 49568e1 | 2020-03-20 19:01:19 +0000 | [diff] [blame] | 779 | return true; |
| 780 | } |
| 781 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 782 | bool GeneratorImpl::EmitUnaryOp(std::ostream& out, |
| 783 | ast::UnaryOpExpression* expr) { |
dan sinclair | daff3e2 | 2020-03-20 19:01:47 +0000 | [diff] [blame] | 784 | switch (expr->op()) { |
Ben Clayton | 52b06fb | 2021-05-13 13:36:32 +0000 | [diff] [blame] | 785 | case ast::UnaryOp::kAddressOf: |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 786 | out << "&"; |
Ben Clayton | 52b06fb | 2021-05-13 13:36:32 +0000 | [diff] [blame] | 787 | break; |
James Price | c932b55 | 2021-06-17 08:35:54 +0000 | [diff] [blame] | 788 | case ast::UnaryOp::kComplement: |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 789 | out << "~"; |
James Price | c932b55 | 2021-06-17 08:35:54 +0000 | [diff] [blame] | 790 | break; |
Ben Clayton | 85bdf17 | 2021-05-17 14:48:37 +0000 | [diff] [blame] | 791 | case ast::UnaryOp::kIndirection: |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 792 | out << "*"; |
Ben Clayton | 85bdf17 | 2021-05-17 14:48:37 +0000 | [diff] [blame] | 793 | break; |
dan sinclair | daff3e2 | 2020-03-20 19:01:47 +0000 | [diff] [blame] | 794 | case ast::UnaryOp::kNot: |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 795 | out << "!"; |
dan sinclair | daff3e2 | 2020-03-20 19:01:47 +0000 | [diff] [blame] | 796 | break; |
| 797 | case ast::UnaryOp::kNegation: |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 798 | out << "-"; |
dan sinclair | daff3e2 | 2020-03-20 19:01:47 +0000 | [diff] [blame] | 799 | break; |
| 800 | } |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 801 | out << "("; |
dan sinclair | daff3e2 | 2020-03-20 19:01:47 +0000 | [diff] [blame] | 802 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 803 | if (!EmitExpression(out, expr->expr())) { |
dan sinclair | daff3e2 | 2020-03-20 19:01:47 +0000 | [diff] [blame] | 804 | return false; |
| 805 | } |
| 806 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 807 | out << ")"; |
dan sinclair | daff3e2 | 2020-03-20 19:01:47 +0000 | [diff] [blame] | 808 | |
| 809 | return true; |
| 810 | } |
| 811 | |
dan sinclair | 7c2fa1e | 2020-07-27 15:25:00 +0000 | [diff] [blame] | 812 | bool GeneratorImpl::EmitBlock(const ast::BlockStatement* stmt) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 813 | line() << "{"; |
| 814 | if (!EmitStatementsWithIndent(stmt->statements())) { |
| 815 | return false; |
dan sinclair | 21f8e25 | 2020-07-27 15:25:00 +0000 | [diff] [blame] | 816 | } |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 817 | line() << "}"; |
dan sinclair | 21f8e25 | 2020-07-27 15:25:00 +0000 | [diff] [blame] | 818 | |
| 819 | return true; |
| 820 | } |
| 821 | |
dan sinclair | 7f9d570 | 2020-03-20 19:01:57 +0000 | [diff] [blame] | 822 | bool GeneratorImpl::EmitStatement(ast::Statement* stmt) { |
Ben Clayton | 1d8098a | 2020-11-30 23:30:58 +0000 | [diff] [blame] | 823 | if (auto* a = stmt->As<ast::AssignmentStatement>()) { |
| 824 | return EmitAssign(a); |
dan sinclair | 7f9d570 | 2020-03-20 19:01:57 +0000 | [diff] [blame] | 825 | } |
Ben Clayton | 1d8098a | 2020-11-30 23:30:58 +0000 | [diff] [blame] | 826 | if (auto* b = stmt->As<ast::BlockStatement>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 827 | return EmitBlock(b); |
dan sinclair | 21f8e25 | 2020-07-27 15:25:00 +0000 | [diff] [blame] | 828 | } |
Ben Clayton | 1d8098a | 2020-11-30 23:30:58 +0000 | [diff] [blame] | 829 | if (auto* b = stmt->As<ast::BreakStatement>()) { |
| 830 | return EmitBreak(b); |
dan sinclair | bf5ab65 | 2020-03-20 19:02:05 +0000 | [diff] [blame] | 831 | } |
Ben Clayton | 1d8098a | 2020-11-30 23:30:58 +0000 | [diff] [blame] | 832 | if (auto* c = stmt->As<ast::CallStatement>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 833 | auto out = line(); |
| 834 | if (!EmitCall(out, c->expr())) { |
| 835 | return false; |
| 836 | } |
| 837 | out << ";"; |
| 838 | return true; |
dan sinclair | b44fe3c | 2020-07-21 13:44:27 +0000 | [diff] [blame] | 839 | } |
Ben Clayton | 1d8098a | 2020-11-30 23:30:58 +0000 | [diff] [blame] | 840 | if (auto* c = stmt->As<ast::ContinueStatement>()) { |
| 841 | return EmitContinue(c); |
dan sinclair | 17686fc | 2020-03-20 19:04:54 +0000 | [diff] [blame] | 842 | } |
Ben Clayton | 1d8098a | 2020-11-30 23:30:58 +0000 | [diff] [blame] | 843 | if (auto* d = stmt->As<ast::DiscardStatement>()) { |
| 844 | return EmitDiscard(d); |
dan sinclair | d81bebc | 2020-07-25 14:33:04 +0000 | [diff] [blame] | 845 | } |
Ben Clayton | 1d8098a | 2020-11-30 23:30:58 +0000 | [diff] [blame] | 846 | if (auto* f = stmt->As<ast::FallthroughStatement>()) { |
| 847 | return EmitFallthrough(f); |
dan sinclair | c083af8 | 2020-03-20 19:05:02 +0000 | [diff] [blame] | 848 | } |
Ben Clayton | 1d8098a | 2020-11-30 23:30:58 +0000 | [diff] [blame] | 849 | if (auto* i = stmt->As<ast::IfStatement>()) { |
| 850 | return EmitIf(i); |
dan sinclair | c574295 | 2020-03-20 19:08:56 +0000 | [diff] [blame] | 851 | } |
Ben Clayton | 1d8098a | 2020-11-30 23:30:58 +0000 | [diff] [blame] | 852 | if (auto* l = stmt->As<ast::LoopStatement>()) { |
| 853 | return EmitLoop(l); |
dan sinclair | 0d00402 | 2020-03-20 19:07:00 +0000 | [diff] [blame] | 854 | } |
Ben Clayton | efc46c1 | 2021-07-02 19:27:42 +0000 | [diff] [blame] | 855 | if (auto* l = stmt->As<ast::ForLoopStatement>()) { |
| 856 | return EmitForLoop(l); |
| 857 | } |
Ben Clayton | 1d8098a | 2020-11-30 23:30:58 +0000 | [diff] [blame] | 858 | if (auto* r = stmt->As<ast::ReturnStatement>()) { |
| 859 | return EmitReturn(r); |
dan sinclair | 2a6e275 | 2020-03-20 19:05:10 +0000 | [diff] [blame] | 860 | } |
Ben Clayton | 1d8098a | 2020-11-30 23:30:58 +0000 | [diff] [blame] | 861 | if (auto* s = stmt->As<ast::SwitchStatement>()) { |
| 862 | return EmitSwitch(s); |
dan sinclair | 5f64aee | 2020-03-20 19:06:52 +0000 | [diff] [blame] | 863 | } |
Ben Clayton | 1d8098a | 2020-11-30 23:30:58 +0000 | [diff] [blame] | 864 | if (auto* v = stmt->As<ast::VariableDeclStatement>()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 865 | return EmitVariable(line(), v->variable()); |
dan sinclair | 4202d7d | 2020-03-20 19:06:45 +0000 | [diff] [blame] | 866 | } |
dan sinclair | 7f9d570 | 2020-03-20 19:01:57 +0000 | [diff] [blame] | 867 | |
Ben Clayton | ffd28e2 | 2021-06-24 11:27:36 +0000 | [diff] [blame] | 868 | diagnostics_.add_error(diag::System::Writer, |
| 869 | "unknown statement type: " + program_->str(stmt)); |
dan sinclair | 7f9d570 | 2020-03-20 19:01:57 +0000 | [diff] [blame] | 870 | return false; |
| 871 | } |
| 872 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 873 | bool 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 | |
| 882 | bool GeneratorImpl::EmitStatementsWithIndent(const ast::StatementList& stmts) { |
| 883 | ScopedIndent si(this); |
| 884 | return EmitStatements(stmts); |
| 885 | } |
| 886 | |
dan sinclair | 7f9d570 | 2020-03-20 19:01:57 +0000 | [diff] [blame] | 887 | bool GeneratorImpl::EmitAssign(ast::AssignmentStatement* stmt) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 888 | auto out = line(); |
| 889 | |
| 890 | if (!EmitExpression(out, stmt->lhs())) { |
dan sinclair | 7f9d570 | 2020-03-20 19:01:57 +0000 | [diff] [blame] | 891 | return false; |
| 892 | } |
| 893 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 894 | out << " = "; |
dan sinclair | 7f9d570 | 2020-03-20 19:01:57 +0000 | [diff] [blame] | 895 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 896 | if (!EmitExpression(out, stmt->rhs())) { |
dan sinclair | 7f9d570 | 2020-03-20 19:01:57 +0000 | [diff] [blame] | 897 | return false; |
| 898 | } |
| 899 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 900 | out << ";"; |
| 901 | |
dan sinclair | 7f9d570 | 2020-03-20 19:01:57 +0000 | [diff] [blame] | 902 | return true; |
| 903 | } |
| 904 | |
dan sinclair | 6bd7061 | 2020-06-03 16:11:28 +0000 | [diff] [blame] | 905 | bool GeneratorImpl::EmitBreak(ast::BreakStatement*) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 906 | line() << "break;"; |
dan sinclair | 37f4fb0 | 2020-03-20 19:04:45 +0000 | [diff] [blame] | 907 | return true; |
| 908 | } |
| 909 | |
| 910 | bool GeneratorImpl::EmitCase(ast::CaseStatement* stmt) { |
dan sinclair | 37f4fb0 | 2020-03-20 19:04:45 +0000 | [diff] [blame] | 911 | if (stmt->IsDefault()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 912 | line() << "default: {"; |
dan sinclair | 37f4fb0 | 2020-03-20 19:04:45 +0000 | [diff] [blame] | 913 | } else { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 914 | auto out = line(); |
| 915 | out << "case "; |
dan sinclair | 37f4fb0 | 2020-03-20 19:04:45 +0000 | [diff] [blame] | 916 | |
dan sinclair | 1aadbd4 | 2020-06-01 16:56:46 +0000 | [diff] [blame] | 917 | bool first = true; |
Ben Clayton | b053acf | 2020-11-16 16:31:07 +0000 | [diff] [blame] | 918 | for (auto* selector : stmt->selectors()) { |
dan sinclair | 1aadbd4 | 2020-06-01 16:56:46 +0000 | [diff] [blame] | 919 | if (!first) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 920 | out << ", "; |
dan sinclair | 1aadbd4 | 2020-06-01 16:56:46 +0000 | [diff] [blame] | 921 | } |
| 922 | |
| 923 | first = false; |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 924 | if (!EmitLiteral(out, selector)) { |
dan sinclair | 1aadbd4 | 2020-06-01 16:56:46 +0000 | [diff] [blame] | 925 | return false; |
| 926 | } |
dan sinclair | 37f4fb0 | 2020-03-20 19:04:45 +0000 | [diff] [blame] | 927 | } |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 928 | out << ": {"; |
dan sinclair | 37f4fb0 | 2020-03-20 19:04:45 +0000 | [diff] [blame] | 929 | } |
dan sinclair | 37f4fb0 | 2020-03-20 19:04:45 +0000 | [diff] [blame] | 930 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 931 | if (!EmitStatementsWithIndent(stmt->body()->statements())) { |
| 932 | return false; |
| 933 | } |
dan sinclair | bf5ab65 | 2020-03-20 19:02:05 +0000 | [diff] [blame] | 934 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 935 | line() << "}"; |
dan sinclair | 17686fc | 2020-03-20 19:04:54 +0000 | [diff] [blame] | 936 | return true; |
| 937 | } |
| 938 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 939 | bool GeneratorImpl::EmitContinue(ast::ContinueStatement*) { |
| 940 | line() << "continue;"; |
| 941 | return true; |
dan sinclair | eaf2689 | 2020-03-20 19:08:07 +0000 | [diff] [blame] | 942 | } |
| 943 | |
dan sinclair | c083af8 | 2020-03-20 19:05:02 +0000 | [diff] [blame] | 944 | bool GeneratorImpl::EmitFallthrough(ast::FallthroughStatement*) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 945 | line() << "fallthrough;"; |
dan sinclair | c083af8 | 2020-03-20 19:05:02 +0000 | [diff] [blame] | 946 | return true; |
| 947 | } |
| 948 | |
dan sinclair | c574295 | 2020-03-20 19:08:56 +0000 | [diff] [blame] | 949 | bool GeneratorImpl::EmitIf(ast::IfStatement* stmt) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 950 | { |
| 951 | auto out = line(); |
| 952 | out << "if ("; |
| 953 | if (!EmitExpression(out, stmt->condition())) { |
| 954 | return false; |
| 955 | } |
| 956 | out << ") {"; |
dan sinclair | c574295 | 2020-03-20 19:08:56 +0000 | [diff] [blame] | 957 | } |
dan sinclair | c574295 | 2020-03-20 19:08:56 +0000 | [diff] [blame] | 958 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 959 | if (!EmitStatementsWithIndent(stmt->body()->statements())) { |
dan sinclair | 0984214 | 2020-03-25 18:54:01 +0000 | [diff] [blame] | 960 | return false; |
dan sinclair | c574295 | 2020-03-20 19:08:56 +0000 | [diff] [blame] | 961 | } |
| 962 | |
Ben Clayton | b053acf | 2020-11-16 16:31:07 +0000 | [diff] [blame] | 963 | for (auto* e : stmt->else_statements()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 964 | 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 sinclair | c574295 | 2020-03-20 19:08:56 +0000 | [diff] [blame] | 976 | return false; |
| 977 | } |
| 978 | } |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 979 | |
| 980 | line() << "}"; |
dan sinclair | c574295 | 2020-03-20 19:08:56 +0000 | [diff] [blame] | 981 | |
dan sinclair | c574295 | 2020-03-20 19:08:56 +0000 | [diff] [blame] | 982 | return true; |
| 983 | } |
| 984 | |
dan sinclair | d81bebc | 2020-07-25 14:33:04 +0000 | [diff] [blame] | 985 | bool GeneratorImpl::EmitDiscard(ast::DiscardStatement*) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 986 | line() << "discard;"; |
dan sinclair | d81bebc | 2020-07-25 14:33:04 +0000 | [diff] [blame] | 987 | return true; |
| 988 | } |
| 989 | |
dan sinclair | 0d00402 | 2020-03-20 19:07:00 +0000 | [diff] [blame] | 990 | bool GeneratorImpl::EmitLoop(ast::LoopStatement* stmt) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 991 | line() << "loop {"; |
dan sinclair | 0d00402 | 2020-03-20 19:07:00 +0000 | [diff] [blame] | 992 | increment_indent(); |
| 993 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 994 | if (!EmitStatements(stmt->body()->statements())) { |
| 995 | return false; |
dan sinclair | 0d00402 | 2020-03-20 19:07:00 +0000 | [diff] [blame] | 996 | } |
| 997 | |
| 998 | if (stmt->has_continuing()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 999 | line(); |
| 1000 | line() << "continuing {"; |
| 1001 | if (!EmitStatementsWithIndent(stmt->continuing()->statements())) { |
dan sinclair | 0984214 | 2020-03-25 18:54:01 +0000 | [diff] [blame] | 1002 | return false; |
dan sinclair | 0d00402 | 2020-03-20 19:07:00 +0000 | [diff] [blame] | 1003 | } |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 1004 | line() << "}"; |
dan sinclair | 0d00402 | 2020-03-20 19:07:00 +0000 | [diff] [blame] | 1005 | } |
| 1006 | |
| 1007 | decrement_indent(); |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 1008 | line() << "}"; |
dan sinclair | 0d00402 | 2020-03-20 19:07:00 +0000 | [diff] [blame] | 1009 | |
| 1010 | return true; |
| 1011 | } |
| 1012 | |
Ben Clayton | efc46c1 | 2021-07-02 19:27:42 +0000 | [diff] [blame] | 1013 | bool GeneratorImpl::EmitForLoop(ast::ForLoopStatement* stmt) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 1014 | 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 Clayton | efc46c1 | 2021-07-02 19:27:42 +0000 | [diff] [blame] | 1019 | } |
| 1020 | } |
| 1021 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 1022 | 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 Clayton | efc46c1 | 2021-07-02 19:27:42 +0000 | [diff] [blame] | 1077 | |
| 1078 | return true; |
| 1079 | } |
| 1080 | |
| 1081 | bool GeneratorImpl::EmitReturn(ast::ReturnStatement* stmt) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 1082 | auto out = line(); |
| 1083 | out << "return"; |
dan sinclair | 2a6e275 | 2020-03-20 19:05:10 +0000 | [diff] [blame] | 1084 | if (stmt->has_value()) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 1085 | out << " "; |
| 1086 | if (!EmitExpression(out, stmt->value())) { |
dan sinclair | 2a6e275 | 2020-03-20 19:05:10 +0000 | [diff] [blame] | 1087 | return false; |
| 1088 | } |
| 1089 | } |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 1090 | out << ";"; |
dan sinclair | 2a6e275 | 2020-03-20 19:05:10 +0000 | [diff] [blame] | 1091 | return true; |
| 1092 | } |
| 1093 | |
dan sinclair | 5f64aee | 2020-03-20 19:06:52 +0000 | [diff] [blame] | 1094 | bool GeneratorImpl::EmitSwitch(ast::SwitchStatement* stmt) { |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 1095 | { |
| 1096 | auto out = line(); |
| 1097 | out << "switch("; |
| 1098 | if (!EmitExpression(out, stmt->condition())) { |
dan sinclair | 5f64aee | 2020-03-20 19:06:52 +0000 | [diff] [blame] | 1099 | return false; |
| 1100 | } |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 1101 | out << ") {"; |
| 1102 | } |
| 1103 | |
| 1104 | { |
| 1105 | ScopedIndent si(this); |
| 1106 | for (auto* s : stmt->body()) { |
| 1107 | if (!EmitCase(s)) { |
| 1108 | return false; |
| 1109 | } |
| 1110 | } |
dan sinclair | 5f64aee | 2020-03-20 19:06:52 +0000 | [diff] [blame] | 1111 | } |
| 1112 | |
Ben Clayton | e1f30f1 | 2021-07-02 22:17:25 +0000 | [diff] [blame] | 1113 | line() << "}"; |
dan sinclair | 5f64aee | 2020-03-20 19:06:52 +0000 | [diff] [blame] | 1114 | return true; |
| 1115 | } |
| 1116 | |
dan sinclair | d9e9ff3 | 2020-03-12 12:40:01 +0000 | [diff] [blame] | 1117 | } // namespace wgsl |
| 1118 | } // namespace writer |
| 1119 | } // namespace tint |