blob: 56d07696bdbf3816044672e9845901b0b6be1fdf [file] [log] [blame]
Austin Engcc2516a2023-10-17 20:57:54 +00001// Copyright 2021 The Dawn & Tint Authors
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002//
Austin Engcc2516a2023-10-17 20:57:54 +00003// Redistribution and use in source and binary forms, with or without
4// modification, are permitted provided that the following conditions are met:
Ryan Harrisondbc13af2022-02-21 15:19:07 +00005//
Austin Engcc2516a2023-10-17 20:57:54 +00006// 1. Redistributions of source code must retain the above copyright notice, this
7// list of conditions and the following disclaimer.
Ryan Harrisondbc13af2022-02-21 15:19:07 +00008//
Austin Engcc2516a2023-10-17 20:57:54 +00009// 2. Redistributions in binary form must reproduce the above copyright notice,
10// this list of conditions and the following disclaimer in the documentation
11// and/or other materials provided with the distribution.
12//
13// 3. Neither the name of the copyright holder nor the names of its
14// contributors may be used to endorse or promote products derived from
15// this software without specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
21// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Ryan Harrisondbc13af2022-02-21 15:19:07 +000027
dan sinclaird3b13692023-07-20 01:14:15 +000028#ifndef SRC_TINT_LANG_WGSL_SEM_FUNCTION_H_
29#define SRC_TINT_LANG_WGSL_SEM_FUNCTION_H_
Ryan Harrisondbc13af2022-02-21 15:19:07 +000030
31#include <array>
dan sinclair766a4582022-09-06 16:00:13 +000032#include <optional>
Ryan Harrisondbc13af2022-02-21 15:19:07 +000033#include <utility>
34#include <vector>
35
dan sinclair99181d82023-07-20 01:14:15 +000036#include "src/tint/lang/wgsl/ast/diagnostic_control.h"
37#include "src/tint/lang/wgsl/ast/variable.h"
dan sinclaird3b13692023-07-20 01:14:15 +000038#include "src/tint/lang/wgsl/sem/call.h"
dan sinclair22b4dd22023-07-21 00:40:07 +000039#include "src/tint/utils/containers/unique_vector.h"
40#include "src/tint/utils/containers/vector.h"
Ben Claytondc68d5c2023-08-01 00:37:35 +000041#include "src/tint/utils/symbol/symbol.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000042
Ryan Harrisondbc13af2022-02-21 15:19:07 +000043// Forward declarations
Ben Claytona7230f02022-04-11 14:37:21 +000044namespace tint::ast {
Ryan Harrisondbc13af2022-02-21 15:19:07 +000045class BuiltinAttribute;
46class Function;
47class LocationAttribute;
48class ReturnStatement;
Ben Claytona7230f02022-04-11 14:37:21 +000049} // namespace tint::ast
50namespace tint::sem {
Ben Claytond9766dc2023-09-21 12:41:20 +000051class BuiltinFn;
Ryan Harrisondbc13af2022-02-21 15:19:07 +000052class Variable;
Ben Claytona7230f02022-04-11 14:37:21 +000053} // namespace tint::sem
dan sinclairc990b3c2022-04-07 16:04:35 +000054
55namespace tint::sem {
Ryan Harrisondbc13af2022-02-21 15:19:07 +000056
Ryan Harrisondbc13af2022-02-21 15:19:07 +000057/// WorkgroupSize is a three-dimensional array of WorkgroupDimensions.
Ben Claytonf10a5792022-10-13 13:47:39 +000058/// Each dimension is a std::optional as a workgroup size can be a const-expression or
59/// override-expression. Override expressions are not known at compilation time, so these will be
60/// std::nullopt.
Ben Clayton490d9882022-09-21 21:05:45 +000061using WorkgroupSize = std::array<std::optional<uint32_t>, 3>;
Ryan Harrisondbc13af2022-02-21 15:19:07 +000062
63/// Function holds the semantic information for function nodes.
dan sinclairbae54e72023-07-28 15:01:54 +000064class Function final : public Castable<Function, CallTarget> {
dan sinclair41e4d9a2022-05-01 14:40:55 +000065 public:
Ben Clayton10252582023-07-25 20:53:25 +000066 /// A vector of [Variable*, BindingPoint] pairs
67 using VariableBindings = std::vector<std::pair<const Variable*, BindingPoint>>;
Ryan Harrisondbc13af2022-02-21 15:19:07 +000068
dan sinclair41e4d9a2022-05-01 14:40:55 +000069 /// Constructor
70 /// @param declaration the ast::Function
Ben Clayton63d0fab2023-03-06 15:43:16 +000071 explicit Function(const ast::Function* declaration);
Ryan Harrisondbc13af2022-02-21 15:19:07 +000072
dan sinclair41e4d9a2022-05-01 14:40:55 +000073 /// Destructor
74 ~Function() override;
Ryan Harrisondbc13af2022-02-21 15:19:07 +000075
Ben Clayton63d0fab2023-03-06 15:43:16 +000076 /// Sets the function's return location
77 /// @param return_location the location value
78 void SetReturnLocation(uint32_t return_location) { return_location_ = return_location; }
79
Brandon Jonesfbc27382023-06-22 21:51:30 +000080 // Sets the function's return index
81 /// @param return_index the index value
82 void SetReturnIndex(uint32_t return_index) { return_index_ = return_index; }
83
dan sinclair41e4d9a2022-05-01 14:40:55 +000084 /// @returns the ast::Function declaration
85 const ast::Function* Declaration() const { return declaration_; }
Ryan Harrisondbc13af2022-02-21 15:19:07 +000086
dan sinclair41e4d9a2022-05-01 14:40:55 +000087 /// @returns the workgroup size {x, y, z} for the function.
88 const sem::WorkgroupSize& WorkgroupSize() const { return workgroup_size_; }
Ryan Harrisondbc13af2022-02-21 15:19:07 +000089
dan sinclair41e4d9a2022-05-01 14:40:55 +000090 /// Sets the workgroup size {x, y, z} for the function.
91 /// @param workgroup_size the new workgroup size of the function
92 void SetWorkgroupSize(sem::WorkgroupSize workgroup_size) {
93 workgroup_size_ = std::move(workgroup_size);
Ryan Harrisondbc13af2022-02-21 15:19:07 +000094 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +000095
dan sinclair41e4d9a2022-05-01 14:40:55 +000096 /// @returns all directly referenced global variables
dan sinclairbae54e72023-07-28 15:01:54 +000097 const UniqueVector<const GlobalVariable*, 4>& DirectlyReferencedGlobals() const {
dan sinclair41e4d9a2022-05-01 14:40:55 +000098 return directly_referenced_globals_;
99 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000100
dan sinclair41e4d9a2022-05-01 14:40:55 +0000101 /// Records that this function directly references the given global variable.
Ben Clayton535535b2023-10-09 15:14:34 +0000102 /// Note: Implicitly adds this global to the transitively-called globals.
dan sinclair41e4d9a2022-05-01 14:40:55 +0000103 /// @param global the module-scope variable
104 void AddDirectlyReferencedGlobal(const sem::GlobalVariable* global) {
Ben Claytondce63f52022-08-17 18:07:20 +0000105 directly_referenced_globals_.Add(global);
Ben Clayton535535b2023-10-09 15:14:34 +0000106 AddTransitivelyReferencedGlobal(global);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000107 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000108
dan sinclair41e4d9a2022-05-01 14:40:55 +0000109 /// @returns all transitively referenced global variables
dan sinclairbae54e72023-07-28 15:01:54 +0000110 const UniqueVector<const GlobalVariable*, 8>& TransitivelyReferencedGlobals() const {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000111 return transitively_referenced_globals_;
112 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000113
dan sinclair41e4d9a2022-05-01 14:40:55 +0000114 /// Records that this function transitively references the given global
115 /// variable.
116 /// @param global the module-scoped variable
Ben Clayton535535b2023-10-09 15:14:34 +0000117 void AddTransitivelyReferencedGlobal(const sem::GlobalVariable* global);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000118
dan sinclair41e4d9a2022-05-01 14:40:55 +0000119 /// @returns the list of functions that this function transitively calls.
dan sinclairbae54e72023-07-28 15:01:54 +0000120 const UniqueVector<const Function*, 8>& TransitivelyCalledFunctions() const {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000121 return transitively_called_functions_;
122 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000123
dan sinclair41e4d9a2022-05-01 14:40:55 +0000124 /// Records that this function transitively calls `function`.
125 /// @param function the function this function transitively calls
126 void AddTransitivelyCalledFunction(const Function* function) {
Ben Claytondce63f52022-08-17 18:07:20 +0000127 transitively_called_functions_.Add(function);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000128 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000129
dan sinclair41e4d9a2022-05-01 14:40:55 +0000130 /// @returns the list of builtins that this function directly calls.
Ben Claytond9766dc2023-09-21 12:41:20 +0000131 const UniqueVector<const BuiltinFn*, 4>& DirectlyCalledBuiltins() const {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000132 return directly_called_builtins_;
133 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000134
dan sinclair41e4d9a2022-05-01 14:40:55 +0000135 /// Records that this function transitively calls `builtin`.
136 /// @param builtin the builtin this function directly calls
Ben Claytond9766dc2023-09-21 12:41:20 +0000137 void AddDirectlyCalledBuiltin(const BuiltinFn* builtin) {
Ben Claytondce63f52022-08-17 18:07:20 +0000138 directly_called_builtins_.Add(builtin);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000139 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000140
dan sinclair41e4d9a2022-05-01 14:40:55 +0000141 /// Adds the given texture/sampler pair to the list of unique pairs
142 /// that this function uses (directly or indirectly). These can only
143 /// be parameters to this function or global variables. Uniqueness is
144 /// ensured by texture_sampler_pairs_ being a UniqueVector.
Stephen White1026cc12024-08-13 18:23:20 +0000145 /// @param texture the texture (must be non-null)
dan sinclair41e4d9a2022-05-01 14:40:55 +0000146 /// @param sampler the sampler (null indicates a texture-only reference)
147 void AddTextureSamplerPair(const sem::Variable* texture, const sem::Variable* sampler) {
Stephen White1026cc12024-08-13 18:23:20 +0000148 TINT_ASSERT(texture != nullptr);
Ben Claytondce63f52022-08-17 18:07:20 +0000149 texture_sampler_pairs_.Add(VariablePair(texture, sampler));
dan sinclair41e4d9a2022-05-01 14:40:55 +0000150 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000151
dan sinclair41e4d9a2022-05-01 14:40:55 +0000152 /// @returns the list of texture/sampler pairs that this function uses
153 /// (directly or indirectly).
dan sinclairbae54e72023-07-28 15:01:54 +0000154 VectorRef<VariablePair> TextureSamplerPairs() const { return texture_sampler_pairs_; }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000155
dan sinclair41e4d9a2022-05-01 14:40:55 +0000156 /// @returns the list of direct calls to functions / builtins made by this
157 /// function
Ben Clayton31a15922024-01-29 16:00:36 +0000158 const Vector<const Call*, 1>& DirectCalls() const { return direct_calls_; }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000159
dan sinclair41e4d9a2022-05-01 14:40:55 +0000160 /// Adds a record of the direct function / builtin calls made by this
161 /// function
162 /// @param call the call
Ben Clayton31a15922024-01-29 16:00:36 +0000163 void AddDirectCall(const Call* call) { direct_calls_.Push(call); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000164
dan sinclair41e4d9a2022-05-01 14:40:55 +0000165 /// @param target the target of a call
166 /// @returns the Call to the given CallTarget, or nullptr the target was not
167 /// called by this function.
168 const Call* FindDirectCallTo(const CallTarget* target) const {
169 for (auto* call : direct_calls_) {
170 if (call->Target() == target) {
171 return call;
172 }
173 }
174 return nullptr;
175 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000176
Ben Clayton4c593c32022-11-30 11:50:54 +0000177 /// @returns the list of callsites to this function
Ben Clayton31a15922024-01-29 16:00:36 +0000178 const Vector<const Call*, 1>& CallSites() const { return callsites_; }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000179
dan sinclair41e4d9a2022-05-01 14:40:55 +0000180 /// Adds a record of a callsite to this function
181 /// @param call the callsite
Ben Clayton31a15922024-01-29 16:00:36 +0000182 void AddCallSite(const Call* call) { callsites_.Push(call); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000183
dan sinclair41e4d9a2022-05-01 14:40:55 +0000184 /// @returns the ancestor entry points
Ben Clayton31a15922024-01-29 16:00:36 +0000185 const Vector<const Function*, 1>& AncestorEntryPoints() const { return ancestor_entry_points_; }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000186
dan sinclair41e4d9a2022-05-01 14:40:55 +0000187 /// Adds a record that the given entry point transitively calls this function
188 /// @param entry_point the entry point that transtively calls this function
189 void AddAncestorEntryPoint(const sem::Function* entry_point) {
Ben Clayton31a15922024-01-29 16:00:36 +0000190 ancestor_entry_points_.Push(entry_point);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000191 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000192
dan sinclair41e4d9a2022-05-01 14:40:55 +0000193 /// Retrieves any referenced location variables
194 /// @returns the <variable, attribute> pair.
195 std::vector<std::pair<const Variable*, const ast::LocationAttribute*>>
196 TransitivelyReferencedLocationVariables() const;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000197
dan sinclair41e4d9a2022-05-01 14:40:55 +0000198 /// Retrieves any referenced builtin variables
199 /// @returns the <variable, attribute> pair.
200 std::vector<std::pair<const Variable*, const ast::BuiltinAttribute*>>
201 TransitivelyReferencedBuiltinVariables() const;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000202
dan sinclair41e4d9a2022-05-01 14:40:55 +0000203 /// Retrieves any referenced uniform variables. Note, the variables must be
204 /// decorated with both binding and group attributes.
205 /// @returns the referenced uniforms
206 VariableBindings TransitivelyReferencedUniformVariables() const;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000207
dan sinclair41e4d9a2022-05-01 14:40:55 +0000208 /// Retrieves any referenced storagebuffer variables. Note, the variables
209 /// must be decorated with both binding and group attributes.
210 /// @returns the referenced storagebuffers
211 VariableBindings TransitivelyReferencedStorageBufferVariables() const;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000212
dan sinclair41e4d9a2022-05-01 14:40:55 +0000213 /// Retrieves any referenced regular Sampler variables. Note, the
214 /// variables must be decorated with both binding and group attributes.
215 /// @returns the referenced storagebuffers
216 VariableBindings TransitivelyReferencedSamplerVariables() const;
217
218 /// Retrieves any referenced comparison Sampler variables. Note, the
219 /// variables must be decorated with both binding and group attributes.
220 /// @returns the referenced storagebuffers
221 VariableBindings TransitivelyReferencedComparisonSamplerVariables() const;
222
223 /// Retrieves any referenced sampled textures variables. Note, the
224 /// variables must be decorated with both binding and group attributes.
225 /// @returns the referenced sampled textures
226 VariableBindings TransitivelyReferencedSampledTextureVariables() const;
227
228 /// Retrieves any referenced multisampled textures variables. Note, the
229 /// variables must be decorated with both binding and group attributes.
230 /// @returns the referenced sampled textures
231 VariableBindings TransitivelyReferencedMultisampledTextureVariables() const;
232
233 /// Retrieves any referenced variables of the given type. Note, the variables
234 /// must be decorated with both binding and group attributes.
235 /// @param type the type of the variables to find
236 /// @returns the referenced variables
dan sinclairbae54e72023-07-28 15:01:54 +0000237 VariableBindings TransitivelyReferencedVariablesOfType(const tint::TypeInfo* type) const;
dan sinclair41e4d9a2022-05-01 14:40:55 +0000238
239 /// Retrieves any referenced variables of the given type. Note, the variables
240 /// must be decorated with both binding and group attributes.
241 /// @returns the referenced variables
242 template <typename T>
243 VariableBindings TransitivelyReferencedVariablesOfType() const {
dan sinclairbae54e72023-07-28 15:01:54 +0000244 return TransitivelyReferencedVariablesOfType(&tint::TypeInfo::Of<T>());
dan sinclair41e4d9a2022-05-01 14:40:55 +0000245 }
246
247 /// Checks if the given entry point is an ancestor
248 /// @param sym the entry point symbol
249 /// @returns true if `sym` is an ancestor entry point of this function
250 bool HasAncestorEntryPoint(Symbol sym) const;
251
Ben Claytond9222f42022-10-14 13:44:54 +0000252 /// Records the first discard statement in the function
253 /// @param stmt the `discard` statement.
254 void SetDiscardStatement(const Statement* stmt) {
255 if (!discard_stmt_) {
256 discard_stmt_ = stmt;
257 }
258 }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000259
Ben Claytond9222f42022-10-14 13:44:54 +0000260 /// @returns the first discard statement for the function, or nullptr if the function does not
261 /// use `discard`.
262 const Statement* DiscardStatement() const { return discard_stmt_; }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000263
264 /// @return the behaviors of this function
265 const sem::Behaviors& Behaviors() const { return behaviors_; }
266
267 /// @return the behaviors of this function
268 sem::Behaviors& Behaviors() { return behaviors_; }
269
dan sinclair766a4582022-09-06 16:00:13 +0000270 /// @return the location for the return, if provided
271 std::optional<uint32_t> ReturnLocation() const { return return_location_; }
272
Brandon Jonesfbc27382023-06-22 21:51:30 +0000273 /// @return the index for the return, if provided
274 std::optional<uint32_t> ReturnIndex() const { return return_index_; }
275
James Price58532052023-01-25 01:24:46 +0000276 /// Modifies the severity of a specific diagnostic rule for this function.
277 /// @param rule the diagnostic rule
278 /// @param severity the new diagnostic severity
Ben Clayton8be957f2024-01-29 16:00:36 +0000279 void SetDiagnosticSeverity(wgsl::DiagnosticRule rule, wgsl::DiagnosticSeverity severity);
James Price58532052023-01-25 01:24:46 +0000280
281 /// @returns the diagnostic severity modifications applied to this function
Ben Clayton11653892023-09-19 19:15:59 +0000282 const wgsl::DiagnosticRuleSeverities& DiagnosticSeverities() const {
James Price58532052023-01-25 01:24:46 +0000283 return diagnostic_severities_;
284 }
285
dan sinclair41e4d9a2022-05-01 14:40:55 +0000286 private:
Ben Claytondce63f52022-08-17 18:07:20 +0000287 Function(const Function&) = delete;
288 Function(Function&&) = delete;
289
dan sinclaircedcdf32023-08-10 02:39:48 +0000290 VariableBindings TransitivelyReferencedSamplerVariablesImpl(core::type::SamplerKind kind) const;
dan sinclair41e4d9a2022-05-01 14:40:55 +0000291 VariableBindings TransitivelyReferencedSampledTextureVariablesImpl(bool multisampled) const;
292
293 const ast::Function* const declaration_;
294
295 sem::WorkgroupSize workgroup_size_;
dan sinclairbae54e72023-07-28 15:01:54 +0000296 UniqueVector<const GlobalVariable*, 4> directly_referenced_globals_;
297 UniqueVector<const GlobalVariable*, 8> transitively_referenced_globals_;
298 UniqueVector<const Function*, 8> transitively_called_functions_;
Ben Claytond9766dc2023-09-21 12:41:20 +0000299 UniqueVector<const BuiltinFn*, 4> directly_called_builtins_;
dan sinclairbae54e72023-07-28 15:01:54 +0000300 UniqueVector<VariablePair, 8> texture_sampler_pairs_;
Ben Clayton31a15922024-01-29 16:00:36 +0000301 Vector<const Call*, 1> direct_calls_;
302 Vector<const Call*, 1> callsites_;
303 Vector<const Function*, 1> ancestor_entry_points_;
Ben Claytond9222f42022-10-14 13:44:54 +0000304 const Statement* discard_stmt_ = nullptr;
dan sinclair41e4d9a2022-05-01 14:40:55 +0000305 sem::Behaviors behaviors_{sem::Behavior::kNext};
Ben Clayton11653892023-09-19 19:15:59 +0000306 wgsl::DiagnosticRuleSeverities diagnostic_severities_;
dan sinclair766a4582022-09-06 16:00:13 +0000307
308 std::optional<uint32_t> return_location_;
Brandon Jonesfbc27382023-06-22 21:51:30 +0000309 std::optional<uint32_t> return_index_;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000310};
311
dan sinclairc990b3c2022-04-07 16:04:35 +0000312} // namespace tint::sem
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000313
dan sinclaird3b13692023-07-20 01:14:15 +0000314#endif // SRC_TINT_LANG_WGSL_SEM_FUNCTION_H_