Merge pull request #47956 from vnen/gdscript-double-stack
GDScript: Use special stack space for temporaries to reduce type changes
This commit is contained in:
commit
a9ecf66342
9 changed files with 400 additions and 89 deletions
|
@ -142,36 +142,6 @@ static _FORCE_INLINE_ void vc_ptrcall(void (T::*method)(P...) const, void *p_bas
|
|||
call_with_ptr_argsc(reinterpret_cast<T *>(p_base), method, p_args);
|
||||
}
|
||||
|
||||
template <class R, class T, class... P>
|
||||
static _FORCE_INLINE_ void vc_change_return_type(R (T::*method)(P...), Variant *v) {
|
||||
VariantTypeAdjust<R>::adjust(v);
|
||||
}
|
||||
|
||||
template <class R, class T, class... P>
|
||||
static _FORCE_INLINE_ void vc_change_return_type(R (T::*method)(P...) const, Variant *v) {
|
||||
VariantTypeAdjust<R>::adjust(v);
|
||||
}
|
||||
|
||||
template <class T, class... P>
|
||||
static _FORCE_INLINE_ void vc_change_return_type(void (T::*method)(P...), Variant *v) {
|
||||
VariantInternal::clear(v);
|
||||
}
|
||||
|
||||
template <class T, class... P>
|
||||
static _FORCE_INLINE_ void vc_change_return_type(void (T::*method)(P...) const, Variant *v) {
|
||||
VariantInternal::clear(v);
|
||||
}
|
||||
|
||||
template <class R, class... P>
|
||||
static _FORCE_INLINE_ void vc_change_return_type(R (*method)(P...), Variant *v) {
|
||||
VariantTypeAdjust<R>::adjust(v);
|
||||
}
|
||||
|
||||
template <class... P>
|
||||
static _FORCE_INLINE_ void vc_change_return_type(void (*method)(P...), Variant *v) {
|
||||
VariantInternal::clear(v);
|
||||
}
|
||||
|
||||
template <class R, class T, class... P>
|
||||
static _FORCE_INLINE_ int vc_get_argument_count(R (T::*method)(P...)) {
|
||||
return sizeof...(P);
|
||||
|
@ -333,7 +303,6 @@ static _FORCE_INLINE_ Variant::Type vc_get_base_type(void (T::*method)(P...) con
|
|||
vc_method_call(m_method_ptr, base, p_args, p_argcount, r_ret, p_defvals, r_error); \
|
||||
} \
|
||||
static void validated_call(Variant *base, const Variant **p_args, int p_argcount, Variant *r_ret) { \
|
||||
vc_change_return_type(m_method_ptr, r_ret); \
|
||||
vc_validated_call(m_method_ptr, base, p_args, r_ret); \
|
||||
} \
|
||||
static void ptrcall(void *p_base, const void **p_args, void *r_ret, int p_argcount) { \
|
||||
|
@ -384,7 +353,6 @@ static _FORCE_INLINE_ void vc_static_ptrcall(void (*method)(P...), const void **
|
|||
vc_static_method_call(m_method_ptr, p_args, p_argcount, r_ret, p_defvals, r_error); \
|
||||
} \
|
||||
static void validated_call(Variant *base, const Variant **p_args, int p_argcount, Variant *r_ret) { \
|
||||
vc_change_return_type(m_method_ptr, r_ret); \
|
||||
vc_validated_static_call(m_method_ptr, p_args, r_ret); \
|
||||
} \
|
||||
static void ptrcall(void *p_base, const void **p_args, void *r_ret, int p_argcount) { \
|
||||
|
@ -435,7 +403,6 @@ static _FORCE_INLINE_ void vc_ptrcall(void (*method)(T *, P...), void *p_base, c
|
|||
vc_method_call_static(m_method_ptr, base, p_args, p_argcount, r_ret, p_defvals, r_error); \
|
||||
} \
|
||||
static void validated_call(Variant *base, const Variant **p_args, int p_argcount, Variant *r_ret) { \
|
||||
vc_change_return_type(m_method_ptr, r_ret); \
|
||||
vc_validated_call_static(m_method_ptr, base, p_args, r_ret); \
|
||||
} \
|
||||
static void ptrcall(void *p_base, const void **p_args, void *r_ret, int p_argcount) { \
|
||||
|
|
|
@ -47,7 +47,8 @@ uint32_t GDScriptByteCodeGenerator::add_parameter(const StringName &p_name, bool
|
|||
}
|
||||
|
||||
uint32_t GDScriptByteCodeGenerator::add_local(const StringName &p_name, const GDScriptDataType &p_type) {
|
||||
int stack_pos = increase_stack();
|
||||
int stack_pos = locals.size() + RESERVED_STACK;
|
||||
locals.push_back(StackSlot(p_type.builtin_type));
|
||||
add_stack_identifier(p_name, stack_pos);
|
||||
return stack_pos;
|
||||
}
|
||||
|
@ -66,25 +67,87 @@ uint32_t GDScriptByteCodeGenerator::add_or_get_name(const StringName &p_name) {
|
|||
return get_name_map_pos(p_name);
|
||||
}
|
||||
|
||||
uint32_t GDScriptByteCodeGenerator::add_temporary() {
|
||||
current_temporaries++;
|
||||
int idx = increase_stack();
|
||||
#ifdef DEBUG_ENABLED
|
||||
temp_stack.push_back(idx);
|
||||
#endif
|
||||
return idx;
|
||||
uint32_t GDScriptByteCodeGenerator::add_temporary(const GDScriptDataType &p_type) {
|
||||
Variant::Type temp_type = Variant::NIL;
|
||||
if (p_type.has_type) {
|
||||
if (p_type.kind == GDScriptDataType::BUILTIN) {
|
||||
switch (p_type.builtin_type) {
|
||||
case Variant::NIL:
|
||||
case Variant::BOOL:
|
||||
case Variant::INT:
|
||||
case Variant::FLOAT:
|
||||
case Variant::STRING:
|
||||
case Variant::VECTOR2:
|
||||
case Variant::VECTOR2I:
|
||||
case Variant::RECT2:
|
||||
case Variant::RECT2I:
|
||||
case Variant::VECTOR3:
|
||||
case Variant::VECTOR3I:
|
||||
case Variant::TRANSFORM2D:
|
||||
case Variant::PLANE:
|
||||
case Variant::QUAT:
|
||||
case Variant::AABB:
|
||||
case Variant::BASIS:
|
||||
case Variant::TRANSFORM:
|
||||
case Variant::COLOR:
|
||||
case Variant::STRING_NAME:
|
||||
case Variant::NODE_PATH:
|
||||
case Variant::RID:
|
||||
case Variant::OBJECT:
|
||||
case Variant::CALLABLE:
|
||||
case Variant::SIGNAL:
|
||||
case Variant::DICTIONARY:
|
||||
case Variant::ARRAY:
|
||||
temp_type = p_type.builtin_type;
|
||||
break;
|
||||
case Variant::PACKED_BYTE_ARRAY:
|
||||
case Variant::PACKED_INT32_ARRAY:
|
||||
case Variant::PACKED_INT64_ARRAY:
|
||||
case Variant::PACKED_FLOAT32_ARRAY:
|
||||
case Variant::PACKED_FLOAT64_ARRAY:
|
||||
case Variant::PACKED_STRING_ARRAY:
|
||||
case Variant::PACKED_VECTOR2_ARRAY:
|
||||
case Variant::PACKED_VECTOR3_ARRAY:
|
||||
case Variant::PACKED_COLOR_ARRAY:
|
||||
case Variant::VARIANT_MAX:
|
||||
// Packed arrays are reference counted, so we don't use the pool for them.
|
||||
temp_type = Variant::NIL;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
temp_type = Variant::OBJECT;
|
||||
}
|
||||
}
|
||||
|
||||
if (!temporaries_pool.has(temp_type)) {
|
||||
temporaries_pool[temp_type] = List<int>();
|
||||
}
|
||||
|
||||
List<int> &pool = temporaries_pool[temp_type];
|
||||
if (pool.is_empty()) {
|
||||
StackSlot new_temp(temp_type);
|
||||
int idx = temporaries.size();
|
||||
pool.push_back(idx);
|
||||
temporaries.push_back(new_temp);
|
||||
|
||||
// First time using this, so adjust to the proper type.
|
||||
if (temp_type != Variant::NIL) {
|
||||
Address addr(Address::TEMPORARY, idx, p_type);
|
||||
write_type_adjust(addr, temp_type);
|
||||
}
|
||||
}
|
||||
int slot = pool.front()->get();
|
||||
pool.pop_front();
|
||||
used_temporaries.push_back(slot);
|
||||
return slot;
|
||||
}
|
||||
|
||||
void GDScriptByteCodeGenerator::pop_temporary() {
|
||||
ERR_FAIL_COND(current_temporaries == 0);
|
||||
current_stack_size--;
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (temp_stack.back()->get() != current_stack_size) {
|
||||
ERR_PRINT("Mismatched popping of temporary value");
|
||||
}
|
||||
temp_stack.pop_back();
|
||||
#endif
|
||||
current_temporaries--;
|
||||
ERR_FAIL_COND(used_temporaries.is_empty());
|
||||
int slot_idx = used_temporaries.back()->get();
|
||||
const StackSlot &slot = temporaries[slot_idx];
|
||||
temporaries_pool[slot.type].push_back(slot_idx);
|
||||
used_temporaries.pop_back();
|
||||
}
|
||||
|
||||
void GDScriptByteCodeGenerator::start_parameters() {
|
||||
|
@ -119,12 +182,18 @@ void GDScriptByteCodeGenerator::write_start(GDScript *p_script, const StringName
|
|||
|
||||
GDScriptFunction *GDScriptByteCodeGenerator::write_end() {
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (current_temporaries != 0) {
|
||||
ERR_PRINT("Non-zero temporary variables at end of function: " + itos(current_temporaries));
|
||||
if (!used_temporaries.is_empty()) {
|
||||
ERR_PRINT("Non-zero temporary variables at end of function: " + itos(used_temporaries.size()));
|
||||
}
|
||||
#endif
|
||||
append(GDScriptFunction::OPCODE_END, 0);
|
||||
|
||||
for (int i = 0; i < temporaries.size(); i++) {
|
||||
for (int j = 0; j < temporaries[i].bytecode_indices.size(); j++) {
|
||||
opcodes.write[temporaries[i].bytecode_indices[j]] = (i + max_locals + RESERVED_STACK) | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
|
||||
}
|
||||
}
|
||||
|
||||
if (constant_map.size()) {
|
||||
function->_constant_count = constant_map.size();
|
||||
function->constants.resize(constant_map.size());
|
||||
|
@ -317,7 +386,7 @@ GDScriptFunction *GDScriptByteCodeGenerator::write_end() {
|
|||
if (debug_stack) {
|
||||
function->stack_debug = stack_debug;
|
||||
}
|
||||
function->_stack_size = stack_max;
|
||||
function->_stack_size = RESERVED_STACK + max_locals + temporaries.size();
|
||||
function->_instruction_args_size = instr_args_max;
|
||||
function->_ptrcall_args_size = ptrcall_max;
|
||||
|
||||
|
@ -341,6 +410,117 @@ void GDScriptByteCodeGenerator::set_initial_line(int p_line) {
|
|||
#define IS_BUILTIN_TYPE(m_var, m_type) \
|
||||
(m_var.type.has_type && m_var.type.kind == GDScriptDataType::BUILTIN && m_var.type.builtin_type == m_type)
|
||||
|
||||
void GDScriptByteCodeGenerator::write_type_adjust(const Address &p_target, Variant::Type p_new_type) {
|
||||
switch (p_new_type) {
|
||||
case Variant::BOOL:
|
||||
append(GDScriptFunction::OPCODE_TYPE_ADJUST_BOOL, 1);
|
||||
break;
|
||||
case Variant::INT:
|
||||
append(GDScriptFunction::OPCODE_TYPE_ADJUST_INT, 1);
|
||||
break;
|
||||
case Variant::FLOAT:
|
||||
append(GDScriptFunction::OPCODE_TYPE_ADJUST_FLOAT, 1);
|
||||
break;
|
||||
case Variant::STRING:
|
||||
append(GDScriptFunction::OPCODE_TYPE_ADJUST_STRING, 1);
|
||||
break;
|
||||
case Variant::VECTOR2:
|
||||
append(GDScriptFunction::OPCODE_TYPE_ADJUST_VECTOR2, 1);
|
||||
break;
|
||||
case Variant::VECTOR2I:
|
||||
append(GDScriptFunction::OPCODE_TYPE_ADJUST_VECTOR2I, 1);
|
||||
break;
|
||||
case Variant::RECT2:
|
||||
append(GDScriptFunction::OPCODE_TYPE_ADJUST_RECT2, 1);
|
||||
break;
|
||||
case Variant::RECT2I:
|
||||
append(GDScriptFunction::OPCODE_TYPE_ADJUST_RECT2I, 1);
|
||||
break;
|
||||
case Variant::VECTOR3:
|
||||
append(GDScriptFunction::OPCODE_TYPE_ADJUST_VECTOR3, 1);
|
||||
break;
|
||||
case Variant::VECTOR3I:
|
||||
append(GDScriptFunction::OPCODE_TYPE_ADJUST_VECTOR3I, 1);
|
||||
break;
|
||||
case Variant::TRANSFORM2D:
|
||||
append(GDScriptFunction::OPCODE_TYPE_ADJUST_TRANSFORM2D, 1);
|
||||
break;
|
||||
case Variant::PLANE:
|
||||
append(GDScriptFunction::OPCODE_TYPE_ADJUST_PLANE, 1);
|
||||
break;
|
||||
case Variant::QUAT:
|
||||
append(GDScriptFunction::OPCODE_TYPE_ADJUST_QUAT, 1);
|
||||
break;
|
||||
case Variant::AABB:
|
||||
append(GDScriptFunction::OPCODE_TYPE_ADJUST_AABB, 1);
|
||||
break;
|
||||
case Variant::BASIS:
|
||||
append(GDScriptFunction::OPCODE_TYPE_ADJUST_BASIS, 1);
|
||||
break;
|
||||
case Variant::TRANSFORM:
|
||||
append(GDScriptFunction::OPCODE_TYPE_ADJUST_TRANSFORM, 1);
|
||||
break;
|
||||
case Variant::COLOR:
|
||||
append(GDScriptFunction::OPCODE_TYPE_ADJUST_COLOR, 1);
|
||||
break;
|
||||
case Variant::STRING_NAME:
|
||||
append(GDScriptFunction::OPCODE_TYPE_ADJUST_STRING_NAME, 1);
|
||||
break;
|
||||
case Variant::NODE_PATH:
|
||||
append(GDScriptFunction::OPCODE_TYPE_ADJUST_NODE_PATH, 1);
|
||||
break;
|
||||
case Variant::RID:
|
||||
append(GDScriptFunction::OPCODE_TYPE_ADJUST_RID, 1);
|
||||
break;
|
||||
case Variant::OBJECT:
|
||||
append(GDScriptFunction::OPCODE_TYPE_ADJUST_OBJECT, 1);
|
||||
break;
|
||||
case Variant::CALLABLE:
|
||||
append(GDScriptFunction::OPCODE_TYPE_ADJUST_CALLABLE, 1);
|
||||
break;
|
||||
case Variant::SIGNAL:
|
||||
append(GDScriptFunction::OPCODE_TYPE_ADJUST_SIGNAL, 1);
|
||||
break;
|
||||
case Variant::DICTIONARY:
|
||||
append(GDScriptFunction::OPCODE_TYPE_ADJUST_DICTIONARY, 1);
|
||||
break;
|
||||
case Variant::ARRAY:
|
||||
append(GDScriptFunction::OPCODE_TYPE_ADJUST_ARRAY, 1);
|
||||
break;
|
||||
case Variant::PACKED_BYTE_ARRAY:
|
||||
append(GDScriptFunction::OPCODE_TYPE_ADJUST_PACKED_BYTE_ARRAY, 1);
|
||||
break;
|
||||
case Variant::PACKED_INT32_ARRAY:
|
||||
append(GDScriptFunction::OPCODE_TYPE_ADJUST_PACKED_INT32_ARRAY, 1);
|
||||
break;
|
||||
case Variant::PACKED_INT64_ARRAY:
|
||||
append(GDScriptFunction::OPCODE_TYPE_ADJUST_PACKED_INT64_ARRAY, 1);
|
||||
break;
|
||||
case Variant::PACKED_FLOAT32_ARRAY:
|
||||
append(GDScriptFunction::OPCODE_TYPE_ADJUST_PACKED_FLOAT32_ARRAY, 1);
|
||||
break;
|
||||
case Variant::PACKED_FLOAT64_ARRAY:
|
||||
append(GDScriptFunction::OPCODE_TYPE_ADJUST_PACKED_FLOAT64_ARRAY, 1);
|
||||
break;
|
||||
case Variant::PACKED_STRING_ARRAY:
|
||||
append(GDScriptFunction::OPCODE_TYPE_ADJUST_PACKED_STRING_ARRAY, 1);
|
||||
break;
|
||||
case Variant::PACKED_VECTOR2_ARRAY:
|
||||
append(GDScriptFunction::OPCODE_TYPE_ADJUST_PACKED_VECTOR2_ARRAY, 1);
|
||||
break;
|
||||
case Variant::PACKED_VECTOR3_ARRAY:
|
||||
append(GDScriptFunction::OPCODE_TYPE_ADJUST_PACKED_VECTOR3_ARRAY, 1);
|
||||
break;
|
||||
case Variant::PACKED_COLOR_ARRAY:
|
||||
append(GDScriptFunction::OPCODE_TYPE_ADJUST_PACKED_COLOR_ARRAY, 1);
|
||||
break;
|
||||
case Variant::NIL:
|
||||
case Variant::VARIANT_MAX:
|
||||
return;
|
||||
}
|
||||
append(p_target);
|
||||
}
|
||||
|
||||
void GDScriptByteCodeGenerator::write_unary_operator(const Address &p_target, Variant::Operator p_operator, const Address &p_left_operand) {
|
||||
if (HAS_BUILTIN_TYPE(p_left_operand)) {
|
||||
// Gather specific operator.
|
||||
|
@ -806,6 +986,14 @@ void GDScriptByteCodeGenerator::write_call_builtin_type(const Address &p_target,
|
|||
return;
|
||||
}
|
||||
|
||||
if (p_target.mode == Address::TEMPORARY) {
|
||||
Variant::Type result_type = Variant::get_builtin_method_return_type(p_type, p_method);
|
||||
Variant::Type temp_type = temporaries[p_target.address].type;
|
||||
if (result_type != temp_type) {
|
||||
write_type_adjust(p_target, result_type);
|
||||
}
|
||||
}
|
||||
|
||||
append(GDScriptFunction::OPCODE_CALL_BUILTIN_TYPE_VALIDATED, 2 + p_arguments.size());
|
||||
|
||||
for (int i = 0; i < p_arguments.size(); i++) {
|
||||
|
|
|
@ -37,6 +37,17 @@
|
|||
#include "gdscript_utility_functions.h"
|
||||
|
||||
class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
|
||||
struct StackSlot {
|
||||
Variant::Type type = Variant::NIL;
|
||||
Vector<int> bytecode_indices;
|
||||
|
||||
StackSlot() = default;
|
||||
StackSlot(Variant::Type p_type) :
|
||||
type(p_type) {}
|
||||
};
|
||||
|
||||
const static int RESERVED_STACK = 3; // For self, class, and nil.
|
||||
|
||||
bool ended = false;
|
||||
GDScriptFunction *function = nullptr;
|
||||
bool debug_stack = false;
|
||||
|
@ -47,15 +58,17 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
|
|||
List<int> stack_identifiers_counts;
|
||||
Map<StringName, int> local_constants;
|
||||
|
||||
Vector<StackSlot> locals;
|
||||
Vector<StackSlot> temporaries;
|
||||
List<int> used_temporaries;
|
||||
Map<Variant::Type, List<int>> temporaries_pool;
|
||||
|
||||
List<GDScriptFunction::StackDebug> stack_debug;
|
||||
List<Map<StringName, int>> block_identifier_stack;
|
||||
Map<StringName, int> block_identifiers;
|
||||
|
||||
int current_stack_size = 3; // First 3 spots are reserved for self, class, and nil.
|
||||
int current_temporaries = 0;
|
||||
int current_locals = 0;
|
||||
int max_locals = 0;
|
||||
int current_line = 0;
|
||||
int stack_max = 3;
|
||||
int instr_args_max = 0;
|
||||
int ptrcall_max = 0;
|
||||
|
||||
|
@ -102,7 +115,9 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
|
|||
List<List<int>> match_continues_to_patch;
|
||||
|
||||
void add_stack_identifier(const StringName &p_id, int p_stackpos) {
|
||||
current_locals++;
|
||||
if (locals.size() > max_locals) {
|
||||
max_locals = locals.size();
|
||||
}
|
||||
stack_identifiers[p_id] = p_stackpos;
|
||||
if (debug_stack) {
|
||||
block_identifiers[p_id] = p_stackpos;
|
||||
|
@ -116,7 +131,7 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
|
|||
}
|
||||
|
||||
void push_stack_identifiers() {
|
||||
stack_identifiers_counts.push_back(current_locals);
|
||||
stack_identifiers_counts.push_back(locals.size());
|
||||
stack_id_stack.push_back(stack_identifiers);
|
||||
if (debug_stack) {
|
||||
Map<StringName, int> block_ids(block_identifiers);
|
||||
|
@ -126,17 +141,16 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
|
|||
}
|
||||
|
||||
void pop_stack_identifiers() {
|
||||
current_locals = stack_identifiers_counts.back()->get();
|
||||
int current_locals = stack_identifiers_counts.back()->get();
|
||||
stack_identifiers_counts.pop_back();
|
||||
stack_identifiers = stack_id_stack.back()->get();
|
||||
stack_id_stack.pop_back();
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (current_temporaries != 0) {
|
||||
ERR_PRINT("Leaving block with non-zero temporary variables: " + itos(current_temporaries));
|
||||
if (!used_temporaries.is_empty()) {
|
||||
ERR_PRINT("Leaving block with non-zero temporary variables: " + itos(used_temporaries.size()));
|
||||
}
|
||||
#endif
|
||||
current_stack_size = current_locals + 3; // Keep the 3 reserved slots for self, class, and nil.
|
||||
|
||||
locals.resize(current_locals);
|
||||
if (debug_stack) {
|
||||
for (Map<StringName, int>::Element *E = block_identifiers.front(); E; E = E->next()) {
|
||||
GDScriptFunction::StackDebug sd;
|
||||
|
@ -279,18 +293,6 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
|
|||
return pos;
|
||||
}
|
||||
|
||||
void alloc_stack(int p_level) {
|
||||
if (p_level >= stack_max) {
|
||||
stack_max = p_level + 1;
|
||||
}
|
||||
}
|
||||
|
||||
int increase_stack() {
|
||||
int top = current_stack_size++;
|
||||
alloc_stack(current_stack_size);
|
||||
return top;
|
||||
}
|
||||
|
||||
void alloc_ptrcall(int p_params) {
|
||||
if (p_params >= ptrcall_max) {
|
||||
ptrcall_max = p_params;
|
||||
|
@ -308,9 +310,11 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
|
|||
case Address::CONSTANT:
|
||||
return p_address.address | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
|
||||
case Address::LOCAL_VARIABLE:
|
||||
case Address::TEMPORARY:
|
||||
case Address::FUNCTION_PARAMETER:
|
||||
return p_address.address | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
|
||||
case Address::TEMPORARY:
|
||||
temporaries.write[p_address.address].bytecode_indices.push_back(opcodes.size());
|
||||
return -1;
|
||||
case Address::NIL:
|
||||
return GDScriptFunction::ADDR_NIL;
|
||||
}
|
||||
|
@ -392,7 +396,7 @@ public:
|
|||
virtual uint32_t add_local_constant(const StringName &p_name, const Variant &p_constant) override;
|
||||
virtual uint32_t add_or_get_constant(const Variant &p_constant) override;
|
||||
virtual uint32_t add_or_get_name(const StringName &p_name) override;
|
||||
virtual uint32_t add_temporary() override;
|
||||
virtual uint32_t add_temporary(const GDScriptDataType &p_type) override;
|
||||
virtual void pop_temporary() override;
|
||||
|
||||
virtual void start_parameters() override;
|
||||
|
@ -409,6 +413,7 @@ public:
|
|||
#endif
|
||||
virtual void set_initial_line(int p_line) override;
|
||||
|
||||
virtual void write_type_adjust(const Address &p_target, Variant::Type p_new_type) override;
|
||||
virtual void write_unary_operator(const Address &p_target, Variant::Operator p_operator, const Address &p_left_operand) override;
|
||||
virtual void write_binary_operator(const Address &p_target, Variant::Operator p_operator, const Address &p_left_operand, const Address &p_right_operand) override;
|
||||
virtual void write_type_test(const Address &p_target, const Address &p_source, const Address &p_type) override;
|
||||
|
|
|
@ -71,7 +71,7 @@ public:
|
|||
virtual uint32_t add_local_constant(const StringName &p_name, const Variant &p_constant) = 0;
|
||||
virtual uint32_t add_or_get_constant(const Variant &p_constant) = 0;
|
||||
virtual uint32_t add_or_get_name(const StringName &p_name) = 0;
|
||||
virtual uint32_t add_temporary() = 0;
|
||||
virtual uint32_t add_temporary(const GDScriptDataType &p_type) = 0;
|
||||
virtual void pop_temporary() = 0;
|
||||
|
||||
virtual void start_parameters() = 0;
|
||||
|
@ -80,9 +80,6 @@ public:
|
|||
virtual void start_block() = 0;
|
||||
virtual void end_block() = 0;
|
||||
|
||||
// virtual int get_max_stack_level() = 0;
|
||||
// virtual int get_max_function_arguments() = 0;
|
||||
|
||||
virtual void write_start(GDScript *p_script, const StringName &p_function_name, bool p_static, MultiplayerAPI::RPCMode p_rpc_mode, const GDScriptDataType &p_return_type) = 0;
|
||||
virtual GDScriptFunction *write_end() = 0;
|
||||
|
||||
|
@ -91,9 +88,7 @@ public:
|
|||
#endif
|
||||
virtual void set_initial_line(int p_line) = 0;
|
||||
|
||||
// virtual void alloc_stack(int p_level) = 0; // Is this needed?
|
||||
// virtual void alloc_call(int p_arg_count) = 0; // This might be automatic from other functions.
|
||||
|
||||
virtual void write_type_adjust(const Address &p_target, Variant::Type p_new_type) = 0;
|
||||
virtual void write_unary_operator(const Address &p_target, Variant::Operator p_operator, const Address &p_left_operand) = 0;
|
||||
virtual void write_binary_operator(const Address &p_target, Variant::Operator p_operator, const Address &p_left_operand, const Address &p_right_operand) = 0;
|
||||
virtual void write_type_test(const Address &p_target, const Address &p_source, const Address &p_type) = 0;
|
||||
|
@ -138,7 +133,6 @@ public:
|
|||
virtual void write_construct_dictionary(const Address &p_target, const Vector<Address> &p_arguments) = 0;
|
||||
virtual void write_await(const Address &p_target, const Address &p_operand) = 0;
|
||||
virtual void write_if(const Address &p_condition) = 0;
|
||||
// virtual void write_elseif(const Address &p_condition) = 0; This kind of makes things more difficult for no real benefit.
|
||||
virtual void write_else() = 0;
|
||||
virtual void write_endif() = 0;
|
||||
virtual void start_for(const GDScriptDataType &p_iterator_type, const GDScriptDataType &p_list_type) = 0;
|
||||
|
|
|
@ -711,7 +711,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
|
|||
case GDScriptParser::Node::UNARY_OPERATOR: {
|
||||
const GDScriptParser::UnaryOpNode *unary = static_cast<const GDScriptParser::UnaryOpNode *>(p_expression);
|
||||
|
||||
GDScriptCodeGenerator::Address result = codegen.add_temporary();
|
||||
GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(unary->get_datatype()));
|
||||
|
||||
GDScriptCodeGenerator::Address operand = _parse_expression(codegen, r_error, unary->operand);
|
||||
if (r_error) {
|
||||
|
@ -729,7 +729,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
|
|||
case GDScriptParser::Node::BINARY_OPERATOR: {
|
||||
const GDScriptParser::BinaryOpNode *binary = static_cast<const GDScriptParser::BinaryOpNode *>(p_expression);
|
||||
|
||||
GDScriptCodeGenerator::Address result = codegen.add_temporary();
|
||||
GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(binary->get_datatype()));
|
||||
|
||||
switch (binary->operation) {
|
||||
case GDScriptParser::BinaryOpNode::OP_LOGIC_AND: {
|
||||
|
|
|
@ -66,7 +66,7 @@ class GDScriptCompiler {
|
|||
}
|
||||
|
||||
GDScriptCodeGenerator::Address add_temporary(const GDScriptDataType &p_type = GDScriptDataType()) {
|
||||
uint32_t addr = generator->add_temporary();
|
||||
uint32_t addr = generator->add_temporary(p_type);
|
||||
return GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::TEMPORARY, addr, p_type);
|
||||
}
|
||||
|
||||
|
|
|
@ -894,6 +894,51 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
|
|||
|
||||
incr += 2;
|
||||
} break;
|
||||
|
||||
#define DISASSEMBLE_TYPE_ADJUST(m_v_type) \
|
||||
case OPCODE_TYPE_ADJUST_##m_v_type: { \
|
||||
text += "type adjust ("; \
|
||||
text += #m_v_type; \
|
||||
text += ") "; \
|
||||
text += DADDR(1); \
|
||||
incr += 2; \
|
||||
} break
|
||||
|
||||
DISASSEMBLE_TYPE_ADJUST(BOOL);
|
||||
DISASSEMBLE_TYPE_ADJUST(INT);
|
||||
DISASSEMBLE_TYPE_ADJUST(FLOAT);
|
||||
DISASSEMBLE_TYPE_ADJUST(STRING);
|
||||
DISASSEMBLE_TYPE_ADJUST(VECTOR2);
|
||||
DISASSEMBLE_TYPE_ADJUST(VECTOR2I);
|
||||
DISASSEMBLE_TYPE_ADJUST(RECT2);
|
||||
DISASSEMBLE_TYPE_ADJUST(RECT2I);
|
||||
DISASSEMBLE_TYPE_ADJUST(VECTOR3);
|
||||
DISASSEMBLE_TYPE_ADJUST(VECTOR3I);
|
||||
DISASSEMBLE_TYPE_ADJUST(TRANSFORM2D);
|
||||
DISASSEMBLE_TYPE_ADJUST(PLANE);
|
||||
DISASSEMBLE_TYPE_ADJUST(QUAT);
|
||||
DISASSEMBLE_TYPE_ADJUST(AABB);
|
||||
DISASSEMBLE_TYPE_ADJUST(BASIS);
|
||||
DISASSEMBLE_TYPE_ADJUST(TRANSFORM);
|
||||
DISASSEMBLE_TYPE_ADJUST(COLOR);
|
||||
DISASSEMBLE_TYPE_ADJUST(STRING_NAME);
|
||||
DISASSEMBLE_TYPE_ADJUST(NODE_PATH);
|
||||
DISASSEMBLE_TYPE_ADJUST(RID);
|
||||
DISASSEMBLE_TYPE_ADJUST(OBJECT);
|
||||
DISASSEMBLE_TYPE_ADJUST(CALLABLE);
|
||||
DISASSEMBLE_TYPE_ADJUST(SIGNAL);
|
||||
DISASSEMBLE_TYPE_ADJUST(DICTIONARY);
|
||||
DISASSEMBLE_TYPE_ADJUST(ARRAY);
|
||||
DISASSEMBLE_TYPE_ADJUST(PACKED_BYTE_ARRAY);
|
||||
DISASSEMBLE_TYPE_ADJUST(PACKED_INT32_ARRAY);
|
||||
DISASSEMBLE_TYPE_ADJUST(PACKED_INT64_ARRAY);
|
||||
DISASSEMBLE_TYPE_ADJUST(PACKED_FLOAT32_ARRAY);
|
||||
DISASSEMBLE_TYPE_ADJUST(PACKED_FLOAT64_ARRAY);
|
||||
DISASSEMBLE_TYPE_ADJUST(PACKED_STRING_ARRAY);
|
||||
DISASSEMBLE_TYPE_ADJUST(PACKED_VECTOR2_ARRAY);
|
||||
DISASSEMBLE_TYPE_ADJUST(PACKED_VECTOR3_ARRAY);
|
||||
DISASSEMBLE_TYPE_ADJUST(PACKED_COLOR_ARRAY);
|
||||
|
||||
case OPCODE_ASSERT: {
|
||||
text += "assert (";
|
||||
text += DADDR(1);
|
||||
|
|
|
@ -351,6 +351,40 @@ public:
|
|||
OPCODE_ITERATE_PACKED_COLOR_ARRAY,
|
||||
OPCODE_ITERATE_OBJECT,
|
||||
OPCODE_STORE_NAMED_GLOBAL,
|
||||
OPCODE_TYPE_ADJUST_BOOL,
|
||||
OPCODE_TYPE_ADJUST_INT,
|
||||
OPCODE_TYPE_ADJUST_FLOAT,
|
||||
OPCODE_TYPE_ADJUST_STRING,
|
||||
OPCODE_TYPE_ADJUST_VECTOR2,
|
||||
OPCODE_TYPE_ADJUST_VECTOR2I,
|
||||
OPCODE_TYPE_ADJUST_RECT2,
|
||||
OPCODE_TYPE_ADJUST_RECT2I,
|
||||
OPCODE_TYPE_ADJUST_VECTOR3,
|
||||
OPCODE_TYPE_ADJUST_VECTOR3I,
|
||||
OPCODE_TYPE_ADJUST_TRANSFORM2D,
|
||||
OPCODE_TYPE_ADJUST_PLANE,
|
||||
OPCODE_TYPE_ADJUST_QUAT,
|
||||
OPCODE_TYPE_ADJUST_AABB,
|
||||
OPCODE_TYPE_ADJUST_BASIS,
|
||||
OPCODE_TYPE_ADJUST_TRANSFORM,
|
||||
OPCODE_TYPE_ADJUST_COLOR,
|
||||
OPCODE_TYPE_ADJUST_STRING_NAME,
|
||||
OPCODE_TYPE_ADJUST_NODE_PATH,
|
||||
OPCODE_TYPE_ADJUST_RID,
|
||||
OPCODE_TYPE_ADJUST_OBJECT,
|
||||
OPCODE_TYPE_ADJUST_CALLABLE,
|
||||
OPCODE_TYPE_ADJUST_SIGNAL,
|
||||
OPCODE_TYPE_ADJUST_DICTIONARY,
|
||||
OPCODE_TYPE_ADJUST_ARRAY,
|
||||
OPCODE_TYPE_ADJUST_PACKED_BYTE_ARRAY,
|
||||
OPCODE_TYPE_ADJUST_PACKED_INT32_ARRAY,
|
||||
OPCODE_TYPE_ADJUST_PACKED_INT64_ARRAY,
|
||||
OPCODE_TYPE_ADJUST_PACKED_FLOAT32_ARRAY,
|
||||
OPCODE_TYPE_ADJUST_PACKED_FLOAT64_ARRAY,
|
||||
OPCODE_TYPE_ADJUST_PACKED_STRING_ARRAY,
|
||||
OPCODE_TYPE_ADJUST_PACKED_VECTOR2_ARRAY,
|
||||
OPCODE_TYPE_ADJUST_PACKED_VECTOR3_ARRAY,
|
||||
OPCODE_TYPE_ADJUST_PACKED_COLOR_ARRAY,
|
||||
OPCODE_ASSERT,
|
||||
OPCODE_BREAKPOINT,
|
||||
OPCODE_LINE,
|
||||
|
|
|
@ -282,6 +282,40 @@ String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const
|
|||
&&OPCODE_ITERATE_PACKED_COLOR_ARRAY, \
|
||||
&&OPCODE_ITERATE_OBJECT, \
|
||||
&&OPCODE_STORE_NAMED_GLOBAL, \
|
||||
&&OPCODE_TYPE_ADJUST_BOOL, \
|
||||
&&OPCODE_TYPE_ADJUST_INT, \
|
||||
&&OPCODE_TYPE_ADJUST_FLOAT, \
|
||||
&&OPCODE_TYPE_ADJUST_STRING, \
|
||||
&&OPCODE_TYPE_ADJUST_VECTOR2, \
|
||||
&&OPCODE_TYPE_ADJUST_VECTOR2I, \
|
||||
&&OPCODE_TYPE_ADJUST_RECT2, \
|
||||
&&OPCODE_TYPE_ADJUST_RECT2I, \
|
||||
&&OPCODE_TYPE_ADJUST_VECTOR3, \
|
||||
&&OPCODE_TYPE_ADJUST_VECTOR3I, \
|
||||
&&OPCODE_TYPE_ADJUST_TRANSFORM2D, \
|
||||
&&OPCODE_TYPE_ADJUST_PLANE, \
|
||||
&&OPCODE_TYPE_ADJUST_QUAT, \
|
||||
&&OPCODE_TYPE_ADJUST_AABB, \
|
||||
&&OPCODE_TYPE_ADJUST_BASIS, \
|
||||
&&OPCODE_TYPE_ADJUST_TRANSFORM, \
|
||||
&&OPCODE_TYPE_ADJUST_COLOR, \
|
||||
&&OPCODE_TYPE_ADJUST_STRING_NAME, \
|
||||
&&OPCODE_TYPE_ADJUST_NODE_PATH, \
|
||||
&&OPCODE_TYPE_ADJUST_RID, \
|
||||
&&OPCODE_TYPE_ADJUST_OBJECT, \
|
||||
&&OPCODE_TYPE_ADJUST_CALLABLE, \
|
||||
&&OPCODE_TYPE_ADJUST_SIGNAL, \
|
||||
&&OPCODE_TYPE_ADJUST_DICTIONARY, \
|
||||
&&OPCODE_TYPE_ADJUST_ARRAY, \
|
||||
&&OPCODE_TYPE_ADJUST_PACKED_BYTE_ARRAY, \
|
||||
&&OPCODE_TYPE_ADJUST_PACKED_INT32_ARRAY, \
|
||||
&&OPCODE_TYPE_ADJUST_PACKED_INT64_ARRAY, \
|
||||
&&OPCODE_TYPE_ADJUST_PACKED_FLOAT32_ARRAY, \
|
||||
&&OPCODE_TYPE_ADJUST_PACKED_FLOAT64_ARRAY, \
|
||||
&&OPCODE_TYPE_ADJUST_PACKED_STRING_ARRAY, \
|
||||
&&OPCODE_TYPE_ADJUST_PACKED_VECTOR2_ARRAY, \
|
||||
&&OPCODE_TYPE_ADJUST_PACKED_VECTOR3_ARRAY, \
|
||||
&&OPCODE_TYPE_ADJUST_PACKED_COLOR_ARRAY, \
|
||||
&&OPCODE_ASSERT, \
|
||||
&&OPCODE_BREAKPOINT, \
|
||||
&&OPCODE_LINE, \
|
||||
|
@ -2973,6 +3007,50 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
|
|||
}
|
||||
DISPATCH_OPCODE;
|
||||
|
||||
#define OPCODE_TYPE_ADJUST(m_v_type, m_c_type) \
|
||||
OPCODE(OPCODE_TYPE_ADJUST_##m_v_type) { \
|
||||
CHECK_SPACE(2); \
|
||||
GET_INSTRUCTION_ARG(arg, 0); \
|
||||
VariantTypeAdjust<m_c_type>::adjust(arg); \
|
||||
ip += 2; \
|
||||
} \
|
||||
DISPATCH_OPCODE
|
||||
|
||||
OPCODE_TYPE_ADJUST(BOOL, bool);
|
||||
OPCODE_TYPE_ADJUST(INT, int64_t);
|
||||
OPCODE_TYPE_ADJUST(FLOAT, double);
|
||||
OPCODE_TYPE_ADJUST(STRING, String);
|
||||
OPCODE_TYPE_ADJUST(VECTOR2, Vector2);
|
||||
OPCODE_TYPE_ADJUST(VECTOR2I, Vector2i);
|
||||
OPCODE_TYPE_ADJUST(RECT2, Rect2);
|
||||
OPCODE_TYPE_ADJUST(RECT2I, Rect2i);
|
||||
OPCODE_TYPE_ADJUST(VECTOR3, Vector3);
|
||||
OPCODE_TYPE_ADJUST(VECTOR3I, Vector3i);
|
||||
OPCODE_TYPE_ADJUST(TRANSFORM2D, Transform2D);
|
||||
OPCODE_TYPE_ADJUST(PLANE, Plane);
|
||||
OPCODE_TYPE_ADJUST(QUAT, Quat);
|
||||
OPCODE_TYPE_ADJUST(AABB, AABB);
|
||||
OPCODE_TYPE_ADJUST(BASIS, Basis);
|
||||
OPCODE_TYPE_ADJUST(TRANSFORM, Transform);
|
||||
OPCODE_TYPE_ADJUST(COLOR, Color);
|
||||
OPCODE_TYPE_ADJUST(STRING_NAME, StringName);
|
||||
OPCODE_TYPE_ADJUST(NODE_PATH, NodePath);
|
||||
OPCODE_TYPE_ADJUST(RID, RID);
|
||||
OPCODE_TYPE_ADJUST(OBJECT, Object *);
|
||||
OPCODE_TYPE_ADJUST(CALLABLE, Callable);
|
||||
OPCODE_TYPE_ADJUST(SIGNAL, Signal);
|
||||
OPCODE_TYPE_ADJUST(DICTIONARY, Dictionary);
|
||||
OPCODE_TYPE_ADJUST(ARRAY, Array);
|
||||
OPCODE_TYPE_ADJUST(PACKED_BYTE_ARRAY, PackedByteArray);
|
||||
OPCODE_TYPE_ADJUST(PACKED_INT32_ARRAY, PackedInt32Array);
|
||||
OPCODE_TYPE_ADJUST(PACKED_INT64_ARRAY, PackedInt64Array);
|
||||
OPCODE_TYPE_ADJUST(PACKED_FLOAT32_ARRAY, PackedFloat32Array);
|
||||
OPCODE_TYPE_ADJUST(PACKED_FLOAT64_ARRAY, PackedFloat64Array);
|
||||
OPCODE_TYPE_ADJUST(PACKED_STRING_ARRAY, PackedStringArray);
|
||||
OPCODE_TYPE_ADJUST(PACKED_VECTOR2_ARRAY, PackedVector2Array);
|
||||
OPCODE_TYPE_ADJUST(PACKED_VECTOR3_ARRAY, PackedVector3Array);
|
||||
OPCODE_TYPE_ADJUST(PACKED_COLOR_ARRAY, PackedColorArray);
|
||||
|
||||
OPCODE(OPCODE_ASSERT) {
|
||||
CHECK_SPACE(3);
|
||||
|
||||
|
|
Loading…
Reference in a new issue