diff --git a/lib/std/core/builtin.c3 b/lib/std/core/builtin.c3 index 7e443268d..c111d6a55 100644 --- a/lib/std/core/builtin.c3 +++ b/lib/std/core/builtin.c3 @@ -147,3 +147,13 @@ macro bool @convertible(#expr, $To) @builtin { return $checks($To x = #expr); } + +macro uint int.hash(int i) = i; +macro uint uint.hash(uint i) = i; +macro uint short.hash(short s) = s; +macro uint ushort.hash(ushort s) = s; +macro uint char.hash(char c) = c; +macro uint ichar.hash(ichar c) = c; +macro uint long.hash(long i) = (uint)((i >> 32) ^ i); +macro uint ulong.hash(ulong i) = (uint)((i >> 32) ^ i); +macro uint bool.hash(bool b) = (uint)b; diff --git a/lib/std/core/mem_array.c3 b/lib/std/core/mem_array.c3 index 76658b593..15b5671a6 100644 --- a/lib/std/core/mem_array.c3 +++ b/lib/std/core/mem_array.c3 @@ -26,7 +26,7 @@ macro talloc($Type, usize elements) **/ macro make($Type, usize elements) { - $Type* ptr = calloc($sizeof($Type) * elements); + $Type* ptr = calloc($Type.sizeof * elements); return ptr[:elements]; } @@ -35,6 +35,6 @@ macro make($Type, usize elements) **/ macro tmake($Type, usize elements) { - $Type* ptr = tcalloc($sizeof($Type) * elements, $alignof($Type[1])); + $Type* ptr = tcalloc($Type.sizeof * elements, $alignof($Type[1])); return ptr[:elements]; } diff --git a/lib/std/math.c3 b/lib/std/math.c3 index c3931318b..5f4babd49 100644 --- a/lib/std/math.c3 +++ b/lib/std/math.c3 @@ -138,5 +138,11 @@ macro bool is_power_of_2(x) return x != 0 && (x & (x - 1)) == 0; } +macro next_power_of_2(x) +{ + $typeof(x) y = 1; + while (y < x) y += y; + return y; +} diff --git a/resources/examples/map.c3 b/resources/examples/map.c3 new file mode 100644 index 000000000..40abcdacf --- /dev/null +++ b/resources/examples/map.c3 @@ -0,0 +1,97 @@ +module std::container::map ; +import std::core::builtin; +import std::io; +fault MapResult +{ + KEY_NOT_FOUND +} + +struct Entry +{ + Key key; + Type value; + usize hash; + Entry* next; + bool used; +} + +struct Map +{ + usize size; + Entry* map; + uint mod; +} + +/** + * @require map != null + **/ +fn void Map.init(Map *map, uint capacity = 128) +{ + if (capacity < 16) capacity = 4; + capacity = math::next_power_of_2(capacity); + map.map = calloc(Entry.sizeof * capacity); + map.mod = capacity - 1; +} + +fn Type! Map.valueForKey(Map *map, Key key) +{ + if (!map.map) return MapResult.KEY_NOT_FOUND!; + uint hash = key.hash(); + usize pos = hash & map.mod; + Entry* entry = &map.map[pos]; + if (!entry) return MapResult.KEY_NOT_FOUND!; + while (entry) + { + if (entry.hash == hash && entry.key == key) return entry.value; + entry = entry.next; + } + return MapResult.KEY_NOT_FOUND!; +} + +fn Type! Map.set(Map *map, Key key, Type value) @maydiscard +{ + if (!map.map) + { + map.map = calloc(Entry.sizeof * 16); + map.mod = 0x0F; + } + + uint hash = key.hash(); + uint pos = hash & map.mod; + Entry *entry = &map.map[pos]; + while (1) + { + if (!entry.used) + { + entry.used = true; + entry.value = value; + entry.hash = hash; + entry.key = key; + return MapResult.KEY_NOT_FOUND!; + } + if (entry.hash == hash && entry.key == key) + { + Type old = entry.value; + entry.value = value; + return old; + } + if (entry.next) + { + entry = entry.next; + continue; + } + Entry* new = mem::calloc(Entry.sizeof); + new.hash = hash; + new.key = key; + new.value = value; + new.next = null; + new.used = true; + entry.next = new; + return MapResult.KEY_NOT_FOUND!; + } +} + +fn usize Map.size(Map* map) +{ + return map.size; +} diff --git a/resources/examples/notworking/map.c3 b/resources/examples/notworking/map.c3 deleted file mode 100644 index 6f4ccb62a..000000000 --- a/resources/examples/notworking/map.c3 +++ /dev/null @@ -1,87 +0,0 @@ -module std::container::map ; - -fault MapResult -{ - KEY_NOT_FOUND -} - -public struct Entry -{ - Key key; - Type value; - usize hash; - Entry* next; -} - -public struct Map -{ - usize size; - void* map; - uint mod; - Allocator allocator; -} - -/** - * @require map != null - **/ -public fn void Map.init(Map *map, Allocator allocator) -{ - map.allocator = allocator; -} - -public fn Type! Map.valueForKey(Map *map, Key key) -{ - if (!map.map) return null; - usize hash = key.hash(); - usize pos = hash & map.mod; - Entry* entry = &map.map[pop]; - if (!entry) return MapResult.KEY_NOT_FOUND!; - while (entry) - { - if (entry.hash == hash && entry.key == key) return entry.value; - entry = entry.next; - } - return MapResult.KEY_NOT_FOUND!; -} - -public fn Type *Map.set(Map *map, Key key, Type value) -{ - if (!map.map) - { - map.map = allocator.calloc(Entry, 16); - map.mod = 0x0F; - } - - usize hash = key.hash(); - usize pos = hash & map.mod; - Entry *entry = &map.map[pop]; - while (1) - { - if (!entry.value) - { - entry.value = value; - entry.hash = hash; - entry.key = key; - return nil; - } - if (entry.hash == hash && entry.key == key) - { - Type *old = entry.value; - entry.value = value; - return old; - } - if (entry.next) - { - entry = entry.next; - } - entry.next = allocator.alloc(Entry); - entry = entry.next; - } -} - -public fn usize Map.size(Map* map) -{ - return map.size; -} - - diff --git a/src/compiler/ast.c b/src/compiler/ast.c index cac025f5d..31c9c9360 100644 --- a/src/compiler/ast.c +++ b/src/compiler/ast.c @@ -342,6 +342,7 @@ bool expr_is_pure(Expr *expr) case EXPR_DESIGNATED_INITIALIZER_LIST: case EXPR_POST_UNARY: case EXPR_SLICE_ASSIGN: + case EXPR_SLICE_COPY: case EXPR_TRY_UNWRAP: case EXPR_TRY_UNWRAP_CHAIN: case EXPR_FORCE_UNWRAP: diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index 3edb0e307..70ecc5f87 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -247,7 +247,6 @@ void compiler_compile(void) Module **modules = global_context.module_list; unsigned module_count = vec_size(modules); - if (module_count > MAX_MODULES) { error_exit("Too many modules."); diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 2bd2a5d83..1344ffc1f 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -1546,6 +1546,7 @@ typedef struct ParseContext_ typedef struct SemaContext_ { + Module *core_module; // Evaluated in this. CompilationUnit *unit; // Compiled in this unit. @@ -1590,6 +1591,7 @@ typedef struct SemaContext_ typedef struct { HTable modules; + Module *core_module; Module **module_list; Module **generic_module_list; Type **type; @@ -2406,7 +2408,7 @@ INLINE bool type_info_poison(TypeInfo *type) INLINE bool type_is_arraylike(Type *type) { DECL_TYPE_KIND_REAL(kind, type); - return kind == TYPE_ARRAY || kind == TYPE_VECTOR || kind == TYPE_FLEXIBLE_ARRAY; + return kind == TYPE_ARRAY || kind == TYPE_VECTOR || kind == TYPE_FLEXIBLE_ARRAY || kind == TYPE_SCALED_VECTOR; } INLINE CanonicalType *type_pointer_type(Type *type) diff --git a/src/compiler/copying.c b/src/compiler/copying.c index 32e09b5d2..fd10dba9f 100644 --- a/src/compiler/copying.c +++ b/src/compiler/copying.c @@ -249,6 +249,7 @@ Expr *copy_expr(CopyStruct *c, Expr *source_expr) MACRO_COPY_TYPE(expr->type_expr); return expr; case EXPR_SLICE_ASSIGN: + case EXPR_SLICE_COPY: MACRO_COPY_EXPRID(expr->slice_assign_expr.left); MACRO_COPY_EXPRID(expr->slice_assign_expr.right); return expr; diff --git a/src/compiler/enums.h b/src/compiler/enums.h index ab19d5069..13a38bd98 100644 --- a/src/compiler/enums.h +++ b/src/compiler/enums.h @@ -235,6 +235,7 @@ typedef enum EXPR_POST_UNARY, EXPR_SLICE, EXPR_SLICE_ASSIGN, + EXPR_SLICE_COPY, EXPR_SUBSCRIPT, EXPR_SUBSCRIPT_ADDR, EXPR_POINTER_OFFSET, diff --git a/src/compiler/llvm_codegen_builtins.c b/src/compiler/llvm_codegen_builtins.c index 51c4b065d..84ea1df1a 100644 --- a/src/compiler/llvm_codegen_builtins.c +++ b/src/compiler/llvm_codegen_builtins.c @@ -220,6 +220,8 @@ INLINE void llvm_emit_memcpy_builtin(GenContext *c, BEValue *be_value, Expr *exp Expr **args = expr->call_expr.arguments; LLVMValueRef arg_slots[4]; llvm_emit_intrinsic_args(c, args, arg_slots, 4); + arg_slots[0] = llvm_emit_bitcast(c, arg_slots[0], type_voidptr); + arg_slots[1] = llvm_emit_bitcast(c, arg_slots[1], type_voidptr); LLVMTypeRef call_type[3]; call_type[0] = call_type[1] = llvm_get_type(c, type_voidptr); call_type[2] = llvm_get_type(c, type_usize); diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index 578d4aa04..e19eaa1e1 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -1176,6 +1176,17 @@ void llvm_emit_cast(GenContext *c, CastKind cast_kind, Expr *expr, BEValue *valu break; case CAST_SAPTR: llvm_emit_subarray_pointer(c, value, value); + if (value->type != to_type) + { + if (llvm_value_is_addr(value)) + { + value->value = LLVMBuildPointerCast(c->builder, value->value, llvm_get_ptr_type(c, to_type), "saptr"); + } + else + { + value->value = LLVMBuildPointerCast(c->builder, value->value, llvm_get_ptr_type(c, to_type), "saptr"); + } + } break; case CAST_EREU: // This is a no op. @@ -2447,6 +2458,42 @@ static void gencontext_emit_slice(GenContext *c, BEValue *be_value, Expr *expr) llvm_value_aggregate_two(c, be_value, type_lowering(expr->type), start_pointer, size); } +static void llvm_emit_slice_copy(GenContext *c, BEValue *be_value, Expr *expr) +{ + llvm_emit_exprid(c, be_value, expr->slice_assign_expr.right); + llvm_value_rvalue(c, be_value); + + BEValue assigned_to; + llvm_emit_exprid(c, &assigned_to, expr->slice_assign_expr.left); + llvm_value_rvalue(c, &assigned_to); + + BEValue to_pointer; + llvm_emit_subarray_pointer(c, &assigned_to, &to_pointer); + llvm_value_rvalue(c, &to_pointer); + + BEValue from_pointer; + BEValue from_len; + llvm_emit_subarray_pointer(c, be_value, &from_pointer); + llvm_value_rvalue(c, &from_pointer); + llvm_emit_subarray_len(c, be_value, &from_len); + llvm_value_rvalue(c, &from_len); + + if (active_target.feature.safe_mode) + { + BEValue to_len; + llvm_emit_subarray_len(c, &assigned_to, &to_len); + BEValue comp; + llvm_emit_int_comp(c, &comp, &to_len, &from_len, BINARYOP_NE); + llvm_emit_panic_if_true(c, &comp, "Subarray copy length mismatch.", expr->span); + } + + Type *pointer_type = to_pointer.type->pointer; + unsigned alignment = type_abi_alignment(pointer_type); + LLVMValueRef bytes = LLVMBuildMul(c->builder, from_len.value, llvm_const_int(c, from_len.type, type_size(pointer_type)), ""); + LLVMBuildMemCpy(c->builder, to_pointer.value, alignment, from_pointer.value, alignment, bytes); +} + + static void llvm_emit_slice_assign(GenContext *c, BEValue *be_value, Expr *expr) { // We will be replacing the slice assign with code that roughly looks like this: @@ -5575,6 +5622,9 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr) case EXPR_DECL: llvm_emit_local_decl(c, expr->decl_expr, value); return; + case EXPR_SLICE_COPY: + llvm_emit_slice_copy(c, value, expr); + return; case EXPR_SLICE_ASSIGN: llvm_emit_slice_assign(c, value, expr); return; diff --git a/src/compiler/sema_casts.c b/src/compiler/sema_casts.c index 146d9d0d9..8b0517462 100644 --- a/src/compiler/sema_casts.c +++ b/src/compiler/sema_casts.c @@ -784,6 +784,7 @@ Expr *recursive_may_narrow_float(Expr *expr, Type *type) case EXPR_MACRO_BLOCK: case EXPR_IDENTIFIER: case EXPR_SLICE_ASSIGN: + case EXPR_SLICE_COPY: case EXPR_SLICE: case EXPR_SUBSCRIPT: case EXPR_RETVAL: @@ -947,6 +948,7 @@ Expr *recursive_may_narrow_int(Expr *expr, Type *type) case EXPR_MACRO_BLOCK: case EXPR_IDENTIFIER: case EXPR_SLICE_ASSIGN: + case EXPR_SLICE_COPY: case EXPR_SLICE: case EXPR_SUBSCRIPT: case EXPR_RETVAL: diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 2e271dec5..3064ca26b 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -419,6 +419,7 @@ bool expr_is_constant_eval(Expr *expr, ConstantEvalKind eval_kind) case EXPR_TRY_UNWRAP_CHAIN: case EXPR_POST_UNARY: case EXPR_SLICE_ASSIGN: + case EXPR_SLICE_COPY: case EXPR_MACRO_BLOCK: case EXPR_RETHROW: return false; @@ -705,6 +706,7 @@ static bool sema_check_expr_lvalue(Expr *top_expr, Expr *expr) case EXPR_DESIGNATED_INITIALIZER_LIST: case EXPR_POST_UNARY: case EXPR_SLICE_ASSIGN: + case EXPR_SLICE_COPY: case EXPR_STRINGIFY: case EXPR_ARGV_TO_SUBARRAY: case EXPR_TERNARY: @@ -807,6 +809,7 @@ bool expr_may_addr(Expr *expr) case EXPR_DESIGNATED_INITIALIZER_LIST: case EXPR_POST_UNARY: case EXPR_SLICE_ASSIGN: + case EXPR_SLICE_COPY: case EXPR_STRINGIFY: case EXPR_ARGV_TO_SUBARRAY: case EXPR_TERNARY: @@ -3047,14 +3050,24 @@ static inline bool sema_expr_analyse_builtin_call(SemaContext *context, Expr *ex case BUILTIN_VOLATILE_LOAD: { if (!sema_check_builtin_args(args, (BuiltinArg[]) { BA_POINTER }, 1)) return false; - rtype = args[0]->type->canonical->pointer; + Type *original = type_flatten(args[0]->type); + if (original == type_voidptr) + { + SEMA_ERROR(args[0], "Expected a typed pointer."); + return false; + } + rtype = original->pointer; break; } case BUILTIN_VOLATILE_STORE: { if (!sema_check_builtin_args(args, (BuiltinArg[]) { BA_POINTER }, 1)) return false; - rtype = args[0]->type->canonical->pointer; - if (!cast_implicit(args[1], rtype)) return false; + Type *original = type_flatten(args[0]->type); + if (original != type_voidptr) + { + if (!cast_implicit(args[1], original->pointer)) return false; + } + rtype = args[1]->type; break; } case BUILTIN_NONE: @@ -5589,17 +5602,52 @@ static inline bool sema_expr_analyse_cast(SemaContext *context, Expr *expr) return true; } +static inline IndexDiff range_const_len(Range *range) +{ + Expr *start = exprptr(range->start); + Expr *end = exprptrzero(range->end); + if (!expr_is_const_int(start)) return -1; + if (!end || !expr_is_const_int(end)) return -1; + if (!int_fits(end->const_expr.ixx, TYPE_I32)) return -1; + if (!int_fits(start->const_expr.ixx, TYPE_I32)) return -1; + IndexDiff end_val = (IndexDiff)int_to_i64(end->const_expr.ixx); + if (range->is_len) return end_val; + IndexDiff start_val = (IndexDiff)int_to_i64(start->const_expr.ixx); + if (range->start_from_end && range->end_from_end) return start_val - end_val + 1; + if (range->start_from_end != range->end_from_end) return -1; + return end_val - start_val + 1; +} + static inline bool sema_expr_analyse_slice_assign(SemaContext *context, Expr *expr, Type *left_type, Expr *right, bool is_unwrapped) { - // 1. Evaluate right side to required type. - if (!sema_analyse_expr_rhs(context, left_type->array.base, right, false)) return false; - Expr *left = exprptr(expr->binary_expr.left); + Type *base = left_type->array.base; + if (right->expr_kind == EXPR_SLICE) + { + Range *left_range = &left->subscript_expr.range; + Range *right_range = &right->subscript_expr.range; + if (!sema_analyse_expr(context, right)) return false; + if (cast_may_implicit(right->type, base, true, false)) goto ASSIGN; + if (!cast_implicit(right, left_type)) return false; + IndexDiff left_len = range_const_len(left_range); + IndexDiff right_len = range_const_len(right_range); + if (left_len >= 0 && right_len >= 0 && left_len != right_len) + { + SEMA_ERROR(expr, "Length mismatch between subarrays."); + return false; + } + expr->expr_kind = EXPR_SLICE_COPY; + } + else + { +ASSIGN: + if (!sema_analyse_expr_rhs(context, base, right, false)) return false; + expr->expr_kind = EXPR_SLICE_ASSIGN; + } + expr->type = right->type; - expr->expr_kind = EXPR_SLICE_ASSIGN; expr->slice_assign_expr.left = exprid(left); expr->slice_assign_expr.right = exprid(right); - return true; } @@ -7690,14 +7738,14 @@ static inline bool sema_expr_analyse_flat_element(SemaContext *context, ExprFlat Type *actual_type = type_flatten_distinct(type); if (element->array) { - if (!type_is_arraylike(actual_type)) + if (!type_is_arraylike(actual_type) && actual_type->type_kind) { if (is_missing) { *is_missing = true; return false; } - SEMA_ERROR(inner, "It's not possible to index into something that is not an array nor vector."); + SEMA_ERROR(inner, "It's not possible to constant index into something that is not an array nor vector."); return false; } if (!sema_analyse_expr(context, inner)) return false; @@ -7730,6 +7778,7 @@ static inline bool sema_expr_analyse_flat_element(SemaContext *context, ExprFlat if (is_missing) { *is_missing = true; + *index_ref = 0; return false; } SEMA_ERROR(element->inner, "Index exceeds array bounds."); @@ -7747,6 +7796,32 @@ static inline bool sema_expr_analyse_flat_element(SemaContext *context, ExprFlat SEMA_ERROR(inner, "Expected an identifier here."); return false; } + const char *kw = inner->identifier_expr.ident; + if (kw == kw_ptr) + { + switch (actual_type->type_kind) + { + case TYPE_SUBARRAY: + *member_ref = NULL; + *return_type = actual_type->array.base; + return true; + case TYPE_ANY: + *member_ref = NULL; + *return_type = type_voidptr; + return true; + default: + break; + } + } + if (kw == kw_len) + { + if (type_is_arraylike(actual_type) || actual_type->type_kind == TYPE_SUBARRAY) + { + *member_ref = NULL; + *return_type = type_usize; + return true; + } + } if (!type_is_union_or_strukt(actual_type)) { if (is_missing) @@ -7794,7 +7869,7 @@ static inline bool sema_expr_analyse_ct_alignof(SemaContext *context, Expr *expr { ExprFlatElement *element = &path[i]; Decl *member; - ArraySize index; + ArraySize index = 0; Type *result_type; if (!sema_expr_analyse_flat_element(context, element, type, &member, &index, &result_type, i, i == 0 ? main_var->span : expr->span, NULL)) return false; if (member) @@ -8317,7 +8392,7 @@ static inline bool sema_expr_analyse_ct_offsetof(SemaContext *context, Expr *exp { ExprFlatElement *element = &path[i]; Decl *member; - ArraySize index; + ArraySize index = 0; Type *result_type; if (!sema_expr_analyse_flat_element(context, element, type, &member, &index, &result_type, i, i == 0 ? main_var->span : expr->span, NULL)) return false; if (member) @@ -8460,6 +8535,7 @@ static inline bool sema_analyse_expr_dispatch(SemaContext *context, Expr *expr) return false; case EXPR_SLICE_ASSIGN: case EXPR_BUILTIN_ACCESS: + case EXPR_SLICE_COPY: // Created during semantic analysis UNREACHABLE case EXPR_MACRO_BLOCK: diff --git a/src/compiler/sema_name_resolution.c b/src/compiler/sema_name_resolution.c index 60e9bf674..19f77600e 100644 --- a/src/compiler/sema_name_resolution.c +++ b/src/compiler/sema_name_resolution.c @@ -593,16 +593,16 @@ Decl *sema_resolve_method_in_module(Module *module, Type *actual_type, const cha if (found && search_type == METHOD_SEARCH_CURRENT) return found; // We are now searching submodules, so hide the private ones. if (search_type == METHOD_SEARCH_CURRENT) search_type = METHOD_SEARCH_SUBMODULE_CURRENT; - VECEACH(module->sub_modules, i) - { - Decl *new_found = sema_resolve_method_in_module(module->sub_modules[i], actual_type, method_name, private_found, ambiguous, search_type); - if (new_found) + FOREACH_BEGIN(Module *mod, module->sub_modules) + Decl *new_found = sema_resolve_method_in_module(mod, actual_type, method_name, private_found, ambiguous, search_type); + if (!new_found) continue; + if (found) { *ambiguous = new_found; return found; } found = new_found; - } + FOREACH_END(); // We might have it ambiguous due to searching sub modules. return found; } @@ -656,6 +656,16 @@ Decl *sema_resolve_type_method(CompilationUnit *unit, Type *type, const char *me return found; } } + if (!found) + { + found = sema_resolve_method_in_module(global_context.core_module, type, method_name, + &private, &ambiguous, METHOD_SEARCH_IMPORTED); + } + if (found && ambiguous) + { + *ambiguous_ref = ambiguous; + return found; + } if (private) *private_ref = private; if (!found) { diff --git a/src/compiler/semantic_analyser.c b/src/compiler/semantic_analyser.c index df537e49a..87808b8df 100644 --- a/src/compiler/semantic_analyser.c +++ b/src/compiler/semantic_analyser.c @@ -294,6 +294,10 @@ void sema_analysis_run(void) error_exit("No modules to compile."); } + // Create the core module if needed. + Path core_path = { .module = kw_std__core, .span = INVALID_SPAN, .len = strlen(kw_std__core) }; + global_context.core_module = compiler_find_or_create_module(&core_path, NULL, false); + // We parse the generic modules, just by storing the decls. VECEACH(global_context.generic_module_list, i) { diff --git a/test/test_suite/slices/slice_to_slice_assign.c3t b/test/test_suite/slices/slice_to_slice_assign.c3t new file mode 100644 index 000000000..3685be98f --- /dev/null +++ b/test/test_suite/slices/slice_to_slice_assign.c3t @@ -0,0 +1,294 @@ +// #target: macos-x64 +module test; +import std::io; + +fn void main() +{ + int[*] z = { 1, 2, 3, 4, 5, 6, 7 }; + int[6] y; + y[1..3] = z[3..5]; + io::printfln("%s %s", y, z); + y[4..] = z[5..6]; + io::printfln("%s %s", y, z); + int[][] a = { int[] { 1 } }; + int[][] b = { int[] { 2 } }; + io::printfln("%s", a); + a[0..0] = b[0..0]; + io::printfln("%s", a); + a[0..0] = y[2..4]; + io::printfln("%s", a); +} +/* #expect: test.ll + +define void @test_main() #0 { +entry: + %z = alloca [7 x i32], align 16 + %y = alloca [6 x i32], align 16 + %taddr = alloca %"int[]", align 8 + %retparam = alloca i64, align 8 + %taddr1 = alloca %"char[]", align 8 + %vararg = alloca %"variant[]", align 8 + %varargslots = alloca [2 x %variant], align 16 + %taddr4 = alloca %"int[]", align 8 + %retparam5 = alloca i64, align 8 + %taddr6 = alloca %"char[]", align 8 + %vararg9 = alloca %"variant[]", align 8 + %varargslots10 = alloca [2 x %variant], align 16 + %a = alloca %"int[][]", align 8 + %literal = alloca [1 x %"int[]"], align 16 + %literal16 = alloca [1 x i32], align 4 + %b = alloca %"int[][]", align 8 + %literal17 = alloca [1 x %"int[]"], align 16 + %literal18 = alloca [1 x i32], align 4 + %retparam19 = alloca i64, align 8 + %taddr20 = alloca %"char[]", align 8 + %vararg23 = alloca %"variant[]", align 8 + %varargslots24 = alloca [1 x %variant], align 16 + %taddr31 = alloca %"int[][]", align 8 + %retparam32 = alloca i64, align 8 + %taddr33 = alloca %"char[]", align 8 + %vararg36 = alloca %"variant[]", align 8 + %varargslots37 = alloca [1 x %variant], align 16 + %retparam44 = alloca i64, align 8 + %taddr45 = alloca %"char[]", align 8 + %vararg48 = alloca %"variant[]", align 8 + %varargslots49 = alloca [1 x %variant], align 16 + %0 = bitcast [7 x i32]* %z to i8* + call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 %0, i8* align 16 bitcast ([7 x i32]* @.__const to i8*), i32 28, i1 false) + %1 = bitcast [6 x i32]* %y to i8* + call void @llvm.memset.p0i8.i64(i8* align 16 %1, i8 0, i64 24, i1 false) + %2 = getelementptr inbounds [7 x i32], [7 x i32]* %z, i64 0, i64 3 + %3 = insertvalue %"int[]" undef, i32* %2, 0 + %4 = insertvalue %"int[]" %3, i64 3, 1 + %5 = getelementptr inbounds [6 x i32], [6 x i32]* %y, i64 0, i64 1 + %6 = insertvalue %"int[]" undef, i32* %5, 0 + %7 = insertvalue %"int[]" %6, i64 3, 1 + %8 = extractvalue %"int[]" %7, 0 + %9 = extractvalue %"int[]" %4, 0 + store %"int[]" %4, %"int[]"* %taddr, align 8 + %10 = getelementptr inbounds %"int[]", %"int[]"* %taddr, i32 0, i32 1 + %11 = load i64, i64* %10, align 8 + %12 = mul i64 %11, 4 + %13 = bitcast i32* %8 to i8* + %14 = bitcast i32* %9 to i8* + call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %13, i8* align 4 %14, i64 %12, i1 false) + store %"char[]" { i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str, i32 0, i32 0), i64 5 }, %"char[]"* %taddr1, align 8 + %15 = bitcast %"char[]"* %taddr1 to { i8*, i64 }* + %16 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %15, i32 0, i32 0 + %lo = load i8*, i8** %16, align 8 + %17 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %15, i32 0, i32 1 + %hi = load i64, i64* %17, align 8 + %18 = bitcast [6 x i32]* %y to i8* + %19 = insertvalue %variant undef, i8* %18, 0 + %20 = insertvalue %variant %19, i64 ptrtoint (%.introspect* @"ct$a6$int" to i64), 1 + %21 = getelementptr inbounds [2 x %variant], [2 x %variant]* %varargslots, i64 0, i64 0 + store %variant %20, %variant* %21, align 16 + %22 = bitcast [7 x i32]* %z to i8* + %23 = insertvalue %variant undef, i8* %22, 0 + %24 = insertvalue %variant %23, i64 ptrtoint (%.introspect* @"ct$a7$int" to i64), 1 + %25 = getelementptr inbounds [2 x %variant], [2 x %variant]* %varargslots, i64 0, i64 1 + store %variant %24, %variant* %25, align 16 + %26 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg, i32 0, i32 1 + store i64 2, i64* %26, align 8 + %27 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg, i32 0, i32 0 + %28 = bitcast [2 x %variant]* %varargslots to %variant* + store %variant* %28, %variant** %27, align 8 + %29 = bitcast %"variant[]"* %vararg to { i8*, i64 }* + %30 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %29, i32 0, i32 0 + %lo2 = load i8*, i8** %30, align 8 + %31 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %29, i32 0, i32 1 + %hi3 = load i64, i64* %31, align 8 + %32 = call i64 @std_io_printfln(i64* %retparam, i8* %lo, i64 %hi, i8* %lo2, i64 %hi3) + %not_err = icmp eq i64 %32, 0 + br i1 %not_err, label %after_check, label %voiderr + +after_check: ; preds = %entry + br label %voiderr + +voiderr: ; preds = %after_check, %entry + %33 = getelementptr inbounds [7 x i32], [7 x i32]* %z, i64 0, i64 5 + %34 = insertvalue %"int[]" undef, i32* %33, 0 + %35 = insertvalue %"int[]" %34, i64 2, 1 + %36 = getelementptr inbounds [6 x i32], [6 x i32]* %y, i64 0, i64 4 + %37 = insertvalue %"int[]" undef, i32* %36, 0 + %38 = insertvalue %"int[]" %37, i64 2, 1 + %39 = extractvalue %"int[]" %38, 0 + %40 = extractvalue %"int[]" %35, 0 + store %"int[]" %35, %"int[]"* %taddr4, align 8 + %41 = getelementptr inbounds %"int[]", %"int[]"* %taddr4, i32 0, i32 1 + %42 = load i64, i64* %41, align 8 + %43 = mul i64 %42, 4 + %44 = bitcast i32* %39 to i8* + %45 = bitcast i32* %40 to i8* + call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 4 %44, i8* align 4 %45, i64 %43, i1 false) + store %"char[]" { i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.1, i32 0, i32 0), i64 5 }, %"char[]"* %taddr6, align 8 + %46 = bitcast %"char[]"* %taddr6 to { i8*, i64 }* + %47 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %46, i32 0, i32 0 + %lo7 = load i8*, i8** %47, align 8 + %48 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %46, i32 0, i32 1 + %hi8 = load i64, i64* %48, align 8 + %49 = bitcast [6 x i32]* %y to i8* + %50 = insertvalue %variant undef, i8* %49, 0 + %51 = insertvalue %variant %50, i64 ptrtoint (%.introspect* @"ct$a6$int" to i64), 1 + %52 = getelementptr inbounds [2 x %variant], [2 x %variant]* %varargslots10, i64 0, i64 0 + store %variant %51, %variant* %52, align 16 + %53 = bitcast [7 x i32]* %z to i8* + %54 = insertvalue %variant undef, i8* %53, 0 + %55 = insertvalue %variant %54, i64 ptrtoint (%.introspect* @"ct$a7$int" to i64), 1 + %56 = getelementptr inbounds [2 x %variant], [2 x %variant]* %varargslots10, i64 0, i64 1 + store %variant %55, %variant* %56, align 16 + %57 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg9, i32 0, i32 1 + store i64 2, i64* %57, align 8 + %58 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg9, i32 0, i32 0 + %59 = bitcast [2 x %variant]* %varargslots10 to %variant* + store %variant* %59, %variant** %58, align 8 + %60 = bitcast %"variant[]"* %vararg9 to { i8*, i64 }* + %61 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %60, i32 0, i32 0 + %lo11 = load i8*, i8** %61, align 8 + %62 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %60, i32 0, i32 1 + %hi12 = load i64, i64* %62, align 8 + %63 = call i64 @std_io_printfln(i64* %retparam5, i8* %lo7, i64 %hi8, i8* %lo11, i64 %hi12) + %not_err13 = icmp eq i64 %63, 0 + br i1 %not_err13, label %after_check14, label %voiderr15 + +after_check14: ; preds = %voiderr + br label %voiderr15 + +voiderr15: ; preds = %after_check14, %voiderr + %64 = getelementptr inbounds [1 x %"int[]"], [1 x %"int[]"]* %literal, i64 0, i64 0 + %65 = getelementptr inbounds [1 x i32], [1 x i32]* %literal16, i64 0, i64 0 + store i32 1, i32* %65, align 4 + %66 = bitcast [1 x i32]* %literal16 to i32* + %67 = insertvalue %"int[]" undef, i32* %66, 0 + %68 = insertvalue %"int[]" %67, i64 1, 1 + store %"int[]" %68, %"int[]"* %64, align 8 + %69 = bitcast [1 x %"int[]"]* %literal to %"int[]"* + %70 = insertvalue %"int[][]" undef, %"int[]"* %69, 0 + %71 = insertvalue %"int[][]" %70, i64 1, 1 + store %"int[][]" %71, %"int[][]"* %a, align 8 + %72 = getelementptr inbounds [1 x %"int[]"], [1 x %"int[]"]* %literal17, i64 0, i64 0 + %73 = getelementptr inbounds [1 x i32], [1 x i32]* %literal18, i64 0, i64 0 + store i32 2, i32* %73, align 4 + %74 = bitcast [1 x i32]* %literal18 to i32* + %75 = insertvalue %"int[]" undef, i32* %74, 0 + %76 = insertvalue %"int[]" %75, i64 1, 1 + store %"int[]" %76, %"int[]"* %72, align 8 + %77 = bitcast [1 x %"int[]"]* %literal17 to %"int[]"* + %78 = insertvalue %"int[][]" undef, %"int[]"* %77, 0 + %79 = insertvalue %"int[][]" %78, i64 1, 1 + store %"int[][]" %79, %"int[][]"* %b, align 8 + store %"char[]" { i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.2, i32 0, i32 0), i64 2 }, %"char[]"* %taddr20, align 8 + %80 = bitcast %"char[]"* %taddr20 to { i8*, i64 }* + %81 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %80, i32 0, i32 0 + %lo21 = load i8*, i8** %81, align 8 + %82 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %80, i32 0, i32 1 + %hi22 = load i64, i64* %82, align 8 + %83 = bitcast %"int[][]"* %a to i8* + %84 = insertvalue %variant undef, i8* %83, 0 + %85 = insertvalue %variant %84, i64 ptrtoint (%.introspect* @"ct$sa$sa$int" to i64), 1 + %86 = getelementptr inbounds [1 x %variant], [1 x %variant]* %varargslots24, i64 0, i64 0 + store %variant %85, %variant* %86, align 16 + %87 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg23, i32 0, i32 1 + store i64 1, i64* %87, align 8 + %88 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg23, i32 0, i32 0 + %89 = bitcast [1 x %variant]* %varargslots24 to %variant* + store %variant* %89, %variant** %88, align 8 + %90 = bitcast %"variant[]"* %vararg23 to { i8*, i64 }* + %91 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %90, i32 0, i32 0 + %lo25 = load i8*, i8** %91, align 8 + %92 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %90, i32 0, i32 1 + %hi26 = load i64, i64* %92, align 8 + %93 = call i64 @std_io_printfln(i64* %retparam19, i8* %lo21, i64 %hi22, i8* %lo25, i64 %hi26) + %not_err27 = icmp eq i64 %93, 0 + br i1 %not_err27, label %after_check28, label %voiderr29 + +after_check28: ; preds = %voiderr15 + br label %voiderr29 + +voiderr29: ; preds = %after_check28, %voiderr15 + %94 = load %"int[][]", %"int[][]"* %b, align 8 + %95 = extractvalue %"int[][]" %94, 0 + %ptroffset = getelementptr inbounds %"int[]", %"int[]"* %95, i64 0 + %96 = insertvalue %"int[][]" undef, %"int[]"* %ptroffset, 0 + %97 = insertvalue %"int[][]" %96, i64 1, 1 + %98 = load %"int[][]", %"int[][]"* %a, align 8 + %99 = extractvalue %"int[][]" %98, 0 + %ptroffset30 = getelementptr inbounds %"int[]", %"int[]"* %99, i64 0 + %100 = insertvalue %"int[][]" undef, %"int[]"* %ptroffset30, 0 + %101 = insertvalue %"int[][]" %100, i64 1, 1 + %102 = extractvalue %"int[][]" %101, 0 + %103 = extractvalue %"int[][]" %97, 0 + store %"int[][]" %97, %"int[][]"* %taddr31, align 8 + %104 = getelementptr inbounds %"int[][]", %"int[][]"* %taddr31, i32 0, i32 1 + %105 = load i64, i64* %104, align 8 + %106 = mul i64 %105, 16 + %107 = bitcast %"int[]"* %102 to i8* + %108 = bitcast %"int[]"* %103 to i8* + call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 8 %107, i8* align 8 %108, i64 %106, i1 false) + store %"char[]" { i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.3, i32 0, i32 0), i64 2 }, %"char[]"* %taddr33, align 8 + %109 = bitcast %"char[]"* %taddr33 to { i8*, i64 }* + %110 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %109, i32 0, i32 0 + %lo34 = load i8*, i8** %110, align 8 + %111 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %109, i32 0, i32 1 + %hi35 = load i64, i64* %111, align 8 + %112 = bitcast %"int[][]"* %a to i8* + %113 = insertvalue %variant undef, i8* %112, 0 + %114 = insertvalue %variant %113, i64 ptrtoint (%.introspect* @"ct$sa$sa$int" to i64), 1 + %115 = getelementptr inbounds [1 x %variant], [1 x %variant]* %varargslots37, i64 0, i64 0 + store %variant %114, %variant* %115, align 16 + %116 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg36, i32 0, i32 1 + store i64 1, i64* %116, align 8 + %117 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg36, i32 0, i32 0 + %118 = bitcast [1 x %variant]* %varargslots37 to %variant* + store %variant* %118, %variant** %117, align 8 + %119 = bitcast %"variant[]"* %vararg36 to { i8*, i64 }* + %120 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %119, i32 0, i32 0 + %lo38 = load i8*, i8** %120, align 8 + %121 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %119, i32 0, i32 1 + %hi39 = load i64, i64* %121, align 8 + %122 = call i64 @std_io_printfln(i64* %retparam32, i8* %lo34, i64 %hi35, i8* %lo38, i64 %hi39) + %not_err40 = icmp eq i64 %122, 0 + br i1 %not_err40, label %after_check41, label %voiderr42 + +after_check41: ; preds = %voiderr29 + br label %voiderr42 + +voiderr42: ; preds = %after_check41, %voiderr29 + %123 = getelementptr inbounds [6 x i32], [6 x i32]* %y, i64 0, i64 2 + %124 = insertvalue %"int[]" undef, i32* %123, 0 + %125 = insertvalue %"int[]" %124, i64 3, 1 + %126 = load %"int[][]", %"int[][]"* %a, align 8 + %127 = extractvalue %"int[][]" %126, 0 + %ptroffset43 = getelementptr inbounds %"int[]", %"int[]"* %127, i64 0 + store %"int[]" %125, %"int[]"* %ptroffset43, align 8 + store %"char[]" { i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.4, i32 0, i32 0), i64 2 }, %"char[]"* %taddr45, align 8 + %128 = bitcast %"char[]"* %taddr45 to { i8*, i64 }* + %129 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %128, i32 0, i32 0 + %lo46 = load i8*, i8** %129, align 8 + %130 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %128, i32 0, i32 1 + %hi47 = load i64, i64* %130, align 8 + %131 = bitcast %"int[][]"* %a to i8* + %132 = insertvalue %variant undef, i8* %131, 0 + %133 = insertvalue %variant %132, i64 ptrtoint (%.introspect* @"ct$sa$sa$int" to i64), 1 + %134 = getelementptr inbounds [1 x %variant], [1 x %variant]* %varargslots49, i64 0, i64 0 + store %variant %133, %variant* %134, align 16 + %135 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg48, i32 0, i32 1 + store i64 1, i64* %135, align 8 + %136 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg48, i32 0, i32 0 + %137 = bitcast [1 x %variant]* %varargslots49 to %variant* + store %variant* %137, %variant** %136, align 8 + %138 = bitcast %"variant[]"* %vararg48 to { i8*, i64 }* + %139 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %138, i32 0, i32 0 + %lo50 = load i8*, i8** %139, align 8 + %140 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %138, i32 0, i32 1 + %hi51 = load i64, i64* %140, align 8 + %141 = call i64 @std_io_printfln(i64* %retparam44, i8* %lo46, i64 %hi47, i8* %lo50, i64 %hi51) + %not_err52 = icmp eq i64 %141, 0 + br i1 %not_err52, label %after_check53, label %voiderr54 + +after_check53: ; preds = %voiderr42 + br label %voiderr54 + +voiderr54: ; preds = %after_check53, %voiderr42 + ret void +} diff --git a/test/test_suite2/slices/slice_to_slice_assign.c3t b/test/test_suite2/slices/slice_to_slice_assign.c3t new file mode 100644 index 000000000..0ef7df15f --- /dev/null +++ b/test/test_suite2/slices/slice_to_slice_assign.c3t @@ -0,0 +1,260 @@ +// #target: macos-x64 +module test; +import std::io; + +fn void main() +{ + int[*] z = { 1, 2, 3, 4, 5, 6, 7 }; + int[6] y; + y[1..3] = z[3..5]; + io::printfln("%s %s", y, z); + y[4..] = z[5..6]; + io::printfln("%s %s", y, z); + int[][] a = { int[] { 1 } }; + int[][] b = { int[] { 2 } }; + io::printfln("%s", a); + a[0..0] = b[0..0]; + io::printfln("%s", a); + a[0..0] = y[2..4]; + io::printfln("%s", a); +} +/* #expect: test.ll + +define void @test_main() #0 { +entry: + %z = alloca [7 x i32], align 16 + %y = alloca [6 x i32], align 16 + %taddr = alloca %"int[]", align 8 + %retparam = alloca i64, align 8 + %taddr1 = alloca %"char[]", align 8 + %vararg = alloca %"variant[]", align 8 + %varargslots = alloca [2 x %variant], align 16 + %taddr4 = alloca %"int[]", align 8 + %retparam5 = alloca i64, align 8 + %taddr6 = alloca %"char[]", align 8 + %vararg9 = alloca %"variant[]", align 8 + %varargslots10 = alloca [2 x %variant], align 16 + %a = alloca %"int[][]", align 8 + %literal = alloca [1 x %"int[]"], align 16 + %literal16 = alloca [1 x i32], align 4 + %b = alloca %"int[][]", align 8 + %literal17 = alloca [1 x %"int[]"], align 16 + %literal18 = alloca [1 x i32], align 4 + %retparam19 = alloca i64, align 8 + %taddr20 = alloca %"char[]", align 8 + %vararg23 = alloca %"variant[]", align 8 + %varargslots24 = alloca [1 x %variant], align 16 + %taddr31 = alloca %"int[][]", align 8 + %retparam32 = alloca i64, align 8 + %taddr33 = alloca %"char[]", align 8 + %vararg36 = alloca %"variant[]", align 8 + %varargslots37 = alloca [1 x %variant], align 16 + %retparam44 = alloca i64, align 8 + %taddr45 = alloca %"char[]", align 8 + %vararg48 = alloca %"variant[]", align 8 + %varargslots49 = alloca [1 x %variant], align 16 + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %z, ptr align 16 @.__const, i32 28, i1 false) + call void @llvm.memset.p0.i64(ptr align 16 %y, i8 0, i64 24, i1 false) + %0 = getelementptr inbounds [7 x i32], ptr %z, i64 0, i64 3 + %1 = insertvalue %"int[]" undef, ptr %0, 0 + %2 = insertvalue %"int[]" %1, i64 3, 1 + %3 = getelementptr inbounds [6 x i32], ptr %y, i64 0, i64 1 + %4 = insertvalue %"int[]" undef, ptr %3, 0 + %5 = insertvalue %"int[]" %4, i64 3, 1 + %6 = extractvalue %"int[]" %5, 0 + %7 = extractvalue %"int[]" %2, 0 + store %"int[]" %2, ptr %taddr, align 8 + %8 = getelementptr inbounds %"int[]", ptr %taddr, i32 0, i32 1 + %9 = load i64, ptr %8, align 8 + %10 = mul i64 %9, 4 + call void @llvm.memcpy.p0.p0.i64(ptr align 4 %6, ptr align 4 %7, i64 %10, i1 false) + store %"char[]" { ptr @.str, i64 5 }, ptr %taddr1, align 8 + %11 = getelementptr inbounds { ptr, i64 }, ptr %taddr1, i32 0, i32 0 + %lo = load ptr, ptr %11, align 8 + %12 = getelementptr inbounds { ptr, i64 }, ptr %taddr1, i32 0, i32 1 + %hi = load i64, ptr %12, align 8 + %13 = insertvalue %variant undef, ptr %y, 0 + %14 = insertvalue %variant %13, i64 ptrtoint (ptr @"ct$a6$int" to i64), 1 + %15 = getelementptr inbounds [2 x %variant], ptr %varargslots, i64 0, i64 0 + store %variant %14, ptr %15, align 16 + %16 = insertvalue %variant undef, ptr %z, 0 + %17 = insertvalue %variant %16, i64 ptrtoint (ptr @"ct$a7$int" to i64), 1 + %18 = getelementptr inbounds [2 x %variant], ptr %varargslots, i64 0, i64 1 + store %variant %17, ptr %18, align 16 + %19 = getelementptr inbounds %"variant[]", ptr %vararg, i32 0, i32 1 + store i64 2, ptr %19, align 8 + %20 = getelementptr inbounds %"variant[]", ptr %vararg, i32 0, i32 0 + store ptr %varargslots, ptr %20, align 8 + %21 = getelementptr inbounds { ptr, i64 }, ptr %vararg, i32 0, i32 0 + %lo2 = load ptr, ptr %21, align 8 + %22 = getelementptr inbounds { ptr, i64 }, ptr %vararg, i32 0, i32 1 + %hi3 = load i64, ptr %22, align 8 + %23 = call i64 @std_io_printfln(ptr %retparam, ptr %lo, i64 %hi, ptr %lo2, i64 %hi3) + %not_err = icmp eq i64 %23, 0 + br i1 %not_err, label %after_check, label %voiderr + +after_check: ; preds = %entry + br label %voiderr + +voiderr: ; preds = %after_check, %entry + %24 = getelementptr inbounds [7 x i32], ptr %z, i64 0, i64 5 + %25 = insertvalue %"int[]" undef, ptr %24, 0 + %26 = insertvalue %"int[]" %25, i64 2, 1 + %27 = getelementptr inbounds [6 x i32], ptr %y, i64 0, i64 4 + %28 = insertvalue %"int[]" undef, ptr %27, 0 + %29 = insertvalue %"int[]" %28, i64 2, 1 + %30 = extractvalue %"int[]" %29, 0 + %31 = extractvalue %"int[]" %26, 0 + store %"int[]" %26, ptr %taddr4, align 8 + %32 = getelementptr inbounds %"int[]", ptr %taddr4, i32 0, i32 1 + %33 = load i64, ptr %32, align 8 + %34 = mul i64 %33, 4 + call void @llvm.memcpy.p0.p0.i64(ptr align 4 %30, ptr align 4 %31, i64 %34, i1 false) + store %"char[]" { ptr @.str.1, i64 5 }, ptr %taddr6, align 8 + %35 = getelementptr inbounds { ptr, i64 }, ptr %taddr6, i32 0, i32 0 + %lo7 = load ptr, ptr %35, align 8 + %36 = getelementptr inbounds { ptr, i64 }, ptr %taddr6, i32 0, i32 1 + %hi8 = load i64, ptr %36, align 8 + %37 = insertvalue %variant undef, ptr %y, 0 + %38 = insertvalue %variant %37, i64 ptrtoint (ptr @"ct$a6$int" to i64), 1 + %39 = getelementptr inbounds [2 x %variant], ptr %varargslots10, i64 0, i64 0 + store %variant %38, ptr %39, align 16 + %40 = insertvalue %variant undef, ptr %z, 0 + %41 = insertvalue %variant %40, i64 ptrtoint (ptr @"ct$a7$int" to i64), 1 + %42 = getelementptr inbounds [2 x %variant], ptr %varargslots10, i64 0, i64 1 + store %variant %41, ptr %42, align 16 + %43 = getelementptr inbounds %"variant[]", ptr %vararg9, i32 0, i32 1 + store i64 2, ptr %43, align 8 + %44 = getelementptr inbounds %"variant[]", ptr %vararg9, i32 0, i32 0 + store ptr %varargslots10, ptr %44, align 8 + %45 = getelementptr inbounds { ptr, i64 }, ptr %vararg9, i32 0, i32 0 + %lo11 = load ptr, ptr %45, align 8 + %46 = getelementptr inbounds { ptr, i64 }, ptr %vararg9, i32 0, i32 1 + %hi12 = load i64, ptr %46, align 8 + %47 = call i64 @std_io_printfln(ptr %retparam5, ptr %lo7, i64 %hi8, ptr %lo11, i64 %hi12) + %not_err13 = icmp eq i64 %47, 0 + br i1 %not_err13, label %after_check14, label %voiderr15 + +after_check14: ; preds = %voiderr + br label %voiderr15 + +voiderr15: ; preds = %after_check14, %voiderr + %48 = getelementptr inbounds [1 x %"int[]"], ptr %literal, i64 0, i64 0 + %49 = getelementptr inbounds [1 x i32], ptr %literal16, i64 0, i64 0 + store i32 1, ptr %49, align 4 + %50 = insertvalue %"int[]" undef, ptr %literal16, 0 + %51 = insertvalue %"int[]" %50, i64 1, 1 + store %"int[]" %51, ptr %48, align 8 + %52 = insertvalue %"int[][]" undef, ptr %literal, 0 + %53 = insertvalue %"int[][]" %52, i64 1, 1 + store %"int[][]" %53, ptr %a, align 8 + %54 = getelementptr inbounds [1 x %"int[]"], ptr %literal17, i64 0, i64 0 + %55 = getelementptr inbounds [1 x i32], ptr %literal18, i64 0, i64 0 + store i32 2, ptr %55, align 4 + %56 = insertvalue %"int[]" undef, ptr %literal18, 0 + %57 = insertvalue %"int[]" %56, i64 1, 1 + store %"int[]" %57, ptr %54, align 8 + %58 = insertvalue %"int[][]" undef, ptr %literal17, 0 + %59 = insertvalue %"int[][]" %58, i64 1, 1 + store %"int[][]" %59, ptr %b, align 8 + store %"char[]" { ptr @.str.2, i64 2 }, ptr %taddr20, align 8 + %60 = getelementptr inbounds { ptr, i64 }, ptr %taddr20, i32 0, i32 0 + %lo21 = load ptr, ptr %60, align 8 + %61 = getelementptr inbounds { ptr, i64 }, ptr %taddr20, i32 0, i32 1 + %hi22 = load i64, ptr %61, align 8 + %62 = insertvalue %variant undef, ptr %a, 0 + %63 = insertvalue %variant %62, i64 ptrtoint (ptr @"ct$sa$sa$int" to i64), 1 + %64 = getelementptr inbounds [1 x %variant], ptr %varargslots24, i64 0, i64 0 + store %variant %63, ptr %64, align 16 + %65 = getelementptr inbounds %"variant[]", ptr %vararg23, i32 0, i32 1 + store i64 1, ptr %65, align 8 + %66 = getelementptr inbounds %"variant[]", ptr %vararg23, i32 0, i32 0 + store ptr %varargslots24, ptr %66, align 8 + %67 = getelementptr inbounds { ptr, i64 }, ptr %vararg23, i32 0, i32 0 + %lo25 = load ptr, ptr %67, align 8 + %68 = getelementptr inbounds { ptr, i64 }, ptr %vararg23, i32 0, i32 1 + %hi26 = load i64, ptr %68, align 8 + %69 = call i64 @std_io_printfln(ptr %retparam19, ptr %lo21, i64 %hi22, ptr %lo25, i64 %hi26) + %not_err27 = icmp eq i64 %69, 0 + br i1 %not_err27, label %after_check28, label %voiderr29 + +after_check28: ; preds = %voiderr15 + br label %voiderr29 + +voiderr29: ; preds = %after_check28, %voiderr15 + %70 = load %"int[][]", ptr %b, align 8 + %71 = extractvalue %"int[][]" %70, 0 + %ptroffset = getelementptr inbounds %"int[]", ptr %71, i64 0 + %72 = insertvalue %"int[][]" undef, ptr %ptroffset, 0 + %73 = insertvalue %"int[][]" %72, i64 1, 1 + %74 = load %"int[][]", ptr %a, align 8 + %75 = extractvalue %"int[][]" %74, 0 + %ptroffset30 = getelementptr inbounds %"int[]", ptr %75, i64 0 + %76 = insertvalue %"int[][]" undef, ptr %ptroffset30, 0 + %77 = insertvalue %"int[][]" %76, i64 1, 1 + %78 = extractvalue %"int[][]" %77, 0 + %79 = extractvalue %"int[][]" %73, 0 + store %"int[][]" %73, ptr %taddr31, align 8 + %80 = getelementptr inbounds %"int[][]", ptr %taddr31, i32 0, i32 1 + %81 = load i64, ptr %80, align 8 + %82 = mul i64 %81, 16 + call void @llvm.memcpy.p0.p0.i64(ptr align 8 %78, ptr align 8 %79, i64 %82, i1 false) + store %"char[]" { ptr @.str.3, i64 2 }, ptr %taddr33, align 8 + %83 = getelementptr inbounds { ptr, i64 }, ptr %taddr33, i32 0, i32 0 + %lo34 = load ptr, ptr %83, align 8 + %84 = getelementptr inbounds { ptr, i64 }, ptr %taddr33, i32 0, i32 1 + %hi35 = load i64, ptr %84, align 8 + %85 = insertvalue %variant undef, ptr %a, 0 + %86 = insertvalue %variant %85, i64 ptrtoint (ptr @"ct$sa$sa$int" to i64), 1 + %87 = getelementptr inbounds [1 x %variant], ptr %varargslots37, i64 0, i64 0 + store %variant %86, ptr %87, align 16 + %88 = getelementptr inbounds %"variant[]", ptr %vararg36, i32 0, i32 1 + store i64 1, ptr %88, align 8 + %89 = getelementptr inbounds %"variant[]", ptr %vararg36, i32 0, i32 0 + store ptr %varargslots37, ptr %89, align 8 + %90 = getelementptr inbounds { ptr, i64 }, ptr %vararg36, i32 0, i32 0 + %lo38 = load ptr, ptr %90, align 8 + %91 = getelementptr inbounds { ptr, i64 }, ptr %vararg36, i32 0, i32 1 + %hi39 = load i64, ptr %91, align 8 + %92 = call i64 @std_io_printfln(ptr %retparam32, ptr %lo34, i64 %hi35, ptr %lo38, i64 %hi39) + %not_err40 = icmp eq i64 %92, 0 + br i1 %not_err40, label %after_check41, label %voiderr42 + +after_check41: ; preds = %voiderr29 + br label %voiderr42 + +voiderr42: ; preds = %after_check41, %voiderr29 + %93 = getelementptr inbounds [6 x i32], ptr %y, i64 0, i64 2 + %94 = insertvalue %"int[]" undef, ptr %93, 0 + %95 = insertvalue %"int[]" %94, i64 3, 1 + %96 = load %"int[][]", ptr %a, align 8 + %97 = extractvalue %"int[][]" %96, 0 + %ptroffset43 = getelementptr inbounds %"int[]", ptr %97, i64 0 + store %"int[]" %95, ptr %ptroffset43, align 8 + store %"char[]" { ptr @.str.4, i64 2 }, ptr %taddr45, align 8 + %98 = getelementptr inbounds { ptr, i64 }, ptr %taddr45, i32 0, i32 0 + %lo46 = load ptr, ptr %98, align 8 + %99 = getelementptr inbounds { ptr, i64 }, ptr %taddr45, i32 0, i32 1 + %hi47 = load i64, ptr %99, align 8 + %100 = insertvalue %variant undef, ptr %a, 0 + %101 = insertvalue %variant %100, i64 ptrtoint (ptr @"ct$sa$sa$int" to i64), 1 + %102 = getelementptr inbounds [1 x %variant], ptr %varargslots49, i64 0, i64 0 + store %variant %101, ptr %102, align 16 + %103 = getelementptr inbounds %"variant[]", ptr %vararg48, i32 0, i32 1 + store i64 1, ptr %103, align 8 + %104 = getelementptr inbounds %"variant[]", ptr %vararg48, i32 0, i32 0 + store ptr %varargslots49, ptr %104, align 8 + %105 = getelementptr inbounds { ptr, i64 }, ptr %vararg48, i32 0, i32 0 + %lo50 = load ptr, ptr %105, align 8 + %106 = getelementptr inbounds { ptr, i64 }, ptr %vararg48, i32 0, i32 1 + %hi51 = load i64, ptr %106, align 8 + %107 = call i64 @std_io_printfln(ptr %retparam44, ptr %lo46, i64 %hi47, ptr %lo50, i64 %hi51) + %not_err52 = icmp eq i64 %107, 0 + br i1 %not_err52, label %after_check53, label %voiderr54 + +after_check53: ; preds = %voiderr42 + br label %voiderr54 + +voiderr54: ; preds = %after_check53, %voiderr42 + ret void +}