Przeglądaj źródła

GDScript: Fix loading of interdependent autoloads

Move the autoload resolution to runtime by loading it into the stack
with an extra instruction. This allows an autoload to use another
autoload singleton independent of load order.
George Marques 3 lat temu
rodzic
commit
3d13588057

+ 6 - 0
modules/gdscript/gdscript_byte_codegen.cpp

@@ -864,6 +864,12 @@ void GDScriptByteCodeGenerator::write_assign_default_parameter(const Address &p_
 	function->default_arguments.push_back(opcodes.size());
 	function->default_arguments.push_back(opcodes.size());
 }
 }
 
 
+void GDScriptByteCodeGenerator::write_store_global(const Address &p_dst, int p_global_index) {
+	append(GDScriptFunction::OPCODE_STORE_GLOBAL, 1);
+	append(p_dst);
+	append(p_global_index);
+}
+
 void GDScriptByteCodeGenerator::write_store_named_global(const Address &p_dst, const StringName &p_global) {
 void GDScriptByteCodeGenerator::write_store_named_global(const Address &p_dst, const StringName &p_global) {
 	append(GDScriptFunction::OPCODE_STORE_NAMED_GLOBAL, 1);
 	append(GDScriptFunction::OPCODE_STORE_NAMED_GLOBAL, 1);
 	append(p_dst);
 	append(p_dst);

+ 1 - 0
modules/gdscript/gdscript_byte_codegen.h

@@ -454,6 +454,7 @@ public:
 	virtual void write_assign_true(const Address &p_target) override;
 	virtual void write_assign_true(const Address &p_target) override;
 	virtual void write_assign_false(const Address &p_target) override;
 	virtual void write_assign_false(const Address &p_target) override;
 	virtual void write_assign_default_parameter(const Address &p_dst, const Address &p_src) override;
 	virtual void write_assign_default_parameter(const Address &p_dst, const Address &p_src) override;
+	virtual void write_store_global(const Address &p_dst, int p_global_index) override;
 	virtual void write_store_named_global(const Address &p_dst, const StringName &p_global) override;
 	virtual void write_store_named_global(const Address &p_dst, const StringName &p_global) override;
 	virtual void write_cast(const Address &p_target, const Address &p_source, const GDScriptDataType &p_type) override;
 	virtual void write_cast(const Address &p_target, const Address &p_source, const GDScriptDataType &p_type) override;
 	virtual void write_call(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) override;
 	virtual void write_call(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) override;

+ 1 - 0
modules/gdscript/gdscript_codegen.h

@@ -115,6 +115,7 @@ public:
 	virtual void write_assign_true(const Address &p_target) = 0;
 	virtual void write_assign_true(const Address &p_target) = 0;
 	virtual void write_assign_false(const Address &p_target) = 0;
 	virtual void write_assign_false(const Address &p_target) = 0;
 	virtual void write_assign_default_parameter(const Address &dst, const Address &src) = 0;
 	virtual void write_assign_default_parameter(const Address &dst, const Address &src) = 0;
+	virtual void write_store_global(const Address &p_dst, int p_global_index) = 0;
 	virtual void write_store_named_global(const Address &p_dst, const StringName &p_global) = 0;
 	virtual void write_store_named_global(const Address &p_dst, const StringName &p_global) = 0;
 	virtual void write_cast(const Address &p_target, const Address &p_source, const GDScriptDataType &p_type) = 0;
 	virtual void write_cast(const Address &p_target, const Address &p_source, const GDScriptDataType &p_type) = 0;
 	virtual void write_call(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) = 0;
 	virtual void write_call(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) = 0;

+ 16 - 3
modules/gdscript/gdscript_compiler.cpp

@@ -35,6 +35,8 @@
 #include "gdscript_cache.h"
 #include "gdscript_cache.h"
 #include "gdscript_utility_functions.h"
 #include "gdscript_utility_functions.h"
 
 
+#include "core/config/project_settings.h"
+
 bool GDScriptCompiler::_is_class_member_property(CodeGen &codegen, const StringName &p_name) {
 bool GDScriptCompiler::_is_class_member_property(CodeGen &codegen, const StringName &p_name) {
 	if (codegen.function_node && codegen.function_node->is_static) {
 	if (codegen.function_node && codegen.function_node->is_static) {
 		return false;
 		return false;
@@ -316,10 +318,21 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
 				}
 				}
 			}
 			}
 
 
+			// Try globals.
 			if (GDScriptLanguage::get_singleton()->get_global_map().has(identifier)) {
 			if (GDScriptLanguage::get_singleton()->get_global_map().has(identifier)) {
-				int idx = GDScriptLanguage::get_singleton()->get_global_map()[identifier];
-				Variant global = GDScriptLanguage::get_singleton()->get_global_array()[idx];
-				return codegen.add_constant(global); // TODO: Get type.
+				// If it's an autoload singleton, we postpone to load it at runtime.
+				// This is so one autoload doesn't try to load another before it's compiled.
+				OrderedHashMap<StringName, ProjectSettings::AutoloadInfo> autoloads = ProjectSettings::get_singleton()->get_autoload_list();
+				if (autoloads.has(identifier) && autoloads[identifier].is_singleton) {
+					GDScriptCodeGenerator::Address global = codegen.add_temporary(_gdtype_from_datatype(in->get_datatype()));
+					int idx = GDScriptLanguage::get_singleton()->get_global_map()[identifier];
+					gen->write_store_global(global, idx);
+					return global;
+				} else {
+					int idx = GDScriptLanguage::get_singleton()->get_global_map()[identifier];
+					Variant global = GDScriptLanguage::get_singleton()->get_global_array()[idx];
+					return codegen.add_constant(global);
+				}
 			}
 			}
 
 
 			// Try global classes.
 			// Try global classes.

+ 8 - 0
modules/gdscript/gdscript_disassembler.cpp

@@ -914,6 +914,14 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
 				incr += 5;
 				incr += 5;
 			} break;
 			} break;
 				DISASSEMBLE_ITERATE_TYPES(DISASSEMBLE_ITERATE);
 				DISASSEMBLE_ITERATE_TYPES(DISASSEMBLE_ITERATE);
