aboutsummaryrefslogtreecommitdiff
path: root/src/check_expr.cpp
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2022-11-03 12:47:11 +0000
committergingerBill <bill@gingerbill.org>2022-11-03 12:47:11 +0000
commitf76316f88915527b4a51210fff712ddc1e17ddcc (patch)
tree695c2f9d500f3d7f9247dc84c8ea9c6fc772077f /src/check_expr.cpp
parent5cf473b31cc1a405e11ac37e135251760b0814d1 (diff)
parent32477a88ef00b39ec3104553af1c057d157665f6 (diff)
Merge branch 'master' into allocator-mode-alloc-non-zeroed
Diffstat (limited to 'src/check_expr.cpp')
-rw-r--r--src/check_expr.cpp80
1 files changed, 64 insertions, 16 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index 0686d9cb2..b3c04caa4 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -821,11 +821,12 @@ i64 check_distance_between_types(CheckerContext *c, Operand *operand, Type *type
if (are_types_identical(src, dst)) {
return 5;
}
-
- Type *dst_elem = base_array_type(dst);
- i64 distance = check_distance_between_types(c, operand, dst_elem);
- if (distance >= 0) {
- return distance + 7;
+ if (dst->Matrix.row_count == dst->Matrix.column_count) {
+ Type *dst_elem = base_array_type(dst);
+ i64 distance = check_distance_between_types(c, operand, dst_elem);
+ if (distance >= 0) {
+ return distance + 7;
+ }
}
}
@@ -2916,7 +2917,12 @@ bool check_transmute(CheckerContext *c, Ast *node, Operand *o, Type *t) {
// return false;
// }
- if (is_type_untyped(o->type)) {
+ Type *src_t = o->type;
+ Type *dst_t = t;
+ Type *src_bt = base_type(src_t);
+ Type *dst_bt = base_type(dst_t);
+
+ if (is_type_untyped(src_t)) {
gbString expr_str = expr_to_string(o->expr);
error(o->expr, "Cannot transmute untyped expression: '%s'", expr_str);
gb_string_free(expr_str);
@@ -2925,7 +2931,6 @@ bool check_transmute(CheckerContext *c, Ast *node, Operand *o, Type *t) {
return false;
}
- Type *dst_bt = base_type(t);
if (dst_bt == nullptr || dst_bt == t_invalid) {
GB_ASSERT(global_error_collector.count != 0);
@@ -2934,21 +2939,21 @@ bool check_transmute(CheckerContext *c, Ast *node, Operand *o, Type *t) {
return false;
}
- Type *src_bt = base_type(o->type);
if (src_bt == nullptr || src_bt == t_invalid) {
// NOTE(bill): this should be an error
GB_ASSERT(global_error_collector.count != 0);
o->mode = Addressing_Value;
o->expr = node;
- o->type = t;
+ o->type = dst_t;
return true;
}
- i64 srcz = type_size_of(o->type);
- i64 dstz = type_size_of(t);
+
+ i64 srcz = type_size_of(src_t);
+ i64 dstz = type_size_of(dst_t);
if (srcz != dstz) {
gbString expr_str = expr_to_string(o->expr);
- gbString type_str = type_to_string(t);
+ gbString type_str = type_to_string(dst_t);
error(o->expr, "Cannot transmute '%s' to '%s', %lld vs %lld bytes", expr_str, type_str, srcz, dstz);
gb_string_free(type_str);
gb_string_free(expr_str);
@@ -2958,16 +2963,53 @@ bool check_transmute(CheckerContext *c, Ast *node, Operand *o, Type *t) {
}
if (build_context.vet_extra) {
- if (are_types_identical(o->type, t)) {
- gbString str = type_to_string(t);
+ if (are_types_identical(o->type, dst_t)) {
+ gbString str = type_to_string(dst_t);
warning(o->expr, "Unneeded transmute to the same type '%s'", str);
gb_string_free(str);
}
}
o->expr = node;
+ o->type = dst_t;
+ if (o->mode == Addressing_Constant) {
+ if (are_types_identical(src_bt, dst_bt)) {
+ return true;
+ }
+ if (is_type_integer(src_t) && is_type_integer(dst_t)) {
+ if (types_have_same_internal_endian(src_t, dst_t)) {
+ ExactValue src_v = exact_value_to_integer(o->value);
+ GB_ASSERT(src_v.kind == ExactValue_Integer);
+ BigInt v = src_v.value_integer;
+
+ BigInt smax = {};
+ BigInt umax = {};
+
+ big_int_from_u64(&smax, 0);
+ big_int_not(&smax, &smax, cast(i32)(srcz*8 - 1), false);
+
+ big_int_from_u64(&umax, 1);
+ BigInt sz_in_bits = big_int_make_i64(srcz*8);
+ big_int_shl_eq(&umax, &sz_in_bits);
+
+ if (is_type_unsigned(src_t) && !is_type_unsigned(dst_t)) {
+ if (big_int_cmp(&v, &smax) >= 0) {
+ big_int_sub_eq(&v, &umax);
+ }
+ } else if (!is_type_unsigned(src_t) && is_type_unsigned(dst_t)) {
+ if (big_int_is_neg(&v)) {
+ big_int_add_eq(&v, &umax);
+ }
+ }
+
+ o->value.kind = ExactValue_Integer;
+ o->value.value_integer = v;
+ return true;
+ }
+ }
+ }
+
o->mode = Addressing_Value;
- o->type = t;
o->value = {};
return true;
}
@@ -6413,7 +6455,9 @@ CallArgumentError check_polymorphic_record_type(CheckerContext *c, Operand *oper
if (e->kind == Entity_TypeName) {
if (o->mode != Addressing_Type) {
if (show_error) {
- error(o->expr, "Expected a type for the argument '%.*s'", LIT(e->token.string));
+ gbString expr = expr_to_string(o->expr);
+ error(o->expr, "Expected a type for the argument '%.*s', got %s", LIT(e->token.string), expr);
+ gb_string_free(expr);
}
err = CallArgumentError_WrongTypes;
}
@@ -6456,6 +6500,10 @@ CallArgumentError check_polymorphic_record_type(CheckerContext *c, Operand *oper
// add_type_info_type(c, o->type);
}
+ if (show_error && err) {
+ return err;
+ }
+
{
bool failure = false;
Entity *found_entity = find_polymorphic_record_entity(c, original_type, param_count, ordered_operands, &failure);