Add checks on enum conversion in safe mode. Bump to 0.3.38.

This commit is contained in:
Christoffer Lerno
2022-09-09 17:18:27 +02:00
parent a0a2e27127
commit fa89ea7b79
7 changed files with 31 additions and 8 deletions

View File

@@ -97,6 +97,7 @@ typedef enum
CAST_BOOLBOOL,
CAST_FPBOOL,
CAST_INTBOOL,
CAST_INTENUM,
CAST_FPFP,
CAST_FPSI,
CAST_FPUI,

View File

@@ -1106,8 +1106,9 @@ void llvm_emit_array_to_vector_cast(GenContext *c, BEValue *value, Type *to_type
llvm_value_set(value, vector, to_type);
}
void llvm_emit_cast(GenContext *c, CastKind cast_kind, BEValue *value, Type *to_type, Type *from_type)
void llvm_emit_cast(GenContext *c, CastKind cast_kind, Expr *expr, BEValue *value, Type *to_type, Type *from_type)
{
Type *to_type_original = to_type;
to_type = type_flatten(to_type);
from_type = type_flatten(from_type);
@@ -1288,6 +1289,27 @@ void llvm_emit_cast(GenContext *c, CastKind cast_kind, BEValue *value, Type *to_
value->value = LLVMBuildBitCast(c->builder, value->value, llvm_get_ptr_type(c, to_type), "");
value->type = to_type;
return;
case CAST_INTENUM:
if (active_target.feature.safe_mode && c->builder != c->global_builder)
{
llvm_value_rvalue(c, value);
BEValue check;
Decl *decl = to_type_original->canonical->decl;
unsigned max = vec_size(decl->enums.values);
if (type_is_signed(value->type))
{
scratch_buffer_clear();
scratch_buffer_printf("Conversion to enum '%s' failed - tried to convert a negative value.", decl->name);
llvm_emit_int_comp_zero(c, &check, value, BINARYOP_LT);
llvm_emit_panic_on_true(c, check.value, scratch_buffer_to_string(), expr->span);
}
scratch_buffer_clear();
scratch_buffer_printf("Conversion to enum '%s' failed - the value was greater than %u.", decl->name, max - 1);
LLVMValueRef val = llvm_const_int(c, value->type, max);
llvm_emit_int_comp_raw(c, &check, value->type, value->type, value->value, val, BINARYOP_GE);
llvm_emit_panic_on_true(c, check.value,scratch_buffer_to_string(), expr->span);
}
return;
case CAST_SABOOL:
llvm_value_fold_optional(c, value);
if (llvm_value_is_addr(value))
@@ -1316,6 +1338,7 @@ static inline void gencontext_emit_cast_expr(GenContext *context, BEValue *be_va
llvm_emit_exprid(context, be_value, expr->cast_expr.expr);
llvm_emit_cast(context,
expr->cast_expr.kind,
expr,
be_value,
expr->type,
exprtype(expr->cast_expr.expr));
@@ -3620,7 +3643,7 @@ void gencontext_emit_elvis_expr(GenContext *c, BEValue *value, Expr *expr)
if (value->kind != BE_BOOLEAN)
{
CastKind cast = cast_to_bool_kind(cond_type);
llvm_emit_cast(c, cast, value, type_bool, cond_type);
llvm_emit_cast(c, cast, cond, value, type_bool, cond_type);
assert(value->kind == BE_BOOLEAN);
}

View File

@@ -426,7 +426,7 @@ void llvm_emit_initialize_reference_temporary_const(GenContext *c, BEValue *ref,
void llvm_emit_len_for_expr(GenContext *c, BEValue *be_value, BEValue *expr_to_len);
LLVMValueRef llvm_get_ref(GenContext *c, Decl *decl);
LLVMValueRef llvm_emit_call_intrinsic(GenContext *c, unsigned intrinsic, LLVMTypeRef *types, unsigned type_count, LLVMValueRef *values, unsigned arg_count);
void llvm_emit_cast(GenContext *c, CastKind cast_kind, BEValue *value, Type *to_type, Type *from_type);
void llvm_emit_cast(GenContext *c, CastKind cast_kind, Expr *expr, BEValue *value, Type *to_type, Type *from_type);
void llvm_emit_local_var_alloca(GenContext *c, Decl *decl);
void llvm_emit_local_decl(GenContext *c, Decl *decl, BEValue *value);

View File

@@ -152,7 +152,7 @@ void llvm_emit_decl_expr_list(GenContext *context, BEValue *be_value, Expr *expr
if (type->type_kind != TYPE_BOOL)
{
CastKind cast = cast_to_bool_kind(type);
llvm_emit_cast(context, cast, be_value, type, type_bool);
llvm_emit_cast(context, cast, last, be_value, type, type_bool);
}
}
}

View File

@@ -214,11 +214,9 @@ bool integer_to_enum(Expr *expr, Type *canonical, Type *type)
Decl *enum_decl = canonical->decl;
if (expr->expr_kind != EXPR_CONST)
{
REMINDER("Add check for runtime enum conversions");
Type *underlying_type = enum_decl->enums.type_info->type->canonical;
if (!cast(expr, underlying_type)) return false;
expr->type = type;
return true;
return insert_cast(expr, CAST_INTENUM, type);
}
unsigned max_enums = vec_size(enum_decl->enums.values);
Int to_convert = expr->const_expr.ixx;

View File

@@ -263,6 +263,7 @@ bool expr_cast_is_constant_eval(Expr *expr, ConstantEvalKind eval_kind)
case CAST_BSINT:
case CAST_BSARRY:
return true;
case CAST_INTENUM:
case CAST_ANYPTR:
case CAST_ERBOOL:
case CAST_EUBOOL:

View File

@@ -1 +1 @@
#define COMPILER_VERSION "0.3.37"
#define COMPILER_VERSION "0.3.38"