mirror of
https://github.com/godotengine/godot.git
synced 2026-04-19 18:31:25 +00:00
GDScript: Fix compiler generates incorrect bytecode for conversion return
This commit is contained in:
parent
734f5473c1
commit
d0eb19359e
14 changed files with 164 additions and 129 deletions
|
|
@ -1834,23 +1834,30 @@ void GDScriptByteCodeGenerator::write_newline(int p_line) {
|
|||
}
|
||||
}
|
||||
|
||||
void GDScriptByteCodeGenerator::write_return(const Address &p_return_value) {
|
||||
if (!function->return_type.has_type() || p_return_value.type.has_type()) {
|
||||
// Either the function is untyped or the return value is also typed.
|
||||
void GDScriptByteCodeGenerator::write_return(const Address &p_return_value, bool p_use_conversion) {
|
||||
if (!p_use_conversion) {
|
||||
append_opcode(GDScriptFunction::OPCODE_RETURN);
|
||||
append(p_return_value);
|
||||
return;
|
||||
}
|
||||
|
||||
// If this is a typed function, then we need to check for potential conversions.
|
||||
if (function->return_type.has_type()) {
|
||||
if (function->return_type.kind == GDScriptDataType::BUILTIN && function->return_type.builtin_type == Variant::ARRAY && function->return_type.has_container_element_type(0)) {
|
||||
// Typed array.
|
||||
switch (function->return_type.kind) {
|
||||
case GDScriptDataType::VARIANT: {
|
||||
ERR_PRINT("Compiler bug: Unresolved return.");
|
||||
|
||||
// Shouldn't get here, but fail-safe to a regular return.
|
||||
append_opcode(GDScriptFunction::OPCODE_RETURN);
|
||||
append(p_return_value);
|
||||
} break;
|
||||
case GDScriptDataType::BUILTIN: {
|
||||
if (function->return_type.builtin_type == Variant::ARRAY && function->return_type.has_container_element_type(0)) {
|
||||
const GDScriptDataType &element_type = function->return_type.get_container_element_type(0);
|
||||
append_opcode(GDScriptFunction::OPCODE_RETURN_TYPED_ARRAY);
|
||||
append(p_return_value);
|
||||
append(get_constant_pos(element_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS));
|
||||
append(element_type.builtin_type);
|
||||
append(element_type.native_type);
|
||||
} else if (function->return_type.kind == GDScriptDataType::BUILTIN && function->return_type.builtin_type == Variant::DICTIONARY &&
|
||||
function->return_type.has_container_element_types()) {
|
||||
// Typed dictionary.
|
||||
} else if (function->return_type.builtin_type == Variant::DICTIONARY && function->return_type.has_container_element_types()) {
|
||||
const GDScriptDataType &key_type = function->return_type.get_container_element_type_or_variant(0);
|
||||
const GDScriptDataType &value_type = function->return_type.get_container_element_type_or_variant(1);
|
||||
append_opcode(GDScriptFunction::OPCODE_RETURN_TYPED_DICTIONARY);
|
||||
|
|
@ -1861,72 +1868,29 @@ void GDScriptByteCodeGenerator::write_return(const Address &p_return_value) {
|
|||
append(key_type.native_type);
|
||||
append(value_type.builtin_type);
|
||||
append(value_type.native_type);
|
||||
} else if (function->return_type.kind == GDScriptDataType::BUILTIN && p_return_value.type.kind == GDScriptDataType::BUILTIN && function->return_type.builtin_type != p_return_value.type.builtin_type) {
|
||||
// Add conversion.
|
||||
} else {
|
||||
append_opcode(GDScriptFunction::OPCODE_RETURN_TYPED_BUILTIN);
|
||||
append(p_return_value);
|
||||
append(function->return_type.builtin_type);
|
||||
} else {
|
||||
// Just assign.
|
||||
append_opcode(GDScriptFunction::OPCODE_RETURN);
|
||||
append(p_return_value);
|
||||
}
|
||||
} else {
|
||||
append_opcode(GDScriptFunction::OPCODE_RETURN);
|
||||
} break;
|
||||
case GDScriptDataType::NATIVE: {
|
||||
append_opcode(GDScriptFunction::OPCODE_RETURN_TYPED_NATIVE);
|
||||
append(p_return_value);
|
||||
}
|
||||
} else {
|
||||
switch (function->return_type.kind) {
|
||||
case GDScriptDataType::BUILTIN: {
|
||||
if (function->return_type.builtin_type == Variant::ARRAY && function->return_type.has_container_element_type(0)) {
|
||||
const GDScriptDataType &element_type = function->return_type.get_container_element_type(0);
|
||||
append_opcode(GDScriptFunction::OPCODE_RETURN_TYPED_ARRAY);
|
||||
append(p_return_value);
|
||||
append(get_constant_pos(element_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS));
|
||||
append(element_type.builtin_type);
|
||||
append(element_type.native_type);
|
||||
} else if (function->return_type.builtin_type == Variant::DICTIONARY && function->return_type.has_container_element_types()) {
|
||||
const GDScriptDataType &key_type = function->return_type.get_container_element_type_or_variant(0);
|
||||
const GDScriptDataType &value_type = function->return_type.get_container_element_type_or_variant(1);
|
||||
append_opcode(GDScriptFunction::OPCODE_RETURN_TYPED_DICTIONARY);
|
||||
append(p_return_value);
|
||||
append(get_constant_pos(key_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS));
|
||||
append(get_constant_pos(value_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS));
|
||||
append(key_type.builtin_type);
|
||||
append(key_type.native_type);
|
||||
append(value_type.builtin_type);
|
||||
append(value_type.native_type);
|
||||
} else {
|
||||
append_opcode(GDScriptFunction::OPCODE_RETURN_TYPED_BUILTIN);
|
||||
append(p_return_value);
|
||||
append(function->return_type.builtin_type);
|
||||
}
|
||||
} break;
|
||||
case GDScriptDataType::NATIVE: {
|
||||
append_opcode(GDScriptFunction::OPCODE_RETURN_TYPED_NATIVE);
|
||||
append(p_return_value);
|
||||
int class_idx = GDScriptLanguage::get_singleton()->get_global_map()[function->return_type.native_type];
|
||||
Variant nc = GDScriptLanguage::get_singleton()->get_global_array()[class_idx];
|
||||
class_idx = get_constant_pos(nc) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
|
||||
append(class_idx);
|
||||
} break;
|
||||
case GDScriptDataType::GDSCRIPT:
|
||||
case GDScriptDataType::SCRIPT: {
|
||||
Variant script = function->return_type.script_type;
|
||||
int script_idx = get_constant_pos(script) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
|
||||
int class_idx = GDScriptLanguage::get_singleton()->get_global_map()[function->return_type.native_type];
|
||||
Variant nc = GDScriptLanguage::get_singleton()->get_global_array()[class_idx];
|
||||
class_idx = get_constant_pos(nc) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
|
||||
append(class_idx);
|
||||
} break;
|
||||
case GDScriptDataType::SCRIPT:
|
||||
case GDScriptDataType::GDSCRIPT: {
|
||||
Variant script = function->return_type.script_type;
|
||||
int script_idx = get_constant_pos(script) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS);
|
||||
|
||||
append_opcode(GDScriptFunction::OPCODE_RETURN_TYPED_SCRIPT);
|
||||
append(p_return_value);
|
||||
append(script_idx);
|
||||
} break;
|
||||
default: {
|
||||
ERR_PRINT("Compiler bug: unresolved return.");
|
||||
|
||||
// Shouldn't get here, but fail-safe to a regular return;
|
||||
append_opcode(GDScriptFunction::OPCODE_RETURN);
|
||||
append(p_return_value);
|
||||
} break;
|
||||
}
|
||||
append_opcode(GDScriptFunction::OPCODE_RETURN_TYPED_SCRIPT);
|
||||
append(p_return_value);
|
||||
append(script_idx);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue