Fixes to function pointer conversion.

This commit is contained in:
Christoffer Lerno
2022-10-02 00:22:21 +02:00
parent f05ffc84d8
commit 9f7ed00f04
10 changed files with 122 additions and 17 deletions

View File

@@ -2266,7 +2266,7 @@ Type *type_get_inferred_array(Type *arr_type);
Type *type_get_inferred_vector(Type *arr_type);
Type *type_get_flexible_array(Type *arr_type);
Type *type_get_scaled_vector(Type *arr_type);
Type *type_get_failable(Type *failable_type);
Type *type_get_optional(Type *failable_type);
Type *type_get_vector(Type *vector_type, unsigned len);
Type *type_get_vector_bool(Type *original_type);
Type *type_int_signed_by_bitsize(BitSize bitsize);
@@ -2376,7 +2376,7 @@ INLINE bool type_is_pointer_sized(Type *type)
INLINE Type *type_add_optional(Type *type, bool make_optional)
{
if (!make_optional || type->type_kind == TYPE_OPTIONAL || type->type_kind == TYPE_FAILABLE_ANY) return type;
return type_get_failable(type);
return type_get_optional(type);
}
INLINE bool type_len_is_inferred(Type *type)

View File

@@ -745,7 +745,7 @@ TypeInfo *parse_optional_type(ParseContext *c)
info->failable = true;
if (info->resolve_status == RESOLVE_DONE)
{
info->type = type_get_failable(info->type);
info->type = type_get_optional(info->type);
}
RANGE_EXTEND_PREV(info);
}

View File

@@ -1437,7 +1437,7 @@ bool cast(Expr *expr, Type *to_type)
if (type_is_optional_any(from_type))
{
expr->type = type_get_failable(to_type);
expr->type = type_get_optional(to_type);
return true;
}
@@ -1468,7 +1468,7 @@ bool cast(Expr *expr, Type *to_type)
Type *result_type = expr->type;
if (from_is_failable && !type_is_optional(result_type))
{
expr->type = type_get_failable(result_type);
expr->type = type_get_optional(result_type);
}
return true;
}

View File

@@ -1498,7 +1498,7 @@ static inline Type *context_unify_returns(SemaContext *context)
if (failable)
{
// If there are only implicit returns, then we assume void!, otherwise it's an "anyfail"
return no_return ? type_get_failable(type_void) : type_anyfail;
return no_return ? type_get_optional(type_void) : type_anyfail;
}
// No failable => void.
return type_void;

View File

@@ -163,7 +163,7 @@ static inline bool sema_expr_analyse_struct_plain_initializer(SemaContext *conte
failable = failable || IS_OPTIONAL(element);
}
assert(initializer->type);
if (failable) initializer->type = type_get_failable(initializer->type);
if (failable) initializer->type = type_get_optional(initializer->type);
// 6. There's the case of too few values as well. Mark the last field as wrong.
assert(elements_needed <= size);
@@ -251,7 +251,7 @@ static inline bool sema_expr_analyse_array_plain_initializer(SemaContext *contex
failable = failable || IS_OPTIONAL(element);
}
assert(initializer->type);
if (failable) initializer->type = type_get_failable(initializer->type);
if (failable) initializer->type = type_get_optional(initializer->type);
if (expected_members > size)
{

View File

@@ -400,7 +400,7 @@ APPEND_QUALIFIERS:
if (type_info->failable)
{
Type *type = type_info->type;
if (!type_is_optional(type)) type_info->type = type_get_failable(type);
if (!type_is_optional(type)) type_info->type = type_get_optional(type);
}
return true;
}

View File

@@ -4,6 +4,8 @@
#include "compiler_internal.h"
static Type *flatten_raw_function_type(Type *type);
static struct
{
Type u0, u1, i8, i16, i32, i64, i128, ixx;
@@ -839,7 +841,7 @@ Type *type_get_ptr_recurse(Type *ptr_type)
if (ptr_type->type_kind == TYPE_OPTIONAL)
{
ptr_type = ptr_type->failable;
return type_get_failable(type_get_ptr(ptr_type));
return type_get_optional(type_get_ptr(ptr_type));
}
return type_get_ptr(ptr_type);
@@ -850,7 +852,7 @@ Type *type_get_ptr(Type *ptr_type)
return type_generate_ptr(ptr_type, false);
}
Type *type_get_failable(Type *failable_type)
Type *type_get_optional(Type *failable_type)
{
assert(!type_is_optional(failable_type));
return type_generate_failable(failable_type, false);
@@ -1171,16 +1173,42 @@ void type_func_prototype_init(uint32_t capacity)
static uint32_t hash_function(Signature *sig)
{
uintptr_t hash = (unsigned)sig->variadic;
hash = hash * 31 + (uintptr_t)type_infoptr(sig->rtype)->type->canonical;
hash = hash * 31 + (uintptr_t)flatten_raw_function_type(type_infoptr(sig->rtype)->type);
Decl **params = sig->params;
VECEACH(params, i)
{
Decl *param = params[i];
hash = hash * 31 + (uintptr_t)param->type->canonical;
hash = hash * 31 + (uintptr_t)flatten_raw_function_type(param->type->canonical);
}
return (uint32_t)((hash >> 16) ^ hash);
}
static bool compare_func_param(Type *one, Type *other)
{
if (one == other) return true;
one = one->canonical;
other = other->canonical;
if (one == other) return true;
if (one->type_kind != other->type_kind) return false;
switch (one->type_kind)
{
case TYPE_POINTER:
return compare_func_param(one->pointer, other->pointer);
case TYPE_ARRAY:
if (one->array.len != other->array.len) return false;
FALLTHROUGH;
case TYPE_SUBARRAY:
case TYPE_FLEXIBLE_ARRAY:
return compare_func_param(one->array.base, other->array.base);
case TYPE_FUNC:
return one->function.prototype->raw_type == other->function.prototype->raw_type;
case TYPE_OPTIONAL:
return compare_func_param(one->failable, other->failable);
default:
return false;
}
}
static int compare_function(Signature *sig, FunctionPrototype *proto)
{
if (sig->variadic != proto->variadic) return -1;
@@ -1188,17 +1216,54 @@ static int compare_function(Signature *sig, FunctionPrototype *proto)
Type **other_params = proto->param_types;
unsigned param_count = vec_size(params);
if (param_count != vec_size(other_params)) return -1;
if (type_infoptr(sig->rtype)->type->canonical != proto->rtype->canonical) return -1;
if (!compare_func_param(type_infoptr(sig->rtype)->type, proto->rtype)) return -1;
VECEACH(params, i)
{
Decl *param = params[i];
Type *other_param = other_params[i];
if (param->type->canonical != other_param->canonical) return -1;
if (!compare_func_param(param->type, other_param->canonical)) return -1;
}
return 0;
}
static Type *flatten_raw_function_type(Type *type)
{
Type *other;
Type *current;
switch (type->type_kind)
{
case TYPE_TYPEDEF:
return flatten_raw_function_type(type->canonical);
case TYPE_FUNC:
return type->function.prototype->raw_type;
case TYPE_OPTIONAL:
current = type->failable;
other = flatten_raw_function_type(current);
return other == current ? type : type_get_optional(other);
case TYPE_POINTER:
current = type->pointer;
other = flatten_raw_function_type(current);
return other == current ? type : type_get_ptr(other);
case TYPE_ARRAY:
current = type->array.base;
other = flatten_raw_function_type(current);
return other == current ? type : type_get_array(other, type->array.len);
case TYPE_SUBARRAY:
current = type->array.base;
other = flatten_raw_function_type(current);
return other == current ? type : type_get_subarray(other);
case TYPE_FLEXIBLE_ARRAY:
current = type->array.base;
other = flatten_raw_function_type(current);
return other == current ? type : type_get_flexible_array(other);
case TYPE_INFERRED_ARRAY:
current = type->array.base;
other = flatten_raw_function_type(current);
return other == current ? type : type_get_inferred_array(other);
default:
return type;
}
}
static inline Type *func_create_new_func_proto(Signature *sig, CallABI abi, uint32_t hash, FuncTypeEntry *entry)
{
unsigned param_count = vec_size(sig->params);

View File

@@ -1 +1 @@
#define COMPILER_VERSION "0.3.64"
#define COMPILER_VERSION "0.3.65"

View File

@@ -0,0 +1,20 @@
module test;
define Callback = fn void();
define Callback2 = fn void();
define GetCallback = fn Callback2**[][123]*();
fn Callback**[][123]* tester()
{
return null;
}
GetCallback x = &tester;
define GetCallbackOpt = fn Callback2!();
fn Callback2! tester2() = null;
GetCallbackOpt y = &tester2;

View File

@@ -0,0 +1,20 @@
module test;
define Callback = fn void();
define Callback2 = fn void();
define GetCallback = fn Callback2**[][123]*();
fn Callback**[][123]* tester()
{
return null;
}
GetCallback x = &tester;
define GetCallbackOpt = fn Callback2!();
fn Callback2! tester2() = null;
GetCallbackOpt y = &tester2;