1/**************************************************************************/
2/* gdscript_byte_codegen.cpp */
3/**************************************************************************/
4/* This file is part of: */
5/* GODOT ENGINE */
6/* https://godotengine.org */
7/**************************************************************************/
8/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10/* */
11/* Permission is hereby granted, free of charge, to any person obtaining */
12/* a copy of this software and associated documentation files (the */
13/* "Software"), to deal in the Software without restriction, including */
14/* without limitation the rights to use, copy, modify, merge, publish, */
15/* distribute, sublicense, and/or sell copies of the Software, and to */
16/* permit persons to whom the Software is furnished to do so, subject to */
17/* the following conditions: */
18/* */
19/* The above copyright notice and this permission notice shall be */
20/* included in all copies or substantial portions of the Software. */
21/* */
22/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29/**************************************************************************/
30
31#include "gdscript_byte_codegen.h"
32
33#include "gdscript.h"
34
35#include "core/debugger/engine_debugger.h"
36
37uint32_t GDScriptByteCodeGenerator::add_parameter(const StringName &p_name, bool p_is_optional, const GDScriptDataType &p_type) {
38 function->_argument_count++;
39 function->argument_types.push_back(p_type);
40 if (p_is_optional) {
41 function->_default_arg_count++;
42 }
43
44 return add_local(p_name, p_type);
45}
46
47uint32_t GDScriptByteCodeGenerator::add_local(const StringName &p_name, const GDScriptDataType &p_type) {
48 int stack_pos = locals.size() + RESERVED_STACK;
49 locals.push_back(StackSlot(p_type.builtin_type));
50 add_stack_identifier(p_name, stack_pos);
51 return stack_pos;
52}
53
54uint32_t GDScriptByteCodeGenerator::add_local_constant(const StringName &p_name, const Variant &p_constant) {
55 int index = add_or_get_constant(p_constant);
56 local_constants[p_name] = index;
57 return index;
58}
59
60uint32_t GDScriptByteCodeGenerator::add_or_get_constant(const Variant &p_constant) {
61 return get_constant_pos(p_constant);
62}
63
64uint32_t GDScriptByteCodeGenerator::add_or_get_name(const StringName &p_name) {
65 return get_name_map_pos(p_name);
66}
67
68uint32_t GDScriptByteCodeGenerator::add_temporary(const GDScriptDataType &p_type) {
69 Variant::Type temp_type = Variant::NIL;
70 if (p_type.has_type && p_type.kind == GDScriptDataType::BUILTIN) {
71 switch (p_type.builtin_type) {
72 case Variant::NIL:
73 case Variant::BOOL:
74 case Variant::INT:
75 case Variant::FLOAT:
76 case Variant::STRING:
77 case Variant::VECTOR2:
78 case Variant::VECTOR2I:
79 case Variant::RECT2:
80 case Variant::RECT2I:
81 case Variant::VECTOR3:
82 case Variant::VECTOR3I:
83 case Variant::TRANSFORM2D:
84 case Variant::VECTOR4:
85 case Variant::VECTOR4I:
86 case Variant::PLANE:
87 case Variant::QUATERNION:
88 case Variant::AABB:
89 case Variant::BASIS:
90 case Variant::TRANSFORM3D:
91 case Variant::PROJECTION:
92 case Variant::COLOR:
93 case Variant::STRING_NAME:
94 case Variant::NODE_PATH:
95 case Variant::RID:
96 case Variant::CALLABLE:
97 case Variant::SIGNAL:
98 temp_type = p_type.builtin_type;
99 break;
100 case Variant::OBJECT:
101 case Variant::DICTIONARY:
102 case Variant::ARRAY:
103 case Variant::PACKED_BYTE_ARRAY:
104 case Variant::PACKED_INT32_ARRAY:
105 case Variant::PACKED_INT64_ARRAY:
106 case Variant::PACKED_FLOAT32_ARRAY:
107 case Variant::PACKED_FLOAT64_ARRAY:
108 case Variant::PACKED_STRING_ARRAY:
109 case Variant::PACKED_VECTOR2_ARRAY:
110 case Variant::PACKED_VECTOR3_ARRAY:
111 case Variant::PACKED_COLOR_ARRAY:
112 case Variant::VARIANT_MAX:
113 // Arrays, dictionaries, and objects are reference counted, so we don't use the pool for them.
114 temp_type = Variant::NIL;
115 break;
116 }
117 }
118
119 if (!temporaries_pool.has(temp_type)) {
120 temporaries_pool[temp_type] = List<int>();
121 }
122
123 List<int> &pool = temporaries_pool[temp_type];
124 if (pool.is_empty()) {
125 StackSlot new_temp(temp_type);
126 int idx = temporaries.size();
127 pool.push_back(idx);
128 temporaries.push_back(new_temp);
129 }
130 int slot = pool.front()->get();
131 pool.pop_front();
132 used_temporaries.push_back(slot);
133 return slot;
134}
135
136void GDScriptByteCodeGenerator::pop_temporary() {
137 ERR_FAIL_COND(used_temporaries.is_empty());
138 int slot_idx = used_temporaries.back()->get();
139 const StackSlot &slot = temporaries[slot_idx];
140 if (slot.type == Variant::NIL) {
141 // Avoid keeping in the stack long-lived references to objects,
142 // which may prevent RefCounted objects from being freed.
143 // However, the cleanup will be performed an the end of the
144 // statement, to allow object references to survive chaining.
145 temporaries_pending_clear.push_back(slot_idx);
146 }
147 temporaries_pool[slot.type].push_back(slot_idx);
148 used_temporaries.pop_back();
149}
150
151void GDScriptByteCodeGenerator::start_parameters() {
152 if (function->_default_arg_count > 0) {
153 append(GDScriptFunction::OPCODE_JUMP_TO_DEF_ARGUMENT);
154 function->default_arguments.push_back(opcodes.size());
155 }
156}
157
158void GDScriptByteCodeGenerator::end_parameters() {
159 function->default_arguments.reverse();
160}
161
162void GDScriptByteCodeGenerator::write_start(GDScript *p_script, const StringName &p_function_name, bool p_static, Variant p_rpc_config, const GDScriptDataType &p_return_type) {
163 function = memnew(GDScriptFunction);
164 debug_stack = EngineDebugger::is_active();
165
166 function->name = p_function_name;
167 function->_script = p_script;
168 function->source = p_script->get_script_path();
169
170#ifdef DEBUG_ENABLED
171 function->func_cname = (String(function->source) + " - " + String(p_function_name)).utf8();
172 function->_func_cname = function->func_cname.get_data();
173#endif
174
175 function->_static = p_static;
176 function->return_type = p_return_type;
177 function->rpc_config = p_rpc_config;
178 function->_argument_count = 0;
179}
180
181GDScriptFunction *GDScriptByteCodeGenerator::write_end() {
182#ifdef DEBUG_ENABLED
183 if (!used_temporaries.is_empty()) {
184 ERR_PRINT("Non-zero temporary variables at end of function: " + itos(used_temporaries.size()));
185 }
186#endif
187 append_opcode(GDScriptFunction::OPCODE_END);
188
189 for (int i = 0; i < temporaries.size(); i++) {
190 int stack_index = i + max_locals + RESERVED_STACK;
191 for (int j = 0; j < temporaries[i].bytecode_indices.size(); j++) {
192 opcodes.write[temporaries[i].bytecode_indices[j]] = stack_index | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
193 }
194 if (temporaries[i].type != Variant::NIL) {
195 function->temporary_slots[stack_index] = temporaries[i].type;
196 }
197 }
198
199 if (constant_map.size()) {
200 function->_constant_count = constant_map.size();
201 function->constants.resize(constant_map.size());
202 function->_constants_ptr = function->constants.ptrw();
203 for (const KeyValue<Variant, int> &K : constant_map) {
204 function->constants.write[K.value] = K.key;
205 }
206 } else {
207 function->_constants_ptr = nullptr;
208 function->_constant_count = 0;
209 }
210
211 if (name_map.size()) {
212 function->global_names.resize(name_map.size());
213 function->_global_names_ptr = &function->global_names[0];
214 for (const KeyValue<StringName, int> &E : name_map) {
215 function->global_names.write[E.value] = E.key;
216 }
217 function->_global_names_count = function->global_names.size();
218
219 } else {
220 function->_global_names_ptr = nullptr;
221 function->_global_names_count = 0;
222 }
223
224 if (opcodes.size()) {
225 function->code = opcodes;
226 function->_code_ptr = &function->code.write[0];
227 function->_code_size = opcodes.size();
228
229 } else {
230 function->_code_ptr = nullptr;
231 function->_code_size = 0;
232 }
233
234 if (function->default_arguments.size()) {
235 function->_default_arg_count = function->default_arguments.size() - 1;
236 function->_default_arg_ptr = &function->default_arguments[0];
237 } else {
238 function->_default_arg_count = 0;
239 function->_default_arg_ptr = nullptr;
240 }
241
242 if (operator_func_map.size()) {
243 function->operator_funcs.resize(operator_func_map.size());
244 function->_operator_funcs_count = function->operator_funcs.size();
245 function->_operator_funcs_ptr = function->operator_funcs.ptr();
246 for (const KeyValue<Variant::ValidatedOperatorEvaluator, int> &E : operator_func_map) {
247 function->operator_funcs.write[E.value] = E.key;
248 }
249 } else {
250 function->_operator_funcs_count = 0;
251 function->_operator_funcs_ptr = nullptr;
252 }
253
254 if (setters_map.size()) {
255 function->setters.resize(setters_map.size());
256 function->_setters_count = function->setters.size();
257 function->_setters_ptr = function->setters.ptr();
258 for (const KeyValue<Variant::ValidatedSetter, int> &E : setters_map) {
259 function->setters.write[E.value] = E.key;
260 }
261 } else {
262 function->_setters_count = 0;
263 function->_setters_ptr = nullptr;
264 }
265
266 if (getters_map.size()) {
267 function->getters.resize(getters_map.size());
268 function->_getters_count = function->getters.size();
269 function->_getters_ptr = function->getters.ptr();
270 for (const KeyValue<Variant::ValidatedGetter, int> &E : getters_map) {
271 function->getters.write[E.value] = E.key;
272 }
273 } else {
274 function->_getters_count = 0;
275 function->_getters_ptr = nullptr;
276 }
277
278 if (keyed_setters_map.size()) {
279 function->keyed_setters.resize(keyed_setters_map.size());
280 function->_keyed_setters_count = function->keyed_setters.size();
281 function->_keyed_setters_ptr = function->keyed_setters.ptr();
282 for (const KeyValue<Variant::ValidatedKeyedSetter, int> &E : keyed_setters_map) {
283 function->keyed_setters.write[E.value] = E.key;
284 }
285 } else {
286 function->_keyed_setters_count = 0;
287 function->_keyed_setters_ptr = nullptr;
288 }
289
290 if (keyed_getters_map.size()) {
291 function->keyed_getters.resize(keyed_getters_map.size());
292 function->_keyed_getters_count = function->keyed_getters.size();
293 function->_keyed_getters_ptr = function->keyed_getters.ptr();
294 for (const KeyValue<Variant::ValidatedKeyedGetter, int> &E : keyed_getters_map) {
295 function->keyed_getters.write[E.value] = E.key;
296 }
297 } else {
298 function->_keyed_getters_count = 0;
299 function->_keyed_getters_ptr = nullptr;
300 }
301
302 if (indexed_setters_map.size()) {
303 function->indexed_setters.resize(indexed_setters_map.size());
304 function->_indexed_setters_count = function->indexed_setters.size();
305 function->_indexed_setters_ptr = function->indexed_setters.ptr();
306 for (const KeyValue<Variant::ValidatedIndexedSetter, int> &E : indexed_setters_map) {
307 function->indexed_setters.write[E.value] = E.key;
308 }
309 } else {
310 function->_indexed_setters_count = 0;
311 function->_indexed_setters_ptr = nullptr;
312 }
313
314 if (indexed_getters_map.size()) {
315 function->indexed_getters.resize(indexed_getters_map.size());
316 function->_indexed_getters_count = function->indexed_getters.size();
317 function->_indexed_getters_ptr = function->indexed_getters.ptr();
318 for (const KeyValue<Variant::ValidatedIndexedGetter, int> &E : indexed_getters_map) {
319 function->indexed_getters.write[E.value] = E.key;
320 }
321 } else {
322 function->_indexed_getters_count = 0;
323 function->_indexed_getters_ptr = nullptr;
324 }
325
326 if (builtin_method_map.size()) {
327 function->builtin_methods.resize(builtin_method_map.size());
328 function->_builtin_methods_ptr = function->builtin_methods.ptr();
329 function->_builtin_methods_count = builtin_method_map.size();
330 for (const KeyValue<Variant::ValidatedBuiltInMethod, int> &E : builtin_method_map) {
331 function->builtin_methods.write[E.value] = E.key;
332 }
333 } else {
334 function->_builtin_methods_ptr = nullptr;
335 function->_builtin_methods_count = 0;
336 }
337
338 if (constructors_map.size()) {
339 function->constructors.resize(constructors_map.size());
340 function->_constructors_ptr = function->constructors.ptr();
341 function->_constructors_count = constructors_map.size();
342 for (const KeyValue<Variant::ValidatedConstructor, int> &E : constructors_map) {
343 function->constructors.write[E.value] = E.key;
344 }
345 } else {
346 function->_constructors_ptr = nullptr;
347 function->_constructors_count = 0;
348 }
349
350 if (utilities_map.size()) {
351 function->utilities.resize(utilities_map.size());
352 function->_utilities_ptr = function->utilities.ptr();
353 function->_utilities_count = utilities_map.size();
354 for (const KeyValue<Variant::ValidatedUtilityFunction, int> &E : utilities_map) {
355 function->utilities.write[E.value] = E.key;
356 }
357 } else {
358 function->_utilities_ptr = nullptr;
359 function->_utilities_count = 0;
360 }
361
362 if (gds_utilities_map.size()) {
363 function->gds_utilities.resize(gds_utilities_map.size());
364 function->_gds_utilities_ptr = function->gds_utilities.ptr();
365 function->_gds_utilities_count = gds_utilities_map.size();
366 for (const KeyValue<GDScriptUtilityFunctions::FunctionPtr, int> &E : gds_utilities_map) {
367 function->gds_utilities.write[E.value] = E.key;
368 }
369 } else {
370 function->_gds_utilities_ptr = nullptr;
371 function->_gds_utilities_count = 0;
372 }
373
374 if (method_bind_map.size()) {
375 function->methods.resize(method_bind_map.size());
376 function->_methods_ptr = function->methods.ptrw();
377 function->_methods_count = method_bind_map.size();
378 for (const KeyValue<MethodBind *, int> &E : method_bind_map) {
379 function->methods.write[E.value] = E.key;
380 }
381 } else {
382 function->_methods_ptr = nullptr;
383 function->_methods_count = 0;
384 }
385
386 if (lambdas_map.size()) {
387 function->lambdas.resize(lambdas_map.size());
388 function->_lambdas_ptr = function->lambdas.ptrw();
389 function->_lambdas_count = lambdas_map.size();
390 for (const KeyValue<GDScriptFunction *, int> &E : lambdas_map) {
391 function->lambdas.write[E.value] = E.key;
392 }
393 } else {
394 function->_lambdas_ptr = nullptr;
395 function->_lambdas_count = 0;
396 }
397
398 if (debug_stack) {
399 function->stack_debug = stack_debug;
400 }
401 function->_stack_size = RESERVED_STACK + max_locals + temporaries.size();
402 function->_instruction_args_size = instr_args_max;
403 function->_ptrcall_args_size = ptrcall_max;
404
405#ifdef DEBUG_ENABLED
406 function->operator_names = operator_names;
407 function->setter_names = setter_names;
408 function->getter_names = getter_names;
409 function->builtin_methods_names = builtin_methods_names;
410 function->constructors_names = constructors_names;
411 function->utilities_names = utilities_names;
412 function->gds_utilities_names = gds_utilities_names;
413#endif
414
415 ended = true;
416 return function;
417}
418
419#ifdef DEBUG_ENABLED
420void GDScriptByteCodeGenerator::set_signature(const String &p_signature) {
421 function->profile.signature = p_signature;
422}
423#endif
424
425void GDScriptByteCodeGenerator::set_initial_line(int p_line) {
426 function->_initial_line = p_line;
427}
428
429#define HAS_BUILTIN_TYPE(m_var) \
430 (m_var.type.has_type && m_var.type.kind == GDScriptDataType::BUILTIN)
431
432#define IS_BUILTIN_TYPE(m_var, m_type) \
433 (m_var.type.has_type && m_var.type.kind == GDScriptDataType::BUILTIN && m_var.type.builtin_type == m_type)
434
435void GDScriptByteCodeGenerator::write_type_adjust(const Address &p_target, Variant::Type p_new_type) {
436 switch (p_new_type) {
437 case Variant::BOOL:
438 append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_BOOL);
439 break;
440 case Variant::INT:
441 append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_INT);
442 break;
443 case Variant::FLOAT:
444 append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_FLOAT);
445 break;
446 case Variant::STRING:
447 append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_STRING);
448 break;
449 case Variant::VECTOR2:
450 append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_VECTOR2);
451 break;
452 case Variant::VECTOR2I:
453 append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_VECTOR2I);
454 break;
455 case Variant::RECT2:
456 append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_RECT2);
457 break;
458 case Variant::RECT2I:
459 append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_RECT2I);
460 break;
461 case Variant::VECTOR3:
462 append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_VECTOR3);
463 break;
464 case Variant::VECTOR3I:
465 append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_VECTOR3I);
466 break;
467 case Variant::TRANSFORM2D:
468 append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_TRANSFORM2D);
469 break;
470 case Variant::VECTOR4:
471 append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_VECTOR3);
472 break;
473 case Variant::VECTOR4I:
474 append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_VECTOR3I);
475 break;
476 case Variant::PLANE:
477 append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_PLANE);
478 break;
479 case Variant::QUATERNION:
480 append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_QUATERNION);
481 break;
482 case Variant::AABB:
483 append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_AABB);
484 break;
485 case Variant::BASIS:
486 append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_BASIS);
487 break;
488 case Variant::TRANSFORM3D:
489 append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_TRANSFORM3D);
490 break;
491 case Variant::PROJECTION:
492 append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_PROJECTION);
493 break;
494 case Variant::COLOR:
495 append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_COLOR);
496 break;
497 case Variant::STRING_NAME:
498 append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_STRING_NAME);
499 break;
500 case Variant::NODE_PATH:
501 append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_NODE_PATH);
502 break;
503 case Variant::RID:
504 append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_RID);
505 break;
506 case Variant::OBJECT:
507 append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_OBJECT);
508 break;
509 case Variant::CALLABLE:
510 append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_CALLABLE);
511 break;
512 case Variant::SIGNAL:
513 append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_SIGNAL);
514 break;
515 case Variant::DICTIONARY:
516 append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_DICTIONARY);
517 break;
518 case Variant::ARRAY:
519 append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_ARRAY);
520 break;
521 case Variant::PACKED_BYTE_ARRAY:
522 append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_PACKED_BYTE_ARRAY);
523 break;
524 case Variant::PACKED_INT32_ARRAY:
525 append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_PACKED_INT32_ARRAY);
526 break;
527 case Variant::PACKED_INT64_ARRAY:
528 append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_PACKED_INT64_ARRAY);
529 break;
530 case Variant::PACKED_FLOAT32_ARRAY:
531 append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_PACKED_FLOAT32_ARRAY);
532 break;
533 case Variant::PACKED_FLOAT64_ARRAY:
534 append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_PACKED_FLOAT64_ARRAY);
535 break;
536 case Variant::PACKED_STRING_ARRAY:
537 append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_PACKED_STRING_ARRAY);
538 break;
539 case Variant::PACKED_VECTOR2_ARRAY:
540 append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_PACKED_VECTOR2_ARRAY);
541 break;
542 case Variant::PACKED_VECTOR3_ARRAY:
543 append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_PACKED_VECTOR3_ARRAY);
544 break;
545 case Variant::PACKED_COLOR_ARRAY:
546 append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_PACKED_COLOR_ARRAY);
547 break;
548 case Variant::NIL:
549 case Variant::VARIANT_MAX:
550 return;
551 }
552 append(p_target);
553}
554
555void GDScriptByteCodeGenerator::write_unary_operator(const Address &p_target, Variant::Operator p_operator, const Address &p_left_operand) {
556 if (HAS_BUILTIN_TYPE(p_left_operand)) {
557 // Gather specific operator.
558 Variant::ValidatedOperatorEvaluator op_func = Variant::get_validated_operator_evaluator(p_operator, p_left_operand.type.builtin_type, Variant::NIL);
559
560 append_opcode(GDScriptFunction::OPCODE_OPERATOR_VALIDATED);
561 append(p_left_operand);
562 append(Address());
563 append(p_target);
564 append(op_func);
565#ifdef DEBUG_ENABLED
566 add_debug_name(operator_names, get_operation_pos(op_func), Variant::get_operator_name(p_operator));
567#endif
568 return;
569 }
570
571 // No specific types, perform variant evaluation.
572 append_opcode(GDScriptFunction::OPCODE_OPERATOR);
573 append(p_left_operand);
574 append(Address());
575 append(p_target);
576 append(p_operator);
577 append(0); // Signature storage.
578 append(0); // Return type storage.
579 constexpr int _pointer_size = sizeof(Variant::ValidatedOperatorEvaluator) / sizeof(*(opcodes.ptr()));
580 for (int i = 0; i < _pointer_size; i++) {
581 append(0); // Space for function pointer.
582 }
583}
584
585void GDScriptByteCodeGenerator::write_binary_operator(const Address &p_target, Variant::Operator p_operator, const Address &p_left_operand, const Address &p_right_operand) {
586 // Avoid validated evaluator for modulo and division when operands are int, since there's no check for division by zero.
587 if (HAS_BUILTIN_TYPE(p_left_operand) && HAS_BUILTIN_TYPE(p_right_operand) && ((p_operator != Variant::OP_DIVIDE && p_operator != Variant::OP_MODULE) || p_left_operand.type.builtin_type != Variant::INT || p_right_operand.type.builtin_type != Variant::INT)) {
588 if (p_target.mode == Address::TEMPORARY) {
589 Variant::Type result_type = Variant::get_operator_return_type(p_operator, p_left_operand.type.builtin_type, p_right_operand.type.builtin_type);
590 Variant::Type temp_type = temporaries[p_target.address].type;
591 if (result_type != temp_type) {
592 write_type_adjust(p_target, result_type);
593 }
594 }
595
596 // Gather specific operator.
597 Variant::ValidatedOperatorEvaluator op_func = Variant::get_validated_operator_evaluator(p_operator, p_left_operand.type.builtin_type, p_right_operand.type.builtin_type);
598
599 append_opcode(GDScriptFunction::OPCODE_OPERATOR_VALIDATED);
600 append(p_left_operand);
601 append(p_right_operand);
602 append(p_target);
603 append(op_func);
604#ifdef DEBUG_ENABLED
605 add_debug_name(operator_names, get_operation_pos(op_func), Variant::get_operator_name(p_operator));
606#endif
607 return;
608 }
609
610 // No specific types, perform variant evaluation.
611 append_opcode(GDScriptFunction::OPCODE_OPERATOR);
612 append(p_left_operand);
613 append(p_right_operand);
614 append(p_target);
615 append(p_operator);
616 append(0); // Signature storage.
617 append(0); // Return type storage.
618 constexpr int _pointer_size = sizeof(Variant::ValidatedOperatorEvaluator) / sizeof(*(opcodes.ptr()));
619 for (int i = 0; i < _pointer_size; i++) {
620 append(0); // Space for function pointer.
621 }
622}
623
624void GDScriptByteCodeGenerator::write_type_test(const Address &p_target, const Address &p_source, const GDScriptDataType &p_type) {
625 switch (p_type.kind) {
626 case GDScriptDataType::BUILTIN: {
627 if (p_type.builtin_type == Variant::ARRAY && p_type.has_container_element_type()) {
628 const GDScriptDataType &element_type = p_type.get_container_element_type();
629 append_opcode(GDScriptFunction::OPCODE_TYPE_TEST_ARRAY);
630 append(p_target);
631 append(p_source);
632 append(get_constant_pos(element_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS));
633 append(element_type.builtin_type);
634 append(element_type.native_type);
635 } else {
636 append_opcode(GDScriptFunction::OPCODE_TYPE_TEST_BUILTIN);
637 append(p_target);
638 append(p_source);
639 append(p_type.builtin_type);
640 }
641 } break;
642 case GDScriptDataType::NATIVE: {
643 append_opcode(GDScriptFunction::OPCODE_TYPE_TEST_NATIVE);
644 append(p_target);
645 append(p_source);
646 append(p_type.native_type);
647 } break;
648 case GDScriptDataType::SCRIPT:
649 case GDScriptDataType::GDSCRIPT: {
650 const Variant &script = p_type.script_type;
651 append_opcode(GDScriptFunction::OPCODE_TYPE_TEST_SCRIPT);
652 append(p_target);
653 append(p_source);
654 append(get_constant_pos(script) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS));
655 } break;
656 default: {
657 ERR_PRINT("Compiler bug: unresolved type in type test.");
658 append_opcode(GDScriptFunction::OPCODE_ASSIGN_FALSE);
659 append(p_target);
660 }
661 }
662}
663
664void GDScriptByteCodeGenerator::write_and_left_operand(const Address &p_left_operand) {
665 append_opcode(GDScriptFunction::OPCODE_JUMP_IF_NOT);
666 append(p_left_operand);
667 logic_op_jump_pos1.push_back(opcodes.size());
668 append(0); // Jump target, will be patched.
669}
670
671void GDScriptByteCodeGenerator::write_and_right_operand(const Address &p_right_operand) {
672 append_opcode(GDScriptFunction::OPCODE_JUMP_IF_NOT);
673 append(p_right_operand);
674 logic_op_jump_pos2.push_back(opcodes.size());
675 append(0); // Jump target, will be patched.
676}
677
678void GDScriptByteCodeGenerator::write_end_and(const Address &p_target) {
679 // If here means both operands are true.
680 append_opcode(GDScriptFunction::OPCODE_ASSIGN_TRUE);
681 append(p_target);
682 // Jump away from the fail condition.
683 append_opcode(GDScriptFunction::OPCODE_JUMP);
684 append(opcodes.size() + 3);
685 // Here it means one of operands is false.
686 patch_jump(logic_op_jump_pos1.back()->get());
687 patch_jump(logic_op_jump_pos2.back()->get());
688 logic_op_jump_pos1.pop_back();
689 logic_op_jump_pos2.pop_back();
690 append_opcode(GDScriptFunction::OPCODE_ASSIGN_FALSE);
691 append(p_target);
692}
693
694void GDScriptByteCodeGenerator::write_or_left_operand(const Address &p_left_operand) {
695 append_opcode(GDScriptFunction::OPCODE_JUMP_IF);
696 append(p_left_operand);
697 logic_op_jump_pos1.push_back(opcodes.size());
698 append(0); // Jump target, will be patched.
699}
700
701void GDScriptByteCodeGenerator::write_or_right_operand(const Address &p_right_operand) {
702 append_opcode(GDScriptFunction::OPCODE_JUMP_IF);
703 append(p_right_operand);
704 logic_op_jump_pos2.push_back(opcodes.size());
705 append(0); // Jump target, will be patched.
706}
707
708void GDScriptByteCodeGenerator::write_end_or(const Address &p_target) {
709 // If here means both operands are false.
710 append_opcode(GDScriptFunction::OPCODE_ASSIGN_FALSE);
711 append(p_target);
712 // Jump away from the success condition.
713 append_opcode(GDScriptFunction::OPCODE_JUMP);
714 append(opcodes.size() + 3);
715 // Here it means one of operands is true.
716 patch_jump(logic_op_jump_pos1.back()->get());
717 patch_jump(logic_op_jump_pos2.back()->get());
718 logic_op_jump_pos1.pop_back();
719 logic_op_jump_pos2.pop_back();
720 append_opcode(GDScriptFunction::OPCODE_ASSIGN_TRUE);
721 append(p_target);
722}
723
724void GDScriptByteCodeGenerator::write_start_ternary(const Address &p_target) {
725 ternary_result.push_back(p_target);
726}
727
728void GDScriptByteCodeGenerator::write_ternary_condition(const Address &p_condition) {
729 append_opcode(GDScriptFunction::OPCODE_JUMP_IF_NOT);
730 append(p_condition);
731 ternary_jump_fail_pos.push_back(opcodes.size());
732 append(0); // Jump target, will be patched.
733}
734
735void GDScriptByteCodeGenerator::write_ternary_true_expr(const Address &p_expr) {
736 append_opcode(GDScriptFunction::OPCODE_ASSIGN);
737 append(ternary_result.back()->get());
738 append(p_expr);
739 // Jump away from the false path.
740 append_opcode(GDScriptFunction::OPCODE_JUMP);
741 ternary_jump_skip_pos.push_back(opcodes.size());
742 append(0);
743 // Fail must jump here.
744 patch_jump(ternary_jump_fail_pos.back()->get());
745 ternary_jump_fail_pos.pop_back();
746}
747
748void GDScriptByteCodeGenerator::write_ternary_false_expr(const Address &p_expr) {
749 append_opcode(GDScriptFunction::OPCODE_ASSIGN);
750 append(ternary_result.back()->get());
751 append(p_expr);
752}
753
754void GDScriptByteCodeGenerator::write_end_ternary() {
755 patch_jump(ternary_jump_skip_pos.back()->get());
756 ternary_jump_skip_pos.pop_back();
757 ternary_result.pop_back();
758}
759
760void GDScriptByteCodeGenerator::write_set(const Address &p_target, const Address &p_index, const Address &p_source) {
761 if (HAS_BUILTIN_TYPE(p_target)) {
762 if (IS_BUILTIN_TYPE(p_index, Variant::INT) && Variant::get_member_validated_indexed_setter(p_target.type.builtin_type) &&
763 IS_BUILTIN_TYPE(p_source, Variant::get_indexed_element_type(p_target.type.builtin_type))) {
764 // Use indexed setter instead.
765 Variant::ValidatedIndexedSetter setter = Variant::get_member_validated_indexed_setter(p_target.type.builtin_type);
766 append_opcode(GDScriptFunction::OPCODE_SET_INDEXED_VALIDATED);
767 append(p_target);
768 append(p_index);
769 append(p_source);
770 append(setter);
771 return;
772 } else if (Variant::get_member_validated_keyed_setter(p_target.type.builtin_type)) {
773 Variant::ValidatedKeyedSetter setter = Variant::get_member_validated_keyed_setter(p_target.type.builtin_type);
774 append_opcode(GDScriptFunction::OPCODE_SET_KEYED_VALIDATED);
775 append(p_target);
776 append(p_index);
777 append(p_source);
778 append(setter);
779 return;
780 }
781 }
782
783 append_opcode(GDScriptFunction::OPCODE_SET_KEYED);
784 append(p_target);
785 append(p_index);
786 append(p_source);
787}
788
789void GDScriptByteCodeGenerator::write_get(const Address &p_target, const Address &p_index, const Address &p_source) {
790 if (HAS_BUILTIN_TYPE(p_source)) {
791 if (IS_BUILTIN_TYPE(p_index, Variant::INT) && Variant::get_member_validated_indexed_getter(p_source.type.builtin_type)) {
792 // Use indexed getter instead.
793 Variant::ValidatedIndexedGetter getter = Variant::get_member_validated_indexed_getter(p_source.type.builtin_type);
794 append_opcode(GDScriptFunction::OPCODE_GET_INDEXED_VALIDATED);
795 append(p_source);
796 append(p_index);
797 append(p_target);
798 append(getter);
799 return;
800 } else if (Variant::get_member_validated_keyed_getter(p_source.type.builtin_type)) {
801 Variant::ValidatedKeyedGetter getter = Variant::get_member_validated_keyed_getter(p_source.type.builtin_type);
802 append_opcode(GDScriptFunction::OPCODE_GET_KEYED_VALIDATED);
803 append(p_source);
804 append(p_index);
805 append(p_target);
806 append(getter);
807 return;
808 }
809 }
810 append_opcode(GDScriptFunction::OPCODE_GET_KEYED);
811 append(p_source);
812 append(p_index);
813 append(p_target);
814}
815
816void GDScriptByteCodeGenerator::write_set_named(const Address &p_target, const StringName &p_name, const Address &p_source) {
817 if (HAS_BUILTIN_TYPE(p_target) && Variant::get_member_validated_setter(p_target.type.builtin_type, p_name) &&
818 IS_BUILTIN_TYPE(p_source, Variant::get_member_type(p_target.type.builtin_type, p_name))) {
819 Variant::ValidatedSetter setter = Variant::get_member_validated_setter(p_target.type.builtin_type, p_name);
820 append_opcode(GDScriptFunction::OPCODE_SET_NAMED_VALIDATED);
821 append(p_target);
822 append(p_source);
823 append(setter);
824#ifdef DEBUG_ENABLED
825 add_debug_name(setter_names, get_setter_pos(setter), p_name);
826#endif
827 return;
828 }
829 append_opcode(GDScriptFunction::OPCODE_SET_NAMED);
830 append(p_target);
831 append(p_source);
832 append(p_name);
833}
834
835void GDScriptByteCodeGenerator::write_get_named(const Address &p_target, const StringName &p_name, const Address &p_source) {
836 if (HAS_BUILTIN_TYPE(p_source) && Variant::get_member_validated_getter(p_source.type.builtin_type, p_name)) {
837 Variant::ValidatedGetter getter = Variant::get_member_validated_getter(p_source.type.builtin_type, p_name);
838 append_opcode(GDScriptFunction::OPCODE_GET_NAMED_VALIDATED);
839 append(p_source);
840 append(p_target);
841 append(getter);
842#ifdef DEBUG_ENABLED
843 add_debug_name(getter_names, get_getter_pos(getter), p_name);
844#endif
845 return;
846 }
847 append_opcode(GDScriptFunction::OPCODE_GET_NAMED);
848 append(p_source);
849 append(p_target);
850 append(p_name);
851}
852
853void GDScriptByteCodeGenerator::write_set_member(const Address &p_value, const StringName &p_name) {
854 append_opcode(GDScriptFunction::OPCODE_SET_MEMBER);
855 append(p_value);
856 append(p_name);
857}
858
859void GDScriptByteCodeGenerator::write_get_member(const Address &p_target, const StringName &p_name) {
860 append_opcode(GDScriptFunction::OPCODE_GET_MEMBER);
861 append(p_target);
862 append(p_name);
863}
864
865void GDScriptByteCodeGenerator::write_set_static_variable(const Address &p_value, const Address &p_class, int p_index) {
866 append_opcode(GDScriptFunction::OPCODE_SET_STATIC_VARIABLE);
867 append(p_value);
868 append(p_class);
869 append(p_index);
870}
871
872void GDScriptByteCodeGenerator::write_get_static_variable(const Address &p_target, const Address &p_class, int p_index) {
873 append_opcode(GDScriptFunction::OPCODE_GET_STATIC_VARIABLE);
874 append(p_target);
875 append(p_class);
876 append(p_index);
877}
878
879void GDScriptByteCodeGenerator::write_assign_with_conversion(const Address &p_target, const Address &p_source) {
880 switch (p_target.type.kind) {
881 case GDScriptDataType::BUILTIN: {
882 if (p_target.type.builtin_type == Variant::ARRAY && p_target.type.has_container_element_type()) {
883 const GDScriptDataType &element_type = p_target.type.get_container_element_type();
884 append_opcode(GDScriptFunction::OPCODE_ASSIGN_TYPED_ARRAY);
885 append(p_target);
886 append(p_source);
887 append(get_constant_pos(element_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS));
888 append(element_type.builtin_type);
889 append(element_type.native_type);
890 } else {
891 append_opcode(GDScriptFunction::OPCODE_ASSIGN_TYPED_BUILTIN);
892 append(p_target);
893 append(p_source);
894 append(p_target.type.builtin_type);
895 }
896 } break;
897 case GDScriptDataType::NATIVE: {
898 int class_idx = GDScriptLanguage::get_singleton()->get_global_map()[p_target.type.native_type];
899 Variant nc = GDScriptLanguage::get_singleton()->get_global_array()[class_idx];
900 class_idx = get_constant_pos(nc) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
901 append_opcode(GDScriptFunction::OPCODE_ASSIGN_TYPED_NATIVE);
902 append(p_target);
903 append(p_source);
904 append(class_idx);
905 } break;
906 case GDScriptDataType::SCRIPT:
907 case GDScriptDataType::GDSCRIPT: {
908 Variant script = p_target.type.script_type;
909 int idx = get_constant_pos(script) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
910
911 append_opcode(GDScriptFunction::OPCODE_ASSIGN_TYPED_SCRIPT);
912 append(p_target);
913 append(p_source);
914 append(idx);
915 } break;
916 default: {
917 ERR_PRINT("Compiler bug: unresolved assign.");
918
919 // Shouldn't get here, but fail-safe to a regular assignment
920 append_opcode(GDScriptFunction::OPCODE_ASSIGN);
921 append(p_target);
922 append(p_source);
923 }
924 }
925}
926
927void GDScriptByteCodeGenerator::write_assign(const Address &p_target, const Address &p_source) {
928 if (p_target.type.kind == GDScriptDataType::BUILTIN && p_target.type.builtin_type == Variant::ARRAY && p_target.type.has_container_element_type()) {
929 const GDScriptDataType &element_type = p_target.type.get_container_element_type();
930 append_opcode(GDScriptFunction::OPCODE_ASSIGN_TYPED_ARRAY);
931 append(p_target);
932 append(p_source);
933 append(get_constant_pos(element_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS));
934 append(element_type.builtin_type);
935 append(element_type.native_type);
936 } else if (p_target.type.kind == GDScriptDataType::BUILTIN && p_source.type.kind == GDScriptDataType::BUILTIN && p_target.type.builtin_type != p_source.type.builtin_type) {
937 // Need conversion.
938 append_opcode(GDScriptFunction::OPCODE_ASSIGN_TYPED_BUILTIN);
939 append(p_target);
940 append(p_source);
941 append(p_target.type.builtin_type);
942 } else {
943 append_opcode(GDScriptFunction::OPCODE_ASSIGN);
944 append(p_target);
945 append(p_source);
946 }
947}
948
949void GDScriptByteCodeGenerator::write_assign_true(const Address &p_target) {
950 append_opcode(GDScriptFunction::OPCODE_ASSIGN_TRUE);
951 append(p_target);
952}
953
954void GDScriptByteCodeGenerator::write_assign_false(const Address &p_target) {
955 append_opcode(GDScriptFunction::OPCODE_ASSIGN_FALSE);
956 append(p_target);
957}
958
959void GDScriptByteCodeGenerator::write_assign_default_parameter(const Address &p_dst, const Address &p_src, bool p_use_conversion) {
960 if (p_use_conversion) {
961 write_assign_with_conversion(p_dst, p_src);
962 } else {
963 write_assign(p_dst, p_src);
964 }
965 function->default_arguments.push_back(opcodes.size());
966}
967
968void GDScriptByteCodeGenerator::write_store_global(const Address &p_dst, int p_global_index) {
969 append_opcode(GDScriptFunction::OPCODE_STORE_GLOBAL);
970 append(p_dst);
971 append(p_global_index);
972}
973
974void GDScriptByteCodeGenerator::write_store_named_global(const Address &p_dst, const StringName &p_global) {
975 append_opcode(GDScriptFunction::OPCODE_STORE_NAMED_GLOBAL);
976 append(p_dst);
977 append(p_global);
978}
979
980void GDScriptByteCodeGenerator::write_cast(const Address &p_target, const Address &p_source, const GDScriptDataType &p_type) {
981 int index = 0;
982
983 switch (p_type.kind) {
984 case GDScriptDataType::BUILTIN: {
985 append_opcode(GDScriptFunction::OPCODE_CAST_TO_BUILTIN);
986 index = p_type.builtin_type;
987 } break;
988 case GDScriptDataType::NATIVE: {
989 int class_idx = GDScriptLanguage::get_singleton()->get_global_map()[p_type.native_type];
990 Variant nc = GDScriptLanguage::get_singleton()->get_global_array()[class_idx];
991 append_opcode(GDScriptFunction::OPCODE_CAST_TO_NATIVE);
992 index = get_constant_pos(nc) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
993 } break;
994 case GDScriptDataType::SCRIPT:
995 case GDScriptDataType::GDSCRIPT: {
996 Variant script = p_type.script_type;
997 int idx = get_constant_pos(script) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
998 append_opcode(GDScriptFunction::OPCODE_CAST_TO_SCRIPT);
999 index = idx;
1000 } break;
1001 default: {
1002 return;
1003 }
1004 }
1005
1006 append(p_source);
1007 append(p_target);
1008 append(index);
1009}
1010
1011GDScriptByteCodeGenerator::CallTarget GDScriptByteCodeGenerator::get_call_target(const GDScriptCodeGenerator::Address &p_target, Variant::Type p_type) {
1012 if (p_target.mode == Address::NIL) {
1013 GDScriptDataType type;
1014 if (p_type != Variant::NIL) {
1015 type.has_type = true;
1016 type.kind = GDScriptDataType::BUILTIN;
1017 type.builtin_type = p_type;
1018 }
1019 uint32_t addr = add_temporary(type);
1020 return CallTarget(Address(Address::TEMPORARY, addr, type), true, this);
1021 } else {
1022 return CallTarget(p_target, false, this);
1023 }
1024}
1025
1026void GDScriptByteCodeGenerator::write_call(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) {
1027 append_opcode_and_argcount(p_target.mode == Address::NIL ? GDScriptFunction::OPCODE_CALL : GDScriptFunction::OPCODE_CALL_RETURN, 2 + p_arguments.size());
1028 for (int i = 0; i < p_arguments.size(); i++) {
1029 append(p_arguments[i]);
1030 }
1031 append(p_base);
1032 CallTarget ct = get_call_target(p_target);
1033 append(ct.target);
1034 append(p_arguments.size());
1035 append(p_function_name);
1036 ct.cleanup();
1037}
1038
1039void GDScriptByteCodeGenerator::write_super_call(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) {
1040 append_opcode_and_argcount(GDScriptFunction::OPCODE_CALL_SELF_BASE, 1 + p_arguments.size());
1041 for (int i = 0; i < p_arguments.size(); i++) {
1042 append(p_arguments[i]);
1043 }
1044 CallTarget ct = get_call_target(p_target);
1045 append(ct.target);
1046 append(p_arguments.size());
1047 append(p_function_name);
1048 ct.cleanup();
1049}
1050
1051void GDScriptByteCodeGenerator::write_call_async(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) {
1052 append_opcode_and_argcount(GDScriptFunction::OPCODE_CALL_ASYNC, 2 + p_arguments.size());
1053 for (int i = 0; i < p_arguments.size(); i++) {
1054 append(p_arguments[i]);
1055 }
1056 append(p_base);
1057 CallTarget ct = get_call_target(p_target);
1058 append(ct.target);
1059 append(p_arguments.size());
1060 append(p_function_name);
1061 ct.cleanup();
1062}
1063
1064void GDScriptByteCodeGenerator::write_call_gdscript_utility(const Address &p_target, const StringName &p_function, const Vector<Address> &p_arguments) {
1065 append_opcode_and_argcount(GDScriptFunction::OPCODE_CALL_GDSCRIPT_UTILITY, 1 + p_arguments.size());
1066 GDScriptUtilityFunctions::FunctionPtr gds_function = GDScriptUtilityFunctions::get_function(p_function);
1067 for (int i = 0; i < p_arguments.size(); i++) {
1068 append(p_arguments[i]);
1069 }
1070 CallTarget ct = get_call_target(p_target);
1071 append(ct.target);
1072 append(p_arguments.size());
1073 append(gds_function);
1074 ct.cleanup();
1075#ifdef DEBUG_ENABLED
1076 add_debug_name(gds_utilities_names, get_gds_utility_pos(gds_function), p_function);
1077#endif
1078}
1079
1080void GDScriptByteCodeGenerator::write_call_utility(const Address &p_target, const StringName &p_function, const Vector<Address> &p_arguments) {
1081 bool is_validated = true;
1082 if (Variant::is_utility_function_vararg(p_function)) {
1083 is_validated = false; // Vararg needs runtime checks, can't use validated call.
1084 } else if (p_arguments.size() == Variant::get_utility_function_argument_count(p_function)) {
1085 bool all_types_exact = true;
1086 for (int i = 0; i < p_arguments.size(); i++) {
1087 if (!IS_BUILTIN_TYPE(p_arguments[i], Variant::get_utility_function_argument_type(p_function, i))) {
1088 all_types_exact = false;
1089 break;
1090 }
1091 }
1092
1093 is_validated = all_types_exact;
1094 }
1095
1096 if (is_validated) {
1097 Variant::Type result_type = Variant::has_utility_function_return_value(p_function) ? Variant::get_utility_function_return_type(p_function) : Variant::NIL;
1098 CallTarget ct = get_call_target(p_target, result_type);
1099 Variant::Type temp_type = temporaries[ct.target.address].type;
1100 if (result_type != temp_type) {
1101 write_type_adjust(ct.target, result_type);
1102 }
1103 append_opcode_and_argcount(GDScriptFunction::OPCODE_CALL_UTILITY_VALIDATED, 1 + p_arguments.size());
1104 for (int i = 0; i < p_arguments.size(); i++) {
1105 append(p_arguments[i]);
1106 }
1107 append(ct.target);
1108 append(p_arguments.size());
1109 append(Variant::get_validated_utility_function(p_function));
1110 ct.cleanup();
1111#ifdef DEBUG_ENABLED
1112 add_debug_name(utilities_names, get_utility_pos(Variant::get_validated_utility_function(p_function)), p_function);
1113#endif
1114 } else {
1115 append_opcode_and_argcount(GDScriptFunction::OPCODE_CALL_UTILITY, 1 + p_arguments.size());
1116 for (int i = 0; i < p_arguments.size(); i++) {
1117 append(p_arguments[i]);
1118 }
1119 CallTarget ct = get_call_target(p_target);
1120 append(ct.target);
1121 append(p_arguments.size());
1122 append(p_function);
1123 ct.cleanup();
1124 }
1125}
1126
1127void GDScriptByteCodeGenerator::write_call_builtin_type(const Address &p_target, const Address &p_base, Variant::Type p_type, const StringName &p_method, bool p_is_static, const Vector<Address> &p_arguments) {
1128 bool is_validated = false;
1129
1130 // Check if all types are correct.
1131 if (Variant::is_builtin_method_vararg(p_type, p_method)) {
1132 is_validated = false; // Vararg needs runtime checks, can't use validated call.
1133 } else if (p_arguments.size() == Variant::get_builtin_method_argument_count(p_type, p_method)) {
1134 bool all_types_exact = true;
1135 for (int i = 0; i < p_arguments.size(); i++) {
1136 if (!IS_BUILTIN_TYPE(p_arguments[i], Variant::get_builtin_method_argument_type(p_type, p_method, i))) {
1137 all_types_exact = false;
1138 break;
1139 }
1140 }
1141
1142 is_validated = all_types_exact;
1143 }
1144
1145 if (!is_validated) {
1146 // Perform regular call.
1147 if (p_is_static) {
1148 append_opcode_and_argcount(GDScriptFunction::OPCODE_CALL_BUILTIN_STATIC, p_arguments.size() + 1);
1149 for (int i = 0; i < p_arguments.size(); i++) {
1150 append(p_arguments[i]);
1151 }
1152 CallTarget ct = get_call_target(p_target);
1153 append(ct.target);
1154 append(p_type);
1155 append(p_method);
1156 append(p_arguments.size());
1157 ct.cleanup();
1158 } else {
1159 write_call(p_target, p_base, p_method, p_arguments);
1160 }
1161 return;
1162 }
1163
1164 Variant::Type result_type = Variant::get_builtin_method_return_type(p_type, p_method);
1165 CallTarget ct = get_call_target(p_target, result_type);
1166 Variant::Type temp_type = temporaries[ct.target.address].type;
1167 if (result_type != temp_type) {
1168 write_type_adjust(ct.target, result_type);
1169 }
1170
1171 append_opcode_and_argcount(GDScriptFunction::OPCODE_CALL_BUILTIN_TYPE_VALIDATED, 2 + p_arguments.size());
1172
1173 for (int i = 0; i < p_arguments.size(); i++) {
1174 append(p_arguments[i]);
1175 }
1176 append(p_base);
1177 append(ct.target);
1178 append(p_arguments.size());
1179 append(Variant::get_validated_builtin_method(p_type, p_method));
1180 ct.cleanup();
1181
1182#ifdef DEBUG_ENABLED
1183 add_debug_name(builtin_methods_names, get_builtin_method_pos(Variant::get_validated_builtin_method(p_type, p_method)), p_method);
1184#endif
1185}
1186
1187void GDScriptByteCodeGenerator::write_call_builtin_type(const Address &p_target, const Address &p_base, Variant::Type p_type, const StringName &p_method, const Vector<Address> &p_arguments) {
1188 write_call_builtin_type(p_target, p_base, p_type, p_method, false, p_arguments);
1189}
1190
1191void GDScriptByteCodeGenerator::write_call_builtin_type_static(const Address &p_target, Variant::Type p_type, const StringName &p_method, const Vector<Address> &p_arguments) {
1192 write_call_builtin_type(p_target, Address(), p_type, p_method, true, p_arguments);
1193}
1194
1195void GDScriptByteCodeGenerator::write_call_native_static(const Address &p_target, const StringName &p_class, const StringName &p_method, const Vector<Address> &p_arguments) {
1196 bool is_validated = false;
1197
1198 MethodBind *method = ClassDB::get_method(p_class, p_method);
1199
1200 if (!is_validated) {
1201 // Perform regular call.
1202 append_opcode_and_argcount(GDScriptFunction::OPCODE_CALL_NATIVE_STATIC, p_arguments.size() + 1);
1203 for (int i = 0; i < p_arguments.size(); i++) {
1204 append(p_arguments[i]);
1205 }
1206 CallTarget ct = get_call_target(p_target);
1207 append(ct.target);
1208 append(method);
1209 append(p_arguments.size());
1210 ct.cleanup();
1211 return;
1212 }
1213}
1214
1215void GDScriptByteCodeGenerator::write_call_method_bind(const Address &p_target, const Address &p_base, MethodBind *p_method, const Vector<Address> &p_arguments) {
1216 append_opcode_and_argcount(p_target.mode == Address::NIL ? GDScriptFunction::OPCODE_CALL_METHOD_BIND : GDScriptFunction::OPCODE_CALL_METHOD_BIND_RET, 2 + p_arguments.size());
1217 for (int i = 0; i < p_arguments.size(); i++) {
1218 append(p_arguments[i]);
1219 }
1220 CallTarget ct = get_call_target(p_target);
1221 append(p_base);
1222 append(ct.target);
1223 append(p_arguments.size());
1224 append(p_method);
1225 ct.cleanup();
1226}
1227
1228void GDScriptByteCodeGenerator::write_call_ptrcall(const Address &p_target, const Address &p_base, MethodBind *p_method, const Vector<Address> &p_arguments) {
1229#define CASE_TYPE(m_type) \
1230 case Variant::m_type: \
1231 append_opcode_and_argcount(GDScriptFunction::OPCODE_CALL_PTRCALL_##m_type, 2 + p_arguments.size()); \
1232 break
1233
1234 bool is_ptrcall = true;
1235
1236 if (p_method->has_return()) {
1237 MethodInfo info;
1238 ClassDB::get_method_info(p_method->get_instance_class(), p_method->get_name(), &info);
1239 switch (info.return_val.type) {
1240 CASE_TYPE(BOOL);
1241 CASE_TYPE(INT);
1242 CASE_TYPE(FLOAT);
1243 CASE_TYPE(STRING);
1244 CASE_TYPE(VECTOR2);
1245 CASE_TYPE(VECTOR2I);
1246 CASE_TYPE(RECT2);
1247 CASE_TYPE(RECT2I);
1248 CASE_TYPE(VECTOR3);
1249 CASE_TYPE(VECTOR3I);
1250 CASE_TYPE(TRANSFORM2D);
1251 CASE_TYPE(PLANE);
1252 CASE_TYPE(AABB);
1253 CASE_TYPE(BASIS);
1254 CASE_TYPE(TRANSFORM3D);
1255 CASE_TYPE(COLOR);
1256 CASE_TYPE(STRING_NAME);
1257 CASE_TYPE(NODE_PATH);
1258 CASE_TYPE(RID);
1259 CASE_TYPE(QUATERNION);
1260 CASE_TYPE(OBJECT);
1261 CASE_TYPE(CALLABLE);
1262 CASE_TYPE(SIGNAL);
1263 CASE_TYPE(DICTIONARY);
1264 CASE_TYPE(ARRAY);
1265 CASE_TYPE(PACKED_BYTE_ARRAY);
1266 CASE_TYPE(PACKED_INT32_ARRAY);
1267 CASE_TYPE(PACKED_INT64_ARRAY);
1268 CASE_TYPE(PACKED_FLOAT32_ARRAY);
1269 CASE_TYPE(PACKED_FLOAT64_ARRAY);
1270 CASE_TYPE(PACKED_STRING_ARRAY);
1271 CASE_TYPE(PACKED_VECTOR2_ARRAY);
1272 CASE_TYPE(PACKED_VECTOR3_ARRAY);
1273 CASE_TYPE(PACKED_COLOR_ARRAY);
1274 default:
1275 append_opcode_and_argcount(p_target.mode == Address::NIL ? GDScriptFunction::OPCODE_CALL_METHOD_BIND : GDScriptFunction::OPCODE_CALL_METHOD_BIND_RET, 2 + p_arguments.size());
1276 is_ptrcall = false;
1277 break;
1278 }
1279 } else {
1280 append_opcode_and_argcount(GDScriptFunction::OPCODE_CALL_PTRCALL_NO_RETURN, 2 + p_arguments.size());
1281 }
1282
1283 for (int i = 0; i < p_arguments.size(); i++) {
1284 append(p_arguments[i]);
1285 }
1286 append(p_base);
1287 CallTarget ct = get_call_target(p_target);
1288 append(ct.target);
1289 append(p_arguments.size());
1290 append(p_method);
1291 ct.cleanup();
1292 if (is_ptrcall) {
1293 alloc_ptrcall(p_arguments.size());
1294 }
1295
1296#undef CASE_TYPE
1297}
1298
1299void GDScriptByteCodeGenerator::write_call_self(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) {
1300 append_opcode_and_argcount(p_target.mode == Address::NIL ? GDScriptFunction::OPCODE_CALL : GDScriptFunction::OPCODE_CALL_RETURN, 2 + p_arguments.size());
1301 for (int i = 0; i < p_arguments.size(); i++) {
1302 append(p_arguments[i]);
1303 }
1304 append(GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
1305 CallTarget ct = get_call_target(p_target);
1306 append(ct.target);
1307 append(p_arguments.size());
1308 append(p_function_name);
1309 ct.cleanup();
1310}
1311
1312void GDScriptByteCodeGenerator::write_call_self_async(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) {
1313 append_opcode_and_argcount(GDScriptFunction::OPCODE_CALL_ASYNC, 2 + p_arguments.size());
1314 for (int i = 0; i < p_arguments.size(); i++) {
1315 append(p_arguments[i]);
1316 }
1317 append(GDScriptFunction::ADDR_SELF);
1318 CallTarget ct = get_call_target(p_target);
1319 append(ct.target);
1320 append(p_arguments.size());
1321 append(p_function_name);
1322 ct.cleanup();
1323}
1324
1325void GDScriptByteCodeGenerator::write_call_script_function(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) {
1326 append_opcode_and_argcount(p_target.mode == Address::NIL ? GDScriptFunction::OPCODE_CALL : GDScriptFunction::OPCODE_CALL_RETURN, 2 + p_arguments.size());
1327 for (int i = 0; i < p_arguments.size(); i++) {
1328 append(p_arguments[i]);
1329 }
1330 append(p_base);
1331 CallTarget ct = get_call_target(p_target);
1332 append(ct.target);
1333 append(p_arguments.size());
1334 append(p_function_name);
1335 ct.cleanup();
1336}
1337
1338void GDScriptByteCodeGenerator::write_lambda(const Address &p_target, GDScriptFunction *p_function, const Vector<Address> &p_captures, bool p_use_self) {
1339 append_opcode_and_argcount(p_use_self ? GDScriptFunction::OPCODE_CREATE_SELF_LAMBDA : GDScriptFunction::OPCODE_CREATE_LAMBDA, 1 + p_captures.size());
1340 for (int i = 0; i < p_captures.size(); i++) {
1341 append(p_captures[i]);
1342 }
1343
1344 CallTarget ct = get_call_target(p_target);
1345 append(ct.target);
1346 append(p_captures.size());
1347 append(p_function);
1348 ct.cleanup();
1349}
1350
1351void GDScriptByteCodeGenerator::write_construct(const Address &p_target, Variant::Type p_type, const Vector<Address> &p_arguments) {
1352 // Try to find an appropriate constructor.
1353 bool all_have_type = true;
1354 Vector<Variant::Type> arg_types;
1355 for (int i = 0; i < p_arguments.size(); i++) {
1356 if (!HAS_BUILTIN_TYPE(p_arguments[i])) {
1357 all_have_type = false;
1358 break;
1359 }
1360 arg_types.push_back(p_arguments[i].type.builtin_type);
1361 }
1362 if (all_have_type) {
1363 int valid_constructor = -1;
1364 for (int i = 0; i < Variant::get_constructor_count(p_type); i++) {
1365 if (Variant::get_constructor_argument_count(p_type, i) != p_arguments.size()) {
1366 continue;
1367 }
1368 int types_correct = true;
1369 for (int j = 0; j < arg_types.size(); j++) {
1370 if (arg_types[j] != Variant::get_constructor_argument_type(p_type, i, j)) {
1371 types_correct = false;
1372 break;
1373 }
1374 }
1375 if (types_correct) {
1376 valid_constructor = i;
1377 break;
1378 }
1379 }
1380 if (valid_constructor >= 0) {
1381 append_opcode_and_argcount(GDScriptFunction::OPCODE_CONSTRUCT_VALIDATED, 1 + p_arguments.size());
1382 for (int i = 0; i < p_arguments.size(); i++) {
1383 append(p_arguments[i]);
1384 }
1385 CallTarget ct = get_call_target(p_target);
1386 append(ct.target);
1387 append(p_arguments.size());
1388 append(Variant::get_validated_constructor(p_type, valid_constructor));
1389 ct.cleanup();
1390#ifdef DEBUG_ENABLED
1391 add_debug_name(constructors_names, get_constructor_pos(Variant::get_validated_constructor(p_type, valid_constructor)), Variant::get_type_name(p_type));
1392#endif
1393 return;
1394 }
1395 }
1396
1397 append_opcode_and_argcount(GDScriptFunction::OPCODE_CONSTRUCT, 1 + p_arguments.size());
1398 for (int i = 0; i < p_arguments.size(); i++) {
1399 append(p_arguments[i]);
1400 }
1401 CallTarget ct = get_call_target(p_target);
1402 append(ct.target);
1403 append(p_arguments.size());
1404 append(p_type);
1405 ct.cleanup();
1406}
1407
1408void GDScriptByteCodeGenerator::write_construct_array(const Address &p_target, const Vector<Address> &p_arguments) {
1409 append_opcode_and_argcount(GDScriptFunction::OPCODE_CONSTRUCT_ARRAY, 1 + p_arguments.size());
1410 for (int i = 0; i < p_arguments.size(); i++) {
1411 append(p_arguments[i]);
1412 }
1413 CallTarget ct = get_call_target(p_target);
1414 append(ct.target);
1415 append(p_arguments.size());
1416 ct.cleanup();
1417}
1418
1419void GDScriptByteCodeGenerator::write_construct_typed_array(const Address &p_target, const GDScriptDataType &p_element_type, const Vector<Address> &p_arguments) {
1420 append_opcode_and_argcount(GDScriptFunction::OPCODE_CONSTRUCT_TYPED_ARRAY, 2 + p_arguments.size());
1421 for (int i = 0; i < p_arguments.size(); i++) {
1422 append(p_arguments[i]);
1423 }
1424 CallTarget ct = get_call_target(p_target);
1425 append(ct.target);
1426 append(get_constant_pos(p_element_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS));
1427 append(p_arguments.size());
1428 append(p_element_type.builtin_type);
1429 append(p_element_type.native_type);
1430 ct.cleanup();
1431}
1432
1433void GDScriptByteCodeGenerator::write_construct_dictionary(const Address &p_target, const Vector<Address> &p_arguments) {
1434 append_opcode_and_argcount(GDScriptFunction::OPCODE_CONSTRUCT_DICTIONARY, 1 + p_arguments.size());
1435 for (int i = 0; i < p_arguments.size(); i++) {
1436 append(p_arguments[i]);
1437 }
1438 CallTarget ct = get_call_target(p_target);
1439 append(ct.target);
1440 append(p_arguments.size() / 2); // This is number of key-value pairs, so only half of actual arguments.
1441 ct.cleanup();
1442}
1443
1444void GDScriptByteCodeGenerator::write_await(const Address &p_target, const Address &p_operand) {
1445 append_opcode(GDScriptFunction::OPCODE_AWAIT);
1446 append(p_operand);
1447 append_opcode(GDScriptFunction::OPCODE_AWAIT_RESUME);
1448 append(p_target);
1449}
1450
1451void GDScriptByteCodeGenerator::write_if(const Address &p_condition) {
1452 append_opcode(GDScriptFunction::OPCODE_JUMP_IF_NOT);
1453 append(p_condition);
1454 if_jmp_addrs.push_back(opcodes.size());
1455 append(0); // Jump destination, will be patched.
1456}
1457
1458void GDScriptByteCodeGenerator::write_else() {
1459 append_opcode(GDScriptFunction::OPCODE_JUMP); // Jump from true if block;
1460 int else_jmp_addr = opcodes.size();
1461 append(0); // Jump destination, will be patched.
1462
1463 patch_jump(if_jmp_addrs.back()->get());
1464 if_jmp_addrs.pop_back();
1465 if_jmp_addrs.push_back(else_jmp_addr);
1466}
1467
1468void GDScriptByteCodeGenerator::write_endif() {
1469 patch_jump(if_jmp_addrs.back()->get());
1470 if_jmp_addrs.pop_back();
1471}
1472
1473void GDScriptByteCodeGenerator::write_jump_if_shared(const Address &p_value) {
1474 append_opcode(GDScriptFunction::OPCODE_JUMP_IF_SHARED);
1475 append(p_value);
1476 if_jmp_addrs.push_back(opcodes.size());
1477 append(0); // Jump destination, will be patched.
1478}
1479
1480void GDScriptByteCodeGenerator::write_end_jump_if_shared() {
1481 patch_jump(if_jmp_addrs.back()->get());
1482 if_jmp_addrs.pop_back();
1483}
1484
1485void GDScriptByteCodeGenerator::start_for(const GDScriptDataType &p_iterator_type, const GDScriptDataType &p_list_type) {
1486 Address counter(Address::LOCAL_VARIABLE, add_local("@counter_pos", p_iterator_type), p_iterator_type);
1487 Address container(Address::LOCAL_VARIABLE, add_local("@container_pos", p_list_type), p_list_type);
1488
1489 // Store state.
1490 for_counter_variables.push_back(counter);
1491 for_container_variables.push_back(container);
1492}
1493
1494void GDScriptByteCodeGenerator::write_for_assignment(const Address &p_list) {
1495 const Address &container = for_container_variables.back()->get();
1496
1497 // Assign container.
1498 append_opcode(GDScriptFunction::OPCODE_ASSIGN);
1499 append(container);
1500 append(p_list);
1501}
1502
1503void GDScriptByteCodeGenerator::write_for(const Address &p_variable, bool p_use_conversion) {
1504 const Address &counter = for_counter_variables.back()->get();
1505 const Address &container = for_container_variables.back()->get();
1506
1507 current_breaks_to_patch.push_back(List<int>());
1508
1509 GDScriptFunction::Opcode begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN;
1510 GDScriptFunction::Opcode iterate_opcode = GDScriptFunction::OPCODE_ITERATE;
1511
1512 if (container.type.has_type) {
1513 if (container.type.kind == GDScriptDataType::BUILTIN) {
1514 switch (container.type.builtin_type) {
1515 case Variant::INT:
1516 begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_INT;
1517 iterate_opcode = GDScriptFunction::OPCODE_ITERATE_INT;
1518 break;
1519 case Variant::FLOAT:
1520 begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_FLOAT;
1521 iterate_opcode = GDScriptFunction::OPCODE_ITERATE_FLOAT;
1522 break;
1523 case Variant::VECTOR2:
1524 begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_VECTOR2;
1525 iterate_opcode = GDScriptFunction::OPCODE_ITERATE_VECTOR2;
1526 break;
1527 case Variant::VECTOR2I:
1528 begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_VECTOR2I;
1529 iterate_opcode = GDScriptFunction::OPCODE_ITERATE_VECTOR2I;
1530 break;
1531 case Variant::VECTOR3:
1532 begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_VECTOR3;
1533 iterate_opcode = GDScriptFunction::OPCODE_ITERATE_VECTOR3;
1534 break;
1535 case Variant::VECTOR3I:
1536 begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_VECTOR3I;
1537 iterate_opcode = GDScriptFunction::OPCODE_ITERATE_VECTOR3I;
1538 break;
1539 case Variant::STRING:
1540 begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_STRING;
1541 iterate_opcode = GDScriptFunction::OPCODE_ITERATE_STRING;
1542 break;
1543 case Variant::DICTIONARY:
1544 begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_DICTIONARY;
1545 iterate_opcode = GDScriptFunction::OPCODE_ITERATE_DICTIONARY;
1546 break;
1547 case Variant::ARRAY:
1548 begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_ARRAY;
1549 iterate_opcode = GDScriptFunction::OPCODE_ITERATE_ARRAY;
1550 break;
1551 case Variant::PACKED_BYTE_ARRAY:
1552 begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_PACKED_BYTE_ARRAY;
1553 iterate_opcode = GDScriptFunction::OPCODE_ITERATE_PACKED_BYTE_ARRAY;
1554 break;
1555 case Variant::PACKED_INT32_ARRAY:
1556 begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_PACKED_INT32_ARRAY;
1557 iterate_opcode = GDScriptFunction::OPCODE_ITERATE_PACKED_INT32_ARRAY;
1558 break;
1559 case Variant::PACKED_INT64_ARRAY:
1560 begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_PACKED_INT64_ARRAY;
1561 iterate_opcode = GDScriptFunction::OPCODE_ITERATE_PACKED_INT64_ARRAY;
1562 break;
1563 case Variant::PACKED_FLOAT32_ARRAY:
1564 begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_PACKED_FLOAT32_ARRAY;
1565 iterate_opcode = GDScriptFunction::OPCODE_ITERATE_PACKED_FLOAT32_ARRAY;
1566 break;
1567 case Variant::PACKED_FLOAT64_ARRAY:
1568 begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_PACKED_FLOAT64_ARRAY;
1569 iterate_opcode = GDScriptFunction::OPCODE_ITERATE_PACKED_FLOAT64_ARRAY;
1570 break;
1571 case Variant::PACKED_STRING_ARRAY:
1572 begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_PACKED_STRING_ARRAY;
1573 iterate_opcode = GDScriptFunction::OPCODE_ITERATE_PACKED_STRING_ARRAY;
1574 break;
1575 case Variant::PACKED_VECTOR2_ARRAY:
1576 begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_PACKED_VECTOR2_ARRAY;
1577 iterate_opcode = GDScriptFunction::OPCODE_ITERATE_PACKED_VECTOR2_ARRAY;
1578 break;
1579 case Variant::PACKED_VECTOR3_ARRAY:
1580 begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_PACKED_VECTOR3_ARRAY;
1581 iterate_opcode = GDScriptFunction::OPCODE_ITERATE_PACKED_VECTOR3_ARRAY;
1582 break;
1583 case Variant::PACKED_COLOR_ARRAY:
1584 begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_PACKED_COLOR_ARRAY;
1585 iterate_opcode = GDScriptFunction::OPCODE_ITERATE_PACKED_COLOR_ARRAY;
1586 break;
1587 default:
1588 break;
1589 }
1590 } else {
1591 begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_OBJECT;
1592 iterate_opcode = GDScriptFunction::OPCODE_ITERATE_OBJECT;
1593 }
1594 }
1595
1596 Address temp;
1597 if (p_use_conversion) {
1598 temp = Address(Address::LOCAL_VARIABLE, add_local("@iterator_temp", GDScriptDataType()));
1599 }
1600
1601 // Begin loop.
1602 append_opcode(begin_opcode);
1603 append(counter);
1604 append(container);
1605 append(p_use_conversion ? temp : p_variable);
1606 for_jmp_addrs.push_back(opcodes.size());
1607 append(0); // End of loop address, will be patched.
1608 append_opcode(GDScriptFunction::OPCODE_JUMP);
1609 append(opcodes.size() + 6); // Skip over 'continue' code.
1610
1611 // Next iteration.
1612 int continue_addr = opcodes.size();
1613 continue_addrs.push_back(continue_addr);
1614 append_opcode(iterate_opcode);
1615 append(counter);
1616 append(container);
1617 append(p_use_conversion ? temp : p_variable);
1618 for_jmp_addrs.push_back(opcodes.size());
1619 append(0); // Jump destination, will be patched.
1620
1621 if (p_use_conversion) {
1622 write_assign_with_conversion(p_variable, temp);
1623 const GDScriptDataType &type = p_variable.type;
1624 if (type.kind != GDScriptDataType::BUILTIN || type.builtin_type == Variant::ARRAY || type.builtin_type == Variant::DICTIONARY) {
1625 write_assign_false(temp); // Can contain RefCounted, so clear it.
1626 }
1627 }
1628}
1629
1630void GDScriptByteCodeGenerator::write_endfor() {
1631 // Jump back to loop check.
1632 append_opcode(GDScriptFunction::OPCODE_JUMP);
1633 append(continue_addrs.back()->get());
1634 continue_addrs.pop_back();
1635
1636 // Patch end jumps (two of them).
1637 for (int i = 0; i < 2; i++) {
1638 patch_jump(for_jmp_addrs.back()->get());
1639 for_jmp_addrs.pop_back();
1640 }
1641
1642 // Patch break statements.
1643 for (const int &E : current_breaks_to_patch.back()->get()) {
1644 patch_jump(E);
1645 }
1646 current_breaks_to_patch.pop_back();
1647
1648 // Pop state.
1649 for_counter_variables.pop_back();
1650 for_container_variables.pop_back();
1651}
1652
1653void GDScriptByteCodeGenerator::start_while_condition() {
1654 current_breaks_to_patch.push_back(List<int>());
1655 continue_addrs.push_back(opcodes.size());
1656}
1657
1658void GDScriptByteCodeGenerator::write_while(const Address &p_condition) {
1659 // Condition check.
1660 append_opcode(GDScriptFunction::OPCODE_JUMP_IF_NOT);
1661 append(p_condition);
1662 while_jmp_addrs.push_back(opcodes.size());
1663 append(0); // End of loop address, will be patched.
1664}
1665
1666void GDScriptByteCodeGenerator::write_endwhile() {
1667 // Jump back to loop check.
1668 append_opcode(GDScriptFunction::OPCODE_JUMP);
1669 append(continue_addrs.back()->get());
1670 continue_addrs.pop_back();
1671
1672 // Patch end jump.
1673 patch_jump(while_jmp_addrs.back()->get());
1674 while_jmp_addrs.pop_back();
1675
1676 // Patch break statements.
1677 for (const int &E : current_breaks_to_patch.back()->get()) {
1678 patch_jump(E);
1679 }
1680 current_breaks_to_patch.pop_back();
1681}
1682
1683void GDScriptByteCodeGenerator::write_break() {
1684 append_opcode(GDScriptFunction::OPCODE_JUMP);
1685 current_breaks_to_patch.back()->get().push_back(opcodes.size());
1686 append(0);
1687}
1688
1689void GDScriptByteCodeGenerator::write_continue() {
1690 append_opcode(GDScriptFunction::OPCODE_JUMP);
1691 append(continue_addrs.back()->get());
1692}
1693
1694void GDScriptByteCodeGenerator::write_breakpoint() {
1695 append_opcode(GDScriptFunction::OPCODE_BREAKPOINT);
1696}
1697
1698void GDScriptByteCodeGenerator::write_newline(int p_line) {
1699 append_opcode(GDScriptFunction::OPCODE_LINE);
1700 append(p_line);
1701 current_line = p_line;
1702}
1703
1704void GDScriptByteCodeGenerator::write_return(const Address &p_return_value) {
1705 if (!function->return_type.has_type || p_return_value.type.has_type) {
1706 // Either the function is untyped or the return value is also typed.
1707
1708 // If this is a typed function, then we need to check for potential conversions.
1709 if (function->return_type.has_type) {
1710 if (function->return_type.kind == GDScriptDataType::BUILTIN && function->return_type.builtin_type == Variant::ARRAY && function->return_type.has_container_element_type()) {
1711 // Typed array.
1712 const GDScriptDataType &element_type = function->return_type.get_container_element_type();
1713 append_opcode(GDScriptFunction::OPCODE_RETURN_TYPED_ARRAY);
1714 append(p_return_value);
1715 append(get_constant_pos(element_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS));
1716 append(element_type.builtin_type);
1717 append(element_type.native_type);
1718 } else if (function->return_type.kind == GDScriptDataType::BUILTIN && p_return_value.type.kind == GDScriptDataType::BUILTIN && function->return_type.builtin_type != p_return_value.type.builtin_type) {
1719 // Add conversion.
1720 append_opcode(GDScriptFunction::OPCODE_RETURN_TYPED_BUILTIN);
1721 append(p_return_value);
1722 append(function->return_type.builtin_type);
1723 } else {
1724 // Just assign.
1725 append_opcode(GDScriptFunction::OPCODE_RETURN);
1726 append(p_return_value);
1727 }
1728 } else {
1729 append_opcode(GDScriptFunction::OPCODE_RETURN);
1730 append(p_return_value);
1731 }
1732 } else {
1733 switch (function->return_type.kind) {
1734 case GDScriptDataType::BUILTIN: {
1735 if (function->return_type.builtin_type == Variant::ARRAY && function->return_type.has_container_element_type()) {
1736 const GDScriptDataType &element_type = function->return_type.get_container_element_type();
1737 append_opcode(GDScriptFunction::OPCODE_RETURN_TYPED_ARRAY);
1738 append(p_return_value);
1739 append(get_constant_pos(element_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS));
1740 append(element_type.builtin_type);
1741 append(element_type.native_type);
1742 } else {
1743 append_opcode(GDScriptFunction::OPCODE_RETURN_TYPED_BUILTIN);
1744 append(p_return_value);
1745 append(function->return_type.builtin_type);
1746 }
1747 } break;
1748 case GDScriptDataType::NATIVE: {
1749 append_opcode(GDScriptFunction::OPCODE_RETURN_TYPED_NATIVE);
1750 append(p_return_value);
1751 int class_idx = GDScriptLanguage::get_singleton()->get_global_map()[function->return_type.native_type];
1752 Variant nc = GDScriptLanguage::get_singleton()->get_global_array()[class_idx];
1753 class_idx = get_constant_pos(nc) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
1754 append(class_idx);
1755 } break;
1756 case GDScriptDataType::GDSCRIPT:
1757 case GDScriptDataType::SCRIPT: {
1758 Variant script = function->return_type.script_type;
1759 int script_idx = get_constant_pos(script) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
1760
1761 append_opcode(GDScriptFunction::OPCODE_RETURN_TYPED_SCRIPT);
1762 append(p_return_value);
1763 append(script_idx);
1764 } break;
1765 default: {
1766 ERR_PRINT("Compiler bug: unresolved return.");
1767
1768 // Shouldn't get here, but fail-safe to a regular return;
1769 append_opcode(GDScriptFunction::OPCODE_RETURN);
1770 append(p_return_value);
1771 } break;
1772 }
1773 }
1774}
1775
1776void GDScriptByteCodeGenerator::write_assert(const Address &p_test, const Address &p_message) {
1777 append_opcode(GDScriptFunction::OPCODE_ASSERT);
1778 append(p_test);
1779 append(p_message);
1780}
1781
1782void GDScriptByteCodeGenerator::start_block() {
1783 push_stack_identifiers();
1784}
1785
1786void GDScriptByteCodeGenerator::end_block() {
1787 pop_stack_identifiers();
1788}
1789
1790void GDScriptByteCodeGenerator::clean_temporaries() {
1791 List<int>::Element *E = temporaries_pending_clear.front();
1792 while (E) {
1793 // The temporary may have been re-used as something else than an object
1794 // since it was added to the list. In that case, there's no need to clear it.
1795 int slot_idx = E->get();
1796 const StackSlot &slot = temporaries[slot_idx];
1797 if (slot.type == Variant::NIL) {
1798 write_assign_false(Address(Address::TEMPORARY, slot_idx));
1799 }
1800
1801 List<int>::Element *next = E->next();
1802 E->erase();
1803 E = next;
1804 }
1805}
1806
1807GDScriptByteCodeGenerator::~GDScriptByteCodeGenerator() {
1808 if (!ended && function != nullptr) {
1809 memdelete(function);
1810 }
1811}
1812