Skip to content

Commit

Permalink
Remove vestiges of top down widening.
Browse files Browse the repository at this point in the history
  • Loading branch information
lerno committed Sep 19, 2023
1 parent e91cb85 commit efece23
Show file tree
Hide file tree
Showing 16 changed files with 282 additions and 357 deletions.
2 changes: 1 addition & 1 deletion lib/std/io/formatter_private.c3
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ fn usz! Formatter.floatformat(&self, FloatFormatting formatting, double y) @priv
is_neg = true;
y = -y;
}
int pl = is_neg || self.flags.plus ? 1 : 0;
isz pl = is_neg || self.flags.plus ? 1 : 0;
// Print inf/nan
if (!math::is_finite(y))
{
Expand Down
2 changes: 1 addition & 1 deletion resources/examples/mandelbrot.c3
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ fn int main(int argc, char **argv)
byte_acc = 0;
bit_num = 0;
}
else if (x == w - 1)
else if (x == (double)w - 1)
{
byte_acc <<= (8 - w % 8);
putchar(byte_acc);
Expand Down
2 changes: 1 addition & 1 deletion resources/examples/spectralnorm.c3
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ double[] temparr;

fn double eval_A(int i, int j)
{
return 1.0 / ((i + j) * (i + j + 1) / 2 + i + 1);
return 1.0 / (double)((i + j) * (i + j + 1) / 2 + i + 1);
}

fn void eval_A_times_u(double[] u, double[] au, double[] x)
Expand Down
8 changes: 3 additions & 5 deletions src/compiler/compiler_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -755,14 +755,12 @@ typedef struct
ExprId left;
ExprId right;
BinaryOp operator : 8;
bool widen : 1;
} ExprBinary;

typedef struct
{
Expr* expr;
UnaryOp operator : 8;
bool widen : 1;
} ExprUnary;


Expand Down Expand Up @@ -2186,7 +2184,7 @@ Expr *expr_new(ExprKind kind, SourceSpan start);
Expr *expr_new_const_int(SourceSpan span, Type *type, uint64_t v);
Expr *expr_new_const_bool(SourceSpan span, Type *type, bool value);
Expr *expr_new_const_typeid(SourceSpan span, Type *type);
bool expr_is_simple(Expr *expr);
bool expr_is_simple(Expr *expr, bool to_float);
bool expr_is_pure(Expr *expr);
bool expr_is_constant_eval(Expr *expr, ConstantEvalKind eval_kind);
bool expr_is_compile_time(Expr *ast);
Expand All @@ -2203,7 +2201,7 @@ bool expr_may_splat_as_vararg(Expr *expr, Type *variadic_base_type);
INLINE Expr *expr_new_expr(ExprKind kind, Expr *expr);
INLINE bool expr_ok(Expr *expr);
INLINE void expr_resolve_ident(Expr *expr, Decl *decl);
INLINE bool exprid_is_simple(ExprId expr_id);
INLINE bool exprid_is_simple(ExprId expr_id, bool to_float);
INLINE bool exprid_is_pure(ExprId expr_id);
INLINE Type *exprtype(ExprId expr_id);
INLINE void expr_replace(Expr *expr, Expr *replacement);
Expand Down Expand Up @@ -3152,7 +3150,7 @@ INLINE void expr_replace(Expr *expr, Expr *replacement)

INLINE bool expr_ok(Expr *expr) { return expr == NULL || expr->expr_kind != EXPR_POISONED; }

INLINE bool exprid_is_simple(ExprId expr_id) { return expr_is_simple(exprptr(expr_id)); }
INLINE bool exprid_is_simple(ExprId expr_id, bool to_float) { return expr_is_simple(exprptr(expr_id), to_float); }

INLINE void expr_resolve_ident(Expr *expr, Decl *decl)
{
Expand Down
16 changes: 13 additions & 3 deletions src/compiler/expr.c
Original file line number Diff line number Diff line change
Expand Up @@ -768,7 +768,7 @@ bool expr_is_pure(Expr *expr)
}


