blob: 0be80be6bfec965a2863ef0ae5b262ef04de4bf5 [file] [log] [blame]
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001// Copyright 2020 The Tint Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef SRC_TINT_WRITER_MSL_GENERATOR_IMPL_H_
16#define SRC_TINT_WRITER_MSL_GENERATOR_IMPL_H_
17
18#include <string>
Antonio Maioranof25140f2022-06-03 14:47:01 +000019#include <tuple>
Ryan Harrisondbc13af2022-02-21 15:19:07 +000020#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 Clayton4d3ff972023-02-21 17:33:54 +000039#include "src/tint/builtin/builtin_value.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000040#include "src/tint/program.h"
41#include "src/tint/scope_stack.h"
42#include "src/tint/sem/struct.h"
dan sinclair52fa68b2023-02-28 14:54:51 +000043#include "src/tint/utils/string_stream.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000044#include "src/tint/writer/array_length_from_uniform_options.h"
Antonio Maiorano7eaab382022-04-11 16:33:30 +000045#include "src/tint/writer/msl/generator.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000046#include "src/tint/writer/text_generator.h"
47
Ryan Harrisondbc13af2022-02-21 15:19:07 +000048// Forward declarations
dan sinclair9fe82602022-04-07 13:58:14 +000049namespace tint::sem {
Ryan Harrisondbc13af2022-02-21 15:19:07 +000050class Builtin;
Ben Clayton54a104e2023-02-22 20:04:40 +000051class Call;
52class ValueConstructor;
53class ValueConversion;
dan sinclair9fe82602022-04-07 13:58:14 +000054} // namespace tint::sem
Ryan Harrisondbc13af2022-02-21 15:19:07 +000055
dan sinclair9fe82602022-04-07 13:58:14 +000056namespace tint::writer::msl {
Ryan Harrisondbc13af2022-02-21 15:19:07 +000057
58/// The result of sanitizing a program for generation.
59struct SanitizedResult {
dan sinclair41e4d9a2022-05-01 14:40:55 +000060 /// Constructor
61 SanitizedResult();
62 /// Destructor
63 ~SanitizedResult();
64 /// Move constructor
65 SanitizedResult(SanitizedResult&&);
Ryan Harrisondbc13af2022-02-21 15:19:07 +000066
dan sinclair41e4d9a2022-05-01 14:40:55 +000067 /// 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 Harrisondbc13af2022-02-21 15:19:07 +000074};
75
76/// Sanitize a program in preparation for generating MSL.
Antonio Maiorano7eaab382022-04-11 16:33:30 +000077/// @program The program to sanitize
78/// @param options The MSL generator options.
Ryan Harrisondbc13af2022-02-21 15:19:07 +000079/// @returns the sanitized program and any supplementary information
Antonio Maiorano7eaab382022-04-11 16:33:30 +000080SanitizedResult Sanitize(const Program* program, const Options& options);
Ryan Harrisondbc13af2022-02-21 15:19:07 +000081
82/// Implementation class for MSL generator
83class GeneratorImpl : public TextGenerator {
dan sinclair41e4d9a2022-05-01 14:40:55 +000084 public:
85 /// Constructor
86 /// @param program the program to generate
87 explicit GeneratorImpl(const Program* program);
88 ~GeneratorImpl();
Ryan Harrisondbc13af2022-02-21 15:19:07 +000089
dan sinclair41e4d9a2022-05-01 14:40:55 +000090 /// @returns true on successful generation; false otherwise
91 bool Generate();
Ryan Harrisondbc13af2022-02-21 15:19:07 +000092
dan sinclair41e4d9a2022-05-01 14:40:55 +000093 /// @returns true if an invariant attribute was generated
94 bool HasInvariant() { return !invariant_define_name_.empty(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +000095
dan sinclair41e4d9a2022-05-01 14:40:55 +000096 /// @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 Harrisondbc13af2022-02-21 15:19:07 +0000101
dan sinclair41e4d9a2022-05-01 14:40:55 +0000102 /// Handles generating a declared type
103 /// @param ty the declared type to generate
104 /// @returns true if the declared type was emitted
dan sinclair5f764d82022-12-08 00:32:27 +0000105 bool EmitTypeDecl(const type::Type* ty);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000106 /// 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 sinclair52fa68b2023-02-28 14:54:51 +0000110 bool EmitIndexAccessor(utils::StringStream& out, const ast::IndexAccessorExpression* expr);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000111 /// 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 sinclair52fa68b2023-02-28 14:54:51 +0000119 bool EmitBinary(utils::StringStream& out, const ast::BinaryExpression* expr);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000120 /// 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 sinclair52fa68b2023-02-28 14:54:51 +0000124 bool EmitBitcast(utils::StringStream& out, const ast::BitcastExpression* expr);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000125 /// 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 sinclairb8b0c212022-10-20 22:45:50 +0000133 /// 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 sinclair41e4d9a2022-05-01 14:40:55 +0000137 /// 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 sinclair52fa68b2023-02-28 14:54:51 +0000141 bool EmitCall(utils::StringStream& out, const ast::CallExpression* expr);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000142 /// 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 sinclair52fa68b2023-02-28 14:54:51 +0000147 bool EmitBuiltinCall(utils::StringStream& out,
148 const sem::Call* call,
149 const sem::Builtin* builtin);
Ben Clayton54a104e2023-02-22 20:04:40 +0000150 /// Handles generating a value conversion expression
dan sinclair41e4d9a2022-05-01 14:40:55 +0000151 /// @param out the output of the expression stream
152 /// @param call the call expression
Ben Clayton54a104e2023-02-22 20:04:40 +0000153 /// @param conv the value conversion
dan sinclair41e4d9a2022-05-01 14:40:55 +0000154 /// @returns true if the expression is emitted
dan sinclair52fa68b2023-02-28 14:54:51 +0000155 bool EmitTypeConversion(utils::StringStream& out,
dan sinclair41e4d9a2022-05-01 14:40:55 +0000156 const sem::Call* call,
Ben Clayton54a104e2023-02-22 20:04:40 +0000157 const sem::ValueConversion* conv);
158 /// Handles generating a value constructor
dan sinclair41e4d9a2022-05-01 14:40:55 +0000159 /// @param out the output of the expression stream
160 /// @param call the call expression
Ben Clayton54a104e2023-02-22 20:04:40 +0000161 /// @param ctor the value constructor
dan sinclair6e77b472022-10-20 13:38:28 +0000162 /// @returns true if the initializer is emitted
dan sinclair52fa68b2023-02-28 14:54:51 +0000163 bool EmitTypeInitializer(utils::StringStream& out,
dan sinclair41e4d9a2022-05-01 14:40:55 +0000164 const sem::Call* call,
Ben Clayton54a104e2023-02-22 20:04:40 +0000165 const sem::ValueConstructor* ctor);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000166 /// 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 sinclair52fa68b2023-02-28 14:54:51 +0000171 bool EmitFunctionCall(utils::StringStream& out,
172 const sem::Call* call,
173 const sem::Function* func);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000174 /// 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 sinclair52fa68b2023-02-28 14:54:51 +0000180 bool EmitAtomicCall(utils::StringStream& out,
dan sinclair41e4d9a2022-05-01 14:40:55 +0000181 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 sinclair52fa68b2023-02-28 14:54:51 +0000189 bool EmitTextureCall(utils::StringStream& out,
190 const sem::Call* call,
191 const sem::Builtin* builtin);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000192 /// 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 sinclair52fa68b2023-02-28 14:54:51 +0000197 bool EmitDotCall(utils::StringStream& out,
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000198 const ast::CallExpression* expr,
199 const sem::Builtin* builtin);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000200 /// 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 sinclair52fa68b2023-02-28 14:54:51 +0000205 bool EmitModfCall(utils::StringStream& out,
dan sinclair41e4d9a2022-05-01 14:40:55 +0000206 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 sinclair52fa68b2023-02-28 14:54:51 +0000213 bool EmitFrexpCall(utils::StringStream& out,
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000214 const ast::CallExpression* expr,
215 const sem::Builtin* builtin);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000216 /// 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 sinclair52fa68b2023-02-28 14:54:51 +0000221 bool EmitDegreesCall(utils::StringStream& out,
dan sinclair41e4d9a2022-05-01 14:40:55 +0000222 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 sinclair52fa68b2023-02-28 14:54:51 +0000229 bool EmitRadiansCall(utils::StringStream& out,
dan sinclair41e4d9a2022-05-01 14:40:55 +0000230 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 sinclair52fa68b2023-02-28 14:54:51 +0000252 bool EmitExpression(utils::StringStream& out, const ast::Expression* expr);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000253 /// 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 sinclair52fa68b2023-02-28 14:54:51 +0000261 bool EmitIdentifier(utils::StringStream& out, const ast::IdentifierExpression* expr);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000262 /// 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 Claytoncb6ddd22022-06-01 10:08:29 +0000266 /// 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 sinclair52fa68b2023-02-28 14:54:51 +0000270 bool EmitConstant(utils::StringStream& out, const constant::Value* constant);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000271 /// 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 sinclair52fa68b2023-02-28 14:54:51 +0000275 bool EmitLiteral(utils::StringStream& out, const ast::LiteralExpression* lit);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000276 /// 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 sinclair49d1a2d2022-06-16 12:01:27 +0000284 /// 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 sinclair41e4d9a2022-05-01 14:40:55 +0000288 /// 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 sinclair52fa68b2023-02-28 14:54:51 +0000292 bool EmitMemberAccessor(utils::StringStream& out, const ast::MemberAccessorExpression* expr);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000293 /// 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 sinclair52fa68b2023-02-28 14:54:51 +0000300 void EmitStage(utils::StringStream& out, ast::PipelineStage stage);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000301 /// 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 Clayton783b1692022-08-02 17:03:35 +0000308 bool EmitStatements(utils::VectorRef<const ast::Statement*> stmts);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000309 /// Emits a list of statements with an indentation
310 /// @param stmts the statement list
311 /// @returns true if the statements were emitted successfully
Ben Clayton783b1692022-08-02 17:03:35 +0000312 bool EmitStatementsWithIndent(utils::VectorRef<const ast::Statement*> stmts);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000313 /// 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 sinclair52fa68b2023-02-28 14:54:51 +0000323 bool EmitType(utils::StringStream& out,
dan sinclair5f764d82022-12-08 00:32:27 +0000324 const type::Type* type,
dan sinclair41e4d9a2022-05-01 14:40:55 +0000325 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 sinclair52fa68b2023-02-28 14:54:51 +0000332 bool EmitTypeAndName(utils::StringStream& out, const type::Type* type, const std::string& name);
dan sinclairff7cf212022-10-03 14:05:23 +0000333 /// Handles generating a address space
dan sinclair41e4d9a2022-05-01 14:40:55 +0000334 /// @param out the output of the type stream
dan sinclairff7cf212022-10-03 14:05:23 +0000335 /// @param sc the address space to generate
336 /// @returns true if the address space is emitted
dan sinclair52fa68b2023-02-28 14:54:51 +0000337 bool EmitAddressSpace(utils::StringStream& out, builtin::AddressSpace sc);
Ben Clayton329dfd72022-11-23 00:05:05 +0000338 /// Handles generating a struct declaration. If the structure has already been emitted, then
339 /// this function will simply return `true` without emitting anything.
dan sinclair41e4d9a2022-05-01 14:40:55 +0000340 /// @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 Claytonbc9e4222023-04-27 18:31:44 +0000343 bool EmitStructType(TextBuffer* buffer, const type::Struct* str);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000344 /// 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 sinclair52fa68b2023-02-28 14:54:51 +0000348 bool EmitUnaryOp(utils::StringStream& out, const ast::UnaryOpExpression* expr);
Ben Claytondcdf66e2022-06-17 12:48:51 +0000349 /// Handles generating a 'var' declaration
dan sinclair41e4d9a2022-05-01 14:40:55 +0000350 /// @param var the variable to generate
351 /// @returns true if the variable was emitted
Ben Claytondcdf66e2022-06-17 12:48:51 +0000352 bool EmitVar(const ast::Var* var);
Ben Clayton576ba1c2023-04-27 17:58:25 +0000353 /// Handles generating a 'let' declaration
Ben Claytondcdf66e2022-06-17 12:48:51 +0000354 /// @param let the variable to generate
dan sinclair41e4d9a2022-05-01 14:40:55 +0000355 /// @returns true if the variable was emitted
Ben Claytondcdf66e2022-06-17 12:48:51 +0000356 bool EmitLet(const ast::Let* let);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000357 /// 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 sinclair52fa68b2023-02-28 14:54:51 +0000361 bool EmitZeroValue(utils::StringStream& out, const type::Type* type);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000362
dan sinclair41e4d9a2022-05-01 14:40:55 +0000363 /// 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 Harrisondbc13af2022-02-21 15:19:07 +0000367
dan sinclair41e4d9a2022-05-01 14:40:55 +0000368 /// 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 sinclair63925792023-02-17 21:56:35 +0000371 std::string builtin_to_attribute(builtin::BuiltinValue builtin) const;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000372
dan sinclair41e4d9a2022-05-01 14:40:55 +0000373 /// 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 sinclair993a6582023-02-20 08:37:45 +0000377 std::string interpolation_to_attribute(builtin::InterpolationType type,
378 builtin::InterpolationSampling sampling) const;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000379
dan sinclair41e4d9a2022-05-01 14:40:55 +0000380 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 Harrisondbc13af2022-02-21 15:19:07 +0000386
dan sinclair41e4d9a2022-05-01 14:40:55 +0000387 /// 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 sinclair52fa68b2023-02-28 14:54:51 +0000401 bool CallBuiltinHelper(utils::StringStream& out,
dan sinclair41e4d9a2022-05-01 14:40:55 +0000402 const ast::CallExpression* call,
403 const sem::Builtin* builtin,
404 F&& build);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000405
Ben Claytonf47887d2022-06-24 17:01:59 +0000406 /// @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 sinclair41e4d9a2022-05-01 14:40:55 +0000410 TextBuffer helpers_; // Helper functions emitted at the top of the output
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000411
dan sinclair41e4d9a2022-05-01 14:40:55 +0000412 /// @returns the MSL packed type size and alignment in bytes for the given
413 /// type.
dan sinclair5f764d82022-12-08 00:32:27 +0000414 SizeAndAlign MslPackedTypeSizeAndAlign(const type::Type* ty);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000415
dan sinclair41e4d9a2022-05-01 14:40:55 +0000416 std::function<bool()> emit_continuing_;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000417
dan sinclair41e4d9a2022-05-01 14:40:55 +0000418 /// Name of atomicCompareExchangeWeak() helper for the given pointer storage
Antonio Maioranof25140f2022-06-03 14:47:01 +0000419 /// class and struct return type
420 using ACEWKeyType =
Ben Claytonbc9e4222023-04-27 18:31:44 +0000421 utils::UnorderedKeyWrapper<std::tuple<builtin::AddressSpace, const type::Struct*>>;
Antonio Maioranof25140f2022-06-03 14:47:01 +0000422 std::unordered_map<ACEWKeyType, std::string> atomicCompareExchangeWeak_;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000423
Ben Claytonf47887d2022-06-24 17:01:59 +0000424 /// Unique name of the 'TINT_INVARIANT' preprocessor define.
425 /// Non-empty only if an invariant attribute has been generated.
dan sinclair41e4d9a2022-05-01 14:40:55 +0000426 std::string invariant_define_name_;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000427
Ben Claytona92f4252022-10-27 14:36:49 +0000428 /// The generated name for the packed vec3 type.
429 std::string packed_vec3_ty_;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000430
Ben Claytonf47887d2022-06-24 17:01:59 +0000431 /// 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 sinclair41e4d9a2022-05-01 14:40:55 +0000435 /// 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 Harrisondbc13af2022-02-21 15:19:07 +0000439
dan sinclair41e4d9a2022-05-01 14:40:55 +0000440 std::unordered_map<const sem::Builtin*, std::string> builtins_;
dan sinclair5f764d82022-12-08 00:32:27 +0000441 std::unordered_map<const type::Type*, std::string> unary_minus_funcs_;
dan sinclair41e4d9a2022-05-01 14:40:55 +0000442 std::unordered_map<uint32_t, std::string> int_dot_funcs_;
Ben Claytonbc9e4222023-04-27 18:31:44 +0000443 std::unordered_set<const type::Struct*> emitted_structs_;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000444};
445
dan sinclair9fe82602022-04-07 13:58:14 +0000446} // namespace tint::writer::msl
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000447
448#endif // SRC_TINT_WRITER_MSL_GENERATOR_IMPL_H_