Remove the last "cast" operations.

This commit is contained in:
Christoffer Lerno
2025-01-06 01:51:03 +01:00
parent 8fd119e546
commit 314c6f94f0
15 changed files with 220 additions and 201 deletions

View File

@@ -411,8 +411,10 @@ static void c_emit_expr(GenContext *c, CValue *value, Expr *expr)
case EXPR_ADDR_CONVERSION:
case EXPR_EXT_TRUNC:
case EXPR_MAKE_ANY:
case EXPR_MAKE_SLICE:
case EXPR_INT_TO_BOOL:
case EXPR_VECTOR_FROM_ARRAY:
case EXPR_ANYFAULT_TO_FAULT:
break;
case EXPR_ACCESS:
break;
@@ -435,7 +437,7 @@ static void c_emit_expr(GenContext *c, CValue *value, Expr *expr)
case EXPR_CALL:
break;
case EXPR_CAST:
break;
UNREACHABLE
case EXPR_CATCH_UNWRAP:
break;
case EXPR_COMPILER_CONST:

View File

@@ -968,7 +968,6 @@ typedef struct
typedef struct
{
CastKind kind : 8;
ExprId expr;
TypeInfoId type_info;
} ExprCast;
@@ -1134,6 +1133,13 @@ typedef struct
Expr *inner;
Expr *typeid;
} ExprMakeAny;
typedef struct
{
Expr *ptr;
ArraySize len;
} ExprMakeSlice;
struct Expr_
{
Type *type;
@@ -1179,6 +1185,7 @@ struct Expr_
Expr** initializer_list; // 8
Expr *inner_expr; // 8
ExprMakeAny make_any_expr;
ExprMakeSlice make_slice_expr;
Decl *lambda_expr; // 8
ExprMacroBlock macro_block; // 24
ExprMacroBody macro_body_expr; // 16
@@ -1322,7 +1329,6 @@ typedef struct
bool value_by_ref : 1;
bool iterator : 1;
bool is_reverse : 1;
CastKind cast : 8;
ExprId enumeration;
AstId body;
DeclId index;
@@ -2227,6 +2233,7 @@ Expr *expr_negate_expr(Expr *expr);
bool expr_may_addr(Expr *expr);
bool expr_in_int_range(Expr *expr, int64_t low, int64_t high);
bool expr_is_unwrapped_ident(Expr *expr);
bool expr_is_zero(Expr *expr);
INLINE Expr *expr_new_expr(ExprKind kind, Expr *expr);
INLINE bool expr_ok(Expr *expr);
INLINE void expr_resolve_ident(Expr *expr, Decl *decl);
@@ -3283,6 +3290,7 @@ ConstInitializer *const_init_new_struct(Type *type, Expr **elements);
ConstInitializer *const_init_new_array_full(Type *type, ConstInitializer **elements);
ConstInitializer *const_init_new_zero_array_value(Type *type, ArrayIndex index);
ConstInitializer *const_init_new_array_value(Expr *expr, ArrayIndex index);
bool const_init_is_zero(ConstInitializer *init);
void const_init_rewrite_to_value(ConstInitializer *const_init, Expr *value);
void const_init_rewrite_to_zero(ConstInitializer *init, Type *type);
@@ -3369,6 +3377,9 @@ static inline void expr_set_span(Expr *expr, SourceSpan loc)
expr_set_span(expr->make_any_expr.inner, loc);
expr_set_span(expr->make_any_expr.typeid, loc);
return;
case EXPR_MAKE_SLICE:
if (expr->make_slice_expr.ptr) expr_set_span(expr->make_slice_expr.ptr, loc);
return;
case EXPR_SPLAT:
case EXPR_PTR_ACCESS:
case EXPR_VECTOR_TO_ARRAY:
@@ -3384,6 +3395,7 @@ static inline void expr_set_span(Expr *expr, SourceSpan loc)
case EXPR_VECTOR_FROM_ARRAY:
case EXPR_ADDR_CONVERSION:
case EXPR_RECAST:
case EXPR_ANYFAULT_TO_FAULT:
expr_set_span(expr->inner_expr, loc);
return;
case EXPR_EXPRESSION_LIST:
@@ -3759,35 +3771,9 @@ INLINE void expr_rewrite_int_to_bool(Expr *expr, bool negate)
{
if (expr_is_const(expr))
{
switch (expr->const_expr.const_kind)
{
case CONST_FLOAT:
case CONST_BOOL:
case CONST_ENUM:
case CONST_BYTES:
case CONST_STRING:
case CONST_SLICE:
case CONST_INITIALIZER:
case CONST_UNTYPED_LIST:
case CONST_MEMBER:
UNREACHABLE
case CONST_ERR:
expr_rewrite_const_bool(expr, type_bool, expr->const_expr.enum_err_val != NULL);
return;
case CONST_INTEGER:
expr_rewrite_const_bool(expr, type_bool, !int_is_zero(expr->const_expr.ixx));
return;
case CONST_POINTER:
expr_rewrite_const_bool(expr, type_bool, expr->const_expr.ptr != 0);
return;
case CONST_TYPEID:
expr_rewrite_const_bool(expr, type_bool, expr->type != NULL);
return;
case CONST_REF:
expr_rewrite_const_bool(expr, type_bool, true);
return;
}
UNREACHABLE
bool is_zero = expr_is_zero(expr);
expr_rewrite_const_bool(expr, type_bool, negate ? is_zero : !is_zero);
return;
}
Expr *inner = expr_copy(expr);
expr->expr_kind = EXPR_INT_TO_BOOL;

View File

@@ -486,6 +486,7 @@ Expr *copy_expr(CopyStruct *c, Expr *source_expr)
case EXPR_FLOAT_TO_INT:
case EXPR_SLICE_LEN:
case EXPR_DISCARD:
case EXPR_ANYFAULT_TO_FAULT:
case EXPR_VECTOR_FROM_ARRAY:
case EXPR_RVALUE:
case EXPR_RECAST:
@@ -496,6 +497,9 @@ Expr *copy_expr(CopyStruct *c, Expr *source_expr)
MACRO_COPY_EXPR(expr->make_any_expr.inner);
MACRO_COPY_EXPR(expr->make_any_expr.typeid);
return expr;
case EXPR_MAKE_SLICE:
MACRO_COPY_EXPR(expr->make_slice_expr.ptr);
return expr;
case EXPR_DEFAULT_ARG:
MACRO_COPY_EXPR(expr->default_arg_expr.inner);
return expr;

View File

@@ -540,14 +540,6 @@ typedef enum
CALL_ENV_ATTR,
} CallEnvKind;
typedef enum
{
CAST_APTSA,
CAST_BSBOOL,
CAST_ERROR,
CAST_EUER,
} CastKind;
typedef enum
{
CMP_LT = -1,
@@ -768,12 +760,14 @@ typedef enum
EXPR_INT_TO_FLOAT,
EXPR_INT_TO_PTR,
EXPR_PTR_TO_INT,
EXPR_ANYFAULT_TO_FAULT,
EXPR_LAMBDA,
EXPR_LAST_FAULT,
EXPR_MACRO_BLOCK,
EXPR_MACRO_BODY,
EXPR_MACRO_BODY_EXPANSION,
EXPR_MAKE_ANY,
EXPR_MAKE_SLICE,
EXPR_MEMBER_GET,
EXPR_NAMED_ARGUMENT,
EXPR_NOP,

View File

@@ -4,7 +4,6 @@
#include "compiler_internal.h"
static inline bool expr_cast_is_runtime_const(Expr *expr);
static inline bool expr_list_is_constant_eval(Expr **exprs);
static inline bool expr_unary_addr_is_constant_eval(Expr *expr);
static inline ConstInitializer *initializer_for_index(ConstInitializer *initializer, ArraySize index, bool from_back);
@@ -29,6 +28,53 @@ bool expr_in_int_range(Expr *expr, int64_t low, int64_t high)
return value >= low && value <= high;
}
bool expr_is_zero(Expr *expr)
{
if (!sema_cast_const(expr)) return false;
switch (expr->const_expr.const_kind)
{
case CONST_FLOAT:
return !expr->const_expr.fxx.f;
case CONST_INTEGER:
return int_is_zero(expr->const_expr.ixx);
case CONST_BOOL:
return !expr->const_expr.b;
case CONST_ENUM:
case CONST_ERR:
return !expr->const_expr.enum_err_val->enum_constant.ordinal;
case CONST_BYTES:
case CONST_STRING:
{
size_t len = expr->const_expr.bytes.len;
for (size_t i = 0; i < len; i++)
{
if (expr->const_expr.bytes.ptr[i]) return false;
}
return true;
}
case CONST_POINTER:
return !expr->const_expr.ptr;
case CONST_TYPEID:
return !expr->const_expr.typeid;
case CONST_SLICE:
return const_init_is_zero(expr->const_expr.slice_init);
case CONST_INITIALIZER:
return const_init_is_zero(expr->const_expr.initializer);
case CONST_UNTYPED_LIST:
{
FOREACH(Expr *, e, expr->const_expr.untyped_list)
{
if (!expr_is_zero(e)) return false;
}
return true;
}
case CONST_REF:
return !expr->const_expr.global_ref;
case CONST_MEMBER:
return false;
}
UNREACHABLE
}
bool expr_is_unwrapped_ident(Expr *expr)
{
if (expr->expr_kind != EXPR_IDENTIFIER) return false;
@@ -83,6 +129,7 @@ bool expr_may_addr(Expr *expr)
case EXPR_BENCHMARK_HOOK:
case EXPR_TEST_HOOK:
case EXPR_VECTOR_FROM_ARRAY:
case EXPR_ANYFAULT_TO_FAULT:
case EXPR_VECTOR_TO_ARRAY:
case EXPR_SLICE_TO_VEC_ARRAY:
case EXPR_SCALAR_TO_VECTOR:
@@ -147,6 +194,7 @@ bool expr_may_addr(Expr *expr)
case EXPR_VASPLAT:
case EXPR_EXT_TRUNC:
case EXPR_INT_TO_BOOL:
case EXPR_MAKE_SLICE:
return false;
}
UNREACHABLE
@@ -208,6 +256,7 @@ bool expr_is_runtime_const(Expr *expr)
case EXPR_SLICE_LEN:
return false;
case EXPR_VECTOR_FROM_ARRAY:
case EXPR_ANYFAULT_TO_FAULT:
case EXPR_RVALUE:
case EXPR_RECAST:
case EXPR_ADDR_CONVERSION:
@@ -219,6 +268,10 @@ bool expr_is_runtime_const(Expr *expr)
case EXPR_SLICE_TO_VEC_ARRAY:
case EXPR_SCALAR_TO_VECTOR:
return expr_is_runtime_const(expr->inner_expr);
case EXPR_MAKE_SLICE:
expr = expr->make_slice_expr.ptr;
if (!expr) return true;
goto RETRY;
case EXPR_MAKE_ANY:
if (!expr_is_runtime_const(expr->make_any_expr.typeid)) return false;
expr = expr->make_any_expr.inner;
@@ -239,7 +292,7 @@ bool expr_is_runtime_const(Expr *expr)
}
return exprid_is_runtime_const(expr->builtin_access_expr.inner);
case EXPR_CAST:
return expr_cast_is_runtime_const(expr);
return exprid_is_runtime_const(expr->cast_expr.expr);
case EXPR_INT_TO_BOOL:
return expr_is_runtime_const(expr->int_to_bool_expr.inner);
case EXPR_EXT_TRUNC:
@@ -365,20 +418,6 @@ bool expr_is_runtime_const(Expr *expr)
UNREACHABLE
}
static inline bool expr_cast_is_runtime_const(Expr *expr)
{
switch (expr->cast_expr.kind)
{
case CAST_ERROR:
UNREACHABLE
case CAST_EUER:
case CAST_APTSA:
case CAST_BSBOOL:
return exprid_is_runtime_const(expr->cast_expr.expr);
}
UNREACHABLE
}
static inline bool expr_list_is_constant_eval(Expr **exprs)
{
@@ -605,6 +644,8 @@ bool expr_is_pure(Expr *expr)
case EXPR_BENCHMARK_HOOK:
case EXPR_TEST_HOOK:
return false;
case EXPR_MAKE_SLICE:
return expr_is_pure(expr->make_slice_expr.ptr);
case EXPR_MAKE_ANY:
return expr_is_pure(expr->make_any_expr.inner) && expr_is_pure(expr->make_any_expr.typeid);
case EXPR_PTR_ACCESS:
@@ -619,6 +660,7 @@ bool expr_is_pure(Expr *expr)
case EXPR_SLICE_LEN:
case EXPR_DISCARD:
case EXPR_VECTOR_FROM_ARRAY:
case EXPR_ANYFAULT_TO_FAULT:
case EXPR_RVALUE:
case EXPR_RECAST:
case EXPR_ADDR_CONVERSION:

View File

@@ -246,6 +246,8 @@ void print_var_expr(FILE *file, Expr *expr)
case EXPR_ADDR_CONVERSION:
print_var_expr(file, expr->inner_expr);
break;
case EXPR_MAKE_SLICE:
TODO
case EXPR_MAKE_ANY:
fputs("TODO: MAKE_ANY", file);
break;
@@ -266,6 +268,7 @@ void print_var_expr(FILE *file, Expr *expr)
print_var_expr(file, expr->access_expr.parent);
fputs(")", file);
break;
case EXPR_ANYFAULT_TO_FAULT:
case EXPR_VECTOR_FROM_ARRAY:
TODO
case EXPR_SLICE_LEN:
@@ -417,11 +420,7 @@ void print_var_expr(FILE *file, Expr *expr)
}
break;
case EXPR_CAST:
fputs("(", file);
print_type(file, type_infoptr(expr->cast_expr.type_info));
fputs(")", file);
print_var_expr(file, exprptr(expr->cast_expr.expr));
break;
UNREACHABLE
case EXPR_BUILTIN:
case EXPR_COMPILER_CONST:
PRINTF("$$%s", expr->builtin_expr.ident);

View File

@@ -1257,34 +1257,6 @@ void llvm_new_phi(GenContext *c, BEValue *value, const char *name, Type *type, L
static inline void llvm_emit_initialize_reference(GenContext *c, BEValue *value, Expr *expr);
/**
* Here we are converting an array to a slice.
* int[] x = &the_array;
* @param c
* @param value
* @param to_type
* @param from_type
*/
static void llvm_emit_arr_to_slice_cast(GenContext *c, BEValue *value, Type *to_type)
{
ByteSize size = value->type->pointer->array.len;
LLVMValueRef pointer;
Type *array_type = value->type->pointer->array.base;
if (size)
{
llvm_value_rvalue(c, value);
pointer = value->value;
}
else
{
pointer = llvm_get_zero(c, type_get_ptr(array_type));
}
LLVMValueRef len = llvm_const_int(c, type_usz, size);
llvm_value_aggregate_two(c, value, to_type, pointer, len);
}
// Prune the common occurrence where the optional is not used.
static void llvm_prune_optional(GenContext *c, LLVMBasicBlockRef discard_fail)
@@ -1399,28 +1371,6 @@ static void llvm_emit_bitstruct_to_bool(GenContext *c, BEValue *value, Type *to_
llvm_value_set(value, llvm_emit_char_array_zero(c, value, false), to_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);
switch (cast_kind)
{
case CAST_BSBOOL:
llvm_emit_bitstruct_to_bool(c, value, to_type, from_type);
return;
case CAST_ERROR:
UNREACHABLE
case CAST_APTSA:
llvm_emit_arr_to_slice_cast(c, value, to_type);
break;
case CAST_EUER:
REMINDER("Improve fault to err comparison");
break;
}
value->type = type_lowering(to_type);
}
void llvm_emit_bool_cast(GenContext *c, Expr *expr, BEValue *value)
{
switch (value->type->type_kind)
@@ -1486,6 +1436,7 @@ void llvm_emit_bool_cast(GenContext *c, Expr *expr, BEValue *value)
value->kind = BE_BOOLEAN;
return;
case TYPE_BITSTRUCT:
llvm_emit_bitstruct_to_bool(c, value, type_bool, value->type);
return;
case TYPE_INFERRED_ARRAY:
@@ -7065,6 +7016,24 @@ void llvm_emit_expr_global_value(GenContext *c, BEValue *value, Expr *expr)
static void llvm_emit_int_to_bool(GenContext *c, BEValue *value, Expr *expr)
{
llvm_emit_expr(c, value, expr->int_to_bool_expr.inner);
Type *inner_type = value->type;
if (inner_type->type_kind == TYPE_ARRAY)
{
assert(inner_type->array.base == type_char || inner_type->array.base == type_ichar);
llvm_value_addr(c, value);
unsigned len = type_size(value->type);
ASSERT0(len > 0);
LLVMValueRef total = NULL;
for (int i = 0; i < len; i++)
{
LLVMValueRef ref = llvm_emit_const_ptradd_inbounds_raw(c, value->value, i);
LLVMValueRef val = llvm_zext_trunc(c, llvm_load(c, c->byte_type, ref, 1, ""), llvm_get_type(c, type_cint));
total = total ? LLVMBuildAdd(c->builder, total, val, "") : val;
}
LLVMValueRef val = LLVMBuildICmp(c->builder, expr->int_to_bool_expr.negate ? LLVMIntEQ : LLVMIntNE, total, llvm_get_zero(c, type_cint), "");
llvm_value_set(value, val, expr->type);
return;
}
llvm_value_rvalue(c, value);
llvm_value_set(value,
expr->int_to_bool_expr.negate
@@ -7224,6 +7193,24 @@ void llvm_emit_slice_to_vec_array(GenContext *c, BEValue *value, Expr *expr)
llvm_value_set_address(value, temp, to_type, alignment);
}
static inline void llvm_emit_make_slice(GenContext *c, BEValue *value, Expr *expr)
{
ArraySize size = expr->make_slice_expr.len;
LLVMValueRef pointer;
if (size)
{
llvm_emit_expr(c, value, expr->make_slice_expr.ptr);
llvm_value_rvalue(c, value);
pointer = value->value;
}
else
{
assert(!expr->make_slice_expr.ptr);
pointer = llvm_get_zero(c, type_voidptr);
}
llvm_value_aggregate_two(c, value, expr->type, pointer, llvm_const_int(c, type_usz, size));
}
void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr)
{
EMIT_EXPR_LOC(c, expr);
@@ -7251,6 +7238,9 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr)
case EXPR_SCALAR_TO_VECTOR:
llvm_emit_scalar_to_vector(c, value, expr);
return;
case EXPR_MAKE_SLICE:
llvm_emit_make_slice(c, value, expr);
return;
case EXPR_ENUM_FROM_ORD:
llvm_emit_enum_from_ord(c, value, expr);
return;
@@ -7307,6 +7297,12 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr)
llvm_value_rvalue(c, value);
value->type = type_lowering(expr->type);
return;
case EXPR_ANYFAULT_TO_FAULT:
REMINDER("Improve anyfault -> fault");
llvm_emit_expr(c, value, expr->inner_expr);
llvm_value_rvalue(c, value);
value->type = type_lowering(expr->type);
return;
case EXPR_VECTOR_FROM_ARRAY:
llvm_emit_vector_from_array(c, value, expr);
return;
@@ -7446,14 +7442,7 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr)
llvm_emit_expression_list_expr(c, value, expr);
return;
case EXPR_CAST:
llvm_emit_exprid(c, value, expr->cast_expr.expr);
llvm_emit_cast(c,
expr->cast_expr.kind,
expr,
value,
expr->type,
exprtype(expr->cast_expr.expr));
return;
UNREACHABLE
case EXPR_BITACCESS:
llvm_emit_bitaccess(c, value, expr);
return;

