summaryrefslogtreecommitdiff
path: root/modules/gdscript/gdscript_byte_codegen.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gdscript/gdscript_byte_codegen.cpp')
-rw-r--r--modules/gdscript/gdscript_byte_codegen.cpp110
1 files changed, 85 insertions, 25 deletions
diff --git a/modules/gdscript/gdscript_byte_codegen.cpp b/modules/gdscript/gdscript_byte_codegen.cpp
index 5f1c738207..d89b89c8b9 100644
--- a/modules/gdscript/gdscript_byte_codegen.cpp
+++ b/modules/gdscript/gdscript_byte_codegen.cpp
@@ -40,10 +40,6 @@ uint32_t GDScriptByteCodeGenerator::add_parameter(const StringName &p_name, bool
function->_argument_count++;
function->argument_types.push_back(p_type);
if (p_is_optional) {
- if (function->_default_arg_count == 0) {
- append(GDScriptFunction::OPCODE_JUMP_TO_DEF_ARGUMENT);
- }
- function->default_arguments.push_back(opcodes.size());
function->_default_arg_count++;
}
@@ -77,15 +73,31 @@ uint32_t GDScriptByteCodeGenerator::add_or_get_name(const StringName &p_name) {
uint32_t GDScriptByteCodeGenerator::add_temporary() {
current_temporaries++;
- return increase_stack();
+ int idx = increase_stack();
+#ifdef DEBUG_ENABLED
+ temp_stack.push_back(idx);
+#endif
+ return idx;
}
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--;
}
-void GDScriptByteCodeGenerator::start_parameters() {}
+void GDScriptByteCodeGenerator::start_parameters() {
+ if (function->_default_arg_count > 0) {
+ append(GDScriptFunction::OPCODE_JUMP_TO_DEF_ARGUMENT);
+ function->default_arguments.push_back(opcodes.size());
+ }
+}
void GDScriptByteCodeGenerator::end_parameters() {
function->default_arguments.invert();
@@ -111,6 +123,11 @@ 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));
+ }
+#endif
append(GDScriptFunction::OPCODE_END, 0);
if (constant_map.size()) {
@@ -151,7 +168,7 @@ GDScriptFunction *GDScriptByteCodeGenerator::write_end() {
}
if (function->default_arguments.size()) {
- function->_default_arg_count = function->default_arguments.size();
+ function->_default_arg_count = function->default_arguments.size() - 1;
function->_default_arg_ptr = &function->default_arguments[0];
} else {
function->_default_arg_count = 0;
@@ -305,7 +322,28 @@ 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_operator(const Address &p_target, Variant::Operator p_operator, const Address &p_left_operand, const Address &p_right_operand) {
+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.
+ Variant::ValidatedOperatorEvaluator op_func = Variant::get_validated_operator_evaluator(p_operator, p_left_operand.type.builtin_type, Variant::NIL);
+
+ append(GDScriptFunction::OPCODE_OPERATOR_VALIDATED, 3);
+ append(p_left_operand);
+ append(Address());
+ append(p_target);
+ append(op_func);
+ return;
+ }
+
+ // No specific types, perform variant evaluation.
+ append(GDScriptFunction::OPCODE_OPERATOR, 3);
+ append(p_left_operand);
+ append(Address());
+ append(p_target);
+ append(p_operator);
+}
+
+void GDScriptByteCodeGenerator::write_binary_operator(const Address &p_target, Variant::Operator p_operator, const Address &p_left_operand, const Address &p_right_operand) {
if (HAS_BUILTIN_TYPE(p_left_operand) && HAS_BUILTIN_TYPE(p_right_operand)) {
// Gather specific operator.
Variant::ValidatedOperatorEvaluator op_func = Variant::get_validated_operator_evaluator(p_operator, p_left_operand.type.builtin_type, p_right_operand.type.builtin_type);
@@ -596,6 +634,11 @@ void GDScriptByteCodeGenerator::write_assign_false(const Address &p_target) {
append(p_target);
}
+void GDScriptByteCodeGenerator::write_assign_default_parameter(const Address &p_dst, const Address &p_src) {
+ write_assign(p_dst, p_src);
+ function->default_arguments.push_back(opcodes.size());
+}
+
void GDScriptByteCodeGenerator::write_cast(const Address &p_target, const Address &p_source, const GDScriptDataType &p_type) {
int index = 0;
@@ -905,23 +948,39 @@ void GDScriptByteCodeGenerator::write_endif() {
if_jmp_addrs.pop_back();
}
-void GDScriptByteCodeGenerator::write_for(const Address &p_variable, const Address &p_list) {
- int counter_pos = add_temporary() | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
- int container_pos = add_temporary() | (GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS);
+void GDScriptByteCodeGenerator::start_for(const GDScriptDataType &p_iterator_type, const GDScriptDataType &p_list_type) {
+ Address counter(Address::LOCAL_VARIABLE, add_local("@counter_pos", p_iterator_type), p_iterator_type);
+ Address container(Address::LOCAL_VARIABLE, add_local("@container_pos", p_list_type), p_list_type);
- current_breaks_to_patch.push_back(List<int>());
+ // Store state.
+ for_counter_variables.push_back(counter);
+ for_container_variables.push_back(container);
+}
+
+void GDScriptByteCodeGenerator::write_for_assignment(const Address &p_variable, const Address &p_list) {
+ const Address &container = for_container_variables.back()->get();
// Assign container.
append(GDScriptFunction::OPCODE_ASSIGN, 2);
- append(container_pos);
+ append(container);
append(p_list);
+ for_iterator_variables.push_back(p_variable);
+}
+
+void GDScriptByteCodeGenerator::write_for() {
+ const Address &iterator = for_iterator_variables.back()->get();
+ const Address &counter = for_counter_variables.back()->get();
+ const Address &container = for_container_variables.back()->get();
+
+ current_breaks_to_patch.push_back(List<int>());
+
GDScriptFunction::Opcode begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN;
GDScriptFunction::Opcode iterate_opcode = GDScriptFunction::OPCODE_ITERATE;
- if (p_list.type.has_type) {
- if (p_list.type.kind == GDScriptDataType::BUILTIN) {
- switch (p_list.type.builtin_type) {
+ if (container.type.has_type) {
+ if (container.type.kind == GDScriptDataType::BUILTIN) {
+ switch (container.type.builtin_type) {
case Variant::INT:
begin_opcode = GDScriptFunction::OPCODE_ITERATE_BEGIN_INT;
iterate_opcode = GDScriptFunction::OPCODE_ITERATE_INT;
@@ -1005,9 +1064,9 @@ void GDScriptByteCodeGenerator::write_for(const Address &p_variable, const Addre
// Begin loop.
append(begin_opcode, 3);
- append(counter_pos);
- append(container_pos);
- append(p_variable);
+ append(counter);
+ append(container);
+ append(iterator);
for_jmp_addrs.push_back(opcodes.size());
append(0); // End of loop address, will be patched.
append(GDScriptFunction::OPCODE_JUMP, 0);
@@ -1017,9 +1076,9 @@ void GDScriptByteCodeGenerator::write_for(const Address &p_variable, const Addre
int continue_addr = opcodes.size();
continue_addrs.push_back(continue_addr);
append(iterate_opcode, 3);
- append(counter_pos);
- append(container_pos);
- append(p_variable);
+ append(counter);
+ append(container);
+ append(iterator);
for_jmp_addrs.push_back(opcodes.size());
append(0); // Jump destination, will be patched.
}
@@ -1042,9 +1101,10 @@ void GDScriptByteCodeGenerator::write_endfor() {
}
current_breaks_to_patch.pop_back();
- // Remove loop temporaries.
- pop_temporary();
- pop_temporary();
+ // Pop state.
+ for_iterator_variables.pop_back();
+ for_counter_variables.pop_back();
+ for_container_variables.pop_back();
}
void GDScriptByteCodeGenerator::start_while_condition() {