bool expr_is_simple(Expr *expr)
bool expr_is_simple(Expr *expr, bool to_float)
{
RETRY:
switch (expr->expr_kind)
Expand All @@ -777,7 +777,7 @@ bool expr_is_simple(Expr *expr)
expr = expr->inner_expr;
goto RETRY;
case EXPR_TERNARY:
return expr_is_simple(exprptr(expr->ternary_expr.else_expr)) && expr_is_simple(exprptr(expr->ternary_expr.then_expr));
return exprid_is_simple(expr->ternary_expr.else_expr, to_float) && exprid_is_simple(expr->ternary_expr.then_expr, to_float);
case EXPR_RETHROW:
expr = expr->rethrow_expr.inner;
goto RETRY;
Expand All @@ -786,6 +786,12 @@ bool expr_is_simple(Expr *expr)
case EXPR_BINARY:
switch (expr->binary_expr.operator)
{
case BINARYOP_DIV:
if (to_float) return false;
FALLTHROUGH;
case BINARYOP_MOD:
case BINARYOP_ELSE:
return exprid_is_simple(expr->binary_expr.left, to_float) && exprid_is_simple(expr->binary_expr.right, to_float);
case BINARYOP_AND:
case BINARYOP_OR:
case BINARYOP_GT:
Expand All @@ -806,15 +812,19 @@ bool expr_is_simple(Expr *expr)
case BINARYOP_SHL_ASSIGN:
case BINARYOP_SUB_ASSIGN:
return true;
case BINARYOP_SHL:
case BINARYOP_SHR:
return to_float;
default:
return false;
}
UNREACHABLE
case EXPR_UNARY:
switch (expr->unary_expr.operator)
{
case UNARYOP_NEG:
case UNARYOP_BITNEG:
return to_float;
case UNARYOP_NEG:
return false;
default:
return true;
Expand Down
47 changes: 21 additions & 26 deletions src/compiler/sema_casts.c
Original file line number Diff line number Diff line change
Expand Up @@ -622,27 +622,6 @@ bool cast_to_index(SemaContext *context, Expr *index)
}
}

bool cast_widen_top_down(SemaContext *context, Expr *expr, Type *type)
{
Type *to = type_no_optional(type);
Type *from = type_no_optional(expr->type);
RETRY:
if (type_is_integer(from) && type_is_integer(to)) goto CONVERT_IF_BIGGER;
if (type_is_float(from) && type_is_float(to)) goto CONVERT_IF_BIGGER;
if (type_is_integer(from) && type_is_float(to)) goto CONVERT;
if (type_flat_is_vector(from) && type_flat_is_vector(to))
{
to = type_vector_type(to);
from = type_vector_type(from);
goto RETRY;
}
return true;
CONVERT_IF_BIGGER:
if (type_size(to) <= type_size(from)) return true;
CONVERT:
return cast_implicit(context, expr, type);
}

Type *cast_numeric_arithmetic_promotion(Type *type)
{
if (!type) return NULL;
Expand Down Expand Up @@ -995,6 +974,21 @@ static bool rule_explicit_ok(CastContext *cc, bool is_explicit, bool silent)
}


static bool rule_int_to_float(CastContext *cc, bool is_explicit, bool is_silent)
{
if (is_explicit) return true;

Expr *expr = cc->expr;

if (!expr_is_simple(expr, true))
{
if (is_silent) return false;
RETURN_SEMA_ERROR(expr, "This conversion requires an explicit cast to %s, because the widening of the expression may be done in more than one way.",
type_quoted_error_string(cc->to_type));
}
return true;
}