+			case OPCODE_STORE_GLOBAL: {
+				text += "store global ";
+				text += DADDR(1);
+				text += " = ";
+				text += String::num_int64(_code_ptr[ip + 2]);
+
+				incr += 3;
+			} break;
 			case OPCODE_STORE_NAMED_GLOBAL: {
 			case OPCODE_STORE_NAMED_GLOBAL: {
 				text += "store named global ";
 				text += "store named global ";
 				text += DADDR(1);
 				text += DADDR(1);

+ 1 - 0
modules/gdscript/gdscript_function.h

@@ -348,6 +348,7 @@ public:
 		OPCODE_ITERATE_PACKED_VECTOR3_ARRAY,
 		OPCODE_ITERATE_PACKED_VECTOR3_ARRAY,
 		OPCODE_ITERATE_PACKED_COLOR_ARRAY,
 		OPCODE_ITERATE_PACKED_COLOR_ARRAY,
 		OPCODE_ITERATE_OBJECT,
 		OPCODE_ITERATE_OBJECT,
+		OPCODE_STORE_GLOBAL,
 		OPCODE_STORE_NAMED_GLOBAL,
 		OPCODE_STORE_NAMED_GLOBAL,
 		OPCODE_TYPE_ADJUST_BOOL,
 		OPCODE_TYPE_ADJUST_BOOL,
 		OPCODE_TYPE_ADJUST_INT,
 		OPCODE_TYPE_ADJUST_INT,

+ 13 - 0
modules/gdscript/gdscript_vm.cpp

@@ -322,6 +322,7 @@ void (*type_init_function_table[])(Variant *) = {
 		&&OPCODE_ITERATE_PACKED_VECTOR3_ARRAY,       \
 		&&OPCODE_ITERATE_PACKED_VECTOR3_ARRAY,       \
 		&&OPCODE_ITERATE_PACKED_COLOR_ARRAY,         \
 		&&OPCODE_ITERATE_PACKED_COLOR_ARRAY,         \
 		&&OPCODE_ITERATE_OBJECT,                     \
 		&&OPCODE_ITERATE_OBJECT,                     \
+		&&OPCODE_STORE_GLOBAL,                       \
 		&&OPCODE_STORE_NAMED_GLOBAL,                 \
 		&&OPCODE_STORE_NAMED_GLOBAL,                 \
 		&&OPCODE_TYPE_ADJUST_BOOL,                   \
 		&&OPCODE_TYPE_ADJUST_BOOL,                   \
 		&&OPCODE_TYPE_ADJUST_INT,                    \
 		&&OPCODE_TYPE_ADJUST_INT,                    \
@@ -3116,6 +3117,18 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 			}
 			}
 			DISPATCH_OPCODE;
 			DISPATCH_OPCODE;
 
 
+			OPCODE(OPCODE_STORE_GLOBAL) {
+				CHECK_SPACE(3);
+				int global_idx = _code_ptr[ip + 2];
+				GD_ERR_BREAK(global_idx < 0 || global_idx >= GDScriptLanguage::get_singleton()->get_global_array_size());
+
+				GET_INSTRUCTION_ARG(dst, 0);
+				*dst = GDScriptLanguage::get_singleton()->get_global_array()[global_idx];
+
+				ip += 3;
+			}
+			DISPATCH_OPCODE;
+
 			OPCODE(OPCODE_STORE_NAMED_GLOBAL) {
 			OPCODE(OPCODE_STORE_NAMED_GLOBAL) {
 				CHECK_SPACE(3);
 				CHECK_SPACE(3);
 				int globalname_idx = _code_ptr[ip + 2];
 				int globalname_idx = _code_ptr[ip + 2];