Path: blob/master/modules/gdscript/gdscript_disassembler.cpp
10278 views
/**************************************************************************/1/* gdscript_disassembler.cpp */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#ifdef DEBUG_ENABLED3132#include "gdscript.h"33#include "gdscript_function.h"3435#include "core/string/string_builder.h"3637static String _get_variant_string(const Variant &p_variant) {38String txt;39if (p_variant.get_type() == Variant::STRING) {40txt = "\"" + String(p_variant) + "\"";41} else if (p_variant.get_type() == Variant::STRING_NAME) {42txt = "&\"" + String(p_variant) + "\"";43} else if (p_variant.get_type() == Variant::NODE_PATH) {44txt = "^\"" + String(p_variant) + "\"";45} else if (p_variant.get_type() == Variant::OBJECT) {46Object *obj = p_variant;47if (!obj) {48txt = "null";49} else {50GDScriptNativeClass *cls = Object::cast_to<GDScriptNativeClass>(obj);51if (cls) {52txt = "class(" + cls->get_name() + ")";53} else {54Script *script = Object::cast_to<Script>(obj);55if (script) {56txt = "script(" + GDScript::debug_get_script_name(script) + ")";57} else {58txt = "object(" + obj->get_class();59if (obj->get_script_instance()) {60txt += ", " + GDScript::debug_get_script_name(obj->get_script_instance()->get_script());61}62txt += ")";63}64}65}66} else {67txt = p_variant;68}69return txt;70}7172static String _disassemble_address(const GDScript *p_script, const GDScriptFunction &p_function, int p_address) {73int addr = p_address & GDScriptFunction::ADDR_MASK;7475switch (p_address >> GDScriptFunction::ADDR_BITS) {76case GDScriptFunction::ADDR_TYPE_STACK: {77switch (addr) {78case GDScriptFunction::ADDR_STACK_SELF:79return "self";80case GDScriptFunction::ADDR_STACK_CLASS:81return "class";82case GDScriptFunction::ADDR_STACK_NIL:83return "nil";84default:85return "stack(" + itos(addr) + ")";86}87} break;88case GDScriptFunction::ADDR_TYPE_CONSTANT: {89return "const(" + _get_variant_string(p_function.get_constant(addr)) + ")";90} break;91case GDScriptFunction::ADDR_TYPE_MEMBER: {92return "member(" + p_script->debug_get_member_by_index(addr) + ")";93} break;94}9596return "<err>";97}9899void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {100#define DADDR(m_ip) (_disassemble_address(_script, *this, _code_ptr[ip + m_ip]))101102for (int ip = 0; ip < _code_size;) {103StringBuilder text;104int incr = 0;105106text += " ";107text += itos(ip);108text += ": ";109110// This makes the compiler complain if some opcode is unchecked in the switch.111Opcode opcode = Opcode(_code_ptr[ip]);112113switch (opcode) {114case OPCODE_OPERATOR: {115constexpr int _pointer_size = sizeof(Variant::ValidatedOperatorEvaluator) / sizeof(*_code_ptr);116int operation = _code_ptr[ip + 4];117118text += "operator ";119120text += DADDR(3);121text += " = ";122text += DADDR(1);123text += " ";124text += Variant::get_operator_name(Variant::Operator(operation));125text += " ";126text += DADDR(2);127128incr += 7 + _pointer_size;129} break;130case OPCODE_OPERATOR_VALIDATED: {131text += "validated operator ";132133text += DADDR(3);134text += " = ";135text += DADDR(1);136text += " ";137text += operator_names[_code_ptr[ip + 4]];138text += " ";139text += DADDR(2);140141incr += 5;142} break;143case OPCODE_TYPE_TEST_BUILTIN: {144text += "type test ";145text += DADDR(1);146text += " = ";147text += DADDR(2);148text += " is ";149text += Variant::get_type_name(Variant::Type(_code_ptr[ip + 3]));150151incr += 4;152} break;153case OPCODE_TYPE_TEST_ARRAY: {154text += "type test ";155text += DADDR(1);156text += " = ";157text += DADDR(2);158text += " is Array[";159160Ref<Script> script_type = get_constant(_code_ptr[ip + 3] & ADDR_MASK);161Variant::Type builtin_type = (Variant::Type)_code_ptr[ip + 4];162StringName native_type = get_global_name(_code_ptr[ip + 5]);163164if (script_type.is_valid() && script_type->is_valid()) {165text += "script(";166text += GDScript::debug_get_script_name(script_type);167text += ")";168} else if (native_type != StringName()) {169text += native_type;170} else {171text += Variant::get_type_name(builtin_type);172}173174text += "]";175176incr += 6;177} break;178case OPCODE_TYPE_TEST_DICTIONARY: {179text += "type test ";180text += DADDR(1);181text += " = ";182text += DADDR(2);183text += " is Dictionary[";184185Ref<Script> key_script_type = get_constant(_code_ptr[ip + 3] & ADDR_MASK);186Variant::Type key_builtin_type = (Variant::Type)_code_ptr[ip + 5];187StringName key_native_type = get_global_name(_code_ptr[ip + 6]);188189if (key_script_type.is_valid() && key_script_type->is_valid()) {190text += "script(";191text += GDScript::debug_get_script_name(key_script_type);192text += ")";193} else if (key_native_type != StringName()) {194text += key_native_type;195} else {196text += Variant::get_type_name(key_builtin_type);197}198199text += ", ";200201Ref<Script> value_script_type = get_constant(_code_ptr[ip + 4] & ADDR_MASK);202Variant::Type value_builtin_type = (Variant::Type)_code_ptr[ip + 7];203StringName value_native_type = get_global_name(_code_ptr[ip + 8]);204205if (value_script_type.is_valid() && value_script_type->is_valid()) {206text += "script(";207text += GDScript::debug_get_script_name(value_script_type);208text += ")";209} else if (value_native_type != StringName()) {210text += value_native_type;211} else {212text += Variant::get_type_name(value_builtin_type);213}214215text += "]";216217incr += 9;218} break;219case OPCODE_TYPE_TEST_NATIVE: {220text += "type test ";221text += DADDR(1);222text += " = ";223text += DADDR(2);224text += " is ";225text += get_global_name(_code_ptr[ip + 3]);226227incr += 4;228} break;229case OPCODE_TYPE_TEST_SCRIPT: {230text += "type test ";231text += DADDR(1);232text += " = ";233text += DADDR(2);234text += " is ";235text += DADDR(3);236237incr += 4;238} break;239case OPCODE_SET_KEYED: {240text += "set keyed ";241text += DADDR(1);242text += "[";243text += DADDR(2);244text += "] = ";245text += DADDR(3);246247incr += 4;248} break;249case OPCODE_SET_KEYED_VALIDATED: {250text += "set keyed validated ";251text += DADDR(1);252text += "[";253text += DADDR(2);254text += "] = ";255text += DADDR(3);256257incr += 5;258} break;259case OPCODE_SET_INDEXED_VALIDATED: {260text += "set indexed validated ";261text += DADDR(1);262text += "[";263text += DADDR(2);264text += "] = ";265text += DADDR(3);266267incr += 5;268} break;269case OPCODE_GET_KEYED: {270text += "get keyed ";271text += DADDR(3);272text += " = ";273text += DADDR(1);274text += "[";275text += DADDR(2);276text += "]";277278incr += 4;279} break;280case OPCODE_GET_KEYED_VALIDATED: {281text += "get keyed validated ";282text += DADDR(3);283text += " = ";284text += DADDR(1);285text += "[";286text += DADDR(2);287text += "]";288289incr += 5;290} break;291case OPCODE_GET_INDEXED_VALIDATED: {292text += "get indexed validated ";293text += DADDR(3);294text += " = ";295text += DADDR(1);296text += "[";297text += DADDR(2);298text += "]";299300incr += 5;301} break;302case OPCODE_SET_NAMED: {303text += "set_named ";304text += DADDR(1);305text += "[\"";306text += _global_names_ptr[_code_ptr[ip + 3]];307text += "\"] = ";308text += DADDR(2);309310incr += 4;311} break;312case OPCODE_SET_NAMED_VALIDATED: {313text += "set_named validated ";314text += DADDR(1);315text += "[\"";316text += setter_names[_code_ptr[ip + 3]];317text += "\"] = ";318text += DADDR(2);319320incr += 4;321} break;322case OPCODE_GET_NAMED: {323text += "get_named ";324text += DADDR(2);325text += " = ";326text += DADDR(1);327text += "[\"";328text += _global_names_ptr[_code_ptr[ip + 3]];329text += "\"]";330331incr += 4;332} break;333case OPCODE_GET_NAMED_VALIDATED: {334text += "get_named validated ";335text += DADDR(2);336text += " = ";337text += DADDR(1);338text += "[\"";339text += getter_names[_code_ptr[ip + 3]];340text += "\"]";341342incr += 4;343} break;344case OPCODE_SET_MEMBER: {345text += "set_member ";346text += "[\"";347text += _global_names_ptr[_code_ptr[ip + 2]];348text += "\"] = ";349text += DADDR(1);350351incr += 3;352} break;353case OPCODE_GET_MEMBER: {354text += "get_member ";355text += DADDR(1);356text += " = ";357text += "[\"";358text += _global_names_ptr[_code_ptr[ip + 2]];359text += "\"]";360361incr += 3;362} break;363case OPCODE_SET_STATIC_VARIABLE: {364Ref<GDScript> gdscript;365if (_code_ptr[ip + 2] == ADDR_CLASS) {366gdscript = Ref<GDScript>(_script);367} else {368gdscript = get_constant(_code_ptr[ip + 2] & ADDR_MASK);369}370371text += "set_static_variable script(";372text += GDScript::debug_get_script_name(gdscript);373text += ")";374if (gdscript.is_valid()) {375text += "[\"" + gdscript->debug_get_static_var_by_index(_code_ptr[ip + 3]) + "\"]";376} else {377text += "[<index " + itos(_code_ptr[ip + 3]) + ">]";378}379text += " = ";380text += DADDR(1);381382incr += 4;383} break;384case OPCODE_GET_STATIC_VARIABLE: {385Ref<GDScript> gdscript;386if (_code_ptr[ip + 2] == ADDR_CLASS) {387gdscript = Ref<GDScript>(_script);388} else {389gdscript = get_constant(_code_ptr[ip + 2] & ADDR_MASK);390}391392text += "get_static_variable ";393text += DADDR(1);394text += " = script(";395text += GDScript::debug_get_script_name(gdscript);396text += ")";397if (gdscript.is_valid()) {398text += "[\"" + gdscript->debug_get_static_var_by_index(_code_ptr[ip + 3]) + "\"]";399} else {400text += "[<index " + itos(_code_ptr[ip + 3]) + ">]";401}402403incr += 4;404} break;405case OPCODE_ASSIGN: {406text += "assign ";407text += DADDR(1);408text += " = ";409text += DADDR(2);410411incr += 3;412} break;413case OPCODE_ASSIGN_NULL: {414text += "assign ";415text += DADDR(1);416text += " = null";417418incr += 2;419} break;420case OPCODE_ASSIGN_TRUE: {421text += "assign ";422text += DADDR(1);423text += " = true";424425incr += 2;426} break;427case OPCODE_ASSIGN_FALSE: {428text += "assign ";429text += DADDR(1);430text += " = false";431432incr += 2;433} break;434case OPCODE_ASSIGN_TYPED_BUILTIN: {435text += "assign typed builtin (";436text += Variant::get_type_name((Variant::Type)_code_ptr[ip + 3]);437text += ") ";438text += DADDR(1);439text += " = ";440text += DADDR(2);441442incr += 4;443} break;444case OPCODE_ASSIGN_TYPED_ARRAY: {445text += "assign typed array ";446text += DADDR(1);447text += " = ";448text += DADDR(2);449450incr += 6;451} break;452case OPCODE_ASSIGN_TYPED_DICTIONARY: {453text += "assign typed dictionary ";454text += DADDR(1);455text += " = ";456text += DADDR(2);457458incr += 9;459} break;460case OPCODE_ASSIGN_TYPED_NATIVE: {461text += "assign typed native (";462text += DADDR(3);463text += ") ";464text += DADDR(1);465text += " = ";466text += DADDR(2);467468incr += 4;469} break;470case OPCODE_ASSIGN_TYPED_SCRIPT: {471Ref<Script> script = get_constant(_code_ptr[ip + 3] & ADDR_MASK);472473text += "assign typed script (";474text += GDScript::debug_get_script_name(script);475text += ") ";476text += DADDR(1);477text += " = ";478text += DADDR(2);479480incr += 4;481} break;482case OPCODE_CAST_TO_BUILTIN: {483text += "cast builtin ";484text += DADDR(2);485text += " = ";486text += DADDR(1);487text += " as ";488text += Variant::get_type_name(Variant::Type(_code_ptr[ip + 1]));489490incr += 4;491} break;492case OPCODE_CAST_TO_NATIVE: {493text += "cast native ";494text += DADDR(2);495text += " = ";496text += DADDR(1);497text += " as ";498text += DADDR(3);499500incr += 4;501} break;502case OPCODE_CAST_TO_SCRIPT: {503text += "cast ";504text += DADDR(2);505text += " = ";506text += DADDR(1);507text += " as ";508text += DADDR(3);509510incr += 4;511} break;512case OPCODE_CONSTRUCT: {513int instr_var_args = _code_ptr[++ip];514Variant::Type t = Variant::Type(_code_ptr[ip + 3 + instr_var_args]);515int argc = _code_ptr[ip + 1 + instr_var_args];516517text += "construct ";518text += DADDR(1 + argc);519text += " = ";520521text += Variant::get_type_name(t) + "(";522for (int i = 0; i < argc; i++) {523if (i > 0) {524text += ", ";525}526text += DADDR(i + 1);527}528text += ")";529530incr = 3 + instr_var_args;531} break;532case OPCODE_CONSTRUCT_VALIDATED: {533int instr_var_args = _code_ptr[++ip];534int argc = _code_ptr[ip + 1 + instr_var_args];535536text += "construct validated ";537text += DADDR(1 + argc);538text += " = ";539540text += constructors_names[_code_ptr[ip + 3 + argc]];541text += "(";542for (int i = 0; i < argc; i++) {543if (i > 0) {544text += ", ";545}546text += DADDR(i + 1);547}548text += ")";549550incr = 3 + instr_var_args;551} break;552case OPCODE_CONSTRUCT_ARRAY: {553int instr_var_args = _code_ptr[++ip];554int argc = _code_ptr[ip + 1 + instr_var_args];555text += "make_array ";556text += DADDR(1 + argc);557text += " = [";558559for (int i = 0; i < argc; i++) {560if (i > 0) {561text += ", ";562}563text += DADDR(1 + i);564}565566text += "]";567568incr += 3 + argc;569} break;570case OPCODE_CONSTRUCT_TYPED_ARRAY: {571int instr_var_args = _code_ptr[++ip];572int argc = _code_ptr[ip + 1 + instr_var_args];573574Ref<Script> script_type = get_constant(_code_ptr[ip + argc + 2] & ADDR_MASK);575Variant::Type builtin_type = (Variant::Type)_code_ptr[ip + argc + 4];576StringName native_type = get_global_name(_code_ptr[ip + argc + 5]);577578String type_name;579if (script_type.is_valid() && script_type->is_valid()) {580type_name = "script(" + GDScript::debug_get_script_name(script_type) + ")";581} else if (native_type != StringName()) {582type_name = native_type;583} else {584type_name = Variant::get_type_name(builtin_type);585}586587text += "make_typed_array (";588text += type_name;589text += ") ";590591text += DADDR(1 + argc);592text += " = [";593594for (int i = 0; i < argc; i++) {595if (i > 0) {596text += ", ";597}598text += DADDR(1 + i);599}600601text += "]";602603incr += 6 + argc;604} break;605case OPCODE_CONSTRUCT_DICTIONARY: {606int instr_var_args = _code_ptr[++ip];607int argc = _code_ptr[ip + 1 + instr_var_args];608text += "make_dict ";609text += DADDR(1 + argc * 2);610text += " = {";611612for (int i = 0; i < argc; i++) {613if (i > 0) {614text += ", ";615}616text += DADDR(1 + i * 2 + 0);617text += ": ";618text += DADDR(1 + i * 2 + 1);619}620621text += "}";622623incr += 3 + argc * 2;624} break;625case OPCODE_CONSTRUCT_TYPED_DICTIONARY: {626int instr_var_args = _code_ptr[++ip];627int argc = _code_ptr[ip + 1 + instr_var_args];628629Ref<Script> key_script_type = get_constant(_code_ptr[ip + argc * 2 + 2] & ADDR_MASK);630Variant::Type key_builtin_type = (Variant::Type)_code_ptr[ip + argc * 2 + 5];631StringName key_native_type = get_global_name(_code_ptr[ip + argc * 2 + 6]);632633String key_type_name;634if (key_script_type.is_valid() && key_script_type->is_valid()) {635key_type_name = "script(" + GDScript::debug_get_script_name(key_script_type) + ")";636} else if (key_native_type != StringName()) {637key_type_name = key_native_type;638} else {639key_type_name = Variant::get_type_name(key_builtin_type);640}641642Ref<Script> value_script_type = get_constant(_code_ptr[ip + argc * 2 + 3] & ADDR_MASK);643Variant::Type value_builtin_type = (Variant::Type)_code_ptr[ip + argc * 2 + 7];644StringName value_native_type = get_global_name(_code_ptr[ip + argc * 2 + 8]);645646String value_type_name;647if (value_script_type.is_valid() && value_script_type->is_valid()) {648value_type_name = "script(" + GDScript::debug_get_script_name(value_script_type) + ")";649} else if (value_native_type != StringName()) {650value_type_name = value_native_type;651} else {652value_type_name = Variant::get_type_name(value_builtin_type);653}654655text += "make_typed_dict (";656text += key_type_name;657text += ", ";658text += value_type_name;659text += ") ";660661text += DADDR(1 + argc * 2);662text += " = {";663664for (int i = 0; i < argc; i++) {665if (i > 0) {666text += ", ";667}668text += DADDR(1 + i * 2 + 0);669text += ": ";670text += DADDR(1 + i * 2 + 1);671}672673text += "}";674675incr += 9 + argc * 2;676} break;677case OPCODE_CALL:678case OPCODE_CALL_RETURN:679case OPCODE_CALL_ASYNC: {680bool ret = (_code_ptr[ip]) == OPCODE_CALL_RETURN;681bool async = (_code_ptr[ip]) == OPCODE_CALL_ASYNC;682683int instr_var_args = _code_ptr[++ip];684685if (ret) {686text += "call-ret ";687} else if (async) {688text += "call-async ";689} else {690text += "call ";691}692693int argc = _code_ptr[ip + 1 + instr_var_args];694if (ret || async) {695text += DADDR(2 + argc) + " = ";696}697698text += DADDR(1 + argc) + ".";699text += String(_global_names_ptr[_code_ptr[ip + 2 + instr_var_args]]);700text += "(";701702for (int i = 0; i < argc; i++) {703if (i > 0) {704text += ", ";705}706text += DADDR(1 + i);707}708text += ")";709710incr = 5 + argc;711} break;712case OPCODE_CALL_METHOD_BIND:713case OPCODE_CALL_METHOD_BIND_RET: {714bool ret = (_code_ptr[ip]) == OPCODE_CALL_METHOD_BIND_RET;715int instr_var_args = _code_ptr[++ip];716717if (ret) {718text += "call-method_bind-ret ";719} else {720text += "call-method_bind ";721}722723MethodBind *method = _methods_ptr[_code_ptr[ip + 2 + instr_var_args]];724725int argc = _code_ptr[ip + 1 + instr_var_args];726if (ret) {727text += DADDR(2 + argc) + " = ";728}729730text += DADDR(1 + argc) + ".";731text += method->get_name();732text += "(";733734for (int i = 0; i < argc; i++) {735if (i > 0) {736text += ", ";737}738text += DADDR(1 + i);739}740text += ")";741742incr = 5 + argc;743} break;744case OPCODE_CALL_BUILTIN_STATIC: {745int instr_var_args = _code_ptr[++ip];746Variant::Type type = (Variant::Type)_code_ptr[ip + 1 + instr_var_args];747int argc = _code_ptr[ip + 3 + instr_var_args];748749text += "call built-in method static ";750text += DADDR(1 + argc);751text += " = ";752text += Variant::get_type_name(type);753text += ".";754text += _global_names_ptr[_code_ptr[ip + 2 + instr_var_args]].operator String();755text += "(";756757for (int i = 0; i < argc; i++) {758if (i > 0) {759text += ", ";760}761text += DADDR(1 + i);762}763text += ")";764765incr += 5 + argc;766} break;767case OPCODE_CALL_NATIVE_STATIC: {768int instr_var_args = _code_ptr[++ip];769MethodBind *method = _methods_ptr[_code_ptr[ip + 1 + instr_var_args]];770int argc = _code_ptr[ip + 2 + instr_var_args];771772text += "call native method static ";773text += DADDR(1 + argc);774text += " = ";775text += method->get_instance_class();776text += ".";777text += method->get_name();778text += "(";779780for (int i = 0; i < argc; i++) {781if (i > 0) {782text += ", ";783}784text += DADDR(1 + i);785}786text += ")";787788incr += 4 + argc;789} break;790791case OPCODE_CALL_NATIVE_STATIC_VALIDATED_RETURN: {792int instr_var_args = _code_ptr[++ip];793text += "call native static method validated (return) ";794MethodBind *method = _methods_ptr[_code_ptr[ip + 2 + instr_var_args]];795int argc = _code_ptr[ip + 1 + instr_var_args];796text += DADDR(1 + argc) + " = ";797text += method->get_instance_class();798text += ".";799text += method->get_name();800text += "(";801for (int i = 0; i < argc; i++) {802if (i > 0) {803text += ", ";804}805text += DADDR(1 + i);806}807text += ")";808incr = 4 + argc;809} break;810811case OPCODE_CALL_NATIVE_STATIC_VALIDATED_NO_RETURN: {812int instr_var_args = _code_ptr[++ip];813814text += "call native static method validated (no return) ";815816MethodBind *method = _methods_ptr[_code_ptr[ip + 2 + instr_var_args]];817818int argc = _code_ptr[ip + 1 + instr_var_args];819820text += method->get_instance_class();821text += ".";822text += method->get_name();823text += "(";824825for (int i = 0; i < argc; i++) {826if (i > 0) {827text += ", ";828}829text += DADDR(1 + i);830}831text += ")";832833incr = 4 + argc;834} break;835836case OPCODE_CALL_METHOD_BIND_VALIDATED_RETURN: {837int instr_var_args = _code_ptr[++ip];838text += "call method-bind validated (return) ";839MethodBind *method = _methods_ptr[_code_ptr[ip + 2 + instr_var_args]];840int argc = _code_ptr[ip + 1 + instr_var_args];841text += DADDR(2 + argc) + " = ";842text += DADDR(1 + argc) + ".";843text += method->get_name();844text += "(";845for (int i = 0; i < argc; i++) {846if (i > 0) {847text += ", ";848}849text += DADDR(1 + i);850}851text += ")";852incr = 5 + argc;853} break;854855case OPCODE_CALL_METHOD_BIND_VALIDATED_NO_RETURN: {856int instr_var_args = _code_ptr[++ip];857858text += "call method-bind validated (no return) ";859860MethodBind *method = _methods_ptr[_code_ptr[ip + 2 + instr_var_args]];861862int argc = _code_ptr[ip + 1 + instr_var_args];863864text += DADDR(1 + argc) + ".";865text += method->get_name();866text += "(";867868for (int i = 0; i < argc; i++) {869if (i > 0) {870text += ", ";871}872text += DADDR(1 + i);873}874text += ")";875876incr = 5 + argc;877} break;878879case OPCODE_CALL_BUILTIN_TYPE_VALIDATED: {880int instr_var_args = _code_ptr[++ip];881int argc = _code_ptr[ip + 1 + instr_var_args];882883text += "call-builtin-method validated ";884885text += DADDR(2 + argc) + " = ";886887text += DADDR(1) + ".";888text += builtin_methods_names[_code_ptr[ip + 4 + argc]];889890text += "(";891892for (int i = 0; i < argc; i++) {893if (i > 0) {894text += ", ";895}896text += DADDR(1 + i);897}898text += ")";899900incr = 5 + argc;901} break;902case OPCODE_CALL_UTILITY: {903int instr_var_args = _code_ptr[++ip];904905text += "call-utility ";906907int argc = _code_ptr[ip + 1 + instr_var_args];908text += DADDR(1 + argc) + " = ";909910text += _global_names_ptr[_code_ptr[ip + 2 + instr_var_args]];911text += "(";912913for (int i = 0; i < argc; i++) {914if (i > 0) {915text += ", ";916}917text += DADDR(1 + i);918}919text += ")";920921incr = 4 + argc;922} break;923case OPCODE_CALL_UTILITY_VALIDATED: {924int instr_var_args = _code_ptr[++ip];925926text += "call-utility validated ";927928int argc = _code_ptr[ip + 1 + instr_var_args];929text += DADDR(1 + argc) + " = ";930931text += utilities_names[_code_ptr[ip + 3 + argc]];932text += "(";933934for (int i = 0; i < argc; i++) {935if (i > 0) {936text += ", ";937}938text += DADDR(1 + i);939}940text += ")";941942incr = 4 + argc;943} break;944case OPCODE_CALL_GDSCRIPT_UTILITY: {945int instr_var_args = _code_ptr[++ip];946947text += "call-gdscript-utility ";948949int argc = _code_ptr[ip + 1 + instr_var_args];950text += DADDR(1 + argc) + " = ";951952text += gds_utilities_names[_code_ptr[ip + 3 + argc]];953text += "(";954955for (int i = 0; i < argc; i++) {956if (i > 0) {957text += ", ";958}959text += DADDR(1 + i);960}961text += ")";962963incr = 4 + argc;964} break;965case OPCODE_CALL_SELF_BASE: {966int instr_var_args = _code_ptr[++ip];967968text += "call-self-base ";969970int argc = _code_ptr[ip + 1 + instr_var_args];971text += DADDR(2 + argc) + " = ";972973text += _global_names_ptr[_code_ptr[ip + 2 + instr_var_args]];974text += "(";975976for (int i = 0; i < argc; i++) {977if (i > 0) {978text += ", ";979}980text += DADDR(1 + i);981}982text += ")";983984incr = 4 + argc;985} break;986case OPCODE_AWAIT: {987text += "await ";988text += DADDR(1);989990incr = 2;991} break;992case OPCODE_AWAIT_RESUME: {993text += "await resume ";994text += DADDR(1);995996incr = 2;997} break;998case OPCODE_CREATE_LAMBDA: {999int instr_var_args = _code_ptr[++ip];1000int captures_count = _code_ptr[ip + 1 + instr_var_args];1001GDScriptFunction *lambda = _lambdas_ptr[_code_ptr[ip + 2 + instr_var_args]];10021003text += DADDR(1 + captures_count);1004text += "create lambda from ";1005text += lambda->name.operator String();1006text += "function, captures (";10071008for (int i = 0; i < captures_count; i++) {1009if (i > 0) {1010text += ", ";1011}1012text += DADDR(1 + i);1013}1014text += ")";10151016incr = 4 + captures_count;1017} break;1018case OPCODE_CREATE_SELF_LAMBDA: {1019int instr_var_args = _code_ptr[++ip];1020int captures_count = _code_ptr[ip + 1 + instr_var_args];1021GDScriptFunction *lambda = _lambdas_ptr[_code_ptr[ip + 2 + instr_var_args]];10221023text += DADDR(1 + captures_count);1024text += "create self lambda from ";1025text += lambda->name.operator String();1026text += "function, captures (";10271028for (int i = 0; i < captures_count; i++) {1029if (i > 0) {1030text += ", ";1031}1032text += DADDR(1 + i);1033}1034text += ")";10351036incr = 4 + captures_count;1037} break;1038case OPCODE_JUMP: {1039text += "jump ";1040text += itos(_code_ptr[ip + 1]);10411042incr = 2;1043} break;1044case OPCODE_JUMP_IF: {1045text += "jump-if ";1046text += DADDR(1);1047text += " to ";1048text += itos(_code_ptr[ip + 2]);10491050incr = 3;1051} break;1052case OPCODE_JUMP_IF_NOT: {1053text += "jump-if-not ";1054text += DADDR(1);1055text += " to ";1056text += itos(_code_ptr[ip + 2]);10571058incr = 3;1059} break;1060case OPCODE_JUMP_TO_DEF_ARGUMENT: {1061text += "jump-to-default-argument ";10621063incr = 1;1064} break;1065case OPCODE_JUMP_IF_SHARED: {1066text += "jump-if-shared ";1067text += DADDR(1);1068text += " to ";1069text += itos(_code_ptr[ip + 2]);10701071incr = 3;1072} break;1073case OPCODE_RETURN: {1074text += "return ";1075text += DADDR(1);10761077incr = 2;1078} break;1079case OPCODE_RETURN_TYPED_BUILTIN: {1080text += "return typed builtin (";1081text += Variant::get_type_name((Variant::Type)_code_ptr[ip + 2]);1082text += ") ";1083text += DADDR(1);10841085incr += 3;1086} break;1087case OPCODE_RETURN_TYPED_ARRAY: {1088text += "return typed array ";1089text += DADDR(1);10901091incr += 5;1092} break;1093case OPCODE_RETURN_TYPED_DICTIONARY: {1094text += "return typed dictionary ";1095text += DADDR(1);10961097incr += 8;1098} break;1099case OPCODE_RETURN_TYPED_NATIVE: {1100text += "return typed native (";1101text += DADDR(2);1102text += ") ";1103text += DADDR(1);11041105incr += 3;1106} break;1107case OPCODE_RETURN_TYPED_SCRIPT: {1108Ref<Script> script = get_constant(_code_ptr[ip + 2] & ADDR_MASK);11091110text += "return typed script (";1111text += GDScript::debug_get_script_name(script);1112text += ") ";1113text += DADDR(1);11141115incr += 3;1116} break;11171118#define DISASSEMBLE_ITERATE(m_type) \1119case OPCODE_ITERATE_##m_type: { \1120text += "for-loop (typed "; \1121text += #m_type; \1122text += ") "; \1123text += DADDR(3); \1124text += " in "; \1125text += DADDR(2); \1126text += " counter "; \1127text += DADDR(1); \1128text += " end "; \1129text += itos(_code_ptr[ip + 4]); \1130incr += 5; \1131} break11321133#define DISASSEMBLE_ITERATE_BEGIN(m_type) \1134case OPCODE_ITERATE_BEGIN_##m_type: { \1135text += "for-init (typed "; \1136text += #m_type; \1137text += ") "; \1138text += DADDR(3); \1139text += " in "; \1140text += DADDR(2); \1141text += " counter "; \1142text += DADDR(1); \1143text += " end "; \1144text += itos(_code_ptr[ip + 4]); \1145incr += 5; \1146} break11471148#define DISASSEMBLE_ITERATE_TYPES(m_macro) \1149m_macro(INT); \1150m_macro(FLOAT); \1151m_macro(VECTOR2); \1152m_macro(VECTOR2I); \1153m_macro(VECTOR3); \1154m_macro(VECTOR3I); \1155m_macro(STRING); \1156m_macro(DICTIONARY); \1157m_macro(ARRAY); \1158m_macro(PACKED_BYTE_ARRAY); \1159m_macro(PACKED_INT32_ARRAY); \1160m_macro(PACKED_INT64_ARRAY); \1161m_macro(PACKED_FLOAT32_ARRAY); \1162m_macro(PACKED_FLOAT64_ARRAY); \1163m_macro(PACKED_STRING_ARRAY); \1164m_macro(PACKED_VECTOR2_ARRAY); \1165m_macro(PACKED_VECTOR3_ARRAY); \1166m_macro(PACKED_COLOR_ARRAY); \1167m_macro(PACKED_VECTOR4_ARRAY); \1168m_macro(OBJECT)11691170case OPCODE_ITERATE_BEGIN: {1171text += "for-init ";1172text += DADDR(3);1173text += " in ";1174text += DADDR(2);1175text += " counter ";1176text += DADDR(1);1177text += " end ";1178text += itos(_code_ptr[ip + 4]);11791180incr += 5;1181} break;1182DISASSEMBLE_ITERATE_TYPES(DISASSEMBLE_ITERATE_BEGIN);1183case OPCODE_ITERATE_BEGIN_RANGE: {1184text += "for-init ";1185text += DADDR(5);1186text += " in range from ";1187text += DADDR(2);1188text += " to ";1189text += DADDR(3);1190text += " step ";1191text += DADDR(4);1192text += " counter ";1193text += DADDR(1);1194text += " end ";1195text += itos(_code_ptr[ip + 6]);11961197incr += 7;1198} break;1199case OPCODE_ITERATE: {1200text += "for-loop ";1201text += DADDR(3);1202text += " in ";1203text += DADDR(2);1204text += " counter ";1205text += DADDR(1);1206text += " end ";1207text += itos(_code_ptr[ip + 4]);12081209incr += 5;1210} break;1211DISASSEMBLE_ITERATE_TYPES(DISASSEMBLE_ITERATE);1212case OPCODE_ITERATE_RANGE: {1213text += "for-loop ";1214text += DADDR(4);1215text += " in range to ";1216text += DADDR(2);1217text += " step ";1218text += DADDR(3);1219text += " counter ";1220text += DADDR(1);1221text += " end ";1222text += itos(_code_ptr[ip + 5]);12231224incr += 6;1225} break;1226case OPCODE_STORE_GLOBAL: {1227text += "store global ";1228text += DADDR(1);1229text += " = ";1230text += String::num_int64(_code_ptr[ip + 2]);12311232incr += 3;1233} break;1234case OPCODE_STORE_NAMED_GLOBAL: {1235text += "store named global ";1236text += DADDR(1);1237text += " = ";1238text += String(_global_names_ptr[_code_ptr[ip + 2]]);12391240incr += 3;1241} break;1242case OPCODE_LINE: {1243int line = _code_ptr[ip + 1] - 1;1244if (line >= 0 && line < p_code_lines.size()) {1245text += "line ";1246text += itos(line + 1);1247text += ": ";1248text += p_code_lines[line];1249} else {1250text += "";1251}12521253incr += 2;1254} break;12551256#define DISASSEMBLE_TYPE_ADJUST(m_v_type) \1257case OPCODE_TYPE_ADJUST_##m_v_type: { \1258text += "type adjust ("; \1259text += #m_v_type; \1260text += ") "; \1261text += DADDR(1); \1262incr += 2; \1263} break12641265DISASSEMBLE_TYPE_ADJUST(BOOL);1266DISASSEMBLE_TYPE_ADJUST(INT);1267DISASSEMBLE_TYPE_ADJUST(FLOAT);1268DISASSEMBLE_TYPE_ADJUST(STRING);1269DISASSEMBLE_TYPE_ADJUST(VECTOR2);1270DISASSEMBLE_TYPE_ADJUST(VECTOR2I);1271DISASSEMBLE_TYPE_ADJUST(RECT2);1272DISASSEMBLE_TYPE_ADJUST(RECT2I);1273DISASSEMBLE_TYPE_ADJUST(VECTOR3);1274DISASSEMBLE_TYPE_ADJUST(VECTOR3I);1275DISASSEMBLE_TYPE_ADJUST(TRANSFORM2D);1276DISASSEMBLE_TYPE_ADJUST(VECTOR4);1277DISASSEMBLE_TYPE_ADJUST(VECTOR4I);1278DISASSEMBLE_TYPE_ADJUST(PLANE);1279DISASSEMBLE_TYPE_ADJUST(QUATERNION);1280DISASSEMBLE_TYPE_ADJUST(AABB);1281DISASSEMBLE_TYPE_ADJUST(BASIS);1282DISASSEMBLE_TYPE_ADJUST(TRANSFORM3D);1283DISASSEMBLE_TYPE_ADJUST(PROJECTION);1284DISASSEMBLE_TYPE_ADJUST(COLOR);1285DISASSEMBLE_TYPE_ADJUST(STRING_NAME);1286DISASSEMBLE_TYPE_ADJUST(NODE_PATH);1287DISASSEMBLE_TYPE_ADJUST(RID);1288DISASSEMBLE_TYPE_ADJUST(OBJECT);1289DISASSEMBLE_TYPE_ADJUST(CALLABLE);1290DISASSEMBLE_TYPE_ADJUST(SIGNAL);1291DISASSEMBLE_TYPE_ADJUST(DICTIONARY);1292DISASSEMBLE_TYPE_ADJUST(ARRAY);1293DISASSEMBLE_TYPE_ADJUST(PACKED_BYTE_ARRAY);1294DISASSEMBLE_TYPE_ADJUST(PACKED_INT32_ARRAY);1295DISASSEMBLE_TYPE_ADJUST(PACKED_INT64_ARRAY);1296DISASSEMBLE_TYPE_ADJUST(PACKED_FLOAT32_ARRAY);1297DISASSEMBLE_TYPE_ADJUST(PACKED_FLOAT64_ARRAY);1298DISASSEMBLE_TYPE_ADJUST(PACKED_STRING_ARRAY);1299DISASSEMBLE_TYPE_ADJUST(PACKED_VECTOR2_ARRAY);1300DISASSEMBLE_TYPE_ADJUST(PACKED_VECTOR3_ARRAY);1301DISASSEMBLE_TYPE_ADJUST(PACKED_COLOR_ARRAY);1302DISASSEMBLE_TYPE_ADJUST(PACKED_VECTOR4_ARRAY);13031304case OPCODE_ASSERT: {1305text += "assert (";1306text += DADDR(1);1307text += ", ";1308text += DADDR(2);1309text += ")";13101311incr += 3;1312} break;1313case OPCODE_BREAKPOINT: {1314text += "breakpoint";13151316incr += 1;1317} break;1318case OPCODE_END: {1319text += "== END ==";13201321incr += 1;1322} break;1323}13241325ip += incr;1326if (text.get_string_length() > 0) {1327print_line(text.as_string());1328}1329}1330}13311332#endif // DEBUG_ENABLED133313341335