From a3816434a682cac510fd24a97cbebd17b1032deb Mon Sep 17 00:00:00 2001 From: George Marques Date: Mon, 9 Jan 2023 09:20:18 -0300 Subject: GDScript: Don't use the NIL address to hold return value of functions This prevents that the NIL address is filled with another value, which causes problems for some instructions that read from NIL. --- modules/gdscript/gdscript_compiler.cpp | 46 ++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 22 deletions(-) (limited to 'modules/gdscript/gdscript_compiler.cpp') diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index 2d36692c3c..640d7dca2f 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -520,10 +520,12 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code case GDScriptParser::Node::CALL: { const GDScriptParser::CallNode *call = static_cast(p_expression); GDScriptDataType type = _gdtype_from_datatype(call->get_datatype(), codegen.script); - GDScriptCodeGenerator::Address result = codegen.add_temporary(type); - GDScriptCodeGenerator::Address nil = GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::NIL); - - GDScriptCodeGenerator::Address return_addr = p_root ? nil : result; + GDScriptCodeGenerator::Address result; + if (p_root) { + result = GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::NIL); + } else { + result = codegen.add_temporary(type); + } Vector arguments; for (int i = 0; i < call->arguments.size(); i++) { @@ -538,20 +540,20 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code // Construct a built-in type. Variant::Type vtype = GDScriptParser::get_builtin_type(static_cast(call->callee)->name); - gen->write_construct(return_addr, vtype, arguments); + gen->write_construct(result, vtype, arguments); } else if (!call->is_super && call->callee->type == GDScriptParser::Node::IDENTIFIER && Variant::has_utility_function(call->function_name)) { // Variant utility function. - gen->write_call_utility(return_addr, call->function_name, arguments); + gen->write_call_utility(result, call->function_name, arguments); } else if (!call->is_super && call->callee->type == GDScriptParser::Node::IDENTIFIER && GDScriptUtilityFunctions::function_exists(call->function_name)) { // GDScript utility function. - gen->write_call_gdscript_utility(return_addr, GDScriptUtilityFunctions::get_function(call->function_name), arguments); + gen->write_call_gdscript_utility(result, GDScriptUtilityFunctions::get_function(call->function_name), arguments); } else { // Regular function. const GDScriptParser::ExpressionNode *callee = call->callee; if (call->is_super) { // Super call. - gen->write_super_call(return_addr, call->function_name, arguments); + gen->write_super_call(result, call->function_name, arguments); } else { if (callee->type == GDScriptParser::Node::IDENTIFIER) { // Self function call. @@ -563,24 +565,24 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code if (_have_exact_arguments(method, arguments)) { // Exact arguments, use ptrcall. - gen->write_call_ptrcall(return_addr, self, method, arguments); + gen->write_call_ptrcall(result, self, method, arguments); } else { // Not exact arguments, but still can use method bind call. - gen->write_call_method_bind(return_addr, self, method, arguments); + 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; self.mode = GDScriptCodeGenerator::Address::CLASS; if (within_await) { - gen->write_call_async(return_addr, self, call->function_name, arguments); + gen->write_call_async(result, self, call->function_name, arguments); } else { - gen->write_call(return_addr, self, call->function_name, arguments); + gen->write_call(result, self, call->function_name, arguments); } } else { if (within_await) { - gen->write_call_self_async(return_addr, call->function_name, arguments); + gen->write_call_self_async(result, call->function_name, arguments); } else { - gen->write_call_self(return_addr, call->function_name, arguments); + gen->write_call_self(result, call->function_name, arguments); } } } else if (callee->type == GDScriptParser::Node::SUBSCRIPT) { @@ -589,18 +591,18 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code if (subscript->is_attribute) { // May be static built-in method call. if (!call->is_super && subscript->base->type == GDScriptParser::Node::IDENTIFIER && GDScriptParser::get_builtin_type(static_cast(subscript->base)->name) < Variant::VARIANT_MAX) { - gen->write_call_builtin_type_static(return_addr, GDScriptParser::get_builtin_type(static_cast(subscript->base)->name), subscript->attribute->name, arguments); + gen->write_call_builtin_type_static(result, GDScriptParser::get_builtin_type(static_cast(subscript->base)->name), subscript->attribute->name, arguments); } else if (!call->is_super && subscript->base->type == GDScriptParser::Node::IDENTIFIER && call->function_name != SNAME("new") && ClassDB::class_exists(static_cast(subscript->base)->name) && !Engine::get_singleton()->has_singleton(static_cast(subscript->base)->name)) { // It's a static native method call. - gen->write_call_native_static(return_addr, static_cast(subscript->base)->name, subscript->attribute->name, arguments); + gen->write_call_native_static(result, static_cast(subscript->base)->name, subscript->attribute->name, arguments); } else { GDScriptCodeGenerator::Address base = _parse_expression(codegen, r_error, subscript->base); if (r_error) { return GDScriptCodeGenerator::Address(); } if (within_await) { - gen->write_call_async(return_addr, 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; @@ -613,18 +615,18 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code MethodBind *method = ClassDB::get_method(class_name, call->function_name); if (_have_exact_arguments(method, arguments)) { // Exact arguments, use ptrcall. - gen->write_call_ptrcall(return_addr, base, method, arguments); + gen->write_call_ptrcall(result, base, method, arguments); } else { // Not exact arguments, but still can use method bind call. - gen->write_call_method_bind(return_addr, base, method, arguments); + gen->write_call_method_bind(result, base, method, arguments); } } else { - gen->write_call(return_addr, base, call->function_name, arguments); + 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(return_addr, base, base.type.builtin_type, call->function_name, arguments); + gen->write_call_builtin_type(result, base, base.type.builtin_type, call->function_name, arguments); } else { - gen->write_call(return_addr, base, call->function_name, arguments); + gen->write_call(result, base, call->function_name, arguments); } if (base.mode == GDScriptCodeGenerator::Address::TEMPORARY) { gen->pop_temporary(); -- cgit v1.2.3