Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/modules/gdscript/gdscript_disassembler.cpp
10278 views
1
/**************************************************************************/
2
/* gdscript_disassembler.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
#ifdef DEBUG_ENABLED
32
33
#include "gdscript.h"
34
#include "gdscript_function.h"
35
36
#include "core/string/string_builder.h"
37
38
static String _get_variant_string(const Variant &p_variant) {
39
String txt;
40
if (p_variant.get_type() == Variant::STRING) {
41
txt = "\"" + String(p_variant) + "\"";
42
} else if (p_variant.get_type() == Variant::STRING_NAME) {
43
txt = "&\"" + String(p_variant) + "\"";
44
} else if (p_variant.get_type() == Variant::NODE_PATH) {
45
txt = "^\"" + String(p_variant) + "\"";
46
} else if (p_variant.get_type() == Variant::OBJECT) {
47
Object *obj = p_variant;
48
if (!obj) {
49
txt = "null";
50
} else {
51
GDScriptNativeClass *cls = Object::cast_to<GDScriptNativeClass>(obj);
52
if (cls) {
53
txt = "class(" + cls->get_name() + ")";
54
} else {
55
Script *script = Object::cast_to<Script>(obj);
56
if (script) {
57
txt = "script(" + GDScript::debug_get_script_name(script) + ")";
58
} else {
59
txt = "object(" + obj->get_class();
60
if (obj->get_script_instance()) {
61
txt += ", " + GDScript::debug_get_script_name(obj->get_script_instance()->get_script());
62
}
63
txt += ")";
64
}
65
}
66
}
67
} else {
68
txt = p_variant;
69
}
70
return txt;
71
}
72
73
static String _disassemble_address(const GDScript *p_script, const GDScriptFunction &p_function, int p_address) {
74
int addr = p_address & GDScriptFunction::ADDR_MASK;
75
76
switch (p_address >> GDScriptFunction::ADDR_BITS) {
77
case GDScriptFunction::ADDR_TYPE_STACK: {
78
switch (addr) {
79
case GDScriptFunction::ADDR_STACK_SELF:
80
return "self";
81
case GDScriptFunction::ADDR_STACK_CLASS:
82
return "class";
83
case GDScriptFunction::ADDR_STACK_NIL:
84
return "nil";
85
default:
86
return "stack(" + itos(addr) + ")";
87
}
88
} break;
89
case GDScriptFunction::ADDR_TYPE_CONSTANT: {
90
return "const(" + _get_variant_string(p_function.get_constant(addr)) + ")";
91
} break;
92
case GDScriptFunction::ADDR_TYPE_MEMBER: {
93
return "member(" + p_script->debug_get_member_by_index(addr) + ")";
94
} break;
95
}
96
97
return "<err>";
98
}
99
100
void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
101
#define DADDR(m_ip) (_disassemble_address(_script, *this, _code_ptr[ip + m_ip]))
102
103
for (int ip = 0; ip < _code_size;) {
104
StringBuilder text;
105
int incr = 0;
106
107
text += " ";
108
text += itos(ip);
109
text += ": ";
110
111
// This makes the compiler complain if some opcode is unchecked in the switch.
112
Opcode opcode = Opcode(_code_ptr[ip]);
113
114
switch (opcode) {
115
case OPCODE_OPERATOR: {
116
constexpr int _pointer_size = sizeof(Variant::ValidatedOperatorEvaluator) / sizeof(*_code_ptr);
117
int operation = _code_ptr[ip + 4];
118
119
text += "operator ";
120
121
text += DADDR(3);
122
text += " = ";
123
text += DADDR(1);
124
text += " ";
125
text += Variant::get_operator_name(Variant::Operator(operation));
126
text += " ";
127
text += DADDR(2);
128
129
incr += 7 + _pointer_size;
130
} break;
131
case OPCODE_OPERATOR_VALIDATED: {
132
text += "validated operator ";
133
134
text += DADDR(3);
135
text += " = ";
136
text += DADDR(1);
137
text += " ";
138
text += operator_names[_code_ptr[ip + 4]];
139
text += " ";
140
text += DADDR(2);
141
142
incr += 5;
143
} break;
144
case OPCODE_TYPE_TEST_BUILTIN: {
145
text += "type test ";
146
text += DADDR(1);
147
text += " = ";
148
text += DADDR(2);
149
text += " is ";
150
text += Variant::get_type_name(Variant::Type(_code_ptr[ip + 3]));
151
152
incr += 4;
153
} break;
154
case OPCODE_TYPE_TEST_ARRAY: {
155
text += "type test ";
156
text += DADDR(1);
157
text += " = ";
158
text += DADDR(2);
159
text += " is Array[";
160
161
Ref<Script> script_type = get_constant(_code_ptr[ip + 3] & ADDR_MASK);
162
Variant::Type builtin_type = (Variant::Type)_code_ptr[ip + 4];
163
StringName native_type = get_global_name(_code_ptr[ip + 5]);
164
165
if (script_type.is_valid() && script_type->is_valid()) {
166
text += "script(";
167
text += GDScript::debug_get_script_name(script_type);
168
text += ")";
169
} else if (native_type != StringName()) {
170
text += native_type;
171
} else {
172
text += Variant::get_type_name(builtin_type);
173
}
174
175
text += "]";
176
177
incr += 6;
178
} break;
179
case OPCODE_TYPE_TEST_DICTIONARY: {
180
text += "type test ";
181
text += DADDR(1);
182
text += " = ";
183
text += DADDR(2);
184
text += " is Dictionary[";
185
186
Ref<Script> key_script_type = get_constant(_code_ptr[ip + 3] & ADDR_MASK);
187
Variant::Type key_builtin_type = (Variant::Type)_code_ptr[ip + 5];
188
StringName key_native_type = get_global_name(_code_ptr[ip + 6]);
189
190
if (key_script_type.is_valid() && key_script_type->is_valid()) {
191
text += "script(";
192
text += GDScript::debug_get_script_name(key_script_type);
193
text += ")";
194
} else if (key_native_type != StringName()) {
195
text += key_native_type;
196
} else {
197
text += Variant::get_type_name(key_builtin_type);
198
}
199
200
text += ", ";
201
202
Ref<Script> value_script_type = get_constant(_code_ptr[ip + 4] & ADDR_MASK);
203
Variant::Type value_builtin_type = (Variant::Type)_code_ptr[ip + 7];
204
StringName value_native_type = get_global_name(_code_ptr[ip + 8]);
205
206
if (value_script_type.is_valid() && value_script_type->is_valid()) {
207
text += "script(";
208
text += GDScript::debug_get_script_name(value_script_type);
209
text += ")";
210
} else if (value_native_type != StringName()) {
211
text += value_native_type;
212
} else {
213
text += Variant::get_type_name(value_builtin_type);
214
}
215
216
text += "]";
217
218
incr += 9;
219
} break;
220
case OPCODE_TYPE_TEST_NATIVE: {
221
text += "type test ";
222
text += DADDR(1);
223
text += " = ";
224
text += DADDR(2);
225
text += " is ";
226
text += get_global_name(_code_ptr[ip + 3]);
227
228
incr += 4;
229
} break;
230
case OPCODE_TYPE_TEST_SCRIPT: {
231
text += "type test ";
232
text += DADDR(1);
233
text += " = ";
234
text += DADDR(2);
235
text += " is ";
236
text += DADDR(3);
237
238
incr += 4;
239
} break;
240
case OPCODE_SET_KEYED: {
241
text += "set keyed ";
242
text += DADDR(1);
243
text += "[";
244
text += DADDR(2);
245
text += "] = ";
246
text += DADDR(3);
247
248
incr += 4;
249
} break;
250
case OPCODE_SET_KEYED_VALIDATED: {
251
text += "set keyed validated ";
252
text += DADDR(1);
253
text += "[";
254
text += DADDR(2);
255
text += "] = ";
256
text += DADDR(3);
257
258
incr += 5;
259
} break;
260
case OPCODE_SET_INDEXED_VALIDATED: {
261
text += "set indexed validated ";
262
text += DADDR(1);
263
text += "[";
264
text += DADDR(2);
265
text += "] = ";
266
text += DADDR(3);
267
268
incr += 5;
269
} break;
270
case OPCODE_GET_KEYED: {
271
text += "get keyed ";
272
text += DADDR(3);
273
text += " = ";
274
text += DADDR(1);
275
text += "[";
276
text += DADDR(2);
277
text += "]";
278
279
incr += 4;
280
} break;
281
case OPCODE_GET_KEYED_VALIDATED: {
282
text += "get keyed validated ";
283
text += DADDR(3);
284
text += " = ";
285
text += DADDR(1);
286
text += "[";
287
text += DADDR(2);
288
text += "]";
289
290
incr += 5;
291
} break;
292
case OPCODE_GET_INDEXED_VALIDATED: {
293
text += "get indexed validated ";
294
text += DADDR(3);
295
text += " = ";
296
text += DADDR(1);
297
text += "[";
298
text += DADDR(2);
299
text += "]";
300
301
incr += 5;
302
} break;
303
case OPCODE_SET_NAMED: {
304
text += "set_named ";
305
text += DADDR(1);
306
text += "[\"";
307
text += _global_names_ptr[_code_ptr[ip + 3]];
308
text += "\"] = ";
309
text += DADDR(2);
310
311
incr += 4;
312
} break;
313
case OPCODE_SET_NAMED_VALIDATED: {
314
text += "set_named validated ";
315
text += DADDR(1);
316
text += "[\"";
317
text += setter_names[_code_ptr[ip + 3]];
318
text += "\"] = ";
319
text += DADDR(2);
320
321
incr += 4;
322
} break;
323
case OPCODE_GET_NAMED: {
324
text += "get_named ";
325
text += DADDR(2);
326
text += " = ";
327
text += DADDR(1);
328
text += "[\"";
329
text += _global_names_ptr[_code_ptr[ip + 3]];
330
text += "\"]";
331
332
incr += 4;
333
} break;
334
case OPCODE_GET_NAMED_VALIDATED: {
335
text += "get_named validated ";
336
text += DADDR(2);
337
text += " = ";
338
text += DADDR(1);
339
text += "[\"";
340
text += getter_names[_code_ptr[ip + 3]];
341
text += "\"]";
342
343
incr += 4;
344
} break;
345
case OPCODE_SET_MEMBER: {
346
text += "set_member ";
347
text += "[\"";
348
text += _global_names_ptr[_code_ptr[ip + 2]];
349
text += "\"] = ";
350
text += DADDR(1);
351
352
incr += 3;
353
} break;
354
case OPCODE_GET_MEMBER: {
355
text += "get_member ";
356
text += DADDR(1);
357
text += " = ";
358
text += "[\"";
359
text += _global_names_ptr[_code_ptr[ip + 2]];
360
text += "\"]";
361
362
incr += 3;
363
} break;
364
case OPCODE_SET_STATIC_VARIABLE: {
365
Ref<GDScript> gdscript;
366
if (_code_ptr[ip + 2] == ADDR_CLASS) {
367
gdscript = Ref<GDScript>(_script);
368
} else {
369
gdscript = get_constant(_code_ptr[ip + 2] & ADDR_MASK);
370
}
371
372
text += "set_static_variable script(";
373
text += GDScript::debug_get_script_name(gdscript);
374
text += ")";
375
if (gdscript.is_valid()) {
376
text += "[\"" + gdscript->debug_get_static_var_by_index(_code_ptr[ip + 3]) + "\"]";
377
} else {
378
text += "[<index " + itos(_code_ptr[ip + 3]) + ">]";
379
}
380
text += " = ";
381
text += DADDR(1);
382
383
incr += 4;
384
} break;
385
case OPCODE_GET_STATIC_VARIABLE: {
386
Ref<GDScript> gdscript;
387
if (_code_ptr[ip + 2] == ADDR_CLASS) {
388
gdscript = Ref<GDScript>(_script);
389
} else {
390
gdscript = get_constant(_code_ptr[ip + 2] & ADDR_MASK);
391
}
392
393
text += "get_static_variable ";
394
text += DADDR(1);
395
text += " = script(";
396
text += GDScript::debug_get_script_name(gdscript);
397
text += ")";
398
if (gdscript.is_valid()) {
399
text += "[\"" + gdscript->debug_get_static_var_by_index(_code_ptr[ip + 3]) + "\"]";
400
} else {
401
text += "[<index " + itos(_code_ptr[ip + 3]) + ">]";
402
}
403
404
incr += 4;
405
} break;
406
case OPCODE_ASSIGN: {
407
text += "assign ";
408
text += DADDR(1);
409
text += " = ";
410
text += DADDR(2);
411
412
incr += 3;
413
} break;
414
case OPCODE_ASSIGN_NULL: {
415
text += "assign ";
416
text += DADDR(1);
417
text += " = null";
418
419
incr += 2;
420
} break;
421
case OPCODE_ASSIGN_TRUE: {
422
text += "assign ";
423
text += DADDR(1);
424
text += " = true";
425
426
incr += 2;
427
} break;
428
case OPCODE_ASSIGN_FALSE: {
429
text += "assign ";
430
text += DADDR(1);
431
text += " = false";
432
433
incr += 2;
434
} break;
435
case OPCODE_ASSIGN_TYPED_BUILTIN: {
436
text += "assign typed builtin (";
437
text += Variant::get_type_name((Variant::Type)_code_ptr[ip + 3]);
438
text += ") ";
439
text += DADDR(1);
440
text += " = ";
441
text += DADDR(2);
442
443
incr += 4;
444
} break;
445
case OPCODE_ASSIGN_TYPED_ARRAY: {
446
text += "assign typed array ";
447
text += DADDR(1);
448
text += " = ";
449
text += DADDR(2);
450
451
incr += 6;
452
} break;
453
case OPCODE_ASSIGN_TYPED_DICTIONARY: {
454
text += "assign typed dictionary ";
455
text += DADDR(1);
456
text += " = ";
457
text += DADDR(2);
458
459
incr += 9;
460
} break;
461
case OPCODE_ASSIGN_TYPED_NATIVE: {
462
text += "assign typed native (";
463
text += DADDR(3);
464
text += ") ";
465
text += DADDR(1);
466
text += " = ";
467
text += DADDR(2);
468
469
incr += 4;
470
} break;
471
case OPCODE_ASSIGN_TYPED_SCRIPT: {
472
Ref<Script> script = get_constant(_code_ptr[ip + 3] & ADDR_MASK);
473
474
text += "assign typed script (";
475
text += GDScript::debug_get_script_name(script);
476
text += ") ";
477
text += DADDR(1);
478
text += " = ";
479
text += DADDR(2);
480
481
incr += 4;
482
} break;
483
case OPCODE_CAST_TO_BUILTIN: {
484
text += "cast builtin ";
485
text += DADDR(2);
486
text += " = ";
487
text += DADDR(1);
488
text += " as ";
489
text += Variant::get_type_name(Variant::Type(_code_ptr[ip + 1]));
490
491
incr += 4;
492
} break;
493
case OPCODE_CAST_TO_NATIVE: {
494
text += "cast native ";
495
text += DADDR(2);
496
text += " = ";
497
text += DADDR(1);
498
text += " as ";
499
text += DADDR(3);
500
501
incr += 4;
502
} break;
503
case OPCODE_CAST_TO_SCRIPT: {
504
text += "cast ";
505
text += DADDR(2);
506
text += " = ";
507
text += DADDR(1);
508
text += " as ";
509
text += DADDR(3);
510
511
incr += 4;
512
} break;
513
case OPCODE_CONSTRUCT: {
514
int instr_var_args = _code_ptr[++ip];
515
Variant::Type t = Variant::Type(_code_ptr[ip + 3 + instr_var_args]);
516
int argc = _code_ptr[ip + 1 + instr_var_args];
517
518
text += "construct ";
519
text += DADDR(1 + argc);
520
text += " = ";
521
522
text += Variant::get_type_name(t) + "(";
523
for (int i = 0; i < argc; i++) {
524
if (i > 0) {
525
text += ", ";
526
}
527
text += DADDR(i + 1);
528
}
529
text += ")";
530
531
incr = 3 + instr_var_args;
532
} break;
533
case OPCODE_CONSTRUCT_VALIDATED: {
534
int instr_var_args = _code_ptr[++ip];
535
int argc = _code_ptr[ip + 1 + instr_var_args];
536
537
text += "construct validated ";
538
text += DADDR(1 + argc);
539
text += " = ";
540
541
text += constructors_names[_code_ptr[ip + 3 + argc]];
542
text += "(";
543
for (int i = 0; i < argc; i++) {
544
if (i > 0) {
545
text += ", ";
546
}
547
text += DADDR(i + 1);
548
}
549
text += ")";
550
551
incr = 3 + instr_var_args;
552
} break;
553
case OPCODE_CONSTRUCT_ARRAY: {
554
int instr_var_args = _code_ptr[++ip];
555
int argc = _code_ptr[ip + 1 + instr_var_args];
556
text += "make_array ";
557
text += DADDR(1 + argc);
558
text += " = [";
559
560
for (int i = 0; i < argc; i++) {
561
if (i > 0) {
562
text += ", ";
563
}
564
text += DADDR(1 + i);
565
}
566
567
text += "]";
568
569
incr += 3 + argc;
570
} break;
571
case OPCODE_CONSTRUCT_TYPED_ARRAY: {
572
int instr_var_args = _code_ptr[++ip];
573
int argc = _code_ptr[ip + 1 + instr_var_args];
574
575
Ref<Script> script_type = get_constant(_code_ptr[ip + argc + 2] & ADDR_MASK);
576
Variant::Type builtin_type = (Variant::Type)_code_ptr[ip + argc + 4];
577
StringName native_type = get_global_name(_code_ptr[ip + argc + 5]);
578
579
String type_name;
580
if (script_type.is_valid() && script_type->is_valid()) {
581
type_name = "script(" + GDScript::debug_get_script_name(script_type) + ")";
582
} else if (native_type != StringName()) {
583
type_name = native_type;
584
} else {
585
type_name = Variant::get_type_name(builtin_type);
586
}
587
588
text += "make_typed_array (";
589
text += type_name;
590
text += ") ";
591
592
text += DADDR(1 + argc);
593
text += " = [";
594
595
for (int i = 0; i < argc; i++) {
596
if (i > 0) {
597
text += ", ";
598
}
599
text += DADDR(1 + i);
600
}
601
602
text += "]";
603
604
incr += 6 + argc;
605
} break;
606
case OPCODE_CONSTRUCT_DICTIONARY: {
607
int instr_var_args = _code_ptr[++ip];
608
int argc = _code_ptr[ip + 1 + instr_var_args];
609
text += "make_dict ";
610
text += DADDR(1 + argc * 2);
611
text += " = {";
612
613
for (int i = 0; i < argc; i++) {
614
if (i > 0) {
615
text += ", ";
616
}
617
text += DADDR(1 + i * 2 + 0);
618
text += ": ";
619
text += DADDR(1 + i * 2 + 1);
620
}
621
622
text += "}";
623
624
incr += 3 + argc * 2;
625
} break;
626
case OPCODE_CONSTRUCT_TYPED_DICTIONARY: {
627
int instr_var_args = _code_ptr[++ip];
628
int argc = _code_ptr[ip + 1 + instr_var_args];
629
630
Ref<Script> key_script_type = get_constant(_code_ptr[ip + argc * 2 + 2] & ADDR_MASK);
631
Variant::Type key_builtin_type = (Variant::Type)_code_ptr[ip + argc * 2 + 5];
632
StringName key_native_type = get_global_name(_code_ptr[ip + argc * 2 + 6]);
633
634
String key_type_name;
635
if (key_script_type.is_valid() && key_script_type->is_valid()) {
636
key_type_name = "script(" + GDScript::debug_get_script_name(key_script_type) + ")";
637
} else if (key_native_type != StringName()) {
638
key_type_name = key_native_type;
639
} else {
640
key_type_name = Variant::get_type_name(key_builtin_type);
641
}
642
643
Ref<Script> value_script_type = get_constant(_code_ptr[ip + argc * 2 + 3] & ADDR_MASK);
644
Variant::Type value_builtin_type = (Variant::Type)_code_ptr[ip + argc * 2 + 7];
645
StringName value_native_type = get_global_name(_code_ptr[ip + argc * 2 + 8]);
646
647
String value_type_name;
648
if (value_script_type.is_valid() && value_script_type->is_valid()) {
649
value_type_name = "script(" + GDScript::debug_get_script_name(value_script_type) + ")";
650
} else if (value_native_type != StringName()) {
651
value_type_name = value_native_type;
652
} else {
653
value_type_name = Variant::get_type_name(value_builtin_type);
654
}
655
656
text += "make_typed_dict (";
657
text += key_type_name;
658
text += ", ";
659
text += value_type_name;
660
text += ") ";
661
662
text += DADDR(1 + argc * 2);
663
text += " = {";
664
665
for (int i = 0; i < argc; i++) {
666
if (i > 0) {
667
text += ", ";
668
}
669
text += DADDR(1 + i * 2 + 0);
670
text += ": ";
671
text += DADDR(1 + i * 2 + 1);
672
}
673
674
text += "}";
675
676
incr += 9 + argc * 2;
677
} break;
678
case OPCODE_CALL:
679
case OPCODE_CALL_RETURN:
680
case OPCODE_CALL_ASYNC: {
681
bool ret = (_code_ptr[ip]) == OPCODE_CALL_RETURN;
682
bool async = (_code_ptr[ip]) == OPCODE_CALL_ASYNC;
683
684
int instr_var_args = _code_ptr[++ip];
685
686
if (ret) {
687
text += "call-ret ";
688
} else if (async) {
689
text += "call-async ";
690
} else {
691
text += "call ";
692
}
693
694
int argc = _code_ptr[ip + 1 + instr_var_args];
695
if (ret || async) {
696
text += DADDR(2 + argc) + " = ";
697
}
698
699
text += DADDR(1 + argc) + ".";
700
text += String(_global_names_ptr[_code_ptr[ip + 2 + instr_var_args]]);
701
text += "(";
702
703
for (int i = 0; i < argc; i++) {
704
if (i > 0) {
705
text += ", ";
706
}
707
text += DADDR(1 + i);
708
}
709
text += ")";
710
711
incr = 5 + argc;
712
} break;
713
case OPCODE_CALL_METHOD_BIND:
714
case OPCODE_CALL_METHOD_BIND_RET: {
715
bool ret = (_code_ptr[ip]) == OPCODE_CALL_METHOD_BIND_RET;
716
int instr_var_args = _code_ptr[++ip];
717
718
if (ret) {
719
text += "call-method_bind-ret ";
720
} else {
721
text += "call-method_bind ";
722
}
723
724
MethodBind *method = _methods_ptr[_code_ptr[ip + 2 + instr_var_args]];
725
726
int argc = _code_ptr[ip + 1 + instr_var_args];
727
if (ret) {
728
text += DADDR(2 + argc) + " = ";
729
}
730
731
text += DADDR(1 + argc) + ".";
732
text += method->get_name();
733
text += "(";
734
735
for (int i = 0; i < argc; i++) {
736
if (i > 0) {
737
text += ", ";
738
}
739
text += DADDR(1 + i);
740
}
741
text += ")";
742
743
incr = 5 + argc;
744
} break;
745
case OPCODE_CALL_BUILTIN_STATIC: {
746
int instr_var_args = _code_ptr[++ip];
747
Variant::Type type = (Variant::Type)_code_ptr[ip + 1 + instr_var_args];
748
int argc = _code_ptr[ip + 3 + instr_var_args];
749
750
text += "call built-in method static ";
751
text += DADDR(1 + argc);
752
text += " = ";
753
text += Variant::get_type_name(type);
754
text += ".";
755
text += _global_names_ptr[_code_ptr[ip + 2 + instr_var_args]].operator String();
756
text += "(";
757
758
for (int i = 0; i < argc; i++) {
759
if (i > 0) {
760
text += ", ";
761
}
762
text += DADDR(1 + i);
763
}
764
text += ")";
765
766
incr += 5 + argc;
767
} break;
768
case OPCODE_CALL_NATIVE_STATIC: {
769
int instr_var_args = _code_ptr[++ip];
770
MethodBind *method = _methods_ptr[_code_ptr[ip + 1 + instr_var_args]];
771
int argc = _code_ptr[ip + 2 + instr_var_args];
772
773
text += "call native method static ";
774
text += DADDR(1 + argc);
775
text += " = ";
776
text += method->get_instance_class();
777
text += ".";
778
text += method->get_name();
779
text += "(";
780
781
for (int i = 0; i < argc; i++) {
782
if (i > 0) {
783
text += ", ";
784
}
785
text += DADDR(1 + i);
786
}
787
text += ")";
788
789
incr += 4 + argc;
790
} break;
791
792
case OPCODE_CALL_NATIVE_STATIC_VALIDATED_RETURN: {
793
int instr_var_args = _code_ptr[++ip];
794
text += "call native static method validated (return) ";
795
MethodBind *method = _methods_ptr[_code_ptr[ip + 2 + instr_var_args]];
796
int argc = _code_ptr[ip + 1 + instr_var_args];
797
text += DADDR(1 + argc) + " = ";
798
text += method->get_instance_class();
799
text += ".";
800
text += method->get_name();
801
text += "(";
802
for (int i = 0; i < argc; i++) {
803
if (i > 0) {
804
text += ", ";
805
}
806
text += DADDR(1 + i);
807
}
808
text += ")";
809
incr = 4 + argc;
810
} break;
811
812
case OPCODE_CALL_NATIVE_STATIC_VALIDATED_NO_RETURN: {
813
int instr_var_args = _code_ptr[++ip];
814
815
text += "call native static method validated (no return) ";
816
817
MethodBind *method = _methods_ptr[_code_ptr[ip + 2 + instr_var_args]];
818
819
int argc = _code_ptr[ip + 1 + instr_var_args];
820
821
text += method->get_instance_class();
822
text += ".";
823
text += method->get_name();
824
text += "(";
825
826
for (int i = 0; i < argc; i++) {
827
if (i > 0) {
828
text += ", ";
829
}
830
text += DADDR(1 + i);
831
}
832
text += ")";
833
834
incr = 4 + argc;
835
} break;
836
837
case OPCODE_CALL_METHOD_BIND_VALIDATED_RETURN: {
838
int instr_var_args = _code_ptr[++ip];
839
text += "call method-bind validated (return) ";
840
MethodBind *method = _methods_ptr[_code_ptr[ip + 2 + instr_var_args]];
841
int argc = _code_ptr[ip + 1 + instr_var_args];
842
text += DADDR(2 + argc) + " = ";
843
text += DADDR(1 + argc) + ".";
844
text += method->get_name();
845
text += "(";
846
for (int i = 0; i < argc; i++) {
847
if (i > 0) {
848
text += ", ";
849
}
850
text += DADDR(1 + i);
851
}
852
text += ")";
853
incr = 5 + argc;
854
} break;
855
856
case OPCODE_CALL_METHOD_BIND_VALIDATED_NO_RETURN: {
857
int instr_var_args = _code_ptr[++ip];
858
859
text += "call method-bind validated (no return) ";
860
861
MethodBind *method = _methods_ptr[_code_ptr[ip + 2 + instr_var_args]];
862
863
int argc = _code_ptr[ip + 1 + instr_var_args];
864
865
text += DADDR(1 + argc) + ".";
866
text += method->get_name();
867
text += "(";
868
869
for (int i = 0; i < argc; i++) {
870
if (i > 0) {
871
text += ", ";
872
}
873
text += DADDR(1 + i);
874
}
875
text += ")";
876
877
incr = 5 + argc;
878
} break;
879
880
case OPCODE_CALL_BUILTIN_TYPE_VALIDATED: {
881
int instr_var_args = _code_ptr[++ip];
882
int argc = _code_ptr[ip + 1 + instr_var_args];
883
884
text += "call-builtin-method validated ";
885
886
text += DADDR(2 + argc) + " = ";
887
888
text += DADDR(1) + ".";
889
text += builtin_methods_names[_code_ptr[ip + 4 + argc]];
890
891
text += "(";
892
893
for (int i = 0; i < argc; i++) {
894
if (i > 0) {
895
text += ", ";
896
}
897
text += DADDR(1 + i);
898
}
899
text += ")";
900
901
incr = 5 + argc;
902
} break;
903
case OPCODE_CALL_UTILITY: {
904
int instr_var_args = _code_ptr[++ip];
905
906
text += "call-utility ";
907
908
int argc = _code_ptr[ip + 1 + instr_var_args];
909
text += DADDR(1 + argc) + " = ";
910
911
text += _global_names_ptr[_code_ptr[ip + 2 + instr_var_args]];
912
text += "(";
913
914
for (int i = 0; i < argc; i++) {
915
if (i > 0) {
916
text += ", ";
917
}
918
text += DADDR(1 + i);
919
}
920
text += ")";
921
922
incr = 4 + argc;
923
} break;
924
case OPCODE_CALL_UTILITY_VALIDATED: {
925
int instr_var_args = _code_ptr[++ip];
926
927
text += "call-utility validated ";
928
929
int argc = _code_ptr[ip + 1 + instr_var_args];
930
text += DADDR(1 + argc) + " = ";
931
932
text += utilities_names[_code_ptr[ip + 3 + argc]];
933
text += "(";
934
935
for (int i = 0; i < argc; i++) {
936
if (i > 0) {
937
text += ", ";
938
}
939
text += DADDR(1 + i);
940
}
941
text += ")";
942
943
incr = 4 + argc;
944
} break;
945
case OPCODE_CALL_GDSCRIPT_UTILITY: {
946
int instr_var_args = _code_ptr[++ip];
947
948
text += "call-gdscript-utility ";
949
950
int argc = _code_ptr[ip + 1 + instr_var_args];
951
text += DADDR(1 + argc) + " = ";
952
953
text += gds_utilities_names[_code_ptr[ip + 3 + argc]];
954
text += "(";
955
956
for (int i = 0; i < argc; i++) {
957
if (i > 0) {
958
text += ", ";
959
}
960
text += DADDR(1 + i);
961
}
962
text += ")";
963
964
incr = 4 + argc;
965
} break;
966
case OPCODE_CALL_SELF_BASE: {
967
int instr_var_args = _code_ptr[++ip];
968
969
text += "call-self-base ";
970
971
int argc = _code_ptr[ip + 1 + instr_var_args];
972
text += DADDR(2 + argc) + " = ";
973
974
text += _global_names_ptr[_code_ptr[ip + 2 + instr_var_args]];
975
text += "(";
976
977
for (int i = 0; i < argc; i++) {
978
if (i > 0) {
979
text += ", ";
980
}
981
text += DADDR(1 + i);
982
}
983
text += ")";
984
985
incr = 4 + argc;
986
} break;
987
case OPCODE_AWAIT: {
988
text += "await ";
989
text += DADDR(1);
990
991
incr = 2;
992
} break;
993
case OPCODE_AWAIT_RESUME: {
994
text += "await resume ";
995
text += DADDR(1);
996
997
incr = 2;
998
} break;
999
case OPCODE_CREATE_LAMBDA: {
1000
int instr_var_args = _code_ptr[++ip];
1001
int captures_count = _code_ptr[ip + 1 + instr_var_args];
1002
GDScriptFunction *lambda = _lambdas_ptr[_code_ptr[ip + 2 + instr_var_args]];
1003
1004
text += DADDR(1 + captures_count);
1005
text += "create lambda from ";
1006
text += lambda->name.operator String();
1007
text += "function, captures (";
1008
1009
for (int i = 0; i < captures_count; i++) {
1010
if (i > 0) {
1011
text += ", ";
1012
}
1013
text += DADDR(1 + i);
1014
}
1015
text += ")";
1016
1017
incr = 4 + captures_count;
1018
} break;
1019
case OPCODE_CREATE_SELF_LAMBDA: {
1020
int instr_var_args = _code_ptr[++ip];
1021
int captures_count = _code_ptr[ip + 1 + instr_var_args];
1022
GDScriptFunction *lambda = _lambdas_ptr[_code_ptr[ip + 2 + instr_var_args]];
1023
1024
text += DADDR(1 + captures_count);
1025
text += "create self lambda from ";
1026
text += lambda->name.operator String();
1027
text += "function, captures (";
1028
1029
for (int i = 0; i < captures_count; i++) {
1030
if (i > 0) {
1031
text += ", ";
1032
}
1033
text += DADDR(1 + i);
1034
}
1035
text += ")";
1036
1037
incr = 4 + captures_count;
1038
} break;
1039
case OPCODE_JUMP: {
1040
text += "jump ";
1041
text += itos(_code_ptr[ip + 1]);
1042
1043
incr = 2;
1044
} break;
1045
case OPCODE_JUMP_IF: {
1046
text += "jump-if ";
1047
text += DADDR(1);
1048
text += " to ";
1049
text += itos(_code_ptr[ip + 2]);
1050
1051
incr = 3;
1052
} break;
1053
case OPCODE_JUMP_IF_NOT: {
1054
text += "jump-if-not ";
1055
text += DADDR(1);
1056
text += " to ";
1057
text += itos(_code_ptr[ip + 2]);
1058
1059
incr = 3;
1060
} break;
1061
case OPCODE_JUMP_TO_DEF_ARGUMENT: {
1062
text += "jump-to-default-argument ";
1063
1064
incr = 1;
1065
} break;
1066
case OPCODE_JUMP_IF_SHARED: {
1067
text += "jump-if-shared ";
1068
text += DADDR(1);
1069
text += " to ";
1070
text += itos(_code_ptr[ip + 2]);
1071
1072
incr = 3;
1073
} break;
1074
case OPCODE_RETURN: {
1075
text += "return ";
1076
text += DADDR(1);
1077
1078
incr = 2;
1079
} break;
1080
case OPCODE_RETURN_TYPED_BUILTIN: {
1081
text += "return typed builtin (";
1082
text += Variant::get_type_name((Variant::Type)_code_ptr[ip + 2]);
1083
text += ") ";
1084
text += DADDR(1);
1085
1086
incr += 3;
1087
} break;
1088
case OPCODE_RETURN_TYPED_ARRAY: {
1089
text += "return typed array ";
1090
text += DADDR(1);
1091
1092
incr += 5;
1093
} break;
1094
case OPCODE_RETURN_TYPED_DICTIONARY: {
1095
text += "return typed dictionary ";
1096
text += DADDR(1);
1097
1098
incr += 8;
1099
} break;
1100
case OPCODE_RETURN_TYPED_NATIVE: {
1101
text += "return typed native (";
1102
text += DADDR(2);
1103
text += ") ";
1104
text += DADDR(1);
1105
1106
incr += 3;
1107
} break;
1108
case OPCODE_RETURN_TYPED_SCRIPT: {
1109
Ref<Script> script = get_constant(_code_ptr[ip + 2] & ADDR_MASK);
1110
1111
text += "return typed script (";
1112
text += GDScript::debug_get_script_name(script);
1113
text += ") ";
1114
text += DADDR(1);
1115
1116
incr += 3;
1117
} break;
1118
1119
#define DISASSEMBLE_ITERATE(m_type) \
1120
case OPCODE_ITERATE_##m_type: { \
1121
text += "for-loop (typed "; \
1122
text += #m_type; \
1123
text += ") "; \
1124
text += DADDR(3); \
1125
text += " in "; \
1126
text += DADDR(2); \
1127
text += " counter "; \
1128
text += DADDR(1); \
1129
text += " end "; \
1130
text += itos(_code_ptr[ip + 4]); \
1131
incr += 5; \
1132
} break
1133
1134
#define DISASSEMBLE_ITERATE_BEGIN(m_type) \
1135
case OPCODE_ITERATE_BEGIN_##m_type: { \
1136
text += "for-init (typed "; \
1137
text += #m_type; \
1138
text += ") "; \
1139
text += DADDR(3); \
1140
text += " in "; \
1141
text += DADDR(2); \
1142
text += " counter "; \
1143
text += DADDR(1); \
1144
text += " end "; \
1145
text += itos(_code_ptr[ip + 4]); \
1146
incr += 5; \
1147
} break
1148
1149
#define DISASSEMBLE_ITERATE_TYPES(m_macro) \
1150
m_macro(INT); \
1151
m_macro(FLOAT); \
1152
m_macro(VECTOR2); \
1153
m_macro(VECTOR2I); \
1154
m_macro(VECTOR3); \
1155
m_macro(VECTOR3I); \
1156
m_macro(STRING); \
1157
m_macro(DICTIONARY); \
1158
m_macro(ARRAY); \
1159
m_macro(PACKED_BYTE_ARRAY); \
1160
m_macro(PACKED_INT32_ARRAY); \
1161
m_macro(PACKED_INT64_ARRAY); \
1162
m_macro(PACKED_FLOAT32_ARRAY); \
1163
m_macro(PACKED_FLOAT64_ARRAY); \
1164
m_macro(PACKED_STRING_ARRAY); \
1165
m_macro(PACKED_VECTOR2_ARRAY); \
1166
m_macro(PACKED_VECTOR3_ARRAY); \
1167
m_macro(PACKED_COLOR_ARRAY); \
1168
m_macro(PACKED_VECTOR4_ARRAY); \
1169
m_macro(OBJECT)
1170
1171
case OPCODE_ITERATE_BEGIN: {
1172
text += "for-init ";
1173
text += DADDR(3);
1174
text += " in ";
1175
text += DADDR(2);
1176
text += " counter ";
1177
text += DADDR(1);
1178
text += " end ";
1179
text += itos(_code_ptr[ip + 4]);
1180
1181
incr += 5;
1182
} break;
1183
DISASSEMBLE_ITERATE_TYPES(DISASSEMBLE_ITERATE_BEGIN);
1184
case OPCODE_ITERATE_BEGIN_RANGE: {
1185
text += "for-init ";
1186
text += DADDR(5);
1187
text += " in range from ";
1188
text += DADDR(2);
1189
text += " to ";
1190
text += DADDR(3);
1191
text += " step ";
1192
text += DADDR(4);
1193
text += " counter ";
1194
text += DADDR(1);
1195
text += " end ";
1196
text += itos(_code_ptr[ip + 6]);
1197
1198
incr += 7;
1199
} break;
1200
case OPCODE_ITERATE: {
1201
text += "for-loop ";
1202
text += DADDR(3);
1203
text += " in ";
1204
text += DADDR(2);
1205
text += " counter ";
1206
text += DADDR(1);
1207
text += " end ";
1208
text += itos(_code_ptr[ip + 4]);
1209
1210
incr += 5;
1211
} break;
1212
DISASSEMBLE_ITERATE_TYPES(DISASSEMBLE_ITERATE);
1213
case OPCODE_ITERATE_RANGE: {
1214
text += "for-loop ";
1215
text += DADDR(4);
1216
text += " in range to ";
1217
text += DADDR(2);
1218
text += " step ";
1219
text += DADDR(3);
1220
text += " counter ";
1221
text += DADDR(1);
1222
text += " end ";
1223
text += itos(_code_ptr[ip + 5]);
1224
1225
incr += 6;
1226
} break;
1227
case OPCODE_STORE_GLOBAL: {
1228
text += "store global ";
1229
text += DADDR(1);
1230
text += " = ";
1231
text += String::num_int64(_code_ptr[ip + 2]);
1232
1233
incr += 3;
1234
} break;
1235
case OPCODE_STORE_NAMED_GLOBAL: {
1236
text += "store named global ";
1237
text += DADDR(1);
1238
text += " = ";
1239
text += String(_global_names_ptr[_code_ptr[ip + 2]]);
1240
1241
incr += 3;
1242
} break;
1243
case OPCODE_LINE: {
1244
int line = _code_ptr[ip + 1] - 1;
1245
if (line >= 0 && line < p_code_lines.size()) {
1246
text += "line ";
1247
text += itos(line + 1);
1248
text += ": ";
1249
text += p_code_lines[line];
1250
} else {
1251
text += "";
1252
}
1253
1254
incr += 2;
1255
} break;
1256
1257
#define DISASSEMBLE_TYPE_ADJUST(m_v_type) \
1258
case OPCODE_TYPE_ADJUST_##m_v_type: { \
1259
text += "type adjust ("; \
1260
text += #m_v_type; \
1261
text += ") "; \
1262
text += DADDR(1); \
1263
incr += 2; \
1264
} break
1265
1266
DISASSEMBLE_TYPE_ADJUST(BOOL);
1267
DISASSEMBLE_TYPE_ADJUST(INT);
1268
DISASSEMBLE_TYPE_ADJUST(FLOAT);
1269
DISASSEMBLE_TYPE_ADJUST(STRING);
1270
DISASSEMBLE_TYPE_ADJUST(VECTOR2);
1271
DISASSEMBLE_TYPE_ADJUST(VECTOR2I);
1272
DISASSEMBLE_TYPE_ADJUST(RECT2);
1273
DISASSEMBLE_TYPE_ADJUST(RECT2I);
1274
DISASSEMBLE_TYPE_ADJUST(VECTOR3);
1275
DISASSEMBLE_TYPE_ADJUST(VECTOR3I);
1276
DISASSEMBLE_TYPE_ADJUST(TRANSFORM2D);
1277
DISASSEMBLE_TYPE_ADJUST(VECTOR4);
1278
DISASSEMBLE_TYPE_ADJUST(VECTOR4I);
1279
DISASSEMBLE_TYPE_ADJUST(PLANE);
1280
DISASSEMBLE_TYPE_ADJUST(QUATERNION);
1281
DISASSEMBLE_TYPE_ADJUST(AABB);
1282
DISASSEMBLE_TYPE_ADJUST(BASIS);
1283
DISASSEMBLE_TYPE_ADJUST(TRANSFORM3D);
1284
DISASSEMBLE_TYPE_ADJUST(PROJECTION);
1285
DISASSEMBLE_TYPE_ADJUST(COLOR);
1286
DISASSEMBLE_TYPE_ADJUST(STRING_NAME);
1287
DISASSEMBLE_TYPE_ADJUST(NODE_PATH);
1288
DISASSEMBLE_TYPE_ADJUST(RID);
1289
DISASSEMBLE_TYPE_ADJUST(OBJECT);
1290
DISASSEMBLE_TYPE_ADJUST(CALLABLE);
1291
DISASSEMBLE_TYPE_ADJUST(SIGNAL);
1292
DISASSEMBLE_TYPE_ADJUST(DICTIONARY);
1293
DISASSEMBLE_TYPE_ADJUST(ARRAY);
1294
DISASSEMBLE_TYPE_ADJUST(PACKED_BYTE_ARRAY);
1295
DISASSEMBLE_TYPE_ADJUST(PACKED_INT32_ARRAY);
1296
DISASSEMBLE_TYPE_ADJUST(PACKED_INT64_ARRAY);
1297
DISASSEMBLE_TYPE_ADJUST(PACKED_FLOAT32_ARRAY);
1298
DISASSEMBLE_TYPE_ADJUST(PACKED_FLOAT64_ARRAY);
1299
DISASSEMBLE_TYPE_ADJUST(PACKED_STRING_ARRAY);
1300
DISASSEMBLE_TYPE_ADJUST(PACKED_VECTOR2_ARRAY);
1301
DISASSEMBLE_TYPE_ADJUST(PACKED_VECTOR3_ARRAY);
1302
DISASSEMBLE_TYPE_ADJUST(PACKED_COLOR_ARRAY);
1303
DISASSEMBLE_TYPE_ADJUST(PACKED_VECTOR4_ARRAY);
1304
1305
case OPCODE_ASSERT: {
1306
text += "assert (";
1307
text += DADDR(1);
1308
text += ", ";
1309
text += DADDR(2);
1310
text += ")";
1311
1312
incr += 3;
1313
} break;
1314
case OPCODE_BREAKPOINT: {
1315
text += "breakpoint";
1316
1317
incr += 1;
1318
} break;
1319
case OPCODE_END: {
1320
text += "== END ==";
1321
1322
incr += 1;
1323
} break;
1324
}
1325
1326
ip += incr;
1327
if (text.get_string_length() > 0) {
1328
print_line(text.as_string());
1329
}
1330
}
1331
}
1332
1333
#endif // DEBUG_ENABLED
1334
1335