diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4d55488b8..f42e4fa3e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -216,7 +216,7 @@ jobs: fail-fast: false matrix: build_type: [Release, Debug] - llvm_version: [17, 18, 19] + llvm_version: [17, 18, 19, 20] steps: - uses: actions/checkout@v4 @@ -375,7 +375,7 @@ jobs: fail-fast: false matrix: build_type: [Release, Debug] - llvm_version: [17, 18, 19] + llvm_version: [17, 18, 19, 20] steps: - uses: actions/checkout@v4 - name: Install common deps @@ -496,7 +496,7 @@ jobs: matrix: ubuntu_version: [20.04, 22.04] build_type: [Release, Debug] - llvm_version: [17, 18, 19] + llvm_version: [17, 18, 19, 20] steps: - uses: actions/checkout@v4 diff --git a/lib/std/io/formatter.c3 b/lib/std/io/formatter.c3 index b5fcfabfe..e2e872198 100644 --- a/lib/std/io/formatter.c3 +++ b/lib/std/io/formatter.c3 @@ -173,6 +173,10 @@ fn usz! Formatter.out_str(&self, any arg) @private case FUNC: return self.out_substr(""); case DISTINCT: + if (arg.type == String.typeid) + { + return self.out_substr(*(String*)arg); + } if (arg.type == ZString.typeid) { return self.out_substr(*(ZString*)arg ? ((ZString*)arg).str_view() : "(null)"); @@ -255,10 +259,6 @@ fn usz! Formatter.out_str(&self, any arg) @private case SLICE: // this is SomeType[] so grab the "SomeType" typeid inner = arg.type.inner; - if (inner == char.typeid) - { - return self.out_substr(*(String*)arg); - } if (inner == void.typeid) inner = char.typeid; PrintFlags flags = self.flags; uint width = self.width; diff --git a/releasenotes.md b/releasenotes.md index 3cceaba31..a510725e7 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -1,5 +1,17 @@ # C3C Release Notes +## 0.6.4 Change list + +### Changes / improvements +- Const vector -> const slice implicit conversion. +- Slicing arrays, slices and bytes at compile time #1466. + +### Fixes +- `Unsupported int[*] $x = { 1, 2, 3, 4 }` #1489. + +### Stdlib changes +- Remove unintended print of `char[]` as String + ## 0.6.3 Change list ### Changes / improvements diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 34bcd5bba..fa6503850 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -154,6 +154,7 @@ typedef struct Decl *enum_err_val; Type *typeid; ConstInitializer *initializer; + ConstInitializer *slice_init; Expr **untyped_list; struct { @@ -2269,7 +2270,7 @@ bool sema_analyse_cond_expr(SemaContext *context, Expr *expr, CondResult *result bool sema_analyse_expr_rhs(SemaContext *context, Type *to, Expr *expr, bool allow_optional, bool *no_match_ref, bool as_binary); -ArrayIndex sema_get_initializer_const_array_size(SemaContext *context, Expr *initializer, bool *may_be_array, bool *is_const_size); + bool sema_analyse_expr(SemaContext *context, Expr *expr); bool sema_cast_const(Expr *expr); @@ -3206,10 +3207,11 @@ static inline void expr_set_span(Expr *expr, SourceSpan loc); bool const_init_local_init_may_be_global(ConstInitializer *init); ConstInitializer *const_init_new_zero(Type *type); ConstInitializer *const_init_new_value(Expr *value); -ConstInitializer *const_init_new_array(Type *type, ConstInitializer **elements); +ConstInitializer *const_init_new_array(Type *type, ConstInitializer **elements) UNUSED; 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); void const_init_rewrite_to_value(ConstInitializer *const_init, Expr *value); void const_init_rewrite_to_zero(ConstInitializer *init, Type *type); @@ -3521,6 +3523,15 @@ INLINE void expr_rewrite_const_null(Expr *expr, Type *type) expr->resolve_status = RESOLVE_DONE; } +INLINE void expr_rewrite_const_empty_slice(Expr *expr, Type *type) +{ + assert(type_flatten(type)->type_kind == TYPE_SLICE); + expr->const_expr = (ExprConst) { .const_kind = CONST_SLICE, .initializer = NULL }; + expr->expr_kind = EXPR_CONST; + expr->type = type; + expr->resolve_status = RESOLVE_DONE; +} + INLINE void expr_rewrite_const_untyped_list(Expr *expr, Expr **elements) { expr->expr_kind = EXPR_CONST; @@ -3531,6 +3542,7 @@ INLINE void expr_rewrite_const_untyped_list(Expr *expr, Expr **elements) INLINE void expr_rewrite_const_initializer(Expr *expr, Type *type, ConstInitializer *initializer) { + assert(type_flatten(type)->type_kind != TYPE_SLICE); assert(type != type_untypedlist); expr->expr_kind = EXPR_CONST; expr->type = type; @@ -3538,6 +3550,16 @@ INLINE void expr_rewrite_const_initializer(Expr *expr, Type *type, ConstInitiali expr->resolve_status = RESOLVE_DONE; } +INLINE void expr_rewrite_const_slice(Expr *expr, Type *type, ConstInitializer *initializer) +{ + assert(type_flatten(type)->type_kind == TYPE_SLICE); + assert(type != type_untypedlist); + expr->expr_kind = EXPR_CONST; + expr->type = type; + expr->const_expr = (ExprConst) { .slice_init = initializer, .const_kind = CONST_SLICE }; + expr->resolve_status = RESOLVE_DONE; +} + INLINE void expr_rewrite_const_typeid(Expr *expr, Type *type) { expr->expr_kind = EXPR_CONST; @@ -3680,6 +3702,12 @@ INLINE unsigned arg_bits_max(AsmArgBits bits, unsigned limit) return 0; } +INLINE bool expr_is_empty_const_slice(Expr *expr) +{ + return expr->expr_kind == EXPR_CONST + && expr->const_expr.const_kind == CONST_SLICE + && expr->const_expr.slice_init == NULL; +} INLINE bool expr_is_const(Expr *expr) { @@ -3738,6 +3766,11 @@ INLINE bool expr_is_const_initializer(Expr *expr) return expr->expr_kind == EXPR_CONST && expr->const_expr.const_kind == CONST_INITIALIZER; } +INLINE bool expr_is_const_slice(Expr *expr) +{ + return expr->expr_kind == EXPR_CONST && expr->const_expr.const_kind == CONST_SLICE; +} + INLINE bool expr_is_const_bytes(Expr *expr) { return expr->expr_kind == EXPR_CONST && expr->const_expr.const_kind == CONST_BYTES; diff --git a/src/compiler/copying.c b/src/compiler/copying.c index a8c7a2435..3df845e07 100644 --- a/src/compiler/copying.c +++ b/src/compiler/copying.c @@ -220,6 +220,7 @@ INLINE ConstInitializer **copy_const_initializer_list(CopyStruct *c, ConstInitia static inline void copy_const_initializer(CopyStruct *c, ConstInitializer **initializer_ref) { + if (!*initializer_ref) return; ConstInitializer *copy = MALLOCS(ConstInitializer); *copy = **initializer_ref; *initializer_ref = copy; @@ -272,6 +273,9 @@ INLINE Expr *copy_const_expr(CopyStruct *c, Expr *expr) case CONST_POINTER: case CONST_TYPEID: break; + case CONST_SLICE: + copy_const_initializer(c, &expr->const_expr.slice_init); + break; case CONST_INITIALIZER: copy_const_initializer(c, &expr->const_expr.initializer); break; diff --git a/src/compiler/enums.h b/src/compiler/enums.h index 1d6fe88fd..7724c6563 100644 --- a/src/compiler/enums.h +++ b/src/compiler/enums.h @@ -621,6 +621,7 @@ typedef enum CONST_STRING, CONST_POINTER, CONST_TYPEID, + CONST_SLICE, CONST_INITIALIZER, CONST_UNTYPED_LIST, CONST_REF, diff --git a/src/compiler/expr.c b/src/compiler/expr.c index 14a2376c7..e11b92307 100644 --- a/src/compiler/expr.c +++ b/src/compiler/expr.c @@ -552,10 +552,12 @@ void expr_rewrite_to_const_zero(Expr *expr, Type *type) case TYPE_INFERRED_ARRAY: case TYPE_FLEXIBLE_ARRAY: UNREACHABLE + case TYPE_SLICE: + expr_rewrite_const_empty_slice(expr, type); + return; case TYPE_STRUCT: case TYPE_UNION: case TYPE_BITSTRUCT: - case TYPE_SLICE: case TYPE_VECTOR: case TYPE_ARRAY: expr_rewrite_const_initializer(expr, type, const_init_new_zero(type)); diff --git a/src/compiler/headers.c b/src/compiler/headers.c index 0ae8ba2c4..ff4ce5450 100644 --- a/src/compiler/headers.c +++ b/src/compiler/headers.c @@ -654,6 +654,7 @@ static void header_gen_global_var(HeaderContext *c, Decl *decl, bool fn_globals, case CONST_ERR: PRINTF("%s\n", decl_get_extname(init->const_expr.enum_err_val)); return; + case CONST_SLICE: case CONST_TYPEID: case CONST_MEMBER: case CONST_INITIALIZER: diff --git a/src/compiler/llvm_codegen.c b/src/compiler/llvm_codegen.c index 14a3c45a5..64d72b65a 100644 --- a/src/compiler/llvm_codegen.c +++ b/src/compiler/llvm_codegen.c @@ -225,11 +225,13 @@ LLVMValueRef llvm_emit_const_initializer(GenContext *c, ConstInitializer *const_ switch (const_init->kind) { case CONST_INIT_ZERO: + assert(const_init->type->type_kind != TYPE_SLICE); return llvm_get_zero(c, const_init->type); case CONST_INIT_ARRAY_VALUE: UNREACHABLE case CONST_INIT_ARRAY_FULL: { + assert(const_init->type->type_kind != TYPE_SLICE); bool was_modified = false; Type *array_type = const_init->type; Type *element_type = array_type->array.base; @@ -258,6 +260,7 @@ LLVMValueRef llvm_emit_const_initializer(GenContext *c, ConstInitializer *const_ case CONST_INIT_ARRAY: { + assert(const_init->type->type_kind != TYPE_SLICE); bool was_modified = false; Type *array_type = const_init->type; Type *element_type = array_type->array.base; @@ -492,6 +495,7 @@ void llvm_emit_global_variable_init(GenContext *c, Decl *decl) { if (expr_is_const_initializer(init_expr)) { + assert(type_flatten(init_expr->type)->type_kind != TYPE_SLICE); ConstInitializer *list = init_expr->const_expr.initializer; init_value = llvm_emit_const_initializer(c, list); } diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index a8dabf2a8..1d985e26f 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -1432,7 +1432,6 @@ void llvm_emit_cast(GenContext *c, CastKind cast_kind, Expr *expr, BEValue *valu Type *to_type_original = to_type; to_type = type_flatten(to_type); from_type = type_flatten(from_type); - switch (cast_kind) { case CAST_BSBOOL: @@ -1756,7 +1755,7 @@ static inline void llvm_emit_const_initialize_bitstruct_ref(GenContext *c, BEVal llvm_store_raw(c, ref, llvm_emit_const_bitstruct(c, initializer)); } -static void llvm_emit_const_init_ref(GenContext *c, BEValue *ref, ConstInitializer *const_init) +static void llvm_emit_const_init_ref(GenContext *c, BEValue *ref, ConstInitializer *const_init, bool top) { if (const_init->type->type_kind == TYPE_VECTOR) { @@ -1778,7 +1777,7 @@ static void llvm_emit_const_init_ref(GenContext *c, BEValue *ref, ConstInitializ // In case of small const initializers, or full arrays - use copy. if (const_init->kind == CONST_INIT_ARRAY_FULL || type_size(const_init->type) <= 32) { - if (const_init_local_init_may_be_global(const_init)) + if (top && const_init_local_init_may_be_global(const_init)) { llvm_emit_initialize_reference_temporary_const(c, ref, const_init); return; @@ -1814,7 +1813,7 @@ static void llvm_emit_const_init_ref(GenContext *c, BEValue *ref, ConstInitializ LLVMValueRef array_pointer = llvm_emit_array_gep_raw(c, array_ref, array_type_llvm, (unsigned)i, ref->alignment, &alignment); BEValue value; llvm_value_set_address(&value, array_pointer, element_type, alignment); - llvm_emit_const_init_ref(c, &value, const_init->init_array_full[i]); + llvm_emit_const_init_ref(c, &value, const_init->init_array_full[i], false); } return; } @@ -1836,7 +1835,7 @@ static void llvm_emit_const_init_ref(GenContext *c, BEValue *ref, ConstInitializ LLVMValueRef array_pointer = llvm_emit_array_gep_raw(c, array_ref, array_type_llvm, (unsigned)element_index, ref->alignment, &alignment); BEValue value; llvm_value_set_address(&value, array_pointer, element_type, alignment); - llvm_emit_const_init_ref(c, &value, element->init_array_value.element); + llvm_emit_const_init_ref(c, &value, element->init_array_value.element, false); } return; } @@ -1850,7 +1849,7 @@ static void llvm_emit_const_init_ref(GenContext *c, BEValue *ref, ConstInitializ llvm_value_bitcast(c, &value, type); // llvm_value_set_address_abi_aligned(&value, llvm_emit_bitcast_ptr(c, ref->value, type), type); // Emit our value. - llvm_emit_const_init_ref(c, &value, const_init->init_union.element); + llvm_emit_const_init_ref(c, &value, const_init->init_union.element, false); return; } case CONST_INIT_STRUCT: @@ -1861,7 +1860,7 @@ static void llvm_emit_const_init_ref(GenContext *c, BEValue *ref, ConstInitializ { BEValue value; llvm_value_struct_gep(c, &value, ref, (unsigned)i); - llvm_emit_const_init_ref(c, &value, init); + llvm_emit_const_init_ref(c, &value, init, false); } return; } @@ -1941,6 +1940,7 @@ static inline void llvm_emit_initialize_reference_list(GenContext *c, BEValue *r { Type *type = type_flatten(expr->type); Expr **elements = expr->initializer_list; + assert(type->type_kind != TYPE_SLICE); if (type->type_kind == TYPE_BITSTRUCT) { @@ -2169,8 +2169,8 @@ static inline void llvm_emit_initialize_reference_designated(GenContext *c, BEVa { Expr **elements = expr->designated_init_list; assert(vec_size(elements)); - Type *type = type_flatten(expr->type); + assert(type->type_kind != TYPE_SLICE); if (type->type_kind == TYPE_BITSTRUCT) { llvm_emit_initialize_reference_designated_bitstruct(c, ref, type->decl, elements); @@ -2339,7 +2339,8 @@ LLVMValueRef llvm_emit_const_bitstruct(GenContext *c, ConstInitializer *initiali static inline void llvm_emit_const_initialize_reference(GenContext *c, BEValue *ref, Expr *expr) { assert(expr_is_const_initializer(expr)); - llvm_emit_const_init_ref(c, ref, expr->const_expr.initializer); + assert(type_flatten(expr->type)->type_kind != TYPE_SLICE); + llvm_emit_const_init_ref(c, ref, expr->const_expr.initializer, true); return; } @@ -4992,6 +4993,7 @@ static inline void llvm_emit_const_initializer_list_expr(GenContext *c, BEValue { if (llvm_is_global_eval(c) || type_flat_is_vector(expr->type) || type_flatten(expr->type)->type_kind == TYPE_BITSTRUCT) { + assert(type_flatten(expr->type)->type_kind != TYPE_SLICE); llvm_value_set(value, llvm_emit_const_initializer(c, expr->const_expr.initializer), expr->type); return; } @@ -5038,6 +5040,39 @@ static void llvm_emit_const_expr(GenContext *c, BEValue *be_value, Expr *expr) case CONST_FLOAT: llvm_value_set(be_value, llvm_emit_real(llvm_get_type(c, type), expr->const_expr.fxx), type); return; + case CONST_SLICE: + if (!expr->const_expr.slice_init) + { + llvm_value_set(be_value, llvm_get_zero(c, type), type); + return; + } + else + { + ConstInitializer *init = expr->const_expr.slice_init; + if (llvm_is_global_eval(c) || type_flat_is_vector(expr->type) || type_flatten(expr->type)->type_kind == TYPE_BITSTRUCT) + { + LLVMValueRef value = llvm_emit_const_initializer(c, init); + AlignSize alignment = type_alloca_alignment(init->type); + LLVMTypeRef val_type = llvm_get_type(c, init->type); + LLVMValueRef global_copy = llvm_add_global_raw(c, ".__const_slice", val_type, alignment); + LLVMSetInitializer(global_copy, value); + llvm_set_private_linkage(global_copy); + LLVMSetUnnamedAddress(global_copy, LLVMGlobalUnnamedAddr); + assert(type_is_arraylike(init->type)); + LLVMValueRef val = llvm_emit_aggregate_two(c, type, global_copy, + llvm_const_int(c, type_usz, init->type->array.len)); + llvm_value_set(be_value, val, type); + } + else + { + assert(type_is_arraylike(init->type)); + llvm_value_set_address_abi_aligned(be_value, llvm_emit_alloca_aligned(c, init->type, "literal"), init->type); + llvm_emit_const_init_ref(c, be_value, init, true); + LLVMValueRef val = llvm_emit_aggregate_two(c, type, be_value->value, llvm_const_int(c, type_usz, init->type->array.len)); + llvm_value_set(be_value, val, type); + } + } + return; case CONST_POINTER: if (!expr->const_expr.ptr) { diff --git a/src/compiler/number.c b/src/compiler/number.c index bf8c0cb19..77be41c38 100644 --- a/src/compiler/number.c +++ b/src/compiler/number.c @@ -51,22 +51,20 @@ static inline bool compare_fps(Real left, Real right, BinaryOp op) } void expr_contract_array(ExprConst *expr_const, ConstKind contract_type) { - if (expr_const->const_kind == CONST_POINTER) + if (expr_const->const_kind == CONST_SLICE && !expr_const->slice_init) { *expr_const = (ExprConst) { .const_kind = contract_type }; return; } - assert(expr_const->const_kind == CONST_INITIALIZER); - Type *type = expr_const->initializer->type; + assert(expr_const->const_kind == CONST_INITIALIZER || expr_const->const_kind == CONST_SLICE); + ConstInitializer *initializer = expr_const->const_kind == CONST_SLICE + ? expr_const->slice_init + : expr_const->initializer; + Type *type = initializer->type; assert(type_is_any_arraylike(type)); ArraySize len = type->array.len; - if (!len) - { - *expr_const = (ExprConst) { .const_kind = contract_type }; - return; - } + assert(len > 0); char *arr = calloc_arena(len); - ConstInitializer *initializer = expr_const->initializer; switch (initializer->kind) { case CONST_INIT_ZERO: @@ -206,6 +204,8 @@ bool expr_const_compare(const ExprConst *left, const ExprConst *right, BinaryOp } is_eq = !memcmp(left->bytes.ptr, right->bytes.ptr, left->bytes.len); goto RETURN; + case CONST_SLICE: + return false; case CONST_INITIALIZER: return false; case CONST_UNTYPED_LIST: @@ -279,6 +279,7 @@ bool expr_const_will_overflow(const ExprConst *expr, TypeKind kind) case CONST_STRING: case CONST_POINTER: case CONST_TYPEID: + case CONST_SLICE: case CONST_INITIALIZER: case CONST_UNTYPED_LIST: case CONST_MEMBER: @@ -316,6 +317,7 @@ const char *expr_const_to_error_string(const ExprConst *expr) return type_to_error_string(expr->typeid); case CONST_MEMBER: return "member"; + case CONST_SLICE: case CONST_INITIALIZER: return "constant list"; case CONST_UNTYPED_LIST: diff --git a/src/compiler/sema_casts.c b/src/compiler/sema_casts.c index fb705712a..601acb752 100644 --- a/src/compiler/sema_casts.c +++ b/src/compiler/sema_casts.c @@ -968,6 +968,11 @@ static bool rule_slice_to_slice(CastContext *cc, bool is_explicit, bool is_silen static bool rule_arr_to_arr(CastContext *cc, bool is_explicit, bool is_silent) { + if (type_flatten(cc->to)->array.len != type_flatten(cc->from)->array.len) + { + if (is_silent) return false; + RETURN_CAST_ERROR(cc->expr, "Arrays of different lengths may not be converted."); + } if (type_size(cc->from) != type_size(cc->to)) { if (is_silent) return false; @@ -1010,6 +1015,18 @@ static bool rule_vec_to_arr(CastContext *cc, bool is_explicit, bool is_silent) return cast_is_allowed(cc, is_explicit, is_silent); } +static bool rule_vecarr_to_slice(CastContext *cc, bool is_explicit, bool is_silent) +{ + Expr *expr = cc->expr; + if (expr_is_const(expr)) + { + cast_context_set_to(cc, type_get_inferred_array(type_get_indexed_type(cc->to_type))); + return cast_is_allowed(cc, is_explicit, is_silent); + } + if (is_silent) return false; + RETURN_CAST_ERROR(expr, "Conversions from arrays or vectors to slices are only permitted on constant arrays, use `&arr` or `arr[..]` instead."); +} + static bool rule_slice_to_vecarr(CastContext *cc, bool is_explicit, bool is_silent) { Expr *expr = cc->expr; @@ -2009,26 +2026,10 @@ static void cast_ptr_to_bool(SemaContext *context, Expr *expr, Type *type) static void cast_slice_to_bool(SemaContext *context, Expr *expr, Type *type) { - if (expr_is_const_initializer(expr)) + if (expr_is_const_slice(expr)) { - ConstInitializer *list = expr->const_expr.initializer; - switch (list->kind) - { - case CONST_INIT_ZERO: - expr_rewrite_const_bool(expr, type, false); - return; - case CONST_INIT_ARRAY: - expr_rewrite_const_bool(expr, type, vec_size(list->init_array.elements) > 0); - return; - case CONST_INIT_ARRAY_FULL: - expr_rewrite_const_bool(expr, type, vec_size(list->init_array_full) > 0); - return; - case CONST_INIT_STRUCT: - case CONST_INIT_UNION: - case CONST_INIT_VALUE: - case CONST_INIT_ARRAY_VALUE: - break; - } + expr_rewrite_const_bool(expr, type, expr->const_expr.slice_init != NULL); + return; } insert_runtime_cast(expr, CAST_SLBOOL, type); } @@ -2050,6 +2051,40 @@ static void cast_slice_to_slice(SemaContext *context, Expr *expr, Type *to_type) insert_runtime_cast(expr, CAST_SLSL, to_type); } +static void cast_vecarr_to_slice(SemaContext *context, Expr *expr, Type *to_type) +{ + if (!sema_cast_const(expr)) + { + UNREACHABLE + } + assert(expr_is_const(expr)); + switch (expr->const_expr.const_kind) + { + case CONST_FLOAT: + case CONST_INTEGER: + case CONST_BOOL: + case CONST_ENUM: + case CONST_ERR: + case CONST_POINTER: + case CONST_TYPEID: + case CONST_SLICE: + case CONST_UNTYPED_LIST: + case CONST_REF: + case CONST_MEMBER: + UNREACHABLE + case CONST_BYTES: + case CONST_STRING: + expr->type = to_type; + return; + case CONST_INITIALIZER: + { + ConstInitializer *init = expr->const_expr.slice_init; + expr_rewrite_const_slice(expr, to_type, init); + return; + } + } + UNREACHABLE +} static void cast_slice_to_vecarr(SemaContext *context, Expr *expr, Type *to_type) { if (!sema_cast_const(expr)) @@ -2074,6 +2109,10 @@ static void cast_slice_to_vecarr(SemaContext *context, Expr *expr, Type *to_type assert(expr->expr_kind == EXPR_CAST); return; } + if (expr_is_const_slice(expr)) + { + expr->const_expr.const_kind = CONST_INITIALIZER; + } assert(expr_is_const(expr)); expr->type = to_type; return; @@ -2190,6 +2229,7 @@ static void cast_typeid_to_bool(SemaContext *context, Expr *expr, Type *to_type) #define AF2BO &cast_anyfault_to_bool #define AF2FA &cast_anyfault_to_fault #define SL2VA &cast_slice_to_vecarr +#define VA2SL &cast_vecarr_to_slice #define XX2VO &cast_all_to_void #define SL2FE &cast_slice_to_infer #define VA2FE &cast_vecarr_to_infer @@ -2227,6 +2267,7 @@ static void cast_typeid_to_bool(SemaContext *context, Expr *expr, Type *to_type) #define RSTDI &rule_to_struct_to_distinct /* Struct -> inline (struct inline = distinct, distinct inline = struct if explicit flatten) */ #define RSLFE &rule_slice_to_infer /* Slice -> infer (only if slice is constant or can infer) */ #define RVAFE &rule_vecarr_to_infer /* Vec/arr -> infer (if base matches) */ +#define RVASL &rule_vecarr_to_slice /* Vec/arr -> slice (if base matches) */ #define RPTFE &rule_ptr_to_infer /* Ptr -> infer (if pointee may infer) */ #define RPTIF &rule_ptr_to_interface /* Ptr -> Interface if the pointee implements it */ #define RIFIF &rule_interface_to_interface/* Interface -> Interface if the latter implements all of the former */ @@ -2243,10 +2284,10 @@ CastRule cast_rules[CONV_LAST + 1][CONV_LAST + 1] = { {REXPL, _NO__, REXPL, REXPL, RWIDE, _NO__, _NO__, REXVC, _NO__, RXXDI, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__}, // FLOAT {REXPL, _NO__, REXPL, RPTIN, _NO__, RPTPT, _NO__, REXVC, _NO__, RXXDI, _NO__, _NO__, _NO__, ROKOK, RPTIF, _NO__, _NO__, _NO__, _NO__, _NO__, ROKOK, RPTPT, RPTFE, _NO__}, // PTR {REXPL, _NO__, REXPL, _NO__, _NO__, RSLPT, RSLSL, RSLVA, _NO__, RXXDI, RSLVA, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, ROKOK, RSLPT, RSLFE, _NO__}, // SLICE - {REXPL, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, RVCVC, _NO__, RXXDI, RVCAR, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, RVAFE, _NO__}, // VECTOR + {REXPL, _NO__, _NO__, _NO__, _NO__, _NO__, RVASL, RVCVC, _NO__, RXXDI, RVCAR, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, RVAFE, _NO__}, // VECTOR {REXPL, _NO__, REXPL, RBSIN, _NO__, _NO__, _NO__, _NO__, _NO__, RXXDI, RBSAR, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__}, // BITSTRUCT {REXPL, _NO__, RDIXX, RDIXX, RDIXX, RDIXX, RDIXX, RDIXX, RDIXX, RDIDI, RDIXX, RDIXX, RDIXX, RDIXX, RDIXX, RDIXX, RDIXX, RDIXX, RDIXX, RDIXX, RDIXX, RDIXX, RDIXX, _NO__}, // DISTINCT - {REXPL, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, RARVC, RARBS, RXXDI, RARAR, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, RVAFE, _NO__}, // ARRAY + {REXPL, _NO__, _NO__, _NO__, _NO__, _NO__, RVASL, RARVC, RARBS, RXXDI, RARAR, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, RVAFE, _NO__}, // ARRAY {REXPL, _NO__, RSTST, RSTST, RSTST, RSTST, RSTST, RSTST, RSTST, RSTDI, RSTST, RSTST, RSTST, RSTST, RSTST, RSTST, RSTST, RSTST, RSTST, RSTST, RSTST, RSTST, _NO__, _NO__}, // STRUCT {REXPL, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, RXXDI, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__, _NO__}, // UNION {REXPL, _NO__, REXPL, _NO__, _NO__, REXPL, _NO__, _NO__, _NO__, RXXDI, _NO__, _NO__, _NO__, _NA__, REXPL, _NO__, _NO__, _NO__, _NO__, _NO__, ROKOK, REXPL, _NO__, _NO__}, // ANY @@ -2271,10 +2312,10 @@ CastFunction cast_function[CONV_LAST + 1][CONV_LAST + 1] = { {XX2VO, 0, FP2BO, FP2IN, FP2FP, 0, 0, EX2VC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // FLOAT {XX2VO, 0, PT2BO, PT2IN, 0, PT2PT, 0, EX2VC, 0, 0, 0, 0, 0, PT2AY, PT2AY, 0, 0, 0, 0, 0, PT2PT, PT2PT, PT2FE, 0 }, // PTR {XX2VO, 0, SL2BO, 0, 0, SL2PT, SL2SL, SL2VA, 0, 0, SL2VA, 0, 0, 0, 0, 0, 0, 0, 0, 0, SL2PT, SL2PT, SL2FE, 0 }, // SLICE - {XX2VO, 0, 0, 0, 0, 0, 0, VC2VC, 0, 0, VC2AR, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, VA2FE, 0 }, // VECTOR + {XX2VO, 0, 0, 0, 0, 0, VA2SL, VC2VC, 0, 0, VC2AR, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, VA2FE, 0 }, // VECTOR {XX2VO, 0, BS2BO, BS2IA, 0, 0, 0, 0, 0, 0, BS2IA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // BITSTRUCT { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // DISTINCT - {XX2VO, 0, 0, 0, 0, 0, 0, AR2VC, IA2BS, 0, AR2AR, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, VA2FE, 0 }, // ARRAY + {XX2VO, 0, 0, 0, 0, 0, VA2SL, AR2VC, IA2BS, 0, AR2AR, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, VA2FE, 0 }, // ARRAY {XX2VO, 0, ST2LN, ST2LN, ST2LN, ST2LN, ST2LN, ST2LN, ST2LN, 0, ST2LN, ST2LN, ST2LN, ST2LN, ST2LN, ST2LN, ST2LN, ST2LN,ST2LN, ST2LN, ST2LN, ST2LN, 0, 0 }, // STRUCT {XX2VO, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // UNION {XX2VO, 0, AY2BO, 0, 0, AY2PT, 0, 0, 0, 0, 0, 0, 0, PT2PT, PT2PT, 0, 0, 0, 0, 0, AY2PT, AY2PT, 0, 0 }, // ANY diff --git a/src/compiler/sema_const.c b/src/compiler/sema_const.c index 717081695..6c883c87c 100644 --- a/src/compiler/sema_const.c +++ b/src/compiler/sema_const.c @@ -3,48 +3,10 @@ // a copy of which can be found in the LICENSE file. #include "sema_internal.h" -static inline ArraySize sema_get_const_len(SemaContext *context, Expr *expr); + static bool sema_append_const_array_one(SemaContext *context, Expr *expr, Expr *list, Expr *element); -static ArrayIndex len_from_const_initializer(ConstInitializer *init); static bool sema_append_concat_const_bytes(SemaContext *context, Expr *expr, Expr *list, Expr *element, bool is_append); - -typedef enum -{ - CONCAT_UNKNOWN, - CONCAT_JOIN_BYTES, - CONCAT_JOIN_ARRAYS, - CONCAT_JOIN_LISTS, -} ConcatType; - - -static ArrayIndex len_from_const_initializer(ConstInitializer *init) -{ - switch (init->kind) - { - case CONST_INIT_ZERO: - return 0; - case CONST_INIT_STRUCT: - case CONST_INIT_UNION: - case CONST_INIT_VALUE: - case CONST_INIT_ARRAY_VALUE: - return -1; - case CONST_INIT_ARRAY: - { - ArrayIndex max = 0; - FOREACH(ConstInitializer *, element, init->init_array.elements) - { - assert(element->kind == CONST_INIT_ARRAY_VALUE); - if (element->init_array_value.index > max) max = element->init_array_value.index; - } - return max; - } - case CONST_INIT_ARRAY_FULL: - return vec_size(init->init_array_full); - } - UNREACHABLE -} - ArrayIndex sema_len_from_const(Expr *expr) { // We also handle the case where we have a cast from a const array. @@ -63,6 +25,7 @@ ArrayIndex sema_len_from_const(Expr *expr) if (!sema_cast_const(inner)) return -1; expr = inner; } + ConstInitializer *init; switch (expr->const_expr.const_kind) { case CONST_FLOAT: @@ -75,17 +38,24 @@ ArrayIndex sema_len_from_const(Expr *expr) case CONST_REF: return -1; case CONST_POINTER: - if (type_flatten(expr->type)->type_kind == TYPE_SLICE) return 0; return -1; case CONST_BYTES: case CONST_STRING: return expr->const_expr.bytes.len; + case CONST_SLICE: + if (!expr->const_expr.slice_init) return 0; + init = expr->const_expr.slice_init; + goto ARRAY_LEN; case CONST_INITIALIZER: - return len_from_const_initializer(expr->const_expr.initializer); + init = expr->const_expr.initializer; + goto ARRAY_LEN; case CONST_UNTYPED_LIST: return vec_size(expr->const_expr.untyped_list); } UNREACHABLE +ARRAY_LEN: + if (type_is_arraylike(init->type)) return init->type->array.len; + return -1; } static inline bool sema_expr_const_append(SemaContext *context, Expr *append_expr, Expr *list, Expr *element) @@ -94,17 +64,13 @@ static inline bool sema_expr_const_append(SemaContext *context, Expr *append_exp switch (list->const_expr.const_kind) { case CONST_INITIALIZER: + case CONST_SLICE: assert(list->type != type_untypedlist); return sema_append_const_array_one(context, append_expr, list, element); case CONST_UNTYPED_LIST: untyped_list = list->const_expr.untyped_list; break; case CONST_POINTER: - if (list->type->canonical->type_kind == TYPE_SLICE) - { - return sema_append_const_array_one(context, append_expr, list, element); - } - FALLTHROUGH; case CONST_BYTES: case CONST_STRING: return sema_append_concat_const_bytes(context, append_expr, list, element, true); @@ -222,6 +188,7 @@ static bool sema_concat_bytes_and_other(SemaContext *context, Expr *expr, Expr * case CONST_UNTYPED_LIST: if (!cast_implicit(context, right, type_get_inferred_array(indexed), false)) return false; goto RETRY; + case CONST_SLICE: case CONST_INITIALIZER: if (!cast_implicit(context, right, type_get_inferred_array(indexed), false)) return false; expr_contract_array(&right->const_expr, left->const_expr.const_kind); @@ -262,63 +229,63 @@ static bool sema_append_concat_const_bytes(SemaContext *context, Expr *expr, Exp return true; } -// TODO there is also another const_len... look at that. -static inline ArraySize sema_get_const_len(SemaContext *context, Expr *expr) +static bool sema_append_const_array_one(SemaContext *context, Expr *expr, Expr *list, Expr *element) { - switch (expr->const_expr.const_kind) + Type *array_type = type_flatten(list->type); + if (expr_is_empty_const_slice(list)) { - case CONST_FLOAT: - case CONST_INTEGER: - case CONST_BOOL: - case CONST_ENUM: - case CONST_ERR: - case CONST_POINTER: - case CONST_TYPEID: - case CONST_REF: - return 1; - case CONST_BYTES: - case CONST_STRING: - return expr->const_expr.bytes.len; - case CONST_INITIALIZER: - { - bool may_be_array; - bool is_const_size; - ArrayIndex len = (ArraySize) sema_get_initializer_const_array_size(context, expr, &may_be_array, - &is_const_size); - assert(is_const_size); - return (ArraySize) len; - } - case CONST_UNTYPED_LIST: - return vec_size(expr->const_expr.untyped_list); - case CONST_MEMBER: - return 1; + // Create a single length array + ConstInitializer *first_element = const_init_new_value(element); + ConstInitializer **list_of_elements = NULL; + vec_add(list_of_elements, first_element); + list->const_expr.slice_init = const_init_new_array_full(type_get_array(array_type->array.base, 1), list_of_elements); + expr_replace(expr, list); + return true; } - UNREACHABLE -} - -static bool sema_append_const_array_one(SemaContext *context, Expr *expr, Expr *list, Expr *element) -{ - bool is_empty_slice = list->const_expr.const_kind == CONST_POINTER; - if (!is_empty_slice && list->const_expr.initializer->kind != CONST_INIT_ARRAY_FULL) + bool is_slice = list->const_expr.const_kind == CONST_SLICE; + assert(!type_is_inferred(array_type)); + bool is_vector = array_type->type_kind == TYPE_VECTOR; + ConstInitializer *init = is_slice ? list->const_expr.slice_init : list->const_expr.initializer; + unsigned len = sema_len_from_const(list) + 1; + Type *indexed = type_get_indexed_type(init->type); + Type *new_inner_type = is_vector ? type_get_vector(indexed, len) : type_get_array(indexed, len); + Type *new_outer_type = list->type; + if (!is_slice) { - RETURN_SEMA_ERROR(list, "Only fully initialized arrays may be appended to."); + Type *outer_indexed = type_get_indexed_type(init->type); + new_outer_type = is_vector ? type_get_vector(outer_indexed, len) : type_get_array(outer_indexed, len); } - Type *array_type = type_flatten(list->type); - bool is_vector = array_type->type_kind == TYPE_VECTOR || array_type->type_kind == TYPE_INFERRED_VECTOR; - unsigned len = (is_empty_slice ? 0 : sema_get_const_len(context, list)) + 1; - Type *indexed = type_get_indexed_type(list->type); - Type *new_type = is_vector ? type_get_vector(indexed, len) : type_get_array(indexed, len); - ConstInitializer *init = list->const_expr.initializer; - ConstInitializer **inits = VECNEW(ConstInitializer*, len); - if (!is_empty_slice) + switch (init->kind) { - FOREACH(ConstInitializer *, i, init->init_array_full) vec_add(inits, i); + case CONST_INIT_ZERO: + { + init->kind = CONST_INIT_ARRAY; + init->type = new_inner_type; + ConstInitializer **inits = NULL; + vec_add(inits, const_init_new_array_value(element, len - 1)); + init->init_array.elements = inits; + expr_replace(expr, list); + expr->type = new_outer_type; + break; + } + case CONST_INIT_ARRAY: + init->type = new_inner_type; + vec_add(init->init_array.elements, const_init_new_array_value(element, len - 1)); + expr_replace(expr, list); + expr->type = new_outer_type; + break; + case CONST_INIT_ARRAY_FULL: + init->type = new_inner_type; + vec_add(init->init_array_full, const_init_new_value(element)); + expr_replace(expr, list); + expr->type = new_outer_type; + break; + case CONST_INIT_ARRAY_VALUE: + case CONST_INIT_STRUCT: + case CONST_INIT_UNION: + case CONST_INIT_VALUE: + UNREACHABLE } - - assert(element->resolve_status == RESOLVE_DONE); - if (!cast_implicit(context, element, indexed, false)) return false; - vec_add(inits, const_init_new_value(element)); - expr_rewrite_const_initializer(expr, new_type, const_init_new_array_full(new_type, inits)); return true; } @@ -345,17 +312,9 @@ bool sema_expr_analyse_ct_concat(SemaContext *context, Expr *concat_expr, Expr * if (!sema_cast_const(right)) RETURN_SEMA_ERROR(left, "Expected this to evaluate to a constant value."); Type *element_type = left->type->canonical; Type *right_type = right->type->canonical; - ConstKind right_kind = right->const_expr.const_kind; switch (left->const_expr.const_kind) { case CONST_POINTER: - if (element_type->type_kind == TYPE_SLICE) - { - len = 0; - indexed_type = type_get_indexed_type(element_type); - break; - } - FALLTHROUGH; case CONST_FLOAT: case CONST_INTEGER: case CONST_BOOL: @@ -363,47 +322,36 @@ bool sema_expr_analyse_ct_concat(SemaContext *context, Expr *concat_expr, Expr * case CONST_ERR: case CONST_TYPEID: case CONST_REF: + case CONST_MEMBER: RETURN_SEMA_ERROR(left, "Only bytes, strings and list-like constants can be concatenated."); case CONST_BYTES: case CONST_STRING: return sema_concat_bytes_and_other(context, concat_expr, left, right); + case CONST_SLICE: case CONST_INITIALIZER: switch (type_flatten(element_type)->type_kind) { case TYPE_VECTOR: - case TYPE_INFERRED_VECTOR: use_array = false; - FALLTHROUGH; + break; + case TYPE_INFERRED_VECTOR: + case TYPE_INFERRED_ARRAY: + UNREACHABLE case TYPE_SLICE: case TYPE_ARRAY: - case TYPE_INFERRED_ARRAY: - { - switch (left->const_expr.initializer->kind) - { - case CONST_INIT_ARRAY_FULL: - break; - case CONST_INIT_ZERO: - if (type_flatten(element_type)->type_kind == TYPE_SLICE) break; - FALLTHROUGH; - default: - RETURN_SEMA_ERROR(left, "Only fully initialized arrays may be concatenated."); - } - indexed_type = type_get_indexed_type(element_type); - assert(indexed_type); - len = sema_get_const_len(context, left); break; - } - case TYPE_UNTYPED_LIST: - UNREACHABLE - default: + case TYPE_STRUCT: + case TYPE_UNION: RETURN_SEMA_ERROR(left, "Only bytes, strings and array-like constants can be concatenated."); + default: + UNREACHABLE } + len = sema_len_from_const(left); + indexed_type = type_get_indexed_type(element_type); break; case CONST_UNTYPED_LIST: len = vec_size(left->const_expr.untyped_list); break; - case CONST_MEMBER: - RETURN_SEMA_ERROR(left, "This can't be concatenated."); } switch (right->const_expr.const_kind) { @@ -430,6 +378,7 @@ bool sema_expr_analyse_ct_concat(SemaContext *context, Expr *concat_expr, Expr * return sema_concat_bytes_and_other(context, concat_expr, left, right); case CONST_UNTYPED_LIST: break; + case CONST_SLICE: case CONST_INITIALIZER: if (indexed_type && cast_implicit_silent(context, right, indexed_type, false)) { @@ -441,7 +390,7 @@ bool sema_expr_analyse_ct_concat(SemaContext *context, Expr *concat_expr, Expr * { indexed_type = NULL; } - len += sema_get_const_len(context, right); + len += sema_len_from_const(right); if (!indexed_type) { Expr **untyped_exprs = VECNEW(Expr*, len + 1); diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index 8a1b9251c..540bd3f38 100755 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -3716,13 +3716,18 @@ bool sema_analyse_var_decl_ct(SemaContext *context, Decl *decl) // Resolve the type if it's present. if (type_info) { - if (!sema_resolve_type_info(context, type_info, RESOLVE_TYPE_DEFAULT)) goto FAIL; + if (!sema_resolve_type_info(context, type_info, RESOLVE_TYPE_ALLOW_INFER)) goto FAIL; // Set the type of the declaration. - decl->type = type_info->type->canonical; + decl->type = type_info->type; init = decl->var.init_expr; // If there is no init, set it to zero. if (!init) { + if (type_is_inferred(decl->type)) + { + SEMA_ERROR(type_info, "No size could be inferred."); + goto FAIL; + } decl->var.init_expr = init = expr_new(EXPR_POISONED, decl->span); expr_rewrite_to_const_zero(init, decl->type); } @@ -3730,6 +3735,10 @@ bool sema_analyse_var_decl_ct(SemaContext *context, Decl *decl) // Analyse the expression. if (!sema_analyse_expr_rhs(context, decl->type, init, false, NULL, false)) goto FAIL; + if (type_is_inferred(decl->type)) + { + decl->type = init->type; + } // Check that it is constant. if (!expr_is_runtime_const(init)) { diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 971e63532..99c38c2c1 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -182,7 +182,7 @@ static inline bool sema_expr_analyse_type_access(SemaContext *context, Expr *exp static inline bool sema_expr_analyse_member_access(SemaContext *context, Expr *expr, Expr *parent, Expr *identifier, bool *missing_ref); static inline bool sema_expr_fold_to_member(Expr *expr, Expr *parent, Decl *member); static inline bool sema_expr_fold_to_index(Expr *expr, Expr *parent, SubscriptIndex index); -static inline bool sema_expr_fold_to_range(Expr *expr, Expr *parent, Range range); + static inline void sema_expr_flatten_const_ident(Expr *expr); static inline bool sema_analyse_expr_check(SemaContext *context, Expr *expr, CheckType check); @@ -209,6 +209,7 @@ static inline bool sema_constant_fold_ops(Expr *expr) case CONST_MEMBER: return true; case CONST_INITIALIZER: + case CONST_SLICE: case CONST_UNTYPED_LIST: case CONST_REF: return false; @@ -3275,6 +3276,62 @@ static inline bool sema_expr_analyse_range(SemaContext *context, Range *range, T } } +static inline void sema_slice_initializer(SemaContext *context, Expr *expr, Expr *subscripted, Range *range) +{ + ConstInitializer *initializer = subscripted->const_expr.initializer; + assert(type_is_arraylike(initializer->type)); + Type *new_type = type_get_slice(type_get_indexed_type(subscripted->type)); + // Turn zero length into an untyped list. + if (range->len_index == 0) + { + expr_rewrite_const_empty_slice(expr, new_type); + return; + } + bool is_vec = initializer->type->type_kind == TYPE_VECTOR; + Type *inner_type = is_vec + ? type_get_vector(new_type->array.base, range->len_index) + : type_get_array(new_type->array.base, range->len_index); + initializer->type = inner_type; + switch (initializer->kind) + { + case CONST_INIT_ZERO: + break; + case CONST_INIT_ARRAY_FULL: + vec_erase_front(initializer->init_array_full, range->start_index); + vec_resize(initializer->init_array_full, range->len_index); + break; + case CONST_INIT_ARRAY: + { + unsigned elements = vec_size(initializer->init_array.elements); + for (unsigned i = 0; i < elements; i++) + { + ConstInitializer *element = initializer->init_array.elements[i]; + ArrayIndex index = element->init_array_value.index; + if (index < range->start_index || index >= range->start_index + range->len_index) + { + vec_erase_at(initializer->init_array.elements, i); + elements--; + i--; + continue; + } + } + if (vec_size(initializer->init_array.elements) == 0) + { + initializer->kind = CONST_INIT_ZERO; + break; + } + break; + } + case CONST_INIT_STRUCT: + case CONST_INIT_UNION: + case CONST_INIT_VALUE: + case CONST_INIT_ARRAY_VALUE: + UNREACHABLE + } + subscripted->const_expr.const_kind = CONST_SLICE; + expr_replace(expr, subscripted); + expr->type = new_type; +} static inline bool sema_expr_analyse_slice(SemaContext *context, Expr *expr, CheckType check) { @@ -3341,9 +3398,18 @@ static inline bool sema_expr_analyse_slice(SemaContext *context, Expr *expr, Che expr_replace(expr, subscripted); return true; case CONST_INITIALIZER: + sema_slice_initializer(context, expr, subscripted, range); + return true; + case CONST_SLICE: + if (!subscripted->const_expr.slice_init) + { + assert(range->len_index == 0); + expr_replace(expr, subscripted); + return true; + } + sema_slice_initializer(context, expr, subscripted, range); + return true; case CONST_POINTER: - // TODO slice - break; case CONST_FLOAT: case CONST_INTEGER: case CONST_BOOL: @@ -4156,77 +4222,6 @@ static bool sema_expr_rewrite_to_typeid_property(SemaContext *context, Expr *exp return false; } -static inline bool sema_expr_fold_to_range(Expr *expr, Expr *parent, Range range) -{ - bool is_vector = type_flat_is_vector(parent->type); - ConstInitializer *init = parent->const_expr.initializer; - ConstInitializer *result; - ASSERT_SPAN(expr, !range.start_from_end); - ArrayIndex start = range.start_index; - ArrayIndex len = range.len_index; - assert(len > 0); - ArrayIndex end = start + len; - Type *indexed = type_get_indexed_type(parent->type); - Type *resulting_type = is_vector ? type_get_vector(indexed, len) : type_get_array(indexed, len); - switch (init->kind) - { - case CONST_INIT_ZERO: - result = init; - break; - case CONST_INIT_STRUCT: - case CONST_INIT_UNION: - case CONST_INIT_VALUE: - case CONST_INIT_ARRAY_VALUE: - UNREACHABLE - case CONST_INIT_ARRAY: - { - ConstInitializer **new = NULL; - FOREACH(ConstInitializer *, e, init->init_array.elements) - { - ArrayIndex index = e->init_array_value.index; - if (index < start || index >= end) continue; - vec_add(new, e->init_array_value.element); - } - - result = new ? const_init_new_array(resulting_type, new) - : const_init_new_zero(resulting_type); - break; - } - case CONST_INIT_ARRAY_FULL: - { - ConstInitializer **new = NULL; - for (ArrayIndex i = start; i < end; i++) - { - vec_add(new, init->init_array_full[i]); - } - ASSERT_SPAN(expr, new); - result = const_init_new_array_full(resulting_type, new); - break; - } - } - result->type = type_flatten(resulting_type); - switch (result->kind) - { - case CONST_INIT_ZERO: - expr_rewrite_to_const_zero(expr, resulting_type); - break; - case CONST_INIT_ARRAY: - case CONST_INIT_ARRAY_FULL: - expr->expr_kind = EXPR_CONST; - expr->const_expr.const_kind = CONST_INITIALIZER; - expr->const_expr.initializer = init; - expr->type = resulting_type; - break; - case CONST_INIT_ARRAY_VALUE: - case CONST_INIT_STRUCT: - case CONST_INIT_UNION: - case CONST_INIT_VALUE: - UNREACHABLE - } - return true; - -} - static inline bool sema_expr_fold_to_index(Expr *expr, Expr *parent, SubscriptIndex index_expr) { ConstInitializer *init = parent->const_expr.initializer; @@ -4274,8 +4269,7 @@ static inline bool sema_expr_fold_to_index(Expr *expr, Expr *parent, SubscriptIn expr->expr_kind = EXPR_CONST; expr->const_expr.const_kind = CONST_INITIALIZER; expr->const_expr.initializer = result; - // TODO fix? - expr->type = result->type; + expr->type = type_get_indexed_type(parent->type); break; case CONST_INIT_ARRAY_VALUE: UNREACHABLE @@ -6711,24 +6705,6 @@ static const char *sema_addr_check_may_take(Expr *inner) return "To take the address of a temporary value, use '&&' instead of '&'."; } -static bool sema_expr_recursive_const_address(SemaContext *context, Expr *expr) -{ - RETRY: - switch (expr->expr_kind) - { - case EXPR_ACCESS: - expr = expr->access_expr.parent; - goto RETRY; - case EXPR_SUBSCRIPT: - if (!sema_cast_const(exprptr(expr->subscript_expr.index.expr))) return false; - expr = exprptr(expr->subscript_expr.expr); - goto RETRY; - case EXPR_IDENTIFIER: - return decl_is_global(expr->identifier_expr.decl); - default: - return false; - } -} /** * Analyse &a * @return true if analysis succeeds. @@ -7604,10 +7580,7 @@ static inline bool sema_expr_analyse_compiler_const(SemaContext *context, Expr * case BUILTIN_DEF_BENCHMARK_NAMES: if (!compiler.build.benchmarking) { - expr->const_expr.const_kind = CONST_INITIALIZER; - expr->expr_kind = EXPR_CONST; - expr->resolve_status = RESOLVE_DONE; - expr->const_expr.initializer = const_init_new_zero(expr->type = type_get_slice(type_string)); + expr_rewrite_const_empty_slice(expr, type_get_slice(type_string)); return true; } expr->type = type_get_slice(type_string); @@ -7617,10 +7590,7 @@ static inline bool sema_expr_analyse_compiler_const(SemaContext *context, Expr * case BUILTIN_DEF_BENCHMARK_FNS: if (!compiler.build.benchmarking) { - expr->const_expr.const_kind = CONST_INITIALIZER; - expr->expr_kind = EXPR_CONST; - expr->resolve_status = RESOLVE_DONE; - expr->const_expr.initializer = const_init_new_zero(expr->type = type_get_slice(type_voidptr)); + expr_rewrite_const_empty_slice(expr, type_get_slice(type_voidptr)); return true; } expr->type = type_get_slice(type_voidptr); @@ -7630,10 +7600,7 @@ static inline bool sema_expr_analyse_compiler_const(SemaContext *context, Expr * case BUILTIN_DEF_TEST_NAMES: if (!compiler.build.testing) { - expr->const_expr.const_kind = CONST_INITIALIZER; - expr->expr_kind = EXPR_CONST; - expr->resolve_status = RESOLVE_DONE; - expr->const_expr.initializer = const_init_new_zero(expr->type = type_get_slice(type_string)); + expr_rewrite_const_empty_slice(expr, type_get_slice(type_string)); return true; } expr->type = type_get_slice(type_string); @@ -7643,10 +7610,7 @@ static inline bool sema_expr_analyse_compiler_const(SemaContext *context, Expr * case BUILTIN_DEF_TEST_FNS: if (!compiler.build.testing) { - expr->const_expr.const_kind = CONST_INITIALIZER; - expr->expr_kind = EXPR_CONST; - expr->resolve_status = RESOLVE_DONE; - expr->const_expr.initializer = const_init_new_zero(expr->type = type_get_slice(type_voidptr)); + expr_rewrite_const_empty_slice(expr, type_get_slice(type_voidptr)); return true; } expr->type = type_get_slice(type_voidptr); diff --git a/src/compiler/sema_initializers.c b/src/compiler/sema_initializers.c index a56f5d5ce..2b505da3c 100644 --- a/src/compiler/sema_initializers.c +++ b/src/compiler/sema_initializers.c @@ -17,7 +17,6 @@ static Decl *sema_resolve_element_for_name(SemaContext *context, Decl **decls, D static Type *sema_expr_analyse_designator(SemaContext *context, Type *current, Expr *expr, ArrayIndex *max_index, Decl **member_ptr); INLINE bool sema_initializer_list_is_empty(Expr *value); static Type *sema_find_type_of_element(SemaContext *context, Type *type, DesignatorElement ***elements_ref, unsigned *curr_index, bool *is_constant, bool *did_report_error, ArrayIndex *max_index, Decl **member_ptr); -ArrayIndex sema_get_initializer_const_array_size(SemaContext *context, Expr *initializer, bool *may_be_array, bool *is_const_size); static ArrayIndex sema_analyse_designator_index(SemaContext *context, Expr *index); static void sema_update_const_initializer_with_designator(ConstInitializer *const_init, DesignatorElement **curr, @@ -57,9 +56,12 @@ bool const_init_local_init_may_be_global_inner(ConstInitializer *init, bool top) case CONST_INIT_UNION: return const_init_local_init_may_be_global_inner(init->init_union.element, false); case CONST_INIT_VALUE: - if (!expr_is_const(init->init_value)) return false; - if (top && expr_is_const_pointer(init->init_value) && !init->init_value->const_expr.ptr) return false; + { + Expr *val = init->init_value; + if (!expr_is_const(val)) return false; + if (expr_is_const_slice(val)) return false; return true; + } case CONST_INIT_ARRAY: list = init->init_array.elements; len = vec_size(list); @@ -139,6 +141,16 @@ ConstInitializer *const_init_new_union(Type *type, ArrayIndex index, Expr *value return init; } +ConstInitializer *const_init_new_array_value(Expr *expr, ArrayIndex index) +{ + ConstInitializer *init = CALLOCS(ConstInitializer); + init->type = type_flatten(expr->type); + init->kind = CONST_INIT_ARRAY_VALUE; + init->init_array_value.index = index; + init->init_array_value.element = const_init_new_value(expr); + return init; +} + ConstInitializer *const_init_new_zero_array_value(Type *type, ArrayIndex index) { ConstInitializer *init = CALLOCS(ConstInitializer); @@ -619,7 +631,7 @@ static void sema_create_const_initializer_from_designated_init(ConstInitializer { // Flatten the type since the external type might be typedef or a distinct type. const_init_rewrite_to_zero(const_init, type_flatten(initializer->type)); - + assert(type_flatten(initializer->type)->type_kind != TYPE_SLICE); // Loop through the initializers. FOREACH(Expr *, expr, initializer->initializer_list) { @@ -795,20 +807,27 @@ bool sema_expr_analyse_initializer_list(SemaContext *context, Type *to, Expr *ex { if (is_zero_init) { - expr->expr_kind = EXPR_CONST; - expr->const_expr.const_kind = CONST_POINTER; - expr->const_expr.ptr = 0; - expr->type = to; - expr->resolve_status = RESOLVE_DONE; + expr_rewrite_const_empty_slice(expr, to); return true; } // Resolve this as an inferred array. Type *type = type_get_inferred_array(flattened->array.base); if (!sema_expr_analyse_initializer(context, type, type, expr)) return false; - expr->resolve_status = RESOLVE_DONE; - expr_insert_addr(expr); - if (!sema_analyse_expr(context, expr)) return false; - return cast_explicit(context, expr, to); + if (expr_is_const_initializer(expr)) + { + ConstInitializer *init = expr->const_expr.initializer; + expr->const_expr.slice_init = init; + expr->const_expr.const_kind = CONST_SLICE; + expr->type = to; + return true; + } + else + { + expr->resolve_status = RESOLVE_DONE; + expr_insert_addr(expr); + if (!sema_analyse_expr(context, expr)) return false; + return cast_explicit(context, expr, to); + } } case TYPE_POINTER: case TYPE_FUNC_PTR: @@ -848,6 +867,7 @@ void const_init_rewrite_to_value(ConstInitializer *const_init, Expr *value) { *const_init = *value->const_expr.initializer; value->const_expr.initializer = const_init; + assert(type_flatten(value->type)->type_kind != TYPE_SLICE); return; } if (value->expr_kind == EXPR_IDENTIFIER) @@ -888,6 +908,7 @@ static inline void sema_update_const_initializer_with_designator_struct(ConstIni if (is_last_path_element && sema_initializer_list_is_empty(value)) { const_init->kind = CONST_INIT_ZERO; + assert(type_flatten(value->type)->type_kind != TYPE_SLICE); return; } Decl **elements = const_init->type->decl->strukt.members; @@ -966,7 +987,6 @@ static inline void sema_update_const_initializer_with_designator_union(ConstInit // Update of the sub element. sub_element->type = type_flatten(const_init->type->decl->strukt.members[element->index]->type); - // And the index const_init->init_union.index = element->index; @@ -1200,99 +1220,6 @@ static Type *sema_find_type_of_element(SemaContext *context, Type *type, Designa return member->type; } -ArrayIndex sema_get_initializer_const_array_size(SemaContext *context, Expr *initializer, bool *may_be_array, bool *is_const_size) -{ - if (expr_is_const(initializer)) - { - assert(initializer->const_expr.const_kind == CONST_INITIALIZER); - ConstInitializer *init = initializer->const_expr.initializer; - Type *type = type_flatten(initializer->type); - *is_const_size = true; - switch (init->kind) - { - case CONST_INIT_ZERO: - if (type->type_kind == TYPE_ARRAY) - { - *may_be_array = true; - return (ArrayIndex)type->array.len; - } - if (type->type_kind == TYPE_SLICE) - { - *may_be_array = true; - return 0; - } - *may_be_array = false; - return 0; - case CONST_INIT_ARRAY: - *may_be_array = true; - return vectail(init->init_array.elements)->init_array_value.index + 1; - case CONST_INIT_ARRAY_FULL: - *may_be_array = true; - return (ArrayIndex)vec_size(init->init_array_full); - case CONST_INIT_ARRAY_VALUE: - UNREACHABLE; - case CONST_INIT_STRUCT: - case CONST_INIT_UNION: - case CONST_INIT_VALUE: - *may_be_array = false; - return 0; - } - UNREACHABLE - } - switch (initializer->expr_kind) - { - case EXPR_INITIALIZER_LIST: - *may_be_array = true; - *is_const_size = true; - return (ArrayIndex)vec_size(initializer->initializer_list); - case EXPR_DESIGNATED_INITIALIZER_LIST: - break; - default: - UNREACHABLE - } - Expr **initializers = initializer->designated_init_list; - ArrayIndex size = 0; - // Otherwise we assume everything's a designator. - FOREACH(Expr *, sub_initializer, initializers) - { - assert(sub_initializer->expr_kind == EXPR_DESIGNATOR); - - DesignatorElement *element = sub_initializer->designator_expr.path[0]; - switch (element->kind) - { - case DESIGNATOR_FIELD: - // Struct, abandon! - *may_be_array = false; - return -1; - case DESIGNATOR_ARRAY: - { - ArrayIndex index = sema_analyse_designator_index(context, element->index_expr); - if (index < 0 || element->index_expr->expr_kind != EXPR_CONST) - { - *is_const_size = false; - return -1; - } - if (index + 1 > size) size = index + 1; - break; - } - case DESIGNATOR_RANGE: - { - ArrayIndex index = sema_analyse_designator_index(context, element->index_end_expr); - if (index < 0 || element->index_end_expr->expr_kind != EXPR_CONST) - { - *is_const_size = false; - return -1; - } - if (index + 1 > size) size = index + 1; - break; - } - default: - UNREACHABLE - } - } - return size; -} - static ArrayIndex sema_analyse_designator_index(SemaContext *context, Expr *index) { if (!sema_analyse_expr(context, index)) diff --git a/src/compiler/sema_liveness.c b/src/compiler/sema_liveness.c index 2e732619f..6bf9fb99c 100644 --- a/src/compiler/sema_liveness.c +++ b/src/compiler/sema_liveness.c @@ -199,6 +199,7 @@ static void sema_trace_stmt_liveness(Ast *ast) static void sema_trace_const_initializer_liveness(ConstInitializer *const_init) { + if (!const_init) return; RETRY: switch (const_init->kind) { @@ -364,6 +365,9 @@ static void sema_trace_expr_liveness(Expr *expr) case CONST_REF: sema_trace_decl_liveness(expr->const_expr.global_ref); return; + case CONST_SLICE: + sema_trace_const_initializer_liveness(expr->const_expr.slice_init); + return; case CONST_INITIALIZER: sema_trace_const_initializer_liveness(expr->const_expr.initializer); return; diff --git a/src/compiler/sema_passes.c b/src/compiler/sema_passes.c index fce96ec4c..9322d6d0e 100644 --- a/src/compiler/sema_passes.c +++ b/src/compiler/sema_passes.c @@ -221,6 +221,7 @@ static bool exec_arg_append_to_scratch(Expr *arg) return true; case CONST_BYTES: case CONST_INITIALIZER: + case CONST_SLICE: case CONST_UNTYPED_LIST: case CONST_MEMBER: return false; diff --git a/src/compiler/sema_stmts.c b/src/compiler/sema_stmts.c index 3754efdec..5535983c4 100644 --- a/src/compiler/sema_stmts.c +++ b/src/compiler/sema_stmts.c @@ -1372,80 +1372,53 @@ static inline bool sema_analyse_foreach_stmt(SemaContext *context, Ast *statemen bool is_reverse = statement->foreach_stmt.is_reverse; bool value_by_ref = statement->foreach_stmt.value_by_ref; bool success = true; - bool iterator_based = false; + bool iterator_was_initializer = enumerator->expr_kind == EXPR_INITIALIZER_LIST; + // Check the type if needed + TypeInfo *variable_type_info = vartype(var); + if (variable_type_info && !sema_resolve_type_info(context, variable_type_info, RESOLVE_TYPE_DEFAULT)) return false; // Conditional scope start SCOPE_START + // In the case of foreach (int x : { 1, 2, 3 }) we will infer the int[] type, so pick out the number of elements. - Type *inferred_type = NULL; + Type *inferred_type = variable_type_info ? type_get_inferred_array(type_no_optional(variable_type_info->type)) : NULL; - // We may have an initializer list, in this case we rely on an inferred type. - if (expr_is_init_list(enumerator) || expr_is_const_initializer(enumerator)) + if (variable_type_info) { - bool may_be_array; - bool is_const_size; - ArrayIndex size = sema_get_initializer_const_array_size(context, enumerator, &may_be_array, &is_const_size); - if (!may_be_array) - { - SEMA_ERROR(enumerator, - "This initializer appears to be a struct initializer when, an array initializer was expected."); - return SCOPE_POP_ERROR(); - } - if (!is_const_size) - { - SEMA_ERROR(enumerator, "Only constant sized initializers may be implicitly initialized."); - return SCOPE_POP_ERROR(); - } - if (size < 0) - { - SEMA_ERROR(enumerator, "The initializer mixes designated initialization with array initialization."); - return SCOPE_POP_ERROR(); - } - assert(size >= 0); - - TypeInfo *variable_type_info = vartype(var); - - if (!variable_type_info) - { - SEMA_ERROR(var, "Add the type of your variable here if you want to iterate over an initializer list."); - return SCOPE_POP_ERROR(); - } - // First infer the type of the variable. - if (!sema_resolve_type_info(context, variable_type_info, RESOLVE_TYPE_DEFAULT)) return false; - // And create the inferred type: - inferred_type = type_get_array(variable_type_info->type, (ArraySize)size); + if (!sema_analyse_inferred_expr(context, inferred_type, enumerator)) return SCOPE_POP_ERROR(); } - - // because we don't want the index + variable to move into the internal scope - if (!sema_analyse_inferred_expr(context, inferred_type, enumerator)) + else { - // Exit early here, because semantic checking might be messed up otherwise. - return SCOPE_POP_ERROR(); + if (!sema_analyse_expr(context, enumerator)) return SCOPE_POP_ERROR(); } - // And pop the cond scope. SCOPE_END; if (IS_OPTIONAL(enumerator)) { - SEMA_ERROR(enumerator, "The expression may not be optional."); - return false; + RETURN_SEMA_ERROR(enumerator, "The foreach iterable expression may not be optional."); } if (statement->foreach_stmt.index_by_ref) { assert(index); - SEMA_ERROR(index, "The index cannot be held by reference, did you accidentally add a '&'?"); - return false; + RETURN_SEMA_ERROR(index, "The index cannot be held by reference, did you accidentally add a '&'?"); } // Insert a single deref as needed. Type *canonical = enumerator->type->canonical; if (canonical->type_kind == TYPE_UNTYPED_LIST) { - RETURN_SEMA_ERROR(enumerator, "It is not possible to enumerate a compile time 'untyped' list at runtime, but you can use the compile time `$foreach` with the list."); + if (variable_type_info || !iterator_was_initializer) + { + RETURN_SEMA_ERROR(enumerator, "It is not possible to enumerate a compile time 'untyped' list at runtime, but you can use the compile time `$foreach` with the list."); + } + else + { + RETURN_SEMA_ERROR(var, "Add an explicit type to the variable if you want to iterate over an initializer list."); + } } if (canonical->type_kind == TYPE_POINTER) { @@ -2833,11 +2806,11 @@ bool sema_analyse_ct_echo_stmt(SemaContext *context, Ast *statement) puts(type_to_error_string(message->const_expr.typeid)); break; case CONST_BYTES: + case CONST_SLICE: case CONST_INITIALIZER: case CONST_UNTYPED_LIST: case CONST_MEMBER: - SEMA_ERROR(message, "Unsupported type for '$echo'"); - break; + RETURN_SEMA_ERROR(message, "Unsupported type for '$echo'"); } statement->ast_kind = AST_NOP_STMT; return true; diff --git a/src/version.h b/src/version.h index 9cb9093a5..9c73f4bd7 100644 --- a/src/version.h +++ b/src/version.h @@ -1,2 +1,2 @@ -#define COMPILER_VERSION "0.6.3" -#define PRERELEASE 0 \ No newline at end of file +#define COMPILER_VERSION "0.6.4" +#define PRERELEASE 1 \ No newline at end of file diff --git a/test/test_suite/compile_time/compile_time_access_subscript.c3t b/test/test_suite/compile_time/compile_time_access_subscript.c3t index efa6c7735..aeb3d4582 100644 --- a/test/test_suite/compile_time/compile_time_access_subscript.c3t +++ b/test/test_suite/compile_time/compile_time_access_subscript.c3t @@ -82,7 +82,7 @@ fn void main() store i32 0, ptr %z14, align 4 %ptradd15 = getelementptr inbounds i8, ptr %z14, i64 4 store i32 0, ptr %ptradd15, align 4 - call void @llvm.memset.p0.i64(ptr align 8 %z16, i8 0, i64 16, i1 false) + store %"int[]" zeroinitializer, ptr %z16, align 8 store float 0.000000e+00, ptr %taddr, align 4 %0 = insertvalue %any undef, ptr %taddr, 0 %1 = insertvalue %any %0, i64 ptrtoint (ptr @"$ct.float" to i64), 1 diff --git a/test/test_suite/compile_time/compile_time_ptr_ref.c3t b/test/test_suite/compile_time/compile_time_ptr_ref.c3t index 70dadef15..32449c8c1 100644 --- a/test/test_suite/compile_time/compile_time_ptr_ref.c3t +++ b/test/test_suite/compile_time/compile_time_ptr_ref.c3t @@ -12,8 +12,9 @@ int ptr = 0; /* #expect: test.ll %"int*[]" = type { ptr, i64 } -@.taddr = private global [5 x ptr] [ptr @test.ptr, ptr @test.ptr, ptr getelementptr (i8, ptr @test.ptr, i64 4), ptr getelementptr (i8, ptr @test.ptr, i64 -4), ptr getelementptr (i8, ptr @test.ptr, i64 -4)], align 8 -@test.blurp = local_unnamed_addr global %"int*[]" { ptr @.taddr, i64 5 }, align 8 + +@.__const_slice = private unnamed_addr global [5 x ptr] [ptr @test.ptr, ptr @test.ptr, ptr getelementptr (i8, ptr @test.ptr, i64 4), ptr getelementptr (i8, ptr @test.ptr, i64 -4), ptr getelementptr (i8, ptr @test.ptr, i64 -4)], align 16 +@test.blurp = local_unnamed_addr global %"int*[]" { ptr @.__const_slice, i64 5 }, align 8 @test.c = local_unnamed_addr global ptr getelementptr (i8, ptr @test.ptr, i64 -4), align 8 @test.c2 = local_unnamed_addr global ptr getelementptr (i8, ptr @test.ptr, i64 4), align 8 @test.c3 = local_unnamed_addr global ptr getelementptr (i8, ptr @test.ptr, i64 4), align 8 diff --git a/test/test_suite/compile_time/concat_append.c3t b/test/test_suite/compile_time/concat_append.c3t index 9abf9989e..b5e4d3f5c 100644 --- a/test/test_suite/compile_time/concat_append.c3t +++ b/test/test_suite/compile_time/concat_append.c3t @@ -39,7 +39,8 @@ entry: %a = alloca [2 x %"char[]"], align 16 %z = alloca i32, align 4 %b = alloca [3 x i32], align 4 - %d = alloca [3 x i32], align 4 + %d = alloca %"int[]", align 8 + %literal = alloca [3 x i32], align 4 %e = alloca [2 x %"char[]"], align 16 %f = alloca %"char[]", align 8 %g = alloca %"char[]", align 8 @@ -48,7 +49,10 @@ entry: call void @llvm.memcpy.p0.p0.i32(ptr align 16 %a, ptr align 16 @.__const, i32 32, i1 false) store i32 3, ptr %z, align 4 call void @llvm.memcpy.p0.p0.i32(ptr align 4 %b, ptr align 4 @.__const.3, i32 12, i1 false) - call void @llvm.memcpy.p0.p0.i32(ptr align 4 %d, ptr align 4 @.__const.4, i32 12, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const.4, i32 12, i1 false) + %0 = insertvalue %"int[]" undef, ptr %literal, 0 + %1 = insertvalue %"int[]" %0, i64 3, 1 + store %"int[]" %1, ptr %d, align 8 call void @llvm.memcpy.p0.p0.i32(ptr align 16 %e, ptr align 16 @.__const.7, i32 32, i1 false) store %"char[]" zeroinitializer, ptr %f, align 8 store %"char[]" { ptr @.str.8, i64 3 }, ptr %g, align 8 diff --git a/test/test_suite/compile_time/concat_slice_bytes.c3t b/test/test_suite/compile_time/concat_slice_bytes.c3t new file mode 100644 index 000000000..0a4490084 --- /dev/null +++ b/test/test_suite/compile_time/concat_slice_bytes.c3t @@ -0,0 +1,18 @@ +module test; +import std; + +fn void main() +{ + String $a = "hello"; + char[] $b = { 'a', 'b' }; + var $c = $a +++ $b; + String y = $c; + char[3] $bytes = x'0103ff'; + var $d = $bytes +++ $b; + char[5] z = $d; +} + +/* #expect: test.ll + +@.str = private unnamed_addr constant [8 x i8] c"helloab\00", align 1 +@.bytes = private unnamed_addr constant [5 x i8] c"\01\03\FFab", align 1 \ No newline at end of file diff --git a/test/test_suite/compile_time/concat_test.c3t b/test/test_suite/compile_time/concat_test.c3t new file mode 100644 index 000000000..97aa5439a --- /dev/null +++ b/test/test_suite/compile_time/concat_test.c3t @@ -0,0 +1,506 @@ +// #target: macos-x64 +module test; +import std; + +fn void test1() +{ + int[] $x = { 1, 2, 3, 4 }; + var $y = $x +++ 5; + io::printn($y); +} + +fn void test2() +{ + int[] $x = { }; + var $y = $x +++ 5; + io::printn($y); + $y = $y +++ 1; + io::printn($y); +} + +fn void test3() +{ + int[] $x = { [5] = 2 }; + var $y = $x +++ 5; + io::printn($y); +} + +fn void test4() +{ + int[4] $x = { [1] = 2 }; + var $y = $x +++ 5; + io::printn($y); +} + +fn void test5() +{ + int[4] $x = { }; + var $y = $x +++ 5; + io::printn($y); +} + +fn int main() +{ + test1(); + test2(); + test3(); + test4(); + test5(); + return 0; +} + +/* #expect: test.ll + +@.__const = private unnamed_addr constant [5 x i32] [i32 1, i32 2, i32 3, i32 4, i32 5], align 16 +@.__const.1 = private unnamed_addr constant [1 x i32] [i32 5], align 4 +@.__const.3 = private unnamed_addr constant [2 x i32] [i32 5, i32 1], align 4 +@.__const.5 = private unnamed_addr constant { [5 x i32], i32, i32 } { [5 x i32] zeroinitializer, i32 2, i32 5 }, align 16 +@.__const.7 = private unnamed_addr constant { i32, i32, [2 x i32], i32 } { i32 0, i32 2, [2 x i32] zeroinitializer, i32 5 }, align 16 +@.__const.9 = private unnamed_addr constant { [4 x i32], i32 } { [4 x i32] zeroinitializer, i32 5 }, align 16 + +define void @test.test1() #0 { +entry: + %literal = alloca [5 x i32], align 16 + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %varargslots = alloca [1 x %any], align 16 + %taddr = alloca %"int[]", align 8 + %retparam = alloca i64, align 8 + %taddr2 = alloca %any, align 8 + %indirectarg = alloca %"any[]", align 8 + %error_var3 = alloca i64, align 8 + %error_var9 = alloca i64, align 8 + +define void @test.test2() #0 { +entry: + %literal = alloca [1 x i32], align 4 + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %varargslots = alloca [1 x %any], align 16 + %taddr = alloca %"int[]", align 8 + %retparam = alloca i64, align 8 + %taddr2 = alloca %any, align 8 + %indirectarg = alloca %"any[]", align 8 + %error_var3 = alloca i64, align 8 + %error_var9 = alloca i64, align 8 + %literal15 = alloca [2 x i32], align 4 + %len16 = alloca i64, align 8 + %error_var17 = alloca i64, align 8 + %varargslots19 = alloca [1 x %any], align 16 + %taddr20 = alloca %"int[]", align 8 + %retparam22 = alloca i64, align 8 + %taddr23 = alloca %any, align 8 + %indirectarg27 = alloca %"any[]", align 8 + %error_var33 = alloca i64, align 8 + %error_var39 = alloca i64, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const.1, i32 4, i1 false) + %0 = insertvalue %"int[]" undef, ptr %literal, 0 + %1 = insertvalue %"int[]" %0, i64 1, 1 + %2 = call ptr @std.io.stdout() + %3 = insertvalue %any undef, ptr %2, 0 + %4 = insertvalue %any %3, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + store %"int[]" %1, ptr %taddr, align 8 + %5 = insertvalue %any undef, ptr %taddr, 0 + %6 = insertvalue %any %5, i64 ptrtoint (ptr @"$ct.sa$int" to i64), 1 + store %any %6, ptr %varargslots, align 16 + %7 = insertvalue %"any[]" undef, ptr %varargslots, 0 + %"$$temp" = insertvalue %"any[]" %7, i64 1, 1 + store %any %4, ptr %taddr2, align 8 + %lo = load i64, ptr %taddr2, align 8 + %ptradd = getelementptr inbounds i8, ptr %taddr2, i64 8 + %hi = load ptr, ptr %ptradd, align 8 + store %"any[]" %"$$temp", ptr %indirectarg, align 8 + %8 = call i64 @std.io.fprintf(ptr %retparam, i64 %lo, ptr %hi, ptr @.str.2, i64 2, ptr byval(%"any[]") align 8 %indirectarg) + %not_err = icmp eq i64 %8, 0 + %9 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %9, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %8, ptr %error_var, align 8 + br label %guard_block + +after_check: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %assign_optional + br label %voiderr + +noerr_block: ; preds = %after_check + %10 = load i64, ptr %retparam, align 8 + store i64 %10, ptr %len, align 8 + %11 = call i64 @std.io.File.write_byte(ptr %2, i8 zeroext 10) + %not_err4 = icmp eq i64 %11, 0 + %12 = call i1 @llvm.expect.i1(i1 %not_err4, i1 true) + br i1 %12, label %after_check6, label %assign_optional5 + +assign_optional5: ; preds = %noerr_block + store i64 %11, ptr %error_var3, align 8 + br label %guard_block7 + +after_check6: ; preds = %noerr_block + br label %noerr_block8 + +guard_block7: ; preds = %assign_optional5 + br label %voiderr + +noerr_block8: ; preds = %after_check6 + %13 = call i64 @std.io.File.flush(ptr %2) + %not_err10 = icmp eq i64 %13, 0 + %14 = call i1 @llvm.expect.i1(i1 %not_err10, i1 true) + br i1 %14, label %after_check12, label %assign_optional11 + +assign_optional11: ; preds = %noerr_block8 + store i64 %13, ptr %error_var9, align 8 + br label %guard_block13 + +after_check12: ; preds = %noerr_block8 + br label %noerr_block14 + +guard_block13: ; preds = %assign_optional11 + br label %voiderr + +noerr_block14: ; preds = %after_check12 + %15 = load i64, ptr %len, align 8 + %add = add i64 %15, 1 + br label %voiderr + +voiderr: ; preds = %noerr_block14, %guard_block13, %guard_block7, %guard_block + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal15, ptr align 4 @.__const.3, i32 8, i1 false) + %16 = insertvalue %"int[]" undef, ptr %literal15, 0 + %17 = insertvalue %"int[]" %16, i64 2, 1 + %18 = call ptr @std.io.stdout() + %19 = insertvalue %any undef, ptr %18, 0 + %20 = insertvalue %any %19, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + store %"int[]" %17, ptr %taddr20, align 8 + %21 = insertvalue %any undef, ptr %taddr20, 0 + %22 = insertvalue %any %21, i64 ptrtoint (ptr @"$ct.sa$int" to i64), 1 + store %any %22, ptr %varargslots19, align 16 + %23 = insertvalue %"any[]" undef, ptr %varargslots19, 0 + %"$$temp21" = insertvalue %"any[]" %23, i64 1, 1 + store %any %20, ptr %taddr23, align 8 + %lo24 = load i64, ptr %taddr23, align 8 + %ptradd25 = getelementptr inbounds i8, ptr %taddr23, i64 8 + %hi26 = load ptr, ptr %ptradd25, align 8 + store %"any[]" %"$$temp21", ptr %indirectarg27, align 8 + %24 = call i64 @std.io.fprintf(ptr %retparam22, i64 %lo24, ptr %hi26, ptr @.str.4, i64 2, ptr byval(%"any[]") align 8 %indirectarg27) + %not_err28 = icmp eq i64 %24, 0 + %25 = call i1 @llvm.expect.i1(i1 %not_err28, i1 true) + br i1 %25, label %after_check30, label %assign_optional29 + +assign_optional29: ; preds = %voiderr + store i64 %24, ptr %error_var17, align 8 + br label %guard_block31 + +after_check30: ; preds = %voiderr + br label %noerr_block32 + +guard_block31: ; preds = %assign_optional29 + br label %voiderr46 + +noerr_block32: ; preds = %after_check30 + %26 = load i64, ptr %retparam22, align 8 + store i64 %26, ptr %len16, align 8 + %27 = call i64 @std.io.File.write_byte(ptr %18, i8 zeroext 10) + %not_err34 = icmp eq i64 %27, 0 + %28 = call i1 @llvm.expect.i1(i1 %not_err34, i1 true) + br i1 %28, label %after_check36, label %assign_optional35 + +assign_optional35: ; preds = %noerr_block32 + store i64 %27, ptr %error_var33, align 8 + br label %guard_block37 + +after_check36: ; preds = %noerr_block32 + br label %noerr_block38 + +guard_block37: ; preds = %assign_optional35 + br label %voiderr46 + +noerr_block38: ; preds = %after_check36 + %29 = call i64 @std.io.File.flush(ptr %18) + %not_err40 = icmp eq i64 %29, 0 + %30 = call i1 @llvm.expect.i1(i1 %not_err40, i1 true) + br i1 %30, label %after_check42, label %assign_optional41 + +assign_optional41: ; preds = %noerr_block38 + store i64 %29, ptr %error_var39, align 8 + br label %guard_block43 + +after_check42: ; preds = %noerr_block38 + br label %noerr_block44 + +guard_block43: ; preds = %assign_optional41 + br label %voiderr46 + +noerr_block44: ; preds = %after_check42 + %31 = load i64, ptr %len16, align 8 + %add45 = add i64 %31, 1 + br label %voiderr46 + +voiderr46: ; preds = %noerr_block44, %guard_block43, %guard_block37, %guard_block31 + ret void +} + +define void @test.test3() #0 { +entry: + %literal = alloca [7 x i32], align 16 + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %varargslots = alloca [1 x %any], align 16 + %taddr = alloca %"int[]", align 8 + %retparam = alloca i64, align 8 + %taddr2 = alloca %any, align 8 + %indirectarg = alloca %"any[]", align 8 + %error_var3 = alloca i64, align 8 + %error_var9 = alloca i64, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 16 @.__const.5, i32 28, i1 false) + %0 = insertvalue %"int[]" undef, ptr %literal, 0 + %1 = insertvalue %"int[]" %0, i64 7, 1 + %2 = call ptr @std.io.stdout() + %3 = insertvalue %any undef, ptr %2, 0 + %4 = insertvalue %any %3, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + store %"int[]" %1, ptr %taddr, align 8 + %5 = insertvalue %any undef, ptr %taddr, 0 + %6 = insertvalue %any %5, i64 ptrtoint (ptr @"$ct.sa$int" to i64), 1 + store %any %6, ptr %varargslots, align 16 + %7 = insertvalue %"any[]" undef, ptr %varargslots, 0 + %"$$temp" = insertvalue %"any[]" %7, i64 1, 1 + store %any %4, ptr %taddr2, align 8 + %lo = load i64, ptr %taddr2, align 8 + %ptradd = getelementptr inbounds i8, ptr %taddr2, i64 8 + %hi = load ptr, ptr %ptradd, align 8 + store %"any[]" %"$$temp", ptr %indirectarg, align 8 + %8 = call i64 @std.io.fprintf(ptr %retparam, i64 %lo, ptr %hi, ptr @.str.6, i64 2, ptr byval(%"any[]") align 8 %indirectarg) + %not_err = icmp eq i64 %8, 0 + %9 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %9, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %8, ptr %error_var, align 8 + br label %guard_block + +after_check: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %assign_optional + br label %voiderr + +noerr_block: ; preds = %after_check + %10 = load i64, ptr %retparam, align 8 + store i64 %10, ptr %len, align 8 + %11 = call i64 @std.io.File.write_byte(ptr %2, i8 zeroext 10) + %not_err4 = icmp eq i64 %11, 0 + %12 = call i1 @llvm.expect.i1(i1 %not_err4, i1 true) + br i1 %12, label %after_check6, label %assign_optional5 + +assign_optional5: ; preds = %noerr_block + store i64 %11, ptr %error_var3, align 8 + br label %guard_block7 + +after_check6: ; preds = %noerr_block + br label %noerr_block8 + +guard_block7: ; preds = %assign_optional5 + br label %voiderr + +noerr_block8: ; preds = %after_check6 + %13 = call i64 @std.io.File.flush(ptr %2) + %not_err10 = icmp eq i64 %13, 0 + %14 = call i1 @llvm.expect.i1(i1 %not_err10, i1 true) + br i1 %14, label %after_check12, label %assign_optional11 + +assign_optional11: ; preds = %noerr_block8 + store i64 %13, ptr %error_var9, align 8 + br label %guard_block13 + +after_check12: ; preds = %noerr_block8 + br label %noerr_block14 + +guard_block13: ; preds = %assign_optional11 + br label %voiderr + +noerr_block14: ; preds = %after_check12 + %15 = load i64, ptr %len, align 8 + %add = add i64 %15, 1 + br label %voiderr + +voiderr: ; preds = %noerr_block14, %guard_block13, %guard_block7, %guard_block + ret void +} + +define void @test.test4() #0 { +entry: + %literal = alloca [5 x i32], align 16 + %x = alloca [5 x i32], align 16 + %x1 = alloca [5 x i32], align 16 + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %x2 = alloca [5 x i32], align 16 + %varargslots = alloca [1 x %any], align 16 + %retparam = alloca i64, align 8 + %taddr = alloca %any, align 8 + %indirectarg = alloca %"any[]", align 8 + %error_var4 = alloca i64, align 8 + %error_var10 = alloca i64, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 16 @.__const.7, i32 20, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x, ptr align 4 %literal, i32 20, i1 false) + %0 = call ptr @std.io.stdout() + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x1, ptr align 16 %x, i32 20, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x2, ptr align 16 %x1, i32 20, i1 false) + %1 = insertvalue %any undef, ptr %0, 0 + %2 = insertvalue %any %1, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + %3 = insertvalue %any undef, ptr %x2, 0 + %4 = insertvalue %any %3, i64 ptrtoint (ptr @"$ct.a5$int" to i64), 1 + store %any %4, ptr %varargslots, align 16 + %5 = insertvalue %"any[]" undef, ptr %varargslots, 0 + %"$$temp" = insertvalue %"any[]" %5, i64 1, 1 + store %any %2, ptr %taddr, align 8 + %lo = load i64, ptr %taddr, align 8 + %ptradd = getelementptr inbounds i8, ptr %taddr, i64 8 + %hi = load ptr, ptr %ptradd, align 8 + store %"any[]" %"$$temp", ptr %indirectarg, align 8 + %6 = call i64 @std.io.fprintf(ptr %retparam, i64 %lo, ptr %hi, ptr @.str.8, i64 2, ptr byval(%"any[]") align 8 %indirectarg) + %not_err = icmp eq i64 %6, 0 + %7 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %7, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %6, ptr %error_var, align 8 + br label %guard_block + +after_check: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %assign_optional + br label %voiderr + +noerr_block: ; preds = %after_check + %8 = load i64, ptr %retparam, align 8 + store i64 %8, ptr %len, align 8 + %9 = call i64 @std.io.File.write_byte(ptr %0, i8 zeroext 10) + %not_err5 = icmp eq i64 %9, 0 + %10 = call i1 @llvm.expect.i1(i1 %not_err5, i1 true) + br i1 %10, label %after_check7, label %assign_optional6 + +assign_optional6: ; preds = %noerr_block + store i64 %9, ptr %error_var4, align 8 + br label %guard_block8 + +after_check7: ; preds = %noerr_block + br label %noerr_block9 + +guard_block8: ; preds = %assign_optional6 + br label %voiderr + +noerr_block9: ; preds = %after_check7 + %11 = call i64 @std.io.File.flush(ptr %0) + %not_err11 = icmp eq i64 %11, 0 + %12 = call i1 @llvm.expect.i1(i1 %not_err11, i1 true) + br i1 %12, label %after_check13, label %assign_optional12 + +assign_optional12: ; preds = %noerr_block9 + store i64 %11, ptr %error_var10, align 8 + br label %guard_block14 + +after_check13: ; preds = %noerr_block9 + br label %noerr_block15 + +guard_block14: ; preds = %assign_optional12 + br label %voiderr + +noerr_block15: ; preds = %after_check13 + %13 = load i64, ptr %len, align 8 + %add = add i64 %13, 1 + br label %voiderr + +voiderr: ; preds = %noerr_block15, %guard_block14, %guard_block8, %guard_block + ret void +} + +define void @test.test5() #0 { +entry: + %literal = alloca [5 x i32], align 16 + %x = alloca [5 x i32], align 16 + %x1 = alloca [5 x i32], align 16 + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %x2 = alloca [5 x i32], align 16 + %varargslots = alloca [1 x %any], align 16 + %retparam = alloca i64, align 8 + %taddr = alloca %any, align 8 + %indirectarg = alloca %"any[]", align 8 + %error_var4 = alloca i64, align 8 + %error_var10 = alloca i64, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 16 @.__const.9, i32 20, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x, ptr align 4 %literal, i32 20, i1 false) + %0 = call ptr @std.io.stdout() + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x1, ptr align 16 %x, i32 20, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %x2, ptr align 16 %x1, i32 20, i1 false) + %1 = insertvalue %any undef, ptr %0, 0 + %2 = insertvalue %any %1, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + %3 = insertvalue %any undef, ptr %x2, 0 + %4 = insertvalue %any %3, i64 ptrtoint (ptr @"$ct.a5$int" to i64), 1 + store %any %4, ptr %varargslots, align 16 + %5 = insertvalue %"any[]" undef, ptr %varargslots, 0 + %"$$temp" = insertvalue %"any[]" %5, i64 1, 1 + store %any %2, ptr %taddr, align 8 + %lo = load i64, ptr %taddr, align 8 + %ptradd = getelementptr inbounds i8, ptr %taddr, i64 8 + %hi = load ptr, ptr %ptradd, align 8 + store %"any[]" %"$$temp", ptr %indirectarg, align 8 + %6 = call i64 @std.io.fprintf(ptr %retparam, i64 %lo, ptr %hi, ptr @.str.10, i64 2, ptr byval(%"any[]") align 8 %indirectarg) + %not_err = icmp eq i64 %6, 0 + %7 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %7, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %6, ptr %error_var, align 8 + br label %guard_block + +after_check: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %assign_optional + br label %voiderr + +noerr_block: ; preds = %after_check + %8 = load i64, ptr %retparam, align 8 + store i64 %8, ptr %len, align 8 + %9 = call i64 @std.io.File.write_byte(ptr %0, i8 zeroext 10) + %not_err5 = icmp eq i64 %9, 0 + %10 = call i1 @llvm.expect.i1(i1 %not_err5, i1 true) + br i1 %10, label %after_check7, label %assign_optional6 + +assign_optional6: ; preds = %noerr_block + store i64 %9, ptr %error_var4, align 8 + br label %guard_block8 + +after_check7: ; preds = %noerr_block + br label %noerr_block9 + +guard_block8: ; preds = %assign_optional6 + br label %voiderr + +noerr_block9: ; preds = %after_check7 + %11 = call i64 @std.io.File.flush(ptr %0) + %not_err11 = icmp eq i64 %11, 0 + %12 = call i1 @llvm.expect.i1(i1 %not_err11, i1 true) + br i1 %12, label %after_check13, label %assign_optional12 + +assign_optional12: ; preds = %noerr_block9 + store i64 %11, ptr %error_var10, align 8 + br label %guard_block14 + +after_check13: ; preds = %noerr_block9 + br label %noerr_block15 + +guard_block14: ; preds = %assign_optional12 + br label %voiderr + +noerr_block15: ; preds = %after_check13 + %13 = load i64, ptr %len, align 8 + %add = add i64 %13, 1 + br label %voiderr + +voiderr: ; preds = %noerr_block15, %guard_block14, %guard_block8, %guard_block + ret void +} diff --git a/test/test_suite/expressions/pointer_access.c3t b/test/test_suite/expressions/pointer_access.c3t index 9827e40f6..27f3746cb 100644 --- a/test/test_suite/expressions/pointer_access.c3t +++ b/test/test_suite/expressions/pointer_access.c3t @@ -63,7 +63,7 @@ entry: %ptradd4 = getelementptr inbounds i8, ptr %ptradd1, i64 24 store double 0.000000e+00, ptr %ptradd4, align 8 %ptradd5 = getelementptr inbounds i8, ptr %ptradd1, i64 32 - call void @llvm.memcpy.p0.p0.i32(ptr align 8 %ptradd5, ptr align 8 @.__const, i32 8, i1 false) + store double 3.300000e+00, ptr %ptradd5, align 8 %ptradd6 = getelementptr inbounds i8, ptr %a, i64 48 store i32 0, ptr %ptradd6, align 8 %ptradd7 = getelementptr inbounds i8, ptr %ptradd6, i64 4 diff --git a/test/test_suite/initializer_lists/fasta.c3t b/test/test_suite/initializer_lists/fasta.c3t index 443dff558..d6600add0 100644 --- a/test/test_suite/initializer_lists/fasta.c3t +++ b/test/test_suite/initializer_lists/fasta.c3t @@ -110,7 +110,6 @@ fn int main(int argc, char **argv) %"char[]" = type { ptr, i64 } %"double[]" = type { ptr, i64 } - @fasta.IM = local_unnamed_addr constant i32 139968, align 4 @fasta.IA = local_unnamed_addr constant i32 3877, align 4 @fasta.IC = local_unnamed_addr constant i32 29573, align 4 @@ -120,12 +119,12 @@ fn int main(int argc, char **argv) @fasta.alu = internal unnamed_addr global %"char[]" { ptr @.str, i64 287 }, align 8 @.str.11 = private unnamed_addr constant [16 x i8] c"acgtBDHKMNRSVWY\00", align 1 @fasta.iub = local_unnamed_addr global %"char[]" { ptr @.str.11, i64 15 }, align 8 -@.taddr = private global [15 x double] [double 2.700000e-01, double 1.200000e-01, double 1.200000e-01, double 2.700000e-01, double 2.000000e-02, double 2.000000e-02, double 2.000000e-02, double 2.000000e-02, double 2.000000e-02, double 2.000000e-02, double 2.000000e-02, double 2.000000e-02, double 2.000000e-02, double 2.000000e-02, double 2.000000e-02], align 8 -@fasta.iub_p = local_unnamed_addr global %"double[]" { ptr @.taddr, i64 15 }, align 8 +@.__const_slice = private unnamed_addr global [15 x double] [double 2.700000e-01, double 1.200000e-01, double 1.200000e-01, double 2.700000e-01, double 2.000000e-02, double 2.000000e-02, double 2.000000e-02, double 2.000000e-02, double 2.000000e-02, double 2.000000e-02, double 2.000000e-02, double 2.000000e-02, double 2.000000e-02, double 2.000000e-02, double 2.000000e-02], align 16 +@fasta.iub_p = local_unnamed_addr global %"double[]" { ptr @.__const_slice, i64 15 }, align 8 @.str.12 = private unnamed_addr constant [5 x i8] c"acgt\00", align 1 @fasta.homosapiens = local_unnamed_addr global %"char[]" { ptr @.str.12, i64 4 }, align 8 -@.taddr.13 = private global [4 x double] [double 0x3FD3639D20BAEB5B, double 0x3FC957AE3DCD561B, double 0x3FC9493AEAB6C2BF, double 0x3FD34BEE4B030838], align 8 -@fasta.homosapiens_p = local_unnamed_addr global %"double[]" { ptr @.taddr.13, i64 4 }, align 8 +@.__const_slice.13 = private unnamed_addr global [4 x double] [double 0x3FD3639D20BAEB5B, double 0x3FC957AE3DCD561B, double 0x3FC9493AEAB6C2BF, double 0x3FD34BEE4B030838], align 16 +@fasta.homosapiens_p = local_unnamed_addr global %"double[]" { ptr @.__const_slice.13, i64 4 }, align 8 @fasta.LINELEN = local_unnamed_addr constant i32 60, align 4 @.str.14 = private unnamed_addr constant [23 x i8] c">ONE Homo sapiens alu\0A\00", align 1 @.str.15 = private unnamed_addr constant [26 x i8] c">TWO IUB ambiguity codes\0A\00", align 1 @@ -169,12 +168,10 @@ entry: store i64 %3, ptr %len, align 8 store i32 0, ptr %i, align 4 br label %loop.cond - loop.cond: ; preds = %if.exit, %entry %4 = load i32, ptr %i, align 4 %lt = icmp slt i32 %4, %2 br i1 %lt, label %loop.body, label %loop.exit - loop.body: ; preds = %loop.cond %5 = load ptr, ptr %seq, align 8 %6 = load i32, ptr %i, align 4 @@ -189,27 +186,22 @@ loop.body: ; preds = %loop.cond %smod3 = srem i32 %9, 60 %eq = icmp eq i32 %smod3, 59 br i1 %eq, label %if.then, label %if.exit - if.then: ; preds = %loop.body call void @putchar(i32 10) br label %if.exit - if.exit: ; preds = %if.then, %loop.body %10 = load i32, ptr %i, align 4 %add = add i32 %10, 1 store i32 %add, ptr %i, align 4 br label %loop.cond - loop.exit: ; preds = %loop.cond %11 = load i32, ptr %i, align 4 %smod4 = srem i32 %11, 60 %neq = icmp ne i32 %smod4, 0 br i1 %neq, label %if.then5, label %if.exit6 - if.then5: ; preds = %loop.exit call void @putchar(i32 10) br label %if.exit6 - if.exit6: ; preds = %if.then5, %loop.exit ret void } @@ -241,26 +233,22 @@ entry: store i32 %trunc, ptr %len, align 4 store i32 0, ptr %i, align 4 br label %loop.cond - loop.cond: ; preds = %if.exit13, %entry %8 = load i32, ptr %i, align 4 %lt = icmp slt i32 %8, %4 br i1 %lt, label %loop.body, label %loop.exit15 - loop.body: ; preds = %loop.cond %9 = call float @fasta.fasta_rand(float 1.000000e+00) %fpfpext = fpext float %9 to double store double %fpfpext, ptr %v, align 8 store i32 0, ptr %j, align 4 br label %loop.cond5 - loop.cond5: ; preds = %if.exit, %loop.body %10 = load i32, ptr %j, align 4 %11 = load i32, ptr %len, align 4 %sub = sub i32 %11, 1 %lt6 = icmp slt i32 %10, %sub br i1 %lt6, label %loop.body7, label %loop.exit - loop.body7: ; preds = %loop.cond5 %12 = load double, ptr %v, align 8 %13 = load ptr, ptr %probability, align 8 @@ -273,16 +261,13 @@ loop.body7: ; preds = %loop.cond5 %16 = load double, ptr %v, align 8 %lt8 = fcmp olt double %16, 0.000000e+00 br i1 %lt8, label %if.then, label %if.exit - if.then: ; preds = %loop.body7 br label %loop.exit - if.exit: ; preds = %loop.body7 %17 = load i32, ptr %j, align 4 %add = add i32 %17, 1 store i32 %add, ptr %j, align 4 br label %loop.cond5 - loop.exit: ; preds = %if.then, %loop.cond5 %18 = load ptr, ptr %symb, align 8 %19 = load i32, ptr %j, align 4 @@ -295,27 +280,22 @@ loop.exit: ; preds = %if.then, %loop.cond %smod = srem i32 %21, 60 %eq11 = icmp eq i32 %smod, 59 br i1 %eq11, label %if.then12, label %if.exit13 - if.then12: ; preds = %loop.exit call void @putchar(i32 10) br label %if.exit13 - if.exit13: ; preds = %if.then12, %loop.exit %22 = load i32, ptr %i, align 4 %add14 = add i32 %22, 1 store i32 %add14, ptr %i, align 4 br label %loop.cond - loop.exit15: ; preds = %loop.cond %23 = load i32, ptr %i, align 4 %smod16 = srem i32 %23, 60 %neq = icmp ne i32 %smod16, 0 br i1 %neq, label %if.then17, label %if.exit18 - if.then17: ; preds = %loop.exit15 call void @putchar(i32 10) br label %if.exit18 - if.exit18: ; preds = %if.then17, %loop.exit15 ret void } @@ -327,14 +307,12 @@ entry: store i32 1000, ptr %n, align 4 %gt = icmp sgt i32 %0, 1 br i1 %gt, label %if.then, label %if.exit - if.then: ; preds = %entry %ptradd = getelementptr inbounds i8, ptr %1, i64 8 %2 = load ptr, ptr %ptradd, align 8 %3 = call i32 @atoi(ptr %2) store i32 %3, ptr %n, align 4 br label %if.exit - if.exit: ; preds = %if.then, %entry %4 = call i32 (ptr, ...) @printf(ptr @.str.14) %5 = load i32, ptr %n, align 4 diff --git a/test/test_suite/initializer_lists/general_tests.c3t b/test/test_suite/initializer_lists/general_tests.c3t index 30a07efb2..83f28ed21 100644 --- a/test/test_suite/initializer_lists/general_tests.c3t +++ b/test/test_suite/initializer_lists/general_tests.c3t @@ -51,7 +51,6 @@ entry: %foo2 = alloca i32, align 4 %str = alloca ptr, align 8 %x = alloca i8, align 1 - %literal = alloca [3 x i32], align 4 %b = alloca %Bar, align 4 %z = alloca %Baz, align 8 %sub = alloca %"int[]", align 8 @@ -61,13 +60,7 @@ entry: store i32 0, ptr %azz, align 4 store i32 33, ptr %foo2, align 4 store ptr @.str, ptr %str, align 8 - call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const.1, i32 12, i1 false) - %0 = insertvalue %"int[]" undef, ptr %literal, 0 - %1 = insertvalue %"int[]" %0, i64 3, 1 - %2 = extractvalue %"int[]" %1, 1 - %not = icmp eq i64 %2, 0 - %3 = zext i1 %not to i8 - store i8 %3, ptr %x, align 1 + store i8 0, ptr %x, align 1 store i32 0, ptr %b, align 4 %ptradd = getelementptr inbounds i8, ptr %b, i64 4 store i32 0, ptr %ptradd, align 4 diff --git a/test/test_suite/initializer_lists/statics.c3t b/test/test_suite/initializer_lists/statics.c3t index 479e328db..725e9f1c3 100644 --- a/test/test_suite/initializer_lists/statics.c3t +++ b/test/test_suite/initializer_lists/statics.c3t @@ -38,8 +38,8 @@ fn int main() @"$ct.statics.Baz" = linkonce global %.introspect { i8 11, i64 0, ptr null, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8 @"$ct.statics.Bar" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8 @.__const = private unnamed_addr constant [1 x %Bar] [%Bar { i32 1, i32 2 }], align 4 -@.taddr = private global [1 x %Bar] [%Bar { i32 1, i32 2 }], align 8 -@test.c = internal unnamed_addr global %"Bar[]" { ptr @.taddr, i64 1 }, align 8 +@.__const_slice = private unnamed_addr global [1 x %Bar] [%Bar { i32 1, i32 2 }], align 4 +@test.c = internal unnamed_addr global %"Bar[]" { ptr @.__const_slice, i64 1 }, align 8 @.str = private unnamed_addr constant [7 x i8] c"%d %d\0A\00", align 1 ; Function Attrs: diff --git a/test/test_suite/initializer_lists/subarrays.c3t b/test/test_suite/initializer_lists/subarrays.c3t index f102952c3..c7900a682 100644 --- a/test/test_suite/initializer_lists/subarrays.c3t +++ b/test/test_suite/initializer_lists/subarrays.c3t @@ -52,21 +52,22 @@ fn int main() @"$ct.subarrays.Baz" = linkonce global %.introspect { i8 11, i64 0, ptr null, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8 @"$ct.subarrays.Bar" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8 -@.taddr = private global [2 x %Bar] [%Bar { i32 3, i32 4 }, %Bar { i32 8, i32 9 }], align 8 -@subarrays.arrbar = local_unnamed_addr global %"Bar[]" { ptr @.taddr, i64 2 }, align 8 -@.taddr.3 = private global [2 x i32] [i32 1, i32 2], align 4 -@subarrays.xd = local_unnamed_addr global %"int[]" { ptr @.taddr.3, i64 2 }, align 8 -@.taddr.4 = private global [2 x i32] [i32 3, i32 4], align 4 -@subarrays.fofeo = local_unnamed_addr global ptr @.taddr.4, align 8 +@.__const_slice = private unnamed_addr global [2 x %Bar] [%Bar { i32 3, i32 4 }, %Bar { i32 8, i32 9 }], align 16 +@subarrays.arrbar = local_unnamed_addr global %"Bar[]" { ptr @.__const_slice, i64 2 }, align 8 +@.__const_slice.3 = private unnamed_addr global [2 x i32] [i32 1, i32 2], align 4 +@subarrays.xd = local_unnamed_addr global %"int[]" { ptr @.__const_slice.3, i64 2 }, align 8 +@.taddr = private global [2 x i32] [i32 3, i32 4], align 4 +@subarrays.fofeo = local_unnamed_addr global ptr @.taddr, align 8 @.str = private unnamed_addr constant [4 x i8] c"%d\0A\00", align 1 -@.str.6 = private unnamed_addr constant [7 x i8] c"Start:\00", align 1 -@.str.7 = private unnamed_addr constant [26 x i8] c"X len: %d mid element %d\0A\00", align 1 -@.str.8 = private unnamed_addr constant [18 x i8] c"Y mid element %d\0A\00", align 1 -@.str.9 = private unnamed_addr constant [25 x i8] c"Fofeo second element %d\0A\00", align 1 -@.__const.10 = private unnamed_addr constant { i32, [4 x i8] } { i32 1, [4 x i8] undef }, align 8 -@.str.12 = private unnamed_addr constant [3 x i8] c"Ok\00", align 1 - -; Function Attrs: +@.__const = private unnamed_addr constant [3 x i32] [i32 1, i32 2, i32 3], align 4 +@.__const.4 = private unnamed_addr constant [3 x i32] [i32 123, i32 234, i32 567], align 4 +@.str.5 = private unnamed_addr constant [7 x i8] c"Start:\00", align 1 +@.str.6 = private unnamed_addr constant [26 x i8] c"X len: %d mid element %d\0A\00", align 1 +@.str.7 = private unnamed_addr constant [18 x i8] c"Y mid element %d\0A\00", align 1 +@.str.8 = private unnamed_addr constant [25 x i8] c"Fofeo second element %d\0A\00", align 1 +@.__const.9 = private unnamed_addr constant { i32, [4 x i8] } { i32 1, [4 x i8] undef }, align 8 +@.str.10 = private unnamed_addr constant [3 x i8] c"Ok\00", align 1 + define i32 @main() #0 { entry: %w = alloca %Bar, align 4 @@ -82,12 +83,11 @@ entry: %ffe = alloca %Baz, align 8 %azz = alloca [1 x i32], align 4 %xy = alloca i8, align 1 - %literal20 = alloca [3 x i32], align 4 - %len22 = alloca i64, align 8 - %error_var23 = alloca i64, align 8 - %retparam25 = alloca i64, align 8 - %error_var31 = alloca i64, align 8 - %error_var37 = alloca i64, align 8 + %len20 = alloca i64, align 8 + %error_var21 = alloca i64, align 8 + %retparam23 = alloca i64, align 8 + %error_var29 = alloca i64, align 8 + %error_var35 = alloca i64, align 8 %b = alloca %Bar, align 4 %z = alloca %Baz, align 8 %sub = alloca %"int[]", align 8 @@ -104,10 +104,10 @@ entry: %4 = insertvalue %"int[]" undef, ptr %literal, 0 %5 = insertvalue %"int[]" %4, i64 3, 1 store %"int[]" %5, ptr %x, align 8 - call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal2, ptr align 4 @.__const.5, i32 12, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal2, ptr align 4 @.__const.4, i32 12, i1 false) store ptr %literal2, ptr %y, align 8 %6 = call ptr @std.io.stdout() - %7 = call i64 @std.io.File.write(ptr %retparam, ptr %6, ptr @.str.6, i64 6) + %7 = call i64 @std.io.File.write(ptr %retparam, ptr %6, ptr @.str.5, i64 6) %not_err = icmp eq i64 %7, 0 %8 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) br i1 %8, label %after_check, label %assign_optional @@ -115,10 +115,13 @@ entry: assign_optional: ; preds = %entry store i64 %7, ptr %error_var, align 8 br label %guard_block + after_check: ; preds = %entry br label %noerr_block + guard_block: ; preds = %assign_optional br label %voiderr + noerr_block: ; preds = %after_check %9 = load i64, ptr %retparam, align 8 store i64 %9, ptr %len, align 8 @@ -130,10 +133,13 @@ noerr_block: ; preds = %after_check assign_optional6: ; preds = %noerr_block store i64 %10, ptr %error_var4, align 8 br label %guard_block8 + after_check7: ; preds = %noerr_block br label %noerr_block9 + guard_block8: ; preds = %assign_optional6 br label %voiderr + noerr_block9: ; preds = %after_check7 %12 = call i64 @std.io.File.flush(ptr %6) %not_err11 = icmp eq i64 %12, 0 @@ -143,10 +149,13 @@ noerr_block9: ; preds = %after_check7 assign_optional12: ; preds = %noerr_block9 store i64 %12, ptr %error_var10, align 8 br label %guard_block14 + after_check13: ; preds = %noerr_block9 br label %noerr_block15 + guard_block14: ; preds = %assign_optional12 br label %voiderr + noerr_block15: ; preds = %after_check13 %14 = load i64, ptr %len, align 8 %add = add i64 %14, 1 @@ -159,92 +168,86 @@ voiderr: ; preds = %noerr_block15, %gua %16 = load ptr, ptr %x, align 8 %ptradd17 = getelementptr inbounds i8, ptr %16, i64 4 %17 = load i32, ptr %ptradd17, align 4 - %18 = call i32 (ptr, ...) @printf(ptr @.str.7, i32 %trunc, i32 %17) + %18 = call i32 (ptr, ...) @printf(ptr @.str.6, i32 %trunc, i32 %17) %19 = load ptr, ptr %y, align 8 %ptradd18 = getelementptr inbounds i8, ptr %19, i64 4 %20 = load i32, ptr %ptradd18, align 4 - %21 = call i32 (ptr, ...) @printf(ptr @.str.8, i32 %20) + %21 = call i32 (ptr, ...) @printf(ptr @.str.7, i32 %20) %22 = load ptr, ptr @subarrays.fofeo, align 8 %ptradd19 = getelementptr inbounds i8, ptr %22, i64 4 %23 = load i32, ptr %ptradd19, align 4 - %24 = call i32 (ptr, ...) @printf(ptr @.str.9, i32 %23) - call void @llvm.memcpy.p0.p0.i32(ptr align 8 %ffe, ptr align 8 @.__const.10, i32 8, i1 false) + %24 = call i32 (ptr, ...) @printf(ptr @.str.8, i32 %23) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %ffe, ptr align 8 @.__const.9, i32 8, i1 false) store i32 0, ptr %azz, align 4 - call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal20, ptr align 4 @.__const.11, i32 12, i1 false) - %25 = insertvalue %"int[]" undef, ptr %literal20, 0 - %26 = insertvalue %"int[]" %25, i64 3, 1 - %27 = extractvalue %"int[]" %26, 1 - %not = icmp eq i64 %27, 0 - %28 = zext i1 %not to i8 - store i8 %28, ptr %xy, align 1 - %29 = load i8, ptr %xy, align 1 - %30 = trunc i8 %29 to i1 - %not21 = xor i1 %30, true - br i1 %not21, label %if.then, label %if.exit + store i8 0, ptr %xy, align 1 + %25 = load i8, ptr %xy, align 1 + %26 = trunc i8 %25 to i1 + %not = xor i1 %26, true + br i1 %not, label %if.then, label %if.exit if.then: ; preds = %voiderr - %31 = call ptr @std.io.stdout() - %32 = call i64 @std.io.File.write(ptr %retparam25, ptr %31, ptr @.str.12, i64 2) - %not_err26 = icmp eq i64 %32, 0 - %33 = call i1 @llvm.expect.i1(i1 %not_err26, i1 true) - br i1 %33, label %after_check28, label %assign_optional27 - -assign_optional27: ; preds = %if.then - store i64 %32, ptr %error_var23, align 8 - br label %guard_block29 - -after_check28: ; preds = %if.then - br label %noerr_block30 - -guard_block29: ; preds = %assign_optional27 - br label %voiderr44 - -noerr_block30: ; preds = %after_check28 - %34 = load i64, ptr %retparam25, align 8 - store i64 %34, ptr %len22, align 8 - %35 = call i64 @std.io.File.write_byte(ptr %31, i8 zeroext 10) - %not_err32 = icmp eq i64 %35, 0 - %36 = call i1 @llvm.expect.i1(i1 %not_err32, i1 true) - br i1 %36, label %after_check34, label %assign_optional33 - -assign_optional33: ; preds = %noerr_block30 - store i64 %35, ptr %error_var31, align 8 - br label %guard_block35 - -after_check34: ; preds = %noerr_block30 - br label %noerr_block36 - -guard_block35: ; preds = %assign_optional33 - br label %voiderr44 - -noerr_block36: ; preds = %after_check34 - %37 = call i64 @std.io.File.flush(ptr %31) - %not_err38 = icmp eq i64 %37, 0 - %38 = call i1 @llvm.expect.i1(i1 %not_err38, i1 true) - br i1 %38, label %after_check40, label %assign_optional39 - -assign_optional39: ; preds = %noerr_block36 - store i64 %37, ptr %error_var37, align 8 - br label %guard_block41 - -after_check40: ; preds = %noerr_block36 - br label %noerr_block42 - -guard_block41: ; preds = %assign_optional39 - br label %voiderr44 - -noerr_block42: ; preds = %after_check40 - %39 = load i64, ptr %len22, align 8 - %add43 = add i64 %39, 1 - br label %voiderr44 - -voiderr44: ; preds = %noerr_block42, %guard_block41, %guard_block35, %guard_block29 + %27 = call ptr @std.io.stdout() + %28 = call i64 @std.io.File.write(ptr %retparam23, ptr %27, ptr @.str.10, i64 2) + %not_err24 = icmp eq i64 %28, 0 + %29 = call i1 @llvm.expect.i1(i1 %not_err24, i1 true) + br i1 %29, label %after_check26, label %assign_optional25 + +assign_optional25: ; preds = %if.then + store i64 %28, ptr %error_var21, align 8 + br label %guard_block27 + +after_check26: ; preds = %if.then + br label %noerr_block28 + +guard_block27: ; preds = %assign_optional25 + br label %voiderr42 + +noerr_block28: ; preds = %after_check26 + %30 = load i64, ptr %retparam23, align 8 + store i64 %30, ptr %len20, align 8 + %31 = call i64 @std.io.File.write_byte(ptr %27, i8 zeroext 10) + %not_err30 = icmp eq i64 %31, 0 + %32 = call i1 @llvm.expect.i1(i1 %not_err30, i1 true) + br i1 %32, label %after_check32, label %assign_optional31 + +assign_optional31: ; preds = %noerr_block28 + store i64 %31, ptr %error_var29, align 8 + br label %guard_block33 + +after_check32: ; preds = %noerr_block28 + br label %noerr_block34 + +guard_block33: ; preds = %assign_optional31 + br label %voiderr42 + +noerr_block34: ; preds = %after_check32 + %33 = call i64 @std.io.File.flush(ptr %27) + %not_err36 = icmp eq i64 %33, 0 + %34 = call i1 @llvm.expect.i1(i1 %not_err36, i1 true) + br i1 %34, label %after_check38, label %assign_optional37 + +assign_optional37: ; preds = %noerr_block34 + store i64 %33, ptr %error_var35, align 8 + br label %guard_block39 + +after_check38: ; preds = %noerr_block34 + br label %noerr_block40 + +guard_block39: ; preds = %assign_optional37 + br label %voiderr42 + +noerr_block40: ; preds = %after_check38 + %35 = load i64, ptr %len20, align 8 + %add41 = add i64 %35, 1 + br label %voiderr42 + +voiderr42: ; preds = %noerr_block40, %guard_block39, %guard_block33, %guard_block27 br label %if.exit -if.exit: ; preds = %voiderr44, %voiderr +if.exit: ; preds = %voiderr42, %voiderr store i32 0, ptr %b, align 4 - %ptradd45 = getelementptr inbounds i8, ptr %b, i64 4 - store i32 0, ptr %ptradd45, align 4 + %ptradd43 = getelementptr inbounds i8, ptr %b, i64 4 + store i32 0, ptr %ptradd43, align 4 call void @llvm.memset.p0.i64(ptr align 8 %z, i8 0, i64 8, i1 false) store %"int[]" zeroinitializer, ptr %sub, align 8 store %"Bar[]" zeroinitializer, ptr %foo, align 8 diff --git a/test/test_suite/slices/array_to_const_err.c3 b/test/test_suite/slices/array_to_const_err.c3 new file mode 100644 index 000000000..349890be1 --- /dev/null +++ b/test/test_suite/slices/array_to_const_err.c3 @@ -0,0 +1,8 @@ +module test; +import std; + +fn void main() +{ + char[*] z = { 1, 2 }; + char[] y = z; // #error: Conversions from arrays or vectors +} diff --git a/test/test_suite/slices/array_to_const_slice.c3t b/test/test_suite/slices/array_to_const_slice.c3t new file mode 100644 index 000000000..a10fd0699 --- /dev/null +++ b/test/test_suite/slices/array_to_const_slice.c3t @@ -0,0 +1,19 @@ +// #target: macos-x64 +module test; +import std; + +fn void main() +{ + char[3] $x = { 1, 2, 5 }; + char[] y = $x; + String $a = "hello"; + char[2] $b = { 'a', 'b' }; + var $c = $a +++ $b; + String y2 = $c; + char[] $bytes = x'0103ff'; + var $d = $bytes +++ $b; + char[] z = $d; +} +/* expect: test.ll + +feofke \ No newline at end of file diff --git a/test/test_suite/slices/various_const_slicing.c3t b/test/test_suite/slices/various_const_slicing.c3t new file mode 100644 index 000000000..5de6cd2d6 --- /dev/null +++ b/test/test_suite/slices/various_const_slicing.c3t @@ -0,0 +1,575 @@ +// #target: macos-x64 +module test; +import std; +const int[4] FOO = { 1, 2, 3, 4 }; +int[] y2 = FOO[1..2]; + +fn void test() +{ + int[][] a = { int[] { 1 } }; + char[4] $a = x'aabbccdd'; + var $b = $a[1..2]; + char[2] y = $b; + assert($b == char[] { 187, 204 }); + assert(y == char[2] { 187, 204 }); + +} +fn int main() +{ + int[*] $x = { 1, 2, 3, 4 }; + var $y = $x[1..3]; + int[] y = { 1, 2 }; + io::printn(y.ptr); + io::printn(y.len); + io::printn(y); + io::printn($y); + int[2] $z = $y[1..2]; + io::printn($z); + int[] $b = $y[:0]; + int[] $c = $y[:0]; + io::printn($c); + return 0; +} + +/* #expect: test.ll + +@test.FOO = local_unnamed_addr constant [2 x i32] [i32 2, i32 3], align 16 +@.__const_slice = private unnamed_addr global [2 x i32] [i32 2, i32 3], align 4 +@test.y2 = local_unnamed_addr global %"int[]" { ptr @.__const_slice, i64 2 }, align 8 +@.__const = private unnamed_addr constant [1 x i32] [i32 1], align 4 +@.bytes = private unnamed_addr constant [2 x i8] c"\BB\CC", align 1 +@.__const.2 = private unnamed_addr constant [2 x i8] c"\BB\CC", align 1 +@.__const.3 = private unnamed_addr constant [2 x i32] [i32 1, i32 2], align 4 +@.__const.6 = private unnamed_addr constant [3 x i32] [i32 2, i32 3, i32 4], align 4 +@.__const.8 = private unnamed_addr constant [2 x i32] [i32 3, i32 4], align 4 + +define void @test.test() #0 { +entry: + %a = alloca %"int[][]", align 8 + %literal = alloca [1 x %"int[]"], align 16 + %literal1 = alloca [1 x i32], align 4 + %y = alloca [2 x i8], align 1 + %literal2 = alloca [2 x i8], align 1 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal1, ptr align 4 @.__const, i32 4, i1 false) + %0 = insertvalue %"int[]" undef, ptr %literal1, 0 + %1 = insertvalue %"int[]" %0, i64 1, 1 + store %"int[]" %1, ptr %literal, align 8 + %2 = insertvalue %"int[][]" undef, ptr %literal, 0 + %3 = insertvalue %"int[][]" %2, i64 1, 1 + store %"int[][]" %3, ptr %a, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 1 %y, ptr align 1 @.bytes, i32 2, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 1 %literal2, ptr align 1 @.__const.2, i32 2, i1 false) + %cmp = call i32 @memcmp(ptr %y, ptr %literal2, i64 2) + %eq = icmp eq i32 %cmp, 0 + call void @llvm.assume(i1 %eq) + ret void +} + +define i32 @main() #0 { +entry: + %y = alloca %"int[]", align 8 + %literal = alloca [2 x i32], align 4 + %x = alloca ptr, align 8 + %x1 = alloca ptr, align 8 + %len = alloca i64, align 8 + %error_var = alloca i64, align 8 + %x2 = alloca ptr, align 8 + %varargslots = alloca [1 x %any], align 16 + %retparam = alloca i64, align 8 + %taddr = alloca %any, align 8 + %indirectarg = alloca %"any[]", align 8 + %error_var4 = alloca i64, align 8 + %error_var10 = alloca i64, align 8 + %x17 = alloca i64, align 8 + %x18 = alloca i64, align 8 + %len19 = alloca i64, align 8 + %error_var20 = alloca i64, align 8 + %x21 = alloca i64, align 8 + %varargslots23 = alloca [1 x %any], align 16 + %retparam25 = alloca i64, align 8 + %taddr26 = alloca %any, align 8 + %indirectarg30 = alloca %"any[]", align 8 + %error_var36 = alloca i64, align 8 + %error_var42 = alloca i64, align 8 + %x50 = alloca %"int[]", align 8 + %x51 = alloca %"int[]", align 8 + %len52 = alloca i64, align 8 + %error_var53 = alloca i64, align 8 + %x54 = alloca %"int[]", align 8 + %varargslots56 = alloca [1 x %any], align 16 + %retparam58 = alloca i64, align 8 + %taddr59 = alloca %any, align 8 + %indirectarg63 = alloca %"any[]", align 8 + %error_var69 = alloca i64, align 8 + %error_var75 = alloca i64, align 8 + %literal83 = alloca [3 x i32], align 4 + %len84 = alloca i64, align 8 + %error_var85 = alloca i64, align 8 + %varargslots87 = alloca [1 x %any], align 16 + %taddr88 = alloca %"int[]", align 8 + %retparam90 = alloca i64, align 8 + %taddr91 = alloca %any, align 8 + %indirectarg95 = alloca %"any[]", align 8 + %error_var101 = alloca i64, align 8 + %error_var107 = alloca i64, align 8 + %literal115 = alloca [2 x i32], align 4 + %x116 = alloca [2 x i32], align 4 + %x117 = alloca [2 x i32], align 4 + %len118 = alloca i64, align 8 + %error_var119 = alloca i64, align 8 + %x120 = alloca [2 x i32], align 4 + %varargslots122 = alloca [1 x %any], align 16 + %retparam124 = alloca i64, align 8 + %taddr125 = alloca %any, align 8 + %indirectarg129 = alloca %"any[]", align 8 + %error_var135 = alloca i64, align 8 + %error_var141 = alloca i64, align 8 + %len149 = alloca i64, align 8 + %error_var150 = alloca i64, align 8 + %varargslots152 = alloca [1 x %any], align 16 + %taddr153 = alloca %"int[]", align 8 + %retparam155 = alloca i64, align 8 + %taddr156 = alloca %any, align 8 + %indirectarg160 = alloca %"any[]", align 8 + %error_var166 = alloca i64, align 8 + %error_var172 = alloca i64, align 8 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal, ptr align 4 @.__const.3, i32 8, i1 false) + %0 = insertvalue %"int[]" undef, ptr %literal, 0 + %1 = insertvalue %"int[]" %0, i64 2, 1 + store %"int[]" %1, ptr %y, align 8 + %2 = load ptr, ptr %y, align 8 + store ptr %2, ptr %x, align 8 + %3 = call ptr @std.io.stdout() + %4 = load ptr, ptr %x, align 8 + store ptr %4, ptr %x1, align 8 + %5 = load ptr, ptr %x1, align 8 + store ptr %5, ptr %x2, align 8 + %6 = insertvalue %any undef, ptr %3, 0 + %7 = insertvalue %any %6, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + %8 = insertvalue %any undef, ptr %x2, 0 + %9 = insertvalue %any %8, i64 ptrtoint (ptr @"$ct.p$int" to i64), 1 + store %any %9, ptr %varargslots, align 16 + %10 = insertvalue %"any[]" undef, ptr %varargslots, 0 + %"$$temp" = insertvalue %"any[]" %10, i64 1, 1 + store %any %7, ptr %taddr, align 8 + %lo = load i64, ptr %taddr, align 8 + %ptradd = getelementptr inbounds i8, ptr %taddr, i64 8 + %hi = load ptr, ptr %ptradd, align 8 + store %"any[]" %"$$temp", ptr %indirectarg, align 8 + %11 = call i64 @std.io.fprintf(ptr %retparam, i64 %lo, ptr %hi, ptr @.str, i64 2, ptr byval(%"any[]") align 8 %indirectarg) + %not_err = icmp eq i64 %11, 0 + %12 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %12, label %after_check, label %assign_optional + +assign_optional: ; preds = %entry + store i64 %11, ptr %error_var, align 8 + br label %guard_block + +after_check: ; preds = %entry + br label %noerr_block + +guard_block: ; preds = %assign_optional + br label %voiderr + +noerr_block: ; preds = %after_check + %13 = load i64, ptr %retparam, align 8 + store i64 %13, ptr %len, align 8 + %14 = call i64 @std.io.File.write_byte(ptr %3, i8 zeroext 10) + %not_err5 = icmp eq i64 %14, 0 + %15 = call i1 @llvm.expect.i1(i1 %not_err5, i1 true) + br i1 %15, label %after_check7, label %assign_optional6 + +assign_optional6: ; preds = %noerr_block + store i64 %14, ptr %error_var4, align 8 + br label %guard_block8 + +after_check7: ; preds = %noerr_block + br label %noerr_block9 + +guard_block8: ; preds = %assign_optional6 + br label %voiderr + +noerr_block9: ; preds = %after_check7 + %16 = call i64 @std.io.File.flush(ptr %3) + %not_err11 = icmp eq i64 %16, 0 + %17 = call i1 @llvm.expect.i1(i1 %not_err11, i1 true) + br i1 %17, label %after_check13, label %assign_optional12 + +assign_optional12: ; preds = %noerr_block9 + store i64 %16, ptr %error_var10, align 8 + br label %guard_block14 + +after_check13: ; preds = %noerr_block9 + br label %noerr_block15 + +guard_block14: ; preds = %assign_optional12 + br label %voiderr + +noerr_block15: ; preds = %after_check13 + %18 = load i64, ptr %len, align 8 + %add = add i64 %18, 1 + br label %voiderr + +voiderr: ; preds = %noerr_block15, %guard_block14, %guard_block8, %guard_block + %ptradd16 = getelementptr inbounds i8, ptr %y, i64 8 + %19 = load i64, ptr %ptradd16, align 8 + store i64 %19, ptr %x17, align 8 + %20 = call ptr @std.io.stdout() + %21 = load i64, ptr %x17, align 8 + store i64 %21, ptr %x18, align 8 + %22 = load i64, ptr %x18, align 8 + store i64 %22, ptr %x21, align 8 + %23 = insertvalue %any undef, ptr %20, 0 + %24 = insertvalue %any %23, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + %25 = insertvalue %any undef, ptr %x21, 0 + %26 = insertvalue %any %25, i64 ptrtoint (ptr @"$ct.ulong" to i64), 1 + store %any %26, ptr %varargslots23, align 16 + %27 = insertvalue %"any[]" undef, ptr %varargslots23, 0 + %"$$temp24" = insertvalue %"any[]" %27, i64 1, 1 + store %any %24, ptr %taddr26, align 8 + %lo27 = load i64, ptr %taddr26, align 8 + %ptradd28 = getelementptr inbounds i8, ptr %taddr26, i64 8 + %hi29 = load ptr, ptr %ptradd28, align 8 + store %"any[]" %"$$temp24", ptr %indirectarg30, align 8 + %28 = call i64 @std.io.fprintf(ptr %retparam25, i64 %lo27, ptr %hi29, ptr @.str.4, i64 2, ptr byval(%"any[]") align 8 %indirectarg30) + %not_err31 = icmp eq i64 %28, 0 + %29 = call i1 @llvm.expect.i1(i1 %not_err31, i1 true) + br i1 %29, label %after_check33, label %assign_optional32 + +assign_optional32: ; preds = %voiderr + store i64 %28, ptr %error_var20, align 8 + br label %guard_block34 + +after_check33: ; preds = %voiderr + br label %noerr_block35 + +guard_block34: ; preds = %assign_optional32 + br label %voiderr49 + +noerr_block35: ; preds = %after_check33 + %30 = load i64, ptr %retparam25, align 8 + store i64 %30, ptr %len19, align 8 + %31 = call i64 @std.io.File.write_byte(ptr %20, i8 zeroext 10) + %not_err37 = icmp eq i64 %31, 0 + %32 = call i1 @llvm.expect.i1(i1 %not_err37, i1 true) + br i1 %32, label %after_check39, label %assign_optional38 + +assign_optional38: ; preds = %noerr_block35 + store i64 %31, ptr %error_var36, align 8 + br label %guard_block40 + +after_check39: ; preds = %noerr_block35 + br label %noerr_block41 + +guard_block40: ; preds = %assign_optional38 + br label %voiderr49 + +noerr_block41: ; preds = %after_check39 + %33 = call i64 @std.io.File.flush(ptr %20) + %not_err43 = icmp eq i64 %33, 0 + %34 = call i1 @llvm.expect.i1(i1 %not_err43, i1 true) + br i1 %34, label %after_check45, label %assign_optional44 + +assign_optional44: ; preds = %noerr_block41 + store i64 %33, ptr %error_var42, align 8 + br label %guard_block46 + +after_check45: ; preds = %noerr_block41 + br label %noerr_block47 + +guard_block46: ; preds = %assign_optional44 + br label %voiderr49 + +noerr_block47: ; preds = %after_check45 + %35 = load i64, ptr %len19, align 8 + %add48 = add i64 %35, 1 + br label %voiderr49 + +voiderr49: ; preds = %noerr_block47, %guard_block46, %guard_block40, %guard_block34 + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %x50, ptr align 8 %y, i32 16, i1 false) + %36 = call ptr @std.io.stdout() + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %x51, ptr align 8 %x50, i32 16, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 8 %x54, ptr align 8 %x51, i32 16, i1 false) + %37 = insertvalue %any undef, ptr %36, 0 + %38 = insertvalue %any %37, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + %39 = insertvalue %any undef, ptr %x54, 0 + %40 = insertvalue %any %39, i64 ptrtoint (ptr @"$ct.sa$int" to i64), 1 + store %any %40, ptr %varargslots56, align 16 + %41 = insertvalue %"any[]" undef, ptr %varargslots56, 0 + %"$$temp57" = insertvalue %"any[]" %41, i64 1, 1 + store %any %38, ptr %taddr59, align 8 + %lo60 = load i64, ptr %taddr59, align 8 + %ptradd61 = getelementptr inbounds i8, ptr %taddr59, i64 8 + %hi62 = load ptr, ptr %ptradd61, align 8 + store %"any[]" %"$$temp57", ptr %indirectarg63, align 8 + %42 = call i64 @std.io.fprintf(ptr %retparam58, i64 %lo60, ptr %hi62, ptr @.str.5, i64 2, ptr byval(%"any[]") align 8 %indirectarg63) + %not_err64 = icmp eq i64 %42, 0 + %43 = call i1 @llvm.expect.i1(i1 %not_err64, i1 true) + br i1 %43, label %after_check66, label %assign_optional65 + +assign_optional65: ; preds = %voiderr49 + store i64 %42, ptr %error_var53, align 8 + br label %guard_block67 + +after_check66: ; preds = %voiderr49 + br label %noerr_block68 + +guard_block67: ; preds = %assign_optional65 + br label %voiderr82 + +noerr_block68: ; preds = %after_check66 + %44 = load i64, ptr %retparam58, align 8 + store i64 %44, ptr %len52, align 8 + %45 = call i64 @std.io.File.write_byte(ptr %36, i8 zeroext 10) + %not_err70 = icmp eq i64 %45, 0 + %46 = call i1 @llvm.expect.i1(i1 %not_err70, i1 true) + br i1 %46, label %after_check72, label %assign_optional71 + +assign_optional71: ; preds = %noerr_block68 + store i64 %45, ptr %error_var69, align 8 + br label %guard_block73 + +after_check72: ; preds = %noerr_block68 + br label %noerr_block74 + +guard_block73: ; preds = %assign_optional71 + br label %voiderr82 + +noerr_block74: ; preds = %after_check72 + %47 = call i64 @std.io.File.flush(ptr %36) + %not_err76 = icmp eq i64 %47, 0 + %48 = call i1 @llvm.expect.i1(i1 %not_err76, i1 true) + br i1 %48, label %after_check78, label %assign_optional77 + +assign_optional77: ; preds = %noerr_block74 + store i64 %47, ptr %error_var75, align 8 + br label %guard_block79 + +after_check78: ; preds = %noerr_block74 + br label %noerr_block80 + +guard_block79: ; preds = %assign_optional77 + br label %voiderr82 + +noerr_block80: ; preds = %after_check78 + %49 = load i64, ptr %len52, align 8 + %add81 = add i64 %49, 1 + br label %voiderr82 + +voiderr82: ; preds = %noerr_block80, %guard_block79, %guard_block73, %guard_block67 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal83, ptr align 4 @.__const.6, i32 12, i1 false) + %50 = insertvalue %"int[]" undef, ptr %literal83, 0 + %51 = insertvalue %"int[]" %50, i64 3, 1 + %52 = call ptr @std.io.stdout() + %53 = insertvalue %any undef, ptr %52, 0 + %54 = insertvalue %any %53, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + store %"int[]" %51, ptr %taddr88, align 8 + %55 = insertvalue %any undef, ptr %taddr88, 0 + %56 = insertvalue %any %55, i64 ptrtoint (ptr @"$ct.sa$int" to i64), 1 + store %any %56, ptr %varargslots87, align 16 + %57 = insertvalue %"any[]" undef, ptr %varargslots87, 0 + %"$$temp89" = insertvalue %"any[]" %57, i64 1, 1 + store %any %54, ptr %taddr91, align 8 + %lo92 = load i64, ptr %taddr91, align 8 + %ptradd93 = getelementptr inbounds i8, ptr %taddr91, i64 8 + %hi94 = load ptr, ptr %ptradd93, align 8 + store %"any[]" %"$$temp89", ptr %indirectarg95, align 8 + %58 = call i64 @std.io.fprintf(ptr %retparam90, i64 %lo92, ptr %hi94, ptr @.str.7, i64 2, ptr byval(%"any[]") align 8 %indirectarg95) + %not_err96 = icmp eq i64 %58, 0 + %59 = call i1 @llvm.expect.i1(i1 %not_err96, i1 true) + br i1 %59, label %after_check98, label %assign_optional97 + +assign_optional97: ; preds = %voiderr82 + store i64 %58, ptr %error_var85, align 8 + br label %guard_block99 + +after_check98: ; preds = %voiderr82 + br label %noerr_block100 + +guard_block99: ; preds = %assign_optional97 + br label %voiderr114 + +noerr_block100: ; preds = %after_check98 + %60 = load i64, ptr %retparam90, align 8 + store i64 %60, ptr %len84, align 8 + %61 = call i64 @std.io.File.write_byte(ptr %52, i8 zeroext 10) + %not_err102 = icmp eq i64 %61, 0 + %62 = call i1 @llvm.expect.i1(i1 %not_err102, i1 true) + br i1 %62, label %after_check104, label %assign_optional103 + +assign_optional103: ; preds = %noerr_block100 + store i64 %61, ptr %error_var101, align 8 + br label %guard_block105 + +after_check104: ; preds = %noerr_block100 + br label %noerr_block106 + +guard_block105: ; preds = %assign_optional103 + br label %voiderr114 + +noerr_block106: ; preds = %after_check104 + %63 = call i64 @std.io.File.flush(ptr %52) + %not_err108 = icmp eq i64 %63, 0 + %64 = call i1 @llvm.expect.i1(i1 %not_err108, i1 true) + br i1 %64, label %after_check110, label %assign_optional109 + +assign_optional109: ; preds = %noerr_block106 + store i64 %63, ptr %error_var107, align 8 + br label %guard_block111 + +after_check110: ; preds = %noerr_block106 + br label %noerr_block112 + +guard_block111: ; preds = %assign_optional109 + br label %voiderr114 + +noerr_block112: ; preds = %after_check110 + %65 = load i64, ptr %len84, align 8 + %add113 = add i64 %65, 1 + br label %voiderr114 + +voiderr114: ; preds = %noerr_block112, %guard_block111, %guard_block105, %guard_block99 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %literal115, ptr align 4 @.__const.8, i32 8, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x116, ptr align 4 %literal115, i32 8, i1 false) + %66 = call ptr @std.io.stdout() + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x117, ptr align 4 %x116, i32 8, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x120, ptr align 4 %x117, i32 8, i1 false) + %67 = insertvalue %any undef, ptr %66, 0 + %68 = insertvalue %any %67, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + %69 = insertvalue %any undef, ptr %x120, 0 + %70 = insertvalue %any %69, i64 ptrtoint (ptr @"$ct.a2$int" to i64), 1 + store %any %70, ptr %varargslots122, align 16 + %71 = insertvalue %"any[]" undef, ptr %varargslots122, 0 + %"$$temp123" = insertvalue %"any[]" %71, i64 1, 1 + store %any %68, ptr %taddr125, align 8 + %lo126 = load i64, ptr %taddr125, align 8 + %ptradd127 = getelementptr inbounds i8, ptr %taddr125, i64 8 + %hi128 = load ptr, ptr %ptradd127, align 8 + store %"any[]" %"$$temp123", ptr %indirectarg129, align 8 + %72 = call i64 @std.io.fprintf(ptr %retparam124, i64 %lo126, ptr %hi128, ptr @.str.9, i64 2, ptr byval(%"any[]") align 8 %indirectarg129) + %not_err130 = icmp eq i64 %72, 0 + %73 = call i1 @llvm.expect.i1(i1 %not_err130, i1 true) + br i1 %73, label %after_check132, label %assign_optional131 + +assign_optional131: ; preds = %voiderr114 + store i64 %72, ptr %error_var119, align 8 + br label %guard_block133 + +after_check132: ; preds = %voiderr114 + br label %noerr_block134 + +guard_block133: ; preds = %assign_optional131 + br label %voiderr148 + +noerr_block134: ; preds = %after_check132 + %74 = load i64, ptr %retparam124, align 8 + store i64 %74, ptr %len118, align 8 + %75 = call i64 @std.io.File.write_byte(ptr %66, i8 zeroext 10) + %not_err136 = icmp eq i64 %75, 0 + %76 = call i1 @llvm.expect.i1(i1 %not_err136, i1 true) + br i1 %76, label %after_check138, label %assign_optional137 + +assign_optional137: ; preds = %noerr_block134 + store i64 %75, ptr %error_var135, align 8 + br label %guard_block139 + +after_check138: ; preds = %noerr_block134 + br label %noerr_block140 + +guard_block139: ; preds = %assign_optional137 + br label %voiderr148 + +noerr_block140: ; preds = %after_check138 + %77 = call i64 @std.io.File.flush(ptr %66) + %not_err142 = icmp eq i64 %77, 0 + %78 = call i1 @llvm.expect.i1(i1 %not_err142, i1 true) + br i1 %78, label %after_check144, label %assign_optional143 + +assign_optional143: ; preds = %noerr_block140 + store i64 %77, ptr %error_var141, align 8 + br label %guard_block145 + +after_check144: ; preds = %noerr_block140 + br label %noerr_block146 + +guard_block145: ; preds = %assign_optional143 + br label %voiderr148 + +noerr_block146: ; preds = %after_check144 + %79 = load i64, ptr %len118, align 8 + %add147 = add i64 %79, 1 + br label %voiderr148 + +voiderr148: ; preds = %noerr_block146, %guard_block145, %guard_block139, %guard_block133 + %80 = call ptr @std.io.stdout() + %81 = insertvalue %any undef, ptr %80, 0 + %82 = insertvalue %any %81, i64 ptrtoint (ptr @"$ct.std.io.File" to i64), 1 + store %"int[]" zeroinitializer, ptr %taddr153, align 8 + %83 = insertvalue %any undef, ptr %taddr153, 0 + %84 = insertvalue %any %83, i64 ptrtoint (ptr @"$ct.sa$int" to i64), 1 + store %any %84, ptr %varargslots152, align 16 + %85 = insertvalue %"any[]" undef, ptr %varargslots152, 0 + %"$$temp154" = insertvalue %"any[]" %85, i64 1, 1 + store %any %82, ptr %taddr156, align 8 + %lo157 = load i64, ptr %taddr156, align 8 + %ptradd158 = getelementptr inbounds i8, ptr %taddr156, i64 8 + %hi159 = load ptr, ptr %ptradd158, align 8 + store %"any[]" %"$$temp154", ptr %indirectarg160, align 8 + %86 = call i64 @std.io.fprintf(ptr %retparam155, i64 %lo157, ptr %hi159, ptr @.str.10, i64 2, ptr byval(%"any[]") align 8 %indirectarg160) + %not_err161 = icmp eq i64 %86, 0 + %87 = call i1 @llvm.expect.i1(i1 %not_err161, i1 true) + br i1 %87, label %after_check163, label %assign_optional162 + +assign_optional162: ; preds = %voiderr148 + store i64 %86, ptr %error_var150, align 8 + br label %guard_block164 + +after_check163: ; preds = %voiderr148 + br label %noerr_block165 + +guard_block164: ; preds = %assign_optional162 + br label %voiderr179 + +noerr_block165: ; preds = %after_check163 + %88 = load i64, ptr %retparam155, align 8 + store i64 %88, ptr %len149, align 8 + %89 = call i64 @std.io.File.write_byte(ptr %80, i8 zeroext 10) + %not_err167 = icmp eq i64 %89, 0 + %90 = call i1 @llvm.expect.i1(i1 %not_err167, i1 true) + br i1 %90, label %after_check169, label %assign_optional168 + +assign_optional168: ; preds = %noerr_block165 + store i64 %89, ptr %error_var166, align 8 + br label %guard_block170 + +after_check169: ; preds = %noerr_block165 + br label %noerr_block171 + +guard_block170: ; preds = %assign_optional168 + br label %voiderr179 + +noerr_block171: ; preds = %after_check169 + %91 = call i64 @std.io.File.flush(ptr %80) + %not_err173 = icmp eq i64 %91, 0 + %92 = call i1 @llvm.expect.i1(i1 %not_err173, i1 true) + br i1 %92, label %after_check175, label %assign_optional174 + +assign_optional174: ; preds = %noerr_block171 + store i64 %91, ptr %error_var172, align 8 + br label %guard_block176 + +after_check175: ; preds = %noerr_block171 + br label %noerr_block177 + +guard_block176: ; preds = %assign_optional174 + br label %voiderr179 + +noerr_block177: ; preds = %after_check175 + %93 = load i64, ptr %len149, align 8 + %add178 = add i64 %93, 1 + br label %voiderr179 + +voiderr179: ; preds = %noerr_block177, %guard_block176, %guard_block170, %guard_block164 + ret i32 0 +} + diff --git a/test/test_suite/statements/foreach_errors.c3 b/test/test_suite/statements/foreach_errors.c3 index e3a9b6988..64531102b 100644 --- a/test/test_suite/statements/foreach_errors.c3 +++ b/test/test_suite/statements/foreach_errors.c3 @@ -44,7 +44,7 @@ fn void test6() fn void test7() { foreach (int a : { 1, 2, 3 }) foo(); - foreach (a : { 1, 2, 3 }) foo(); // #error: Add the type of your variable here if you want to iterate over + foreach (a : { 1, 2, 3 }) foo(); // #error: Add an explicit type to the variable } fn void test8() diff --git a/test/test_suite/statements/foreach_r_errors.c3 b/test/test_suite/statements/foreach_r_errors.c3 index bd211ead3..df840104a 100644 --- a/test/test_suite/statements/foreach_r_errors.c3 +++ b/test/test_suite/statements/foreach_r_errors.c3 @@ -44,7 +44,7 @@ fn void test6() fn void test7() { foreach_r (int a : { 1, 2, 3 }) foo(); - foreach_r (a : { 1, 2, 3 }) foo(); // #error: Add the type of your variable here if you want to iterate over + foreach_r (a : { 1, 2, 3 }) foo(); // #error: Add an explicit type to the variable } fn void test8() diff --git a/test/test_suite/statements/foreach_r_with_error.c3 b/test/test_suite/statements/foreach_r_with_error.c3 index cbed085c8..dea64e90c 100644 --- a/test/test_suite/statements/foreach_r_with_error.c3 +++ b/test/test_suite/statements/foreach_r_with_error.c3 @@ -4,7 +4,7 @@ fn void test() { int[3]! x; int g; - foreach_r (z : x) // #error: The expression may not be optional. + foreach_r (z : x) // #error: The foreach iterable expression may not be { g += z; x[0] = 1; diff --git a/test/test_suite/statements/foreach_with_error.c3 b/test/test_suite/statements/foreach_with_error.c3 index 4737c8b9d..7edd14487 100644 --- a/test/test_suite/statements/foreach_with_error.c3 +++ b/test/test_suite/statements/foreach_with_error.c3 @@ -4,7 +4,7 @@ fn void test() { int[3]! x; int g; - foreach (z : x) // #error: The expression may not be optional. + foreach (z : x) // #error: The foreach iterable expression { g += z; x[0] = 1; diff --git a/test/test_suite/struct/initialize_inline_designated.c3t b/test/test_suite/struct/initialize_inline_designated.c3t index a8a28f2cf..f8c0fe5d9 100644 --- a/test/test_suite/struct/initialize_inline_designated.c3t +++ b/test/test_suite/struct/initialize_inline_designated.c3t @@ -18,13 +18,14 @@ fn void main() } /* #expect: test.ll -%Abc = type { i32, i32 } %Bcd = type { %Abc, i32 } -@.__const = private unnamed_addr constant %Abc { i32 123, i32 333 }, align 4 +%Abc = type { i32, i32 } %z = alloca %Bcd, align 4 - call void @llvm.memcpy.p0.p0.i32(ptr align 4 %z, ptr align 4 @.__const, i32 8, i1 false) - %ptradd = getelementptr inbounds i8, ptr %z, i64 8 - store i32 0, ptr %ptradd, align 4 + store i32 123, ptr %z, align 4 + %ptradd = getelementptr inbounds i8, ptr %z, i64 4 + store i32 333, ptr %ptradd, align 4 + %ptradd1 = getelementptr inbounds i8, ptr %z, i64 8 + store i32 0, ptr %ptradd1, align 4 ret void } diff --git a/test/test_suite/struct/nested_struct_union_init.c3t b/test/test_suite/struct/nested_struct_union_init.c3t index 9798c1d0b..a56616fe1 100644 --- a/test/test_suite/struct/nested_struct_union_init.c3t +++ b/test/test_suite/struct/nested_struct_union_init.c3t @@ -67,25 +67,25 @@ entry: %x = alloca %Matrix3x3, align 4 %m = alloca %Matrix2x2, align 4 %m2 = alloca %Matrix2x2_b, align 4 - call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x, ptr align 4 @.__const, i32 4, i1 false) + store float 1.000000e+00, ptr %x, align 4 %ptradd = getelementptr inbounds i8, ptr %x, i64 4 - call void @llvm.memcpy.p0.p0.i32(ptr align 4 %ptradd, ptr align 4 @.__const.16, i32 4, i1 false) + store float 2.000000e+00, ptr %ptradd, align 4 %ptradd1 = getelementptr inbounds i8, ptr %x, i64 8 - call void @llvm.memcpy.p0.p0.i32(ptr align 4 %ptradd1, ptr align 4 @.__const.17, i32 4, i1 false) + store float 3.000000e+00, ptr %ptradd1, align 4 %ptradd2 = getelementptr inbounds i8, ptr %x, i64 12 - call void @llvm.memcpy.p0.p0.i32(ptr align 4 %ptradd2, ptr align 4 @.__const.18, i32 4, i1 false) + store float 4.000000e+00, ptr %ptradd2, align 4 %ptradd3 = getelementptr inbounds i8, ptr %x, i64 16 - call void @llvm.memcpy.p0.p0.i32(ptr align 4 %ptradd3, ptr align 4 @.__const.19, i32 4, i1 false) + store float 5.000000e+00, ptr %ptradd3, align 4 %ptradd4 = getelementptr inbounds i8, ptr %x, i64 20 - call void @llvm.memcpy.p0.p0.i32(ptr align 4 %ptradd4, ptr align 4 @.__const.20, i32 4, i1 false) + store float 6.000000e+00, ptr %ptradd4, align 4 %ptradd5 = getelementptr inbounds i8, ptr %x, i64 24 - call void @llvm.memcpy.p0.p0.i32(ptr align 4 %ptradd5, ptr align 4 @.__const.21, i32 4, i1 false) + store float 7.000000e+00, ptr %ptradd5, align 4 %ptradd6 = getelementptr inbounds i8, ptr %x, i64 28 - call void @llvm.memcpy.p0.p0.i32(ptr align 4 %ptradd6, ptr align 4 @.__const.22, i32 4, i1 false) + store float 8.000000e+00, ptr %ptradd6, align 4 %ptradd7 = getelementptr inbounds i8, ptr %x, i64 32 - call void @llvm.memcpy.p0.p0.i32(ptr align 4 %ptradd7, ptr align 4 @.__const.23, i32 4, i1 false) - call void @llvm.memcpy.p0.p0.i32(ptr align 4 %m, ptr align 4 @.__const.24, i32 16, i1 false) - call void @llvm.memcpy.p0.p0.i32(ptr align 4 %m2, ptr align 4 @.__const.25, i32 16, i1 false) + store float 9.000000e+00, ptr %ptradd7, align 4 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %m, ptr align 4 @.__const, i32 16, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %m2, ptr align 4 @.__const.16, i32 16, i1 false) %0 = load float, ptr %x, align 4 %fpfpext = fpext float %0 to double %ptradd8 = getelementptr inbounds i8, ptr %x, i64 4