mirror of
https://github.com/godotengine/godot.git
synced 2025-10-23 09:53:25 +00:00
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.
This commit is contained in:
parent
b14f7aa9f9
commit
a3816434a6
5 changed files with 104 additions and 43 deletions
|
@ -520,10 +520,12 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
|
|||
case GDScriptParser::Node::CALL: {
|
||||
const GDScriptParser::CallNode *call = static_cast<const GDScriptParser::CallNode *>(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<GDScriptCodeGenerator::Address> 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<GDScriptParser::IdentifierNode *>(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<GDScriptParser::IdentifierNode *>(subscript->base)->name) < Variant::VARIANT_MAX) {
|
||||
gen->write_call_builtin_type_static(return_addr, GDScriptParser::get_builtin_type(static_cast<GDScriptParser::IdentifierNode *>(subscript->base)->name), subscript->attribute->name, arguments);
|
||||
gen->write_call_builtin_type_static(result, GDScriptParser::get_builtin_type(static_cast<GDScriptParser::IdentifierNode *>(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<GDScriptParser::IdentifierNode *>(subscript->base)->name) && !Engine::get_singleton()->has_singleton(static_cast<GDScriptParser::IdentifierNode *>(subscript->base)->name)) {
|
||||
// It's a static native method call.
|
||||
gen->write_call_native_static(return_addr, static_cast<GDScriptParser::IdentifierNode *>(subscript->base)->name, subscript->attribute->name, arguments);
|
||||
gen->write_call_native_static(result, static_cast<GDScriptParser::IdentifierNode *>(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();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue