Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 1 | // Copyright 2020 The Tint Authors. |
| 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | |
| 15 | #ifndef SRC_TINT_WRITER_MSL_GENERATOR_IMPL_H_ |
| 16 | #define SRC_TINT_WRITER_MSL_GENERATOR_IMPL_H_ |
| 17 | |
| 18 | #include <string> |
Antonio Maiorano | f25140f | 2022-06-03 14:47:01 +0000 | [diff] [blame] | 19 | #include <tuple> |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 20 | #include <unordered_map> |
| 21 | #include <unordered_set> |
| 22 | #include <vector> |
| 23 | |
| 24 | #include "src/tint/ast/assignment_statement.h" |
| 25 | #include "src/tint/ast/binary_expression.h" |
| 26 | #include "src/tint/ast/bitcast_expression.h" |
| 27 | #include "src/tint/ast/break_statement.h" |
| 28 | #include "src/tint/ast/continue_statement.h" |
| 29 | #include "src/tint/ast/discard_statement.h" |
| 30 | #include "src/tint/ast/expression.h" |
| 31 | #include "src/tint/ast/if_statement.h" |
| 32 | #include "src/tint/ast/index_accessor_expression.h" |
| 33 | #include "src/tint/ast/interpolate_attribute.h" |
| 34 | #include "src/tint/ast/loop_statement.h" |
| 35 | #include "src/tint/ast/member_accessor_expression.h" |
| 36 | #include "src/tint/ast/return_statement.h" |
| 37 | #include "src/tint/ast/switch_statement.h" |
| 38 | #include "src/tint/ast/unary_op_expression.h" |
Ben Clayton | 4d3ff97 | 2023-02-21 17:33:54 +0000 | [diff] [blame] | 39 | #include "src/tint/builtin/builtin_value.h" |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 40 | #include "src/tint/program.h" |
| 41 | #include "src/tint/scope_stack.h" |
| 42 | #include "src/tint/sem/struct.h" |
dan sinclair | 52fa68b | 2023-02-28 14:54:51 +0000 | [diff] [blame] | 43 | #include "src/tint/utils/string_stream.h" |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 44 | #include "src/tint/writer/array_length_from_uniform_options.h" |
Antonio Maiorano | 7eaab38 | 2022-04-11 16:33:30 +0000 | [diff] [blame] | 45 | #include "src/tint/writer/msl/generator.h" |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 46 | #include "src/tint/writer/text_generator.h" |
| 47 | |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 48 | // Forward declarations |
dan sinclair | 9fe8260 | 2022-04-07 13:58:14 +0000 | [diff] [blame] | 49 | namespace tint::sem { |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 50 | class Builtin; |
Ben Clayton | 54a104e | 2023-02-22 20:04:40 +0000 | [diff] [blame] | 51 | class Call; |
| 52 | class ValueConstructor; |
| 53 | class ValueConversion; |
dan sinclair | 9fe8260 | 2022-04-07 13:58:14 +0000 | [diff] [blame] | 54 | } // namespace tint::sem |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 55 | |
dan sinclair | 9fe8260 | 2022-04-07 13:58:14 +0000 | [diff] [blame] | 56 | namespace tint::writer::msl { |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 57 | |
| 58 | /// The result of sanitizing a program for generation. |
| 59 | struct SanitizedResult { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 60 | /// Constructor |
| 61 | SanitizedResult(); |
| 62 | /// Destructor |
| 63 | ~SanitizedResult(); |
| 64 | /// Move constructor |
| 65 | SanitizedResult(SanitizedResult&&); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 66 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 67 | /// The sanitized program. |
| 68 | Program program; |
| 69 | /// True if the shader needs a UBO of buffer sizes. |
| 70 | bool needs_storage_buffer_sizes = false; |
| 71 | /// Indices into the array_length_from_uniform binding that are statically |
| 72 | /// used. |
| 73 | std::unordered_set<uint32_t> used_array_length_from_uniform_indices; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 74 | }; |
| 75 | |
| 76 | /// Sanitize a program in preparation for generating MSL. |
Antonio Maiorano | 7eaab38 | 2022-04-11 16:33:30 +0000 | [diff] [blame] | 77 | /// @program The program to sanitize |
| 78 | /// @param options The MSL generator options. |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 79 | /// @returns the sanitized program and any supplementary information |
Antonio Maiorano | 7eaab38 | 2022-04-11 16:33:30 +0000 | [diff] [blame] | 80 | SanitizedResult Sanitize(const Program* program, const Options& options); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 81 | |
| 82 | /// Implementation class for MSL generator |
| 83 | class GeneratorImpl : public TextGenerator { |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 84 | public: |
| 85 | /// Constructor |
| 86 | /// @param program the program to generate |
| 87 | explicit GeneratorImpl(const Program* program); |
| 88 | ~GeneratorImpl(); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 89 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 90 | /// @returns true on successful generation; false otherwise |
| 91 | bool Generate(); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 92 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 93 | /// @returns true if an invariant attribute was generated |
| 94 | bool HasInvariant() { return !invariant_define_name_.empty(); } |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 95 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 96 | /// @returns a map from entry point to list of required workgroup allocations |
| 97 | const std::unordered_map<std::string, std::vector<uint32_t>>& DynamicWorkgroupAllocations() |
| 98 | const { |
| 99 | return workgroup_allocations_; |
| 100 | } |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 101 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 102 | /// Handles generating a declared type |
| 103 | /// @param ty the declared type to generate |
| 104 | /// @returns true if the declared type was emitted |
dan sinclair | 5f764d8 | 2022-12-08 00:32:27 +0000 | [diff] [blame] | 105 | bool EmitTypeDecl(const type::Type* ty); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 106 | /// Handles an index accessor expression |
| 107 | /// @param out the output of the expression stream |
| 108 | /// @param expr the expression to emit |
| 109 | /// @returns true if the index accessor was emitted |
dan sinclair | 52fa68b | 2023-02-28 14:54:51 +0000 | [diff] [blame] | 110 | bool EmitIndexAccessor(utils::StringStream& out, const ast::IndexAccessorExpression* expr); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 111 | /// Handles an assignment statement |
| 112 | /// @param stmt the statement to emit |
| 113 | /// @returns true if the statement was emitted successfully |
| 114 | bool EmitAssign(const ast::AssignmentStatement* stmt); |
| 115 | /// Handles generating a binary expression |
| 116 | /// @param out the output of the expression stream |
| 117 | /// @param expr the binary expression |
| 118 | /// @returns true if the expression was emitted, false otherwise |
dan sinclair | 52fa68b | 2023-02-28 14:54:51 +0000 | [diff] [blame] | 119 | bool EmitBinary(utils::StringStream& out, const ast::BinaryExpression* expr); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 120 | /// Handles generating a bitcast expression |
| 121 | /// @param out the output of the expression stream |
| 122 | /// @param expr the bitcast expression |
| 123 | /// @returns true if the bitcast was emitted |
dan sinclair | 52fa68b | 2023-02-28 14:54:51 +0000 | [diff] [blame] | 124 | bool EmitBitcast(utils::StringStream& out, const ast::BitcastExpression* expr); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 125 | /// Handles a block statement |
| 126 | /// @param stmt the statement to emit |
| 127 | /// @returns true if the statement was emitted successfully |
| 128 | bool EmitBlock(const ast::BlockStatement* stmt); |
| 129 | /// Handles a break statement |
| 130 | /// @param stmt the statement to emit |
| 131 | /// @returns true if the statement was emitted successfully |
| 132 | bool EmitBreak(const ast::BreakStatement* stmt); |
dan sinclair | b8b0c21 | 2022-10-20 22:45:50 +0000 | [diff] [blame] | 133 | /// Handles a break-if statement |
| 134 | /// @param stmt the statement to emit |
| 135 | /// @returns true if the statement was emitted successfully |
| 136 | bool EmitBreakIf(const ast::BreakIfStatement* stmt); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 137 | /// Handles generating a call expression |
| 138 | /// @param out the output of the expression stream |
| 139 | /// @param expr the call expression |
| 140 | /// @returns true if the call expression is emitted |
dan sinclair | 52fa68b | 2023-02-28 14:54:51 +0000 | [diff] [blame] | 141 | bool EmitCall(utils::StringStream& out, const ast::CallExpression* expr); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 142 | /// Handles generating a builtin call expression |
| 143 | /// @param out the output of the expression stream |
| 144 | /// @param call the call expression |
| 145 | /// @param builtin the builtin being called |
| 146 | /// @returns true if the call expression is emitted |
dan sinclair | 52fa68b | 2023-02-28 14:54:51 +0000 | [diff] [blame] | 147 | bool EmitBuiltinCall(utils::StringStream& out, |
| 148 | const sem::Call* call, |
| 149 | const sem::Builtin* builtin); |
Ben Clayton | 54a104e | 2023-02-22 20:04:40 +0000 | [diff] [blame] | 150 | /// Handles generating a value conversion expression |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 151 | /// @param out the output of the expression stream |
| 152 | /// @param call the call expression |
Ben Clayton | 54a104e | 2023-02-22 20:04:40 +0000 | [diff] [blame] | 153 | /// @param conv the value conversion |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 154 | /// @returns true if the expression is emitted |
dan sinclair | 52fa68b | 2023-02-28 14:54:51 +0000 | [diff] [blame] | 155 | bool EmitTypeConversion(utils::StringStream& out, |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 156 | const sem::Call* call, |
Ben Clayton | 54a104e | 2023-02-22 20:04:40 +0000 | [diff] [blame] | 157 | const sem::ValueConversion* conv); |
| 158 | /// Handles generating a value constructor |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 159 | /// @param out the output of the expression stream |
| 160 | /// @param call the call expression |
Ben Clayton | 54a104e | 2023-02-22 20:04:40 +0000 | [diff] [blame] | 161 | /// @param ctor the value constructor |
dan sinclair | 6e77b47 | 2022-10-20 13:38:28 +0000 | [diff] [blame] | 162 | /// @returns true if the initializer is emitted |
dan sinclair | 52fa68b | 2023-02-28 14:54:51 +0000 | [diff] [blame] | 163 | bool EmitTypeInitializer(utils::StringStream& out, |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 164 | const sem::Call* call, |
Ben Clayton | 54a104e | 2023-02-22 20:04:40 +0000 | [diff] [blame] | 165 | const sem::ValueConstructor* ctor); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 166 | /// Handles generating a function call |
| 167 | /// @param out the output of the expression stream |
| 168 | /// @param call the call expression |
| 169 | /// @param func the target function |
| 170 | /// @returns true if the call is emitted |
dan sinclair | 52fa68b | 2023-02-28 14:54:51 +0000 | [diff] [blame] | 171 | bool EmitFunctionCall(utils::StringStream& out, |
| 172 | const sem::Call* call, |
| 173 | const sem::Function* func); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 174 | /// Handles generating a call to an atomic function (`atomicAdd`, |
| 175 | /// `atomicMax`, etc) |
| 176 | /// @param out the output of the expression stream |
| 177 | /// @param expr the call expression |
| 178 | /// @param builtin the semantic information for the atomic builtin |
| 179 | /// @returns true if the call expression is emitted |
dan sinclair | 52fa68b | 2023-02-28 14:54:51 +0000 | [diff] [blame] | 180 | bool EmitAtomicCall(utils::StringStream& out, |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 181 | const ast::CallExpression* expr, |
| 182 | const sem::Builtin* builtin); |
| 183 | /// Handles generating a call to a texture function (`textureSample`, |
| 184 | /// `textureSampleGrad`, etc) |
| 185 | /// @param out the output of the expression stream |
| 186 | /// @param call the call expression |
| 187 | /// @param builtin the semantic information for the texture builtin |
| 188 | /// @returns true if the call expression is emitted |
dan sinclair | 52fa68b | 2023-02-28 14:54:51 +0000 | [diff] [blame] | 189 | bool EmitTextureCall(utils::StringStream& out, |
| 190 | const sem::Call* call, |
| 191 | const sem::Builtin* builtin); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 192 | /// Handles generating a call to the `dot()` builtin |
| 193 | /// @param out the output of the expression stream |
| 194 | /// @param expr the call expression |
| 195 | /// @param builtin the semantic information for the builtin |
| 196 | /// @returns true if the call expression is emitted |
dan sinclair | 52fa68b | 2023-02-28 14:54:51 +0000 | [diff] [blame] | 197 | bool EmitDotCall(utils::StringStream& out, |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 198 | const ast::CallExpression* expr, |
| 199 | const sem::Builtin* builtin); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 200 | /// Handles generating a call to the `modf()` builtin |
| 201 | /// @param out the output of the expression stream |
| 202 | /// @param expr the call expression |
| 203 | /// @param builtin the semantic information for the builtin |
| 204 | /// @returns true if the call expression is emitted |
dan sinclair | 52fa68b | 2023-02-28 14:54:51 +0000 | [diff] [blame] | 205 | bool EmitModfCall(utils::StringStream& out, |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 206 | const ast::CallExpression* expr, |
| 207 | const sem::Builtin* builtin); |
| 208 | /// Handles generating a call to the `frexp()` builtin |
| 209 | /// @param out the output of the expression stream |
| 210 | /// @param expr the call expression |
| 211 | /// @param builtin the semantic information for the builtin |
| 212 | /// @returns true if the call expression is emitted |
dan sinclair | 52fa68b | 2023-02-28 14:54:51 +0000 | [diff] [blame] | 213 | bool EmitFrexpCall(utils::StringStream& out, |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 214 | const ast::CallExpression* expr, |
| 215 | const sem::Builtin* builtin); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 216 | /// Handles generating a call to the `degrees()` builtin |
| 217 | /// @param out the output of the expression stream |
| 218 | /// @param expr the call expression |
| 219 | /// @param builtin the semantic information for the builtin |
| 220 | /// @returns true if the call expression is emitted |
dan sinclair | 52fa68b | 2023-02-28 14:54:51 +0000 | [diff] [blame] | 221 | bool EmitDegreesCall(utils::StringStream& out, |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 222 | const ast::CallExpression* expr, |
| 223 | const sem::Builtin* builtin); |
| 224 | /// Handles generating a call to the `radians()` builtin |
| 225 | /// @param out the output of the expression stream |
| 226 | /// @param expr the call expression |
| 227 | /// @param builtin the semantic information for the builtin |
| 228 | /// @returns true if the call expression is emitted |
dan sinclair | 52fa68b | 2023-02-28 14:54:51 +0000 | [diff] [blame] | 229 | bool EmitRadiansCall(utils::StringStream& out, |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 230 | const ast::CallExpression* expr, |
| 231 | const sem::Builtin* builtin); |
| 232 | /// Handles a case statement |
| 233 | /// @param stmt the statement |
| 234 | /// @returns true if the statement was emitted successfully |
| 235 | bool EmitCase(const ast::CaseStatement* stmt); |
| 236 | /// Handles a continue statement |
| 237 | /// @param stmt the statement to emit |
| 238 | /// @returns true if the statement was emitted successfully |
| 239 | bool EmitContinue(const ast::ContinueStatement* stmt); |
| 240 | /// Handles generating a discard statement |
| 241 | /// @param stmt the discard statement |
| 242 | /// @returns true if the statement was successfully emitted |
| 243 | bool EmitDiscard(const ast::DiscardStatement* stmt); |
| 244 | /// Handles emitting the entry point function |
| 245 | /// @param func the entry point function |
| 246 | /// @returns true if the entry point function was emitted |
| 247 | bool EmitEntryPointFunction(const ast::Function* func); |
| 248 | /// Handles generate an Expression |
| 249 | /// @param out the output of the expression stream |
| 250 | /// @param expr the expression |
| 251 | /// @returns true if the expression was emitted |
dan sinclair | 52fa68b | 2023-02-28 14:54:51 +0000 | [diff] [blame] | 252 | bool EmitExpression(utils::StringStream& out, const ast::Expression* expr); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 253 | /// Handles generating a function |
| 254 | /// @param func the function to generate |
| 255 | /// @returns true if the function was emitted |
| 256 | bool EmitFunction(const ast::Function* func); |
| 257 | /// Handles generating an identifier expression |
| 258 | /// @param out the output of the expression stream |
| 259 | /// @param expr the identifier expression |
| 260 | /// @returns true if the identifier was emitted |
dan sinclair | 52fa68b | 2023-02-28 14:54:51 +0000 | [diff] [blame] | 261 | bool EmitIdentifier(utils::StringStream& out, const ast::IdentifierExpression* expr); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 262 | /// Handles an if statement |
| 263 | /// @param stmt the statement to emit |
| 264 | /// @returns true if the statement was successfully emitted |
| 265 | bool EmitIf(const ast::IfStatement* stmt); |
Ben Clayton | cb6ddd2 | 2022-06-01 10:08:29 +0000 | [diff] [blame] | 266 | /// Handles a constant value |
| 267 | /// @param out the output stream |
| 268 | /// @param constant the constant value to emit |
| 269 | /// @returns true if the constant value was successfully emitted |
dan sinclair | 52fa68b | 2023-02-28 14:54:51 +0000 | [diff] [blame] | 270 | bool EmitConstant(utils::StringStream& out, const constant::Value* constant); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 271 | /// Handles a literal |
| 272 | /// @param out the output of the expression stream |
| 273 | /// @param lit the literal to emit |
| 274 | /// @returns true if the literal was successfully emitted |
dan sinclair | 52fa68b | 2023-02-28 14:54:51 +0000 | [diff] [blame] | 275 | bool EmitLiteral(utils::StringStream& out, const ast::LiteralExpression* lit); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 276 | /// Handles a loop statement |
| 277 | /// @param stmt the statement to emit |
| 278 | /// @returns true if the statement was emitted |
| 279 | bool EmitLoop(const ast::LoopStatement* stmt); |
| 280 | /// Handles a for loop statement |
| 281 | /// @param stmt the statement to emit |
| 282 | /// @returns true if the statement was emitted |
| 283 | bool EmitForLoop(const ast::ForLoopStatement* stmt); |
dan sinclair | 49d1a2d | 2022-06-16 12:01:27 +0000 | [diff] [blame] | 284 | /// Handles a while statement |
| 285 | /// @param stmt the statement to emit |
| 286 | /// @returns true if the statement was emitted |
| 287 | bool EmitWhile(const ast::WhileStatement* stmt); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 288 | /// Handles a member accessor expression |
| 289 | /// @param out the output of the expression stream |
| 290 | /// @param expr the member accessor expression |
| 291 | /// @returns true if the member accessor was emitted |
dan sinclair | 52fa68b | 2023-02-28 14:54:51 +0000 | [diff] [blame] | 292 | bool EmitMemberAccessor(utils::StringStream& out, const ast::MemberAccessorExpression* expr); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 293 | /// Handles return statements |
| 294 | /// @param stmt the statement to emit |
| 295 | /// @returns true if the statement was successfully emitted |
| 296 | bool EmitReturn(const ast::ReturnStatement* stmt); |
| 297 | /// Handles emitting a pipeline stage name |
| 298 | /// @param out the output of the expression stream |
| 299 | /// @param stage the stage to emit |
dan sinclair | 52fa68b | 2023-02-28 14:54:51 +0000 | [diff] [blame] | 300 | void EmitStage(utils::StringStream& out, ast::PipelineStage stage); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 301 | /// Handles statement |
| 302 | /// @param stmt the statement to emit |
| 303 | /// @returns true if the statement was emitted |
| 304 | bool EmitStatement(const ast::Statement* stmt); |
| 305 | /// Emits a list of statements |
| 306 | /// @param stmts the statement list |
| 307 | /// @returns true if the statements were emitted successfully |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 308 | bool EmitStatements(utils::VectorRef<const ast::Statement*> stmts); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 309 | /// Emits a list of statements with an indentation |
| 310 | /// @param stmts the statement list |
| 311 | /// @returns true if the statements were emitted successfully |
Ben Clayton | 783b169 | 2022-08-02 17:03:35 +0000 | [diff] [blame] | 312 | bool EmitStatementsWithIndent(utils::VectorRef<const ast::Statement*> stmts); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 313 | /// Handles generating a switch statement |
| 314 | /// @param stmt the statement to emit |
| 315 | /// @returns true if the statement was emitted |
| 316 | bool EmitSwitch(const ast::SwitchStatement* stmt); |
| 317 | /// Handles generating a type |
| 318 | /// @param out the output of the type stream |
| 319 | /// @param type the type to generate |
| 320 | /// @param name the name of the variable, only used for array emission |
| 321 | /// @param name_printed (optional) if not nullptr and an array was printed |
| 322 | /// @returns true if the type is emitted |
dan sinclair | 52fa68b | 2023-02-28 14:54:51 +0000 | [diff] [blame] | 323 | bool EmitType(utils::StringStream& out, |
dan sinclair | 5f764d8 | 2022-12-08 00:32:27 +0000 | [diff] [blame] | 324 | const type::Type* type, |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 325 | const std::string& name, |
| 326 | bool* name_printed = nullptr); |
| 327 | /// Handles generating type and name |
| 328 | /// @param out the output stream |
| 329 | /// @param type the type to generate |
| 330 | /// @param name the name to emit |
| 331 | /// @returns true if the type is emitted |
dan sinclair | 52fa68b | 2023-02-28 14:54:51 +0000 | [diff] [blame] | 332 | bool EmitTypeAndName(utils::StringStream& out, const type::Type* type, const std::string& name); |
dan sinclair | ff7cf21 | 2022-10-03 14:05:23 +0000 | [diff] [blame] | 333 | /// Handles generating a address space |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 334 | /// @param out the output of the type stream |
dan sinclair | ff7cf21 | 2022-10-03 14:05:23 +0000 | [diff] [blame] | 335 | /// @param sc the address space to generate |
| 336 | /// @returns true if the address space is emitted |
dan sinclair | 52fa68b | 2023-02-28 14:54:51 +0000 | [diff] [blame] | 337 | bool EmitAddressSpace(utils::StringStream& out, builtin::AddressSpace sc); |
Ben Clayton | 329dfd7 | 2022-11-23 00:05:05 +0000 | [diff] [blame] | 338 | /// Handles generating a struct declaration. If the structure has already been emitted, then |
| 339 | /// this function will simply return `true` without emitting anything. |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 340 | /// @param buffer the text buffer that the type declaration will be written to |
| 341 | /// @param str the struct to generate |
| 342 | /// @returns true if the struct is emitted |
Ben Clayton | bc9e422 | 2023-04-27 18:31:44 +0000 | [diff] [blame] | 343 | bool EmitStructType(TextBuffer* buffer, const type::Struct* str); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 344 | /// Handles a unary op expression |
| 345 | /// @param out the output of the expression stream |
| 346 | /// @param expr the expression to emit |
| 347 | /// @returns true if the expression was emitted |
dan sinclair | 52fa68b | 2023-02-28 14:54:51 +0000 | [diff] [blame] | 348 | bool EmitUnaryOp(utils::StringStream& out, const ast::UnaryOpExpression* expr); |
Ben Clayton | dcdf66e | 2022-06-17 12:48:51 +0000 | [diff] [blame] | 349 | /// Handles generating a 'var' declaration |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 350 | /// @param var the variable to generate |
| 351 | /// @returns true if the variable was emitted |
Ben Clayton | dcdf66e | 2022-06-17 12:48:51 +0000 | [diff] [blame] | 352 | bool EmitVar(const ast::Var* var); |
Ben Clayton | 576ba1c | 2023-04-27 17:58:25 +0000 | [diff] [blame] | 353 | /// Handles generating a 'let' declaration |
Ben Clayton | dcdf66e | 2022-06-17 12:48:51 +0000 | [diff] [blame] | 354 | /// @param let the variable to generate |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 355 | /// @returns true if the variable was emitted |
Ben Clayton | dcdf66e | 2022-06-17 12:48:51 +0000 | [diff] [blame] | 356 | bool EmitLet(const ast::Let* let); |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 357 | /// Emits the zero value for the given type |
| 358 | /// @param out the output of the expression stream |
| 359 | /// @param type the type to emit the value for |
| 360 | /// @returns true if the zero value was successfully emitted. |
dan sinclair | 52fa68b | 2023-02-28 14:54:51 +0000 | [diff] [blame] | 361 | bool EmitZeroValue(utils::StringStream& out, const type::Type* type); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 362 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 363 | /// Handles generating a builtin name |
| 364 | /// @param builtin the semantic info for the builtin |
| 365 | /// @returns the name or "" if not valid |
| 366 | std::string generate_builtin_name(const sem::Builtin* builtin); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 367 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 368 | /// Converts a builtin to an attribute name |
| 369 | /// @param builtin the builtin to convert |
| 370 | /// @returns the string name of the builtin or blank on error |
dan sinclair | 6392579 | 2023-02-17 21:56:35 +0000 | [diff] [blame] | 371 | std::string builtin_to_attribute(builtin::BuiltinValue builtin) const; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 372 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 373 | /// Converts interpolation attributes to an MSL attribute |
| 374 | /// @param type the interpolation type |
| 375 | /// @param sampling the interpolation sampling |
| 376 | /// @returns the string name of the attribute or blank on error |
dan sinclair | 993a658 | 2023-02-20 08:37:45 +0000 | [diff] [blame] | 377 | std::string interpolation_to_attribute(builtin::InterpolationType type, |
| 378 | builtin::InterpolationSampling sampling) const; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 379 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 380 | private: |
| 381 | // A pair of byte size and alignment `uint32_t`s. |
| 382 | struct SizeAndAlign { |
| 383 | uint32_t size; |
| 384 | uint32_t align; |
| 385 | }; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 386 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 387 | /// CallBuiltinHelper will call the builtin helper function, creating it |
| 388 | /// if it hasn't been built already. If the builtin needs to be built then |
| 389 | /// CallBuiltinHelper will generate the function signature and will call |
| 390 | /// `build` to emit the body of the function. |
| 391 | /// @param out the output of the expression stream |
| 392 | /// @param call the call expression |
| 393 | /// @param builtin the semantic information for the builtin |
| 394 | /// @param build a function with the signature: |
| 395 | /// `bool(TextBuffer* buffer, const std::vector<std::string>& params)` |
| 396 | /// Where: |
| 397 | /// `buffer` is the body of the generated function |
| 398 | /// `params` is the name of all the generated function parameters |
| 399 | /// @returns true if the call expression is emitted |
| 400 | template <typename F> |
dan sinclair | 52fa68b | 2023-02-28 14:54:51 +0000 | [diff] [blame] | 401 | bool CallBuiltinHelper(utils::StringStream& out, |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 402 | const ast::CallExpression* call, |
| 403 | const sem::Builtin* builtin, |
| 404 | F&& build); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 405 | |
Ben Clayton | f47887d | 2022-06-24 17:01:59 +0000 | [diff] [blame] | 406 | /// @returns the name of the templated tint_array helper type, generating it if this is the |
| 407 | /// first call. |
| 408 | const std::string& ArrayType(); |
| 409 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 410 | TextBuffer helpers_; // Helper functions emitted at the top of the output |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 411 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 412 | /// @returns the MSL packed type size and alignment in bytes for the given |
| 413 | /// type. |
dan sinclair | 5f764d8 | 2022-12-08 00:32:27 +0000 | [diff] [blame] | 414 | SizeAndAlign MslPackedTypeSizeAndAlign(const type::Type* ty); |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 415 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 416 | std::function<bool()> emit_continuing_; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 417 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 418 | /// Name of atomicCompareExchangeWeak() helper for the given pointer storage |
Antonio Maiorano | f25140f | 2022-06-03 14:47:01 +0000 | [diff] [blame] | 419 | /// class and struct return type |
| 420 | using ACEWKeyType = |
Ben Clayton | bc9e422 | 2023-04-27 18:31:44 +0000 | [diff] [blame] | 421 | utils::UnorderedKeyWrapper<std::tuple<builtin::AddressSpace, const type::Struct*>>; |
Antonio Maiorano | f25140f | 2022-06-03 14:47:01 +0000 | [diff] [blame] | 422 | std::unordered_map<ACEWKeyType, std::string> atomicCompareExchangeWeak_; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 423 | |
Ben Clayton | f47887d | 2022-06-24 17:01:59 +0000 | [diff] [blame] | 424 | /// Unique name of the 'TINT_INVARIANT' preprocessor define. |
| 425 | /// Non-empty only if an invariant attribute has been generated. |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 426 | std::string invariant_define_name_; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 427 | |
Ben Clayton | a92f425 | 2022-10-27 14:36:49 +0000 | [diff] [blame] | 428 | /// The generated name for the packed vec3 type. |
| 429 | std::string packed_vec3_ty_; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 430 | |
Ben Clayton | f47887d | 2022-06-24 17:01:59 +0000 | [diff] [blame] | 431 | /// Unique name of the tint_array<T, N> template. |
| 432 | /// Non-empty only if the template has been generated. |
| 433 | std::string array_template_name_; |
| 434 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 435 | /// A map from entry point name to a list of dynamic workgroup allocations. |
| 436 | /// Each entry in the vector is the size of the workgroup allocation that |
| 437 | /// should be created for that index. |
| 438 | std::unordered_map<std::string, std::vector<uint32_t>> workgroup_allocations_; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 439 | |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 440 | std::unordered_map<const sem::Builtin*, std::string> builtins_; |
dan sinclair | 5f764d8 | 2022-12-08 00:32:27 +0000 | [diff] [blame] | 441 | std::unordered_map<const type::Type*, std::string> unary_minus_funcs_; |
dan sinclair | 41e4d9a | 2022-05-01 14:40:55 +0000 | [diff] [blame] | 442 | std::unordered_map<uint32_t, std::string> int_dot_funcs_; |
Ben Clayton | bc9e422 | 2023-04-27 18:31:44 +0000 | [diff] [blame] | 443 | std::unordered_set<const type::Struct*> emitted_structs_; |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 444 | }; |
| 445 | |
dan sinclair | 9fe8260 | 2022-04-07 13:58:14 +0000 | [diff] [blame] | 446 | } // namespace tint::writer::msl |
Ryan Harrison | dbc13af | 2022-02-21 15:19:07 +0000 | [diff] [blame] | 447 | |
| 448 | #endif // SRC_TINT_WRITER_MSL_GENERATOR_IMPL_H_ |