diff --git a/src/compiler/c_codegen.c b/src/compiler/c_codegen.c index 5a0c66575..474c593ad 100644 --- a/src/compiler/c_codegen.c +++ b/src/compiler/c_codegen.c @@ -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: diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 4be412de4..55dd5598f 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -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; diff --git a/src/compiler/copying.c b/src/compiler/copying.c index b053bdf01..8878106e8 100644 --- a/src/compiler/copying.c +++ b/src/compiler/copying.c @@ -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; diff --git a/src/compiler/enums.h b/src/compiler/enums.h index 53f3e49e3..900ed11df 100644 --- a/src/compiler/enums.h +++ b/src/compiler/enums.h @@ -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, diff --git a/src/compiler/expr.c b/src/compiler/expr.c index cfa27c99a..b724d2d73 100644 --- a/src/compiler/expr.c +++ b/src/compiler/expr.c @@ -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: diff --git a/src/compiler/json_output.c b/src/compiler/json_output.c index 89d08fafa..06d5160d1 100644 --- a/src/compiler/json_output.c +++ b/src/compiler/json_output.c @@ -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); diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index 1e473e3d0..1aa004ea0 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -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; diff --git a/src/compiler/llvm_codegen_internal.h b/src/compiler/llvm_codegen_internal.h index 435f207c8..055019f14 100644 --- a/src/compiler/llvm_codegen_internal.h +++ b/src/compiler/llvm_codegen_internal.h @@ -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); diff --git a/src/compiler/sema_casts.c b/src/compiler/sema_casts.c index ab6f6253a..7ac4ea2f8 100644 --- a/src/compiler/sema_casts.c +++ b/src/compiler/sema_casts.c @@ -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)) { diff --git a/src/compiler/sema_const.c b/src/compiler/sema_const.c index 515fc7e14..22d14aecb 100644 --- a/src/compiler/sema_const.c +++ b/src/compiler/sema_const.c @@ -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) diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 3908a5555..b93a4fe2d 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -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: diff --git a/src/compiler/sema_initializers.c b/src/compiler/sema_initializers.c index c998dcd69..51e1d086d 100644 --- a/src/compiler/sema_initializers.c +++ b/src/compiler/sema_initializers.c @@ -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); diff --git a/src/compiler/sema_liveness.c b/src/compiler/sema_liveness.c index b00a562c6..8b68c2cc8 100644 --- a/src/compiler/sema_liveness.c +++ b/src/compiler/sema_liveness.c @@ -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: diff --git a/src/compiler/sema_stmts.c b/src/compiler/sema_stmts.c index c175ee931..b6a91d5ab 100644 --- a/src/compiler/sema_stmts.c +++ b/src/compiler/sema_stmts.c @@ -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: diff --git a/test/test_suite/bitstruct/bitstruct_bool.c3t b/test/test_suite/bitstruct/bitstruct_bool.c3t index ea8d46b8d..bbece73f1 100644 --- a/test/test_suite/bitstruct/bitstruct_bool.c3t +++ b/test/test_suite/bitstruct/bitstruct_bool.c3t @@ -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