View File

@@ -544,7 +544,6 @@ void llvm_emit_initialize_reference_temporary_const(GenContext *c, BEValue *ref,
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, Expr *expr, BEValue *value, Type *to_type, Type *from_type);
void llvm_emit_bool_cast(GenContext *c, Expr *expr, BEValue *value);
void llvm_emit_local_var_alloca(GenContext *c, Decl *decl);
void llvm_emit_local_decl(GenContext *c, Decl *decl, BEValue *value);

View File

@@ -25,10 +25,8 @@ typedef struct
static bool sema_error_const_int_out_of_range(CastContext *cc, Expr *expr, Expr *problem, Type *to_type);
static Expr *recursive_may_narrow(Expr *expr, Type *type);
static void expr_recursively_rewrite_untyped_list(Expr *expr, Expr **list);
static inline bool insert_runtime_cast(Expr *expr, CastKind kind, Type *type);
static void vector_const_initializer_convert_to_type(SemaContext *context, ConstInitializer *initializer, Type *to_type);
static bool cast_is_allowed(CastContext *cc, bool is_explicit, bool is_silent);
INLINE bool insert_runtime_cast_unless_const(Expr *expr, CastKind kind, Type *type);
static bool cast_if_valid(SemaContext *context, Expr *expr, Type *to_type, bool is_explicit, bool is_silent,
bool is_binary_conversion);
@@ -452,12 +450,7 @@ RETRY:
expr = expr->ext_trunc_expr.inner;
goto RETRY;
case EXPR_CAST:
switch (expr->cast_expr.kind)
{
default:
// For all other casts we regard them as opaque.
goto CHECK_SIZE;
}
UNREACHABLE
case EXPR_CONST:
// For constants, just check that they will fit.
if (type_is_integer(type))
@@ -1397,23 +1390,20 @@ static bool rule_bits_to_int(CastContext *cc, bool is_explicit, bool is_silent)
// CASTS ----
/**
* Insert a cast. This will assume that the cast is valid. No typeinfo will be registered.
*/
static inline bool insert_runtime_cast(Expr *expr, CastKind kind, Type *type)
static void cast_vaptr_to_slice(SemaContext *context, Expr *expr, Type *type)
{
ASSERT0(expr->resolve_status == RESOLVE_DONE);
ASSERT0(expr->type);
Type *flat = type_flatten(expr->type);
ASSERT0(flat->type_kind == TYPE_POINTER);
flat = flat->pointer;
ASSERT0(flat->array.len > 0);
Expr *inner = expr_copy(expr);
expr->expr_kind = EXPR_CAST;
expr->cast_expr.kind = kind;
expr->cast_expr.expr = exprid(inner);
expr->cast_expr.type_info = 0;
expr->make_slice_expr = (ExprMakeSlice) {.ptr = inner, .len = flat->array.len};
expr->expr_kind = EXPR_MAKE_SLICE;
expr->resolve_status = RESOLVE_DONE;
expr->type = type;
return true;
}
static void cast_vaptr_to_slice(SemaContext *context, Expr *expr, Type *type) { insert_runtime_cast(expr, CAST_APTSA, type); }
static void cast_ptr_to_any(SemaContext *context, Expr *expr, Type *type)
{
Expr *inner = expr_copy(expr);
@@ -1437,15 +1427,6 @@ static void cast_any_to_ptr(SemaContext *context, Expr *expr, Type *type) { expr
static void cast_all_to_void(SemaContext *context, Expr *expr, Type *to_type) { expr_rewrite_discard(expr); }
static void cast_retype(SemaContext *context, Expr *expr, Type *to_type) { expr->type = to_type; }
/**
* Insert a cast on non-const only
*/
INLINE bool insert_runtime_cast_unless_const(Expr *expr, CastKind kind, Type *type)
{
if (sema_cast_const(expr) && expr->const_expr.const_kind != CONST_TYPEID) return false;
return insert_runtime_cast(expr, kind, type);
}
static void vector_const_initializer_convert_to_type(SemaContext *context, ConstInitializer *initializer, Type *to_type)
{
switch (initializer->kind)
@@ -1635,36 +1616,8 @@ static void cast_int_arr_to_bitstruct(SemaContext *context, Expr *expr, Type *ty
static void cast_bitstruct_to_bool(SemaContext *context, Expr *expr, Type *type)
{
if (expr_is_const(expr))
{
if (!expr_is_const_initializer(expr) || expr->const_expr.initializer->kind == CONST_INIT_ZERO)
{
expr_rewrite_const_bool(expr, type, false);
return;
}
ASSERT0(expr->const_expr.initializer->kind == CONST_INIT_STRUCT);
FOREACH(ConstInitializer *, in, expr->const_expr.initializer->init_struct)
{
if (in->kind == CONST_INIT_ZERO) continue;
Expr *e = in->init_value;
if (expr_is_const_bool(e))
{
if (!e->const_expr.b) continue;
expr_rewrite_const_bool(expr, type, true);
return;
}
if (expr_is_const_int(e))
{
if (int_is_zero(e->const_expr.ixx)) continue;
expr_rewrite_const_bool(expr, type, true);
return;
}
UNREACHABLE
}
expr_rewrite_const_bool(expr, type, false);
return;
}
insert_runtime_cast(expr, CAST_BSBOOL, type);
expr_rewrite_int_to_bool(expr, false);
expr->type = type;
}
@@ -1849,7 +1802,15 @@ static void cast_untyped_list_to_other(SemaContext *context, Expr *expr, Type *t
static void cast_anyfault_to_fault(SemaContext *context, Expr *expr, Type *type)
{
if (insert_runtime_cast_unless_const(expr, CAST_EUER, type) || !expr_is_const_fault(expr)) return;
if (!sema_cast_const(expr))
{
expr->inner_expr = expr_copy(expr);
expr->expr_kind = EXPR_ANYFAULT_TO_FAULT;
expr->type = type;
expr->resolve_status = RESOLVE_DONE;
return;
}
assert(expr_is_const_fault(expr));
Decl *value = expr->const_expr.enum_err_val;
ASSERT0(value->type != type);
expr->type = type;
@@ -2072,13 +2033,6 @@ static void cast_slice_to_vecarr(SemaContext *context, Expr *expr, Type *to_type
{
switch (expr->expr_kind)
{
case EXPR_CAST:
{
Expr *inner = exprptr(expr->cast_expr.expr)->unary_expr.expr;
expr_replace(expr, inner);
cast_no_check(context, expr, to_type, false);
return;
}
case EXPR_SLICE:
{
expr->inner_expr = expr_copy(expr);
@@ -2090,8 +2044,6 @@ static void cast_slice_to_vecarr(SemaContext *context, Expr *expr, Type *to_type
default:
UNREACHABLE;
}
ASSERT0(expr->expr_kind == EXPR_CAST);
return;
}
if (expr_is_const_slice(expr))
{

View File

@@ -17,13 +17,8 @@ ArrayIndex sema_len_from_const(Expr *expr)
{
return range_const_len(&expr->slice_expr.range);
}
if (expr->expr_kind != EXPR_CAST) return -1;
if (expr->cast_expr.kind != CAST_APTSA) return -1;
Expr *inner = exprptr(expr->cast_expr.expr);
if (inner->expr_kind != EXPR_UNARY || inner->unary_expr.operator != UNARYOP_ADDR) return -1;
inner = inner->unary_expr.expr;
if (!sema_cast_const(inner)) return -1;
expr = inner;
if (expr->expr_kind != EXPR_MAKE_SLICE) return -1;
return expr->make_slice_expr.len;
}
ConstInitializer *init;
switch (expr->const_expr.const_kind)

View File

@@ -551,6 +551,7 @@ static bool sema_binary_is_expr_lvalue(SemaContext *context, Expr *top_expr, Exp
case EXPR_MACRO_BODY:
case EXPR_MACRO_BODY_EXPANSION:
case EXPR_MAKE_ANY:
case EXPR_MAKE_SLICE:
case EXPR_MEMBER_GET:
case EXPR_NAMED_ARGUMENT:
case EXPR_NOP:
@@ -582,6 +583,7 @@ static bool sema_binary_is_expr_lvalue(SemaContext *context, Expr *top_expr, Exp
case EXPR_TYPEID_INFO:
case EXPR_TYPEINFO:
case EXPR_VASPLAT:
case EXPR_ANYFAULT_TO_FAULT:
case EXPR_VECTOR_FROM_ARRAY:
case EXPR_VECTOR_TO_ARRAY:
case EXPR_SLICE_TO_VEC_ARRAY:
@@ -624,11 +626,13 @@ static bool expr_may_ref(Expr *expr)
case EXPR_PTR_TO_INT:
case EXPR_SLICE_LEN:
case EXPR_VECTOR_FROM_ARRAY:
case EXPR_ANYFAULT_TO_FAULT:
case EXPR_INT_TO_BOOL:
case EXPR_RVALUE:
case EXPR_RECAST:
case EXPR_DISCARD:
case EXPR_ADDR_CONVERSION:
case EXPR_MAKE_SLICE:
return false;
case EXPR_OTHER_CONTEXT:
return expr_may_ref(expr->expr_other_context.inner);
@@ -9003,6 +9007,7 @@ static inline bool sema_expr_analyse_ct_defined(SemaContext *context, Expr *expr
case EXPR_PTR_ACCESS:
case EXPR_ENUM_FROM_ORD:
case EXPR_SLICE_LEN:
case EXPR_ANYFAULT_TO_FAULT:
case EXPR_VECTOR_FROM_ARRAY:
case EXPR_RVALUE:
case EXPR_RECAST:
@@ -9013,6 +9018,7 @@ static inline bool sema_expr_analyse_ct_defined(SemaContext *context, Expr *expr
case EXPR_INT_TO_FLOAT:
case EXPR_INT_TO_PTR:
case EXPR_PTR_TO_INT:
case EXPR_MAKE_SLICE:
if (!sema_analyse_expr(active_context, main_expr)) goto FAIL;
break;
}
@@ -9402,6 +9408,7 @@ static inline bool sema_analyse_expr_dispatch(SemaContext *context, Expr *expr,
case EXPR_VECTOR_TO_ARRAY:
case EXPR_SLICE_TO_VEC_ARRAY:
case EXPR_SCALAR_TO_VECTOR:
case EXPR_MAKE_SLICE:
UNREACHABLE
case EXPR_MAKE_ANY:
if (!sema_analyse_expr(context, expr->make_any_expr.typeid)) return false;
@@ -9413,6 +9420,7 @@ static inline bool sema_analyse_expr_dispatch(SemaContext *context, Expr *expr,
return sema_analyse_expr(context, expr->inner_expr);
case EXPR_PTR_ACCESS:
case EXPR_SLICE_LEN:
case EXPR_ANYFAULT_TO_FAULT:
case EXPR_VECTOR_FROM_ARRAY:
return sema_analyse_expr(context, expr->inner_expr);
case EXPR_INT_TO_BOOL:

View File

@@ -886,6 +886,47 @@ void const_init_rewrite_to_value(ConstInitializer *const_init, Expr *value)
const_init->kind = CONST_INIT_VALUE;
}
bool const_init_is_zero(ConstInitializer *init)
{
RETRY:
switch (init->kind)
{
case CONST_INIT_ZERO:
return true;
case CONST_INIT_STRUCT:
{
FOREACH(ConstInitializer *, i, init->init_struct)
{
if (!const_init_is_zero(i)) return false;
}
return true;
}
case CONST_INIT_UNION:
init = init->init_union.element;
goto RETRY;
case CONST_INIT_VALUE:
return expr_is_zero(init->init_value);
case CONST_INIT_ARRAY:
{
FOREACH(ConstInitializer *, i, init->init_array.elements)
{
if (!const_init_is_zero(i)) return false;
}
return true;
}
case CONST_INIT_ARRAY_FULL:
{
FOREACH(ConstInitializer *, i, init->init_array_full)
{
if (!const_init_is_zero(i)) return false;
}
return true;
}
case CONST_INIT_ARRAY_VALUE:
return const_init_is_zero(init->init_array_value.element);
}
UNREACHABLE
}
ConstInitializer *const_init_new_value(Expr *value)
{
ConstInitializer *init = CALLOCS(ConstInitializer);

View File

@@ -271,6 +271,9 @@ RETRY:
return;
case EXPR_BUILTIN:
return;
case EXPR_MAKE_SLICE:
expr = expr->make_slice_expr.ptr;
goto RETRY;
case EXPR_MAKE_ANY:
sema_trace_expr_liveness(expr->make_any_expr.typeid);
expr = expr->make_any_expr.inner;
@@ -339,6 +342,7 @@ RETRY:
case EXPR_INT_TO_PTR:
case EXPR_PTR_TO_INT:
case EXPR_SLICE_LEN:
case EXPR_ANYFAULT_TO_FAULT:
case EXPR_VECTOR_FROM_ARRAY:
case EXPR_RVALUE:
case EXPR_RECAST:

View File

@@ -285,6 +285,9 @@ static inline Expr *sema_dive_into_expression(Expr *expr)
case EXPR_RECAST:
expr = expr->inner_expr;
continue;
case EXPR_MAKE_SLICE:
expr = expr->make_slice_expr.ptr;
continue;
case EXPR_MAKE_ANY:
expr = expr->make_any_expr.inner;
continue;
@@ -766,6 +769,7 @@ static inline bool sema_expr_valid_try_expression(Expr *expr)
case EXPR_INT_TO_BOOL:
case EXPR_VECTOR_TO_ARRAY:
case EXPR_SLICE_TO_VEC_ARRAY:
case EXPR_MAKE_SLICE:
case EXPR_SCALAR_TO_VECTOR:
case EXPR_PTR_ACCESS:
case EXPR_FLOAT_TO_INT:
@@ -773,6 +777,7 @@ static inline bool sema_expr_valid_try_expression(Expr *expr)
case EXPR_INT_TO_PTR:
case EXPR_PTR_TO_INT:
case EXPR_SLICE_LEN:
case EXPR_ANYFAULT_TO_FAULT:
case EXPR_VECTOR_FROM_ARRAY:
case EXPR_RVALUE:
case EXPR_RECAST:

View File

@@ -37,8 +37,8 @@ fn void main()
%1 = load i32, ptr %a, align 4
%2 = load i32, ptr %b, align 4
%and = and i32 %1, %2
%neq = icmp ne i32 %and, 0
br i1 %neq, label %if.then, label %if.exit
%i2b = icmp ne i32 %and, 0
br i1 %i2b, label %if.then, label %if.exit
if.then: ; preds = %entry
ret void
@@ -56,9 +56,8 @@ if.exit: ; preds = %entry
%6 = load i8, ptr %ptradd, align 1
%zext2 = zext i8 %6 to i32
%7 = add i32 %zext, %zext2
%8 = icmp ne i32 %7, 0
%not = xor i1 %8, true
br i1 %not, label %if.then3, label %if.exit4
%8 = icmp eq i32 %7, 0
br i1 %8, label %if.then3, label %if.exit4
if.then3: ; preds = %if.exit
ret void