Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/modules/gdscript/gdscript_byte_codegen.cpp
20852 views
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 "core/debugger/engine_debugger.h"
34
35
uint32_t GDScriptByteCodeGenerator::add_parameter(const StringName &p_name, bool p_is_optional, const GDScriptDataType &p_type) {
36
function->_argument_count++;
37
function->argument_types.push_back(p_type);
38
if (p_is_optional) {
39
function->_default_arg_count++;
40
}
41
42
return add_local(p_name, p_type);
43
}
44
45
uint32_t GDScriptByteCodeGenerator::add_local(const StringName &p_name, const GDScriptDataType &p_type) {
46
int stack_pos = locals.size() + GDScriptFunction::FIXED_ADDRESSES_MAX;
47
locals.push_back(StackSlot(p_type.builtin_type, p_type.can_contain_object()));
48
add_stack_identifier(p_name, stack_pos);
49
return stack_pos;
50
}
51
52
uint32_t GDScriptByteCodeGenerator::add_local_constant(const StringName &p_name, const Variant &p_constant) {
53
int index = add_or_get_constant(p_constant);
54
local_constants[p_name] = index;
55
return index;
56
}
57
58
uint32_t GDScriptByteCodeGenerator::add_or_get_constant(const Variant &p_constant) {
59
return get_constant_pos(p_constant);
60
}
61
62
uint32_t GDScriptByteCodeGenerator::add_or_get_name(const StringName &p_name) {
63
return get_name_map_pos(p_name);
64
}
65
66
uint32_t GDScriptByteCodeGenerator::add_temporary(const GDScriptDataType &p_type) {
67
Variant::Type temp_type = Variant::NIL;
68
if (p_type.kind == GDScriptDataType::BUILTIN) {
69
switch (p_type.builtin_type) {
70
case Variant::NIL:
71
case Variant::BOOL:
72
case Variant::INT:
73
case Variant::FLOAT:
74
case Variant::STRING:
75
case Variant::VECTOR2:
76
case Variant::VECTOR2I:
77
case Variant::RECT2:
78
case Variant::RECT2I:
79
case Variant::VECTOR3:
80
case Variant::VECTOR3I:
81
case Variant::TRANSFORM2D:
82
case Variant::VECTOR4:
83
case Variant::VECTOR4I:
84
case Variant::PLANE:
85
case Variant::QUATERNION:
86
case Variant::AABB:
87
case Variant::BASIS:
88
case Variant::TRANSFORM3D:
89
case Variant::PROJECTION:
90
case Variant::COLOR:
91
case Variant::STRING_NAME:
92
case Variant::NODE_PATH:
93
case Variant::RID:
94
case Variant::CALLABLE:
95
case Variant::SIGNAL:
96
temp_type = p_type.builtin_type;
97
break;
98
case Variant::OBJECT:
99
case Variant::DICTIONARY:
100
case Variant::ARRAY:
101
case Variant::PACKED_BYTE_ARRAY:
102
case Variant::PACKED_INT32_ARRAY:
103
case Variant::PACKED_INT64_ARRAY:
104
case Variant::PACKED_FLOAT32_ARRAY:
105
case Variant::PACKED_FLOAT64_ARRAY:
106
case Variant::PACKED_STRING_ARRAY:
107
case Variant::PACKED_VECTOR2_ARRAY:
108
case Variant::PACKED_VECTOR3_ARRAY:
109
case Variant::PACKED_COLOR_ARRAY:
110
case Variant::PACKED_VECTOR4_ARRAY:
111
case Variant::VARIANT_MAX:
112
// Arrays, dictionaries, and objects are reference counted, so we don't use the pool for them.
113
temp_type = Variant::NIL;
114
break;
115
}
116
}
117
118
if (!temporaries_pool.has(temp_type)) {
119
temporaries_pool[temp_type] = List<int>();
120
}
121
122
List<int> &pool = temporaries_pool[temp_type];
123
if (pool.is_empty()) {
124
StackSlot new_temp(temp_type, p_type.can_contain_object());
125
int idx = temporaries.size();
126
pool.push_back(idx);
127
temporaries.push_back(new_temp);
128
}
129
int slot = pool.front()->get();
130
pool.pop_front();
131
used_temporaries.push_back(slot);
132
return slot;
133
}
134
135
void GDScriptByteCodeGenerator::pop_temporary() {
136
ERR_FAIL_COND(used_temporaries.is_empty());
137
int slot_idx = used_temporaries.back()->get();
138
if (temporaries[slot_idx].can_contain_object) {
139
// Avoid keeping in the stack long-lived references to objects,
140
// which may prevent `RefCounted` objects from being freed.
141
// However, the cleanup will be performed an the end of the
142
// statement, to allow object references to survive chaining.
143
temporaries_pending_clear.insert(slot_idx);
144
}
145
temporaries_pool[temporaries[slot_idx].type].push_back(slot_idx);
146
used_temporaries.pop_back();
147
}
148
149
void GDScriptByteCodeGenerator::start_parameters() {
150
if (function->_default_arg_count > 0) {
151
append(GDScriptFunction::OPCODE_JUMP_TO_DEF_ARGUMENT);
152
function->default_arguments.push_back(opcodes.size());
153
}
154
}
155
156
void GDScriptByteCodeGenerator::end_parameters() {
157
function->default_arguments.reverse();
158
}
159
160
void GDScriptByteCodeGenerator::write_start(GDScript *p_script, const StringName &p_function_name, bool p_static, Variant p_rpc_config, const GDScriptDataType &p_return_type) {
161
function = memnew(GDScriptFunction);
162
163
function->name = p_function_name;
164
function->_script = p_script;
165
function->source = p_script->get_script_path();
166
167
#ifdef DEBUG_ENABLED
168
function->func_cname = (String(function->source) + " - " + String(p_function_name)).utf8();
169
function->_func_cname = function->func_cname.get_data();
170
#endif
171
172
function->_static = p_static;
173
function->return_type = p_return_type;
174
function->rpc_config = p_rpc_config;
175
function->_argument_count = 0;
176
}
177
178
GDScriptFunction *GDScriptByteCodeGenerator::write_end() {
179
#ifdef DEBUG_ENABLED
180
if (!used_temporaries.is_empty()) {
181
ERR_PRINT("Non-zero temporary variables at end of function: " + itos(used_temporaries.size()));
182
}
183
#endif
184
append_opcode(GDScriptFunction::OPCODE_END);
185
186
for (int i = 0; i < temporaries.size(); i++) {
187
int stack_index = i + max_locals + GDScriptFunction::FIXED_ADDRESSES_MAX;
188
for (int j = 0; j < temporaries[i].bytecode_indices.size(); j++) {
189
opcodes.write[temporaries[i].bytecode_indices[j]] = stack_index | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
190
}
191
if (temporaries[i].type != Variant::NIL) {
192
function->temporary_slots[stack_index] = temporaries[i].type;
193
}
194
}
195
196
if (constant_map.size()) {
197
function->_constant_count = constant_map.size();
198
function->constants.resize(constant_map.size());
199
function->_constants_ptr = function->constants.ptrw();
200
for (const KeyValue<Variant, int> &K : constant_map) {
201
function->constants.write[K.value] = K.key;
202
}
203
for (const KeyValue<StringName, int> &K : local_constants) {
204
function->constant_map.insert(K.key, function->constants[K.value]);
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 (GDScriptLanguage::get_singleton()->should_track_locals()) {
399
function->stack_debug = stack_debug;
400
}
401
function->_stack_size = GDScriptFunction::FIXED_ADDRESSES_MAX + max_locals + temporaries.size();
402
function->_instruction_args_size = instr_args_max;
403
404
#ifdef DEBUG_ENABLED
405
function->operator_names = operator_names;
406
function->setter_names = setter_names;
407
function->getter_names = getter_names;
408
function->builtin_methods_names = builtin_methods_names;
409
function->constructors_names = constructors_names;
410
function->utilities_names = utilities_names;
411
function->gds_utilities_names = gds_utilities_names;
412
#endif
413
414
ended = true;
415
return function;
416
}
417
418
#ifdef DEBUG_ENABLED
419
void GDScriptByteCodeGenerator::set_signature(const String &p_signature) {
420
function->profile.signature = p_signature;
421
}
422
#endif
423
424
void GDScriptByteCodeGenerator::set_initial_line(int p_line) {
425
function->_initial_line = p_line;
426
}
427
428
#define HAS_BUILTIN_TYPE(m_var) \
429
(m_var.type.kind == GDScriptDataType::BUILTIN)
430
431
#define IS_BUILTIN_TYPE(m_var, m_type) \
432
(m_var.type.kind == GDScriptDataType::BUILTIN && m_var.type.builtin_type == m_type && m_type != Variant::NIL)
433
434
void GDScriptByteCodeGenerator::write_type_adjust(const Address &p_target, Variant::Type p_new_type) {
435
switch (p_new_type) {
436
case Variant::BOOL:
437
append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_BOOL);
438
break;
439
case Variant::INT:
440
append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_INT);
441
break;
442
case Variant::FLOAT:
443
append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_FLOAT);
444
break;
445
case Variant::STRING:
446
append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_STRING);
447
break;
448
case Variant::VECTOR2:
449
append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_VECTOR2);
450
break;
451
case Variant::VECTOR2I:
452
append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_VECTOR2I);
453
break;
454
case Variant::RECT2:
455
append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_RECT2);
456
break;
457
case Variant::RECT2I:
458
append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_RECT2I);
459
break;
460
case Variant::VECTOR3:
461
append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_VECTOR3);
462
break;
463
case Variant::VECTOR3I:
464
append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_VECTOR3I);
465
break;
466
case Variant::TRANSFORM2D:
467
append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_TRANSFORM2D);
468
break;
469
case Variant::VECTOR4:
470
append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_VECTOR3);
471
break;
472
case Variant::VECTOR4I:
473
append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_VECTOR3I);
474
break;
475
case Variant::PLANE:
476
append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_PLANE);
477
break;
478
case Variant::QUATERNION:
479
append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_QUATERNION);
480
break;
481
case Variant::AABB:
482
append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_AABB);
483
break;
484
case Variant::BASIS:
485
append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_BASIS);
486
break;
487
case Variant::TRANSFORM3D:
488
append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_TRANSFORM3D);
489
break;
490
case Variant::PROJECTION:
491
append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_PROJECTION);
492
break;
493
case Variant::COLOR:
494
append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_COLOR);
495
break;
496
case Variant::STRING_NAME:
497
append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_STRING_NAME);
498
break;
499
case Variant::NODE_PATH:
500
append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_NODE_PATH);
501
break;
502
case Variant::RID:
503
append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_RID);
504
break;
505
case Variant::OBJECT:
506
append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_OBJECT);
507
break;
508
case Variant::CALLABLE:
509
append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_CALLABLE);
510
break;
511
case Variant::SIGNAL:
512
append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_SIGNAL);
513
break;
514
case Variant::DICTIONARY:
515
append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_DICTIONARY);
516
break;
517
case Variant::ARRAY:
518
append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_ARRAY);
519
break;
520
case Variant::PACKED_BYTE_ARRAY:
521
append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_PACKED_BYTE_ARRAY);
522
break;
523
case Variant::PACKED_INT32_ARRAY:
524
append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_PACKED_INT32_ARRAY);
525
break;
526
case Variant::PACKED_INT64_ARRAY:
527
append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_PACKED_INT64_ARRAY);
528
break;
529
case Variant::PACKED_FLOAT32_ARRAY:
530
append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_PACKED_FLOAT32_ARRAY);
531
break;
532
case Variant::PACKED_FLOAT64_ARRAY:
533
append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_PACKED_FLOAT64_ARRAY);
534
break;
535
case Variant::PACKED_STRING_ARRAY:
536
append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_PACKED_STRING_ARRAY);
537
break;
538
case Variant::PACKED_VECTOR2_ARRAY:
539
append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_PACKED_VECTOR2_ARRAY);
540
break;
541
case Variant::PACKED_VECTOR3_ARRAY:
542
append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_PACKED_VECTOR3_ARRAY);
543
break;
544
case Variant::PACKED_COLOR_ARRAY:
545
append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_PACKED_COLOR_ARRAY);
546
break;
547
case Variant::PACKED_VECTOR4_ARRAY:
548
append_opcode(GDScriptFunction::OPCODE_TYPE_ADJUST_PACKED_VECTOR4_ARRAY);
549
break;
550
case Variant::NIL:
551
case Variant::VARIANT_MAX:
552
return;
553
}
554
append(p_target);
555
}
556
557
void GDScriptByteCodeGenerator::write_unary_operator(const Address &p_target, Variant::Operator p_operator, const Address &p_left_operand) {
558
if (HAS_BUILTIN_TYPE(p_left_operand)) {
559
// Gather specific operator.
560
Variant::ValidatedOperatorEvaluator op_func = Variant::get_validated_operator_evaluator(p_operator, p_left_operand.type.builtin_type, Variant::NIL);
561
562
append_opcode(GDScriptFunction::OPCODE_OPERATOR_VALIDATED);
563
append(p_left_operand);
564
append(Address());
565
append(p_target);
566
append(op_func);
567
#ifdef DEBUG_ENABLED
568
add_debug_name(operator_names, get_operation_pos(op_func), Variant::get_operator_name(p_operator));
569
#endif
570
return;
571
}
572
573
// No specific types, perform variant evaluation.
574
append_opcode(GDScriptFunction::OPCODE_OPERATOR);
575
append(p_left_operand);
576
append(Address());
577
append(p_target);
578
append(p_operator);
579
append(0); // Signature storage.
580
append(0); // Return type storage.
581
constexpr int _pointer_size = sizeof(Variant::ValidatedOperatorEvaluator) / sizeof(*(opcodes.ptr()));
582
for (int i = 0; i < _pointer_size; i++) {
583
append(0); // Space for function pointer.
584
}
585
}
586
587
void GDScriptByteCodeGenerator::write_binary_operator(const Address &p_target, Variant::Operator p_operator, const Address &p_left_operand, const Address &p_right_operand) {
588
bool valid = HAS_BUILTIN_TYPE(p_left_operand) && HAS_BUILTIN_TYPE(p_right_operand);
589
590
// Avoid validated evaluator for modulo and division when operands are int or integer vector, since there's no check for division by zero.
591
if (valid && (p_operator == Variant::OP_DIVIDE || p_operator == Variant::OP_MODULE)) {
592
switch (p_left_operand.type.builtin_type) {
593
case Variant::INT:
594
// Cannot use modulo between int / float, we should raise an error later in GDScript
595
valid = p_right_operand.type.builtin_type != Variant::INT && p_operator == Variant::OP_DIVIDE;
596
break;
597
case Variant::VECTOR2I:
598
case Variant::VECTOR3I:
599
case Variant::VECTOR4I:
600
valid = p_right_operand.type.builtin_type != Variant::INT && p_right_operand.type.builtin_type != p_left_operand.type.builtin_type;
601
break;
602
default:
603
break;
604
}
605
}
606
607
if (valid) {
608
if (p_target.mode == Address::TEMPORARY) {
609
Variant::Type result_type = Variant::get_operator_return_type(p_operator, p_left_operand.type.builtin_type, p_right_operand.type.builtin_type);
610
Variant::Type temp_type = temporaries[p_target.address].type;
611
if (result_type != temp_type) {
612
write_type_adjust(p_target, result_type);
613
}
614
}
615
616
// Gather specific operator.
617
Variant::ValidatedOperatorEvaluator op_func = Variant::get_validated_operator_evaluator(p_operator, p_left_operand.type.builtin_type, p_right_operand.type.builtin_type);
618
619
append_opcode(GDScriptFunction::OPCODE_OPERATOR_VALIDATED);
620
append(p_left_operand);
621
append(p_right_operand);
622
append(p_target);
623
append(op_func);
624
#ifdef DEBUG_ENABLED
625
add_debug_name(operator_names, get_operation_pos(op_func), Variant::get_operator_name(p_operator));
626
#endif
627
return;
628
}
629
630
// No specific types, perform variant evaluation.
631
append_opcode(GDScriptFunction::OPCODE_OPERATOR);
632
append(p_left_operand);
633
append(p_right_operand);
634
append(p_target);
635
append(p_operator);
636
append(0); // Signature storage.
637
append(0); // Return type storage.
638
constexpr int _pointer_size = sizeof(Variant::ValidatedOperatorEvaluator) / sizeof(*(opcodes.ptr()));
639
for (int i = 0; i < _pointer_size; i++) {
640
append(0); // Space for function pointer.
641
}
642
}
643
644
void GDScriptByteCodeGenerator::write_type_test(const Address &p_target, const Address &p_source, const GDScriptDataType &p_type) {
645
switch (p_type.kind) {
646
case GDScriptDataType::BUILTIN: {
647
if (p_type.builtin_type == Variant::ARRAY && p_type.has_container_element_type(0)) {
648
const GDScriptDataType &element_type = p_type.get_container_element_type(0);
649
append_opcode(GDScriptFunction::OPCODE_TYPE_TEST_ARRAY);
650
append(p_target);
651
append(p_source);
652
append(get_constant_pos(element_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS));
653
append(element_type.builtin_type);
654
append(element_type.native_type);
655
} else if (p_type.builtin_type == Variant::DICTIONARY && p_type.has_container_element_types()) {
656
const GDScriptDataType &key_element_type = p_type.get_container_element_type_or_variant(0);
657
const GDScriptDataType &value_element_type = p_type.get_container_element_type_or_variant(1);
658
append_opcode(GDScriptFunction::OPCODE_TYPE_TEST_DICTIONARY);
659
append(p_target);
660
append(p_source);
661
append(get_constant_pos(key_element_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS));
662
append(get_constant_pos(value_element_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS));
663
append(key_element_type.builtin_type);
664
append(key_element_type.native_type);
665
append(value_element_type.builtin_type);
666
append(value_element_type.native_type);
667
} else {
668
append_opcode(GDScriptFunction::OPCODE_TYPE_TEST_BUILTIN);
669
append(p_target);
670
append(p_source);
671
append(p_type.builtin_type);
672
}
673
} break;
674
case GDScriptDataType::NATIVE: {
675
append_opcode(GDScriptFunction::OPCODE_TYPE_TEST_NATIVE);
676
append(p_target);
677
append(p_source);
678
append(p_type.native_type);
679
} break;
680
case GDScriptDataType::SCRIPT:
681
case GDScriptDataType::GDSCRIPT: {
682
const Variant &script = p_type.script_type;
683
append_opcode(GDScriptFunction::OPCODE_TYPE_TEST_SCRIPT);
684
append(p_target);
685
append(p_source);
686
append(get_constant_pos(script) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS));
687
} break;
688
default: {
689
ERR_PRINT("Compiler bug: unresolved type in type test.");
690
append_opcode(GDScriptFunction::OPCODE_ASSIGN_FALSE);
691
append(p_target);
692
}
693
}
694
}
695
696
void GDScriptByteCodeGenerator::write_and_left_operand(const Address &p_left_operand) {
697
append_opcode(GDScriptFunction::OPCODE_JUMP_IF_NOT);
698
append(p_left_operand);
699
logic_op_jump_pos1.push_back(opcodes.size());
700
append(0); // Jump target, will be patched.
701
}
702
703
void GDScriptByteCodeGenerator::write_and_right_operand(const Address &p_right_operand) {
704
append_opcode(GDScriptFunction::OPCODE_JUMP_IF_NOT);
705
append(p_right_operand);
706
logic_op_jump_pos2.push_back(opcodes.size());
707
append(0); // Jump target, will be patched.
708
}
709
710
void GDScriptByteCodeGenerator::write_end_and(const Address &p_target) {
711
// If here means both operands are true.
712
append_opcode(GDScriptFunction::OPCODE_ASSIGN_TRUE);
713
append(p_target);
714
// Jump away from the fail condition.
715
append_opcode(GDScriptFunction::OPCODE_JUMP);
716
append(opcodes.size() + 3);
717
// Here it means one of operands is false.
718
patch_jump(logic_op_jump_pos1.back()->get());
719
patch_jump(logic_op_jump_pos2.back()->get());
720
logic_op_jump_pos1.pop_back();
721
logic_op_jump_pos2.pop_back();
722
append_opcode(GDScriptFunction::OPCODE_ASSIGN_FALSE);
723
append(p_target);
724
}
725
726
void GDScriptByteCodeGenerator::write_or_left_operand(const Address &p_left_operand) {
727
append_opcode(GDScriptFunction::OPCODE_JUMP_IF);
728
append(p_left_operand);
729
logic_op_jump_pos1.push_back(opcodes.size());
730
append(0); // Jump target, will be patched.
731
}
732
733
void GDScriptByteCodeGenerator::write_or_right_operand(const Address &p_right_operand) {
734
append_opcode(GDScriptFunction::OPCODE_JUMP_IF);
735
append(p_right_operand);
736
logic_op_jump_pos2.push_back(opcodes.size());
737
append(0); // Jump target, will be patched.
738
}
739
740
void GDScriptByteCodeGenerator::write_end_or(const Address &p_target) {
741
// If here means both operands are false.
742
append_opcode(GDScriptFunction::OPCODE_ASSIGN_FALSE);
743
append(p_target);
744
// Jump away from the success condition.
745
append_opcode(GDScriptFunction::OPCODE_JUMP);
746
append(opcodes.size() + 3);
747
// Here it means one of operands is true.
748
patch_jump(logic_op_jump_pos1.back()->get());
749
patch_jump(logic_op_jump_pos2.back()->get());
750
logic_op_jump_pos1.pop_back();
751
logic_op_jump_pos2.pop_back();
752
append_opcode(GDScriptFunction::OPCODE_ASSIGN_TRUE);
753
append(p_target);
754
}
755
756
void GDScriptByteCodeGenerator::write_start_ternary(const Address &p_target) {
757
ternary_result.push_back(p_target);
758
}
759
760
void GDScriptByteCodeGenerator::write_ternary_condition(const Address &p_condition) {
761
append_opcode(GDScriptFunction::OPCODE_JUMP_IF_NOT);
762
append(p_condition);
763
ternary_jump_fail_pos.push_back(opcodes.size());
764
append(0); // Jump target, will be patched.
765
}
766
767
void GDScriptByteCodeGenerator::write_ternary_true_expr(const Address &p_expr) {
768
append_opcode(GDScriptFunction::OPCODE_ASSIGN);
769
append(ternary_result.back()->get());
770
append(p_expr);
771
// Jump away from the false path.
772
append_opcode(GDScriptFunction::OPCODE_JUMP);
773
ternary_jump_skip_pos.push_back(opcodes.size());
774
append(0);
775
// Fail must jump here.
776
patch_jump(ternary_jump_fail_pos.back()->get());
777
ternary_jump_fail_pos.pop_back();
778
}
779
780
void GDScriptByteCodeGenerator::write_ternary_false_expr(const Address &p_expr) {
781
append_opcode(GDScriptFunction::OPCODE_ASSIGN);
782
append(ternary_result.back()->get());
783
append(p_expr);
784
}
785
786
void GDScriptByteCodeGenerator::write_end_ternary() {
787
patch_jump(ternary_jump_skip_pos.back()->get());
788
ternary_jump_skip_pos.pop_back();
789
ternary_result.pop_back();
790
}
791
792
void GDScriptByteCodeGenerator::write_set(const Address &p_target, const Address &p_index, const Address &p_source) {
793
if (HAS_BUILTIN_TYPE(p_target)) {
794
if (IS_BUILTIN_TYPE(p_index, Variant::INT) && Variant::get_member_validated_indexed_setter(p_target.type.builtin_type) &&
795
IS_BUILTIN_TYPE(p_source, Variant::get_indexed_element_type(p_target.type.builtin_type))) {
796
// Use indexed setter instead.
797
Variant::ValidatedIndexedSetter setter = Variant::get_member_validated_indexed_setter(p_target.type.builtin_type);
798
append_opcode(GDScriptFunction::OPCODE_SET_INDEXED_VALIDATED);
799
append(p_target);
800
append(p_index);
801
append(p_source);
802
append(setter);
803
return;
804
} else if (Variant::get_member_validated_keyed_setter(p_target.type.builtin_type)) {
805
Variant::ValidatedKeyedSetter setter = Variant::get_member_validated_keyed_setter(p_target.type.builtin_type);
806
append_opcode(GDScriptFunction::OPCODE_SET_KEYED_VALIDATED);
807
append(p_target);
808
append(p_index);
809
append(p_source);
810
append(setter);
811
return;
812
}
813
}
814
815
append_opcode(GDScriptFunction::OPCODE_SET_KEYED);
816
append(p_target);
817
append(p_index);
818
append(p_source);
819
}
820
821
void GDScriptByteCodeGenerator::write_get(const Address &p_target, const Address &p_index, const Address &p_source) {
822
if (HAS_BUILTIN_TYPE(p_source)) {
823
if (IS_BUILTIN_TYPE(p_index, Variant::INT) && Variant::get_member_validated_indexed_getter(p_source.type.builtin_type)) {
824
// Use indexed getter instead.
825
Variant::ValidatedIndexedGetter getter = Variant::get_member_validated_indexed_getter(p_source.type.builtin_type);
826
append_opcode(GDScriptFunction::OPCODE_GET_INDEXED_VALIDATED);
827
append(p_source);
828
append(p_index);
829
append(p_target);
830
append(getter);
831
return;
832
} else if (Variant::get_member_validated_keyed_getter(p_source.type.builtin_type)) {
833
Variant::ValidatedKeyedGetter getter = Variant::get_member_validated_keyed_getter(p_source.type.builtin_type);
834
append_opcode(GDScriptFunction::OPCODE_GET_KEYED_VALIDATED);
835
append(p_source);
836
append(p_index);
837
append(p_target);
838
append(getter);
839
return;
840
}
841
}
842
append_opcode(GDScriptFunction::OPCODE_GET_KEYED);
843
append(p_source);
844
append(p_index);
845
append(p_target);
846
}
847
848
void GDScriptByteCodeGenerator::write_set_named(const Address &p_target, const StringName &p_name, const Address &p_source) {
849
if (HAS_BUILTIN_TYPE(p_target) && Variant::get_member_validated_setter(p_target.type.builtin_type, p_name) &&
850
IS_BUILTIN_TYPE(p_source, Variant::get_member_type(p_target.type.builtin_type, p_name))) {
851
Variant::ValidatedSetter setter = Variant::get_member_validated_setter(p_target.type.builtin_type, p_name);
852
append_opcode(GDScriptFunction::OPCODE_SET_NAMED_VALIDATED);
853
append(p_target);
854
append(p_source);
855
append(setter);
856
#ifdef DEBUG_ENABLED
857
add_debug_name(setter_names, get_setter_pos(setter), p_name);
858
#endif
859
return;
860
}
861
append_opcode(GDScriptFunction::OPCODE_SET_NAMED);
862
append(p_target);
863
append(p_source);
864
append(p_name);
865
}
866
867
void GDScriptByteCodeGenerator::write_get_named(const Address &p_target, const StringName &p_name, const Address &p_source) {
868
if (HAS_BUILTIN_TYPE(p_source) && Variant::get_member_validated_getter(p_source.type.builtin_type, p_name)) {
869
Variant::ValidatedGetter getter = Variant::get_member_validated_getter(p_source.type.builtin_type, p_name);
870
append_opcode(GDScriptFunction::OPCODE_GET_NAMED_VALIDATED);
871
append(p_source);
872
append(p_target);
873
append(getter);
874
#ifdef DEBUG_ENABLED
875
add_debug_name(getter_names, get_getter_pos(getter), p_name);
876
#endif
877
return;
878
}
879
append_opcode(GDScriptFunction::OPCODE_GET_NAMED);
880
append(p_source);
881
append(p_target);
882
append(p_name);
883
}
884
885
void GDScriptByteCodeGenerator::write_set_member(const Address &p_value, const StringName &p_name) {
886
append_opcode(GDScriptFunction::OPCODE_SET_MEMBER);
887
append(p_value);
888
append(p_name);
889
}
890
891
void GDScriptByteCodeGenerator::write_get_member(const Address &p_target, const StringName &p_name) {
892
append_opcode(GDScriptFunction::OPCODE_GET_MEMBER);
893
append(p_target);
894
append(p_name);
895
}
896
897
void GDScriptByteCodeGenerator::write_set_static_variable(const Address &p_value, const Address &p_class, int p_index) {
898
append_opcode(GDScriptFunction::OPCODE_SET_STATIC_VARIABLE);
899
append(p_value);
900
append(p_class);
901
append(p_index);
902
}
903
904
void GDScriptByteCodeGenerator::write_get_static_variable(const Address &p_target, const Address &p_class, int p_index) {
905
append_opcode(GDScriptFunction::OPCODE_GET_STATIC_VARIABLE);
906
append(p_target);
907
append(p_class);
908
append(p_index);
909
}
910
911
void GDScriptByteCodeGenerator::write_assign_with_conversion(const Address &p_target, const Address &p_source) {
912
switch (p_target.type.kind) {
913
case GDScriptDataType::BUILTIN: {
914
if (p_target.type.builtin_type == Variant::ARRAY && p_target.type.has_container_element_type(0)) {
915
const GDScriptDataType &element_type = p_target.type.get_container_element_type(0);
916
append_opcode(GDScriptFunction::OPCODE_ASSIGN_TYPED_ARRAY);
917
append(p_target);
918
append(p_source);
919
append(get_constant_pos(element_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS));
920
append(element_type.builtin_type);
921
append(element_type.native_type);
922
} else if (p_target.type.builtin_type == Variant::DICTIONARY && p_target.type.has_container_element_types()) {
923
const GDScriptDataType &key_type = p_target.type.get_container_element_type_or_variant(0);
924
const GDScriptDataType &value_type = p_target.type.get_container_element_type_or_variant(1);
925
append_opcode(GDScriptFunction::OPCODE_ASSIGN_TYPED_DICTIONARY);
926
append(p_target);
927
append(p_source);
928
append(get_constant_pos(key_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS));
929
append(get_constant_pos(value_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS));
930
append(key_type.builtin_type);
931
append(key_type.native_type);
932
append(value_type.builtin_type);
933
append(value_type.native_type);
934
} else {
935
append_opcode(GDScriptFunction::OPCODE_ASSIGN_TYPED_BUILTIN);
936
append(p_target);
937
append(p_source);
938
append(p_target.type.builtin_type);
939
}
940
} break;
941
case GDScriptDataType::NATIVE: {
942
int class_idx = GDScriptLanguage::get_singleton()->get_global_map()[p_target.type.native_type];
943
Variant nc = GDScriptLanguage::get_singleton()->get_global_array()[class_idx];
944
class_idx = get_constant_pos(nc) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
945
append_opcode(GDScriptFunction::OPCODE_ASSIGN_TYPED_NATIVE);
946
append(p_target);
947
append(p_source);
948
append(class_idx);
949
} break;
950
case GDScriptDataType::SCRIPT:
951
case GDScriptDataType::GDSCRIPT: {
952
Variant script = p_target.type.script_type;
953
int idx = get_constant_pos(script) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
954
955
append_opcode(GDScriptFunction::OPCODE_ASSIGN_TYPED_SCRIPT);
956
append(p_target);
957
append(p_source);
958
append(idx);
959
} break;
960
default: {
961
ERR_PRINT("Compiler bug: unresolved assign.");
962
963
// Shouldn't get here, but fail-safe to a regular assignment
964
append_opcode(GDScriptFunction::OPCODE_ASSIGN);
965
append(p_target);
966
append(p_source);
967
}
968
}
969
}
970
971
void GDScriptByteCodeGenerator::write_assign(const Address &p_target, const Address &p_source) {
972
if (p_target.type.kind == GDScriptDataType::BUILTIN && p_target.type.builtin_type == Variant::ARRAY && p_target.type.has_container_element_type(0)) {
973
const GDScriptDataType &element_type = p_target.type.get_container_element_type(0);
974
append_opcode(GDScriptFunction::OPCODE_ASSIGN_TYPED_ARRAY);
975
append(p_target);
976
append(p_source);
977
append(get_constant_pos(element_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS));
978
append(element_type.builtin_type);
979
append(element_type.native_type);
980
} else if (p_target.type.kind == GDScriptDataType::BUILTIN && p_target.type.builtin_type == Variant::DICTIONARY && p_target.type.has_container_element_types()) {
981
const GDScriptDataType &key_type = p_target.type.get_container_element_type_or_variant(0);
982
const GDScriptDataType &value_type = p_target.type.get_container_element_type_or_variant(1);
983
append_opcode(GDScriptFunction::OPCODE_ASSIGN_TYPED_DICTIONARY);
984
append(p_target);
985
append(p_source);
986
append(get_constant_pos(key_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS));
987
append(get_constant_pos(value_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS));
988
append(key_type.builtin_type);
989
append(key_type.native_type);
990
append(value_type.builtin_type);
991
append(value_type.native_type);
992
} else if (p_target.type.kind == GDScriptDataType::BUILTIN && p_source.type.kind == GDScriptDataType::BUILTIN && p_target.type.builtin_type != p_source.type.builtin_type) {
993
// Need conversion.
994
append_opcode(GDScriptFunction::OPCODE_ASSIGN_TYPED_BUILTIN);
995
append(p_target);
996
append(p_source);
997
append(p_target.type.builtin_type);
998
} else {
999
append_opcode(GDScriptFunction::OPCODE_ASSIGN);
1000
append(p_target);
1001
append(p_source);
1002
}
1003
}
1004
1005
void GDScriptByteCodeGenerator::write_assign_null(const Address &p_target) {
1006
append_opcode(GDScriptFunction::OPCODE_ASSIGN_NULL);
1007
append(p_target);
1008
}
1009
1010
void GDScriptByteCodeGenerator::write_assign_true(const Address &p_target) {
1011
append_opcode(GDScriptFunction::OPCODE_ASSIGN_TRUE);
1012
append(p_target);
1013
}
1014
1015
void GDScriptByteCodeGenerator::write_assign_false(const Address &p_target) {
1016
append_opcode(GDScriptFunction::OPCODE_ASSIGN_FALSE);
1017
append(p_target);
1018
}
1019
1020
void GDScriptByteCodeGenerator::write_assign_default_parameter(const Address &p_dst, const Address &p_src, bool p_use_conversion) {
1021
if (p_use_conversion) {
1022
write_assign_with_conversion(p_dst, p_src);
1023
} else {
1024
write_assign(p_dst, p_src);
1025
}
1026
function->default_arguments.push_back(opcodes.size());
1027
}
1028
1029
void GDScriptByteCodeGenerator::write_store_global(const Address &p_dst, int p_global_index) {
1030
append_opcode(GDScriptFunction::OPCODE_STORE_GLOBAL);
1031
append(p_dst);
1032
append(p_global_index);
1033
}
1034
1035
void GDScriptByteCodeGenerator::write_store_named_global(const Address &p_dst, const StringName &p_global) {
1036
append_opcode(GDScriptFunction::OPCODE_STORE_NAMED_GLOBAL);
1037
append(p_dst);
1038
append(p_global);
1039
}
1040
1041
void GDScriptByteCodeGenerator::write_cast(const Address &p_target, const Address &p_source, const GDScriptDataType &p_type) {
1042
int index = 0;
1043
1044
switch (p_type.kind) {
1045
case GDScriptDataType::BUILTIN: {
1046
append_opcode(GDScriptFunction::OPCODE_CAST_TO_BUILTIN);
1047
index = p_type.builtin_type;
1048
} break;
1049
case GDScriptDataType::NATIVE: {
1050
int class_idx = GDScriptLanguage::get_singleton()->get_global_map()[p_type.native_type];
1051
Variant nc = GDScriptLanguage::get_singleton()->get_global_array()[class_idx];
1052
append_opcode(GDScriptFunction::OPCODE_CAST_TO_NATIVE);
1053
index = get_constant_pos(nc) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
1054
} break;
1055
case GDScriptDataType::SCRIPT:
1056
case GDScriptDataType::GDSCRIPT: {
1057
Variant script = p_type.script_type;
1058
int idx = get_constant_pos(script) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
1059
append_opcode(GDScriptFunction::OPCODE_CAST_TO_SCRIPT);
1060
index = idx;
1061
} break;
1062
default: {
1063
return;
1064
}
1065
}
1066
1067
append(p_source);
1068
append(p_target);
1069
append(index);
1070
}
1071
1072
GDScriptByteCodeGenerator::CallTarget GDScriptByteCodeGenerator::get_call_target(const GDScriptCodeGenerator::Address &p_target, Variant::Type p_type) {
1073
if (p_target.mode == Address::NIL) {
1074
GDScriptDataType type;
1075
if (p_type != Variant::NIL) {
1076
type.kind = GDScriptDataType::BUILTIN;
1077
type.builtin_type = p_type;
1078
}
1079
uint32_t addr = add_temporary(type);
1080
return CallTarget(Address(Address::TEMPORARY, addr, type), true, this);
1081
} else {
1082
return CallTarget(p_target, false, this);
1083
}
1084
}
1085
1086
void GDScriptByteCodeGenerator::write_call(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) {
1087
append_opcode_and_argcount(p_target.mode == Address::NIL ? GDScriptFunction::OPCODE_CALL : GDScriptFunction::OPCODE_CALL_RETURN, 2 + p_arguments.size());
1088
for (int i = 0; i < p_arguments.size(); i++) {
1089
append(p_arguments[i]);
1090
}
1091
append(p_base);
1092
CallTarget ct = get_call_target(p_target);
1093
append(ct.target);
1094
append(p_arguments.size());
1095
append(p_function_name);
1096
ct.cleanup();
1097
}
1098
1099
void GDScriptByteCodeGenerator::write_super_call(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) {
1100
append_opcode_and_argcount(GDScriptFunction::OPCODE_CALL_SELF_BASE, 1 + p_arguments.size());
1101
for (int i = 0; i < p_arguments.size(); i++) {
1102
append(p_arguments[i]);
1103
}
1104
CallTarget ct = get_call_target(p_target);
1105
append(ct.target);
1106
append(p_arguments.size());
1107
append(p_function_name);
1108
ct.cleanup();
1109
}
1110
1111
void GDScriptByteCodeGenerator::write_call_async(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) {
1112
append_opcode_and_argcount(GDScriptFunction::OPCODE_CALL_ASYNC, 2 + p_arguments.size());
1113
for (int i = 0; i < p_arguments.size(); i++) {
1114
append(p_arguments[i]);
1115
}
1116
append(p_base);
1117
CallTarget ct = get_call_target(p_target);
1118
append(ct.target);
1119
append(p_arguments.size());
1120
append(p_function_name);
1121
ct.cleanup();
1122
}
1123
1124
void GDScriptByteCodeGenerator::write_call_gdscript_utility(const Address &p_target, const StringName &p_function, const Vector<Address> &p_arguments) {
1125
append_opcode_and_argcount(GDScriptFunction::OPCODE_CALL_GDSCRIPT_UTILITY, 1 + p_arguments.size());
1126
GDScriptUtilityFunctions::FunctionPtr gds_function = GDScriptUtilityFunctions::get_function(p_function);
1127
for (int i = 0; i < p_arguments.size(); i++) {
1128
append(p_arguments[i]);
1129
}
1130
CallTarget ct = get_call_target(p_target);
1131
append(ct.target);
1132
append(p_arguments.size());
1133
append(gds_function);
1134
ct.cleanup();
1135
#ifdef DEBUG_ENABLED
1136
add_debug_name(gds_utilities_names, get_gds_utility_pos(gds_function), p_function);
1137
#endif
1138
}
1139
1140
void GDScriptByteCodeGenerator::write_call_utility(const Address &p_target, const StringName &p_function, const Vector<Address> &p_arguments) {
1141
bool is_validated = true;
1142
if (Variant::is_utility_function_vararg(p_function)) {
1143
is_validated = false; // Vararg needs runtime checks, can't use validated call.
1144
} else if (p_arguments.size() == Variant::get_utility_function_argument_count(p_function)) {
1145
bool all_types_exact = true;
1146
for (int i = 0; i < p_arguments.size(); i++) {
1147
if (!IS_BUILTIN_TYPE(p_arguments[i], Variant::get_utility_function_argument_type(p_function, i))) {
1148
all_types_exact = false;
1149
break;
1150
}
1151
}
1152
1153
is_validated = all_types_exact;
1154
}
1155
1156
if (is_validated) {
1157
Variant::Type result_type = Variant::has_utility_function_return_value(p_function) ? Variant::get_utility_function_return_type(p_function) : Variant::NIL;
1158
CallTarget ct = get_call_target(p_target, result_type);
1159
Variant::Type temp_type = temporaries[ct.target.address].type;
1160
if (result_type != temp_type) {
1161
write_type_adjust(ct.target, result_type);
1162
}
1163
append_opcode_and_argcount(GDScriptFunction::OPCODE_CALL_UTILITY_VALIDATED, 1 + p_arguments.size());
1164
for (int i = 0; i < p_arguments.size(); i++) {
1165
append(p_arguments[i]);
1166
}
1167
append(ct.target);
1168
append(p_arguments.size());
1169
append(Variant::get_validated_utility_function(p_function));
1170
ct.cleanup();
1171
#ifdef DEBUG_ENABLED
1172
add_debug_name(utilities_names, get_utility_pos(Variant::get_validated_utility_function(p_function)), p_function);
1173
#endif
1174
} else {
1175
append_opcode_and_argcount(GDScriptFunction::OPCODE_CALL_UTILITY, 1 + p_arguments.size());
1176
for (int i = 0; i < p_arguments.size(); i++) {
1177
append(p_arguments[i]);
1178
}
1179
CallTarget ct = get_call_target(p_target);
1180
append(ct.target);
1181
append(p_arguments.size());
1182
append(p_function);
1183
ct.cleanup();
1184
}
1185
}
1186
1187
void 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) {
1188
bool is_validated = false;
1189
1190
// Check if all types are correct.
1191
if (Variant::is_builtin_method_vararg(p_type, p_method)) {
1192
is_validated = false; // Vararg needs runtime checks, can't use validated call.
1193
} else if (p_arguments.size() == Variant::get_builtin_method_argument_count(p_type, p_method)) {
1194
bool all_types_exact = true;
1195
for (int i = 0; i < p_arguments.size(); i++) {
1196
if (!IS_BUILTIN_TYPE(p_arguments[i], Variant::get_builtin_method_argument_type(p_type, p_method, i))) {
1197
all_types_exact = false;
1198
break;
1199
}
1200
}
1201
1202
is_validated = all_types_exact;
1203
}
1204
1205
if (!is_validated) {
1206
// Perform regular call.
1207
if (p_is_static) {
1208
append_opcode_and_argcount(GDScriptFunction::OPCODE_CALL_BUILTIN_STATIC, p_arguments.size() + 1);
1209
for (int i = 0; i < p_arguments.size(); i++) {
1210
append(p_arguments[i]);
1211
}
1212
CallTarget ct = get_call_target(p_target);
1213
append(ct.target);
1214
append(p_type);
1215
append(p_method);
1216
append(p_arguments.size());
1217
ct.cleanup();
1218
} else {
1219
write_call(p_target, p_base, p_method, p_arguments);
1220
}
1221
return;
1222
}
1223
1224
Variant::Type result_type = Variant::get_builtin_method_return_type(p_type, p_method);
1225
CallTarget ct = get_call_target(p_target, result_type);
1226
Variant::Type temp_type = temporaries[ct.target.address].type;
1227
if (result_type != temp_type) {
1228
write_type_adjust(ct.target, result_type);
1229
}
1230
1231
append_opcode_and_argcount(GDScriptFunction::OPCODE_CALL_BUILTIN_TYPE_VALIDATED, 2 + p_arguments.size());
1232
1233
for (int i = 0; i < p_arguments.size(); i++) {
1234
append(p_arguments[i]);
1235
}
1236
append(p_base);
1237
append(ct.target);
1238
append(p_arguments.size());
1239
append(Variant::get_validated_builtin_method(p_type, p_method));
1240
ct.cleanup();
1241
1242
#ifdef DEBUG_ENABLED
1243
add_debug_name(builtin_methods_names, get_builtin_method_pos(Variant::get_validated_builtin_method(p_type, p_method)), p_method);
1244
#endif
1245
}
1246
1247
void 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) {
1248
write_call_builtin_type(p_target, p_base, p_type, p_method, false, p_arguments);
1249
}
1250
1251
void GDScriptByteCodeGenerator::write_call_builtin_type_static(const Address &p_target, Variant::Type p_type, const StringName &p_method, const Vector<Address> &p_arguments) {
1252
write_call_builtin_type(p_target, Address(), p_type, p_method, true, p_arguments);
1253
}
1254
1255
void GDScriptByteCodeGenerator::write_call_native_static(const Address &p_target, const StringName &p_class, const StringName &p_method, const Vector<Address> &p_arguments) {
1256
MethodBind *method = ClassDB::get_method(p_class, p_method);
1257
1258
// Perform regular call.
1259
append_opcode_and_argcount(GDScriptFunction::OPCODE_CALL_NATIVE_STATIC, p_arguments.size() + 1);
1260
for (int i = 0; i < p_arguments.size(); i++) {
1261
append(p_arguments[i]);
1262
}
1263
CallTarget ct = get_call_target(p_target);
1264
append(ct.target);
1265
append(method);
1266
append(p_arguments.size());
1267
ct.cleanup();
1268
return;
1269
}
1270
1271
void GDScriptByteCodeGenerator::write_call_native_static_validated(const GDScriptCodeGenerator::Address &p_target, MethodBind *p_method, const Vector<GDScriptCodeGenerator::Address> &p_arguments) {
1272
Variant::Type return_type = Variant::NIL;
1273
bool has_return = p_method->has_return();
1274
1275
if (has_return) {
1276
PropertyInfo return_info = p_method->get_return_info();
1277
return_type = return_info.type;
1278
}
1279
1280
CallTarget ct = get_call_target(p_target, return_type);
1281
1282
if (has_return) {
1283
Variant::Type temp_type = temporaries[ct.target.address].type;
1284
if (temp_type != return_type) {
1285
write_type_adjust(ct.target, return_type);
1286
}
1287
}
1288
1289
GDScriptFunction::Opcode code = p_method->has_return() ? GDScriptFunction::OPCODE_CALL_NATIVE_STATIC_VALIDATED_RETURN : GDScriptFunction::OPCODE_CALL_NATIVE_STATIC_VALIDATED_NO_RETURN;
1290
append_opcode_and_argcount(code, 1 + p_arguments.size());
1291
1292
for (int i = 0; i < p_arguments.size(); i++) {
1293
append(p_arguments[i]);
1294
}
1295
append(ct.target);
1296
append(p_arguments.size());
1297
append(p_method);
1298
ct.cleanup();
1299
}
1300
1301
void GDScriptByteCodeGenerator::write_call_method_bind(const Address &p_target, const Address &p_base, MethodBind *p_method, const Vector<Address> &p_arguments) {
1302
append_opcode_and_argcount(p_target.mode == Address::NIL ? GDScriptFunction::OPCODE_CALL_METHOD_BIND : GDScriptFunction::OPCODE_CALL_METHOD_BIND_RET, 2 + p_arguments.size());
1303
for (int i = 0; i < p_arguments.size(); i++) {
1304
append(p_arguments[i]);
1305
}
1306
CallTarget ct = get_call_target(p_target);
1307
append(p_base);
1308
append(ct.target);
1309
append(p_arguments.size());
1310
append(p_method);
1311
ct.cleanup();
1312
}
1313
1314
void GDScriptByteCodeGenerator::write_call_method_bind_validated(const Address &p_target, const Address &p_base, MethodBind *p_method, const Vector<Address> &p_arguments) {
1315
Variant::Type return_type = Variant::NIL;
1316
bool has_return = p_method->has_return();
1317
1318
if (has_return) {
1319
PropertyInfo return_info = p_method->get_return_info();
1320
return_type = return_info.type;
1321
}
1322
1323
CallTarget ct = get_call_target(p_target, return_type);
1324
1325
if (has_return) {
1326
Variant::Type temp_type = temporaries[ct.target.address].type;
1327
if (temp_type != return_type) {
1328
write_type_adjust(ct.target, return_type);
1329
}
1330
}
1331
1332
GDScriptFunction::Opcode code = p_method->has_return() ? GDScriptFunction::OPCODE_CALL_METHOD_BIND_VALIDATED_RETURN : GDScriptFunction::OPCODE_CALL_METHOD_BIND_VALIDATED_NO_RETURN;
1333
append_opcode_and_argcount(code, 2 + p_arguments.size());
1334
1335
for (int i = 0; i < p_arguments.size(); i++) {
1336
append(p_arguments[i]);
1337
}
1338
append(p_base);
1339
append(ct.target);
1340
append(p_arguments.size());
1341
append(p_method);
1342
ct.cleanup();
1343
}
1344
1345
void GDScriptByteCodeGenerator::write_call_self(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) {
1346
append_opcode_and_argcount(p_target.mode == Address::NIL ? GDScriptFunction::OPCODE_CALL : GDScriptFunction::OPCODE_CALL_RETURN, 2 + p_arguments.size());
1347
for (int i = 0; i < p_arguments.size(); i++) {
1348
append(p_arguments[i]);
1349
}
1350
append(GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
1351
CallTarget ct = get_call_target(p_target);
1352
append(ct.target);
1353
append(p_arguments.size());
1354
append(p_function_name);
1355
ct.cleanup();
1356
}
1357
1358
void GDScriptByteCodeGenerator::write_call_self_async(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) {
1359
append_opcode_and_argcount(GDScriptFunction::OPCODE_CALL_ASYNC, 2 + p_arguments.size());
1360
for (int i = 0; i < p_arguments.size(); i++) {
1361
append(p_arguments[i]);
1362
}
1363
append(GDScriptFunction::ADDR_SELF);
1364
CallTarget ct = get_call_target(p_target);
1365
append(ct.target);
1366
append(p_arguments.size());
1367
append(p_function_name);
1368
ct.cleanup();
1369
}
1370
1371
void GDScriptByteCodeGenerator::write_call_script_function(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) {
1372
append_opcode_and_argcount(p_target.mode == Address::NIL ? GDScriptFunction::OPCODE_CALL : GDScriptFunction::OPCODE_CALL_RETURN, 2 + p_arguments.size());
1373
for (int i = 0; i < p_arguments.size(); i++) {
1374
append(p_arguments[i]);
1375
}
1376
append(p_base);
1377
CallTarget ct = get_call_target(p_target);
1378
append(ct.target);
1379
append(p_arguments.size());
1380
append(p_function_name);
1381
ct.cleanup();
1382
}
1383
1384
void GDScriptByteCodeGenerator::write_lambda(const Address &p_target, GDScriptFunction *p_function, const Vector<Address> &p_captures, bool p_use_self) {
1385
append_opcode_and_argcount(p_use_self ? GDScriptFunction::OPCODE_CREATE_SELF_LAMBDA : GDScriptFunction::OPCODE_CREATE_LAMBDA, 1 + p_captures.size());
1386
for (int i = 0; i < p_captures.size(); i++) {
1387
append(p_captures[i]);
1388
}
1389
1390
CallTarget ct = get_call_target(p_target);
1391
append(ct.target);
1392
append(p_captures.size());
1393
append(p_function);
1394
ct.cleanup();
1395
}
1396
1397
void GDScriptByteCodeGenerator::write_construct(const Address &p_target, Variant::Type p_type, const Vector<Address> &p_arguments) {
1398
// Try to find an appropriate constructor.
1399
bool all_have_type = true;
1400
Vector<Variant::Type> arg_types;
1401
for (int i = 0; i < p_arguments.size(); i++) {
1402
if (!HAS_BUILTIN_TYPE(p_arguments[i])) {
1403
all_have_type = false;
1404
break;
1405
}
1406
arg_types.push_back(p_arguments[i].type.builtin_type);
1407
}
1408
if (all_have_type) {
1409
int valid_constructor = -1;
1410
for (int i = 0; i < Variant::get_constructor_count(p_type); i++) {
1411
if (Variant::get_constructor_argument_count(p_type, i) != p_arguments.size()) {
1412
continue;
1413
}
1414
int types_correct = true;
1415
for (int j = 0; j < arg_types.size(); j++) {
1416
if (arg_types[j] != Variant::get_constructor_argument_type(p_type, i, j)) {
1417
types_correct = false;
1418
break;
1419
}
1420
}
1421
if (types_correct) {
1422
valid_constructor = i;
1423
break;
1424
}
1425
}
1426
if (valid_constructor >= 0) {
1427
append_opcode_and_argcount(GDScriptFunction::OPCODE_CONSTRUCT_VALIDATED, 1 + p_arguments.size());
1428
for (int i = 0; i < p_arguments.size(); i++) {
1429
append(p_arguments[i]);
1430
}
1431
CallTarget ct = get_call_target(p_target);
1432
append(ct.target);
1433
append(p_arguments.size());
1434
append(Variant::get_validated_constructor(p_type, valid_constructor));
1435
ct.cleanup();
1436
#ifdef DEBUG_ENABLED
1437
add_debug_name(constructors_names, get_constructor_pos(Variant::get_validated_constructor(p_type, valid_constructor)), Variant::get_type_name(p_type));
1438
#endif
1439
return;
1440
}
1441
}
1442
1443
append_opcode_and_argcount(GDScriptFunction::OPCODE_CONSTRUCT, 1 + p_arguments.size());
1444
for (int i = 0; i < p_arguments.size(); i++) {
1445
append(p_arguments[i]);
1446
}
1447
CallTarget ct = get_call_target(p_target);
1448
append(ct.target);
1449
append(p_arguments.size());
1450
append(p_type);
1451
ct.cleanup();
1452
}
1453
1454
void GDScriptByteCodeGenerator::write_construct_array(const Address &p_target, const Vector<Address> &p_arguments) {
1455
append_opcode_and_argcount(GDScriptFunction::OPCODE_CONSTRUCT_ARRAY, 1 + p_arguments.size());
1456
for (int i = 0; i < p_arguments.size(); i++) {
1457
append(p_arguments[i]);
1458
}
1459
CallTarget ct = get_call_target(p_target);
1460
append(ct.target);
1461
append(p_arguments.size());
1462
ct.cleanup();
1463
}
1464
1465
void GDScriptByteCodeGenerator::write_construct_typed_array(const Address &p_target, const GDScriptDataType &p_element_type, const Vector<Address> &p_arguments) {
1466
append_opcode_and_argcount(GDScriptFunction::OPCODE_CONSTRUCT_TYPED_ARRAY, 2 + p_arguments.size());
1467
for (int i = 0; i < p_arguments.size(); i++) {
1468
append(p_arguments[i]);
1469
}
1470
CallTarget ct = get_call_target(p_target);
1471
append(ct.target);
1472
append(get_constant_pos(p_element_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS));
1473
append(p_arguments.size());
1474
append(p_element_type.builtin_type);
1475
append(p_element_type.native_type);
1476
ct.cleanup();
1477
}
1478
1479
void GDScriptByteCodeGenerator::write_construct_dictionary(const Address &p_target, const Vector<Address> &p_arguments) {
1480
append_opcode_and_argcount(GDScriptFunction::OPCODE_CONSTRUCT_DICTIONARY, 1 + p_arguments.size());
1481
for (int i = 0; i < p_arguments.size(); i++) {
1482
append(p_arguments[i]);
1483
}
1484
CallTarget ct = get_call_target(p_target);
1485
append(ct.target);
1486
append(p_arguments.size() / 2); // This is number of key-value pairs, so only half of actual arguments.
1487
ct.cleanup();
1488
}
1489
1490
void GDScriptByteCodeGenerator::write_construct_typed_dictionary(const Address &p_target, const GDScriptDataType &p_key_type, const GDScriptDataType &p_value_type, const Vector<Address> &p_arguments) {
1491
append_opcode_and_argcount(GDScriptFunction::OPCODE_CONSTRUCT_TYPED_DICTIONARY, 3 + p_arguments.size());
1492
for (int i = 0; i < p_arguments.size(); i++) {
1493
append(p_arguments[i]);
1494
}
1495
CallTarget ct = get_call_target(p_target);
1496
append(ct.target);
1497
append(get_constant_pos(p_key_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS));
1498
append(get_constant_pos(p_value_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS));
1499
append(p_arguments.size() / 2); // This is number of key-value pairs, so only half of actual arguments.
1500
append(p_key_type.builtin_type);
1501
append(p_key_type.native_type);
1502
append(p_value_type.builtin_type);
1503
append(p_value_type.native_type);
1504
ct.cleanup();
1505
}
1506
1507
void GDScriptByteCodeGenerator::write_await(const Address &p_target, const Address &p_operand) {
1508
append_opcode(GDScriptFunction::OPCODE_AWAIT);
1509
append(p_operand);
1510
append_opcode(GDScriptFunction::OPCODE_AWAIT_RESUME);
1511
append(p_target);
1512
}
1513
1514
void GDScriptByteCodeGenerator::write_if(const Address &p_condition) {
1515
append_opcode(GDScriptFunction::OPCODE_JUMP_IF_NOT);
1516
append(p_condition);
1517
if_jmp_addrs.push_back(opcodes.size());
1518
append(0); // Jump destination, will be patched.
1519
}
1520
1521
void GDScriptByteCodeGenerator::write_else() {
1522
append_opcode(GDScriptFunction::OPCODE_JUMP); // Jump from true if block;
1523
int else_jmp_addr = opcodes.size();
1524
append(0); // Jump destination, will be patched.
1525
1526
patch_jump(if_jmp_addrs.back()->get());
1527
if_jmp_addrs.pop_back();
1528
if_jmp_addrs.push_back(else_jmp_addr);
1529
}
1530
1531
void GDScriptByteCodeGenerator::write_endif() {
1532
patch_jump(if_jmp_addrs.back()->get());
1533
if_jmp_addrs.pop_back();
1534
}
1535
1536
void GDScriptByteCodeGenerator::write_jump_if_shared(const Address &p_value) {
1537
append_opcode(GDScriptFunction::OPCODE_JUMP_IF_SHARED);
1538
append(p_value);
1539
if_jmp_addrs.push_back(opcodes.size());
1540
append(0); // Jump destination, will be patched.
1541
}
1542
1543
void GDScriptByteCodeGenerator::write_end_jump_if_shared() {
1544
patch_jump(if_jmp_addrs.back()->get());
1545
if_jmp_addrs.pop_back();
1546
}
1547
1548
void GDScriptByteCodeGenerator::start_for(const GDScriptDataType &p_iterator_type, const GDScriptDataType &p_list_type, bool p_is_range) {
1549
Address counter(Address::LOCAL_VARIABLE, add_local("@counter_pos", p_iterator_type), p_iterator_type);
1550
1551
// Store state.
1552
for_counter_variables.push_back(counter);
1553
1554
if (p_is_range) {
1555
GDScriptDataType int_type;
1556
int_type.kind = GDScriptDataType::BUILTIN;
1557
int_type.builtin_type = Variant::INT;
1558
1559
Address range_from(Address::LOCAL_VARIABLE, add_local("@range_from", int_type), int_type);
1560
Address range_to(Address::LOCAL_VARIABLE, add_local("@range_to", int_type), int_type);
1561
Address range_step(Address::LOCAL_VARIABLE, add_local("@range_step", int_type), int_type);
1562
1563
// Store state.
1564
for_range_from_variables.push_back(range_from);
1565
for_range_to_variables.push_back(range_to);
1566
for_range_step_variables.push_back(range_step);
1567
} else {
1568
Address container(Address::LOCAL_VARIABLE, add_local("@container_pos", p_list_type), p_list_type);
1569
1570
// Store state.
1571
for_container_variables.push_back(container);
1572
}
1573
}
1574
1575
void GDScriptByteCodeGenerator::write_for_list_assignment(const Address &p_list) {
1576
const Address &container = for_container_variables.back()->get();
1577
1578
// Assign container.
1579
append_opcode(GDScriptFunction::OPCODE_ASSIGN);
1580
append(container);
1581
append(p_list);
1582
}
1583
1584
void GDScriptByteCodeGenerator::write_for_range_assignment(const Address &p_from, const Address &p_to, const Address &p_step) {
1585
const Address &range_from = for_range_from_variables.back()->get();
1586
const Address &range_to = for_range_to_variables.back()->get();
1587
const Address &range_step = for_range_step_variables.back()->get();
1588
1589
// Assign range args.
1590
if (range_from.type == p_from.type) {
1591
write_assign(range_from, p_from);
1592
} else {
1593
write_assign_with_conversion(range_from, p_from);
1594
}
1595
if (range_to.type == p_to.type) {
1596
write_assign(range_to, p_to);
1597
} else {
1598
write_assign_with_conversion(range_to, p_to);
1599
}
1600
if (range_step.type == p_step.type) {
1601
write_assign(range_step, p_step);
1602
} else {
1603
write_assign_with_conversion(range_step, p_step);
1604
}
1605
}
1606
1607
void GDScriptByteCodeGenerator::write_for(const Address &p_variable, bool p_use_conversion, bool p_is_range) {
1608
const Address &counter = for_counter_variables.back()->get();
1609
const Address &container = p_is_range ? Address() : for_container_variables.back()->get();
1610
const Address &range_from = p_is_range ? for_range_from_variables.back()->get() : Address();
1611
const Address &range_to = p_is_range ? for_range_to_variables.back()->get() : Address();
1612
const Address &range_step = p_is_range ? for_range_step_variables.back()->get() : Address();
1613
1614
current_breaks_to_patch.push_back(List<int>());
1615
1616
GDScriptFunction::Opcode begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN;
1617
GDScriptFunction::Opcode iterate_opcode = GDScriptFunction::OPCODE_ITERATE;
1618
1619
if (p_is_range) {
1620
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_RANGE;
1621
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_RANGE;
1622
} else if (container.type.has_type()) {
1623
if (container.type.kind == GDScriptDataType::BUILTIN) {
1624
switch (container.type.builtin_type) {
1625
case Variant::INT:
1626
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_INT;
1627
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_INT;
1628
break;
1629
case Variant::FLOAT:
1630
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_FLOAT;
1631
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_FLOAT;
1632
break;
1633
case Variant::VECTOR2:
1634
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_VECTOR2;
1635
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_VECTOR2;
1636
break;
1637
case Variant::VECTOR2I:
1638
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_VECTOR2I;
1639
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_VECTOR2I;
1640
break;
1641
case Variant::VECTOR3:
1642
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_VECTOR3;
1643
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_VECTOR3;
1644
break;
1645
case Variant::VECTOR3I:
1646
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_VECTOR3I;
1647
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_VECTOR3I;
1648
break;
1649
case Variant::STRING:
1650
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_STRING;
1651
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_STRING;
1652
break;
1653
case Variant::DICTIONARY:
1654
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_DICTIONARY;
1655
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_DICTIONARY;
1656
break;
1657
case Variant::ARRAY:
1658
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_ARRAY;
1659
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_ARRAY;
1660
break;
1661
case Variant::PACKED_BYTE_ARRAY:
1662
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_PACKED_BYTE_ARRAY;
1663
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_PACKED_BYTE_ARRAY;
1664
break;
1665
case Variant::PACKED_INT32_ARRAY:
1666
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_PACKED_INT32_ARRAY;
1667
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_PACKED_INT32_ARRAY;
1668
break;
1669
case Variant::PACKED_INT64_ARRAY:
1670
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_PACKED_INT64_ARRAY;
1671
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_PACKED_INT64_ARRAY;
1672
break;
1673
case Variant::PACKED_FLOAT32_ARRAY:
1674
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_PACKED_FLOAT32_ARRAY;
1675
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_PACKED_FLOAT32_ARRAY;
1676
break;
1677
case Variant::PACKED_FLOAT64_ARRAY:
1678
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_PACKED_FLOAT64_ARRAY;
1679
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_PACKED_FLOAT64_ARRAY;
1680
break;
1681
case Variant::PACKED_STRING_ARRAY:
1682
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_PACKED_STRING_ARRAY;
1683
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_PACKED_STRING_ARRAY;
1684
break;
1685
case Variant::PACKED_VECTOR2_ARRAY:
1686
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_PACKED_VECTOR2_ARRAY;
1687
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_PACKED_VECTOR2_ARRAY;
1688
break;
1689
case Variant::PACKED_VECTOR3_ARRAY:
1690
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_PACKED_VECTOR3_ARRAY;
1691
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_PACKED_VECTOR3_ARRAY;
1692
break;
1693
case Variant::PACKED_COLOR_ARRAY:
1694
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_PACKED_COLOR_ARRAY;
1695
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_PACKED_COLOR_ARRAY;
1696
break;
1697
case Variant::PACKED_VECTOR4_ARRAY:
1698
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_PACKED_VECTOR4_ARRAY;
1699
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_PACKED_VECTOR4_ARRAY;
1700
break;
1701
default:
1702
break;
1703
}
1704
} else {
1705
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_OBJECT;
1706
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_OBJECT;
1707
}
1708
}
1709
1710
Address temp;
1711
if (p_use_conversion) {
1712
temp = Address(Address::LOCAL_VARIABLE, add_local("@iterator_temp", GDScriptDataType()));
1713
}
1714
1715
// Begin loop.
1716
append_opcode(begin_opcode);
1717
append(counter);
1718
if (p_is_range) {
1719
append(range_from);
1720
append(range_to);
1721
append(range_step);
1722
} else {
1723
append(container);
1724
}
1725
append(p_use_conversion ? temp : p_variable);
1726
for_jmp_addrs.push_back(opcodes.size());
1727
append(0); // End of loop address, will be patched.
1728
append_opcode(GDScriptFunction::OPCODE_JUMP);
1729
append(opcodes.size() + (p_is_range ? 7 : 6)); // Skip over 'continue' code.
1730
1731
// Next iteration.
1732
int continue_addr = opcodes.size();
1733
continue_addrs.push_back(continue_addr);
1734
append_opcode(iterate_opcode);
1735
append(counter);
1736
if (p_is_range) {
1737
append(range_to);
1738
append(range_step);
1739
} else {
1740
append(container);
1741
}
1742
append(p_use_conversion ? temp : p_variable);
1743
for_jmp_addrs.push_back(opcodes.size());
1744
append(0); // Jump destination, will be patched.
1745
1746
if (p_use_conversion) {
1747
write_assign_with_conversion(p_variable, temp);
1748
if (p_variable.type.can_contain_object()) {
1749
clear_address(temp); // Can contain `RefCounted`, so clear it.
1750
}
1751
}
1752
}
1753
1754
void GDScriptByteCodeGenerator::write_endfor(bool p_is_range) {
1755
// Jump back to loop check.
1756
append_opcode(GDScriptFunction::OPCODE_JUMP);
1757
append(continue_addrs.back()->get());
1758
continue_addrs.pop_back();
1759
1760
// Patch end jumps (two of them).
1761
for (int i = 0; i < 2; i++) {
1762
patch_jump(for_jmp_addrs.back()->get());
1763
for_jmp_addrs.pop_back();
1764
}
1765
1766
// Patch break statements.
1767
for (const int &E : current_breaks_to_patch.back()->get()) {
1768
patch_jump(E);
1769
}
1770
current_breaks_to_patch.pop_back();
1771
1772
// Pop state.
1773
for_counter_variables.pop_back();
1774
if (p_is_range) {
1775
for_range_from_variables.pop_back();
1776
for_range_to_variables.pop_back();
1777
for_range_step_variables.pop_back();
1778
} else {
1779
for_container_variables.pop_back();
1780
}
1781
}
1782
1783
void GDScriptByteCodeGenerator::start_while_condition() {
1784
current_breaks_to_patch.push_back(List<int>());
1785
continue_addrs.push_back(opcodes.size());
1786
}
1787
1788
void GDScriptByteCodeGenerator::write_while(const Address &p_condition) {
1789
// Condition check.
1790
append_opcode(GDScriptFunction::OPCODE_JUMP_IF_NOT);
1791
append(p_condition);
1792
while_jmp_addrs.push_back(opcodes.size());
1793
append(0); // End of loop address, will be patched.
1794
}
1795
1796
void GDScriptByteCodeGenerator::write_endwhile() {
1797
// Jump back to loop check.
1798
append_opcode(GDScriptFunction::OPCODE_JUMP);
1799
append(continue_addrs.back()->get());
1800
continue_addrs.pop_back();
1801
1802
// Patch end jump.
1803
patch_jump(while_jmp_addrs.back()->get());
1804
while_jmp_addrs.pop_back();
1805
1806
// Patch break statements.
1807
for (const int &E : current_breaks_to_patch.back()->get()) {
1808
patch_jump(E);
1809
}
1810
current_breaks_to_patch.pop_back();
1811
}
1812
1813
void GDScriptByteCodeGenerator::write_break() {
1814
append_opcode(GDScriptFunction::OPCODE_JUMP);
1815
current_breaks_to_patch.back()->get().push_back(opcodes.size());
1816
append(0);
1817
}
1818
1819
void GDScriptByteCodeGenerator::write_continue() {
1820
append_opcode(GDScriptFunction::OPCODE_JUMP);
1821
append(continue_addrs.back()->get());
1822
}
1823
1824
void GDScriptByteCodeGenerator::write_breakpoint() {
1825
append_opcode(GDScriptFunction::OPCODE_BREAKPOINT);
1826
}
1827
1828
void GDScriptByteCodeGenerator::write_newline(int p_line) {
1829
if (GDScriptLanguage::get_singleton()->should_track_call_stack()) {
1830
// Add newline for debugger and stack tracking if enabled in the project settings.
1831
append_opcode(GDScriptFunction::OPCODE_LINE);
1832
append(p_line);
1833
current_line = p_line;
1834
}
1835
}
1836
1837
void GDScriptByteCodeGenerator::write_return(const Address &p_return_value) {
1838
if (!function->return_type.has_type() || p_return_value.type.has_type()) {
1839
// Either the function is untyped or the return value is also typed.
1840
1841
// If this is a typed function, then we need to check for potential conversions.
1842
if (function->return_type.has_type()) {
1843
if (function->return_type.kind == GDScriptDataType::BUILTIN && function->return_type.builtin_type == Variant::ARRAY && function->return_type.has_container_element_type(0)) {
1844
// Typed array.
1845
const GDScriptDataType &element_type = function->return_type.get_container_element_type(0);
1846
append_opcode(GDScriptFunction::OPCODE_RETURN_TYPED_ARRAY);
1847
append(p_return_value);
1848
append(get_constant_pos(element_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS));
1849
append(element_type.builtin_type);
1850
append(element_type.native_type);
1851
} else if (function->return_type.kind == GDScriptDataType::BUILTIN && function->return_type.builtin_type == Variant::DICTIONARY &&
1852
function->return_type.has_container_element_types()) {
1853
// Typed dictionary.
1854
const GDScriptDataType &key_type = function->return_type.get_container_element_type_or_variant(0);
1855
const GDScriptDataType &value_type = function->return_type.get_container_element_type_or_variant(1);
1856
append_opcode(GDScriptFunction::OPCODE_RETURN_TYPED_DICTIONARY);
1857
append(p_return_value);
1858
append(get_constant_pos(key_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS));
1859
append(get_constant_pos(value_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS));
1860
append(key_type.builtin_type);
1861
append(key_type.native_type);
1862
append(value_type.builtin_type);
1863
append(value_type.native_type);
1864
} 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) {
1865
// Add conversion.
1866
append_opcode(GDScriptFunction::OPCODE_RETURN_TYPED_BUILTIN);
1867
append(p_return_value);
1868
append(function->return_type.builtin_type);
1869
} else {
1870
// Just assign.
1871
append_opcode(GDScriptFunction::OPCODE_RETURN);
1872
append(p_return_value);
1873
}
1874
} else {
1875
append_opcode(GDScriptFunction::OPCODE_RETURN);
1876
append(p_return_value);
1877
}
1878
} else {
1879
switch (function->return_type.kind) {
1880
case GDScriptDataType::BUILTIN: {
1881
if (function->return_type.builtin_type == Variant::ARRAY && function->return_type.has_container_element_type(0)) {
1882
const GDScriptDataType &element_type = function->return_type.get_container_element_type(0);
1883
append_opcode(GDScriptFunction::OPCODE_RETURN_TYPED_ARRAY);
1884
append(p_return_value);
1885
append(get_constant_pos(element_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS));
1886
append(element_type.builtin_type);
1887
append(element_type.native_type);
1888
} else if (function->return_type.builtin_type == Variant::DICTIONARY && function->return_type.has_container_element_types()) {
1889
const GDScriptDataType &key_type = function->return_type.get_container_element_type_or_variant(0);
1890
const GDScriptDataType &value_type = function->return_type.get_container_element_type_or_variant(1);
1891
append_opcode(GDScriptFunction::OPCODE_RETURN_TYPED_DICTIONARY);
1892
append(p_return_value);
1893
append(get_constant_pos(key_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS));
1894
append(get_constant_pos(value_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS));
1895
append(key_type.builtin_type);
1896
append(key_type.native_type);
1897
append(value_type.builtin_type);
1898
append(value_type.native_type);
1899
} else {
1900
append_opcode(GDScriptFunction::OPCODE_RETURN_TYPED_BUILTIN);
1901
append(p_return_value);
1902
append(function->return_type.builtin_type);
1903
}
1904
} break;
1905
case GDScriptDataType::NATIVE: {
1906
append_opcode(GDScriptFunction::OPCODE_RETURN_TYPED_NATIVE);
1907
append(p_return_value);
1908
int class_idx = GDScriptLanguage::get_singleton()->get_global_map()[function->return_type.native_type];
1909
Variant nc = GDScriptLanguage::get_singleton()->get_global_array()[class_idx];
1910
class_idx = get_constant_pos(nc) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
1911
append(class_idx);
1912
} break;
1913
case GDScriptDataType::GDSCRIPT:
1914
case GDScriptDataType::SCRIPT: {
1915
Variant script = function->return_type.script_type;
1916
int script_idx = get_constant_pos(script) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
1917
1918
append_opcode(GDScriptFunction::OPCODE_RETURN_TYPED_SCRIPT);
1919
append(p_return_value);
1920
append(script_idx);
1921
} break;
1922
default: {
1923
ERR_PRINT("Compiler bug: unresolved return.");
1924
1925
// Shouldn't get here, but fail-safe to a regular return;
1926
append_opcode(GDScriptFunction::OPCODE_RETURN);
1927
append(p_return_value);
1928
} break;
1929
}
1930
}
1931
}
1932
1933
void GDScriptByteCodeGenerator::write_assert(const Address &p_test, const Address &p_message) {
1934
append_opcode(GDScriptFunction::OPCODE_ASSERT);
1935
append(p_test);
1936
append(p_message);
1937
}
1938
1939
void GDScriptByteCodeGenerator::start_block() {
1940
push_stack_identifiers();
1941
}
1942
1943
void GDScriptByteCodeGenerator::end_block() {
1944
pop_stack_identifiers();
1945
}
1946
1947
void GDScriptByteCodeGenerator::clear_temporaries() {
1948
for (int slot_idx : temporaries_pending_clear) {
1949
// The temporary may have been reused as something else since it was added to the list.
1950
// In that case, there's **no** need to clear it.
1951
if (temporaries[slot_idx].can_contain_object) {
1952
clear_address(Address(Address::TEMPORARY, slot_idx)); // Can contain `RefCounted`, so clear it.
1953
}
1954
}
1955
temporaries_pending_clear.clear();
1956
}
1957
1958
void GDScriptByteCodeGenerator::clear_address(const Address &p_address) {
1959
// Do not check `is_local_dirty()` here! Always clear the address since the codegen doesn't track the compiler.
1960
// Also, this method is used to initialize local variables of built-in types, since they cannot be `null`.
1961
1962
if (p_address.type.kind == GDScriptDataType::BUILTIN) {
1963
switch (p_address.type.builtin_type) {
1964
case Variant::BOOL:
1965
write_assign_false(p_address);
1966
break;
1967
case Variant::DICTIONARY:
1968
if (p_address.type.has_container_element_types()) {
1969
write_construct_typed_dictionary(p_address, p_address.type.get_container_element_type_or_variant(0), p_address.type.get_container_element_type_or_variant(1), Vector<GDScriptCodeGenerator::Address>());
1970
} else {
1971
write_construct(p_address, p_address.type.builtin_type, Vector<GDScriptCodeGenerator::Address>());
1972
}
1973
break;
1974
case Variant::ARRAY:
1975
if (p_address.type.has_container_element_type(0)) {
1976
write_construct_typed_array(p_address, p_address.type.get_container_element_type(0), Vector<GDScriptCodeGenerator::Address>());
1977
} else {
1978
write_construct(p_address, p_address.type.builtin_type, Vector<GDScriptCodeGenerator::Address>());
1979
}
1980
break;
1981
case Variant::NIL:
1982
case Variant::OBJECT:
1983
write_assign_null(p_address);
1984
break;
1985
default:
1986
write_construct(p_address, p_address.type.builtin_type, Vector<GDScriptCodeGenerator::Address>());
1987
break;
1988
}
1989
} else {
1990
write_assign_null(p_address);
1991
}
1992
1993
if (p_address.mode == Address::LOCAL_VARIABLE) {
1994
dirty_locals.erase(p_address.address);
1995
}
1996
}
1997
1998
// Returns `true` if the local has been reused and not cleaned up with `clear_address()`.
1999
bool GDScriptByteCodeGenerator::is_local_dirty(const Address &p_address) const {
2000
ERR_FAIL_COND_V(p_address.mode != Address::LOCAL_VARIABLE, false);
2001
return dirty_locals.has(p_address.address);
2002
}
2003
2004
GDScriptByteCodeGenerator::~GDScriptByteCodeGenerator() {
2005
if (!ended && function != nullptr) {
2006
memdelete(function);
2007
}
2008
}
2009
2010