瀏覽代碼

GDScript: Adjust type of temporaries when needed

George Marques 4 年之前
父節點
當前提交
9411bf05a4

+ 127 - 1
modules/gdscript/gdscript_byte_codegen.cpp

@@ -126,8 +126,15 @@ uint32_t GDScriptByteCodeGenerator::add_temporary(const GDScriptDataType &p_type
 	List<int> &pool = temporaries_pool[temp_type];
 	if (pool.is_empty()) {
 		StackSlot new_temp(temp_type);
-		pool.push_back(temporaries.size());
+		int idx = temporaries.size();
+		pool.push_back(idx);
 		temporaries.push_back(new_temp);
+
+		// First time using this, so adjust to the proper type.
+		if (temp_type != Variant::NIL) {
+			Address addr(Address::TEMPORARY, idx, p_type);
+			write_type_adjust(addr, temp_type);
+		}
 	}
 	int slot = pool.front()->get();
 	pool.pop_front();
@@ -403,6 +410,117 @@ 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_type_adjust(const Address &p_target, Variant::Type p_new_type) {
+	switch (p_new_type) {
+		case Variant::BOOL:
+			append(GDScriptFunction::OPCODE_TYPE_ADJUST_BOOL, 1);
+			break;
+		case Variant::INT:
+			append(GDScriptFunction::OPCODE_TYPE_ADJUST_INT, 1);
+			break;
+		case Variant::FLOAT:
+			append(GDScriptFunction::OPCODE_TYPE_ADJUST_FLOAT, 1);
+			break;
+		case Variant::STRING:
+			append(GDScriptFunction::OPCODE_TYPE_ADJUST_STRING, 1);
+			break;
+		case Variant::VECTOR2:
+			append(GDScriptFunction::OPCODE_TYPE_ADJUST_VECTOR2, 1);
+			break;
+		case Variant::VECTOR2I:
+			append(GDScriptFunction::OPCODE_TYPE_ADJUST_VECTOR2I, 1);
+			break;
+		case Variant::RECT2:
+			append(GDScriptFunction::OPCODE_TYPE_ADJUST_RECT2, 1);
+			break;
+		case Variant::RECT2I:
+			append(GDScriptFunction::OPCODE_TYPE_ADJUST_RECT2I, 1);
+			break;
+		case Variant::VECTOR3:
+			append(GDScriptFunction::OPCODE_TYPE_ADJUST_VECTOR3, 1);
+			break;
+		case Variant::VECTOR3I:
+			append(GDScriptFunction::OPCODE_TYPE_ADJUST_VECTOR3I, 1);
+			break;
+		case Variant::TRANSFORM2D:
+			append(GDScriptFunction::OPCODE_TYPE_ADJUST_TRANSFORM2D, 1);
+			break;
+		case Variant::PLANE:
+			append(GDScriptFunction::OPCODE_TYPE_ADJUST_PLANE, 1);
+			break;
+		case Variant::QUAT:
+			append(GDScriptFunction::OPCODE_TYPE_ADJUST_QUAT, 1);
+			break;
+		case Variant::AABB:
+			append(GDScriptFunction::OPCODE_TYPE_ADJUST_AABB, 1);
+			break;
+		case Variant::BASIS:
+			append(GDScriptFunction::OPCODE_TYPE_ADJUST_BASIS, 1);
+			break;
+		case Variant::TRANSFORM:
+			append(GDScriptFunction::OPCODE_TYPE_ADJUST_TRANSFORM, 1);
+			break;
+		case Variant::COLOR:
+			append(GDScriptFunction::OPCODE_TYPE_ADJUST_COLOR, 1);
+			break;
+		case Variant::STRING_NAME:
+			append(GDScriptFunction::OPCODE_TYPE_ADJUST_STRING_NAME, 1);
+			break;
+		case Variant::NODE_PATH:
+			append(GDScriptFunction::OPCODE_TYPE_ADJUST_NODE_PATH, 1);
+			break;
+		case Variant::RID:
+			append(GDScriptFunction::OPCODE_TYPE_ADJUST_RID, 1);
+			break;
+		case Variant::OBJECT:
+			append(GDScriptFunction::OPCODE_TYPE_ADJUST_OBJECT, 1);
+			break;
+		case Variant::CALLABLE:
+			append(GDScriptFunction::OPCODE_TYPE_ADJUST_CALLABLE, 1);
+			break;
+		case Variant::SIGNAL:
+			append(GDScriptFunction::OPCODE_TYPE_ADJUST_SIGNAL, 1);
+			break;
+		case Variant::DICTIONARY:
+			append(GDScriptFunction::OPCODE_TYPE_ADJUST_DICTIONARY, 1);
+			break;
+		case Variant::ARRAY:
+			append(GDScriptFunction::OPCODE_TYPE_ADJUST_ARRAY, 1);
+			break;
+		case Variant::PACKED_BYTE_ARRAY:
+			append(GDScriptFunction::OPCODE_TYPE_ADJUST_PACKED_BYTE_ARRAY, 1);
+			break;
+		case Variant::PACKED_INT32_ARRAY:
+			append(GDScriptFunction::OPCODE_TYPE_ADJUST_PACKED_INT32_ARRAY, 1);
+			break;
+		case Variant::PACKED_INT64_ARRAY:
+			append(GDScriptFunction::OPCODE_TYPE_ADJUST_PACKED_INT64_ARRAY, 1);
+			break;
+		case Variant::PACKED_FLOAT32_ARRAY:
+			append(GDScriptFunction::OPCODE_TYPE_ADJUST_PACKED_FLOAT32_ARRAY, 1);
+			break;
+		case Variant::PACKED_FLOAT64_ARRAY:
+			append(GDScriptFunction::OPCODE_TYPE_ADJUST_PACKED_FLOAT64_ARRAY, 1);
+			break;
+		case Variant::PACKED_STRING_ARRAY:
+			append(GDScriptFunction::OPCODE_TYPE_ADJUST_PACKED_STRING_ARRAY, 1);
+			break;
+		case Variant::PACKED_VECTOR2_ARRAY:
+			append(GDScriptFunction::OPCODE_TYPE_ADJUST_PACKED_VECTOR2_ARRAY, 1);
+			break;
+		case Variant::PACKED_VECTOR3_ARRAY:
+			append(GDScriptFunction::OPCODE_TYPE_ADJUST_PACKED_VECTOR3_ARRAY, 1);
+			break;
+		case Variant::PACKED_COLOR_ARRAY:
+			append(GDScriptFunction::OPCODE_TYPE_ADJUST_PACKED_COLOR_ARRAY, 1);
+			break;
+		case Variant::NIL:
+		case Variant::VARIANT_MAX:
+			return;
+	}
+	append(p_target);
+}
+
 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.
@@ -868,6 +986,14 @@ void GDScriptByteCodeGenerator::write_call_builtin_type(const Address &p_target,
 		return;
 	}
 
+	if (p_target.mode == Address::TEMPORARY) {
+		Variant::Type result_type = Variant::get_builtin_method_return_type(p_type, p_method);
+		Variant::Type temp_type = temporaries[p_target.address].type;
+		if (result_type != temp_type) {
+			write_type_adjust(p_target, result_type);
+		}
+	}
+
 	append(GDScriptFunction::OPCODE_CALL_BUILTIN_TYPE_VALIDATED, 2 + p_arguments.size());
 
 	for (int i = 0; i < p_arguments.size(); i++) {

+ 1 - 0
modules/gdscript/gdscript_byte_codegen.h

@@ -413,6 +413,7 @@ public:
 #endif
 	virtual void set_initial_line(int p_line) override;
 
+	virtual void write_type_adjust(const Address &p_target, Variant::Type p_new_type) override;
 	virtual void write_unary_operator(const Address &p_target, Variant::Operator p_operator, const Address &p_left_operand) override;
 	virtual void write_binary_operator(const Address &p_target, Variant::Operator p_operator, const Address &p_left_operand, const Address &p_right_operand) override;
 	virtual void write_type_test(const Address &p_target, const Address &p_source, const Address &p_type) override;

+ 1 - 7
modules/gdscript/gdscript_codegen.h

@@ -80,9 +80,6 @@ public:
 	virtual void start_block() = 0;
 	virtual void end_block() = 0;
 
-	// virtual int get_max_stack_level() = 0;
-	// virtual int get_max_function_arguments() = 0;
-
 	virtual void write_start(GDScript *p_script, const StringName &p_function_name, bool p_static, MultiplayerAPI::RPCMode p_rpc_mode, const GDScriptDataType &p_return_type) = 0;
 	virtual GDScriptFunction *write_end() = 0;
 
@@ -91,9 +88,7 @@ public:
 #endif
 	virtual void set_initial_line(int p_line) = 0;
 
-	// virtual void alloc_stack(int p_level) = 0; // Is this needed?
-	// virtual void alloc_call(int p_arg_count) = 0; // This might be automatic from other functions.
-
+	virtual void write_type_adjust(const Address &p_target, Variant::Type p_new_type) = 0;
 	virtual void write_unary_operator(const Address &p_target, Variant::Operator p_operator, const Address &p_left_operand) = 0;
 	virtual void write_binary_operator(const Address &p_target, Variant::Operator p_operator, const Address &p_left_operand, const Address &p_right_operand) = 0;
 	virtual void write_type_test(const Address &p_target, const Address &p_source, const Address &p_type) = 0;
@@ -138,7 +133,6 @@ public:
 	virtual void write_construct_dictionary(const Address &p_target, const Vector<Address> &p_arguments) = 0;
 	virtual void write_await(const Address &p_target, const Address &p_operand) = 0;
 	virtual void write_if(const Address &p_condition) = 0;
-	// virtual void write_elseif(const Address &p_condition) = 0; This kind of makes things more difficult for no real benefit.
 	virtual void write_else() = 0;
 	virtual void write_endif() = 0;
 	virtual void start_for(const GDScriptDataType &p_iterator_type, const GDScriptDataType &p_list_type) = 0;

+ 45 - 0
modules/gdscript/gdscript_disassembler.cpp

@@ -894,6 +894,51 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
 
 				incr += 2;
 			} break;
+
+#define DISASSEMBLE_TYPE_ADJUST(m_v_type) \
+	case OPCODE_TYPE_ADJUST_##m_v_type: { \
+		text += "type adjust (";          \
+		text += #m_v_type;                \
+		text += ") ";                     \
+		text += DADDR(1);                 \
+		incr += 2;                        \
+	} break
+
+				DISASSEMBLE_TYPE_ADJUST(BOOL);
+				DISASSEMBLE_TYPE_ADJUST(INT);
+				DISASSEMBLE_TYPE_ADJUST(FLOAT);
+				DISASSEMBLE_TYPE_ADJUST(STRING);
+				DISASSEMBLE_TYPE_ADJUST(VECTOR2);
+				DISASSEMBLE_TYPE_ADJUST(VECTOR2I);
+				DISASSEMBLE_TYPE_ADJUST(RECT2);
+				DISASSEMBLE_TYPE_ADJUST(RECT2I);
+				DISASSEMBLE_TYPE_ADJUST(VECTOR3);
+				DISASSEMBLE_TYPE_ADJUST(VECTOR3I);
+				DISASSEMBLE_TYPE_ADJUST(TRANSFORM2D);
+				DISASSEMBLE_TYPE_ADJUST(PLANE);
+				DISASSEMBLE_TYPE_ADJUST(QUAT);
+				DISASSEMBLE_TYPE_ADJUST(AABB);
+				DISASSEMBLE_TYPE_ADJUST(BASIS);
+				DISASSEMBLE_TYPE_ADJUST(TRANSFORM);
+				DISASSEMBLE_TYPE_ADJUST(COLOR);
+				DISASSEMBLE_TYPE_ADJUST(STRING_NAME);
+				DISASSEMBLE_TYPE_ADJUST(NODE_PATH);
+				DISASSEMBLE_TYPE_ADJUST(RID);
+				DISASSEMBLE_TYPE_ADJUST(OBJECT);
+				DISASSEMBLE_TYPE_ADJUST(CALLABLE);
+				DISASSEMBLE_TYPE_ADJUST(SIGNAL);
+				DISASSEMBLE_TYPE_ADJUST(DICTIONARY);
+				DISASSEMBLE_TYPE_ADJUST(ARRAY);
+				DISASSEMBLE_TYPE_ADJUST(PACKED_BYTE_ARRAY);
+				DISASSEMBLE_TYPE_ADJUST(PACKED_INT32_ARRAY);
+				DISASSEMBLE_TYPE_ADJUST(PACKED_INT64_ARRAY);
+				DISASSEMBLE_TYPE_ADJUST(PACKED_FLOAT32_ARRAY);
+				DISASSEMBLE_TYPE_ADJUST(PACKED_FLOAT64_ARRAY);
+				DISASSEMBLE_TYPE_ADJUST(PACKED_STRING_ARRAY);
+				DISASSEMBLE_TYPE_ADJUST(PACKED_VECTOR2_ARRAY);
+				DISASSEMBLE_TYPE_ADJUST(PACKED_VECTOR3_ARRAY);
+				DISASSEMBLE_TYPE_ADJUST(PACKED_COLOR_ARRAY);
+
 			case OPCODE_ASSERT: {
 				text += "assert (";
 				text += DADDR(1);

+ 34 - 0
modules/gdscript/gdscript_function.h

@@ -351,6 +351,40 @@ public:
 		OPCODE_ITERATE_PACKED_COLOR_ARRAY,
 		OPCODE_ITERATE_OBJECT,
 		OPCODE_STORE_NAMED_GLOBAL,
+		OPCODE_TYPE_ADJUST_BOOL,
+		OPCODE_TYPE_ADJUST_INT,
+		OPCODE_TYPE_ADJUST_FLOAT,
+		OPCODE_TYPE_ADJUST_STRING,
+		OPCODE_TYPE_ADJUST_VECTOR2,
+		OPCODE_TYPE_ADJUST_VECTOR2I,
+		OPCODE_TYPE_ADJUST_RECT2,
+		OPCODE_TYPE_ADJUST_RECT2I,
+		OPCODE_TYPE_ADJUST_VECTOR3,
+		OPCODE_TYPE_ADJUST_VECTOR3I,
+		OPCODE_TYPE_ADJUST_TRANSFORM2D,
+		OPCODE_TYPE_ADJUST_PLANE,
+		OPCODE_TYPE_ADJUST_QUAT,
+		OPCODE_TYPE_ADJUST_AABB,
+		OPCODE_TYPE_ADJUST_BASIS,
+		OPCODE_TYPE_ADJUST_TRANSFORM,
+		OPCODE_TYPE_ADJUST_COLOR,
+		OPCODE_TYPE_ADJUST_STRING_NAME,
+		OPCODE_TYPE_ADJUST_NODE_PATH,
+		OPCODE_TYPE_ADJUST_RID,
+		OPCODE_TYPE_ADJUST_OBJECT,
+		OPCODE_TYPE_ADJUST_CALLABLE,
+		OPCODE_TYPE_ADJUST_SIGNAL,
+		OPCODE_TYPE_ADJUST_DICTIONARY,
+		OPCODE_TYPE_ADJUST_ARRAY,
+		OPCODE_TYPE_ADJUST_PACKED_BYTE_ARRAY,
+		OPCODE_TYPE_ADJUST_PACKED_INT32_ARRAY,
+		OPCODE_TYPE_ADJUST_PACKED_INT64_ARRAY,
+		OPCODE_TYPE_ADJUST_PACKED_FLOAT32_ARRAY,
+		OPCODE_TYPE_ADJUST_PACKED_FLOAT64_ARRAY,
+		OPCODE_TYPE_ADJUST_PACKED_STRING_ARRAY,
+		OPCODE_TYPE_ADJUST_PACKED_VECTOR2_ARRAY,
+		OPCODE_TYPE_ADJUST_PACKED_VECTOR3_ARRAY,
+		OPCODE_TYPE_ADJUST_PACKED_COLOR_ARRAY,
 		OPCODE_ASSERT,
 		OPCODE_BREAKPOINT,
 		OPCODE_LINE,

+ 78 - 0
modules/gdscript/gdscript_vm.cpp

@@ -282,6 +282,40 @@ String GDScriptFunction::_get_call_error(const Callable::CallError &p_err, const
 		&&OPCODE_ITERATE_PACKED_COLOR_ARRAY,         \
 		&&OPCODE_ITERATE_OBJECT,                     \
 		&&OPCODE_STORE_NAMED_GLOBAL,                 \
+		&&OPCODE_TYPE_ADJUST_BOOL,                   \
+		&&OPCODE_TYPE_ADJUST_INT,                    \
+		&&OPCODE_TYPE_ADJUST_FLOAT,                  \
+		&&OPCODE_TYPE_ADJUST_STRING,                 \
+		&&OPCODE_TYPE_ADJUST_VECTOR2,                \
+		&&OPCODE_TYPE_ADJUST_VECTOR2I,               \
+		&&OPCODE_TYPE_ADJUST_RECT2,                  \
+		&&OPCODE_TYPE_ADJUST_RECT2I,                 \
+		&&OPCODE_TYPE_ADJUST_VECTOR3,                \
+		&&OPCODE_TYPE_ADJUST_VECTOR3I,               \
+		&&OPCODE_TYPE_ADJUST_TRANSFORM2D,            \
+		&&OPCODE_TYPE_ADJUST_PLANE,                  \
+		&&OPCODE_TYPE_ADJUST_QUAT,                   \
+		&&OPCODE_TYPE_ADJUST_AABB,                   \
+		&&OPCODE_TYPE_ADJUST_BASIS,                  \
+		&&OPCODE_TYPE_ADJUST_TRANSFORM,              \
+		&&OPCODE_TYPE_ADJUST_COLOR,                  \
+		&&OPCODE_TYPE_ADJUST_STRING_NAME,            \
+		&&OPCODE_TYPE_ADJUST_NODE_PATH,              \
+		&&OPCODE_TYPE_ADJUST_RID,                    \
+		&&OPCODE_TYPE_ADJUST_OBJECT,                 \
+		&&OPCODE_TYPE_ADJUST_CALLABLE,               \
+		&&OPCODE_TYPE_ADJUST_SIGNAL,                 \
+		&&OPCODE_TYPE_ADJUST_DICTIONARY,             \
+		&&OPCODE_TYPE_ADJUST_ARRAY,                  \
+		&&OPCODE_TYPE_ADJUST_PACKED_BYTE_ARRAY,      \
+		&&OPCODE_TYPE_ADJUST_PACKED_INT32_ARRAY,     \
+		&&OPCODE_TYPE_ADJUST_PACKED_INT64_ARRAY,     \
+		&&OPCODE_TYPE_ADJUST_PACKED_FLOAT32_ARRAY,   \
+		&&OPCODE_TYPE_ADJUST_PACKED_FLOAT64_ARRAY,   \
+		&&OPCODE_TYPE_ADJUST_PACKED_STRING_ARRAY,    \
+		&&OPCODE_TYPE_ADJUST_PACKED_VECTOR2_ARRAY,   \
+		&&OPCODE_TYPE_ADJUST_PACKED_VECTOR3_ARRAY,   \
+		&&OPCODE_TYPE_ADJUST_PACKED_COLOR_ARRAY,     \
 		&&OPCODE_ASSERT,                             \
 		&&OPCODE_BREAKPOINT,                         \
 		&&OPCODE_LINE,                               \
@@ -2973,6 +3007,50 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 			}
 			DISPATCH_OPCODE;
 
+#define OPCODE_TYPE_ADJUST(m_v_type, m_c_type)    \
+	OPCODE(OPCODE_TYPE_ADJUST_##m_v_type) {       \
+		CHECK_SPACE(2);                           \
+		GET_INSTRUCTION_ARG(arg, 0);              \
+		VariantTypeAdjust<m_c_type>::adjust(arg); \
+		ip += 2;                                  \
+	}                                             \
+	DISPATCH_OPCODE
+
+			OPCODE_TYPE_ADJUST(BOOL, bool);
+			OPCODE_TYPE_ADJUST(INT, int64_t);
+			OPCODE_TYPE_ADJUST(FLOAT, double);
+			OPCODE_TYPE_ADJUST(STRING, String);
+			OPCODE_TYPE_ADJUST(VECTOR2, Vector2);
+			OPCODE_TYPE_ADJUST(VECTOR2I, Vector2i);
+			OPCODE_TYPE_ADJUST(RECT2, Rect2);
+			OPCODE_TYPE_ADJUST(RECT2I, Rect2i);
+			OPCODE_TYPE_ADJUST(VECTOR3, Vector3);
+			OPCODE_TYPE_ADJUST(VECTOR3I, Vector3i);
+			OPCODE_TYPE_ADJUST(TRANSFORM2D, Transform2D);
+			OPCODE_TYPE_ADJUST(PLANE, Plane);
+			OPCODE_TYPE_ADJUST(QUAT, Quat);
+			OPCODE_TYPE_ADJUST(AABB, AABB);
+			OPCODE_TYPE_ADJUST(BASIS, Basis);
+			OPCODE_TYPE_ADJUST(TRANSFORM, Transform);
+			OPCODE_TYPE_ADJUST(COLOR, Color);
+			OPCODE_TYPE_ADJUST(STRING_NAME, StringName);
+			OPCODE_TYPE_ADJUST(NODE_PATH, NodePath);
+			OPCODE_TYPE_ADJUST(RID, RID);
+			OPCODE_TYPE_ADJUST(OBJECT, Object *);
+			OPCODE_TYPE_ADJUST(CALLABLE, Callable);
+			OPCODE_TYPE_ADJUST(SIGNAL, Signal);
+			OPCODE_TYPE_ADJUST(DICTIONARY, Dictionary);
+			OPCODE_TYPE_ADJUST(ARRAY, Array);
+			OPCODE_TYPE_ADJUST(PACKED_BYTE_ARRAY, PackedByteArray);
+			OPCODE_TYPE_ADJUST(PACKED_INT32_ARRAY, PackedInt32Array);
+			OPCODE_TYPE_ADJUST(PACKED_INT64_ARRAY, PackedInt64Array);
+			OPCODE_TYPE_ADJUST(PACKED_FLOAT32_ARRAY, PackedFloat32Array);
+			OPCODE_TYPE_ADJUST(PACKED_FLOAT64_ARRAY, PackedFloat64Array);
+			OPCODE_TYPE_ADJUST(PACKED_STRING_ARRAY, PackedStringArray);
+			OPCODE_TYPE_ADJUST(PACKED_VECTOR2_ARRAY, PackedVector2Array);
+			OPCODE_TYPE_ADJUST(PACKED_VECTOR3_ARRAY, PackedVector3Array);
+			OPCODE_TYPE_ADJUST(PACKED_COLOR_ARRAY, PackedColorArray);
+
 			OPCODE(OPCODE_ASSERT) {
 				CHECK_SPACE(3);