Browse Source

Fix polymorphic procedure return by pointer values #374

gingerBill 6 years ago
parent
commit
f5fdd031f9
2 changed files with 39 additions and 18 deletions
  1. 12 2
      src/check_expr.cpp
  2. 27 16
      src/check_type.cpp

+ 12 - 2
src/check_expr.cpp

@@ -86,6 +86,11 @@ CallArgumentData check_call_arguments   (CheckerContext *c, Operand *operand, Ty
 Type *           check_init_variable    (CheckerContext *c, Entity *e, Operand *operand, String context_name);
 
 
+Type *type_to_abi_compat_param_type(gbAllocator a, Type *original_type);
+Type *type_to_abi_compat_result_type(gbAllocator a, Type *original_type);
+bool abi_compat_return_by_pointer(gbAllocator a, ProcCallingConvention cc, Type *abi_return_type);
+void set_procedure_abi_types(CheckerContext *c, Type *type);
+
 
 Entity *entity_from_expr(Ast *expr) {
 	expr = unparen_expr(expr);
@@ -807,7 +812,7 @@ bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, Type *source,
 			}
 		}
 		if (modify_type) {
-			Type *ds = default_type(source);
+			Type *ds = default_type(source); // IMPORTANT TODO(bill): IS THIS CORRECT?
 			gb_memmove(poly, ds, gb_size_of(Type));
 		}
 		return true;
@@ -935,6 +940,7 @@ bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, Type *source,
 			if (x->result_count != y->result_count) {
 				return false;
 			}
+
 			for (isize i = 0; i < x->param_count; i++) {
 				Entity *a = x->params->Tuple.variables[i];
 				Entity *b = y->params->Tuple.variables[i];
@@ -947,7 +953,11 @@ bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, Type *source,
 				bool ok = is_polymorphic_type_assignable(c, a->type, b->type, false, modify_type);
 				if (!ok) return false;
 			}
-			// TODO(bill): Polymorphic type assignment
+
+			if (modify_type) {
+				set_procedure_abi_types(c, source);
+			}
+
 			return true;
 			#endif
 		}

+ 27 - 16
src/check_type.cpp

@@ -1237,6 +1237,9 @@ Type *determine_type_from_polymorphic(CheckerContext *ctx, Type *poly_type, Oper
 	}
 
 	if (is_polymorphic_type_assignable(ctx, poly_type, operand.type, false, modify_type)) {
+		if (modify_type) {
+			set_procedure_abi_types(ctx, poly_type);
+		}
 		return poly_type;
 	}
 	if (modify_type) {
@@ -1980,8 +1983,8 @@ Type *type_to_abi_compat_result_type(gbAllocator a, Type *original_type) {
 		new_type = tuple;
 	}
 
-
-	// return reduce_tuple_to_single_type(new_type);
+	new_type->cached_size = -1;
+	new_type->cached_align = -1;
 	return new_type;
 }
 
@@ -2013,6 +2016,27 @@ bool abi_compat_return_by_pointer(gbAllocator a, ProcCallingConvention cc, Type
 	return false;
 }
 
+void set_procedure_abi_types(CheckerContext *c, Type *type) {
+	type = base_type(type);
+	if (type->kind != Type_Proc) {
+		return;
+	}
+
+	type->Proc.abi_compat_params = array_make<Type *>(c->allocator, cast(isize)type->Proc.param_count);
+	for (i32 i = 0; i < type->Proc.param_count; i++) {
+		Entity *e = type->Proc.params->Tuple.variables[i];
+		if (e->kind == Entity_Variable) {
+			Type *original_type = e->type;
+			Type *new_type = type_to_abi_compat_param_type(c->allocator, original_type);
+			type->Proc.abi_compat_params[i] = new_type;
+		}
+	}
+
+	// NOTE(bill): The types are the same
+	type->Proc.abi_compat_result_type = type_to_abi_compat_result_type(c->allocator, type->Proc.results);
+	type->Proc.return_by_pointer = abi_compat_return_by_pointer(c->allocator, type->Proc.calling_convention, type->Proc.abi_compat_result_type);
+}
+
 // NOTE(bill): 'operands' is for generating non generic procedure type
 bool check_procedure_type(CheckerContext *ctx, Type *type, Ast *proc_type_node, Array<Operand> *operands) {
 	ast_node(pt, ProcType, proc_type_node);
@@ -2108,20 +2132,7 @@ bool check_procedure_type(CheckerContext *ctx, Type *type, Ast *proc_type_node,
 	}
 	type->Proc.is_polymorphic = is_polymorphic;
 
-
-	type->Proc.abi_compat_params = array_make<Type *>(c->allocator, param_count);
-	for (isize i = 0; i < param_count; i++) {
-		Entity *e = type->Proc.params->Tuple.variables[i];
-		if (e->kind == Entity_Variable) {
-			Type *original_type = e->type;
-			Type *new_type = type_to_abi_compat_param_type(c->allocator, original_type);
-			type->Proc.abi_compat_params[i] = new_type;
-		}
-	}
-
-	// NOTE(bill): The types are the same
-	type->Proc.abi_compat_result_type = type_to_abi_compat_result_type(c->allocator, type->Proc.results);
-	type->Proc.return_by_pointer = abi_compat_return_by_pointer(c->allocator, pt->calling_convention, type->Proc.abi_compat_result_type);
+	set_procedure_abi_types(c, type);
 
 	return success;
 }