diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 42aa89dbe..0921032a5 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -649,14 +649,39 @@ typedef struct Decl_ // static_assert(sizeof(void*) != 8 || sizeof(Decl) == 136, "Decl has unexpected size."); +typedef enum RangeType +{ + RANGE_DYNAMIC, + RANGE_CONST_END, + RANGE_CONST_LEN, + RANGE_CONST_RANGE, +} RangeType; + typedef struct { + ResolveStatus status : 3; + RangeType range_type; bool start_from_end : 1; bool end_from_end : 1; bool is_len : 1; bool is_range : 1; - ExprId start; - ExprId end; + union + { + struct + { + ExprId start; + union + { + ExprId end; + ArrayIndex const_end; + }; + }; + struct + { + ArrayIndex start_index; + ArrayIndex len_index; + }; + }; } Range; typedef struct diff --git a/src/compiler/copying.c b/src/compiler/copying.c index 0837fc9e5..dc2016682 100644 --- a/src/compiler/copying.c +++ b/src/compiler/copying.c @@ -192,8 +192,20 @@ Expr *copy_expr_single(Expr *source_expr) void copy_range(CopyStruct *c, Range *range) { - MACRO_COPY_EXPRID(range->start); - MACRO_COPY_EXPRID(range->end); + switch (range->range_type) + { + case RANGE_CONST_LEN: + case RANGE_CONST_END: + MACRO_COPY_EXPRID(range->start); + return; + case RANGE_CONST_RANGE: + return; + case RANGE_DYNAMIC: + MACRO_COPY_EXPRID(range->start); + MACRO_COPY_EXPRID(range->end); + return; + } + UNREACHABLE } INLINE ConstInitializer **copy_const_initializer_list(CopyStruct *c, ConstInitializer **initializer_list) diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index 147b9c1f9..b74a7bf6c 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -2875,8 +2875,6 @@ static void llvm_emit_slice_values(GenContext *c, Expr *slice, BEValue *parent_r assert(slice->expr_kind == EXPR_SLICE); Expr *parent_expr = exprptr(slice->subscript_expr.expr); - Expr *start = exprptr(slice->subscript_expr.range.start); - Expr *end = exprptrzero(slice->subscript_expr.range.end); Type *parent_type = type_flatten(parent_expr->type); BEValue parent_addr_x; @@ -2906,16 +2904,31 @@ static void llvm_emit_slice_values(GenContext *c, Expr *slice, BEValue *parent_r } // Emit the start and end - Type *start_type = start->type->canonical; + + Type *start_type; + Range range = slice->subscript_expr.range; BEValue start_index; - llvm_emit_expr(c, &start_index, start); - llvm_value_rvalue(c, &start_index); + switch (range.range_type) + { + case RANGE_DYNAMIC: + case RANGE_CONST_LEN: + case RANGE_CONST_END: + llvm_emit_exprid(c, &start_index, range.start); + llvm_value_rvalue(c, &start_index); + start_type = start_index.type; + break; + case RANGE_CONST_RANGE: + start_type = type_isz; + llvm_value_set_int(c, &start_index, type_isz, range.start_index); + break; + } BEValue len = { .value = NULL }; bool check_end = true; - bool start_from_end = slice->subscript_expr.range.start_from_end; - bool end_from_end = slice->subscript_expr.range.end_from_end; - if (!end || start_from_end || end_from_end || safe_mode_enabled()) + bool start_from_end = range.start_from_end; + bool end_from_end = range.end_from_end; + bool has_end = range.range_type != RANGE_DYNAMIC || range.end; + if (!has_end || start_from_end || end_from_end || safe_mode_enabled()) { switch (parent_type->type_kind) { @@ -2926,11 +2939,11 @@ static void llvm_emit_slice_values(GenContext *c, Expr *slice, BEValue *parent_r break; case TYPE_SLICE: assert(parent_load_value); - llvm_value_set(&len, llvm_emit_extract_value(c, parent_load_value, 1), type_usz); + llvm_value_set(&len, llvm_emit_extract_value(c, parent_load_value, 1), start_type); break; case TYPE_ARRAY: case TYPE_VECTOR: - llvm_value_set_int(c, &len, type_usz, parent_type->array.len); + llvm_value_set_int(c, &len, start_type, parent_type->array.len); break; default: UNREACHABLE @@ -2953,24 +2966,41 @@ static void llvm_emit_slice_values(GenContext *c, Expr *slice, BEValue *parent_r } // Insert trap for negative start offset for non pointers. - if (parent_type->type_kind != TYPE_POINTER) + if (parent_type->type_kind != TYPE_POINTER && range.range_type != RANGE_CONST_RANGE) { - llvm_emit_trap_negative(c, start, start_index.value, "Negative indexing (%d)", &start_index); + llvm_emit_trap_negative(c, exprptr(range.start), start_index.value, "Negative indexing (%d)", &start_index); } - Type *end_type; BEValue end_index; bool is_len_range = *is_exclusive = slice->subscript_expr.range.is_len; - if (end) + Type *end_type = start_type; + if (has_end) { // Get the index. - llvm_emit_expr(c, &end_index, end); - llvm_value_rvalue(c, &end_index); - end_type = end->type->canonical; + switch (range.range_type) + { + case RANGE_DYNAMIC: + llvm_emit_exprid(c, &end_index, range.end); + llvm_value_rvalue(c, &end_index); + end_type = end_index.type; + break; + case RANGE_CONST_LEN: + assert(range.is_len); + llvm_value_set_int(c, &end_index, end_type, range.const_end); + break; + case RANGE_CONST_END: + assert(!range.is_len); + llvm_value_set_int(c, &end_index, end_type, range.const_end); + break; + case RANGE_CONST_RANGE: + llvm_value_set_int(c, &end_index, end_type, range.len_index); + break; + } // Reverse if it is "from back" if (end_from_end) { + assert(range.range_type == RANGE_DYNAMIC); end_index.value = llvm_emit_sub_int(c, end_type, len.value, end_index.value, slice->span); llvm_value_rvalue(c, &end_index); } @@ -2989,7 +3019,7 @@ static void llvm_emit_slice_values(GenContext *c, Expr *slice, BEValue *parent_r BEValue excess; llvm_emit_int_comp(c, &excess, &len, &end_index, BINARYOP_LT); BEValue actual_end_index = end_index; - actual_end_index.value = llvm_emit_sub_int(c, end_type, end_index.value, llvm_const_int(c, end_type, 1), slice->span); + actual_end_index.value = llvm_emit_sub_int(c, end_type, end_index.value, llvm_const_int(c, type_isz, 1), slice->span); llvm_emit_panic_if_true(c, &excess, "End index out of bounds", slice->span, "End index out of bounds (end index of %d exceeds size of %d)", &actual_end_index, &len); } } @@ -3011,13 +3041,13 @@ static void llvm_emit_slice_values(GenContext *c, Expr *slice, BEValue *parent_r { assert(len.value && "Pointer should never end up here."); end_index.value = len.value; - end_type = type_usz; + end_type = start_type; // Use "len-range" when implicit, this avoids len - 1 here. *is_exclusive = true; } llvm_value_set(end_ref, end_index.value, end_type); - llvm_value_set(start_ref, start_index.value, start_type); + llvm_value_set(start_ref, start_index.value, end_type); llvm_value_set_address(parent_ref, parent_base, parent_type, type_abi_alignment(parent_type)); } @@ -3610,8 +3640,8 @@ static void llvm_emit_slice_comp(GenContext *c, BEValue *be_value, BEValue *lhs, llvm_value_rvalue(c, rhs); BEValue lhs_len; BEValue rhs_len; - llvm_value_set(&lhs_len, llvm_emit_extract_value(c, lhs->value, 1), type_usz); - llvm_value_set(&rhs_len, llvm_emit_extract_value(c, rhs->value, 1), type_usz); + llvm_value_set(&lhs_len, llvm_emit_extract_value(c, lhs->value, 1), type_isz); + llvm_value_set(&rhs_len, llvm_emit_extract_value(c, rhs->value, 1), type_isz); BEValue lhs_value; BEValue rhs_value; llvm_value_set(&lhs_value, llvm_emit_extract_value(c, lhs->value, 0), array_base_pointer); @@ -3624,9 +3654,9 @@ static void llvm_emit_slice_comp(GenContext *c, BEValue *be_value, BEValue *lhs, llvm_emit_block(c, value_cmp); BEValue index_var; - llvm_value_set_address_abi_aligned(&index_var, llvm_emit_alloca_aligned(c, type_usz, "cmp.idx"), type_usz); - LLVMValueRef one = llvm_const_int(c, type_usz, 1); - llvm_store_raw(c, &index_var, llvm_get_zero(c, type_usz)); + llvm_value_set_address_abi_aligned(&index_var, llvm_emit_alloca_aligned(c, type_isz, "cmp.idx"), type_isz); + LLVMValueRef one = llvm_const_int(c, type_isz, 1); + llvm_store_raw(c, &index_var, llvm_get_zero(c, type_isz)); llvm_emit_br(c, loop_begin); llvm_emit_block(c, loop_begin); @@ -3852,11 +3882,11 @@ MEMCMP: LLVMBasicBlockRef comparison = llvm_basic_block_new(c, "array_loop_comparison"); LLVMBasicBlockRef comparison_phi; LLVMBasicBlockRef loop_begin_phi; - LLVMValueRef len_val = llvm_const_int(c, type_usz, len); - LLVMValueRef one = llvm_const_int(c, type_usz, 1); + LLVMValueRef len_val = llvm_const_int(c, type_isz, len); + LLVMValueRef one = llvm_const_int(c, type_isz, 1); BEValue index_var; - llvm_value_set_address_abi_aligned(&index_var, llvm_emit_alloca_aligned(c, type_usz, "cmp.idx"), type_usz); - llvm_store_raw(c, &index_var, llvm_get_zero(c, type_usz)); + llvm_value_set_address_abi_aligned(&index_var, llvm_emit_alloca_aligned(c, type_isz, "cmp.idx"), type_isz); + llvm_store_raw(c, &index_var, llvm_get_zero(c, type_isz)); llvm_emit_br(c, loop_begin); llvm_emit_block(c, loop_begin); @@ -3879,7 +3909,7 @@ MEMCMP: LLVMValueRef new_index = LLVMBuildAdd(c->builder, index_copy.value, one, "inc"); llvm_store_raw(c, &index_var, new_index); - llvm_emit_int_comp_raw(c, &comp, type_usz, type_usz, new_index, len_val, BINARYOP_LT); + llvm_emit_int_comp_raw(c, &comp, type_isz, type_isz, new_index, len_val, BINARYOP_LT); comparison_phi = c->current_block; llvm_emit_cond_br(c, &comp, loop_begin, exit); llvm_emit_block(c, exit); diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index b754ce308..4e3beb588 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -3129,6 +3129,201 @@ static inline bool sema_expr_analyse_pointer_offset(SemaContext *context, Expr * return true; } +typedef enum RangeEnv +{ + RANGE_ARRAY, + RANGE_SLICE, + RANGE_PTR, + RANGE_FLEXIBLE, +} RangeEnv; + +INLINE bool sema_expre_analyse_range_internal(SemaContext *context, Range *range, Type *indexed_type, ArrayIndex len, RangeEnv env) +{ + Expr *start = exprptr(range->start); + assert(start); + Expr *end = exprptrzero(range->end); + + if (!sema_analyse_expr(context, start)) return false; + if (end && !sema_analyse_expr(context, end)) return false; + + if (!cast_to_index(context, start, indexed_type)) return false; + if (end && !cast_to_index(context, end, indexed_type)) return false; + if (end && end->type != start->type) + { + Type *common = type_find_max_type(start->type, end->type); + if (!common) + { + SourceSpan span = start->span; + span = extend_span_with_token(span, end->span); + sema_error_at(context, span, "No common type can be found between start and end index."); + return false; + } + if (!cast_implicit(context, start, common, false) || !cast_implicit(context, end, common, false)) return false; + } + // Check range + if (env != RANGE_ARRAY && env != RANGE_SLICE) + { + if (range->start_from_end) + { + RETURN_SEMA_ERROR(start, "Indexing from the end is not allowed for pointers or flexible array members."); + } + if (!end) + { + RETURN_SEMA_ERROR(start, "Omitting end index is not allowed for pointers or flexible array members."); + } + if (end && range->end_from_end) + { + RETURN_SEMA_ERROR(end, "Indexing from the end is not allowed for pointers or flexible array members."); + } + } + bool end_is_const = !end || sema_cast_const(end); + if (end && sema_cast_const(end)) + { + // Only ArrayIndex sized + if (!int_fits(end->const_expr.ixx, TYPE_I64)) + { + RETURN_SEMA_ERROR(end, "The index cannot be stored in a 64-signed integer, which isn't supported."); + } + + int64_t end_index = int_to_i64(end->const_expr.ixx); + + if (range->end_from_end) + { + if (end_index < 0) RETURN_SEMA_ERROR(end, "Negative numbers are not allowed when indexing from the end."); + // Something like 1 .. ^4 with an unknown length. + if (len < 0) return true; + // Otherwise we fold the "from end" + end_index = len - end_index; + if (end_index < 0) + { + RETURN_SEMA_ERROR(end, "An index may only be negative for pointers (it was: %lld).", end_index); + } + range->end_from_end = false; + } + if (end_index < 0 && env != RANGE_PTR) + { + RETURN_SEMA_ERROR(end, "An index may only be negative for pointers (it was: %lld).", end_index); + } + // No more analysis + if (end_index > MAX_ARRAYINDEX || end_index < -MAX_ARRAYINDEX) return true; + range->const_end = end_index; + range->range_type = range->is_len ? RANGE_CONST_LEN : RANGE_CONST_END; + } + else if (!end && len > 0) + { + range->is_len = false; + range->const_end = len - 1; + range->range_type = RANGE_CONST_END; + } + + if (sema_cast_const(start)) + { + // Only ArrayIndex sized + if (!int_fits(start->const_expr.ixx, TYPE_I64)) + { + RETURN_SEMA_ERROR(end, "The index cannot be stored in a 64-signed integer, which isn't supported."); + } + // Only ArrayIndex sized + int64_t start_index = int_to_i64(start->const_expr.ixx); + if (range->start_from_end) + { + if (start_index < 0) RETURN_SEMA_ERROR(end, "Negative numbers are not allowed when indexing from the end."); + // Something like ^1 .. 4 with an unknown length. + if (len < 0) return true; + // Otherwise we fold the "from end" + start_index = len - start_index; + if (start_index < 0) + { + RETURN_SEMA_ERROR(start, "An index may only be negative for pointers (it was: %lld).", start_index); + } + if (start_index > MAX_ARRAYINDEX || start_index < -MAX_ARRAYINDEX) return true; + range->start_from_end = false; + } + if (start_index < 0 && env != RANGE_PTR) + { + RETURN_SEMA_ERROR(start, "An index may only be negative for pointers (it was: %lld).", start_index); + } + if (len > -1 && start_index >= len) + { + RETURN_SEMA_ERROR(start, "Index out of bounds: the start index was %lld, exceeding the maximum (%lld)", + start_index, len - 1); + } + if (range->range_type == RANGE_CONST_END) + { + int64_t end_index = range->const_end; + if (end_index < start_index) RETURN_SEMA_ERROR(start, "The start index (%lld) should not be greater than the end index (%lld).", + start_index, end_index); + if (start_index > MAX_ARRAYINDEX) return true; + range->const_end = end_index + 1 - start_index; + range->range_type = RANGE_CONST_LEN; + range->is_len = true; + } + if (range->range_type == RANGE_CONST_LEN) + { + int64_t end_index = range->const_end; + range->range_type = RANGE_CONST_RANGE; + range->start_index = start_index; + range->len_index = end_index; + } + } + if (len > -1) + { + switch (range->range_type) + { + case RANGE_CONST_END: + if (range->const_end >= len) + { + RETURN_SEMA_ERROR(end ? end : start, "End index out of bounds, was %d, exceeding max index %d.", range->const_end, len - 1); + } + break; + case RANGE_CONST_LEN: + if (range->const_end > len) + { + RETURN_SEMA_ERROR(end ? end : start, "Length out of bounds, was %d, exceeding max length %d.", range->const_end, len); + } + break; + case RANGE_CONST_RANGE: + if (range->len_index > len) + { + RETURN_SEMA_ERROR(end ? end : start, "End index out of bounds, was %d, exceeding max index %d.", range->len_index - 1, len - 1); + } + break; + default: + break; + } + } + return true; +} + + +static inline bool sema_expr_analyse_range(SemaContext *context, Range *range, Type *indexed_type, ArrayIndex len, RangeEnv env) +{ + switch (range->status) + { + case RESOLVE_DONE: + return true; + case RESOLVE_NOT_DONE: + range->status = RESOLVE_RUNNING; + if (!sema_expre_analyse_range_internal(context, range, indexed_type, len, env)) + { + range->status = RESOLVE_NOT_DONE; + return false; + } + range->status = RESOLVE_DONE; + return true; + case RESOLVE_RUNNING: + { + SourceSpan span = exprptr(range->start)->span; + if (range->end) span = extend_span_with_token(span, exprptr(range->end)->span); + sema_error_at(context, span, "Recursive definition of range."); + range->status = RESOLVE_NOT_DONE; + return false; + } + default: + UNREACHABLE + } + +} static inline bool sema_expr_analyse_slice(SemaContext *context, Expr *expr) { ASSERT_SPAN(expr, expr->expr_kind == EXPR_SLICE); @@ -3137,113 +3332,40 @@ static inline bool sema_expr_analyse_slice(SemaContext *context, Expr *expr) bool optional = IS_OPTIONAL(subscripted); Type *type = type_flatten(subscripted->type); Type *original_type = type_no_optional(subscripted->type); - Expr *start = exprptr(expr->subscript_expr.range.start); - Expr *end = exprptrzero(expr->subscript_expr.range.end); + RangeEnv env; + switch (type->type_kind) + { + case TYPE_POINTER: + env = RANGE_PTR; + break; + case TYPE_FLEXIBLE_ARRAY: + env = RANGE_FLEXIBLE; + break; + case TYPE_SLICE: + env = RANGE_SLICE; + break; + default: + env = RANGE_ARRAY; + break; + } + ArrayIndex length = sema_len_from_expr(subscripted); + if (!sema_expr_analyse_range(context, &expr->subscript_expr.range, subscripted->type, length, env)) return false; Expr *current_expr = subscripted; - Type *inner_type = sema_subscript_find_indexable_type_recursively(&type, ¤t_expr); + if (type == type_voidptr) inner_type = type_char; + if (!inner_type || !type_is_valid_for_array(inner_type)) { RETURN_SEMA_ERROR(subscripted, "Cannot index '%s'.", type_to_error_string(subscripted->type)); } - expr->subscript_expr.expr = exprid(current_expr); - - if (!sema_analyse_expr(context, start)) return false; - if (end && !sema_analyse_expr(context, end)) return false; // Fix index sizes - if (!cast_to_index(context, start, subscripted->type)) return false; - if (end && !cast_to_index(context, end, subscripted->type)) return false; - if (end && end->type != start->type) - { - Type *common = type_find_max_type(start->type, end->type); - if (!common) - { - SEMA_ERROR(expr, "No common type can be found between start and end index."); - return false; - } - if (!cast_implicit(context, start, common, false) || !cast_implicit(context, end, common, false)) return false; - } - bool start_from_end = expr->subscript_expr.range.start_from_end; bool end_from_end = expr->subscript_expr.range.end_from_end; - // Check range - if (type->type_kind == TYPE_POINTER || type->type_kind == TYPE_FLEXIBLE_ARRAY) - { - if (start_from_end) - { - SEMA_ERROR(start, "Indexing from the end is not allowed for pointers or flexible array members."); - return false; - } - if (!end) - { - SEMA_ERROR(expr, "Omitting end index is not allowed for pointers or flexible array members."); - return false; - } - if (end && end_from_end) - { - SEMA_ERROR(end, "Indexing from the end is not allowed for pointers or flexible array members."); - return false; - } - } bool is_lenrange = expr->subscript_expr.range.is_len; - bool remove_from_end = false; - if (!sema_slice_index_is_in_range(context, type, start, false, start_from_end, &remove_from_end)) return false; - if (remove_from_end) - { - start_from_end = expr->subscript_expr.range.start_from_end = false; - } - remove_from_end = false; - if (end) - { - if (is_lenrange) - { - if (!sema_slice_len_is_in_range(context, type, end, end_from_end, &remove_from_end)) return false; - } - else - { - if (!sema_slice_index_is_in_range(context, type, end, true, end_from_end, &remove_from_end)) return false; - } - } - if (remove_from_end) - { - end_from_end = expr->subscript_expr.range.end_from_end = false; - } - - if (start && end && sema_cast_const(start) && sema_cast_const(end)) - { - if (!is_lenrange && start_from_end && end_from_end) - { - if (expr_const_compare(&start->const_expr, &end->const_expr, BINARYOP_LT)) - { - SEMA_ERROR(start, "Start index greater than end index."); - return false; - } - } - else if (!is_lenrange && !start_from_end && !end_from_end) - { - if (expr_const_compare(&start->const_expr, &end->const_expr, BINARYOP_GT)) - { - SEMA_ERROR(start, "Start index greater than end index."); - return false; - } - } - // If both are - if (type->type_kind == TYPE_ARRAY || type->type_kind == TYPE_VECTOR) - { - ASSERT_SPAN(expr, !start_from_end); - ASSERT_SPAN(expr, !end_from_end); - if (!is_lenrange) - { - end->const_expr.ixx = int_sub(int_add64(end->const_expr.ixx, 1), start->const_expr.ixx); - is_lenrange = expr->subscript_expr.range.is_len = true; - (void)is_lenrange; - } - } - } // Retain the original type when doing distinct slices. Type *result_type = type_get_slice(inner_type); diff --git a/src/compiler/sema_internal.h b/src/compiler/sema_internal.h index e892eab24..f3aea7f45 100644 --- a/src/compiler/sema_internal.h +++ b/src/compiler/sema_internal.h @@ -181,6 +181,17 @@ INLINE void sema_display_deprecated_warning_on_use(SemaContext *context, Decl *d static inline IndexDiff range_const_len(Range *range) { + switch (range->range_type) + { + case RANGE_CONST_LEN: + return range->const_end; + case RANGE_CONST_END: + return -1; + case RANGE_CONST_RANGE: + return range->len_index; + case RANGE_DYNAMIC: + break; + } Expr *start = exprptr(range->start); Expr *end = exprptrzero(range->end); if (!end || !expr_is_const_int(end)) return -1; diff --git a/src/compiler/sema_liveness.c b/src/compiler/sema_liveness.c index 2b87f3628..51030ec1d 100644 --- a/src/compiler/sema_liveness.c +++ b/src/compiler/sema_liveness.c @@ -415,9 +415,20 @@ RETRY: case EXPR_SUBSCRIPT: case EXPR_SUBSCRIPT_ADDR: sema_trace_expr_liveness(exprptr(expr->subscript_expr.expr)); - sema_trace_expr_liveness(exprptr(expr->subscript_expr.range.start)); - sema_trace_expr_liveness(exprptrzero(expr->subscript_expr.range.end)); - return; + switch (expr->subscript_expr.range.range_type) + { + case RANGE_CONST_RANGE: + return; + case RANGE_DYNAMIC: + sema_trace_expr_liveness(exprptr(expr->subscript_expr.range.start)); + sema_trace_expr_liveness(exprptrzero(expr->subscript_expr.range.end)); + return; + case RANGE_CONST_END: + case RANGE_CONST_LEN: + sema_trace_expr_liveness(exprptr(expr->subscript_expr.range.start)); + return; + } + UNREACHABLE case EXPR_SWIZZLE: sema_trace_expr_liveness(exprptr(expr->swizzle_expr.parent)); return; diff --git a/test/test_suite/subarrays/slice_checks.c3t b/test/test_suite/subarrays/slice_checks.c3t index e352c5b0e..3380831eb 100644 --- a/test/test_suite/subarrays/slice_checks.c3t +++ b/test/test_suite/subarrays/slice_checks.c3t @@ -31,13 +31,13 @@ fn void main() %2 = load %"int[]", ptr %slice, align 8 %3 = extractvalue %"int[]" %2, 0 %4 = extractvalue %"int[]" %2, 1 - %gt = icmp ugt i64 2, %4 + %gt = icmp sgt i64 2, %4 %5 = call i1 @llvm.expect.i1(i1 %gt, i1 false) br i1 %5, label %panic, label %checkok checkok: ; preds = %entry - %ge = icmp uge i64 5, %4 - %6 = call i1 @llvm.expect.i1(i1 %ge, i1 false) + %lt = icmp slt i64 %4, 6 + %6 = call i1 @llvm.expect.i1(i1 %lt, i1 false) br i1 %6, label %panic5, label %checkok12 checkok12: ; preds = %checkok @@ -48,7 +48,7 @@ checkok12: ; preds = %checkok %9 = load %"int[]", ptr %slice, align 8 %10 = extractvalue %"int[]" %9, 0 %11 = extractvalue %"int[]" %9, 1 - %gt14 = icmp ugt i64 6, %11 + %gt14 = icmp sgt i64 6, %11 %12 = call i1 @llvm.expect.i1(i1 %gt14, i1 false) br i1 %12, label %panic15, label %checkok22 @@ -61,13 +61,13 @@ checkok22: ; preds = %checkok12 %15 = load %"int[]", ptr %slice, align 8 %16 = extractvalue %"int[]" %15, 0 %17 = extractvalue %"int[]" %15, 1 - %gt24 = icmp ugt i64 0, %17 + %gt24 = icmp sgt i64 0, %17 %18 = call i1 @llvm.expect.i1(i1 %gt24, i1 false) br i1 %18, label %panic25, label %checkok32 checkok32: ; preds = %checkok22 - %ge33 = icmp uge i64 9, %17 - %19 = call i1 @llvm.expect.i1(i1 %ge33, i1 false) + %lt33 = icmp slt i64 %17, 10 + %19 = call i1 @llvm.expect.i1(i1 %lt33, i1 false) br i1 %19, label %panic34, label %checkok41 checkok41: ; preds = %checkok32 @@ -77,13 +77,13 @@ checkok41: ; preds = %checkok32 %22 = load %"int[]", ptr %slice, align 8 %23 = extractvalue %"int[]" %22, 0 %24 = extractvalue %"int[]" %22, 1 - %gt42 = icmp ugt i64 5, %24 + %gt42 = icmp sgt i64 5, %24 %25 = call i1 @llvm.expect.i1(i1 %gt42, i1 false) br i1 %25, label %panic43, label %checkok50 checkok50: ; preds = %checkok41 - %gt51 = icmp ugt i64 15, %24 - %26 = call i1 @llvm.expect.i1(i1 %gt51, i1 false) + %lt51 = icmp slt i64 %24, 15 + %26 = call i1 @llvm.expect.i1(i1 %lt51, i1 false) br i1 %26, label %panic52, label %checkok59 checkok59: ; preds = %checkok50 @@ -94,13 +94,13 @@ checkok59: ; preds = %checkok50 %29 = load %"int[]", ptr %slice, align 8 %30 = extractvalue %"int[]" %29, 0 %31 = extractvalue %"int[]" %29, 1 - %gt61 = icmp ugt i64 1, %31 + %gt61 = icmp sgt i64 1, %31 %32 = call i1 @llvm.expect.i1(i1 %gt61, i1 false) br i1 %32, label %panic62, label %checkok69 checkok69: ; preds = %checkok59 - %ge70 = icmp uge i64 3, %31 - %33 = call i1 @llvm.expect.i1(i1 %ge70, i1 false) + %lt70 = icmp slt i64 %31, 4 + %33 = call i1 @llvm.expect.i1(i1 %lt70, i1 false) br i1 %33, label %panic71, label %checkok78 checkok78: ; preds = %checkok69 @@ -111,13 +111,13 @@ checkok78: ; preds = %checkok69 %36 = load %"int[]", ptr %slice, align 8 %37 = extractvalue %"int[]" %36, 0 %38 = extractvalue %"int[]" %36, 1 - %gt80 = icmp ugt i64 2, %38 + %gt80 = icmp sgt i64 2, %38 %39 = call i1 @llvm.expect.i1(i1 %gt80, i1 false) br i1 %39, label %panic81, label %checkok88 checkok88: ; preds = %checkok78 - %gt89 = icmp ugt i64 12, %38 - %40 = call i1 @llvm.expect.i1(i1 %gt89, i1 false) + %lt89 = icmp slt i64 %38, 12 + %40 = call i1 @llvm.expect.i1(i1 %lt89, i1 false) br i1 %40, label %panic90, label %checkok97 checkok97: ; preds = %checkok88 diff --git a/test/test_suite/subarrays/slice_comparison.c3t b/test/test_suite/subarrays/slice_comparison.c3t index 4b64e34cd..8fce3e616 100644 --- a/test/test_suite/subarrays/slice_comparison.c3t +++ b/test/test_suite/subarrays/slice_comparison.c3t @@ -58,7 +58,7 @@ slice_cmp_values: ; preds = %entry slice_loop_start: ; preds = %slice_loop_comparison, %slice_cmp_values %3 = load i64, ptr %cmp.idx, align 8 - %lt = icmp ult i64 %3, %1 + %lt = icmp slt i64 %3, %1 br i1 %lt, label %slice_loop_comparison, label %slice_cmp_exit slice_loop_comparison: ; preds = %slice_loop_start @@ -95,7 +95,7 @@ slice_cmp_values4: ; preds = %if.exit slice_loop_start6: ; preds = %slice_loop_comparison8, %slice_cmp_values4 %13 = load i64, ptr %cmp.idx5, align 8 - %lt7 = icmp ult i64 %13, %9 + %lt7 = icmp slt i64 %13, %9 br i1 %lt7, label %slice_loop_comparison8, label %slice_cmp_exit12 slice_loop_comparison8: ; preds = %slice_loop_start6 @@ -133,7 +133,7 @@ slice_cmp_values17: ; preds = %switch.entry slice_loop_start19: ; preds = %slice_loop_comparison21, %slice_cmp_values17 %20 = load i64, ptr %cmp.idx18, align 8 - %lt20 = icmp ult i64 %20, 4 + %lt20 = icmp slt i64 %20, 4 br i1 %lt20, label %slice_loop_comparison21, label %slice_cmp_exit25 slice_loop_comparison21: ; preds = %slice_loop_start19 @@ -166,7 +166,7 @@ slice_cmp_values28: ; preds = %next_if slice_loop_start30: ; preds = %slice_loop_comparison32, %slice_cmp_values28 %26 = load i64, ptr %cmp.idx29, align 8 - %lt31 = icmp ult i64 %26, 5 + %lt31 = icmp slt i64 %26, 5 br i1 %lt31, label %slice_loop_comparison32, label %slice_cmp_exit36 slice_loop_comparison32: ; preds = %slice_loop_start30 @@ -199,7 +199,7 @@ slice_cmp_values41: ; preds = %next_if39 slice_loop_start43: ; preds = %slice_loop_comparison45, %slice_cmp_values41 %32 = load i64, ptr %cmp.idx42, align 8 - %lt44 = icmp ult i64 %32, 4 + %lt44 = icmp slt i64 %32, 4 br i1 %lt44, label %slice_loop_comparison45, label %slice_cmp_exit49 slice_loop_comparison45: ; preds = %slice_loop_start43 diff --git a/test/test_suite/subarrays/slice_negative_len.c3 b/test/test_suite/subarrays/slice_negative_len.c3 index 58e1ae00a..8e1baa8bf 100644 --- a/test/test_suite/subarrays/slice_negative_len.c3 +++ b/test/test_suite/subarrays/slice_negative_len.c3 @@ -2,7 +2,7 @@ fn void test() { int[3] x = { 1, 2, 3}; int[] z = x[2..2]; - z = x[2..1]; // #error: Start index greater than end index. + z = x[2..1]; // #error: greater than the end index } fn void test2() @@ -10,13 +10,13 @@ fn void test2() int[3] x = { 1, 2, 3}; int[] z = x[^2..^2]; z = x[^3..]; - z = x[^1..^2]; // #error: Start index greater than end index. + z = x[^1..^2]; // #error: greater than the end index } fn void test3() { int[3] x = { 1, 2, 3 }; - int[] z = x[..4]; // #error: End index out of bounds, was 4, exceeding 3. + int[] z = x[..4]; // #error: End index out of bounds, was 4, exceeding } fn void test4() @@ -29,31 +29,31 @@ fn void test4() fn void test5() { int[3] x = { 1, 2, 3 }; - int[] z = x[..^4]; // #error: Index out of bounds, using a negative index is only allowed for pointers. + int[] z = x[..^4]; // #error: An index may only be negative } fn void test6() { int[3] x = { 1, 2, 3 }; - int[] z = x[3..]; // #error: Index out of bounds, was 3, exceeding maximum (2). + int[] z = x[3..]; // #error: Index out of bounds: the start index was } fn void test7() { int[3] x = { 1, 2, 3 }; - int[] z = x[-1..]; // #error: Index out of bounds, using a negative index is only allowed for pointers + int[] z = x[-1..]; // #error: An index may only be negative } fn void test8() { int[3] x = { 1, 2, 3 }; - int[] z = x[^4..]; // #error: Index out of bounds, using a negative index is only allowed for pointers + int[] z = x[^4..]; // #error: An index may only be negative } fn void test9() { int[3] x = { 1, 2, 3 }; - int[] z = x[^0..]; // #error: Index out of bounds, was 3, exceeding maximum (2) + int[] z = x[^0..]; // #error: Index out of bounds: the start } fn void test10() @@ -77,11 +77,11 @@ fn void test105() int[] w = a.z[0..]; // #error: Omitting end index is not allowed for pointers int[] z = a.z[^2..]; // #error: Indexing from the end is not allowed for pointers int[] y = a.z[..^2]; // #error: Indexing from the end is not allowed for pointers - a.z[-10..-3]; // #error: Index out of bounds, using a negative index is only allowed for pointers + a.z[-10..-3]; // #error: An index may only be negative for pointers } fn void test11() { int[3] x = { 1, 2, 3 }; - int[] z = x[..^0]; // #error: End index out of bounds, was 3, exceeding 3. + int[] z = x[..^0]; // #error: End index out of bounds, was 3, exceeding }