Blender V4.3
FN_multi_function_procedure.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#pragma once
6
11#include "FN_multi_function.hh"
12
14
15class Variable;
16class Instruction;
17class CallInstruction;
18class BranchInstruction;
19class DestructInstruction;
20class DummyInstruction;
21class ReturnInstruction;
22class Procedure;
23
25enum class InstructionType {
26 Call,
27 Branch,
29 Dummy,
30 Return,
31};
32
38 public:
47
48 private:
49 Type type_ = None;
50 Instruction *instruction_ = nullptr;
51 /* Only used when it is a branch instruction. */
52 bool branch_output_ = false;
53
54 public:
55 InstructionCursor() = default;
60
62
63 Instruction *next(Procedure &procedure) const;
64 void set_next(Procedure &procedure, Instruction *new_instruction) const;
65
66 Instruction *instruction() const;
67
68 Type type() const;
69
70 BLI_STRUCT_EQUALITY_OPERATORS_3(InstructionCursor, type_, instruction_, branch_output_)
71};
72
79 private:
80 DataType data_type_;
82 std::string name_;
83 int index_in_graph_;
84
85 friend Procedure;
86 friend CallInstruction;
87 friend BranchInstruction;
89
90 public:
91 DataType data_type() const;
93
94 StringRefNull name() const;
95 void set_name(std::string name);
96
97 int index_in_procedure() const;
98};
99
122
128 private:
129 const MultiFunction *fn_ = nullptr;
130 Instruction *next_ = nullptr;
132
133 friend Procedure;
134
135 public:
136 const MultiFunction &fn() const;
137
138 Instruction *next();
139 const Instruction *next() const;
140 void set_next(Instruction *instruction);
141
142 void set_param_variable(int param_index, Variable *variable);
143 void set_params(Span<Variable *> variables);
144
147};
148
154 private:
155 Variable *condition_ = nullptr;
156 Instruction *branch_true_ = nullptr;
157 Instruction *branch_false_ = nullptr;
158
159 friend Procedure;
160
161 public:
163 const Variable *condition() const;
164 void set_condition(Variable *variable);
165
167 const Instruction *branch_true() const;
168 void set_branch_true(Instruction *instruction);
169
171 const Instruction *branch_false() const;
172 void set_branch_false(Instruction *instruction);
173};
174
182 private:
183 Variable *variable_ = nullptr;
184 Instruction *next_ = nullptr;
185
186 friend Procedure;
187
188 public:
190 const Variable *variable() const;
191 void set_variable(Variable *variable);
192
193 Instruction *next();
194 const Instruction *next() const;
195 void set_next(Instruction *instruction);
196};
197
202 private:
203 Instruction *next_ = nullptr;
204
205 friend Procedure;
206
207 public:
208 Instruction *next();
209 const Instruction *next() const;
210 void set_next(Instruction *instruction);
211};
212
217
225
230
240 private:
241 LinearAllocator<> allocator_;
242 Vector<CallInstruction *> call_instructions_;
243 Vector<BranchInstruction *> branch_instructions_;
244 Vector<DestructInstruction *> destruct_instructions_;
245 Vector<DummyInstruction *> dummy_instructions_;
246 Vector<ReturnInstruction *> return_instructions_;
247 Vector<Variable *> variables_;
248 Vector<Parameter> params_;
249 Vector<destruct_ptr<MultiFunction>> owned_functions_;
250 Instruction *entry_ = nullptr;
251
252 friend class ProcedureDotExport;
253
254 public:
255 Procedure() = default;
256 ~Procedure();
257
258 Variable &new_variable(DataType data_type, std::string name = "");
264
265 void add_parameter(ParamType::InterfaceType interface_type, Variable &variable);
267
268 template<typename T, typename... Args> const MultiFunction &construct_function(Args &&...args);
269
271 const Instruction *entry() const;
273
276
277 std::string to_dot() const;
278
279 bool validate() const;
280
281 private:
282 bool validate_all_instruction_pointers_set() const;
283 bool validate_all_params_provided() const;
284 bool validate_same_variables_in_one_call() const;
285 bool validate_parameters() const;
286 bool validate_initialization() const;
287
288 struct InitState {
289 bool can_be_initialized = false;
290 bool can_be_uninitialized = false;
291 };
292
293 InitState find_initialization_state_before_instruction(const Instruction &target_instruction,
294 const Variable &variable) const;
295};
296
297/* -------------------------------------------------------------------- */
302 : type_(Call), instruction_(&instruction)
303{
304}
305
307 : type_(Destruct), instruction_(&instruction)
308{
309}
310
311inline InstructionCursor::InstructionCursor(BranchInstruction &instruction, bool branch_output)
312 : type_(Branch), instruction_(&instruction), branch_output_(branch_output)
313{
314}
315
317 : type_(Dummy), instruction_(&instruction)
318{
319}
320
322{
323 InstructionCursor cursor;
324 cursor.type_ = Type::Entry;
325 return cursor;
326}
327
329{
330 /* This isn't really const correct unfortunately, because to make it correct we'll need a const
331 * version of #InstructionCursor. */
332 return instruction_;
333}
334
336{
337 return type_;
338}
339
342/* -------------------------------------------------------------------- */
347{
348 return data_type_;
349}
350
352{
353 return users_;
354}
355
357{
358 return name_;
359}
360
362{
363 return index_in_graph_;
364}
365
368/* -------------------------------------------------------------------- */
373{
374 return type_;
375}
376
378{
379 return prev_;
380}
381
384/* -------------------------------------------------------------------- */
389{
390 return *fn_;
391}
392
394{
395 return next_;
396}
397
399{
400 return next_;
401}
402
404{
405 return params_;
406}
407
409{
410 return params_;
411}
412
415/* -------------------------------------------------------------------- */
420{
421 return condition_;
422}
423
425{
426 return condition_;
427}
428
430{
431 return branch_true_;
432}
433
435{
436 return branch_true_;
437}
438
440{
441 return branch_false_;
442}
443
445{
446 return branch_false_;
447}
448
451/* -------------------------------------------------------------------- */
456{
457 return variable_;
458}
459
461{
462 return variable_;
463}
464
466{
467 return next_;
468}
469
471{
472 return next_;
473}
474
477/* -------------------------------------------------------------------- */
482{
483 return next_;
484}
485
487{
488 return next_;
489}
490
493/* -------------------------------------------------------------------- */
498{
499 static_assert(sizeof(Parameter) == sizeof(ConstParameter));
500 return params_.as_span().cast<ConstParameter>();
501}
502
504{
505 return entry_;
506}
507
508inline const Instruction *Procedure::entry() const
509{
510 return entry_;
511}
512
514{
515 return variables_;
516}
517
519{
520 return variables_;
521}
522
523template<typename T, typename... Args>
524inline const MultiFunction &Procedure::construct_function(Args &&...args)
525{
526 destruct_ptr<T> fn = allocator_.construct<T>(std::forward<Args>(args)...);
527 const MultiFunction &fn_ref = *fn;
528 owned_functions_.append(std::move(fn));
529 return fn_ref;
530}
531
534} // namespace blender::fn::multi_function
#define BLI_STRUCT_EQUALITY_OPERATORS_3(Type, m1, m2, m3)
destruct_ptr< T > construct(Args &&...args)
void set_param_variable(int param_index, Variable *variable)
void set_next(Procedure &procedure, Instruction *new_instruction) const
CallInstruction & new_call_instruction(const MultiFunction &fn)
const MultiFunction & construct_function(Args &&...args)
void add_parameter(ParamType::InterfaceType interface_type, Variable &variable)
Variable & new_variable(DataType data_type, std::string name="")
static ulong * next
#define T
std::unique_ptr< T, DestructValueAtAddress< T > > destruct_ptr