Merge pull request #43725 from vnen/gdscript-typed-vm-2
GDScript: Typed VM Take 2
This commit is contained in:
commit
4ed42bfc29
|
@ -38,7 +38,82 @@
|
||||||
class VariantInternal {
|
class VariantInternal {
|
||||||
public:
|
public:
|
||||||
// Set type.
|
// Set type.
|
||||||
_FORCE_INLINE_ static void initialize(Variant *v, Variant::Type p_type) { v->type = p_type; }
|
_FORCE_INLINE_ static void initialize(Variant *v, Variant::Type p_type) {
|
||||||
|
v->clear();
|
||||||
|
v->type = p_type;
|
||||||
|
|
||||||
|
switch (p_type) {
|
||||||
|
case Variant::AABB:
|
||||||
|
init_aabb(v);
|
||||||
|
break;
|
||||||
|
case Variant::TRANSFORM2D:
|
||||||
|
init_transform2d(v);
|
||||||
|
break;
|
||||||
|
case Variant::TRANSFORM:
|
||||||
|
init_transform(v);
|
||||||
|
break;
|
||||||
|
case Variant::STRING:
|
||||||
|
init_string(v);
|
||||||
|
break;
|
||||||
|
case Variant::STRING_NAME:
|
||||||
|
init_string_name(v);
|
||||||
|
break;
|
||||||
|
case Variant::NODE_PATH:
|
||||||
|
init_node_path(v);
|
||||||
|
break;
|
||||||
|
case Variant::CALLABLE:
|
||||||
|
init_callable(v);
|
||||||
|
break;
|
||||||
|
case Variant::SIGNAL:
|
||||||
|
init_signal(v);
|
||||||
|
break;
|
||||||
|
case Variant::DICTIONARY:
|
||||||
|
init_dictionary(v);
|
||||||
|
break;
|
||||||
|
case Variant::ARRAY:
|
||||||
|
init_array(v);
|
||||||
|
break;
|
||||||
|
case Variant::PACKED_BYTE_ARRAY:
|
||||||
|
init_byte_array(v);
|
||||||
|
break;
|
||||||
|
case Variant::PACKED_INT32_ARRAY:
|
||||||
|
init_int32_array(v);
|
||||||
|
break;
|
||||||
|
case Variant::PACKED_INT64_ARRAY:
|
||||||
|
init_int64_array(v);
|
||||||
|
break;
|
||||||
|
case Variant::PACKED_FLOAT32_ARRAY:
|
||||||
|
init_float32_array(v);
|
||||||
|
break;
|
||||||
|
case Variant::PACKED_FLOAT64_ARRAY:
|
||||||
|
init_float64_array(v);
|
||||||
|
break;
|
||||||
|
case Variant::PACKED_STRING_ARRAY:
|
||||||
|
init_string_array(v);
|
||||||
|
break;
|
||||||
|
case Variant::PACKED_VECTOR2_ARRAY:
|
||||||
|
init_vector2_array(v);
|
||||||
|
break;
|
||||||
|
case Variant::PACKED_VECTOR3_ARRAY:
|
||||||
|
init_vector3_array(v);
|
||||||
|
break;
|
||||||
|
case Variant::PACKED_COLOR_ARRAY:
|
||||||
|
init_color_array(v);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ static void set_object(Variant *v, Object *obj) {
|
||||||
|
if (obj) {
|
||||||
|
v->_get_obj().obj = obj;
|
||||||
|
v->_get_obj().id = obj->get_instance_id();
|
||||||
|
} else {
|
||||||
|
v->_get_obj().obj = nullptr;
|
||||||
|
v->_get_obj().id = ObjectID();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Atomic types.
|
// Atomic types.
|
||||||
_FORCE_INLINE_ static bool *get_bool(Variant *v) { return &v->_data._bool; }
|
_FORCE_INLINE_ static bool *get_bool(Variant *v) { return &v->_data._bool; }
|
||||||
|
@ -216,6 +291,162 @@ public:
|
||||||
v->_get_obj().obj = nullptr;
|
v->_get_obj().obj = nullptr;
|
||||||
v->_get_obj().id = ObjectID();
|
v->_get_obj().id = ObjectID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ static void *get_opaque_pointer(Variant *v) {
|
||||||
|
switch (v->type) {
|
||||||
|
case Variant::NIL:
|
||||||
|
return nullptr;
|
||||||
|
case Variant::BOOL:
|
||||||
|
return get_bool(v);
|
||||||
|
case Variant::INT:
|
||||||
|
return get_int(v);
|
||||||
|
case Variant::FLOAT:
|
||||||
|
return get_float(v);
|
||||||
|
case Variant::STRING:
|
||||||
|
return get_string(v);
|
||||||
|
case Variant::VECTOR2:
|
||||||
|
return get_vector2(v);
|
||||||
|
case Variant::VECTOR2I:
|
||||||
|
return get_vector2i(v);
|
||||||
|
case Variant::VECTOR3:
|
||||||
|
return get_vector3(v);
|
||||||
|
case Variant::VECTOR3I:
|
||||||
|
return get_vector3i(v);
|
||||||
|
case Variant::RECT2:
|
||||||
|
return get_rect2(v);
|
||||||
|
case Variant::RECT2I:
|
||||||
|
return get_rect2i(v);
|
||||||
|
case Variant::TRANSFORM:
|
||||||
|
return get_transform(v);
|
||||||
|
case Variant::TRANSFORM2D:
|
||||||
|
return get_transform2d(v);
|
||||||
|
case Variant::QUAT:
|
||||||
|
return get_quat(v);
|
||||||
|
case Variant::PLANE:
|
||||||
|
return get_plane(v);
|
||||||
|
case Variant::BASIS:
|
||||||
|
return get_basis(v);
|
||||||
|
case Variant::AABB:
|
||||||
|
return get_aabb(v);
|
||||||
|
case Variant::COLOR:
|
||||||
|
return get_color(v);
|
||||||
|
case Variant::STRING_NAME:
|
||||||
|
return get_string_name(v);
|
||||||
|
case Variant::NODE_PATH:
|
||||||
|
return get_node_path(v);
|
||||||
|
case Variant::RID:
|
||||||
|
return get_rid(v);
|
||||||
|
case Variant::CALLABLE:
|
||||||
|
return get_callable(v);
|
||||||
|
case Variant::SIGNAL:
|
||||||
|
return get_signal(v);
|
||||||
|
case Variant::DICTIONARY:
|
||||||
|
return get_dictionary(v);
|
||||||
|
case Variant::ARRAY:
|
||||||
|
return get_array(v);
|
||||||
|
case Variant::PACKED_BYTE_ARRAY:
|
||||||
|
return get_byte_array(v);
|
||||||
|
case Variant::PACKED_INT32_ARRAY:
|
||||||
|
return get_int32_array(v);
|
||||||
|
case Variant::PACKED_INT64_ARRAY:
|
||||||
|
return get_int64_array(v);
|
||||||
|
case Variant::PACKED_FLOAT32_ARRAY:
|
||||||
|
return get_float32_array(v);
|
||||||
|
case Variant::PACKED_FLOAT64_ARRAY:
|
||||||
|
return get_float64_array(v);
|
||||||
|
case Variant::PACKED_STRING_ARRAY:
|
||||||
|
return get_string_array(v);
|
||||||
|
case Variant::PACKED_VECTOR2_ARRAY:
|
||||||
|
return get_vector2_array(v);
|
||||||
|
case Variant::PACKED_VECTOR3_ARRAY:
|
||||||
|
return get_vector3_array(v);
|
||||||
|
case Variant::PACKED_COLOR_ARRAY:
|
||||||
|
return get_color_array(v);
|
||||||
|
case Variant::OBJECT:
|
||||||
|
return v->_get_obj().obj;
|
||||||
|
case Variant::VARIANT_MAX:
|
||||||
|
ERR_FAIL_V(nullptr);
|
||||||
|
}
|
||||||
|
ERR_FAIL_V(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
_FORCE_INLINE_ static const void *get_opaque_pointer(const Variant *v) {
|
||||||
|
switch (v->type) {
|
||||||
|
case Variant::NIL:
|
||||||
|
return nullptr;
|
||||||
|
case Variant::BOOL:
|
||||||
|
return get_bool(v);
|
||||||
|
case Variant::INT:
|
||||||
|
return get_int(v);
|
||||||
|
case Variant::FLOAT:
|
||||||
|
return get_float(v);
|
||||||
|
case Variant::STRING:
|
||||||
|
return get_string(v);
|
||||||
|
case Variant::VECTOR2:
|
||||||
|
return get_vector2(v);
|
||||||
|
case Variant::VECTOR2I:
|
||||||
|
return get_vector2i(v);
|
||||||
|
case Variant::VECTOR3:
|
||||||
|
return get_vector3(v);
|
||||||
|
case Variant::VECTOR3I:
|
||||||
|
return get_vector3i(v);
|
||||||
|
case Variant::RECT2:
|
||||||
|
return get_rect2(v);
|
||||||
|
case Variant::RECT2I:
|
||||||
|
return get_rect2i(v);
|
||||||
|
case Variant::TRANSFORM:
|
||||||
|
return get_transform(v);
|
||||||
|
case Variant::TRANSFORM2D:
|
||||||
|
return get_transform2d(v);
|
||||||
|
case Variant::QUAT:
|
||||||
|
return get_quat(v);
|
||||||
|
case Variant::PLANE:
|
||||||
|
return get_plane(v);
|
||||||
|
case Variant::BASIS:
|
||||||
|
return get_basis(v);
|
||||||
|
case Variant::AABB:
|
||||||
|
return get_aabb(v);
|
||||||
|
case Variant::COLOR:
|
||||||
|
return get_color(v);
|
||||||
|
case Variant::STRING_NAME:
|
||||||
|
return get_string_name(v);
|
||||||
|
case Variant::NODE_PATH:
|
||||||
|
return get_node_path(v);
|
||||||
|
case Variant::RID:
|
||||||
|
return get_rid(v);
|
||||||
|
case Variant::CALLABLE:
|
||||||
|
return get_callable(v);
|
||||||
|
case Variant::SIGNAL:
|
||||||
|
return get_signal(v);
|
||||||
|
case Variant::DICTIONARY:
|
||||||
|
return get_dictionary(v);
|
||||||
|
case Variant::ARRAY:
|
||||||
|
return get_array(v);
|
||||||
|
case Variant::PACKED_BYTE_ARRAY:
|
||||||
|
return get_byte_array(v);
|
||||||
|
case Variant::PACKED_INT32_ARRAY:
|
||||||
|
return get_int32_array(v);
|
||||||
|
case Variant::PACKED_INT64_ARRAY:
|
||||||
|
return get_int64_array(v);
|
||||||
|
case Variant::PACKED_FLOAT32_ARRAY:
|
||||||
|
return get_float32_array(v);
|
||||||
|
case Variant::PACKED_FLOAT64_ARRAY:
|
||||||
|
return get_float64_array(v);
|
||||||
|
case Variant::PACKED_STRING_ARRAY:
|
||||||
|
return get_string_array(v);
|
||||||
|
case Variant::PACKED_VECTOR2_ARRAY:
|
||||||
|
return get_vector2_array(v);
|
||||||
|
case Variant::PACKED_VECTOR3_ARRAY:
|
||||||
|
return get_vector3_array(v);
|
||||||
|
case Variant::PACKED_COLOR_ARRAY:
|
||||||
|
return get_color_array(v);
|
||||||
|
case Variant::OBJECT:
|
||||||
|
return v->_get_obj().obj;
|
||||||
|
case Variant::VARIANT_MAX:
|
||||||
|
ERR_FAIL_V(nullptr);
|
||||||
|
}
|
||||||
|
ERR_FAIL_V(nullptr);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -33,6 +33,8 @@
|
||||||
|
|
||||||
#include "gdscript_codegen.h"
|
#include "gdscript_codegen.h"
|
||||||
|
|
||||||
|
#include "gdscript_function.h"
|
||||||
|
|
||||||
class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
|
class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
|
||||||
bool ended = false;
|
bool ended = false;
|
||||||
GDScriptFunction *function = nullptr;
|
GDScriptFunction *function = nullptr;
|
||||||
|
@ -49,15 +51,26 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
|
||||||
|
|
||||||
int current_stack_size = 0;
|
int current_stack_size = 0;
|
||||||
int current_temporaries = 0;
|
int current_temporaries = 0;
|
||||||
|
int current_line = 0;
|
||||||
|
int stack_max = 0;
|
||||||
|
int instr_args_max = 0;
|
||||||
|
int ptrcall_max = 0;
|
||||||
|
|
||||||
HashMap<Variant, int, VariantHasher, VariantComparator> constant_map;
|
HashMap<Variant, int, VariantHasher, VariantComparator> constant_map;
|
||||||
Map<StringName, int> name_map;
|
Map<StringName, int> name_map;
|
||||||
#ifdef TOOLS_ENABLED
|
#ifdef TOOLS_ENABLED
|
||||||
Vector<StringName> named_globals;
|
Vector<StringName> named_globals;
|
||||||
#endif
|
#endif
|
||||||
int current_line = 0;
|
Map<Variant::ValidatedOperatorEvaluator, int> operator_func_map;
|
||||||
int stack_max = 0;
|
Map<Variant::ValidatedSetter, int> setters_map;
|
||||||
int call_max = 0;
|
Map<Variant::ValidatedGetter, int> getters_map;
|
||||||
|
Map<Variant::ValidatedKeyedSetter, int> keyed_setters_map;
|
||||||
|
Map<Variant::ValidatedKeyedGetter, int> keyed_getters_map;
|
||||||
|
Map<Variant::ValidatedIndexedSetter, int> indexed_setters_map;
|
||||||
|
Map<Variant::ValidatedIndexedGetter, int> indexed_getters_map;
|
||||||
|
Map<Variant::ValidatedBuiltInMethod, int> builtin_method_map;
|
||||||
|
Map<Variant::ValidatedConstructor, int> constructors_map;
|
||||||
|
Map<MethodBind *, int> method_bind_map;
|
||||||
|
|
||||||
List<int> if_jmp_addrs; // List since this can be nested.
|
List<int> if_jmp_addrs; // List since this can be nested.
|
||||||
List<int> for_jmp_addrs;
|
List<int> for_jmp_addrs;
|
||||||
|
@ -134,22 +147,105 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int get_operation_pos(const Variant::ValidatedOperatorEvaluator p_operation) {
|
||||||
|
if (operator_func_map.has(p_operation))
|
||||||
|
return operator_func_map[p_operation];
|
||||||
|
int pos = operator_func_map.size();
|
||||||
|
operator_func_map[p_operation] = pos;
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_setter_pos(const Variant::ValidatedSetter p_setter) {
|
||||||
|
if (setters_map.has(p_setter))
|
||||||
|
return setters_map[p_setter];
|
||||||
|
int pos = setters_map.size();
|
||||||
|
setters_map[p_setter] = pos;
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_getter_pos(const Variant::ValidatedGetter p_getter) {
|
||||||
|
if (getters_map.has(p_getter))
|
||||||
|
return getters_map[p_getter];
|
||||||
|
int pos = getters_map.size();
|
||||||
|
getters_map[p_getter] = pos;
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_keyed_setter_pos(const Variant::ValidatedKeyedSetter p_keyed_setter) {
|
||||||
|
if (keyed_setters_map.has(p_keyed_setter))
|
||||||
|
return keyed_setters_map[p_keyed_setter];
|
||||||
|
int pos = keyed_setters_map.size();
|
||||||
|
keyed_setters_map[p_keyed_setter] = pos;
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_keyed_getter_pos(const Variant::ValidatedKeyedGetter p_keyed_getter) {
|
||||||
|
if (keyed_getters_map.has(p_keyed_getter))
|
||||||
|
return keyed_getters_map[p_keyed_getter];
|
||||||
|
int pos = keyed_getters_map.size();
|
||||||
|
keyed_getters_map[p_keyed_getter] = pos;
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_indexed_setter_pos(const Variant::ValidatedIndexedSetter p_indexed_setter) {
|
||||||
|
if (indexed_setters_map.has(p_indexed_setter))
|
||||||
|
return indexed_setters_map[p_indexed_setter];
|
||||||
|
int pos = indexed_setters_map.size();
|
||||||
|
indexed_setters_map[p_indexed_setter] = pos;
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_indexed_getter_pos(const Variant::ValidatedIndexedGetter p_indexed_getter) {
|
||||||
|
if (indexed_getters_map.has(p_indexed_getter))
|
||||||
|
return indexed_getters_map[p_indexed_getter];
|
||||||
|
int pos = indexed_getters_map.size();
|
||||||
|
indexed_getters_map[p_indexed_getter] = pos;
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_builtin_method_pos(const Variant::ValidatedBuiltInMethod p_method) {
|
||||||
|
if (builtin_method_map.has(p_method)) {
|
||||||
|
return builtin_method_map[p_method];
|
||||||
|
}
|
||||||
|
int pos = builtin_method_map.size();
|
||||||
|
builtin_method_map[p_method] = pos;
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_constructor_pos(const Variant::ValidatedConstructor p_constructor) {
|
||||||
|
if (constructors_map.has(p_constructor)) {
|
||||||
|
return constructors_map[p_constructor];
|
||||||
|
}
|
||||||
|
int pos = constructors_map.size();
|
||||||
|
constructors_map[p_constructor] = pos;
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_method_bind_pos(MethodBind *p_method) {
|
||||||
|
if (method_bind_map.has(p_method)) {
|
||||||
|
return method_bind_map[p_method];
|
||||||
|
}
|
||||||
|
int pos = method_bind_map.size();
|
||||||
|
method_bind_map[p_method] = pos;
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
void alloc_stack(int p_level) {
|
void alloc_stack(int p_level) {
|
||||||
if (p_level >= stack_max)
|
if (p_level >= stack_max)
|
||||||
stack_max = p_level + 1;
|
stack_max = p_level + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void alloc_call(int p_params) {
|
|
||||||
if (p_params >= call_max)
|
|
||||||
call_max = p_params;
|
|
||||||
}
|
|
||||||
|
|
||||||
int increase_stack() {
|
int increase_stack() {
|
||||||
int top = current_stack_size++;
|
int top = current_stack_size++;
|
||||||
alloc_stack(current_stack_size);
|
alloc_stack(current_stack_size);
|
||||||
return top;
|
return top;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void alloc_ptrcall(int p_params) {
|
||||||
|
if (p_params >= ptrcall_max)
|
||||||
|
ptrcall_max = p_params;
|
||||||
|
}
|
||||||
|
|
||||||
int address_of(const Address &p_address) {
|
int address_of(const Address &p_address) {
|
||||||
switch (p_address.mode) {
|
switch (p_address.mode) {
|
||||||
case Address::SELF:
|
case Address::SELF:
|
||||||
|
@ -177,8 +273,13 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
|
||||||
return -1; // Unreachable.
|
return -1; // Unreachable.
|
||||||
}
|
}
|
||||||
|
|
||||||
void append(int code) {
|
void append(GDScriptFunction::Opcode p_code, int p_argument_count) {
|
||||||
opcodes.push_back(code);
|
opcodes.push_back((p_code & GDScriptFunction::INSTR_MASK) | (p_argument_count << GDScriptFunction::INSTR_BITS));
|
||||||
|
instr_args_max = MAX(instr_args_max, p_argument_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void append(int p_code) {
|
||||||
|
opcodes.push_back(p_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
void append(const Address &p_address) {
|
void append(const Address &p_address) {
|
||||||
|
@ -189,6 +290,46 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
|
||||||
opcodes.push_back(get_name_map_pos(p_name));
|
opcodes.push_back(get_name_map_pos(p_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void append(const Variant::ValidatedOperatorEvaluator p_operation) {
|
||||||
|
opcodes.push_back(get_operation_pos(p_operation));
|
||||||
|
}
|
||||||
|
|
||||||
|
void append(const Variant::ValidatedSetter p_setter) {
|
||||||
|
opcodes.push_back(get_setter_pos(p_setter));
|
||||||
|
}
|
||||||
|
|
||||||
|
void append(const Variant::ValidatedGetter p_getter) {
|
||||||
|
opcodes.push_back(get_getter_pos(p_getter));
|
||||||
|
}
|
||||||
|
|
||||||
|
void append(const Variant::ValidatedKeyedSetter p_keyed_setter) {
|
||||||
|
opcodes.push_back(get_keyed_setter_pos(p_keyed_setter));
|
||||||
|
}
|
||||||
|
|
||||||
|
void append(const Variant::ValidatedKeyedGetter p_keyed_getter) {
|
||||||
|
opcodes.push_back(get_keyed_getter_pos(p_keyed_getter));
|
||||||
|
}
|
||||||
|
|
||||||
|
void append(const Variant::ValidatedIndexedSetter p_indexed_setter) {
|
||||||
|
opcodes.push_back(get_indexed_setter_pos(p_indexed_setter));
|
||||||
|
}
|
||||||
|
|
||||||
|
void append(const Variant::ValidatedIndexedGetter p_indexed_getter) {
|
||||||
|
opcodes.push_back(get_indexed_getter_pos(p_indexed_getter));
|
||||||
|
}
|
||||||
|
|
||||||
|
void append(const Variant::ValidatedBuiltInMethod p_method) {
|
||||||
|
opcodes.push_back(get_builtin_method_pos(p_method));
|
||||||
|
}
|
||||||
|
|
||||||
|
void append(const Variant::ValidatedConstructor p_constructor) {
|
||||||
|
opcodes.push_back(get_constructor_pos(p_constructor));
|
||||||
|
}
|
||||||
|
|
||||||
|
void append(MethodBind *p_method) {
|
||||||
|
opcodes.push_back(get_method_bind_pos(p_method));
|
||||||
|
}
|
||||||
|
|
||||||
void patch_jump(int p_address) {
|
void patch_jump(int p_address) {
|
||||||
opcodes.write[p_address] = opcodes.size();
|
opcodes.write[p_address] = opcodes.size();
|
||||||
}
|
}
|
||||||
|
@ -244,8 +385,9 @@ public:
|
||||||
virtual void write_super_call(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) override;
|
virtual void write_super_call(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) override;
|
||||||
virtual void write_call_async(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) override;
|
virtual void write_call_async(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) override;
|
||||||
virtual void write_call_builtin(const Address &p_target, GDScriptFunctions::Function p_function, const Vector<Address> &p_arguments) override;
|
virtual void write_call_builtin(const Address &p_target, GDScriptFunctions::Function p_function, const Vector<Address> &p_arguments) override;
|
||||||
virtual void write_call_method_bind(const Address &p_target, const Address &p_base, const MethodBind *p_method, const Vector<Address> &p_arguments) override;
|
virtual void 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) override;
|
||||||
virtual void write_call_ptrcall(const Address &p_target, const Address &p_base, const MethodBind *p_method, const Vector<Address> &p_arguments) override;
|
virtual void write_call_method_bind(const Address &p_target, const Address &p_base, MethodBind *p_method, const Vector<Address> &p_arguments) override;
|
||||||
|
virtual void write_call_ptrcall(const Address &p_target, const Address &p_base, MethodBind *p_method, const Vector<Address> &p_arguments) override;
|
||||||
virtual void write_call_self(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) override;
|
virtual void write_call_self(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) override;
|
||||||
virtual void write_call_script_function(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) override;
|
virtual void write_call_script_function(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) override;
|
||||||
virtual void write_construct(const Address &p_target, Variant::Type p_type, const Vector<Address> &p_arguments) override;
|
virtual void write_construct(const Address &p_target, Variant::Type p_type, const Vector<Address> &p_arguments) override;
|
||||||
|
|
|
@ -126,8 +126,9 @@ public:
|
||||||
virtual void write_super_call(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) = 0;
|
virtual void write_super_call(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) = 0;
|
||||||
virtual void write_call_async(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) = 0;
|
virtual void write_call_async(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) = 0;
|
||||||
virtual void write_call_builtin(const Address &p_target, GDScriptFunctions::Function p_function, const Vector<Address> &p_arguments) = 0;
|
virtual void write_call_builtin(const Address &p_target, GDScriptFunctions::Function p_function, const Vector<Address> &p_arguments) = 0;
|
||||||
virtual void write_call_method_bind(const Address &p_target, const Address &p_base, const MethodBind *p_method, const Vector<Address> &p_arguments) = 0;
|
virtual void 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) = 0;
|
||||||
virtual void write_call_ptrcall(const Address &p_target, const Address &p_base, const MethodBind *p_method, const Vector<Address> &p_arguments) = 0;
|
virtual void write_call_method_bind(const Address &p_target, const Address &p_base, MethodBind *p_method, const Vector<Address> &p_arguments) = 0;
|
||||||
|
virtual void write_call_ptrcall(const Address &p_target, const Address &p_base, MethodBind *p_method, const Vector<Address> &p_arguments) = 0;
|
||||||
virtual void write_call_self(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) = 0;
|
virtual void write_call_self(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) = 0;
|
||||||
virtual void write_call_script_function(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) = 0;
|
virtual void write_call_script_function(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) = 0;
|
||||||
virtual void write_construct(const Address &p_target, Variant::Type p_type, const Vector<Address> &p_arguments) = 0;
|
virtual void write_construct(const Address &p_target, Variant::Type p_type, const Vector<Address> &p_arguments) = 0;
|
||||||
|
|
|
@ -158,6 +158,48 @@ GDScriptDataType GDScriptCompiler::_gdtype_from_datatype(const GDScriptParser::D
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool _is_exact_type(const PropertyInfo &p_par_type, const GDScriptDataType &p_arg_type) {
|
||||||
|
if (!p_arg_type.has_type) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (p_par_type.type == Variant::NIL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (p_par_type.type == Variant::OBJECT) {
|
||||||
|
if (p_arg_type.kind == GDScriptDataType::BUILTIN) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
StringName class_name;
|
||||||
|
if (p_arg_type.kind == GDScriptDataType::NATIVE) {
|
||||||
|
class_name = p_arg_type.native_type;
|
||||||
|
} else {
|
||||||
|
class_name = p_arg_type.native_type == StringName() ? p_arg_type.script_type->get_instance_base_type() : p_arg_type.native_type;
|
||||||
|
}
|
||||||
|
return p_par_type.class_name == class_name || ClassDB::is_parent_class(class_name, p_par_type.class_name);
|
||||||
|
} else {
|
||||||
|
if (p_arg_type.kind != GDScriptDataType::BUILTIN) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return p_par_type.type == p_arg_type.builtin_type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool _have_exact_arguments(const MethodBind *p_method, const Vector<GDScriptCodeGenerator::Address> &p_arguments) {
|
||||||
|
if (p_method->get_argument_count() != p_arguments.size()) {
|
||||||
|
// ptrcall won't work with default arguments.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
MethodInfo info;
|
||||||
|
ClassDB::get_method_info(p_method->get_instance_class(), p_method->get_name(), &info);
|
||||||
|
for (int i = 0; i < p_arguments.size(); i++) {
|
||||||
|
const PropertyInfo &prop = info.arguments[i];
|
||||||
|
if (!_is_exact_type(prop, p_arguments[i].type)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &codegen, Error &r_error, const GDScriptParser::ExpressionNode *p_expression, bool p_root, bool p_initializer, const GDScriptCodeGenerator::Address &p_index_addr) {
|
GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &codegen, Error &r_error, const GDScriptParser::ExpressionNode *p_expression, bool p_root, bool p_initializer, const GDScriptCodeGenerator::Address &p_index_addr) {
|
||||||
if (p_expression->is_constant) {
|
if (p_expression->is_constant) {
|
||||||
return codegen.add_constant(p_expression->reduced_value);
|
return codegen.add_constant(p_expression->reduced_value);
|
||||||
|
@ -430,7 +472,20 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
|
||||||
} else {
|
} else {
|
||||||
if (callee->type == GDScriptParser::Node::IDENTIFIER) {
|
if (callee->type == GDScriptParser::Node::IDENTIFIER) {
|
||||||
// Self function call.
|
// Self function call.
|
||||||
if ((codegen.function_node && codegen.function_node->is_static) || call->function_name == "new") {
|
if (ClassDB::has_method(codegen.script->native->get_name(), call->function_name)) {
|
||||||
|
// Native method, use faster path.
|
||||||
|
GDScriptCodeGenerator::Address self;
|
||||||
|
self.mode = GDScriptCodeGenerator::Address::SELF;
|
||||||
|
MethodBind *method = ClassDB::get_method(codegen.script->native->get_name(), call->function_name);
|
||||||
|
|
||||||
|
if (_have_exact_arguments(method, arguments)) {
|
||||||
|
// Exact arguments, use ptrcall.
|
||||||
|
gen->write_call_ptrcall(result, self, method, arguments);
|
||||||
|
} else {
|
||||||
|
// Not exact arguments, but still can use method bind call.
|
||||||
|
gen->write_call_method_bind(result, self, method, arguments);
|
||||||
|
}
|
||||||
|
} else if ((codegen.function_node && codegen.function_node->is_static) || call->function_name == "new") {
|
||||||
GDScriptCodeGenerator::Address self;
|
GDScriptCodeGenerator::Address self;
|
||||||
self.mode = GDScriptCodeGenerator::Address::CLASS;
|
self.mode = GDScriptCodeGenerator::Address::CLASS;
|
||||||
gen->write_call(result, self, call->function_name, arguments);
|
gen->write_call(result, self, call->function_name, arguments);
|
||||||
|
@ -447,6 +502,28 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
|
||||||
}
|
}
|
||||||
if (within_await) {
|
if (within_await) {
|
||||||
gen->write_call_async(result, base, call->function_name, arguments);
|
gen->write_call_async(result, base, call->function_name, arguments);
|
||||||
|
} else if (base.type.has_type && base.type.kind != GDScriptDataType::BUILTIN) {
|
||||||
|
// Native method, use faster path.
|
||||||
|
StringName class_name;
|
||||||
|
if (base.type.kind == GDScriptDataType::NATIVE) {
|
||||||
|
class_name = base.type.native_type;
|
||||||
|
} else {
|
||||||
|
class_name = base.type.native_type == StringName() ? base.type.script_type->get_instance_base_type() : base.type.native_type;
|
||||||
|
}
|
||||||
|
if (ClassDB::class_exists(class_name) && ClassDB::has_method(class_name, call->function_name)) {
|
||||||
|
MethodBind *method = ClassDB::get_method(class_name, call->function_name);
|
||||||
|
if (_have_exact_arguments(method, arguments)) {
|
||||||
|
// Exact arguments, use ptrcall.
|
||||||
|
gen->write_call_ptrcall(result, base, method, arguments);
|
||||||
|
} else {
|
||||||
|
// Not exact arguments, but still can use method bind call.
|
||||||
|
gen->write_call_method_bind(result, base, method, arguments);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
gen->write_call(result, base, call->function_name, arguments);
|
||||||
|
}
|
||||||
|
} else if (base.type.has_type && base.type.kind == GDScriptDataType::BUILTIN) {
|
||||||
|
gen->write_call_builtin_type(result, base, base.type.builtin_type, call->function_name, arguments);
|
||||||
} else {
|
} else {
|
||||||
gen->write_call(result, base, call->function_name, arguments);
|
gen->write_call(result, base, call->function_name, arguments);
|
||||||
}
|
}
|
||||||
|
@ -493,7 +570,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
|
||||||
GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(get_node->get_datatype()));
|
GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(get_node->get_datatype()));
|
||||||
|
|
||||||
MethodBind *get_node_method = ClassDB::get_method("Node", "get_node");
|
MethodBind *get_node_method = ClassDB::get_method("Node", "get_node");
|
||||||
gen->write_call_method_bind(result, GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::SELF), get_node_method, args);
|
gen->write_call_ptrcall(result, GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::SELF), get_node_method, args);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
} break;
|
} break;
|
||||||
|
|
|
@ -0,0 +1,813 @@
|
||||||
|
/*************************************************************************/
|
||||||
|
/* gdscript_disassembler.cpp */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/*************************************************************************/
|
||||||
|
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/*************************************************************************/
|
||||||
|
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
|
||||||
|
#include "gdscript_function.h"
|
||||||
|
|
||||||
|
#include "core/string/string_builder.h"
|
||||||
|
#include "gdscript.h"
|
||||||
|
#include "gdscript_functions.h"
|
||||||
|
|
||||||
|
static String _get_variant_string(const Variant &p_variant) {
|
||||||
|
String txt;
|
||||||
|
if (p_variant.get_type() == Variant::STRING) {
|
||||||
|
txt = "\"" + String(p_variant) + "\"";
|
||||||
|
} else if (p_variant.get_type() == Variant::STRING_NAME) {
|
||||||
|
txt = "&\"" + String(p_variant) + "\"";
|
||||||
|
} else if (p_variant.get_type() == Variant::NODE_PATH) {
|
||||||
|
txt = "^\"" + String(p_variant) + "\"";
|
||||||
|
} else if (p_variant.get_type() == Variant::OBJECT) {
|
||||||
|
Object *obj = p_variant;
|
||||||
|
if (!obj) {
|
||||||
|
txt = "null";
|
||||||
|
} else {
|
||||||
|
GDScriptNativeClass *cls = Object::cast_to<GDScriptNativeClass>(obj);
|
||||||
|
if (cls) {
|
||||||
|
txt += cls->get_name();
|
||||||
|
txt += " (class)";
|
||||||
|
} else {
|
||||||
|
txt = obj->get_class();
|
||||||
|
if (obj->get_script_instance()) {
|
||||||
|
txt += "(" + obj->get_script_instance()->get_script()->get_path() + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
txt = p_variant;
|
||||||
|
}
|
||||||
|
return txt;
|
||||||
|
}
|
||||||
|
|
||||||
|
static String _disassemble_address(const GDScript *p_script, const GDScriptFunction &p_function, int p_address) {
|
||||||
|
int addr = p_address & GDScriptFunction::ADDR_MASK;
|
||||||
|
|
||||||
|
switch (p_address >> GDScriptFunction::ADDR_BITS) {
|
||||||
|
case GDScriptFunction::ADDR_TYPE_SELF: {
|
||||||
|
return "self";
|
||||||
|
} break;
|
||||||
|
case GDScriptFunction::ADDR_TYPE_CLASS: {
|
||||||
|
return "class";
|
||||||
|
} break;
|
||||||
|
case GDScriptFunction::ADDR_TYPE_MEMBER: {
|
||||||
|
return "member(" + p_script->debug_get_member_by_index(addr) + ")";
|
||||||
|
} break;
|
||||||
|
case GDScriptFunction::ADDR_TYPE_CLASS_CONSTANT: {
|
||||||
|
return "class_const(" + p_function.get_global_name(addr) + ")";
|
||||||
|
} break;
|
||||||
|
case GDScriptFunction::ADDR_TYPE_LOCAL_CONSTANT: {
|
||||||
|
return "const(" + _get_variant_string(p_function.get_constant(addr)) + ")";
|
||||||
|
} break;
|
||||||
|
case GDScriptFunction::ADDR_TYPE_STACK: {
|
||||||
|
return "stack(" + itos(addr) + ")";
|
||||||
|
} break;
|
||||||
|
case GDScriptFunction::ADDR_TYPE_STACK_VARIABLE: {
|
||||||
|
return "var_stack(" + itos(addr) + ")";
|
||||||
|
} break;
|
||||||
|
case GDScriptFunction::ADDR_TYPE_GLOBAL: {
|
||||||
|
return "global(" + _get_variant_string(GDScriptLanguage::get_singleton()->get_global_array()[addr]) + ")";
|
||||||
|
} break;
|
||||||
|
case GDScriptFunction::ADDR_TYPE_NAMED_GLOBAL: {
|
||||||
|
return "named_global(" + p_function.get_global_name(addr) + ")";
|
||||||
|
} break;
|
||||||
|
case GDScriptFunction::ADDR_TYPE_NIL: {
|
||||||
|
return "nil";
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "<err>";
|
||||||
|
}
|
||||||
|
|
||||||
|
void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
|
||||||
|
#define DADDR(m_ip) (_disassemble_address(_script, *this, _code_ptr[ip + m_ip]))
|
||||||
|
|
||||||
|
for (int ip = 0; ip < _code_size;) {
|
||||||
|
StringBuilder text;
|
||||||
|
int incr = 0;
|
||||||
|
|
||||||
|
text += " ";
|
||||||
|
text += itos(ip);
|
||||||
|
text += ": ";
|
||||||
|
|
||||||
|
// This makes the compiler complain if some opcode is unchecked in the switch.
|
||||||
|
Opcode code = Opcode(_code_ptr[ip] & INSTR_MASK);
|
||||||
|
int instr_var_args = (_code_ptr[ip] & INSTR_ARGS_MASK) >> INSTR_BITS;
|
||||||
|
|
||||||
|
switch (code) {
|
||||||
|
case OPCODE_OPERATOR: {
|
||||||
|
int operation = _code_ptr[ip + 4];
|
||||||
|
|
||||||
|
text += "operator ";
|
||||||
|
|
||||||
|
text += DADDR(3);
|
||||||
|
text += " = ";
|
||||||
|
text += DADDR(1);
|
||||||
|
text += " ";
|
||||||
|
text += Variant::get_operator_name(Variant::Operator(operation));
|
||||||
|
text += " ";
|
||||||
|
text += DADDR(2);
|
||||||
|
|
||||||
|
incr += 5;
|
||||||
|
} break;
|
||||||
|
case OPCODE_OPERATOR_VALIDATED: {
|
||||||
|
text += "validated operator ";
|
||||||
|
|
||||||
|
text += DADDR(3);
|
||||||
|
text += " = ";
|
||||||
|
text += DADDR(1);
|
||||||
|
text += " <operator function> ";
|
||||||
|
text += DADDR(2);
|
||||||
|
|
||||||
|
incr += 5;
|
||||||
|
} break;
|
||||||
|
case OPCODE_EXTENDS_TEST: {
|
||||||
|
text += "is object ";
|
||||||
|
text += DADDR(3);
|
||||||
|
text += " = ";
|
||||||
|
text += DADDR(1);
|
||||||
|
text += " is ";
|
||||||
|
text += DADDR(2);
|
||||||
|
|
||||||
|
incr += 4;
|
||||||
|
} break;
|
||||||
|
case OPCODE_IS_BUILTIN: {
|
||||||
|
text += "is builtin ";
|
||||||
|
text += DADDR(2);
|
||||||
|
text += " = ";
|
||||||
|
text += DADDR(1);
|
||||||
|
text += " is ";
|
||||||
|
text += Variant::get_type_name(Variant::Type(_code_ptr[ip + 3]));
|
||||||
|
|
||||||
|
incr += 4;
|
||||||
|
} break;
|
||||||
|
case OPCODE_SET_KEYED: {
|
||||||
|
text += "set keyed ";
|
||||||
|
text += DADDR(1);
|
||||||
|
text += "[";
|
||||||
|
text += DADDR(2);
|
||||||
|
text += "] = ";
|
||||||
|
text += DADDR(3);
|
||||||
|
|
||||||
|
incr += 4;
|
||||||
|
} break;
|
||||||
|
case OPCODE_SET_KEYED_VALIDATED: {
|
||||||
|
text += "set keyed validated ";
|
||||||
|
text += DADDR(1);
|
||||||
|
text += "[";
|
||||||
|
text += DADDR(2);
|
||||||
|
text += "] = ";
|
||||||
|
text += DADDR(3);
|
||||||
|
|
||||||
|
incr += 5;
|
||||||
|
} break;
|
||||||
|
case OPCODE_SET_INDEXED_VALIDATED: {
|
||||||
|
text += "set indexed validated ";
|
||||||
|
text += DADDR(1);
|
||||||
|
text += "[";
|
||||||
|
text += DADDR(2);
|
||||||
|
text += "] = ";
|
||||||
|
text += DADDR(3);
|
||||||
|
|
||||||
|
incr += 5;
|
||||||
|
} break;
|
||||||
|
case OPCODE_GET_KEYED: {
|
||||||
|
text += "get keyed ";
|
||||||
|
text += DADDR(3);
|
||||||
|
text += " = ";
|
||||||
|
text += DADDR(1);
|
||||||
|
text += "[";
|
||||||
|
text += DADDR(2);
|
||||||
|
text += "]";
|
||||||
|
|
||||||
|
incr += 4;
|
||||||
|
} break;
|
||||||
|
case OPCODE_GET_KEYED_VALIDATED: {
|
||||||
|
text += "get keyed validated ";
|
||||||
|
text += DADDR(3);
|
||||||
|
text += " = ";
|
||||||
|
text += DADDR(1);
|
||||||
|
text += "[";
|
||||||
|
text += DADDR(2);
|
||||||
|
text += "]";
|
||||||
|
|
||||||
|
incr += 5;
|
||||||
|
} break;
|
||||||
|
case OPCODE_GET_INDEXED_VALIDATED: {
|
||||||
|
text += "get indexed validated ";
|
||||||
|
text += DADDR(3);
|
||||||
|
text += " = ";
|
||||||
|
text += DADDR(1);
|
||||||
|
text += "[";
|
||||||
|
text += DADDR(2);
|
||||||
|
text += "]";
|
||||||
|
|
||||||
|
incr += 5;
|
||||||
|
} break;
|
||||||
|
case OPCODE_SET_NAMED: {
|
||||||
|
text += "set_named ";
|
||||||
|
text += DADDR(1);
|
||||||
|
text += "[\"";
|
||||||
|
text += _global_names_ptr[_code_ptr[ip + 3]];
|
||||||
|
text += "\"] = ";
|
||||||
|
text += DADDR(2);
|
||||||
|
|
||||||
|
incr += 4;
|
||||||
|
} break;
|
||||||
|
case OPCODE_SET_NAMED_VALIDATED: {
|
||||||
|
text += "set_named validated ";
|
||||||
|
text += DADDR(1);
|
||||||
|
text += "[\"";
|
||||||
|
text += "<unknown name>";
|
||||||
|
text += "\"] = ";
|
||||||
|
text += DADDR(2);
|
||||||
|
|
||||||
|
incr += 4;
|
||||||
|
} break;
|
||||||
|
case OPCODE_GET_NAMED: {
|
||||||
|
text += "get_named ";
|
||||||
|
text += DADDR(2);
|
||||||
|
text += " = ";
|
||||||
|
text += DADDR(1);
|
||||||
|
text += "[\"";
|
||||||
|
text += _global_names_ptr[_code_ptr[ip + 3]];
|
||||||
|
text += "\"]";
|
||||||
|
|
||||||
|
incr += 4;
|
||||||
|
} break;
|
||||||
|
case OPCODE_GET_NAMED_VALIDATED: {
|
||||||
|
text += "get_named validated ";
|
||||||
|
text += DADDR(2);
|
||||||
|
text += " = ";
|
||||||
|
text += DADDR(1);
|
||||||
|
text += "[\"";
|
||||||
|
text += "<unknown name>";
|
||||||
|
text += "\"]";
|
||||||
|
|
||||||
|
incr += 4;
|
||||||
|
} break;
|
||||||
|
case OPCODE_SET_MEMBER: {
|
||||||
|
text += "set_member ";
|
||||||
|
text += "[\"";
|
||||||
|
text += _global_names_ptr[_code_ptr[ip + 2]];
|
||||||
|
text += "\"] = ";
|
||||||
|
text += DADDR(1);
|
||||||
|
|
||||||
|
incr += 3;
|
||||||
|
} break;
|
||||||
|
case OPCODE_GET_MEMBER: {
|
||||||
|
text += "get_member ";
|
||||||
|
text += DADDR(1);
|
||||||
|
text += " = ";
|
||||||
|
text += "[\"";
|
||||||
|
text += _global_names_ptr[_code_ptr[ip + 2]];
|
||||||
|
text += "\"]";
|
||||||
|
|
||||||
|
incr += 3;
|
||||||
|
} break;
|
||||||
|
case OPCODE_ASSIGN: {
|
||||||
|
text += "assign ";
|
||||||
|
text += DADDR(1);
|
||||||
|
text += " = ";
|
||||||
|
text += DADDR(2);
|
||||||
|
|
||||||
|
incr += 3;
|
||||||
|
} break;
|
||||||
|
case OPCODE_ASSIGN_TRUE: {
|
||||||
|
text += "assign ";
|
||||||
|
text += DADDR(1);
|
||||||
|
text += " = true";
|
||||||
|
|
||||||
|
incr += 2;
|
||||||
|
} break;
|
||||||
|
case OPCODE_ASSIGN_FALSE: {
|
||||||
|
text += "assign ";
|
||||||
|
text += DADDR(1);
|
||||||
|
text += " = false";
|
||||||
|
|
||||||
|
incr += 2;
|
||||||
|
} break;
|
||||||
|
case OPCODE_ASSIGN_TYPED_BUILTIN: {
|
||||||
|
text += "assign typed builtin (";
|
||||||
|
text += Variant::get_type_name((Variant::Type)_code_ptr[ip + 3]);
|
||||||
|
text += ") ";
|
||||||
|
text += DADDR(1);
|
||||||
|
text += " = ";
|
||||||
|
text += DADDR(2);
|
||||||
|
|
||||||
|
incr += 4;
|
||||||
|
} break;
|
||||||
|
case OPCODE_ASSIGN_TYPED_NATIVE: {
|
||||||
|
Variant class_name = _constants_ptr[_code_ptr[ip + 3]];
|
||||||
|
GDScriptNativeClass *nc = Object::cast_to<GDScriptNativeClass>(class_name.operator Object *());
|
||||||
|
|
||||||
|
text += "assign typed native (";
|
||||||
|
text += nc->get_name().operator String();
|
||||||
|
text += ") ";
|
||||||
|
text += DADDR(1);
|
||||||
|
text += " = ";
|
||||||
|
text += DADDR(2);
|
||||||
|
|
||||||
|
incr += 4;
|
||||||
|
} break;
|
||||||
|
case OPCODE_ASSIGN_TYPED_SCRIPT: {
|
||||||
|
Variant script = _constants_ptr[_code_ptr[ip + 3]];
|
||||||
|
Script *sc = Object::cast_to<Script>(script.operator Object *());
|
||||||
|
|
||||||
|
text += "assign typed script (";
|
||||||
|
text += sc->get_path();
|
||||||
|
text += ") ";
|
||||||
|
text += DADDR(1);
|
||||||
|
text += " = ";
|
||||||
|
text += DADDR(2);
|
||||||
|
|
||||||
|
incr += 4;
|
||||||
|
} break;
|
||||||
|
case OPCODE_CAST_TO_BUILTIN: {
|
||||||
|
text += "cast builtin ";
|
||||||
|
text += DADDR(2);
|
||||||
|
text += " = ";
|
||||||
|
text += DADDR(1);
|
||||||
|
text += " as ";
|
||||||
|
text += Variant::get_type_name(Variant::Type(_code_ptr[ip + 1]));
|
||||||
|
|
||||||
|
incr += 4;
|
||||||
|
} break;
|
||||||
|
case OPCODE_CAST_TO_NATIVE: {
|
||||||
|
Variant class_name = _constants_ptr[_code_ptr[ip + 1]];
|
||||||
|
GDScriptNativeClass *nc = Object::cast_to<GDScriptNativeClass>(class_name.operator Object *());
|
||||||
|
|
||||||
|
text += "cast native ";
|
||||||
|
text += DADDR(2);
|
||||||
|
text += " = ";
|
||||||
|
text += DADDR(1);
|
||||||
|
text += " as ";
|
||||||
|
text += nc->get_name();
|
||||||
|
|
||||||
|
incr += 4;
|
||||||
|
} break;
|
||||||
|
case OPCODE_CAST_TO_SCRIPT: {
|
||||||
|
text += "cast ";
|
||||||
|
text += DADDR(2);
|
||||||
|
text += " = ";
|
||||||
|
text += DADDR(1);
|
||||||
|
text += " as ";
|
||||||
|
text += DADDR(3);
|
||||||
|
|
||||||
|
incr += 4;
|
||||||
|
} break;
|
||||||
|
case OPCODE_CONSTRUCT: {
|
||||||
|
Variant::Type t = Variant::Type(_code_ptr[ip + 3 + instr_var_args]);
|
||||||
|
int argc = _code_ptr[ip + 1 + instr_var_args];
|
||||||
|
|
||||||
|
text += "construct ";
|
||||||
|
text += DADDR(1 + argc);
|
||||||
|
text += " = ";
|
||||||
|
|
||||||
|
text += Variant::get_type_name(t) + "(";
|
||||||
|
for (int i = 0; i < argc; i++) {
|
||||||
|
if (i > 0)
|
||||||
|
text += ", ";
|
||||||
|
text += DADDR(i + 1);
|
||||||
|
}
|
||||||
|
text += ")";
|
||||||
|
|
||||||
|
incr = 3 + instr_var_args;
|
||||||
|
} break;
|
||||||
|
case OPCODE_CONSTRUCT_VALIDATED: {
|
||||||
|
int argc = _code_ptr[ip + 1 + instr_var_args];
|
||||||
|
|
||||||
|
text += "construct validated ";
|
||||||
|
text += DADDR(1 + argc);
|
||||||
|
text += " = ";
|
||||||
|
|
||||||
|
text += "<unkown type>(";
|
||||||
|
for (int i = 0; i < argc; i++) {
|
||||||
|
if (i > 0)
|
||||||
|
text += ", ";
|
||||||
|
text += DADDR(i + 1);
|
||||||
|
}
|
||||||
|
text += ")";
|
||||||
|
|
||||||
|
incr = 3 + instr_var_args;
|
||||||
|
} break;
|
||||||
|
case OPCODE_CONSTRUCT_ARRAY: {
|
||||||
|
int argc = _code_ptr[ip + 1 + instr_var_args];
|
||||||
|
text += " make_array ";
|
||||||
|
text += DADDR(1 + argc);
|
||||||
|
text += " = [";
|
||||||
|
|
||||||
|
for (int i = 0; i < argc; i++) {
|
||||||
|
if (i > 0)
|
||||||
|
text += ", ";
|
||||||
|
text += DADDR(1 + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
text += "]";
|
||||||
|
|
||||||
|
incr += 3 + argc;
|
||||||
|
} break;
|
||||||
|
case OPCODE_CONSTRUCT_DICTIONARY: {
|
||||||
|
int argc = _code_ptr[ip + 1 + instr_var_args];
|
||||||
|
text += "make_dict ";
|
||||||
|
text += DADDR(1 + argc * 2);
|
||||||
|
text += " = {";
|
||||||
|
|
||||||
|
for (int i = 0; i < argc; i++) {
|
||||||
|
if (i > 0)
|
||||||
|
text += ", ";
|
||||||
|
text += DADDR(1 + i * 2 + 0);
|
||||||
|
text += ": ";
|
||||||
|
text += DADDR(1 + i * 2 + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
text += "}";
|
||||||
|
|
||||||
|
incr += 3 + argc * 2;
|
||||||
|
} break;
|
||||||
|
case OPCODE_CALL:
|
||||||
|
case OPCODE_CALL_RETURN:
|
||||||
|
case OPCODE_CALL_ASYNC: {
|
||||||
|
bool ret = (_code_ptr[ip] & INSTR_MASK) == OPCODE_CALL_RETURN;
|
||||||
|
bool async = (_code_ptr[ip] & INSTR_MASK) == OPCODE_CALL_ASYNC;
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
text += "call-ret ";
|
||||||
|
} else if (async) {
|
||||||
|
text += "call-async ";
|
||||||
|
} else {
|
||||||
|
text += "call ";
|
||||||
|
}
|
||||||
|
|
||||||
|
int argc = _code_ptr[ip + 1 + instr_var_args];
|
||||||
|
if (ret || async) {
|
||||||
|
text += DADDR(2 + argc) + " = ";
|
||||||
|
}
|
||||||
|
|
||||||
|
text += DADDR(1 + argc) + ".";
|
||||||
|
text += String(_global_names_ptr[_code_ptr[ip + 2 + instr_var_args]]);
|
||||||
|
text += "(";
|
||||||
|
|
||||||
|
for (int i = 0; i < argc; i++) {
|
||||||
|
if (i > 0)
|
||||||
|
text += ", ";
|
||||||
|
text += DADDR(1 + i);
|
||||||
|
}
|
||||||
|
text += ")";
|
||||||
|
|
||||||
|
incr = 5 + argc;
|
||||||
|
} break;
|
||||||
|
case OPCODE_CALL_METHOD_BIND:
|
||||||
|
case OPCODE_CALL_METHOD_BIND_RET: {
|
||||||
|
bool ret = (_code_ptr[ip] & INSTR_MASK) == OPCODE_CALL_METHOD_BIND_RET;
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
text += "call-method_bind-ret ";
|
||||||
|
} else {
|
||||||
|
text += "call-method_bind ";
|
||||||
|
}
|
||||||
|
|
||||||
|
MethodBind *method = _methods_ptr[_code_ptr[ip + 2 + instr_var_args]];
|
||||||
|
|
||||||
|
int argc = _code_ptr[ip + 1 + instr_var_args];
|
||||||
|
if (ret) {
|
||||||
|
text += DADDR(2 + argc) + " = ";
|
||||||
|
}
|
||||||
|
|
||||||
|
text += DADDR(1 + argc) + ".";
|
||||||
|
text += method->get_name();
|
||||||
|
text += "(";
|
||||||
|
|
||||||
|
for (int i = 0; i < argc; i++) {
|
||||||
|
if (i > 0)
|
||||||
|
text += ", ";
|
||||||
|
text += DADDR(1 + i);
|
||||||
|
}
|
||||||
|
text += ")";
|
||||||
|
|
||||||
|
incr = 5 + argc;
|
||||||
|
} break;
|
||||||
|
case OPCODE_CALL_PTRCALL_NO_RETURN: {
|
||||||
|
text += "call-ptrcall (no return) ";
|
||||||
|
|
||||||
|
MethodBind *method = _methods_ptr[_code_ptr[ip + 2 + instr_var_args]];
|
||||||
|
|
||||||
|
int argc = _code_ptr[ip + 1 + instr_var_args];
|
||||||
|
|
||||||
|
text += DADDR(1 + argc) + ".";
|
||||||
|
text += method->get_name();
|
||||||
|
text += "(";
|
||||||
|
|
||||||
|
for (int i = 0; i < argc; i++) {
|
||||||
|
if (i > 0)
|
||||||
|
text += ", ";
|
||||||
|
text += DADDR(1 + i);
|
||||||
|
}
|
||||||
|
text += ")";
|
||||||
|
|
||||||
|
incr = 5 + argc;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
#define DISASSEMBLE_PTRCALL(m_type) \
|
||||||
|
case OPCODE_CALL_PTRCALL_##m_type: { \
|
||||||
|
text += "call-ptrcall (return "; \
|
||||||
|
text += #m_type; \
|
||||||
|
text += ") "; \
|
||||||
|
MethodBind *method = _methods_ptr[_code_ptr[ip + 2 + instr_var_args]]; \
|
||||||
|
int argc = _code_ptr[ip + 1 + instr_var_args]; \
|
||||||
|
text += DADDR(2 + argc) + " = "; \
|
||||||
|
text += DADDR(1 + argc) + "."; \
|
||||||
|
text += method->get_name(); \
|
||||||
|
text += "("; \
|
||||||
|
for (int i = 0; i < argc; i++) { \
|
||||||
|
if (i > 0) \
|
||||||
|
text += ", "; \
|
||||||
|
text += DADDR(1 + i); \
|
||||||
|
} \
|
||||||
|
text += ")"; \
|
||||||
|
incr = 5 + argc; \
|
||||||
|
} break
|
||||||
|
|
||||||
|
DISASSEMBLE_PTRCALL(BOOL);
|
||||||
|
DISASSEMBLE_PTRCALL(INT);
|
||||||
|
DISASSEMBLE_PTRCALL(FLOAT);
|
||||||
|
DISASSEMBLE_PTRCALL(STRING);
|
||||||
|
DISASSEMBLE_PTRCALL(VECTOR2);
|
||||||
|
DISASSEMBLE_PTRCALL(VECTOR2I);
|
||||||
|
DISASSEMBLE_PTRCALL(RECT2);
|
||||||
|
DISASSEMBLE_PTRCALL(RECT2I);
|
||||||
|
DISASSEMBLE_PTRCALL(VECTOR3);
|
||||||
|
DISASSEMBLE_PTRCALL(VECTOR3I);
|
||||||
|
DISASSEMBLE_PTRCALL(TRANSFORM2D);
|
||||||
|
DISASSEMBLE_PTRCALL(PLANE);
|
||||||
|
DISASSEMBLE_PTRCALL(AABB);
|
||||||
|
DISASSEMBLE_PTRCALL(BASIS);
|
||||||
|
DISASSEMBLE_PTRCALL(TRANSFORM);
|
||||||
|
DISASSEMBLE_PTRCALL(COLOR);
|
||||||
|
DISASSEMBLE_PTRCALL(STRING_NAME);
|
||||||
|
DISASSEMBLE_PTRCALL(NODE_PATH);
|
||||||
|
DISASSEMBLE_PTRCALL(RID);
|
||||||
|
DISASSEMBLE_PTRCALL(QUAT);
|
||||||
|
DISASSEMBLE_PTRCALL(OBJECT);
|
||||||
|
DISASSEMBLE_PTRCALL(CALLABLE);
|
||||||
|
DISASSEMBLE_PTRCALL(SIGNAL);
|
||||||
|
DISASSEMBLE_PTRCALL(DICTIONARY);
|
||||||
|
DISASSEMBLE_PTRCALL(ARRAY);
|
||||||
|
DISASSEMBLE_PTRCALL(PACKED_BYTE_ARRAY);
|
||||||
|
DISASSEMBLE_PTRCALL(PACKED_INT32_ARRAY);
|
||||||
|
DISASSEMBLE_PTRCALL(PACKED_INT64_ARRAY);
|
||||||
|
DISASSEMBLE_PTRCALL(PACKED_FLOAT32_ARRAY);
|
||||||
|
DISASSEMBLE_PTRCALL(PACKED_FLOAT64_ARRAY);
|
||||||
|
DISASSEMBLE_PTRCALL(PACKED_STRING_ARRAY);
|
||||||
|
DISASSEMBLE_PTRCALL(PACKED_VECTOR2_ARRAY);
|
||||||
|
DISASSEMBLE_PTRCALL(PACKED_VECTOR3_ARRAY);
|
||||||
|
DISASSEMBLE_PTRCALL(PACKED_COLOR_ARRAY);
|
||||||
|
|
||||||
|
case OPCODE_CALL_BUILTIN_TYPE_VALIDATED: {
|
||||||
|
int argc = _code_ptr[ip + 1 + instr_var_args];
|
||||||
|
|
||||||
|
text += "call-builtin-method validated ";
|
||||||
|
|
||||||
|
text += DADDR(2 + argc) + " = ";
|
||||||
|
|
||||||
|
text += DADDR(1) + ".";
|
||||||
|
text += "<unknown method>";
|
||||||
|
|
||||||
|
text += "(";
|
||||||
|
|
||||||
|
for (int i = 0; i < argc; i++) {
|
||||||
|
if (i > 0)
|
||||||
|
text += ", ";
|
||||||
|
text += DADDR(1 + i);
|
||||||
|
}
|
||||||
|
text += ")";
|
||||||
|
|
||||||
|
incr = 5 + argc;
|
||||||
|
} break;
|
||||||
|
case OPCODE_CALL_BUILT_IN: {
|
||||||
|
text += "call-built-in ";
|
||||||
|
|
||||||
|
int argc = _code_ptr[ip + 1 + instr_var_args];
|
||||||
|
text += DADDR(1 + argc) + " = ";
|
||||||
|
|
||||||
|
text += GDScriptFunctions::get_func_name(GDScriptFunctions::Function(_code_ptr[ip + 2 + instr_var_args]));
|
||||||
|
text += "(";
|
||||||
|
|
||||||
|
for (int i = 0; i < argc; i++) {
|
||||||
|
if (i > 0)
|
||||||
|
text += ", ";
|
||||||
|
text += DADDR(1 + i);
|
||||||
|
}
|
||||||
|
text += ")";
|
||||||
|
|
||||||
|
incr = 4 + argc;
|
||||||
|
} break;
|
||||||
|
case OPCODE_CALL_SELF_BASE: {
|
||||||
|
text += "call-self-base ";
|
||||||
|
|
||||||
|
int argc = _code_ptr[ip + 1 + instr_var_args];
|
||||||
|
text += DADDR(2 + argc) + " = ";
|
||||||
|
|
||||||
|
text += _global_names_ptr[_code_ptr[ip + 2 + instr_var_args]];
|
||||||
|
text += "(";
|
||||||
|
|
||||||
|
for (int i = 0; i < argc; i++) {
|
||||||
|
if (i > 0)
|
||||||
|
text += ", ";
|
||||||
|
text += DADDR(1 + i);
|
||||||
|
}
|
||||||
|
text += ")";
|
||||||
|
|
||||||
|
incr = 4 + argc;
|
||||||
|
} break;
|
||||||
|
case OPCODE_AWAIT: {
|
||||||
|
text += "await ";
|
||||||
|
text += DADDR(1);
|
||||||
|
|
||||||
|
incr += 2;
|
||||||
|
} break;
|
||||||
|
case OPCODE_AWAIT_RESUME: {
|
||||||
|
text += "await resume ";
|
||||||
|
text += DADDR(1);
|
||||||
|
|
||||||
|
incr = 2;
|
||||||
|
} break;
|
||||||
|
case OPCODE_JUMP: {
|
||||||
|
text += "jump ";
|
||||||
|
text += itos(_code_ptr[ip + 1]);
|
||||||
|
|
||||||
|
incr = 2;
|
||||||
|
} break;
|
||||||
|
case OPCODE_JUMP_IF: {
|
||||||
|
text += "jump-if ";
|
||||||
|
text += DADDR(1);
|
||||||
|
text += " to ";
|
||||||
|
text += itos(_code_ptr[ip + 2]);
|
||||||
|
|
||||||
|
incr = 3;
|
||||||
|
} break;
|
||||||
|
case OPCODE_JUMP_IF_NOT: {
|
||||||
|
text += "jump-if-not ";
|
||||||
|
text += DADDR(1);
|
||||||
|
text += " to ";
|
||||||
|
text += itos(_code_ptr[ip + 2]);
|
||||||
|
|
||||||
|
incr = 3;
|
||||||
|
} break;
|
||||||
|
case OPCODE_JUMP_TO_DEF_ARGUMENT: {
|
||||||
|
text += "jump-to-default-argument ";
|
||||||
|
|
||||||
|
incr = 1;
|
||||||
|
} break;
|
||||||
|
case OPCODE_RETURN: {
|
||||||
|
text += "return ";
|
||||||
|
text += DADDR(1);
|
||||||
|
|
||||||
|
incr = 2;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
#define DISASSEMBLE_ITERATE(m_type) \
|
||||||
|
case OPCODE_ITERATE_##m_type: { \
|
||||||
|
text += "for-loop (typed "; \
|
||||||
|
text += #m_type; \
|
||||||
|
text += ") "; \
|
||||||
|
text += DADDR(3); \
|
||||||
|
text += " in "; \
|
||||||
|
text += DADDR(2); \
|
||||||
|
text += " counter "; \
|
||||||
|
text += DADDR(1); \
|
||||||
|
text += " end "; \
|
||||||
|
text += itos(_code_ptr[ip + 4]); \
|
||||||
|
incr += 5; \
|
||||||
|
} break
|
||||||
|
|
||||||
|
#define DISASSEMBLE_ITERATE_BEGIN(m_type) \
|
||||||
|
case OPCODE_ITERATE_BEGIN_##m_type: { \
|
||||||
|
text += "for-init (typed "; \
|
||||||
|
text += #m_type; \
|
||||||
|
text += ") "; \
|
||||||
|
text += DADDR(3); \
|
||||||
|
text += " in "; \
|
||||||
|
text += DADDR(2); \
|
||||||
|
text += " counter "; \
|
||||||
|
text += DADDR(1); \
|
||||||
|
text += " end "; \
|
||||||
|
text += itos(_code_ptr[ip + 4]); \
|
||||||
|
incr += 5; \
|
||||||
|
} break
|
||||||
|
|
||||||
|
#define DISASSEMBLE_ITERATE_TYPES(m_macro) \
|
||||||
|
m_macro(INT); \
|
||||||
|
m_macro(FLOAT); \
|
||||||
|
m_macro(VECTOR2); \
|
||||||
|
m_macro(VECTOR2I); \
|
||||||
|
m_macro(VECTOR3); \
|
||||||
|
m_macro(VECTOR3I); \
|
||||||
|
m_macro(STRING); \
|
||||||
|
m_macro(DICTIONARY); \
|
||||||
|
m_macro(ARRAY); \
|
||||||
|
m_macro(PACKED_BYTE_ARRAY); \
|
||||||
|
m_macro(PACKED_INT32_ARRAY); \
|
||||||
|
m_macro(PACKED_INT64_ARRAY); \
|
||||||
|
m_macro(PACKED_FLOAT32_ARRAY); \
|
||||||
|
m_macro(PACKED_FLOAT64_ARRAY); \
|
||||||
|
m_macro(PACKED_STRING_ARRAY); \
|
||||||
|
m_macro(PACKED_VECTOR2_ARRAY); \
|
||||||
|
m_macro(PACKED_VECTOR3_ARRAY); \
|
||||||
|
m_macro(PACKED_COLOR_ARRAY); \
|
||||||
|
m_macro(OBJECT)
|
||||||
|
|
||||||
|
case OPCODE_ITERATE_BEGIN: {
|
||||||
|
text += "for-init ";
|
||||||
|
text += DADDR(3);
|
||||||
|
text += " in ";
|
||||||
|
text += DADDR(2);
|
||||||
|
text += " counter ";
|
||||||
|
text += DADDR(1);
|
||||||
|
text += " end ";
|
||||||
|
text += itos(_code_ptr[ip + 4]);
|
||||||
|
|
||||||
|
incr += 5;
|
||||||
|
} break;
|
||||||
|
DISASSEMBLE_ITERATE_TYPES(DISASSEMBLE_ITERATE_BEGIN);
|
||||||
|
case OPCODE_ITERATE: {
|
||||||
|
text += "for-loop ";
|
||||||
|
text += DADDR(2);
|
||||||
|
text += " in ";
|
||||||
|
text += DADDR(2);
|
||||||
|
text += " counter ";
|
||||||
|
text += DADDR(1);
|
||||||
|
text += " end ";
|
||||||
|
text += itos(_code_ptr[ip + 4]);
|
||||||
|
|
||||||
|
incr += 5;
|
||||||
|
} break;
|
||||||
|
DISASSEMBLE_ITERATE_TYPES(DISASSEMBLE_ITERATE);
|
||||||
|
case OPCODE_LINE: {
|
||||||
|
int line = _code_ptr[ip + 1] - 1;
|
||||||
|
if (line >= 0 && line < p_code_lines.size()) {
|
||||||
|
text += "line ";
|
||||||
|
text += itos(line + 1);
|
||||||
|
text += ": ";
|
||||||
|
text += p_code_lines[line];
|
||||||
|
} else {
|
||||||
|
text += "";
|
||||||
|
}
|
||||||
|
|
||||||
|
incr += 2;
|
||||||
|
} break;
|
||||||
|
case OPCODE_ASSERT: {
|
||||||
|
text += "assert (";
|
||||||
|
text += DADDR(1);
|
||||||
|
text += ", ";
|
||||||
|
text += DADDR(2);
|
||||||
|
text += ")";
|
||||||
|
|
||||||
|
incr += 3;
|
||||||
|
} break;
|
||||||
|
case OPCODE_BREAKPOINT: {
|
||||||
|
text += "breakpoint";
|
||||||
|
|
||||||
|
incr += 1;
|
||||||
|
} break;
|
||||||
|
case OPCODE_END: {
|
||||||
|
text += "== END ==";
|
||||||
|
|
||||||
|
incr += 1;
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ip += incr;
|
||||||
|
if (text.get_string_length() > 0) {
|
||||||
|
print_line(text.as_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -159,12 +159,19 @@ class GDScriptFunction {
|
||||||
public:
|
public:
|
||||||
enum Opcode {
|
enum Opcode {
|
||||||
OPCODE_OPERATOR,
|
OPCODE_OPERATOR,
|
||||||
|
OPCODE_OPERATOR_VALIDATED,
|
||||||
OPCODE_EXTENDS_TEST,
|
OPCODE_EXTENDS_TEST,
|
||||||
OPCODE_IS_BUILTIN,
|
OPCODE_IS_BUILTIN,
|
||||||
OPCODE_SET,
|
OPCODE_SET_KEYED,
|
||||||
OPCODE_GET,
|
OPCODE_SET_KEYED_VALIDATED,
|
||||||
|
OPCODE_SET_INDEXED_VALIDATED,
|
||||||
|
OPCODE_GET_KEYED,
|
||||||
|
OPCODE_GET_KEYED_VALIDATED,
|
||||||
|
OPCODE_GET_INDEXED_VALIDATED,
|
||||||
OPCODE_SET_NAMED,
|
OPCODE_SET_NAMED,
|
||||||
|
OPCODE_SET_NAMED_VALIDATED,
|
||||||
OPCODE_GET_NAMED,
|
OPCODE_GET_NAMED,
|
||||||
|
OPCODE_GET_NAMED_VALIDATED,
|
||||||
OPCODE_SET_MEMBER,
|
OPCODE_SET_MEMBER,
|
||||||
OPCODE_GET_MEMBER,
|
OPCODE_GET_MEMBER,
|
||||||
OPCODE_ASSIGN,
|
OPCODE_ASSIGN,
|
||||||
|
@ -176,14 +183,54 @@ public:
|
||||||
OPCODE_CAST_TO_BUILTIN,
|
OPCODE_CAST_TO_BUILTIN,
|
||||||
OPCODE_CAST_TO_NATIVE,
|
OPCODE_CAST_TO_NATIVE,
|
||||||
OPCODE_CAST_TO_SCRIPT,
|
OPCODE_CAST_TO_SCRIPT,
|
||||||
OPCODE_CONSTRUCT, //only for basic types!!
|
OPCODE_CONSTRUCT, // Only for basic types!
|
||||||
|
OPCODE_CONSTRUCT_VALIDATED, // Only for basic types!
|
||||||
OPCODE_CONSTRUCT_ARRAY,
|
OPCODE_CONSTRUCT_ARRAY,
|
||||||
OPCODE_CONSTRUCT_DICTIONARY,
|
OPCODE_CONSTRUCT_DICTIONARY,
|
||||||
OPCODE_CALL,
|
OPCODE_CALL,
|
||||||
OPCODE_CALL_RETURN,
|
OPCODE_CALL_RETURN,
|
||||||
OPCODE_CALL_ASYNC,
|
OPCODE_CALL_ASYNC,
|
||||||
OPCODE_CALL_BUILT_IN,
|
OPCODE_CALL_BUILT_IN,
|
||||||
|
OPCODE_CALL_BUILTIN_TYPE_VALIDATED,
|
||||||
OPCODE_CALL_SELF_BASE,
|
OPCODE_CALL_SELF_BASE,
|
||||||
|
OPCODE_CALL_METHOD_BIND,
|
||||||
|
OPCODE_CALL_METHOD_BIND_RET,
|
||||||
|
// ptrcall have one instruction per return type.
|
||||||
|
OPCODE_CALL_PTRCALL_NO_RETURN,
|
||||||
|
OPCODE_CALL_PTRCALL_BOOL,
|
||||||
|
OPCODE_CALL_PTRCALL_INT,
|
||||||
|
OPCODE_CALL_PTRCALL_FLOAT,
|
||||||
|
OPCODE_CALL_PTRCALL_STRING,
|
||||||
|
OPCODE_CALL_PTRCALL_VECTOR2,
|
||||||
|
OPCODE_CALL_PTRCALL_VECTOR2I,
|
||||||
|
OPCODE_CALL_PTRCALL_RECT2,
|
||||||
|
OPCODE_CALL_PTRCALL_RECT2I,
|
||||||
|
OPCODE_CALL_PTRCALL_VECTOR3,
|
||||||
|
OPCODE_CALL_PTRCALL_VECTOR3I,
|
||||||
|
OPCODE_CALL_PTRCALL_TRANSFORM2D,
|
||||||
|
OPCODE_CALL_PTRCALL_PLANE,
|
||||||
|
OPCODE_CALL_PTRCALL_QUAT,
|
||||||
|
OPCODE_CALL_PTRCALL_AABB,
|
||||||
|
OPCODE_CALL_PTRCALL_BASIS,
|
||||||
|
OPCODE_CALL_PTRCALL_TRANSFORM,
|
||||||
|
OPCODE_CALL_PTRCALL_COLOR,
|
||||||
|
OPCODE_CALL_PTRCALL_STRING_NAME,
|
||||||
|
OPCODE_CALL_PTRCALL_NODE_PATH,
|
||||||
|
OPCODE_CALL_PTRCALL_RID,
|
||||||
|
OPCODE_CALL_PTRCALL_OBJECT,
|
||||||
|
OPCODE_CALL_PTRCALL_CALLABLE,
|
||||||
|
OPCODE_CALL_PTRCALL_SIGNAL,
|
||||||
|
OPCODE_CALL_PTRCALL_DICTIONARY,
|
||||||
|
OPCODE_CALL_PTRCALL_ARRAY,
|
||||||
|
OPCODE_CALL_PTRCALL_PACKED_BYTE_ARRAY,
|
||||||
|
OPCODE_CALL_PTRCALL_PACKED_INT32_ARRAY,
|
||||||
|
OPCODE_CALL_PTRCALL_PACKED_INT64_ARRAY,
|
||||||
|
OPCODE_CALL_PTRCALL_PACKED_FLOAT32_ARRAY,
|
||||||
|
OPCODE_CALL_PTRCALL_PACKED_FLOAT64_ARRAY,
|
||||||
|
OPCODE_CALL_PTRCALL_PACKED_STRING_ARRAY,
|
||||||
|
OPCODE_CALL_PTRCALL_PACKED_VECTOR2_ARRAY,
|
||||||
|
OPCODE_CALL_PTRCALL_PACKED_VECTOR3_ARRAY,
|
||||||
|
OPCODE_CALL_PTRCALL_PACKED_COLOR_ARRAY,
|
||||||
OPCODE_AWAIT,
|
OPCODE_AWAIT,
|
||||||
OPCODE_AWAIT_RESUME,
|
OPCODE_AWAIT_RESUME,
|
||||||
OPCODE_JUMP,
|
OPCODE_JUMP,
|
||||||
|
@ -192,7 +239,45 @@ public:
|
||||||
OPCODE_JUMP_TO_DEF_ARGUMENT,
|
OPCODE_JUMP_TO_DEF_ARGUMENT,
|
||||||
OPCODE_RETURN,
|
OPCODE_RETURN,
|
||||||
OPCODE_ITERATE_BEGIN,
|
OPCODE_ITERATE_BEGIN,
|
||||||
|
OPCODE_ITERATE_BEGIN_INT,
|
||||||
|
OPCODE_ITERATE_BEGIN_FLOAT,
|
||||||
|
OPCODE_ITERATE_BEGIN_VECTOR2,
|
||||||
|
OPCODE_ITERATE_BEGIN_VECTOR2I,
|
||||||
|
OPCODE_ITERATE_BEGIN_VECTOR3,
|
||||||
|
OPCODE_ITERATE_BEGIN_VECTOR3I,
|
||||||
|
OPCODE_ITERATE_BEGIN_STRING,
|
||||||
|
OPCODE_ITERATE_BEGIN_DICTIONARY,
|
||||||
|
OPCODE_ITERATE_BEGIN_ARRAY,
|
||||||
|
OPCODE_ITERATE_BEGIN_PACKED_BYTE_ARRAY,
|
||||||
|
OPCODE_ITERATE_BEGIN_PACKED_INT32_ARRAY,
|
||||||
|
OPCODE_ITERATE_BEGIN_PACKED_INT64_ARRAY,
|
||||||
|
OPCODE_ITERATE_BEGIN_PACKED_FLOAT32_ARRAY,
|
||||||
|
OPCODE_ITERATE_BEGIN_PACKED_FLOAT64_ARRAY,
|
||||||
|
OPCODE_ITERATE_BEGIN_PACKED_STRING_ARRAY,
|
||||||
|
OPCODE_ITERATE_BEGIN_PACKED_VECTOR2_ARRAY,
|
||||||
|
OPCODE_ITERATE_BEGIN_PACKED_VECTOR3_ARRAY,
|
||||||
|
OPCODE_ITERATE_BEGIN_PACKED_COLOR_ARRAY,
|
||||||
|
OPCODE_ITERATE_BEGIN_OBJECT,
|
||||||
OPCODE_ITERATE,
|
OPCODE_ITERATE,
|
||||||
|
OPCODE_ITERATE_INT,
|
||||||
|
OPCODE_ITERATE_FLOAT,
|
||||||
|
OPCODE_ITERATE_VECTOR2,
|
||||||
|
OPCODE_ITERATE_VECTOR2I,
|
||||||
|
OPCODE_ITERATE_VECTOR3,
|
||||||
|
OPCODE_ITERATE_VECTOR3I,
|
||||||
|
OPCODE_ITERATE_STRING,
|
||||||
|
OPCODE_ITERATE_DICTIONARY,
|
||||||
|
OPCODE_ITERATE_ARRAY,
|
||||||
|
OPCODE_ITERATE_PACKED_BYTE_ARRAY,
|
||||||
|
OPCODE_ITERATE_PACKED_INT32_ARRAY,
|
||||||
|
OPCODE_ITERATE_PACKED_INT64_ARRAY,
|
||||||
|
OPCODE_ITERATE_PACKED_FLOAT32_ARRAY,
|
||||||
|
OPCODE_ITERATE_PACKED_FLOAT64_ARRAY,
|
||||||
|
OPCODE_ITERATE_PACKED_STRING_ARRAY,
|
||||||
|
OPCODE_ITERATE_PACKED_VECTOR2_ARRAY,
|
||||||
|
OPCODE_ITERATE_PACKED_VECTOR3_ARRAY,
|
||||||
|
OPCODE_ITERATE_PACKED_COLOR_ARRAY,
|
||||||
|
OPCODE_ITERATE_OBJECT,
|
||||||
OPCODE_ASSERT,
|
OPCODE_ASSERT,
|
||||||
OPCODE_BREAKPOINT,
|
OPCODE_BREAKPOINT,
|
||||||
OPCODE_LINE,
|
OPCODE_LINE,
|
||||||
|
@ -215,6 +300,12 @@ public:
|
||||||
ADDR_TYPE_NIL = 9
|
ADDR_TYPE_NIL = 9
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum Instruction {
|
||||||
|
INSTR_BITS = 20,
|
||||||
|
INSTR_MASK = ((1 << INSTR_BITS) - 1),
|
||||||
|
INSTR_ARGS_MASK = ~INSTR_MASK,
|
||||||
|
};
|
||||||
|
|
||||||
struct StackDebug {
|
struct StackDebug {
|
||||||
int line;
|
int line;
|
||||||
int pos;
|
int pos;
|
||||||
|
@ -229,27 +320,59 @@ private:
|
||||||
StringName source;
|
StringName source;
|
||||||
|
|
||||||
mutable Variant nil;
|
mutable Variant nil;
|
||||||
mutable Variant *_constants_ptr;
|
mutable Variant *_constants_ptr = nullptr;
|
||||||
int _constant_count;
|
int _constant_count = 0;
|
||||||
const StringName *_global_names_ptr;
|
const StringName *_global_names_ptr = nullptr;
|
||||||
int _global_names_count;
|
int _global_names_count = 0;
|
||||||
const int *_default_arg_ptr;
|
const int *_default_arg_ptr = nullptr;
|
||||||
int _default_arg_count;
|
int _default_arg_count = 0;
|
||||||
const int *_code_ptr;
|
int _operator_funcs_count = 0;
|
||||||
int _code_size;
|
const Variant::ValidatedOperatorEvaluator *_operator_funcs_ptr = nullptr;
|
||||||
int _argument_count;
|
int _setters_count = 0;
|
||||||
int _stack_size;
|
const Variant::ValidatedSetter *_setters_ptr = nullptr;
|
||||||
int _call_size;
|
int _getters_count = 0;
|
||||||
int _initial_line;
|
const Variant::ValidatedGetter *_getters_ptr = nullptr;
|
||||||
bool _static;
|
int _keyed_setters_count = 0;
|
||||||
MultiplayerAPI::RPCMode rpc_mode;
|
const Variant::ValidatedKeyedSetter *_keyed_setters_ptr = nullptr;
|
||||||
|
int _keyed_getters_count = 0;
|
||||||
|
const Variant::ValidatedKeyedGetter *_keyed_getters_ptr = nullptr;
|
||||||
|
int _indexed_setters_count = 0;
|
||||||
|
const Variant::ValidatedIndexedSetter *_indexed_setters_ptr = nullptr;
|
||||||
|
int _indexed_getters_count = 0;
|
||||||
|
const Variant::ValidatedIndexedGetter *_indexed_getters_ptr = nullptr;
|
||||||
|
int _builtin_methods_count = 0;
|
||||||
|
const Variant::ValidatedBuiltInMethod *_builtin_methods_ptr = nullptr;
|
||||||
|
int _constructors_count = 0;
|
||||||
|
const Variant::ValidatedConstructor *_constructors_ptr = nullptr;
|
||||||
|
int _methods_count = 0;
|
||||||
|
MethodBind **_methods_ptr = nullptr;
|
||||||
|
const int *_code_ptr = nullptr;
|
||||||
|
int _code_size = 0;
|
||||||
|
int _argument_count = 0;
|
||||||
|
int _stack_size = 0;
|
||||||
|
int _instruction_args_size = 0;
|
||||||
|
int _ptrcall_args_size = 0;
|
||||||
|
|
||||||
GDScript *_script;
|
int _initial_line = 0;
|
||||||
|
bool _static = false;
|
||||||
|
MultiplayerAPI::RPCMode rpc_mode = MultiplayerAPI::RPC_MODE_DISABLED;
|
||||||
|
|
||||||
|
GDScript *_script = nullptr;
|
||||||
|
|
||||||
StringName name;
|
StringName name;
|
||||||
Vector<Variant> constants;
|
Vector<Variant> constants;
|
||||||
Vector<StringName> global_names;
|
Vector<StringName> global_names;
|
||||||
Vector<int> default_arguments;
|
Vector<int> default_arguments;
|
||||||
|
Vector<Variant::ValidatedOperatorEvaluator> operator_funcs;
|
||||||
|
Vector<Variant::ValidatedSetter> setters;
|
||||||
|
Vector<Variant::ValidatedGetter> getters;
|
||||||
|
Vector<Variant::ValidatedKeyedSetter> keyed_setters;
|
||||||
|
Vector<Variant::ValidatedKeyedGetter> keyed_getters;
|
||||||
|
Vector<Variant::ValidatedIndexedSetter> indexed_setters;
|
||||||
|
Vector<Variant::ValidatedIndexedGetter> indexed_getters;
|
||||||
|
Vector<Variant::ValidatedBuiltInMethod> builtin_methods;
|
||||||
|
Vector<Variant::ValidatedConstructor> constructors;
|
||||||
|
Vector<MethodBind *> methods;
|
||||||
Vector<int> code;
|
Vector<int> code;
|
||||||
Vector<GDScriptDataType> argument_types;
|
Vector<GDScriptDataType> argument_types;
|
||||||
GDScriptDataType return_type;
|
GDScriptDataType return_type;
|
||||||
|
@ -265,22 +388,22 @@ private:
|
||||||
|
|
||||||
friend class GDScriptLanguage;
|
friend class GDScriptLanguage;
|
||||||
|
|
||||||
SelfList<GDScriptFunction> function_list;
|
SelfList<GDScriptFunction> function_list{ this };
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
CharString func_cname;
|
CharString func_cname;
|
||||||
const char *_func_cname;
|
const char *_func_cname = nullptr;
|
||||||
|
|
||||||
struct Profile {
|
struct Profile {
|
||||||
StringName signature;
|
StringName signature;
|
||||||
uint64_t call_count;
|
uint64_t call_count = 0;
|
||||||
uint64_t self_time;
|
uint64_t self_time = 0;
|
||||||
uint64_t total_time;
|
uint64_t total_time = 0;
|
||||||
uint64_t frame_call_count;
|
uint64_t frame_call_count = 0;
|
||||||
uint64_t frame_self_time;
|
uint64_t frame_self_time = 0;
|
||||||
uint64_t frame_total_time;
|
uint64_t frame_total_time = 0;
|
||||||
uint64_t last_frame_call_count;
|
uint64_t last_frame_call_count = 0;
|
||||||
uint64_t last_frame_self_time;
|
uint64_t last_frame_self_time = 0;
|
||||||
uint64_t last_frame_total_time;
|
uint64_t last_frame_total_time = 0;
|
||||||
} profile;
|
} profile;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue