From 07c59e6a6c6ccde946b81369cd38780631905214 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Sun, 5 Jan 2025 02:24:11 +0100 Subject: [PATCH] Fix `+a = 1` erronously being accepted. Refactorings. --- releasenotes.md | 1 + src/compiler/c_codegen.c | 1 + src/compiler/compiler_internal.h | 17 +- src/compiler/copying.c | 1 + src/compiler/enums.h | 4 +- src/compiler/expr.c | 6 +- src/compiler/json_output.c | 4 + src/compiler/llvm_codegen_expr.c | 141 ++-------- src/compiler/llvm_codegen_internal.h | 2 +- src/compiler/sema_casts.c | 27 +- src/compiler/sema_expr.c | 38 ++- src/compiler/sema_liveness.c | 1 + src/compiler/sema_stmts.c | 26 +- test/test_suite/expressions/plus_int.c3 | 7 + .../slices/slice_to_slice_assign.c3t | 85 +++--- .../slices/slice_to_slice_vector_assign.c3t | 85 +++--- test/test_suite/statements/foreach_common.c3t | 243 ++++++++---------- test/unit/regression/vector_ops.c3 | 2 + 18 files changed, 304 insertions(+), 387 deletions(-) diff --git a/releasenotes.md b/releasenotes.md index 809838f77..29b3b7265 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -54,6 +54,7 @@ - Prohibit raw vaargs in regular functions with a function body. - Assert on certain slice to slice casts. #1768. - Fix vector float -> bool conversion. +- Fix `+a = 1` erronously being accepted. ### Stdlib changes - Increase BitWriter.write_bits limit up to 32 bits. diff --git a/src/compiler/c_codegen.c b/src/compiler/c_codegen.c index 6e1638da6..487752014 100644 --- a/src/compiler/c_codegen.c +++ b/src/compiler/c_codegen.c @@ -396,6 +396,7 @@ static void c_emit_expr(GenContext *c, CValue *value, Expr *expr) switch (expr->expr_kind) { case EXPR_PTR_ACCESS: + case EXPR_SLICE_LEN: case EXPR_DISCARD: case EXPR_RVALUE: case EXPR_RECAST: diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 834a3886b..abe5e269d 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -3371,6 +3371,7 @@ static inline void expr_set_span(Expr *expr, SourceSpan loc) return; case EXPR_SPLAT: case EXPR_PTR_ACCESS: + case EXPR_SLICE_LEN: case EXPR_DISCARD: case EXPR_VECTOR_FROM_ARRAY: case EXPR_ADDR_CONVERSION: @@ -3606,6 +3607,7 @@ INLINE void expr_rewrite_recast(Expr *expr, Type *type) expr->type = type; } + INLINE void expr_rewrite_rvalue(Expr *expr, Type *type) { switch (expr->expr_kind) @@ -3716,12 +3718,23 @@ INLINE void expr_rewrite_const_typeid(Expr *expr, Type *type) expr->resolve_status = RESOLVE_DONE; } -INLINE void expr_rewrite_ptr_access(Expr *expr, Type *type) +INLINE void expr_rewrite_ptr_access(Expr *expr, Expr *inner, Type *type) { - Expr *inner = expr_copy(expr); + assert(inner->resolve_status == RESOLVE_DONE); expr->expr_kind = EXPR_PTR_ACCESS; expr->inner_expr = inner; expr->type = type; + expr->resolve_status = RESOLVE_DONE; +} + + +INLINE void expr_rewrite_slice_len(Expr *expr, Expr *inner, Type *type) +{ + assert(inner->resolve_status == RESOLVE_DONE); + expr->expr_kind = EXPR_SLICE_LEN; + expr->inner_expr = inner; + expr->type = type_add_optional(type, IS_OPTIONAL(inner)); + expr->resolve_status = RESOLVE_DONE; } INLINE void expr_rewrite_int_to_bool(Expr *expr, bool negate) diff --git a/src/compiler/copying.c b/src/compiler/copying.c index d5756d67c..b8f8d162f 100644 --- a/src/compiler/copying.c +++ b/src/compiler/copying.c @@ -476,6 +476,7 @@ Expr *copy_expr(CopyStruct *c, Expr *source_expr) case EXPR_SPLAT: case EXPR_STRINGIFY: case EXPR_PTR_ACCESS: + case EXPR_SLICE_LEN: case EXPR_DISCARD: case EXPR_VECTOR_FROM_ARRAY: case EXPR_RVALUE: diff --git a/src/compiler/enums.h b/src/compiler/enums.h index c08dfc458..b24e33c03 100644 --- a/src/compiler/enums.h +++ b/src/compiler/enums.h @@ -379,8 +379,6 @@ typedef enum BoolErr__ typedef enum { - ACCESS_LEN, - ACCESS_PTR, ACCESS_TYPEOFANY, ACCESS_TYPEOFANYFAULT, ACCESS_ENUMNAME, @@ -552,7 +550,6 @@ typedef enum CAST_EUER, CAST_FPFP, CAST_FPINT, - CAST_INTBOOL, CAST_INTENUM, CAST_INTFP, CAST_IDPTR, @@ -800,6 +797,7 @@ typedef enum EXPR_RVALUE, EXPR_RECAST, EXPR_SLICE, + EXPR_SLICE_LEN, EXPR_SLICE_ASSIGN, EXPR_SLICE_COPY, EXPR_SPLAT, diff --git a/src/compiler/expr.c b/src/compiler/expr.c index 9617882c9..bc5d74220 100644 --- a/src/compiler/expr.c +++ b/src/compiler/expr.c @@ -84,6 +84,7 @@ bool expr_may_addr(Expr *expr) case EXPR_TEST_HOOK: case EXPR_VECTOR_FROM_ARRAY: case EXPR_PTR_ACCESS: + case EXPR_SLICE_LEN: case EXPR_RVALUE: case EXPR_RECAST: case EXPR_DISCARD: @@ -194,6 +195,7 @@ bool expr_is_runtime_const(Expr *expr) case EXPR_BITACCESS: case EXPR_COND: case EXPR_PTR_ACCESS: + case EXPR_SLICE_LEN: return false; case EXPR_VECTOR_FROM_ARRAY: case EXPR_RVALUE: @@ -213,8 +215,6 @@ bool expr_is_runtime_const(Expr *expr) { case ACCESS_ENUMNAME: case ACCESS_FAULTNAME: - case ACCESS_LEN: - case ACCESS_PTR: case ACCESS_FAULTORDINAL: break; case ACCESS_TYPEOFANYFAULT: @@ -359,7 +359,6 @@ static inline bool expr_cast_is_runtime_const(Expr *expr) case CAST_EUER: case CAST_PTRBOOL: case CAST_BOOLFP: - case CAST_INTBOOL: case CAST_FPFP: case CAST_FPINT: case CAST_INTFP: @@ -609,6 +608,7 @@ bool expr_is_pure(Expr *expr) 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: + case EXPR_SLICE_LEN: case EXPR_DISCARD: case EXPR_VECTOR_FROM_ARRAY: case EXPR_RVALUE: diff --git a/src/compiler/json_output.c b/src/compiler/json_output.c index 25f8fd8d2..88aa5a4b0 100644 --- a/src/compiler/json_output.c +++ b/src/compiler/json_output.c @@ -268,6 +268,10 @@ void print_var_expr(FILE *file, Expr *expr) break; case EXPR_VECTOR_FROM_ARRAY: TODO + case EXPR_SLICE_LEN: + print_var_expr(file, expr->access_expr.parent); + fputs(".len", file); + break; case EXPR_PTR_ACCESS: print_var_expr(file, expr->access_expr.parent); fputs(".ptr", file); diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index 17aca4360..71c5f718e 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -709,17 +709,21 @@ static inline void llvm_emit_subscript_addr(GenContext *c, BEValue *value, Expr if (parent_type_kind == TYPE_SLICE) { needs_len = safe_mode_enabled() || start_from_end; + if (needs_len) + { + llvm_emit_slice_len(c, value, &len); + llvm_value_rvalue(c, &len); + } } - else if (parent_type_kind == TYPE_ARRAY) + else if (parent_type_kind == TYPE_ARRAY || parent_type_kind == TYPE_VECTOR) { // From back should always be folded. ASSERT0(!expr_is_const(expr) || !start_from_end); needs_len = (safe_mode_enabled() && !expr_is_const(expr)) || start_from_end; - } - if (needs_len) - { - llvm_emit_len_for_expr(c, &len, value); - llvm_value_rvalue(c, &len); + if (needs_len) + { + llvm_value_set_int(c, &len, type_isz, value->type->array.len); + } } llvm_emit_ptr_from_array(c, value); @@ -1476,11 +1480,6 @@ void llvm_emit_cast(GenContext *c, CastKind cast_kind, Expr *expr, BEValue *valu value->value = LLVMBuildUIToFP(c->builder, value->value, llvm_get_type(c, to_type), "boolfp"); value->kind = BE_VALUE; break; - case CAST_INTBOOL: - llvm_value_rvalue(c, value); - value->value = LLVMBuildICmp(c->builder, LLVMIntNE, value->value, llvm_get_zero(c, from_type), "intbool"); - value->kind = type_kind_is_any_vector(value->type->type_kind) ? BE_BOOLVECTOR : BE_BOOLEAN; - break; case CAST_FPFP: llvm_value_rvalue(c, value); value->value = type_convert_will_trunc(to_type, from_type) @@ -1542,22 +1541,7 @@ void llvm_emit_cast(GenContext *c, CastKind cast_kind, Expr *expr, BEValue *valu value->type = type_lowering(to_type); return; case CAST_SLBOOL: - llvm_value_fold_optional(c, value); - if (llvm_value_is_addr(value)) - { - value->value = llvm_emit_struct_gep_raw(c, - value->value, - llvm_get_type(c, value->type), - 1, - value->alignment, - &value->alignment); - } - else - { - value->value = llvm_emit_extract_value(c, value->value, 1); - } - value->type = type_lowering(type_usz); - llvm_value_rvalue(c, value); + llvm_emit_slice_len(c, value, value); llvm_emit_int_comp_zero(c, value, value, BINARYOP_NE); break; } @@ -2749,54 +2733,8 @@ static void llvm_emit_unary_expr(GenContext *c, BEValue *value, Expr *expr) llvm_value_set(value, llvm_value, res_type); return; } - switch (type->type_kind) - { - case ALL_FLOATS: - llvm_value_rvalue(c, value); - llvm_value = LLVMBuildFCmp(c->builder, LLVMRealUEQ, value->value, llvm_get_zero(c, type), "not"); - break; - case TYPE_BOOL: - llvm_value_rvalue(c, value); - llvm_value = LLVMBuildNot(c->builder, value->value, "not"); - break; - case TYPE_SLICE: - if (value->kind != BE_VALUE) - { - llvm_emit_len_for_expr(c, value, value); - llvm_value_rvalue(c, value); - llvm_value = value->value; - } - else - { - llvm_value = llvm_emit_extract_value(c, value->value, 1); - } - llvm_value = LLVMBuildIsNull(c->builder, llvm_value, "not"); - break; - case ALL_INTS: - case TYPE_FUNC_PTR: - case TYPE_POINTER: - llvm_value_rvalue(c, value); - llvm_value = LLVMBuildIsNull(c->builder, value->value, "not"); - break; - case TYPE_ANY: - case TYPE_INTERFACE: - llvm_emit_any_pointer(c, value, value); - llvm_value_rvalue(c, value); - llvm_value = LLVMBuildIsNull(c->builder, value->value, "not"); - break; - case TYPE_ARRAY: - // Handle the bitstruct to bool case. - if (type->array.base == type_char) - { - llvm_value = llvm_emit_char_array_zero(c, value, true); - break; - } - FALLTHROUGH; - default: - DEBUG_LOG("Unexpectedly tried to not %s", type_quoted_error_string(inner->type)); - UNREACHABLE - } - llvm_value_set(value, llvm_value, type_bool); + llvm_value_rvalue(c, value); + value->value = LLVMBuildNot(c->builder, value->value, "not"); return; case UNARYOP_BITNEG: llvm_emit_expr(c, value, inner); @@ -2865,37 +2803,6 @@ static void llvm_emit_unary_expr(GenContext *c, BEValue *value, Expr *expr) UNREACHABLE } -void llvm_emit_len_for_expr(GenContext *c, BEValue *be_value, BEValue *expr_to_len) -{ - switch (expr_to_len->type->type_kind) - { - case TYPE_SLICE: - llvm_value_fold_optional(c, be_value); - if (expr_to_len->kind == BE_VALUE) - { - llvm_value_set(be_value, llvm_emit_extract_value(c, expr_to_len->value, 1), type_usz); - } - else - { - LLVMTypeRef slice_type = llvm_get_type(c, expr_to_len->type); - AlignSize alignment; - LLVMValueRef len_addr = llvm_emit_struct_gep_raw(c, - expr_to_len->value, - slice_type, - 1, - expr_to_len->alignment, - &alignment); - llvm_value_set_address(be_value, len_addr, type_usz, alignment); - } - break; - case TYPE_ARRAY: - case TYPE_VECTOR: - llvm_value_set(be_value, llvm_const_int(c, type_usz, expr_to_len->type->array.len), type_usz); - break; - default: - UNREACHABLE - } -} static void llvm_emit_trap_negative(GenContext *c, Expr *expr, LLVMValueRef value, const char *error, BEValue *index_val) @@ -5448,7 +5355,11 @@ LLVMValueRef llvm_emit_const_ptradd_inbounds_raw(GenContext *c, LLVMValueRef ptr void llvm_emit_slice_len(GenContext *c, BEValue *slice, BEValue *len) { - llvm_value_addr(c, slice); + if (!llvm_value_is_addr(slice)) + { + llvm_value_set(len, llvm_emit_extract_value(c, slice->value, 1), type_usz); + return; + } AlignSize alignment = 0; LLVMValueRef len_addr = llvm_emit_struct_gep_raw(c, slice->value, @@ -7092,18 +7003,6 @@ static inline void llvm_emit_builtin_access(GenContext *c, BEValue *be_value, Ex llvm_value_fold_optional(c, be_value); switch (expr->builtin_access_expr.kind) { - case ACCESS_LEN: - llvm_emit_len_for_expr(c, be_value, be_value); - return; - case ACCESS_PTR: - if (type_is_any(be_value->type)) - { - llvm_emit_any_pointer(c, be_value, be_value); - return; - } - ASSERT0(be_value->type->type_kind == TYPE_SLICE); - llvm_emit_slice_pointer(c, be_value, be_value); - return; case ACCESS_FAULTORDINAL: { LLVMBasicBlockRef current_block = llvm_get_current_block_if_in_use(c); @@ -7418,6 +7317,10 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr) case EXPR_VECTOR_FROM_ARRAY: llvm_emit_vector_from_array(c, value, expr); return; + case EXPR_SLICE_LEN: + llvm_emit_expr(c, value, expr->inner_expr); + llvm_emit_slice_len(c, value, value); + return; case EXPR_PTR_ACCESS: llvm_emit_ptr_access(c, value, expr); return; diff --git a/src/compiler/llvm_codegen_internal.h b/src/compiler/llvm_codegen_internal.h index 8fa687d5a..435f207c8 100644 --- a/src/compiler/llvm_codegen_internal.h +++ b/src/compiler/llvm_codegen_internal.h @@ -541,7 +541,7 @@ BEValue llvm_emit_assign_expr(GenContext *c, BEValue *ref, Expr *expr, LLVMValue INLINE void llvm_emit_exprid(GenContext *c, BEValue *value, ExprId expr); INLINE void llvm_emit_statement_chain(GenContext *c, AstId current); void llvm_emit_initialize_reference_temporary_const(GenContext *c, BEValue *ref, ConstInitializer *initializer); -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, Expr *expr, BEValue *value, Type *to_type, Type *from_type); diff --git a/src/compiler/sema_casts.c b/src/compiler/sema_casts.c index dc06696d6..71baebbb3 100644 --- a/src/compiler/sema_casts.c +++ b/src/compiler/sema_casts.c @@ -345,6 +345,9 @@ Expr *recursive_may_narrow(Expr *expr, Type *type) RETRY: switch (expr->expr_kind) { + case EXPR_RECAST: + expr = expr->inner_expr; + goto RETRY; case EXPR_BITASSIGN: case EXPR_BINARY: switch (expr->binary_expr.operator) @@ -409,14 +412,12 @@ RETRY: } UNREACHABLE + case EXPR_SLICE_LEN: + if (type_size(type) < type_size(type_cint)) return expr; + return NULL; case EXPR_BUILTIN_ACCESS: switch (expr->builtin_access_expr.kind) { - case ACCESS_LEN: - // Special: we may resize this, but not smaller than cint. - if (type_size(type) < type_size(type_cint)) return expr; - return NULL; - case ACCESS_PTR: case ACCESS_TYPEOFANYFAULT: case ACCESS_TYPEOFANY: case ACCESS_ENUMNAME: @@ -1439,10 +1440,10 @@ static void cast_typeid_to_int(SemaContext *context, Expr *expr, Type *type) { e static void cast_fault_to_int(SemaContext *context, Expr *expr, Type *type) { cast_typeid_to_int(context, expr, type); } static void cast_typeid_to_ptr(SemaContext *context, Expr *expr, Type *type) { insert_runtime_cast(expr, CAST_IDPTR, type); } static void cast_any_to_bool(SemaContext *context, Expr *expr, Type *type) { - expr_rewrite_ptr_access(expr, type_voidptr); + expr_rewrite_ptr_access(expr, expr_copy(expr), type_voidptr); expr_rewrite_int_to_bool(expr, false); } -static void cast_any_to_ptr(SemaContext *context, Expr *expr, Type *type) { expr_rewrite_ptr_access(expr, type); } +static void cast_any_to_ptr(SemaContext *context, Expr *expr, Type *type) { expr_rewrite_ptr_access(expr, expr_copy(expr), type); } 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; } @@ -1758,8 +1759,14 @@ static void cast_vec_to_vec(SemaContext *context, Expr *expr, Type *to_type) insert_runtime_cast(expr, CAST_INTFP, to_type); return; case TYPE_BOOL: - insert_runtime_cast(expr, CAST_INTBOOL, to_type); + { + Expr *left = expr_copy(expr); + Expr *right = expr_new_expr(EXPR_CONST, expr); + expr_rewrite_to_const_zero(right, left->type); + expr_rewrite_to_binary(expr, left, right, BINARYOP_VEC_NE); + expr->type = to_type; return; + } case ALL_INTS: expr_rewrite_ext_trunc(expr, to_type, type_is_signed(type_flatten_to_int(expr->type))); return; @@ -1834,7 +1841,7 @@ static void cast_slice_to_ptr(SemaContext *context, Expr *expr, Type *type) return; } - expr_rewrite_ptr_access(expr, type); + expr_rewrite_ptr_access(expr, expr_copy(expr), type); } /** @@ -1987,8 +1994,6 @@ static void cast_slice_to_bool(SemaContext *context, Expr *expr, Type *type) */ static void cast_slice_to_slice(SemaContext *context, Expr *expr, Type *to_type) { - Type *to_type_base = type_flatten(type_flatten(to_type)->array.base); - Type *from_type_base = type_flatten(type_flatten(expr->type)->array.base); if (sema_cast_const(expr)) { expr->type = to_type; diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 0ed34cff7..1cb92e1ed 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -559,6 +559,7 @@ static bool sema_binary_is_expr_lvalue(SemaContext *context, Expr *top_expr, Exp case EXPR_POINTER_OFFSET: case EXPR_POST_UNARY: case EXPR_PTR_ACCESS: + case EXPR_SLICE_LEN: case EXPR_RECAST: case EXPR_RETHROW: case EXPR_RETVAL: @@ -605,6 +606,7 @@ static bool expr_may_ref(Expr *expr) case EXPR_MEMBER_GET: case EXPR_EXT_TRUNC: case EXPR_PTR_ACCESS: + case EXPR_SLICE_LEN: case EXPR_VECTOR_FROM_ARRAY: case EXPR_INT_TO_BOOL: case EXPR_RVALUE: @@ -4997,7 +4999,7 @@ CHECK_DEEPER: expr_rewrite_const_int(expr, type_isz, parent->const_expr.bytes.len); return true; } - expr_rewrite_to_builtin_access(expr, current_parent, ACCESS_LEN, type_usz); + expr_rewrite_slice_len(expr, parent, type_usz); return true; } if (flat_type->type_kind == TYPE_ARRAY || flat_type->type_kind == TYPE_VECTOR) @@ -5035,12 +5037,12 @@ CHECK_DEEPER: { if (flat_type->type_kind == TYPE_SLICE) { - expr_rewrite_to_builtin_access(expr, current_parent, ACCESS_PTR, type_get_ptr(flat_type->array.base)); + expr_rewrite_ptr_access(expr, current_parent, type_get_ptr(flat_type->array.base)); return true; } if (type_is_any_raw(flat_type)) { - expr_rewrite_to_builtin_access(expr, current_parent, ACCESS_PTR, type_voidptr); + expr_rewrite_ptr_access(expr, current_parent, type_voidptr); return true; } } @@ -7064,20 +7066,25 @@ static inline bool sema_expr_analyse_neg_plus(SemaContext *context, Expr *expr) { if (is_plus) { - SEMA_ERROR(expr, "Cannot use '+' with an expression of type %s.", type_quoted_error_string(no_fail)); - return false; + RETURN_SEMA_ERROR(expr, "Cannot use '+' with an expression of type %s.", type_quoted_error_string(no_fail)); } - SEMA_ERROR(expr, "Cannot negate an expression of type %s.", type_quoted_error_string(no_fail)); - return false; + RETURN_SEMA_ERROR(expr, "Cannot negate an expression of type %s.", type_quoted_error_string(no_fail)); } // 3. Promote the type Type *result_type = cast_numeric_arithmetic_promotion(no_fail); if (!cast_implicit(context, inner, result_type, false)) return false; - // If it's a plus, we simply replace the inner with the outer. + // If it's a plus, we simply replace the inner with the outer or with a recast. if (is_plus) { - expr_replace(expr, inner); + if (expr_is_const(expr)) + { + expr_replace(expr, inner); + return true; + } + expr->expr_kind = EXPR_RECAST; + expr->inner_expr = inner; + expr->type = inner->type; return true; } // 4. If it's non-const, we're done. @@ -8981,6 +8988,7 @@ static inline bool sema_expr_analyse_ct_defined(SemaContext *context, Expr *expr case EXPR_EXT_TRUNC: case EXPR_INT_TO_BOOL: case EXPR_PTR_ACCESS: + case EXPR_SLICE_LEN: case EXPR_VECTOR_FROM_ARRAY: case EXPR_RVALUE: case EXPR_RECAST: @@ -9378,6 +9386,7 @@ static inline bool sema_analyse_expr_dispatch(SemaContext *context, Expr *expr, case EXPR_DISCARD: return sema_analyse_expr(context, expr->inner_expr); case EXPR_PTR_ACCESS: + case EXPR_SLICE_LEN: case EXPR_VECTOR_FROM_ARRAY: return sema_analyse_expr(context, expr->inner_expr); case EXPR_INT_TO_BOOL: @@ -9822,13 +9831,16 @@ bool sema_analyse_expr(SemaContext *context, Expr *expr) bool sema_cast_const(Expr *expr) { - if (expr->resolve_status != RESOLVE_DONE) - { - puts("Tesst"); - } ASSERT_SPAN(expr, expr->resolve_status == RESOLVE_DONE); switch (expr->expr_kind) { + case EXPR_RECAST: + if (sema_cast_const(expr->inner_expr)) + { + expr_replace(expr, expr->inner_expr); + return true; + } + return false; case EXPR_ACCESS: case EXPR_BITACCESS: { diff --git a/src/compiler/sema_liveness.c b/src/compiler/sema_liveness.c index 3e62e0aef..0d22eb44b 100644 --- a/src/compiler/sema_liveness.c +++ b/src/compiler/sema_liveness.c @@ -330,6 +330,7 @@ RETRY: case EXPR_RETHROW: case EXPR_OPTIONAL: case EXPR_PTR_ACCESS: + case EXPR_SLICE_LEN: 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 bee8d417d..d98c76db1 100644 --- a/src/compiler/sema_stmts.c +++ b/src/compiler/sema_stmts.c @@ -765,6 +765,7 @@ static inline bool sema_expr_valid_try_expression(Expr *expr) case EXPR_EXT_TRUNC: case EXPR_INT_TO_BOOL: case EXPR_PTR_ACCESS: + case EXPR_SLICE_LEN: case EXPR_VECTOR_FROM_ARRAY: case EXPR_RVALUE: case EXPR_RECAST: @@ -1622,19 +1623,20 @@ SKIP_OVERLOAD:; } else { - if (enumerator_type->type_kind == TYPE_ARRAY) + switch (enumerator_type->type_kind) { - array_len = enumerator_type->array.len; - len_call = NULL; - } - else - { - len_call = expr_new(EXPR_BUILTIN_ACCESS, enumerator->span); - if (!sema_analyse_expr(context, enum_val)) return false; - len_call->builtin_access_expr.inner = exprid(enum_val); - len_call->builtin_access_expr.kind = ACCESS_LEN; - len_call->resolve_status = RESOLVE_DONE; - len_call->type = type_isz; + case TYPE_ARRAY: + case TYPE_VECTOR: + array_len = enumerator_type->array.len; + len_call = NULL; + break; + case TYPE_SLICE: + if (!sema_analyse_expr(context, enum_val)) return false; + len_call = expr_new_expr(EXPR_SLICE_LEN, enumerator); + expr_rewrite_slice_len(len_call, enum_val, type_isz); + break; + default: + UNREACHABLE } } bool is_single_pass = array_len == 1; diff --git a/test/test_suite/expressions/plus_int.c3 b/test/test_suite/expressions/plus_int.c3 index f29a78c09..7ebebcf46 100644 --- a/test/test_suite/expressions/plus_int.c3 +++ b/test/test_suite/expressions/plus_int.c3 @@ -18,3 +18,10 @@ fn void test3() @ok(+a); long b = +a; // #error: 'long!' to 'long' } + + +fn void test4() +{ + int a = 1; + +a = 3; // #error: An assignable expression +} \ No newline at end of file diff --git a/test/test_suite/slices/slice_to_slice_assign.c3t b/test/test_suite/slices/slice_to_slice_assign.c3t index 8f4412060..e0240bc94 100644 --- a/test/test_suite/slices/slice_to_slice_assign.c3t +++ b/test/test_suite/slices/slice_to_slice_assign.c3t @@ -24,25 +24,22 @@ define void @test.main() #0 { entry: %z = alloca [7 x i32], align 16 %y = alloca [6 x i32], align 16 - %taddr = alloca %"int[]", align 8 %varargslots = alloca [2 x %any], align 16 %retparam = alloca i64, align 8 - %taddr6 = alloca %"int[]", align 8 - %varargslots8 = alloca [2 x %any], align 16 - %retparam10 = alloca i64, align 8 + %varargslots5 = alloca [2 x %any], align 16 + %retparam7 = alloca i64, align 8 %a = alloca %"int[][]", align 8 %literal = alloca [1 x %"int[]"], align 16 - %literal11 = alloca [1 x i32], align 4 + %literal8 = alloca [1 x i32], align 4 %b = alloca %"int[][]", align 8 - %literal12 = alloca [1 x %"int[]"], align 16 - %literal13 = alloca [1 x i32], align 4 - %varargslots14 = alloca [1 x %any], align 16 - %retparam15 = alloca i64, align 8 - %taddr16 = alloca %"int[][]", align 8 - %varargslots18 = alloca [1 x %any], align 16 - %retparam19 = alloca i64, align 8 - %varargslots21 = alloca [1 x %any], align 16 - %retparam22 = alloca i64, align 8 + %literal9 = alloca [1 x %"int[]"], align 16 + %literal10 = alloca [1 x i32], align 4 + %varargslots11 = alloca [1 x %any], align 16 + %retparam12 = alloca i64, align 8 + %varargslots13 = alloca [1 x %any], align 16 + %retparam14 = alloca i64, align 8 + %varargslots16 = alloca [1 x %any], align 16 + %retparam17 = alloca i64, align 8 call void @llvm.memcpy.p0.p0.i32(ptr align 16 %z, ptr align 16 @.__const, i32 28, i1 false) call void @llvm.memset.p0.i64(ptr align 16 %y, i8 0, i64 24, i1 false) %ptradd = getelementptr inbounds i8, ptr %z, i64 12 @@ -53,9 +50,7 @@ entry: %3 = insertvalue %"int[]" %2, i64 3, 1 %4 = extractvalue %"int[]" %3, 0 %5 = extractvalue %"int[]" %1, 0 - store %"int[]" %1, ptr %taddr, align 8 - %ptradd2 = getelementptr inbounds i8, ptr %taddr, i64 8 - %6 = load i64, ptr %ptradd2, align 8 + %6 = extractvalue %"int[]" %1, 1 %7 = mul i64 %6, 4 call void @llvm.memmove.p0.p0.i64(ptr align 4 %4, ptr align 4 %5, i64 %7, i1 false) %8 = insertvalue %any undef, ptr %y, 0 @@ -63,48 +58,46 @@ entry: store %any %9, ptr %varargslots, align 16 %10 = insertvalue %any undef, ptr %z, 0 %11 = insertvalue %any %10, i64 ptrtoint (ptr @"$ct.a7$int" to i64), 1 - %ptradd3 = getelementptr inbounds i8, ptr %varargslots, i64 16 - store %any %11, ptr %ptradd3, align 16 + %ptradd2 = getelementptr inbounds i8, ptr %varargslots, i64 16 + store %any %11, ptr %ptradd2, align 16 %12 = call i64 @std.io.printfn(ptr %retparam, ptr @.str, i64 5, ptr %varargslots, i64 2) - %ptradd4 = getelementptr inbounds i8, ptr %z, i64 20 - %13 = insertvalue %"int[]" undef, ptr %ptradd4, 0 + %ptradd3 = getelementptr inbounds i8, ptr %z, i64 20 + %13 = insertvalue %"int[]" undef, ptr %ptradd3, 0 %14 = insertvalue %"int[]" %13, i64 2, 1 - %ptradd5 = getelementptr inbounds i8, ptr %y, i64 16 - %15 = insertvalue %"int[]" undef, ptr %ptradd5, 0 + %ptradd4 = getelementptr inbounds i8, ptr %y, i64 16 + %15 = insertvalue %"int[]" undef, ptr %ptradd4, 0 %16 = insertvalue %"int[]" %15, i64 2, 1 %17 = extractvalue %"int[]" %16, 0 %18 = extractvalue %"int[]" %14, 0 - store %"int[]" %14, ptr %taddr6, align 8 - %ptradd7 = getelementptr inbounds i8, ptr %taddr6, i64 8 - %19 = load i64, ptr %ptradd7, align 8 + %19 = extractvalue %"int[]" %14, 1 %20 = mul i64 %19, 4 call void @llvm.memmove.p0.p0.i64(ptr align 4 %17, ptr align 4 %18, i64 %20, i1 false) %21 = insertvalue %any undef, ptr %y, 0 %22 = insertvalue %any %21, i64 ptrtoint (ptr @"$ct.a6$int" to i64), 1 - store %any %22, ptr %varargslots8, align 16 + store %any %22, ptr %varargslots5, align 16 %23 = insertvalue %any undef, ptr %z, 0 %24 = insertvalue %any %23, i64 ptrtoint (ptr @"$ct.a7$int" to i64), 1 - %ptradd9 = getelementptr inbounds i8, ptr %varargslots8, i64 16 - store %any %24, ptr %ptradd9, align 16 - %25 = call i64 @std.io.printfn(ptr %retparam10, ptr @.str.1, i64 5, ptr %varargslots8, i64 2) - call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal11, ptr align 4 @.__const.2, i32 4, i1 false) - %26 = insertvalue %"int[]" undef, ptr %literal11, 0 + %ptradd6 = getelementptr inbounds i8, ptr %varargslots5, i64 16 + store %any %24, ptr %ptradd6, align 16 + %25 = call i64 @std.io.printfn(ptr %retparam7, ptr @.str.1, i64 5, ptr %varargslots5, i64 2) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal8, ptr align 4 @.__const.2, i32 4, i1 false) + %26 = insertvalue %"int[]" undef, ptr %literal8, 0 %27 = insertvalue %"int[]" %26, i64 1, 1 store %"int[]" %27, ptr %literal, align 8 %28 = insertvalue %"int[][]" undef, ptr %literal, 0 %29 = insertvalue %"int[][]" %28, i64 1, 1 store %"int[][]" %29, ptr %a, align 8 - call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal13, ptr align 4 @.__const.3, i32 4, i1 false) - %30 = insertvalue %"int[]" undef, ptr %literal13, 0 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal10, ptr align 4 @.__const.3, i32 4, i1 false) + %30 = insertvalue %"int[]" undef, ptr %literal10, 0 %31 = insertvalue %"int[]" %30, i64 1, 1 - store %"int[]" %31, ptr %literal12, align 8 - %32 = insertvalue %"int[][]" undef, ptr %literal12, 0 + store %"int[]" %31, ptr %literal9, align 8 + %32 = insertvalue %"int[][]" undef, ptr %literal9, 0 %33 = insertvalue %"int[][]" %32, i64 1, 1 store %"int[][]" %33, ptr %b, align 8 %34 = insertvalue %any undef, ptr %a, 0 %35 = insertvalue %any %34, i64 ptrtoint (ptr @"$ct.sa$sa$int" to i64), 1 - store %any %35, ptr %varargslots14, align 16 - %36 = call i64 @std.io.printfn(ptr %retparam15, ptr @.str.4, i64 2, ptr %varargslots14, i64 1) + store %any %35, ptr %varargslots11, align 16 + %36 = call i64 @std.io.printfn(ptr %retparam12, ptr @.str.4, i64 2, ptr %varargslots11, i64 1) %37 = load %"int[][]", ptr %b, align 8 %38 = extractvalue %"int[][]" %37, 0 %39 = insertvalue %"int[][]" undef, ptr %38, 0 @@ -115,24 +108,22 @@ entry: %44 = insertvalue %"int[][]" %43, i64 1, 1 %45 = extractvalue %"int[][]" %44, 0 %46 = extractvalue %"int[][]" %40, 0 - store %"int[][]" %40, ptr %taddr16, align 8 - %ptradd17 = getelementptr inbounds i8, ptr %taddr16, i64 8 - %47 = load i64, ptr %ptradd17, align 8 + %47 = extractvalue %"int[][]" %40, 1 %48 = mul i64 %47, 16 call void @llvm.memmove.p0.p0.i64(ptr align 8 %45, ptr align 8 %46, i64 %48, i1 false) %49 = insertvalue %any undef, ptr %a, 0 %50 = insertvalue %any %49, i64 ptrtoint (ptr @"$ct.sa$sa$int" to i64), 1 - store %any %50, ptr %varargslots18, align 16 - %51 = call i64 @std.io.printfn(ptr %retparam19, ptr @.str.5, i64 2, ptr %varargslots18, i64 1) - %ptradd20 = getelementptr inbounds i8, ptr %y, i64 8 - %52 = insertvalue %"int[]" undef, ptr %ptradd20, 0 + store %any %50, ptr %varargslots13, align 16 + %51 = call i64 @std.io.printfn(ptr %retparam14, ptr @.str.5, i64 2, ptr %varargslots13, i64 1) + %ptradd15 = getelementptr inbounds i8, ptr %y, i64 8 + %52 = insertvalue %"int[]" undef, ptr %ptradd15, 0 %53 = insertvalue %"int[]" %52, i64 3, 1 %54 = load %"int[][]", ptr %a, align 8 %55 = extractvalue %"int[][]" %54, 0 store %"int[]" %53, ptr %55, align 8 %56 = insertvalue %any undef, ptr %a, 0 %57 = insertvalue %any %56, i64 ptrtoint (ptr @"$ct.sa$sa$int" to i64), 1 - store %any %57, ptr %varargslots21, align 16 - %58 = call i64 @std.io.printfn(ptr %retparam22, ptr @.str.6, i64 2, ptr %varargslots21, i64 1) + store %any %57, ptr %varargslots16, align 16 + %58 = call i64 @std.io.printfn(ptr %retparam17, ptr @.str.6, i64 2, ptr %varargslots16, i64 1) ret void } diff --git a/test/test_suite/slices/slice_to_slice_vector_assign.c3t b/test/test_suite/slices/slice_to_slice_vector_assign.c3t index a2bbb8494..077065740 100644 --- a/test/test_suite/slices/slice_to_slice_vector_assign.c3t +++ b/test/test_suite/slices/slice_to_slice_vector_assign.c3t @@ -25,25 +25,22 @@ define void @test.main() #0 { entry: %z = alloca <7 x i32>, align 32 %y = alloca <6 x i32>, align 32 - %taddr = alloca %"int[]", align 8 %varargslots = alloca [2 x %any], align 16 %retparam = alloca i64, align 8 - %taddr6 = alloca %"int[]", align 8 - %varargslots8 = alloca [2 x %any], align 16 - %retparam10 = alloca i64, align 8 + %varargslots5 = alloca [2 x %any], align 16 + %retparam7 = alloca i64, align 8 %a = alloca %"int[][]", align 8 %literal = alloca [1 x %"int[]"], align 16 - %literal11 = alloca [1 x i32], align 4 + %literal8 = alloca [1 x i32], align 4 %b = alloca %"int[][]", align 8 - %literal12 = alloca [1 x %"int[]"], align 16 - %literal13 = alloca [1 x i32], align 4 - %varargslots14 = alloca [1 x %any], align 16 - %retparam15 = alloca i64, align 8 - %taddr16 = alloca %"int[][]", align 8 - %varargslots18 = alloca [1 x %any], align 16 - %retparam19 = alloca i64, align 8 - %varargslots21 = alloca [1 x %any], align 16 - %retparam22 = alloca i64, align 8 + %literal9 = alloca [1 x %"int[]"], align 16 + %literal10 = alloca [1 x i32], align 4 + %varargslots11 = alloca [1 x %any], align 16 + %retparam12 = alloca i64, align 8 + %varargslots13 = alloca [1 x %any], align 16 + %retparam14 = alloca i64, align 8 + %varargslots16 = alloca [1 x %any], align 16 + %retparam17 = alloca i64, align 8 store <7 x i32> , ptr %z, align 32 store <6 x i32> zeroinitializer, ptr %y, align 32 %ptradd = getelementptr inbounds i8, ptr %z, i64 12 @@ -54,9 +51,7 @@ entry: %3 = insertvalue %"int[]" %2, i64 3, 1 %4 = extractvalue %"int[]" %3, 0 %5 = extractvalue %"int[]" %1, 0 - store %"int[]" %1, ptr %taddr, align 8 - %ptradd2 = getelementptr inbounds i8, ptr %taddr, i64 8 - %6 = load i64, ptr %ptradd2, align 8 + %6 = extractvalue %"int[]" %1, 1 %7 = mul i64 %6, 4 call void @llvm.memmove.p0.p0.i64(ptr align 4 %4, ptr align 4 %5, i64 %7, i1 false) %8 = insertvalue %any undef, ptr %y, 0 @@ -64,48 +59,46 @@ entry: store %any %9, ptr %varargslots, align 16 %10 = insertvalue %any undef, ptr %z, 0 %11 = insertvalue %any %10, i64 ptrtoint (ptr @"$ct.v7$int" to i64), 1 - %ptradd3 = getelementptr inbounds i8, ptr %varargslots, i64 16 - store %any %11, ptr %ptradd3, align 16 + %ptradd2 = getelementptr inbounds i8, ptr %varargslots, i64 16 + store %any %11, ptr %ptradd2, align 16 %12 = call i64 @std.io.printfn(ptr %retparam, ptr @.str, i64 5, ptr %varargslots, i64 2) - %ptradd4 = getelementptr inbounds i8, ptr %z, i64 20 - %13 = insertvalue %"int[]" undef, ptr %ptradd4, 0 + %ptradd3 = getelementptr inbounds i8, ptr %z, i64 20 + %13 = insertvalue %"int[]" undef, ptr %ptradd3, 0 %14 = insertvalue %"int[]" %13, i64 2, 1 - %ptradd5 = getelementptr inbounds i8, ptr %y, i64 16 - %15 = insertvalue %"int[]" undef, ptr %ptradd5, 0 + %ptradd4 = getelementptr inbounds i8, ptr %y, i64 16 + %15 = insertvalue %"int[]" undef, ptr %ptradd4, 0 %16 = insertvalue %"int[]" %15, i64 2, 1 %17 = extractvalue %"int[]" %16, 0 %18 = extractvalue %"int[]" %14, 0 - store %"int[]" %14, ptr %taddr6, align 8 - %ptradd7 = getelementptr inbounds i8, ptr %taddr6, i64 8 - %19 = load i64, ptr %ptradd7, align 8 + %19 = extractvalue %"int[]" %14, 1 %20 = mul i64 %19, 4 call void @llvm.memmove.p0.p0.i64(ptr align 4 %17, ptr align 4 %18, i64 %20, i1 false) %21 = insertvalue %any undef, ptr %y, 0 %22 = insertvalue %any %21, i64 ptrtoint (ptr @"$ct.v6$int" to i64), 1 - store %any %22, ptr %varargslots8, align 16 + store %any %22, ptr %varargslots5, align 16 %23 = insertvalue %any undef, ptr %z, 0 %24 = insertvalue %any %23, i64 ptrtoint (ptr @"$ct.v7$int" to i64), 1 - %ptradd9 = getelementptr inbounds i8, ptr %varargslots8, i64 16 - store %any %24, ptr %ptradd9, align 16 - %25 = call i64 @std.io.printfn(ptr %retparam10, ptr @.str.1, i64 5, ptr %varargslots8, i64 2) - call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal11, ptr align 4 @.__const, i32 4, i1 false) - %26 = insertvalue %"int[]" undef, ptr %literal11, 0 + %ptradd6 = getelementptr inbounds i8, ptr %varargslots5, i64 16 + store %any %24, ptr %ptradd6, align 16 + %25 = call i64 @std.io.printfn(ptr %retparam7, ptr @.str.1, i64 5, ptr %varargslots5, i64 2) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal8, ptr align 4 @.__const, i32 4, i1 false) + %26 = insertvalue %"int[]" undef, ptr %literal8, 0 %27 = insertvalue %"int[]" %26, i64 1, 1 store %"int[]" %27, ptr %literal, align 8 %28 = insertvalue %"int[][]" undef, ptr %literal, 0 %29 = insertvalue %"int[][]" %28, i64 1, 1 store %"int[][]" %29, ptr %a, align 8 - call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal13, ptr align 4 @.__const.2, i32 4, i1 false) - %30 = insertvalue %"int[]" undef, ptr %literal13, 0 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal10, ptr align 4 @.__const.2, i32 4, i1 false) + %30 = insertvalue %"int[]" undef, ptr %literal10, 0 %31 = insertvalue %"int[]" %30, i64 1, 1 - store %"int[]" %31, ptr %literal12, align 8 - %32 = insertvalue %"int[][]" undef, ptr %literal12, 0 + store %"int[]" %31, ptr %literal9, align 8 + %32 = insertvalue %"int[][]" undef, ptr %literal9, 0 %33 = insertvalue %"int[][]" %32, i64 1, 1 store %"int[][]" %33, ptr %b, align 8 %34 = insertvalue %any undef, ptr %a, 0 %35 = insertvalue %any %34, i64 ptrtoint (ptr @"$ct.sa$sa$int" to i64), 1 - store %any %35, ptr %varargslots14, align 16 - %36 = call i64 @std.io.printfn(ptr %retparam15, ptr @.str.3, i64 2, ptr %varargslots14, i64 1) + store %any %35, ptr %varargslots11, align 16 + %36 = call i64 @std.io.printfn(ptr %retparam12, ptr @.str.3, i64 2, ptr %varargslots11, i64 1) %37 = load %"int[][]", ptr %b, align 8 %38 = extractvalue %"int[][]" %37, 0 %39 = insertvalue %"int[][]" undef, ptr %38, 0 @@ -116,24 +109,22 @@ entry: %44 = insertvalue %"int[][]" %43, i64 1, 1 %45 = extractvalue %"int[][]" %44, 0 %46 = extractvalue %"int[][]" %40, 0 - store %"int[][]" %40, ptr %taddr16, align 8 - %ptradd17 = getelementptr inbounds i8, ptr %taddr16, i64 8 - %47 = load i64, ptr %ptradd17, align 8 + %47 = extractvalue %"int[][]" %40, 1 %48 = mul i64 %47, 16 call void @llvm.memmove.p0.p0.i64(ptr align 8 %45, ptr align 8 %46, i64 %48, i1 false) %49 = insertvalue %any undef, ptr %a, 0 %50 = insertvalue %any %49, i64 ptrtoint (ptr @"$ct.sa$sa$int" to i64), 1 - store %any %50, ptr %varargslots18, align 16 - %51 = call i64 @std.io.printfn(ptr %retparam19, ptr @.str.4, i64 2, ptr %varargslots18, i64 1) - %ptradd20 = getelementptr inbounds i8, ptr %y, i64 8 - %52 = insertvalue %"int[]" undef, ptr %ptradd20, 0 + store %any %50, ptr %varargslots13, align 16 + %51 = call i64 @std.io.printfn(ptr %retparam14, ptr @.str.4, i64 2, ptr %varargslots13, i64 1) + %ptradd15 = getelementptr inbounds i8, ptr %y, i64 8 + %52 = insertvalue %"int[]" undef, ptr %ptradd15, 0 %53 = insertvalue %"int[]" %52, i64 3, 1 %54 = load %"int[][]", ptr %a, align 8 %55 = extractvalue %"int[][]" %54, 0 store %"int[]" %53, ptr %55, align 8 %56 = insertvalue %any undef, ptr %a, 0 %57 = insertvalue %any %56, i64 ptrtoint (ptr @"$ct.sa$sa$int" to i64), 1 - store %any %57, ptr %varargslots21, align 16 - %58 = call i64 @std.io.printfn(ptr %retparam22, ptr @.str.5, i64 2, ptr %varargslots21, i64 1) + store %any %57, ptr %varargslots16, align 16 + %58 = call i64 @std.io.printfn(ptr %retparam17, ptr @.str.5, i64 2, ptr %varargslots16, i64 1) ret void } diff --git a/test/test_suite/statements/foreach_common.c3t b/test/test_suite/statements/foreach_common.c3t index 3b60b4a67..66ec250d1 100644 --- a/test/test_suite/statements/foreach_common.c3t +++ b/test/test_suite/statements/foreach_common.c3t @@ -76,22 +76,17 @@ entry: %.anon38 = alloca i64, align 8 %a42 = alloca double, align 8 %.anon47 = alloca i64, align 8 - %.anon48 = alloca i64, align 8 %a51 = alloca float, align 4 %.anon55 = alloca i64, align 8 - %.anon56 = alloca i64, align 8 - %a60 = alloca ptr, align 8 - %.anon66 = alloca i64, align 8 - %.anon67 = alloca i64, align 8 - %i71 = alloca i64, align 8 - %a72 = alloca float, align 4 - %.anon76 = alloca i64, align 8 - %.anon77 = alloca i64, align 8 - %i81 = alloca i8, align 1 - %a83 = alloca double, align 8 - %.anon88 = alloca i64, align 8 - %.anon89 = alloca i64, align 8 - %a93 = alloca double, align 8 + %a59 = alloca ptr, align 8 + %.anon65 = alloca i64, align 8 + %i69 = alloca i64, align 8 + %a70 = alloca float, align 4 + %.anon74 = alloca i64, align 8 + %i78 = alloca i8, align 1 + %a80 = alloca double, align 8 + %.anon85 = alloca i64, align 8 + %a89 = alloca double, align 8 call void @llvm.memcpy.p0.p0.i32(ptr align 4 %foo, ptr align 4 @.__const, i32 12, i1 false) store <3 x float> , ptr %foo2, align 16 store i64 0, ptr %.anon, align 8 @@ -238,137 +233,127 @@ loop.body41: ; preds = %loop.cond39 br label %loop.cond39 loop.exit46: ; preds = %loop.cond39 - store i64 3, ptr %.anon47, align 8 - store i64 0, ptr %.anon48, align 8 - br label %loop.cond49 + store i64 0, ptr %.anon47, align 8 + br label %loop.cond48 -loop.cond49: ; preds = %loop.body50, %loop.exit46 - %36 = load i64, ptr %.anon48, align 8 - %37 = load i64, ptr %.anon47, align 8 - %lt = icmp ult i64 %36, %37 - br i1 %lt, label %loop.body50, label %loop.exit54 +loop.cond48: ; preds = %loop.body50, %loop.exit46 + %36 = load i64, ptr %.anon47, align 8 + %gt49 = icmp ugt i64 3, %36 + br i1 %gt49, label %loop.body50, label %loop.exit54 -loop.body50: ; preds = %loop.cond49 - %38 = load <3 x float>, ptr %foo2, align 16 - %39 = load i64, ptr %.anon48, align 8 - %40 = extractelement <3 x float> %38, i64 %39 - store float %40, ptr %a51, align 4 - %41 = load float, ptr %a51, align 4 - %fpfpext52 = fpext float %41 to double +loop.body50: ; preds = %loop.cond48 + %37 = load <3 x float>, ptr %foo2, align 16 + %38 = load i64, ptr %.anon47, align 8 + %39 = extractelement <3 x float> %37, i64 %38 + store float %39, ptr %a51, align 4 + %40 = load float, ptr %a51, align 4 + %fpfpext52 = fpext float %40 to double call void (ptr, ...) @printf(ptr @.str.6, double %fpfpext52) - %42 = load i64, ptr %.anon48, align 8 - %addnuw53 = add nuw i64 %42, 1 - store i64 %addnuw53, ptr %.anon48, align 8 - br label %loop.cond49 + %41 = load i64, ptr %.anon47, align 8 + %addnuw53 = add nuw i64 %41, 1 + store i64 %addnuw53, ptr %.anon47, align 8 + br label %loop.cond48 -loop.exit54: ; preds = %loop.cond49 - store i64 3, ptr %.anon55, align 8 - store i64 0, ptr %.anon56, align 8 - br label %loop.cond57 +loop.exit54: ; preds = %loop.cond48 + store i64 0, ptr %.anon55, align 8 + br label %loop.cond56 -loop.cond57: ; preds = %loop.body59, %loop.exit54 - %43 = load i64, ptr %.anon56, align 8 - %44 = load i64, ptr %.anon55, align 8 - %lt58 = icmp ult i64 %43, %44 - br i1 %lt58, label %loop.body59, label %loop.exit65 +loop.cond56: ; preds = %loop.body58, %loop.exit54 + %42 = load i64, ptr %.anon55, align 8 + %gt57 = icmp ugt i64 3, %42 + br i1 %gt57, label %loop.body58, label %loop.exit64 -loop.body59: ; preds = %loop.cond57 - %45 = load i64, ptr %.anon56, align 8 - %ptroffset61 = getelementptr inbounds [4 x i8], ptr %foo2, i64 %45 - store ptr %ptroffset61, ptr %a60, align 8 - %46 = load ptr, ptr %a60, align 8 +loop.body58: ; preds = %loop.cond56 + %43 = load i64, ptr %.anon55, align 8 + %ptroffset60 = getelementptr inbounds [4 x i8], ptr %foo2, i64 %43 + store ptr %ptroffset60, ptr %a59, align 8 + %44 = load ptr, ptr %a59, align 8 + %45 = load float, ptr %44, align 4 + %fmul61 = fmul float %45, 2.000000e+00 + store float %fmul61, ptr %44, align 4 + %46 = load ptr, ptr %a59, align 8 %47 = load float, ptr %46, align 4 - %fmul62 = fmul float %47, 2.000000e+00 - store float %fmul62, ptr %46, align 4 - %48 = load ptr, ptr %a60, align 8 - %49 = load float, ptr %48, align 4 - %fpfpext63 = fpext float %49 to double - call void (ptr, ...) @printf(ptr @.str.7, double %fpfpext63) - %50 = load i64, ptr %.anon56, align 8 - %addnuw64 = add nuw i64 %50, 1 - store i64 %addnuw64, ptr %.anon56, align 8 - br label %loop.cond57 + %fpfpext62 = fpext float %47 to double + call void (ptr, ...) @printf(ptr @.str.7, double %fpfpext62) + %48 = load i64, ptr %.anon55, align 8 + %addnuw63 = add nuw i64 %48, 1 + store i64 %addnuw63, ptr %.anon55, align 8 + br label %loop.cond56 -loop.exit65: ; preds = %loop.cond57 - store i64 3, ptr %.anon66, align 8 - store i64 0, ptr %.anon67, align 8 - br label %loop.cond68 +loop.exit64: ; preds = %loop.cond56 + store i64 0, ptr %.anon65, align 8 + br label %loop.cond66 -loop.cond68: ; preds = %loop.body70, %loop.exit65 - %51 = load i64, ptr %.anon67, align 8 - %52 = load i64, ptr %.anon66, align 8 - %lt69 = icmp ult i64 %51, %52 - br i1 %lt69, label %loop.body70, label %loop.exit75 +loop.cond66: ; preds = %loop.body68, %loop.exit64 + %49 = load i64, ptr %.anon65, align 8 + %gt67 = icmp ugt i64 3, %49 + br i1 %gt67, label %loop.body68, label %loop.exit73 -loop.body70: ; preds = %loop.cond68 - %53 = load i64, ptr %.anon67, align 8 - store i64 %53, ptr %i71, align 8 - %54 = load <3 x float>, ptr %foo2, align 16 - %55 = load i64, ptr %.anon67, align 8 - %56 = extractelement <3 x float> %54, i64 %55 - store float %56, ptr %a72, align 4 - %57 = load float, ptr %a72, align 4 - %fpfpext73 = fpext float %57 to double - %58 = load i64, ptr %i71, align 8 - call void (ptr, ...) @printf(ptr @.str.8, i64 %58, double %fpfpext73) - %59 = load i64, ptr %.anon67, align 8 - %addnuw74 = add nuw i64 %59, 1 - store i64 %addnuw74, ptr %.anon67, align 8 - br label %loop.cond68 +loop.body68: ; preds = %loop.cond66 + %50 = load i64, ptr %.anon65, align 8 + store i64 %50, ptr %i69, align 8 + %51 = load <3 x float>, ptr %foo2, align 16 + %52 = load i64, ptr %.anon65, align 8 + %53 = extractelement <3 x float> %51, i64 %52 + store float %53, ptr %a70, align 4 + %54 = load float, ptr %a70, align 4 + %fpfpext71 = fpext float %54 to double + %55 = load i64, ptr %i69, align 8 + call void (ptr, ...) @printf(ptr @.str.8, i64 %55, double %fpfpext71) + %56 = load i64, ptr %.anon65, align 8 + %addnuw72 = add nuw i64 %56, 1 + store i64 %addnuw72, ptr %.anon65, align 8 + br label %loop.cond66 -loop.exit75: ; preds = %loop.cond68 - store i64 3, ptr %.anon76, align 8 - store i64 0, ptr %.anon77, align 8 - br label %loop.cond78 +loop.exit73: ; preds = %loop.cond66 + store i64 0, ptr %.anon74, align 8 + br label %loop.cond75 -loop.cond78: ; preds = %loop.body80, %loop.exit75 - %60 = load i64, ptr %.anon77, align 8 - %61 = load i64, ptr %.anon76, align 8 - %lt79 = icmp ult i64 %60, %61 - br i1 %lt79, label %loop.body80, label %loop.exit87 +loop.cond75: ; preds = %loop.body77, %loop.exit73 + %57 = load i64, ptr %.anon74, align 8 + %gt76 = icmp ugt i64 3, %57 + br i1 %gt76, label %loop.body77, label %loop.exit84 -loop.body80: ; preds = %loop.cond78 - %62 = load i64, ptr %.anon77, align 8 - %trunc82 = trunc i64 %62 to i8 - store i8 %trunc82, ptr %i81, align 1 - %63 = load <3 x float>, ptr %foo2, align 16 - %64 = load i64, ptr %.anon77, align 8 - %65 = extractelement <3 x float> %63, i64 %64 - %fpfpext84 = fpext float %65 to double - store double %fpfpext84, ptr %a83, align 8 - %66 = load i8, ptr %i81, align 1 - %zext85 = zext i8 %66 to i32 - %67 = load double, ptr %a83, align 8 - call void (ptr, ...) @printf(ptr @.str.9, i32 %zext85, double %67) - %68 = load i64, ptr %.anon77, align 8 - %addnuw86 = add nuw i64 %68, 1 - store i64 %addnuw86, ptr %.anon77, align 8 - br label %loop.cond78 +loop.body77: ; preds = %loop.cond75 + %58 = load i64, ptr %.anon74, align 8 + %trunc79 = trunc i64 %58 to i8 + store i8 %trunc79, ptr %i78, align 1 + %59 = load <3 x float>, ptr %foo2, align 16 + %60 = load i64, ptr %.anon74, align 8 + %61 = extractelement <3 x float> %59, i64 %60 + %fpfpext81 = fpext float %61 to double + store double %fpfpext81, ptr %a80, align 8 + %62 = load i8, ptr %i78, align 1 + %zext82 = zext i8 %62 to i32 + %63 = load double, ptr %a80, align 8 + call void (ptr, ...) @printf(ptr @.str.9, i32 %zext82, double %63) + %64 = load i64, ptr %.anon74, align 8 + %addnuw83 = add nuw i64 %64, 1 + store i64 %addnuw83, ptr %.anon74, align 8 + br label %loop.cond75 -loop.exit87: ; preds = %loop.cond78 - store i64 3, ptr %.anon88, align 8 - store i64 0, ptr %.anon89, align 8 - br label %loop.cond90 +loop.exit84: ; preds = %loop.cond75 + store i64 0, ptr %.anon85, align 8 + br label %loop.cond86 -loop.cond90: ; preds = %loop.body92, %loop.exit87 - %69 = load i64, ptr %.anon89, align 8 - %70 = load i64, ptr %.anon88, align 8 - %lt91 = icmp ult i64 %69, %70 - br i1 %lt91, label %loop.body92, label %loop.exit96 +loop.cond86: ; preds = %loop.body88, %loop.exit84 + %65 = load i64, ptr %.anon85, align 8 + %gt87 = icmp ugt i64 3, %65 + br i1 %gt87, label %loop.body88, label %loop.exit92 -loop.body92: ; preds = %loop.cond90 - %71 = load <3 x float>, ptr %foo2, align 16 - %72 = load i64, ptr %.anon89, align 8 - %73 = extractelement <3 x float> %71, i64 %72 - %fpfpext94 = fpext float %73 to double - store double %fpfpext94, ptr %a93, align 8 - %74 = load double, ptr %a93, align 8 - call void (ptr, ...) @printf(ptr @.str.10, double %74) - %75 = load i64, ptr %.anon89, align 8 - %addnuw95 = add nuw i64 %75, 1 - store i64 %addnuw95, ptr %.anon89, align 8 - br label %loop.cond90 +loop.body88: ; preds = %loop.cond86 + %66 = load <3 x float>, ptr %foo2, align 16 + %67 = load i64, ptr %.anon85, align 8 + %68 = extractelement <3 x float> %66, i64 %67 + %fpfpext90 = fpext float %68 to double + store double %fpfpext90, ptr %a89, align 8 + %69 = load double, ptr %a89, align 8 + call void (ptr, ...) @printf(ptr @.str.10, double %69) + %70 = load i64, ptr %.anon85, align 8 + %addnuw91 = add nuw i64 %70, 1 + store i64 %addnuw91, ptr %.anon85, align 8 + br label %loop.cond86 -loop.exit96: ; preds = %loop.cond90 +loop.exit92: ; preds = %loop.cond86 ret void } diff --git a/test/unit/regression/vector_ops.c3 b/test/unit/regression/vector_ops.c3 index 84b4f2574..f1c3e3ef1 100644 --- a/test/unit/regression/vector_ops.c3 +++ b/test/unit/regression/vector_ops.c3 @@ -83,6 +83,8 @@ fn void! testb() @test fn void! testi() @test { + int[<4>] x = { 4, 0, -1, 33 }; + assert({ true, false, true, true} == (bool[<4>])x); int[<4>] y = { 1, 2, 3, 4 }; int[<4>] z = { 2, 2, 2, -100 }; int[<4>] w = y + z;