static bool rule_widen_narrow(CastContext *cc, bool is_explicit, bool is_silent)
{
if (is_explicit) return true;
Expand All @@ -1006,11 +1000,11 @@ static bool rule_widen_narrow(CastContext *cc, bool is_explicit, bool is_silent)
// If widening, require simple.
if (to_size > from_size)
{
if (expr_is_simple(cc->expr)) return true;
if (expr_is_simple(cc->expr, type_is_float(cc->to))) return true;
if (is_silent) return false;
{
SEMA_ERROR(expr, "This conversion requires an explicit cast to %s, because the widening of the expression may be done in more than one way.",
type_quoted_error_string(cc->to_type));
type_quoted_error_string(cc->to_type));
}
return false;
}
Expand All @@ -1023,7 +1017,7 @@ static bool rule_widen_narrow(CastContext *cc, bool is_explicit, bool is_silent)
if (cc->to_group != CONV_INT)
{
RETURN_SEMA_ERROR(expr, "The value '%s' is out of range for %s, so you need an explicit cast to truncate the value.", expr_const_to_error_string(&expr->const_expr),
type_quoted_error_string(cc->to_type));
type_quoted_error_string(cc->to_type));
}
sema_error_const_int_out_of_range(expr, expr, cc->to_type);
}
Expand All @@ -1042,7 +1036,7 @@ static bool rule_widen_narrow(CastContext *cc, bool is_explicit, bool is_silent)
if (type_is_integer(type_flatten(problem->type))) expr = problem;
// Otherwise require a cast.
SEMA_ERROR(expr, "%s cannot implicitly be converted to %s, but you may use a cast.",
type_quoted_error_string(expr->type), type_quoted_error_string(cc->to_type));
type_quoted_error_string(expr->type), type_quoted_error_string(cc->to_type));
return false;
}
return true;
Expand Down Expand Up @@ -1868,6 +1862,7 @@ static void cast_typeid_to_bool(Expr *expr, Type *to_type)
#define REXPL &rule_explicit_ok /* Is explicit */
#define _NA__ &rule_not_applicable /* "Not applicable" - should not be seen. */
#define RIFIF &rule_widen_narrow /* Widen / narrow conversion of int/float */
#define RINFL &rule_int_to_float /* Simple expressions, check sizes */
#define ROKOK &rule_all_ok /* Always works */
#define RINPT &rule_int_to_ptr /* Int -> ptr (explicit + size match) */
#define RPTIN &rule_ptr_to_int /* Ptr -> int (explicit + size match) */
Expand Down Expand Up @@ -1897,7 +1892,7 @@ CastRule cast_rules[CONV_LAST + 1][CONV_LAST + 1] = {
{_NA__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__}, // VOID (from)
{ROKOK, _NA__, ROKOK, ROKOK, ROKOK, ROKOK, ROKOK, ROKOK, ROKOK, ROKOK, ROKOK, ROKOK, ROKOK, ROKOK, ROKOK, ROKOK, ROKOK, ROKOK, ROKOK, ROKOK, _NO__}, // WILDCARD
{REXPL, _NO__, _NA__, REXPL, REXPL, _NO__, _NO__, ROKOK, _NO__, RXXDI, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__}, // BOOL
{REXPL, _NO__, REXPL, RIFIF, ROKOK, RINPT, _NO__, ROKOK, RINBS, RXXDI, _NO__, _NO__, _NO__, _NO__, _NO__, RINEN, _NO__, _NO__, RINPT, RINPT, _NO__}, // INT
{REXPL, _NO__, REXPL, RIFIF, RINFL, RINPT, _NO__, ROKOK, RINBS, RXXDI, _NO__, _NO__, _NO__, _NO__, _NO__, RINEN, _NO__, _NO__, RINPT, RINPT, _NO__}, // INT
{REXPL, _NO__, REXPL, REXPL, RIFIF, _NO__, _NO__, ROKOK, _NO__, RXXDI, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__}, // FLOAT
{REXPL, _NO__, REXPL, RPTIN, _NO__, RPTPT, _NO__, ROKOK, _NO__, RXXDI, _NO__, _NO__, _NO__, ROKOK, _NO__, _NO__, _NO__, _NO__, ROKOK, RPTPT, RPTFE}, // PTR
{REXPL, _NO__, REXPL, _NO__, _NO__, RSAPT, RSASA, RSAVA, _NO__, RXXDI, RSAVA, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, ROKOK, RSAPT, RSAFE}, // SARRAY
Expand Down
78 changes: 3 additions & 75 deletions src/compiler/sema_expr.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ static Type *sema_subscript_find_indexable_type_recursively(Type **type, Expr **

// -- binary helper functions
static void expr_binary_unify_failability(Expr *expr, Expr *left, Expr *right);
static inline bool sema_binary_promote_top_down(SemaContext *context, Expr *binary, Expr *left, Expr *right);

static inline bool sema_binary_analyse_subexpr(SemaContext *context, Expr *binary, Expr *left, Expr *right);
static inline bool sema_binary_analyse_arithmetic_subexpr(SemaContext *context, Expr *expr, const char *error, bool bool_and_bitstruct_is_allowed);
static inline bool sema_binary_analyse_ct_identifier_lvalue(SemaContext *context, Expr *expr);
Expand Down Expand Up @@ -174,7 +174,7 @@ static inline bool sema_create_const_max(SemaContext *context, Expr *expr, Type
static inline bool sema_create_const_params(SemaContext *context, Expr *expr, Type *type);
static inline void sema_create_const_membersof(SemaContext *context, Expr *expr, Type *type, AlignSize alignment,
AlignSize offset);
void expr_insert_widening_type(Expr *expr, Type *infer_type);

static inline int64_t expr_get_index_max(Expr *expr);
static inline bool expr_both_any_integer_or_integer_vector(Expr *left, Expr *right);
static inline bool expr_both_any_integer_or_integer_bool_vector(Expr *left, Expr *right);
Expand Down Expand Up @@ -1023,13 +1023,6 @@ static inline bool sema_expr_analyse_hash_identifier(SemaContext *context, Expr
}


static inline bool sema_binary_promote_top_down(SemaContext *context, Expr *binary, Expr *left, Expr *right)
{
if (!binary->binary_expr.widen) return true;
Type *to = binary->type;
return cast_widen_top_down(context, left, to) && cast_widen_top_down(context, right, to);
}

static inline bool sema_binary_analyse_subexpr(SemaContext *context, Expr *binary, Expr *left, Expr *right)
{
// Special handling of f = FOO_BAR
Expand Down Expand Up @@ -1079,7 +1072,7 @@ static inline bool sema_binary_analyse_arithmetic_subexpr(SemaContext *context,
// 1. Analyse both sides.
if (!sema_binary_analyse_subexpr(context, expr, left, right)) return false;

if (!sema_binary_promote_top_down(context, expr, left, right)) return false;
//if (!sema_binary_promote_top_down(context, expr, left, right)) return false;

Type *left_type = type_no_optional(left->type)->canonical;
Type *right_type = type_no_optional(right->type)->canonical;
Expand Down Expand Up @@ -5090,8 +5083,6 @@ static bool sema_expr_analyse_sub(SemaContext *context, Expr *expr, Expr *left,
return sema_expr_analyse_enum_add_sub(context, expr, left, right);
}

if (!sema_binary_promote_top_down(context, expr, left, right)) return false;

left_type = type_no_optional(left->type)->canonical;
right_type = type_no_optional(right->type)->canonical;

Expand Down Expand Up @@ -5270,8 +5261,6 @@ static bool sema_expr_analyse_add(SemaContext *context, Expr *expr, Expr *left,
return sema_expr_analyse_enum_add_sub(context, expr, left, right);
}

if (!sema_binary_promote_top_down(context, expr, left, right)) return false;

left_type = type_no_optional(left->type)->canonical;
right_type = type_no_optional(right->type)->canonical;

Expand Down Expand Up @@ -5513,8 +5502,6 @@ static bool sema_expr_analyse_shift(SemaContext *context, Expr *expr, Expr *left
return sema_type_error_on_binop(expr);
}

if (expr->binary_expr.widen && !cast_widen_top_down(context, left, expr->type)) return false;

// 3. Promote lhs using the usual numeric promotion.
if (!cast_implicit(context, left, cast_numeric_arithmetic_promotion(type_no_optional(left->type)))) return false;

Expand Down Expand Up @@ -6011,7 +5998,6 @@ static inline bool sema_expr_analyse_neg_plus(SemaContext *context, Expr *expr)
Expr *inner = expr->unary_expr.expr;
bool is_plus = expr->unary_expr.operator == UNARYOP_PLUS;
if (!sema_analyse_expr(context, inner)) return false;
if (expr->unary_expr.widen && !cast_widen_top_down(context, inner, expr->type)) return false;

// 2. Check if it's possible to negate this (i.e. is it an int, float or vector)
Type *no_fail = type_no_optional(inner->type);
Expand Down Expand Up @@ -6069,8 +6055,6 @@ static inline bool sema_expr_analyse_bit_not(SemaContext *context, Expr *expr)
Expr *inner = expr->unary_expr.expr;
if (!sema_analyse_expr(context, inner)) return false;

if (expr->unary_expr.widen && !cast_widen_top_down(context, inner, expr->type)) return false;

// 2. Check that it's a vector, bool
Type *canonical = type_no_optional(inner->type)->canonical;
Type *flat = type_flatten(canonical);
Expand Down Expand Up @@ -6319,8 +6303,6 @@ static inline bool sema_expr_analyse_or_error(SemaContext *context, Expr *expr)
if (!sema_analyse_expr(context, lhs)) return false;
}

if (expr->binary_expr.widen && !cast_widen_top_down(context, lhs, expr->type)) return false;

Type *type = lhs->type;
if (!type_is_optional(type))
{
Expand All @@ -6335,7 +6317,6 @@ static inline bool sema_expr_analyse_or_error(SemaContext *context, Expr *expr)

// First we analyse the "else" and try to implictly cast.
if (!sema_analyse_expr(context, rhs)) return false;
if (expr->binary_expr.widen && !cast_widen_top_down(context, rhs, expr->type)) return false;

if (lhs->expr_kind == EXPR_OPTIONAL)
{
Expand Down Expand Up @@ -8350,58 +8331,6 @@ static inline int64_t expr_get_index_max(Expr *expr)
UNREACHABLE
}

void expr_insert_widening_type(Expr *expr, Type *infer_type)
{
if (!infer_type) return;
switch (expr->expr_kind)
{
case EXPR_BINARY:
switch (expr->binary_expr.operator)
{
case BINARYOP_MULT:
case BINARYOP_SUB:
case BINARYOP_ADD:
case BINARYOP_DIV:
case BINARYOP_MOD:
case BINARYOP_SHR:
case BINARYOP_SHL:
case BINARYOP_BIT_OR:
case BINARYOP_BIT_XOR:
case BINARYOP_BIT_AND:
case BINARYOP_ELSE:
if (!expr_is_simple(exprptr(expr->binary_expr.left)) || !expr_is_simple(exprptr(expr->binary_expr.right))) return;
expr->type = infer_type;
expr->binary_expr.widen = true;
return;
default:
return;
}
case EXPR_GROUP:
expr_insert_widening_type(expr->inner_expr, infer_type);
return;
case EXPR_TERNARY:
if (!exprid_is_simple(expr->ternary_expr.else_expr)) return;
if (expr->ternary_expr.then_expr && !exprid_is_simple(expr->ternary_expr.else_expr)) return;
expr->type = infer_type;
expr->ternary_expr.widen = true;
return;
case EXPR_UNARY:
switch (expr->unary_expr.operator)
{
case UNARYOP_NEG:
case UNARYOP_BITNEG:
if (!expr_is_simple(expr->unary_expr.expr)) return;
expr->type = infer_type;
expr->unary_expr.widen = true;
return;
default:
return;
}
default:
return;
}
UNREACHABLE
}
bool sema_analyse_inferred_expr(SemaContext *context, Type *infer_type, Expr *expr)
{
infer_type = type_no_optional(infer_type);
Expand Down Expand Up @@ -8436,7 +8365,6 @@ bool sema_analyse_inferred_expr(SemaContext *context, Type *infer_type, Expr *ex
if (!sema_expr_analyse_lambda(context, infer_type, expr)) return expr_poison(expr);
break;
default:
expr_insert_widening_type(expr, infer_type);
if (!sema_analyse_expr_dispatch(context, expr)) return expr_poison(expr);
break;
}
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/sema_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ bool sema_bit_assignment_check(Expr *right, Decl *member);
int sema_check_comp_time_bool(SemaContext *context, Expr *expr);
bool sema_expr_check_assign(SemaContext *c, Expr *expr);
bool sema_analyse_function_signature(SemaContext *context, Decl *func_decl, CallABI abi, Signature *signature, bool is_real_function);
bool cast_widen_top_down(SemaContext *context, Expr *expr, Type *type);

MemberIndex sema_len_from_const(Expr *expr);

void cast_promote_vararg(Expr *arg);
Expand Down
Loading

0 comments on commit efece23

Please sign in to comment.