From a0a2e271276682b6a4e95f28c8a89b644c051fe9 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Thu, 8 Sep 2022 20:51:32 +0200 Subject: [PATCH] $vasplat() implemented. $vacount removed (). Improved dynscope implementation. Version bump to 0.3.37. --- resources/examples/contextfree/dynscope.c3 | 34 +- src/compiler/ast.c | 10 +- src/compiler/compiler_internal.h | 27 +- src/compiler/copying.c | 31 +- src/compiler/enums.h | 2 + src/compiler/llvm_codegen_expr.c | 36 +- src/compiler/parse_expr.c | 110 +-- src/compiler/parse_global.c | 2 +- src/compiler/parse_stmt.c | 1 + src/compiler/parser_internal.h | 3 +- src/compiler/sema_casts.c | 2 + src/compiler/sema_expr.c | 272 +++++- src/compiler/sema_stmts.c | 2 +- src/compiler/tokens.c | 2 + src/version.h | 2 +- .../macros/macro_untyped_varargs_2.c3t | 6 +- test/test_suite/macros/macro_vasplat.c3t | 789 ++++++++++++++++++ .../macros/macro_untyped_varargs_2.c3t | 6 +- test/test_suite2/macros/macro_vasplat.c3t | 777 +++++++++++++++++ 19 files changed, 1964 insertions(+), 150 deletions(-) create mode 100644 test/test_suite/macros/macro_vasplat.c3t create mode 100644 test/test_suite2/macros/macro_vasplat.c3t diff --git a/resources/examples/contextfree/dynscope.c3 b/resources/examples/contextfree/dynscope.c3 index c12ed9931..f5ce2174e 100644 --- a/resources/examples/contextfree/dynscope.c3 +++ b/resources/examples/contextfree/dynscope.c3 @@ -3,26 +3,30 @@ import std::io; tlocal char[] context_user = "safe"; -macro long perform(task) +macro long reallyPerform(task) { - io::printf("%s: %s\n", context_user, task); - return task.len; + io::printfln("%s: %s", context_user, task); + return task.len; } -macro @with_mode(char[] user, #action, arg) +macro long perform(task) { - @scope(context_user) - { - context_user = user; - return #action(arg); - }; + return reallyPerform(task); +} + +macro @with_mode(char[] user, #action, ...) +{ + @scope(context_user) + { + context_user = user; + return #action($vasplat()); + }; } fn void main() { - long result = perform("something!"); - result += @with_mode("faster", perform, "reliable"); - result += perform(char[][] {"again", "more"}); - result += perform(int[<2>] { 56, 99 }); - io::printf("Result: %d\n", result); -} \ No newline at end of file + long val1 = perform("something"); + long val2 = @with_mode("faster", perform, "reliable"); + long val3 = perform(char[][] {"something"}); + io::printfln("%d %d %d", val1, val2, val3); +} diff --git a/src/compiler/ast.c b/src/compiler/ast.c index 601d827c9..84a04f1f2 100644 --- a/src/compiler/ast.c +++ b/src/compiler/ast.c @@ -290,6 +290,8 @@ bool expr_is_pure(Expr *expr) case EXPR_TYPEID: case EXPR_CT_ARG: return true; + case EXPR_VASPLAT: + return true; case EXPR_ARGV_TO_SUBARRAY: case EXPR_BITASSIGN: return false; @@ -354,13 +356,13 @@ bool expr_is_pure(Expr *expr) case EXPR_TYPEID_INFO: return exprid_is_pure(expr->typeid_info_expr.parent); case EXPR_SLICE: - return exprid_is_pure(expr->slice_expr.expr) - && exprid_is_pure(expr->slice_expr.start) - && exprid_is_pure(expr->slice_expr.end); + return exprid_is_pure(expr->subscript_expr.expr) + && exprid_is_pure(expr->subscript_expr.range.start) + && exprid_is_pure(expr->subscript_expr.range.end); case EXPR_SUBSCRIPT: case EXPR_SUBSCRIPT_ADDR: return exprid_is_pure(expr->subscript_expr.expr) - && exprid_is_pure(expr->subscript_expr.index); + && exprid_is_pure(expr->subscript_expr.range.start); case EXPR_TERNARY: return exprid_is_pure(expr->ternary_expr.cond) && exprid_is_pure(expr->ternary_expr.else_expr) diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 8aeb5a664..1239c7be3 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -708,7 +708,15 @@ typedef struct Decl_ - +typedef struct +{ + bool start_from_end : 1; + bool end_from_end : 1; + bool is_len : 1; + bool is_range : 1; + ExprId start; + ExprId end; +} Range; typedef struct { @@ -763,21 +771,10 @@ typedef struct typedef struct { - bool from_back : 1; ExprId expr; - ExprId index; + Range range; } ExprSubscript; -typedef struct -{ - bool start_from_back : 1; - bool end_from_back : 1; - bool is_lenrange : 1; - ExprId expr; - ExprId start; - ExprId end; -} ExprSlice; - typedef struct { ExprId left; @@ -955,7 +952,7 @@ typedef struct { Expr **values; Decl **declarations; - Ast *ast; + AstId first_stmt; } ExprBodyExpansion; @@ -1090,6 +1087,7 @@ struct Expr_ ExprKind expr_kind : 8; ResolveStatus resolve_status : 4; union { + Range vasplat_expr; ExprTypeidInfo typeid_info_expr; ExprVariantSwitch variant_switch; // 32 ExprCast cast_expr; // 12 @@ -1108,7 +1106,6 @@ struct Expr_ Expr** try_unwrap_chain_expr; // 8 ExprTryUnwrap try_unwrap_expr; // 24 ExprCall call_expr; // 32 - ExprSlice slice_expr; // 16 Expr *inner_expr; // 8 ExprBuiltinAccess builtin_access_expr; ExprCatchUnwrap catch_unwrap_expr; // 24 diff --git a/src/compiler/copying.c b/src/compiler/copying.c index cb8a341b0..c466e7883 100644 --- a/src/compiler/copying.c +++ b/src/compiler/copying.c @@ -169,21 +169,34 @@ Expr *expr_macro_copy(Expr *source_expr) return copy_expr(©_struct, source_expr); } +void copy_range(CopyStruct *c, Range *range) +{ + MACRO_COPY_EXPRID(range->start); + MACRO_COPY_EXPRID(range->end); +} + Expr *copy_expr(CopyStruct *c, Expr *source_expr) { if (!source_expr) return NULL; Expr *expr = expr_copy(source_expr); switch (source_expr->expr_kind) { - case EXPR_MACRO_BODY_EXPANSION: case EXPR_VARIANTSWITCH: case EXPR_ARGV_TO_SUBARRAY: UNREACHABLE + case EXPR_MACRO_BODY_EXPANSION: + MACRO_COPY_EXPR_LIST(expr->body_expansion_expr.values); + MACRO_COPY_DECL_LIST(expr->body_expansion_expr.declarations); + MACRO_COPY_ASTID(expr->body_expansion_expr.first_stmt); + return expr; case EXPR_FLATPATH: case EXPR_NOP: case EXPR_BUILTIN: case EXPR_RETVAL: return expr; + case EXPR_VASPLAT: + copy_range(c, &expr->vasplat_expr); + return expr; case EXPR_CT_ARG: MACRO_COPY_EXPRID(expr->ct_arg_expr.arg); return expr; @@ -243,9 +256,10 @@ Expr *copy_expr(CopyStruct *c, Expr *source_expr) MACRO_COPY_EXPRID(expr->slice_assign_expr.right); return expr; case EXPR_SLICE: - MACRO_COPY_EXPRID(expr->slice_expr.expr); - MACRO_COPY_EXPRID(expr->slice_expr.start); - MACRO_COPY_EXPRID(expr->slice_expr.end); + case EXPR_SUBSCRIPT: + case EXPR_SUBSCRIPT_ADDR: + MACRO_COPY_EXPRID(expr->subscript_expr.expr); + copy_range(c, &expr->subscript_expr.range); return expr; case EXPR_ASM: switch (expr->expr_asm_arg.kind) @@ -278,7 +292,9 @@ Expr *copy_expr(CopyStruct *c, Expr *source_expr) MACRO_COPY_EXPR_LIST(expr->cond_expr); return expr; case EXPR_MACRO_BLOCK: - UNREACHABLE + MACRO_COPY_DECL_LIST(expr->macro_block.params); + MACRO_COPY_ASTID(expr->macro_block.first_stmt); + return expr; case EXPR_COMPOUND_LITERAL: MACRO_COPY_EXPR(expr->expr_compound_literal.initializer); MACRO_COPY_TYPE(expr->expr_compound_literal.type_info); @@ -335,11 +351,6 @@ Expr *copy_expr(CopyStruct *c, Expr *source_expr) } } return expr; - case EXPR_SUBSCRIPT: - case EXPR_SUBSCRIPT_ADDR: - MACRO_COPY_EXPRID(expr->subscript_expr.expr); - MACRO_COPY_EXPRID(expr->subscript_expr.index); - return expr; case EXPR_BITACCESS: case EXPR_ACCESS: MACRO_COPY_EXPR(expr->access_expr.parent); diff --git a/src/compiler/enums.h b/src/compiler/enums.h index 84e74e36f..16e75c564 100644 --- a/src/compiler/enums.h +++ b/src/compiler/enums.h @@ -247,6 +247,7 @@ typedef enum EXPR_TYPEINFO, EXPR_UNARY, EXPR_VARIANTSWITCH, + EXPR_VASPLAT, EXPR_NOP, EXPR_TYPEID_INFO, EXPR_VARIANT, @@ -566,6 +567,7 @@ typedef enum TOKEN_CT_VAREF, // $varef, TOKEN_CT_VAARG, // $vaarg, TOKEN_CT_VAEXPR, // $vaexpr, + TOKEN_CT_VASPLAT, // $vasplat, TOKEN_DOCS_START, // /** TOKEN_DOCS_END, // */ (may start with an arbitrary number of `*` TOKEN_DOC_DIRECTIVE, // Any doc directive diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index 089b8f31b..58eab842a 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -512,10 +512,10 @@ static inline void llvm_emit_vector_subscript(GenContext *c, BEValue *value, Exp assert(vec->type_kind == TYPE_VECTOR); Type *element = vec->array.base; LLVMValueRef vector = value->value; - llvm_emit_exprid(c, value, expr->subscript_expr.index); + llvm_emit_exprid(c, value, expr->subscript_expr.range.start); llvm_value_rvalue(c, value); LLVMValueRef index = value->value; - if (expr->subscript_expr.from_back) + if (expr->subscript_expr.range.start_from_end) { index = LLVMBuildNUWSub(c->builder, llvm_const_int(c, value->type, vec->array.len), index, ""); } @@ -531,7 +531,7 @@ static inline void gencontext_emit_subscript(GenContext *c, BEValue *value, Expr { bool is_value = expr->expr_kind == EXPR_SUBSCRIPT; Expr *parent_expr = exprptr(expr->subscript_expr.expr); - Expr *index_expr = exprptr(expr->subscript_expr.index); + Expr *index_expr = exprptr(expr->subscript_expr.range.start); Type *parent_type = type_lowering(parent_expr->type); if (is_value && parent_type->type_kind == TYPE_VECTOR) { @@ -548,13 +548,13 @@ static inline void gencontext_emit_subscript(GenContext *c, BEValue *value, Expr bool needs_len = false; if (parent_type_kind == TYPE_SUBARRAY) { - needs_len = active_target.feature.safe_mode || expr->subscript_expr.from_back; + needs_len = active_target.feature.safe_mode || expr->subscript_expr.range.start_from_end; } else if (parent_type_kind == TYPE_ARRAY) { // From back should always be folded. - assert(expr->expr_kind != EXPR_CONST || !expr->subscript_expr.from_back); - needs_len = (active_target.feature.safe_mode && expr->expr_kind != EXPR_CONST) || expr->subscript_expr.from_back; + assert(expr->expr_kind != EXPR_CONST || !expr->subscript_expr.range.start_from_end); + needs_len = (active_target.feature.safe_mode && expr->expr_kind != EXPR_CONST) || expr->subscript_expr.range.start_from_end; } if (needs_len) { @@ -570,7 +570,7 @@ static inline void gencontext_emit_subscript(GenContext *c, BEValue *value, Expr // It needs to be an rvalue. llvm_value_rvalue(c, &index); - if (expr->subscript_expr.from_back) + if (expr->subscript_expr.range.start_from_end) { assert(needs_len); index.value = LLVMBuildNUWSub(c->builder, llvm_zext_trunc(c, len.value, llvm_get_type(c, index.type)), index.value, ""); @@ -2250,9 +2250,9 @@ static void llvm_emit_slice_values(GenContext *c, Expr *slice, BEValue *parent_r { assert(slice->expr_kind == EXPR_SLICE); - Expr *parent_expr = exprptr(slice->slice_expr.expr); - Expr *start = exprptr(slice->slice_expr.start); - Expr *end = exprptrzero(slice->slice_expr.end); + Expr *parent_expr = exprptr(slice->subscript_expr.expr); + Expr *start = exprptr(slice->subscript_expr.range.start); + Expr *end = exprptrzero(slice->subscript_expr.range.end); Type *parent_type = type_flatten_distinct(parent_expr->type); BEValue parent_addr_x; @@ -2288,7 +2288,9 @@ static void llvm_emit_slice_values(GenContext *c, Expr *slice, BEValue *parent_r BEValue len = { .value = NULL }; bool check_end = true; - if (!end || slice->slice_expr.start_from_back || slice->slice_expr.end_from_back || active_target.feature.safe_mode) + bool start_from_end = slice->subscript_expr.range.start_from_end; + bool end_from_end = slice->subscript_expr.range.end_from_end; + if (!end || start_from_end || end_from_end || active_target.feature.safe_mode) { switch (parent_type->type_kind) { @@ -2310,7 +2312,7 @@ static void llvm_emit_slice_values(GenContext *c, Expr *slice, BEValue *parent_r } // Walk from end if it is slice from the back. - if (slice->slice_expr.start_from_back) + if (start_from_end) { start_index.value = llvm_emit_sub_int(c, start_type, len.value, start_index.value, slice->span); } @@ -2332,7 +2334,7 @@ static void llvm_emit_slice_values(GenContext *c, Expr *slice, BEValue *parent_r Type *end_type; BEValue end_index; - bool is_len_range = *is_exclusive = slice->slice_expr.is_lenrange; + bool is_len_range = *is_exclusive = slice->subscript_expr.range.is_len; if (end) { // Get the index. @@ -2341,7 +2343,7 @@ static void llvm_emit_slice_values(GenContext *c, Expr *slice, BEValue *parent_r end_type = end->type->canonical; // Reverse if it is "from back" - if (slice->slice_expr.end_from_back) + if (end_from_end) { end_index.value = llvm_emit_sub_int(c, end_type, len.value, end_index.value, slice->span); llvm_value_rvalue(c, &end_index); @@ -3541,7 +3543,7 @@ static void llvm_emit_vector_assign_expr(GenContext *c, BEValue *be_value, Expr LLVMValueRef vector_value = llvm_load_value_store(c, &addr); // Emit the index - llvm_emit_exprid(c, &index, left->subscript_expr.index); + llvm_emit_exprid(c, &index, left->subscript_expr.range.start); LLVMValueRef index_val = llvm_load_value_store(c, &index); if (binary_op > BINARYOP_ASSIGN) @@ -5431,7 +5433,8 @@ static void llvm_emit_macro_body_expansion(GenContext *c, BEValue *value, Expr * llvm_emit_expr(c, value, expr); llvm_store_to_ptr_aligned(c, declarations[i]->backend_ref, value, declarations[i]->alignment); } - llvm_emit_stmt(c, body_expr->body_expansion_expr.ast); + AstId body = body_expr->body_expansion_expr.first_stmt; + if (body) llvm_emit_stmt(c, astptr(body)); } void llvm_emit_try_unwrap(GenContext *c, BEValue *value, Expr *expr) @@ -5886,6 +5889,7 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr) case EXPR_CT_CONV: case EXPR_CT_ARG: case EXPR_ASM: + case EXPR_VASPLAT: UNREACHABLE case EXPR_BUILTIN_ACCESS: llvm_emit_builtin_access(c, value, expr); diff --git a/src/compiler/parse_expr.c b/src/compiler/parse_expr.c index 992f76ea7..bb3487c49 100644 --- a/src/compiler/parse_expr.c +++ b/src/compiler/parse_expr.c @@ -19,6 +19,41 @@ typedef struct extern ParseRule rules[TOKEN_EOF + 1]; +bool parse_range(ParseContext *c, Range *range) +{ + // Not range with missing entry + if (tok_is(c, TOKEN_DOTDOT) || tok_is(c, TOKEN_COLON)) + { + // ..123 and :123 + range->start_from_end = false; + range->start = exprid(expr_new_const_int(c->span, type_uint, 0, true)); + } + else + { + // Might be ^ prefix + range->start_from_end = try_consume(c, TOKEN_BIT_XOR); + ASSIGN_EXPRID_OR_RET(range->start, parse_expr(c), false); + } + bool is_len_range = range->is_len = try_consume(c, TOKEN_COLON); + if (!is_len_range && !try_consume(c, TOKEN_DOTDOT)) + { + range->is_range = false; + return true; + } + range->is_range = true; + // ] ) are the possible ways to end a range. + if (tok_is(c, TOKEN_RBRACKET) || tok_is(c, TOKEN_RPAREN)) + { + // So here we have [1..] or [3:] + range->end_from_end = false; + range->end = 0; + return true; + } + range->end_from_end = try_consume(c, TOKEN_BIT_XOR); + ASSIGN_EXPRID_OR_RET(range->end, parse_expr(c), false); + return true; +} + inline Expr *parse_precedence_with_left_side(ParseContext *c, Expr *left_side, Precedence precedence) { while (1) @@ -236,6 +271,7 @@ Expr *parse_cond(ParseContext *c) return decl_expr; } + // These used to be explicitly inlined, but that seems to lead to confusing MSVC linker errors. // They are probably still inlined by the compiler, though I haven't checked. Expr* parse_expr(ParseContext *c) @@ -293,12 +329,26 @@ static bool parse_param_path(ParseContext *c, DesignatorElement ***path) return true; } } + +Expr *parse_vasplat(ParseContext *c) +{ + Expr *expr = EXPR_NEW_TOKEN(EXPR_VASPLAT); + advance_and_verify(c, TOKEN_CT_VASPLAT); + TRY_CONSUME_OR_RET(TOKEN_LPAREN, "'$vasplat' must be followed by '()'.", poisoned_expr); + if (!try_consume(c, TOKEN_RPAREN)) + { + if (!parse_range(c, &expr->vasplat_expr)) return poisoned_expr; + CONSUME_OR_RET(TOKEN_RPAREN, poisoned_expr); + } + RANGE_EXTEND_PREV(expr); + return expr; +} /** * param_list ::= ('...' parameter | parameter (',' parameter)*)? * * parameter ::= (param_path '=')? expr */ -bool parse_arg_list(ParseContext *c, Expr ***result, TokenType param_end, bool *splat) +bool parse_arg_list(ParseContext *c, Expr ***result, TokenType param_end, bool *splat, bool vasplat) { *result = NULL; if (splat) *splat = false; @@ -322,6 +372,10 @@ bool parse_arg_list(ParseContext *c, Expr ***result, TokenType param_end, bool * RANGE_EXTEND_PREV(expr); } + else if (vasplat && tok_is(c, TOKEN_CT_VASPLAT)) + { + ASSIGN_EXPR_OR_RET(expr, parse_vasplat(c), false); + } else { if (splat) @@ -573,7 +627,7 @@ Expr *parse_initializer_list(ParseContext *c, Expr *left) if (!try_consume(c, TOKEN_RBRACE)) { Expr **exprs = NULL; - if (!parse_arg_list(c, &exprs, TOKEN_RBRACE, NULL)) return poisoned_expr; + if (!parse_arg_list(c, &exprs, TOKEN_RBRACE, NULL, true)) return poisoned_expr; int designated = -1; VECEACH(exprs, i) { @@ -663,7 +717,7 @@ static Expr *parse_call_expr(ParseContext *c, Expr *left) { // Pick a modest guess. params = VECNEW(Expr*, 4); - if (!parse_arg_list(c, ¶ms, TOKEN_RPAREN, &splat)) return poisoned_expr; + if (!parse_arg_list(c, ¶ms, TOKEN_RPAREN, &splat, true)) return poisoned_expr; } if (try_consume(c, TOKEN_EOS) && !tok_is(c, TOKEN_RPAREN)) { @@ -750,52 +804,14 @@ static Expr *parse_subscript_expr(ParseContext *c, Expr *left) advance_and_verify(c, TOKEN_LBRACKET); Expr *subs_expr = expr_new_expr(EXPR_SUBSCRIPT, left); - Expr *index = NULL; - bool is_range = false; - bool from_back = false; - bool end_from_back = false; - Expr *end = NULL; - - // Not range with missing entry - if (!tok_is(c, TOKEN_DOTDOT) && !tok_is(c, TOKEN_COLON)) - { - // Might be ^ prefix - from_back = try_consume(c, TOKEN_BIT_XOR); - ASSIGN_EXPR_OR_RET(index, parse_expr(c), poisoned_expr); - } - else - { - index = expr_new_const_int(c->span, type_uint, 0, true); - } - bool is_len_range = try_consume(c, TOKEN_COLON); - if (is_len_range || try_consume(c, TOKEN_DOTDOT)) - { - is_range = true; - if (!tok_is(c, TOKEN_RBRACKET)) - { - end_from_back = try_consume(c, TOKEN_BIT_XOR); - ASSIGN_EXPR_OR_RET(end, parse_expr(c), poisoned_expr); - } - } + subs_expr->subscript_expr.expr = exprid(left); + if (!parse_range(c, &subs_expr->subscript_expr.range)) return poisoned_expr; CONSUME_OR_RET(TOKEN_RBRACKET, poisoned_expr); - RANGE_EXTEND_PREV(subs_expr); - - if (is_range) + if (subs_expr->subscript_expr.range.is_range) { subs_expr->expr_kind = EXPR_SLICE; - subs_expr->slice_expr.expr = exprid(left); - subs_expr->slice_expr.start = exprid(index); - subs_expr->slice_expr.start_from_back = from_back; - subs_expr->slice_expr.end = end ? exprid(end) : 0; - subs_expr->slice_expr.end_from_back = end_from_back; - subs_expr->slice_expr.is_lenrange = is_len_range; - } - else - { - subs_expr->subscript_expr.expr = exprid(left); - subs_expr->subscript_expr.index = exprid(index); - subs_expr->subscript_expr.from_back = from_back; } + RANGE_EXTEND_PREV(subs_expr); return subs_expr; } @@ -920,12 +936,12 @@ static Expr *parse_ct_arg(ParseContext *c, Expr *left) TokenType type = expr->ct_arg_expr.type = c->tok; assert(type != TOKEN_CT_VATYPE); advance(c); - CONSUME_OR_RET(TOKEN_LPAREN, poisoned_expr); if (type != TOKEN_CT_VACOUNT) { + CONSUME_OR_RET(TOKEN_LPAREN, poisoned_expr); ASSIGN_EXPRID_OR_RET(expr->ct_arg_expr.arg, parse_expr(c), poisoned_expr); + CONSUME_OR_RET(TOKEN_RPAREN, poisoned_expr); } - CONSUME_OR_RET(TOKEN_RPAREN, poisoned_expr); RANGE_EXTEND_PREV(expr); return expr; } diff --git a/src/compiler/parse_global.c b/src/compiler/parse_global.c index 33a41c052..08f1cda39 100644 --- a/src/compiler/parse_global.c +++ b/src/compiler/parse_global.c @@ -2034,7 +2034,7 @@ static inline Decl *parse_enum_declaration(ParseContext *c, Visibility visibilit if (try_consume(c, TOKEN_LPAREN)) { Expr **result = NULL; - if (!parse_arg_list(c, &result, TOKEN_RPAREN, NULL)) return poisoned_decl; + if (!parse_arg_list(c, &result, TOKEN_RPAREN, NULL, false)) return poisoned_decl; enum_const->enum_constant.args = result; CONSUME_OR_RET(TOKEN_RPAREN, poisoned_decl); } diff --git a/src/compiler/parse_stmt.c b/src/compiler/parse_stmt.c index d53c2e83c..4284bcf99 100644 --- a/src/compiler/parse_stmt.c +++ b/src/compiler/parse_stmt.c @@ -1290,6 +1290,7 @@ Ast *parse_stmt(ParseContext *c) case TOKEN_CT_ENDFOREACH: case TOKEN_CT_CASTABLE: case TOKEN_CT_CONVERTIBLE: + case TOKEN_CT_VASPLAT: SEMA_ERROR_HERE("Unexpected '%s' found when expecting a statement.", token_type_to_string(c->tok)); advance(c); diff --git a/src/compiler/parser_internal.h b/src/compiler/parser_internal.h index 23c890c8a..dc48c4a49 100644 --- a/src/compiler/parser_internal.h +++ b/src/compiler/parser_internal.h @@ -48,7 +48,8 @@ Decl *parse_var_decl(ParseContext *c); bool parse_parameters(ParseContext *c, Visibility visibility, Decl ***params_ref, Decl **body_params, Variadic *variadic, int *vararg_index_ref); -bool parse_arg_list(ParseContext *c, Expr ***result, TokenType param_end, bool *splat); + +bool parse_arg_list(ParseContext *c, Expr ***result, TokenType param_end, bool *splat, bool vasplat); Expr *parse_type_compound_literal_expr_after_type(ParseContext *c, TypeInfo *type_info); bool parse_module(ParseContext *c); diff --git a/src/compiler/sema_casts.c b/src/compiler/sema_casts.c index a25cb0627..4216f4764 100644 --- a/src/compiler/sema_casts.c +++ b/src/compiler/sema_casts.c @@ -834,6 +834,7 @@ Expr *recursive_may_narrow_float(Expr *expr, Type *type) case EXPR_POINTER_OFFSET: case EXPR_CT_ARG: case EXPR_ASM: + case EXPR_VASPLAT: UNREACHABLE case EXPR_BUILTIN_ACCESS: @@ -1003,6 +1004,7 @@ Expr *recursive_may_narrow_int(Expr *expr, Type *type) case EXPR_POINTER_OFFSET: case EXPR_CT_ARG: case EXPR_ASM: + case EXPR_VASPLAT: UNREACHABLE case EXPR_POST_UNARY: return recursive_may_narrow_int(expr->unary_expr.expr, type); diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 14ac5c36b..9a0481902 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -21,6 +21,7 @@ static bool sema_check_stmt_compile_time(SemaContext *context, Ast *ast); static bool binary_arithmetic_promotion(SemaContext *context, Expr *left, Expr *right, Type *left_type, Type *right_type, Expr *parent, const char *error_message); static inline bool expr_both_const(Expr *left, Expr *right); static inline bool sema_expr_index_const_list(Expr *const_list, Expr *index, Expr *result); +static Expr **sema_expand_vasplat_exprs(SemaContext *c, Expr **exprs); static bool sema_decay_array_pointers(Expr *expr) { @@ -361,6 +362,7 @@ bool expr_is_constant_eval(Expr *expr, ConstantEvalKind eval_kind) return false; case EXPR_BUILTIN: case EXPR_CT_EVAL: + case EXPR_VASPLAT: return false; case EXPR_BITACCESS: case EXPR_ACCESS: @@ -447,11 +449,11 @@ bool expr_is_constant_eval(Expr *expr, ConstantEvalKind eval_kind) if (expr->slice_expr.end && !exprid_is_constant_eval(expr->slice_expr.end, CONSTANT_EVAL_FOLDABLE)) return false; return exprid_is_constant_eval(expr->slice_expr.expr, eval_kind);*/ case EXPR_SUBSCRIPT: - if (!exprid_is_constant_eval(expr->subscript_expr.index, eval_kind)) return false; + if (!exprid_is_constant_eval(expr->subscript_expr.range.start, eval_kind)) return false; expr = exprptr(expr->subscript_expr.expr); goto RETRY; case EXPR_SUBSCRIPT_ADDR: - if (!exprid_is_constant_eval(expr->subscript_expr.index, eval_kind)) return false; + if (!exprid_is_constant_eval(expr->subscript_expr.range.start, eval_kind)) return false; expr = exprptr(expr->subscript_expr.expr); if (expr->expr_kind == EXPR_IDENTIFIER) { @@ -709,6 +711,7 @@ static bool sema_check_expr_lvalue(Expr *top_expr, Expr *expr) case EXPR_POINTER_OFFSET: case EXPR_CT_ARG: case EXPR_ASM: + case EXPR_VASPLAT: goto ERR; } UNREACHABLE @@ -809,6 +812,7 @@ bool expr_may_addr(Expr *expr) case EXPR_POINTER_OFFSET: case EXPR_CT_ARG: case EXPR_ASM: + case EXPR_VASPLAT: return false; } UNREACHABLE @@ -1141,7 +1145,7 @@ static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to, if (expr->identifier_expr.ident == declptr(body_param)->name) { expr->expr_kind = EXPR_MACRO_BODY_EXPANSION; - expr->body_expansion_expr.ast = NULL; + expr->body_expansion_expr.first_stmt = 0; expr->body_expansion_expr.declarations = NULL; expr->resolve_status = RESOLVE_NOT_DONE; expr->type = type_void; @@ -1611,24 +1615,31 @@ INLINE bool sema_expand_call_arguments(SemaContext *context, CalledDecl *callee, } // 17c. Vararg not set? That's fine. - if (params[i]->var.vararg) continue; + if (param->var.vararg) continue; // 17d. Argument missing, that's bad. - if (!has_named || !params[i]->name) + if (!has_named || !param->name) { if (func_param_count == 1) { - SEMA_ERROR(call, "This call expected a parameter of type %s, did you forget it?", type_quoted_error_string(params[i]->type)); + if (param->type) + { + SEMA_ERROR(call, "This call expected a parameter of type %s, did you forget it?", type_quoted_error_string(param->type)); + } + else + { + SEMA_ERROR(call, "This call expected a parameter, did you forget it?"); + } return false; } if (variadic != VARIADIC_NONE && i > vararg_index) { - if (!param[i].name) + if (!param) { sema_error_at_after(args[num_args - 1]->span, "Argument #%d is not set.", i); return false; } - sema_error_at_after(args[num_args - 1]->span, "Expected '.%s = ...' after this argument.", params[i]->name); + sema_error_at_after(args[num_args - 1]->span, "Expected '.%s = ...' after this argument.", param->name); return false; } if (num_args) @@ -1644,7 +1655,7 @@ INLINE bool sema_expand_call_arguments(SemaContext *context, CalledDecl *callee, } return false; } - SEMA_ERROR(call, "The parameter '%s' must be set, did you forget it?", params[i]->name); + SEMA_ERROR(call, "The parameter '%s' must be set, did you forget it?", param->name); return false; } call->call_expr.arguments = actual_args; @@ -1662,6 +1673,9 @@ static inline bool sema_expr_analyse_call_invocation(SemaContext *context, Expr unsigned vararg_index = sig->vararg_index; Variadic variadic = sig->variadic; Decl **decl_params = callee.params; + + if (args) args = call->call_expr.arguments = sema_expand_vasplat_exprs(context, args); + unsigned num_args = vec_size(args); // 3. If this is a type call, then we have an implicit first argument. @@ -2401,7 +2415,8 @@ static bool sema_analyse_body_expansion(SemaContext *macro_context, Expr *call) Decl *param = params[i]; if (!sema_add_local(context, param)) return SCOPE_POP_ERROR(); } - Ast *ast = call->body_expansion_expr.ast = ast_macro_copy(macro_context->yield_body); + Ast *ast = ast_macro_copy(macro_context->yield_body); + call->body_expansion_expr.first_stmt = astid(ast); if (!sema_analyse_statement(context, ast)) return SCOPE_POP_ERROR(); assert(ast->ast_kind == AST_COMPOUND_STMT); if (context->active_scope.jump_end) @@ -3041,7 +3056,7 @@ static inline bool sema_expr_analyse_subscript(SemaContext *context, Expr *expr, sema_deref_array_pointers(subscripted); // 2. Evaluate the index. - Expr *index = exprptr(expr->subscript_expr.index); + Expr *index = exprptr(expr->subscript_expr.range.start); if (!sema_analyse_expr(context, index)) return false; // 3. Check failability due to value. @@ -3053,6 +3068,7 @@ static inline bool sema_expr_analyse_subscript(SemaContext *context, Expr *expr, Expr *current_expr = subscripted; int64_t index_value = -1; + bool start_from_end = expr->subscript_expr.range.start_from_end; if (expr_is_const_int(index) && (current_type->type_kind == TYPE_ARRAY || current_type == type_complist)) { // 4c. And that it's in range. @@ -3069,13 +3085,13 @@ static inline bool sema_expr_analyse_subscript(SemaContext *context, Expr *expr, return false; } index_value = int_to_i64(index->const_expr.ixx); - if (expr->subscript_expr.from_back) + if (start_from_end) { index_value = size - index_value; } if (index_value < 0 || index_value >= size) { - if (expr->subscript_expr.from_back) + if (start_from_end) { SEMA_ERROR(index, size > 1 @@ -3156,8 +3172,11 @@ static inline bool sema_expr_analyse_subscript(SemaContext *context, Expr *expr, // Check range bool remove_from_back = false; - if (!expr_check_index_in_range(context, current_type, index, false, expr->subscript_expr.from_back, &remove_from_back)) return false; - if (remove_from_back) expr->subscript_expr.from_back = false; + if (!expr_check_index_in_range(context, current_type, index, false, start_from_end, &remove_from_back)) return false; + if (remove_from_back) + { + start_from_end = expr->subscript_expr.range.start_from_end = false; + } if (is_addr) { @@ -3209,13 +3228,13 @@ static inline bool sema_expr_analyse_pointer_offset(SemaContext *context, Expr * static inline bool sema_expr_analyse_slice(SemaContext *context, Expr *expr) { assert(expr->expr_kind == EXPR_SLICE); - Expr *subscripted = exprptr(expr->slice_expr.expr); + Expr *subscripted = exprptr(expr->subscript_expr.expr); if (!sema_analyse_expr(context, subscripted)) return false; bool failable = IS_OPTIONAL(subscripted); Type *type = type_flatten(subscripted->type); Type *original_type = type_no_optional(subscripted->type); - Expr *start = exprptr(expr->slice_expr.start); - Expr *end = exprptrzero(expr->slice_expr.end); + Expr *start = exprptr(expr->subscript_expr.range.start); + Expr *end = exprptrzero(expr->subscript_expr.range.end); Expr *current_expr = subscripted; @@ -3225,7 +3244,7 @@ static inline bool sema_expr_analyse_slice(SemaContext *context, Expr *expr) SEMA_ERROR(subscripted, "Cannot index '%s'.", type_to_error_string(subscripted->type)); return false; } - expr->slice_expr.expr = exprid(current_expr); + expr->subscript_expr.expr = exprid(current_expr); if (!sema_analyse_expr(context, start)) return false; if (end && !sema_analyse_expr(context, end)) return false; @@ -3239,10 +3258,13 @@ static inline bool sema_expr_analyse_slice(SemaContext *context, Expr *expr) if (!common || !cast_implicit(start, common) || !cast_implicit(end, common)) return false; } + bool start_from_end = expr->subscript_expr.range.start_from_end; + bool end_from_end = expr->subscript_expr.range.end_from_end; + // Check range if (type->type_kind == TYPE_POINTER) { - if (expr->slice_expr.start_from_back) + if (start_from_end) { SEMA_ERROR(start, "Indexing from the end is not allowed for pointers."); return false; @@ -3252,33 +3274,39 @@ static inline bool sema_expr_analyse_slice(SemaContext *context, Expr *expr) SEMA_ERROR(expr, "Omitting end index is not allowed for pointers."); return false; } - if (end && expr->slice_expr.end_from_back) + if (end && end_from_end) { SEMA_ERROR(end, "Indexing from the end is not allowed for pointers."); return false; } } - bool is_lenrange = expr->slice_expr.is_lenrange; + bool is_lenrange = expr->subscript_expr.range.is_len; bool remove_from_end = false; - if (!expr_check_index_in_range(context, type, start, false, expr->slice_expr.start_from_back, &remove_from_end)) return false; - if (remove_from_end) expr->slice_expr.start_from_back = false; + if (!expr_check_index_in_range(context, type, start, false, start_from_end, &remove_from_end)) return false; + if (remove_from_end) + { + start_from_end = expr->subscript_expr.range.start_from_end = false; + } remove_from_end = false; if (end) { if (is_lenrange) { - if (!expr_check_len_in_range(context, type, end, expr->slice_expr.end_from_back, &remove_from_end)) return false; + if (!expr_check_len_in_range(context, type, end, end_from_end, &remove_from_end)) return false; } else { - if (!expr_check_index_in_range(context, type, end, true, expr->slice_expr.end_from_back, &remove_from_end)) return false; + if (!expr_check_index_in_range(context, type, end, true, end_from_end, &remove_from_end)) return false; } } - if (remove_from_end) expr->slice_expr.end_from_back = false; + if (remove_from_end) + { + end_from_end = expr->subscript_expr.range.end_from_end = false; + } if (start && end && start->expr_kind == EXPR_CONST && end->expr_kind == EXPR_CONST) { - if (!is_lenrange && expr->slice_expr.start_from_back && expr->slice_expr.end_from_back) + if (!is_lenrange && start_from_end && end_from_end) { if (expr_const_compare(&start->const_expr, &end->const_expr, BINARYOP_LT)) { @@ -3286,7 +3314,7 @@ static inline bool sema_expr_analyse_slice(SemaContext *context, Expr *expr) return false; } } - else if (!is_lenrange && !expr->slice_expr.start_from_back && !expr->slice_expr.end_from_back) + else if (!is_lenrange && !start_from_end && !end_from_end) { if (expr_const_compare(&start->const_expr, &end->const_expr, BINARYOP_GT)) { @@ -3297,12 +3325,12 @@ static inline bool sema_expr_analyse_slice(SemaContext *context, Expr *expr) // If both are if (type->type_kind == TYPE_ARRAY || type->type_kind == TYPE_VECTOR) { - assert(!expr->slice_expr.start_from_back); - assert(!expr->slice_expr.end_from_back); + assert(!start_from_end); + assert(!end_from_end); if (!is_lenrange) { end->const_expr.ixx = int_sub(int_add64(end->const_expr.ixx, 1), start->const_expr.ixx); - is_lenrange = expr->slice_expr.is_lenrange = true; + is_lenrange = expr->subscript_expr.range.is_len = true; } } } @@ -4936,6 +4964,175 @@ static inline bool sema_expr_analyse_untyped_initializer(SemaContext *context, E return true; } +static Expr **vasplat_append(SemaContext *c, Expr **init_expressions, Expr *expr) +{ + Expr **args = c->macro_varargs; + unsigned param_count = vec_size(args); + Range *range = &expr->vasplat_expr; + Expr *start = exprptrzero(range->start); + unsigned start_idx = 0; + if (start) + { + if (!range->is_range) + { + SEMA_ERROR(expr, "$vasplat() expected a range."); + return NULL; + } + if (!sema_analyse_expr(c, start)) return NULL; + if (!expr_is_const_int(start)) + { + SEMA_ERROR(expr, "Expected a constant integer."); + return NULL; + } + Int start_index = start->const_expr.ixx; + if (int_is_neg(start_index)) + { + SEMA_ERROR(expr, "Expected a positive integer."); + return NULL; + } + if (int_bits_needed(start_index) > 31) + { + SEMA_ERROR(expr, "Start index is too big."); + return NULL; + } + start_idx = start_index.i.low; + if (range->start_from_end) + { + start_idx = param_count - start_idx; + } + if (param_count < start_idx) + { + SEMA_ERROR(expr, "Start index exceeds the number of parameters (%d).", start_idx); + return NULL; + } + } + Expr *end = exprptrzero(range->end); + unsigned end_idx = param_count; + if (end) + { + if (!sema_analyse_expr(c, end)) return NULL; + if (!expr_is_const_int(end)) + { + SEMA_ERROR(expr, "Expected a constant integer."); + return NULL; + } + Int end_index = end->const_expr.ixx; + if (int_is_neg(end_index)) + { + SEMA_ERROR(expr, "Expected a positive integer."); + return NULL; + } + if (int_bits_needed(end_index) > 31) + { + if (range->is_len) + { + SEMA_ERROR(expr, "End index is too large."); + } + else + { + SEMA_ERROR(expr, "Length is too large."); + } + return NULL; + } + end_idx = end_index.i.low; + if (range->end_from_end) + { + if (end_idx > param_count) + { + end_idx = 0; + } + else + { + end_idx = param_count - end_idx; + } + } + if (range->is_len) + { + end_idx = start_idx + end_idx; + } + else + { + end_idx++; + } + if (param_count <= end_idx) + { + SEMA_ERROR(expr, "End index would exceed the number of parameters."); + return NULL; + } + } + for (unsigned i = start_idx; i < end_idx; i++) + { + vec_add(init_expressions, args[i]); + } + return init_expressions; +} + + +INLINE Expr **sema_expand_vasplat(SemaContext *c, Expr **list, unsigned index) +{ + unsigned size = vec_size(list); + + // If it was the last element then just append. + if (index == size - 1) + { + vec_pop(list); + return vasplat_append(c, list, list[index]); + } + // Otherwise append to the end. + list = vasplat_append(c, list, list[index]); + if (!list) return NULL; + unsigned new_size = vec_size(list); + unsigned added_elements = new_size - size; + + if (added_elements == 0) + { + for (unsigned i = index + 1; i < size; i++) + { + list[i - 1] = list[i]; + } + vec_pop(list); + return list; + } + + // Copy those elements + for (unsigned i = 0; i < added_elements; i++) + { + unsigned dest = index + i; + unsigned source = size + i; + // Copy the next element to the index position. + list[dest] = list[source]; + // Copy the following into the place of the index. + list[source] = list[dest + 1]; + } + vec_pop(list); + return list; +} + +static Expr **sema_expand_vasplat_exprs(SemaContext *c, Expr **exprs) +{ + if (!c->current_macro) return exprs; + + unsigned count = vec_size(exprs); + bool expand; + do + { + expand = false; + for (unsigned i = 0; i < count; i++) + { + if (exprs[i]->expr_kind == EXPR_VASPLAT) + { + exprs = sema_expand_vasplat(c, exprs, i); + // If we have null back it failed. + if (!exprs) return NULL; + count = vec_size(exprs); + expand = true; + break; + } + } + } while (expand); + return exprs; +} + static inline bool sema_expr_analyse_initializer(SemaContext *context, Type *external_type, Type *assigned, Expr *expr) { // Note at this point this we either have @@ -4953,6 +5150,11 @@ static inline bool sema_expr_analyse_initializer(SemaContext *context, Type *ext // 2. Grab the expressions inside. Expr **init_expressions = expr->initializer_list; + + if (init_expressions) + { + expr->initializer_list = init_expressions = sema_expand_vasplat_exprs(context, init_expressions); + } unsigned init_expression_count = vec_size(init_expressions); // 3. Zero size init will initialize to empty. @@ -4972,6 +5174,7 @@ static inline bool sema_expr_analyse_initializer(SemaContext *context, Type *ext return true; } + // 4. If we have an inferred array, we need to set the size. external_type = sema_type_lower_by_size(external_type, init_expression_count); assigned = sema_type_lower_by_size(assigned, init_expression_count); @@ -7904,6 +8107,9 @@ static inline bool sema_analyse_expr_dispatch(SemaContext *context, Expr *expr) case EXPR_TYPEID_INFO: case EXPR_ASM: UNREACHABLE + case EXPR_VASPLAT: + SEMA_ERROR(expr, "'$vasplat' can only be used inside of macros."); + return false; case EXPR_CT_ARG: return sema_expr_analyse_ct_arg(context, expr); case EXPR_VARIANT: @@ -8063,7 +8269,7 @@ static inline bool sema_cast_rvalue(SemaContext *context, Expr *expr) switch (expr->expr_kind) { case EXPR_MACRO_BODY_EXPANSION: - if (!expr->body_expansion_expr.ast) + if (!expr->body_expansion_expr.first_stmt) { SEMA_ERROR(expr, "'@%s' must be followed by ().", declptr(context->current_macro->func_decl.body_param)->name); return false; diff --git a/src/compiler/sema_stmts.c b/src/compiler/sema_stmts.c index 737bbe6aa..1652e6f17 100644 --- a/src/compiler/sema_stmts.c +++ b/src/compiler/sema_stmts.c @@ -1218,7 +1218,7 @@ static inline bool sema_analyse_foreach_stmt(SemaContext *context, Ast *statemen enum_val = expr_variable(temp); if (is_addr) expr_insert_deref(enum_val); subscript->subscript_expr.expr = exprid(enum_val); - subscript->subscript_expr.index = exprid(expr_variable(idx_decl)); + subscript->subscript_expr.range.start = exprid(expr_variable(idx_decl)); if (value_by_ref) { Expr *addr = expr_new(EXPR_UNARY, subscript->span); diff --git a/src/compiler/tokens.c b/src/compiler/tokens.c index 460362969..01814b94b 100644 --- a/src/compiler/tokens.c +++ b/src/compiler/tokens.c @@ -368,6 +368,8 @@ const char *token_type_to_string(TokenType type) return "$varef"; case TOKEN_CT_VAEXPR: return "$vaexpr"; + case TOKEN_CT_VASPLAT: + return "$vasplat"; case TOKEN_CT_NAMEOF: return "$nameof"; case TOKEN_CT_OFFSETOF: diff --git a/src/version.h b/src/version.h index ca1b07e16..c143df3e1 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define COMPILER_VERSION "0.3.36" \ No newline at end of file +#define COMPILER_VERSION "0.3.37" \ No newline at end of file diff --git a/test/test_suite/macros/macro_untyped_varargs_2.c3t b/test/test_suite/macros/macro_untyped_varargs_2.c3t index dbd0feffa..dc10ed84e 100644 --- a/test/test_suite/macros/macro_untyped_varargs_2.c3t +++ b/test/test_suite/macros/macro_untyped_varargs_2.c3t @@ -8,14 +8,14 @@ macro @foo(...) { int i = $vaarg(1) + $vaarg(1); int j = $vaexpr(2) + $vaexpr(2); - $for (var $i = 0; $i < $vacount(); $i++): + $for (var $i = 0; $i < $vacount; $i++): io::printfln("%d", $vaarg($i)); $endfor; } macro foo2(...) { - $for (var $i = 0; $i < $vacount(); $i++): + $for (var $i = 0; $i < $vacount; $i++): { $vatype($i) x; } @@ -26,7 +26,7 @@ macro foo2(...) macro foo3(...) { var $x = 0; - $for (var $i = 0; $i < $vacount(); $i++): + $for (var $i = 0; $i < $vacount; $i++): $x += $vaconst($i); $endfor; return $x; diff --git a/test/test_suite/macros/macro_vasplat.c3t b/test/test_suite/macros/macro_vasplat.c3t new file mode 100644 index 000000000..a3eb1268c --- /dev/null +++ b/test/test_suite/macros/macro_vasplat.c3t @@ -0,0 +1,789 @@ +// #target: macos-x64 +module test; +import std::io; + +macro @hello(...) +{ + int[*] a = { 1, $vasplat(), 3 }; + foreach (i, x : a) io::printfln("%d: %d", i, x); +} + +macro @hello1(...) +{ + int[*] a = { 1, $vasplat() }; + foreach (i, x : a) io::printfln("x:%d: %d", i, x); +} + +macro @hello2(...) +{ + int[*] a = { $vasplat(), 888 }; + foreach (i, x : a) io::printfln("x:%d: %d", i, x); +} + +macro @hello3(...) +{ + int[*] a = { $vasplat() }; + foreach (i, x : a) io::printfln("x:%d: %d", i, x); +} + +macro @hello4(...) +{ + int[*] a = { 5, $vasplat(2..4), 77 }; + foreach (i, x : a) io::printfln("y:%d: %d", i, x); +} + +macro @hello5(...) +{ + int[*] a = { 5, $vasplat(2..), 77 }; + foreach (i, x : a) io::printfln("y:%d: %d", i, x); + int[*] b = { 55, $vasplat(2..^2), 88 }; + foreach (i, x : b) io::printfln("z:%d: %d", i, x); + int[*] c = { 55, $vasplat(0:^2), 88 }; + foreach (i, x : c) io::printfln("zz:%d: %d", i, x); +} + +macro @hello6(...) +{ + @hello(66, $vasplat()); +} +fn void main() +{ + @hello1(223, 326); + @hello1(); + @hello(26, 36); + @hello(); + @hello2(2123, 3326); + @hello2(); + @hello3(2123, 3326); + @hello4(1, 2, 3, 4, 5, 6, 7, 8); + @hello5(1, 2, 3, 4, 5, 6, 7, 8); + @hello6(1, 2, 3); +} + +/* #expect: test.ll + +define void @test_main() #0 { +entry: + %a = alloca [3 x i32], align 4 + %.anon = alloca i64, align 8 + %i = alloca i64, align 8 + %x = alloca i32, align 4 + %retparam = alloca i64, align 8 + %taddr = alloca %"char[]", align 8 + %vararg = alloca %"variant[]", align 8 + %varargslots = alloca [2 x %variant], align 16 + %a3 = alloca [1 x i32], align 4 + %.anon4 = alloca i64, align 8 + %i8 = alloca i64, align 8 + %x9 = alloca i32, align 4 + %retparam10 = alloca i64, align 8 + %taddr11 = alloca %"char[]", align 8 + %vararg14 = alloca %"variant[]", align 8 + %varargslots15 = alloca [2 x %variant], align 16 + %a23 = alloca [4 x i32], align 16 + %.anon24 = alloca i64, align 8 + %i28 = alloca i64, align 8 + %x29 = alloca i32, align 4 + %retparam30 = alloca i64, align 8 + %taddr31 = alloca %"char[]", align 8 + %vararg34 = alloca %"variant[]", align 8 + %varargslots35 = alloca [2 x %variant], align 16 + %a43 = alloca [2 x i32], align 4 + %.anon44 = alloca i64, align 8 + %i48 = alloca i64, align 8 + %x49 = alloca i32, align 4 + %retparam50 = alloca i64, align 8 + %taddr51 = alloca %"char[]", align 8 + %vararg54 = alloca %"variant[]", align 8 + %varargslots55 = alloca [2 x %variant], align 16 + %a63 = alloca [3 x i32], align 4 + %.anon64 = alloca i64, align 8 + %i68 = alloca i64, align 8 + %x69 = alloca i32, align 4 + %retparam70 = alloca i64, align 8 + %taddr71 = alloca %"char[]", align 8 + %vararg74 = alloca %"variant[]", align 8 + %varargslots75 = alloca [2 x %variant], align 16 + %a83 = alloca [1 x i32], align 4 + %.anon84 = alloca i64, align 8 + %i88 = alloca i64, align 8 + %x89 = alloca i32, align 4 + %retparam90 = alloca i64, align 8 + %taddr91 = alloca %"char[]", align 8 + %vararg94 = alloca %"variant[]", align 8 + %varargslots95 = alloca [2 x %variant], align 16 + %a103 = alloca [2 x i32], align 4 + %.anon104 = alloca i64, align 8 + %i108 = alloca i64, align 8 + %x109 = alloca i32, align 4 + %retparam110 = alloca i64, align 8 + %taddr111 = alloca %"char[]", align 8 + %vararg114 = alloca %"variant[]", align 8 + %varargslots115 = alloca [2 x %variant], align 16 + %a123 = alloca [5 x i32], align 16 + %.anon124 = alloca i64, align 8 + %i128 = alloca i64, align 8 + %x129 = alloca i32, align 4 + %retparam130 = alloca i64, align 8 + %taddr131 = alloca %"char[]", align 8 + %vararg134 = alloca %"variant[]", align 8 + %varargslots135 = alloca [2 x %variant], align 16 + %a143 = alloca [8 x i32], align 16 + %.anon144 = alloca i64, align 8 + %i148 = alloca i64, align 8 + %x149 = alloca i32, align 4 + %retparam150 = alloca i64, align 8 + %taddr151 = alloca %"char[]", align 8 + %vararg154 = alloca %"variant[]", align 8 + %varargslots155 = alloca [2 x %variant], align 16 + %b = alloca [7 x i32], align 16 + %.anon163 = alloca i64, align 8 + %i167 = alloca i64, align 8 + %x168 = alloca i32, align 4 + %retparam169 = alloca i64, align 8 + %taddr170 = alloca %"char[]", align 8 + %vararg173 = alloca %"variant[]", align 8 + %varargslots174 = alloca [2 x %variant], align 16 + %c = alloca [8 x i32], align 16 + %.anon182 = alloca i64, align 8 + %i186 = alloca i64, align 8 + %x187 = alloca i32, align 4 + %retparam188 = alloca i64, align 8 + %taddr189 = alloca %"char[]", align 8 + %vararg192 = alloca %"variant[]", align 8 + %varargslots193 = alloca [2 x %variant], align 16 + %a201 = alloca [6 x i32], align 16 + %.anon202 = alloca i64, align 8 + %i206 = alloca i64, align 8 + %x207 = alloca i32, align 4 + %retparam208 = alloca i64, align 8 + %taddr209 = alloca %"char[]", align 8 + %vararg212 = alloca %"variant[]", align 8 + %varargslots213 = alloca [2 x %variant], align 16 + %0 = bitcast [3 x i32]* %a to i8* + call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %0, i8* align 4 bitcast ([3 x i32]* @.__const to i8*), i32 12, i1 false) + store i64 0, i64* %.anon, align 8 + br label %loop.cond +loop.cond: ; preds = %voiderr, %entry + %1 = load i64, i64* %.anon, align 8 + %gt = icmp ugt i64 3, %1 + br i1 %gt, label %loop.body, label %loop.exit +loop.body: ; preds = %loop.cond + %2 = load i64, i64* %.anon, align 8 + store i64 %2, i64* %i, align 8 + %3 = load i64, i64* %.anon, align 8 + %4 = getelementptr inbounds [3 x i32], [3 x i32]* %a, i64 0, i64 %3 + %5 = load i32, i32* %4, align 4 + store i32 %5, i32* %x, align 4 + store %"char[]" { i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str, i32 0, i32 0), i64 8 }, %"char[]"* %taddr, align 8 + %6 = bitcast %"char[]"* %taddr to { i8*, i64 }* + %7 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %6, i32 0, i32 0 + %lo = load i8*, i8** %7, align 8 + %8 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %6, i32 0, i32 1 + %hi = load i64, i64* %8, align 8 + %9 = bitcast i64* %i to i8* + %10 = insertvalue %variant undef, i8* %9, 0 + %11 = insertvalue %variant %10, i64 ptrtoint (%.introspect* @"ct$ulong" to i64), 1 + %12 = getelementptr inbounds [2 x %variant], [2 x %variant]* %varargslots, i64 0, i64 0 + store %variant %11, %variant* %12, align 16 + %13 = bitcast i32* %x to i8* + %14 = insertvalue %variant undef, i8* %13, 0 + %15 = insertvalue %variant %14, i64 ptrtoint (%.introspect* @"ct$int" to i64), 1 + %16 = getelementptr inbounds [2 x %variant], [2 x %variant]* %varargslots, i64 0, i64 1 + store %variant %15, %variant* %16, align 16 + %17 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg, i32 0, i32 1 + store i64 2, i64* %17, align 8 + %18 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg, i32 0, i32 0 + %19 = bitcast [2 x %variant]* %varargslots to %variant* + store %variant* %19, %variant** %18, align 8 + %20 = bitcast %"variant[]"* %vararg to { i8*, i64 }* + %21 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %20, i32 0, i32 0 + %lo1 = load i8*, i8** %21, align 8 + %22 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %20, i32 0, i32 1 + %hi2 = load i64, i64* %22, align 8 + %23 = call i64 @std_io_printfln(i64* %retparam, i8* %lo, i64 %hi, i8* %lo1, i64 %hi2) + %not_err = icmp eq i64 %23, 0 + br i1 %not_err, label %after_check, label %voiderr +after_check: ; preds = %loop.body + br label %voiderr +voiderr: ; preds = %after_check, %loop.body + %24 = load i64, i64* %.anon, align 8 + %add = add i64 %24, 1 + store i64 %add, i64* %.anon, align 8 + br label %loop.cond +loop.exit: ; preds = %loop.cond + %25 = bitcast [1 x i32]* %a3 to i8* + call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %25, i8* align 4 bitcast ([1 x i32]* @.__const.1 to i8*), i32 4, i1 false) + store i64 0, i64* %.anon4, align 8 + br label %loop.cond5 +loop.cond5: ; preds = %voiderr20, %loop.exit + %26 = load i64, i64* %.anon4, align 8 + %gt6 = icmp ugt i64 1, %26 + br i1 %gt6, label %loop.body7, label %loop.exit22 +loop.body7: ; preds = %loop.cond5 + %27 = load i64, i64* %.anon4, align 8 + store i64 %27, i64* %i8, align 8 + %28 = load i64, i64* %.anon4, align 8 + %29 = getelementptr inbounds [1 x i32], [1 x i32]* %a3, i64 0, i64 %28 + %30 = load i32, i32* %29, align 4 + store i32 %30, i32* %x9, align 4 + store %"char[]" { i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.2, i32 0, i32 0), i64 8 }, %"char[]"* %taddr11, align 8 + %31 = bitcast %"char[]"* %taddr11 to { i8*, i64 }* + %32 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %31, i32 0, i32 0 + %lo12 = load i8*, i8** %32, align 8 + %33 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %31, i32 0, i32 1 + %hi13 = load i64, i64* %33, align 8 + %34 = bitcast i64* %i8 to i8* + %35 = insertvalue %variant undef, i8* %34, 0 + %36 = insertvalue %variant %35, i64 ptrtoint (%.introspect* @"ct$ulong" to i64), 1 + %37 = getelementptr inbounds [2 x %variant], [2 x %variant]* %varargslots15, i64 0, i64 0 + store %variant %36, %variant* %37, align 16 + %38 = bitcast i32* %x9 to i8* + %39 = insertvalue %variant undef, i8* %38, 0 + %40 = insertvalue %variant %39, i64 ptrtoint (%.introspect* @"ct$int" to i64), 1 + %41 = getelementptr inbounds [2 x %variant], [2 x %variant]* %varargslots15, i64 0, i64 1 + store %variant %40, %variant* %41, align 16 + %42 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg14, i32 0, i32 1 + store i64 2, i64* %42, align 8 + %43 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg14, i32 0, i32 0 + %44 = bitcast [2 x %variant]* %varargslots15 to %variant* + store %variant* %44, %variant** %43, align 8 + %45 = bitcast %"variant[]"* %vararg14 to { i8*, i64 }* + %46 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %45, i32 0, i32 0 + %lo16 = load i8*, i8** %46, align 8 + %47 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %45, i32 0, i32 1 + %hi17 = load i64, i64* %47, align 8 + %48 = call i64 @std_io_printfln(i64* %retparam10, i8* %lo12, i64 %hi13, i8* %lo16, i64 %hi17) + %not_err18 = icmp eq i64 %48, 0 + br i1 %not_err18, label %after_check19, label %voiderr20 +after_check19: ; preds = %loop.body7 + br label %voiderr20 +voiderr20: ; preds = %after_check19, %loop.body7 + %49 = load i64, i64* %.anon4, align 8 + %add21 = add i64 %49, 1 + store i64 %add21, i64* %.anon4, align 8 + br label %loop.cond5 +loop.exit22: ; preds = %loop.cond5 + %50 = bitcast [4 x i32]* %a23 to i8* + call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 %50, i8* align 16 bitcast ([4 x i32]* @.__const.3 to i8*), i32 16, i1 false) + store i64 0, i64* %.anon24, align 8 + br label %loop.cond25 +loop.cond25: ; preds = %voiderr40, %loop.exit22 + %51 = load i64, i64* %.anon24, align 8 + %gt26 = icmp ugt i64 4, %51 + br i1 %gt26, label %loop.body27, label %loop.exit42 +loop.body27: ; preds = %loop.cond25 + %52 = load i64, i64* %.anon24, align 8 + store i64 %52, i64* %i28, align 8 + %53 = load i64, i64* %.anon24, align 8 + %54 = getelementptr inbounds [4 x i32], [4 x i32]* %a23, i64 0, i64 %53 + %55 = load i32, i32* %54, align 4 + store i32 %55, i32* %x29, align 4 + store %"char[]" { i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.4, i32 0, i32 0), i64 6 }, %"char[]"* %taddr31, align 8 + %56 = bitcast %"char[]"* %taddr31 to { i8*, i64 }* + %57 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %56, i32 0, i32 0 + %lo32 = load i8*, i8** %57, align 8 + %58 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %56, i32 0, i32 1 + %hi33 = load i64, i64* %58, align 8 + %59 = bitcast i64* %i28 to i8* + %60 = insertvalue %variant undef, i8* %59, 0 + %61 = insertvalue %variant %60, i64 ptrtoint (%.introspect* @"ct$ulong" to i64), 1 + %62 = getelementptr inbounds [2 x %variant], [2 x %variant]* %varargslots35, i64 0, i64 0 + store %variant %61, %variant* %62, align 16 + %63 = bitcast i32* %x29 to i8* + %64 = insertvalue %variant undef, i8* %63, 0 + %65 = insertvalue %variant %64, i64 ptrtoint (%.introspect* @"ct$int" to i64), 1 + %66 = getelementptr inbounds [2 x %variant], [2 x %variant]* %varargslots35, i64 0, i64 1 + store %variant %65, %variant* %66, align 16 + %67 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg34, i32 0, i32 1 + store i64 2, i64* %67, align 8 + %68 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg34, i32 0, i32 0 + %69 = bitcast [2 x %variant]* %varargslots35 to %variant* + store %variant* %69, %variant** %68, align 8 + %70 = bitcast %"variant[]"* %vararg34 to { i8*, i64 }* + %71 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %70, i32 0, i32 0 + %lo36 = load i8*, i8** %71, align 8 + %72 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %70, i32 0, i32 1 + %hi37 = load i64, i64* %72, align 8 + %73 = call i64 @std_io_printfln(i64* %retparam30, i8* %lo32, i64 %hi33, i8* %lo36, i64 %hi37) + %not_err38 = icmp eq i64 %73, 0 + br i1 %not_err38, label %after_check39, label %voiderr40 +after_check39: ; preds = %loop.body27 + br label %voiderr40 +voiderr40: ; preds = %after_check39, %loop.body27 + %74 = load i64, i64* %.anon24, align 8 + %add41 = add i64 %74, 1 + store i64 %add41, i64* %.anon24, align 8 + br label %loop.cond25 +loop.exit42: ; preds = %loop.cond25 + %75 = bitcast [2 x i32]* %a43 to i8* + call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %75, i8* align 4 bitcast ([2 x i32]* @.__const.5 to i8*), i32 8, i1 false) + store i64 0, i64* %.anon44, align 8 + br label %loop.cond45 +loop.cond45: ; preds = %voiderr60, %loop.exit42 + %76 = load i64, i64* %.anon44, align 8 + %gt46 = icmp ugt i64 2, %76 + br i1 %gt46, label %loop.body47, label %loop.exit62 +loop.body47: ; preds = %loop.cond45 + %77 = load i64, i64* %.anon44, align 8 + store i64 %77, i64* %i48, align 8 + %78 = load i64, i64* %.anon44, align 8 + %79 = getelementptr inbounds [2 x i32], [2 x i32]* %a43, i64 0, i64 %78 + %80 = load i32, i32* %79, align 4 + store i32 %80, i32* %x49, align 4 + store %"char[]" { i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.6, i32 0, i32 0), i64 6 }, %"char[]"* %taddr51, align 8 + %81 = bitcast %"char[]"* %taddr51 to { i8*, i64 }* + %82 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %81, i32 0, i32 0 + %lo52 = load i8*, i8** %82, align 8 + %83 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %81, i32 0, i32 1 + %hi53 = load i64, i64* %83, align 8 + %84 = bitcast i64* %i48 to i8* + %85 = insertvalue %variant undef, i8* %84, 0 + %86 = insertvalue %variant %85, i64 ptrtoint (%.introspect* @"ct$ulong" to i64), 1 + %87 = getelementptr inbounds [2 x %variant], [2 x %variant]* %varargslots55, i64 0, i64 0 + store %variant %86, %variant* %87, align 16 + %88 = bitcast i32* %x49 to i8* + %89 = insertvalue %variant undef, i8* %88, 0 + %90 = insertvalue %variant %89, i64 ptrtoint (%.introspect* @"ct$int" to i64), 1 + %91 = getelementptr inbounds [2 x %variant], [2 x %variant]* %varargslots55, i64 0, i64 1 + store %variant %90, %variant* %91, align 16 + %92 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg54, i32 0, i32 1 + store i64 2, i64* %92, align 8 + %93 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg54, i32 0, i32 0 + %94 = bitcast [2 x %variant]* %varargslots55 to %variant* + store %variant* %94, %variant** %93, align 8 + %95 = bitcast %"variant[]"* %vararg54 to { i8*, i64 }* + %96 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %95, i32 0, i32 0 + %lo56 = load i8*, i8** %96, align 8 + %97 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %95, i32 0, i32 1 + %hi57 = load i64, i64* %97, align 8 + %98 = call i64 @std_io_printfln(i64* %retparam50, i8* %lo52, i64 %hi53, i8* %lo56, i64 %hi57) + %not_err58 = icmp eq i64 %98, 0 + br i1 %not_err58, label %after_check59, label %voiderr60 +after_check59: ; preds = %loop.body47 + br label %voiderr60 +voiderr60: ; preds = %after_check59, %loop.body47 + %99 = load i64, i64* %.anon44, align 8 + %add61 = add i64 %99, 1 + store i64 %add61, i64* %.anon44, align 8 + br label %loop.cond45 +loop.exit62: ; preds = %loop.cond45 + %100 = bitcast [3 x i32]* %a63 to i8* + call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %100, i8* align 4 bitcast ([3 x i32]* @.__const.7 to i8*), i32 12, i1 false) + store i64 0, i64* %.anon64, align 8 + br label %loop.cond65 +loop.cond65: ; preds = %voiderr80, %loop.exit62 + %101 = load i64, i64* %.anon64, align 8 + %gt66 = icmp ugt i64 3, %101 + br i1 %gt66, label %loop.body67, label %loop.exit82 +loop.body67: ; preds = %loop.cond65 + %102 = load i64, i64* %.anon64, align 8 + store i64 %102, i64* %i68, align 8 + %103 = load i64, i64* %.anon64, align 8 + %104 = getelementptr inbounds [3 x i32], [3 x i32]* %a63, i64 0, i64 %103 + %105 = load i32, i32* %104, align 4 + store i32 %105, i32* %x69, align 4 + store %"char[]" { i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.8, i32 0, i32 0), i64 8 }, %"char[]"* %taddr71, align 8 + %106 = bitcast %"char[]"* %taddr71 to { i8*, i64 }* + %107 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %106, i32 0, i32 0 + %lo72 = load i8*, i8** %107, align 8 + %108 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %106, i32 0, i32 1 + %hi73 = load i64, i64* %108, align 8 + %109 = bitcast i64* %i68 to i8* + %110 = insertvalue %variant undef, i8* %109, 0 + %111 = insertvalue %variant %110, i64 ptrtoint (%.introspect* @"ct$ulong" to i64), 1 + %112 = getelementptr inbounds [2 x %variant], [2 x %variant]* %varargslots75, i64 0, i64 0 + store %variant %111, %variant* %112, align 16 + %113 = bitcast i32* %x69 to i8* + %114 = insertvalue %variant undef, i8* %113, 0 + %115 = insertvalue %variant %114, i64 ptrtoint (%.introspect* @"ct$int" to i64), 1 + %116 = getelementptr inbounds [2 x %variant], [2 x %variant]* %varargslots75, i64 0, i64 1 + store %variant %115, %variant* %116, align 16 + %117 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg74, i32 0, i32 1 + store i64 2, i64* %117, align 8 + %118 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg74, i32 0, i32 0 + %119 = bitcast [2 x %variant]* %varargslots75 to %variant* + store %variant* %119, %variant** %118, align 8 + %120 = bitcast %"variant[]"* %vararg74 to { i8*, i64 }* + %121 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %120, i32 0, i32 0 + %lo76 = load i8*, i8** %121, align 8 + %122 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %120, i32 0, i32 1 + %hi77 = load i64, i64* %122, align 8 + %123 = call i64 @std_io_printfln(i64* %retparam70, i8* %lo72, i64 %hi73, i8* %lo76, i64 %hi77) + %not_err78 = icmp eq i64 %123, 0 + br i1 %not_err78, label %after_check79, label %voiderr80 +after_check79: ; preds = %loop.body67 + br label %voiderr80 +voiderr80: ; preds = %after_check79, %loop.body67 + %124 = load i64, i64* %.anon64, align 8 + %add81 = add i64 %124, 1 + store i64 %add81, i64* %.anon64, align 8 + br label %loop.cond65 +loop.exit82: ; preds = %loop.cond65 + %125 = bitcast [1 x i32]* %a83 to i8* + call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %125, i8* align 4 bitcast ([1 x i32]* @.__const.9 to i8*), i32 4, i1 false) + store i64 0, i64* %.anon84, align 8 + br label %loop.cond85 +loop.cond85: ; preds = %voiderr100, %loop.exit82 + %126 = load i64, i64* %.anon84, align 8 + %gt86 = icmp ugt i64 1, %126 + br i1 %gt86, label %loop.body87, label %loop.exit102 +loop.body87: ; preds = %loop.cond85 + %127 = load i64, i64* %.anon84, align 8 + store i64 %127, i64* %i88, align 8 + %128 = load i64, i64* %.anon84, align 8 + %129 = getelementptr inbounds [1 x i32], [1 x i32]* %a83, i64 0, i64 %128 + %130 = load i32, i32* %129, align 4 + store i32 %130, i32* %x89, align 4 + store %"char[]" { i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.10, i32 0, i32 0), i64 8 }, %"char[]"* %taddr91, align 8 + %131 = bitcast %"char[]"* %taddr91 to { i8*, i64 }* + %132 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %131, i32 0, i32 0 + %lo92 = load i8*, i8** %132, align 8 + %133 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %131, i32 0, i32 1 + %hi93 = load i64, i64* %133, align 8 + %134 = bitcast i64* %i88 to i8* + %135 = insertvalue %variant undef, i8* %134, 0 + %136 = insertvalue %variant %135, i64 ptrtoint (%.introspect* @"ct$ulong" to i64), 1 + %137 = getelementptr inbounds [2 x %variant], [2 x %variant]* %varargslots95, i64 0, i64 0 + store %variant %136, %variant* %137, align 16 + %138 = bitcast i32* %x89 to i8* + %139 = insertvalue %variant undef, i8* %138, 0 + %140 = insertvalue %variant %139, i64 ptrtoint (%.introspect* @"ct$int" to i64), 1 + %141 = getelementptr inbounds [2 x %variant], [2 x %variant]* %varargslots95, i64 0, i64 1 + store %variant %140, %variant* %141, align 16 + %142 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg94, i32 0, i32 1 + store i64 2, i64* %142, align 8 + %143 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg94, i32 0, i32 0 + %144 = bitcast [2 x %variant]* %varargslots95 to %variant* + store %variant* %144, %variant** %143, align 8 + %145 = bitcast %"variant[]"* %vararg94 to { i8*, i64 }* + %146 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %145, i32 0, i32 0 + %lo96 = load i8*, i8** %146, align 8 + %147 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %145, i32 0, i32 1 + %hi97 = load i64, i64* %147, align 8 + %148 = call i64 @std_io_printfln(i64* %retparam90, i8* %lo92, i64 %hi93, i8* %lo96, i64 %hi97) + %not_err98 = icmp eq i64 %148, 0 + br i1 %not_err98, label %after_check99, label %voiderr100 +after_check99: ; preds = %loop.body87 + br label %voiderr100 +voiderr100: ; preds = %after_check99, %loop.body87 + %149 = load i64, i64* %.anon84, align 8 + %add101 = add i64 %149, 1 + store i64 %add101, i64* %.anon84, align 8 + br label %loop.cond85 +loop.exit102: ; preds = %loop.cond85 + %150 = bitcast [2 x i32]* %a103 to i8* + call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %150, i8* align 4 bitcast ([2 x i32]* @.__const.11 to i8*), i32 8, i1 false) + store i64 0, i64* %.anon104, align 8 + br label %loop.cond105 +loop.cond105: ; preds = %voiderr120, %loop.exit102 + %151 = load i64, i64* %.anon104, align 8 + %gt106 = icmp ugt i64 2, %151 + br i1 %gt106, label %loop.body107, label %loop.exit122 +loop.body107: ; preds = %loop.cond105 + %152 = load i64, i64* %.anon104, align 8 + store i64 %152, i64* %i108, align 8 + %153 = load i64, i64* %.anon104, align 8 + %154 = getelementptr inbounds [2 x i32], [2 x i32]* %a103, i64 0, i64 %153 + %155 = load i32, i32* %154, align 4 + store i32 %155, i32* %x109, align 4 + store %"char[]" { i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.12, i32 0, i32 0), i64 8 }, %"char[]"* %taddr111, align 8 + %156 = bitcast %"char[]"* %taddr111 to { i8*, i64 }* + %157 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %156, i32 0, i32 0 + %lo112 = load i8*, i8** %157, align 8 + %158 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %156, i32 0, i32 1 + %hi113 = load i64, i64* %158, align 8 + %159 = bitcast i64* %i108 to i8* + %160 = insertvalue %variant undef, i8* %159, 0 + %161 = insertvalue %variant %160, i64 ptrtoint (%.introspect* @"ct$ulong" to i64), 1 + %162 = getelementptr inbounds [2 x %variant], [2 x %variant]* %varargslots115, i64 0, i64 0 + store %variant %161, %variant* %162, align 16 + %163 = bitcast i32* %x109 to i8* + %164 = insertvalue %variant undef, i8* %163, 0 + %165 = insertvalue %variant %164, i64 ptrtoint (%.introspect* @"ct$int" to i64), 1 + %166 = getelementptr inbounds [2 x %variant], [2 x %variant]* %varargslots115, i64 0, i64 1 + store %variant %165, %variant* %166, align 16 + %167 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg114, i32 0, i32 1 + store i64 2, i64* %167, align 8 + %168 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg114, i32 0, i32 0 + %169 = bitcast [2 x %variant]* %varargslots115 to %variant* + store %variant* %169, %variant** %168, align 8 + %170 = bitcast %"variant[]"* %vararg114 to { i8*, i64 }* + %171 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %170, i32 0, i32 0 + %lo116 = load i8*, i8** %171, align 8 + %172 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %170, i32 0, i32 1 + %hi117 = load i64, i64* %172, align 8 + %173 = call i64 @std_io_printfln(i64* %retparam110, i8* %lo112, i64 %hi113, i8* %lo116, i64 %hi117) + %not_err118 = icmp eq i64 %173, 0 + br i1 %not_err118, label %after_check119, label %voiderr120 +after_check119: ; preds = %loop.body107 + br label %voiderr120 +voiderr120: ; preds = %after_check119, %loop.body107 + %174 = load i64, i64* %.anon104, align 8 + %add121 = add i64 %174, 1 + store i64 %add121, i64* %.anon104, align 8 + br label %loop.cond105 +loop.exit122: ; preds = %loop.cond105 + %175 = bitcast [5 x i32]* %a123 to i8* + call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 %175, i8* align 16 bitcast ([5 x i32]* @.__const.13 to i8*), i32 20, i1 false) + store i64 0, i64* %.anon124, align 8 + br label %loop.cond125 +loop.cond125: ; preds = %voiderr140, %loop.exit122 + %176 = load i64, i64* %.anon124, align 8 + %gt126 = icmp ugt i64 5, %176 + br i1 %gt126, label %loop.body127, label %loop.exit142 +loop.body127: ; preds = %loop.cond125 + %177 = load i64, i64* %.anon124, align 8 + store i64 %177, i64* %i128, align 8 + %178 = load i64, i64* %.anon124, align 8 + %179 = getelementptr inbounds [5 x i32], [5 x i32]* %a123, i64 0, i64 %178 + %180 = load i32, i32* %179, align 4 + store i32 %180, i32* %x129, align 4 + store %"char[]" { i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.14, i32 0, i32 0), i64 8 }, %"char[]"* %taddr131, align 8 + %181 = bitcast %"char[]"* %taddr131 to { i8*, i64 }* + %182 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %181, i32 0, i32 0 + %lo132 = load i8*, i8** %182, align 8 + %183 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %181, i32 0, i32 1 + %hi133 = load i64, i64* %183, align 8 + %184 = bitcast i64* %i128 to i8* + %185 = insertvalue %variant undef, i8* %184, 0 + %186 = insertvalue %variant %185, i64 ptrtoint (%.introspect* @"ct$ulong" to i64), 1 + %187 = getelementptr inbounds [2 x %variant], [2 x %variant]* %varargslots135, i64 0, i64 0 + store %variant %186, %variant* %187, align 16 + %188 = bitcast i32* %x129 to i8* + %189 = insertvalue %variant undef, i8* %188, 0 + %190 = insertvalue %variant %189, i64 ptrtoint (%.introspect* @"ct$int" to i64), 1 + %191 = getelementptr inbounds [2 x %variant], [2 x %variant]* %varargslots135, i64 0, i64 1 + store %variant %190, %variant* %191, align 16 + %192 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg134, i32 0, i32 1 + store i64 2, i64* %192, align 8 + %193 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg134, i32 0, i32 0 + %194 = bitcast [2 x %variant]* %varargslots135 to %variant* + store %variant* %194, %variant** %193, align 8 + %195 = bitcast %"variant[]"* %vararg134 to { i8*, i64 }* + %196 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %195, i32 0, i32 0 + %lo136 = load i8*, i8** %196, align 8 + %197 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %195, i32 0, i32 1 + %hi137 = load i64, i64* %197, align 8 + %198 = call i64 @std_io_printfln(i64* %retparam130, i8* %lo132, i64 %hi133, i8* %lo136, i64 %hi137) + %not_err138 = icmp eq i64 %198, 0 + br i1 %not_err138, label %after_check139, label %voiderr140 +after_check139: ; preds = %loop.body127 + br label %voiderr140 +voiderr140: ; preds = %after_check139, %loop.body127 + %199 = load i64, i64* %.anon124, align 8 + %add141 = add i64 %199, 1 + store i64 %add141, i64* %.anon124, align 8 + br label %loop.cond125 +loop.exit142: ; preds = %loop.cond125 + %200 = bitcast [8 x i32]* %a143 to i8* + call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 %200, i8* align 16 bitcast ([8 x i32]* @.__const.15 to i8*), i32 32, i1 false) + store i64 0, i64* %.anon144, align 8 + br label %loop.cond145 +loop.cond145: ; preds = %voiderr160, %loop.exit142 + %201 = load i64, i64* %.anon144, align 8 + %gt146 = icmp ugt i64 8, %201 + br i1 %gt146, label %loop.body147, label %loop.exit162 +loop.body147: ; preds = %loop.cond145 + %202 = load i64, i64* %.anon144, align 8 + store i64 %202, i64* %i148, align 8 + %203 = load i64, i64* %.anon144, align 8 + %204 = getelementptr inbounds [8 x i32], [8 x i32]* %a143, i64 0, i64 %203 + %205 = load i32, i32* %204, align 4 + store i32 %205, i32* %x149, align 4 + store %"char[]" { i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.16, i32 0, i32 0), i64 8 }, %"char[]"* %taddr151, align 8 + %206 = bitcast %"char[]"* %taddr151 to { i8*, i64 }* + %207 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %206, i32 0, i32 0 + %lo152 = load i8*, i8** %207, align 8 + %208 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %206, i32 0, i32 1 + %hi153 = load i64, i64* %208, align 8 + %209 = bitcast i64* %i148 to i8* + %210 = insertvalue %variant undef, i8* %209, 0 + %211 = insertvalue %variant %210, i64 ptrtoint (%.introspect* @"ct$ulong" to i64), 1 + %212 = getelementptr inbounds [2 x %variant], [2 x %variant]* %varargslots155, i64 0, i64 0 + store %variant %211, %variant* %212, align 16 + %213 = bitcast i32* %x149 to i8* + %214 = insertvalue %variant undef, i8* %213, 0 + %215 = insertvalue %variant %214, i64 ptrtoint (%.introspect* @"ct$int" to i64), 1 + %216 = getelementptr inbounds [2 x %variant], [2 x %variant]* %varargslots155, i64 0, i64 1 + store %variant %215, %variant* %216, align 16 + %217 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg154, i32 0, i32 1 + store i64 2, i64* %217, align 8 + %218 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg154, i32 0, i32 0 + %219 = bitcast [2 x %variant]* %varargslots155 to %variant* + store %variant* %219, %variant** %218, align 8 + %220 = bitcast %"variant[]"* %vararg154 to { i8*, i64 }* + %221 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %220, i32 0, i32 0 + %lo156 = load i8*, i8** %221, align 8 + %222 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %220, i32 0, i32 1 + %hi157 = load i64, i64* %222, align 8 + %223 = call i64 @std_io_printfln(i64* %retparam150, i8* %lo152, i64 %hi153, i8* %lo156, i64 %hi157) + %not_err158 = icmp eq i64 %223, 0 + br i1 %not_err158, label %after_check159, label %voiderr160 +after_check159: ; preds = %loop.body147 + br label %voiderr160 +voiderr160: ; preds = %after_check159, %loop.body147 + %224 = load i64, i64* %.anon144, align 8 + %add161 = add i64 %224, 1 + store i64 %add161, i64* %.anon144, align 8 + br label %loop.cond145 +loop.exit162: ; preds = %loop.cond145 + %225 = bitcast [7 x i32]* %b to i8* + call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 %225, i8* align 16 bitcast ([7 x i32]* @.__const.17 to i8*), i32 28, i1 false) + store i64 0, i64* %.anon163, align 8 + br label %loop.cond164 +loop.cond164: ; preds = %voiderr179, %loop.exit162 + %226 = load i64, i64* %.anon163, align 8 + %gt165 = icmp ugt i64 7, %226 + br i1 %gt165, label %loop.body166, label %loop.exit181 +loop.body166: ; preds = %loop.cond164 + %227 = load i64, i64* %.anon163, align 8 + store i64 %227, i64* %i167, align 8 + %228 = load i64, i64* %.anon163, align 8 + %229 = getelementptr inbounds [7 x i32], [7 x i32]* %b, i64 0, i64 %228 + %230 = load i32, i32* %229, align 4 + store i32 %230, i32* %x168, align 4 + store %"char[]" { i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.18, i32 0, i32 0), i64 8 }, %"char[]"* %taddr170, align 8 + %231 = bitcast %"char[]"* %taddr170 to { i8*, i64 }* + %232 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %231, i32 0, i32 0 + %lo171 = load i8*, i8** %232, align 8 + %233 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %231, i32 0, i32 1 + %hi172 = load i64, i64* %233, align 8 + %234 = bitcast i64* %i167 to i8* + %235 = insertvalue %variant undef, i8* %234, 0 + %236 = insertvalue %variant %235, i64 ptrtoint (%.introspect* @"ct$ulong" to i64), 1 + %237 = getelementptr inbounds [2 x %variant], [2 x %variant]* %varargslots174, i64 0, i64 0 + store %variant %236, %variant* %237, align 16 + %238 = bitcast i32* %x168 to i8* + %239 = insertvalue %variant undef, i8* %238, 0 + %240 = insertvalue %variant %239, i64 ptrtoint (%.introspect* @"ct$int" to i64), 1 + %241 = getelementptr inbounds [2 x %variant], [2 x %variant]* %varargslots174, i64 0, i64 1 + store %variant %240, %variant* %241, align 16 + %242 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg173, i32 0, i32 1 + store i64 2, i64* %242, align 8 + %243 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg173, i32 0, i32 0 + %244 = bitcast [2 x %variant]* %varargslots174 to %variant* + store %variant* %244, %variant** %243, align 8 + %245 = bitcast %"variant[]"* %vararg173 to { i8*, i64 }* + %246 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %245, i32 0, i32 0 + %lo175 = load i8*, i8** %246, align 8 + %247 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %245, i32 0, i32 1 + %hi176 = load i64, i64* %247, align 8 + %248 = call i64 @std_io_printfln(i64* %retparam169, i8* %lo171, i64 %hi172, i8* %lo175, i64 %hi176) + %not_err177 = icmp eq i64 %248, 0 + br i1 %not_err177, label %after_check178, label %voiderr179 +after_check178: ; preds = %loop.body166 + br label %voiderr179 +voiderr179: ; preds = %after_check178, %loop.body166 + %249 = load i64, i64* %.anon163, align 8 + %add180 = add i64 %249, 1 + store i64 %add180, i64* %.anon163, align 8 + br label %loop.cond164 +loop.exit181: ; preds = %loop.cond164 + %250 = bitcast [8 x i32]* %c to i8* + call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 %250, i8* align 16 bitcast ([8 x i32]* @.__const.19 to i8*), i32 32, i1 false) + store i64 0, i64* %.anon182, align 8 + br label %loop.cond183 +loop.cond183: ; preds = %voiderr198, %loop.exit181 + %251 = load i64, i64* %.anon182, align 8 + %gt184 = icmp ugt i64 8, %251 + br i1 %gt184, label %loop.body185, label %loop.exit200 +loop.body185: ; preds = %loop.cond183 + %252 = load i64, i64* %.anon182, align 8 + store i64 %252, i64* %i186, align 8 + %253 = load i64, i64* %.anon182, align 8 + %254 = getelementptr inbounds [8 x i32], [8 x i32]* %c, i64 0, i64 %253 + %255 = load i32, i32* %254, align 4 + store i32 %255, i32* %x187, align 4 + store %"char[]" { i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.20, i32 0, i32 0), i64 9 }, %"char[]"* %taddr189, align 8 + %256 = bitcast %"char[]"* %taddr189 to { i8*, i64 }* + %257 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %256, i32 0, i32 0 + %lo190 = load i8*, i8** %257, align 8 + %258 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %256, i32 0, i32 1 + %hi191 = load i64, i64* %258, align 8 + %259 = bitcast i64* %i186 to i8* + %260 = insertvalue %variant undef, i8* %259, 0 + %261 = insertvalue %variant %260, i64 ptrtoint (%.introspect* @"ct$ulong" to i64), 1 + %262 = getelementptr inbounds [2 x %variant], [2 x %variant]* %varargslots193, i64 0, i64 0 + store %variant %261, %variant* %262, align 16 + %263 = bitcast i32* %x187 to i8* + %264 = insertvalue %variant undef, i8* %263, 0 + %265 = insertvalue %variant %264, i64 ptrtoint (%.introspect* @"ct$int" to i64), 1 + %266 = getelementptr inbounds [2 x %variant], [2 x %variant]* %varargslots193, i64 0, i64 1 + store %variant %265, %variant* %266, align 16 + %267 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg192, i32 0, i32 1 + store i64 2, i64* %267, align 8 + %268 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg192, i32 0, i32 0 + %269 = bitcast [2 x %variant]* %varargslots193 to %variant* + store %variant* %269, %variant** %268, align 8 + %270 = bitcast %"variant[]"* %vararg192 to { i8*, i64 }* + %271 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %270, i32 0, i32 0 + %lo194 = load i8*, i8** %271, align 8 + %272 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %270, i32 0, i32 1 + %hi195 = load i64, i64* %272, align 8 + %273 = call i64 @std_io_printfln(i64* %retparam188, i8* %lo190, i64 %hi191, i8* %lo194, i64 %hi195) + %not_err196 = icmp eq i64 %273, 0 + br i1 %not_err196, label %after_check197, label %voiderr198 +after_check197: ; preds = %loop.body185 + br label %voiderr198 +voiderr198: ; preds = %after_check197, %loop.body185 + %274 = load i64, i64* %.anon182, align 8 + %add199 = add i64 %274, 1 + store i64 %add199, i64* %.anon182, align 8 + br label %loop.cond183 +loop.exit200: ; preds = %loop.cond183 + %275 = bitcast [6 x i32]* %a201 to i8* + call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 16 %275, i8* align 16 bitcast ([6 x i32]* @.__const.21 to i8*), i32 24, i1 false) + store i64 0, i64* %.anon202, align 8 + br label %loop.cond203 +loop.cond203: ; preds = %voiderr218, %loop.exit200 + %276 = load i64, i64* %.anon202, align 8 + %gt204 = icmp ugt i64 6, %276 + br i1 %gt204, label %loop.body205, label %loop.exit220 +loop.body205: ; preds = %loop.cond203 + %277 = load i64, i64* %.anon202, align 8 + store i64 %277, i64* %i206, align 8 + %278 = load i64, i64* %.anon202, align 8 + %279 = getelementptr inbounds [6 x i32], [6 x i32]* %a201, i64 0, i64 %278 + %280 = load i32, i32* %279, align 4 + store i32 %280, i32* %x207, align 4 + store %"char[]" { i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.22, i32 0, i32 0), i64 6 }, %"char[]"* %taddr209, align 8 + %281 = bitcast %"char[]"* %taddr209 to { i8*, i64 }* + %282 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %281, i32 0, i32 0 + %lo210 = load i8*, i8** %282, align 8 + %283 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %281, i32 0, i32 1 + %hi211 = load i64, i64* %283, align 8 + %284 = bitcast i64* %i206 to i8* + %285 = insertvalue %variant undef, i8* %284, 0 + %286 = insertvalue %variant %285, i64 ptrtoint (%.introspect* @"ct$ulong" to i64), 1 + %287 = getelementptr inbounds [2 x %variant], [2 x %variant]* %varargslots213, i64 0, i64 0 + store %variant %286, %variant* %287, align 16 + %288 = bitcast i32* %x207 to i8* + %289 = insertvalue %variant undef, i8* %288, 0 + %290 = insertvalue %variant %289, i64 ptrtoint (%.introspect* @"ct$int" to i64), 1 + %291 = getelementptr inbounds [2 x %variant], [2 x %variant]* %varargslots213, i64 0, i64 1 + store %variant %290, %variant* %291, align 16 + %292 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg212, i32 0, i32 1 + store i64 2, i64* %292, align 8 + %293 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg212, i32 0, i32 0 + %294 = bitcast [2 x %variant]* %varargslots213 to %variant* + store %variant* %294, %variant** %293, align 8 + %295 = bitcast %"variant[]"* %vararg212 to { i8*, i64 }* + %296 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %295, i32 0, i32 0 + %lo214 = load i8*, i8** %296, align 8 + %297 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %295, i32 0, i32 1 + %hi215 = load i64, i64* %297, align 8 + %298 = call i64 @std_io_printfln(i64* %retparam208, i8* %lo210, i64 %hi211, i8* %lo214, i64 %hi215) + %not_err216 = icmp eq i64 %298, 0 + br i1 %not_err216, label %after_check217, label %voiderr218 +after_check217: ; preds = %loop.body205 + br label %voiderr218 +voiderr218: ; preds = %after_check217, %loop.body205 + %299 = load i64, i64* %.anon202, align 8 + %add219 = add i64 %299, 1 + store i64 %add219, i64* %.anon202, align 8 + br label %loop.cond203 +loop.exit220: ; preds = %loop.cond203 + ret void +} + diff --git a/test/test_suite2/macros/macro_untyped_varargs_2.c3t b/test/test_suite2/macros/macro_untyped_varargs_2.c3t index f3f4f9807..f1ca97d60 100644 --- a/test/test_suite2/macros/macro_untyped_varargs_2.c3t +++ b/test/test_suite2/macros/macro_untyped_varargs_2.c3t @@ -8,14 +8,14 @@ macro @foo(...) { int i = $vaarg(1) + $vaarg(1); int j = $vaexpr(2) + $vaexpr(2); - $for (var $i = 0; $i < $vacount(); $i++): + $for (var $i = 0; $i < $vacount; $i++): io::printfln("%d", $vaarg($i)); $endfor; } macro foo2(...) { - $for (var $i = 0; $i < $vacount(); $i++): + $for (var $i = 0; $i < $vacount; $i++): { $vatype($i) x; } @@ -26,7 +26,7 @@ macro foo2(...) macro foo3(...) { var $x = 0; - $for (var $i = 0; $i < $vacount(); $i++): + $for (var $i = 0; $i < $vacount; $i++): $x += $vaconst($i); $endfor; return $x; diff --git a/test/test_suite2/macros/macro_vasplat.c3t b/test/test_suite2/macros/macro_vasplat.c3t new file mode 100644 index 000000000..be0822805 --- /dev/null +++ b/test/test_suite2/macros/macro_vasplat.c3t @@ -0,0 +1,777 @@ +// #target: macos-x64 +module test; +import std::io; + +macro @hello(...) +{ + int[*] a = { 1, $vasplat(), 3 }; + foreach (i, x : a) io::printfln("%d: %d", i, x); +} + +macro @hello1(...) +{ + int[*] a = { 1, $vasplat() }; + foreach (i, x : a) io::printfln("x:%d: %d", i, x); +} + +macro @hello2(...) +{ + int[*] a = { $vasplat(), 888 }; + foreach (i, x : a) io::printfln("x:%d: %d", i, x); +} + +macro @hello3(...) +{ + int[*] a = { $vasplat() }; + foreach (i, x : a) io::printfln("x:%d: %d", i, x); +} + +macro @hello4(...) +{ + int[*] a = { 5, $vasplat(2..4), 77 }; + foreach (i, x : a) io::printfln("y:%d: %d", i, x); +} + +macro @hello5(...) +{ + int[*] a = { 5, $vasplat(2..), 77 }; + foreach (i, x : a) io::printfln("y:%d: %d", i, x); + int[*] b = { 55, $vasplat(2..^2), 88 }; + foreach (i, x : b) io::printfln("z:%d: %d", i, x); + int[*] c = { 55, $vasplat(0:^2), 88 }; + foreach (i, x : c) io::printfln("zz:%d: %d", i, x); +} + +macro @hello6(...) +{ + @hello(66, $vasplat()); +} +fn void main() +{ + @hello1(223, 326); + @hello1(); + @hello(26, 36); + @hello(); + @hello2(2123, 3326); + @hello2(); + @hello3(2123, 3326); + @hello4(1, 2, 3, 4, 5, 6, 7, 8); + @hello5(1, 2, 3, 4, 5, 6, 7, 8); + @hello6(1, 2, 3); +} + +/* #expect: test.ll + +define void @test_main() #0 { +entry: + %a = alloca [3 x i32], align 4 + %.anon = alloca i64, align 8 + %i = alloca i64, align 8 + %x = alloca i32, align 4 + %retparam = alloca i64, align 8 + %taddr = alloca %"char[]", align 8 + %vararg = alloca %"variant[]", align 8 + %varargslots = alloca [2 x %variant], align 16 + %a3 = alloca [1 x i32], align 4 + %.anon4 = alloca i64, align 8 + %i8 = alloca i64, align 8 + %x9 = alloca i32, align 4 + %retparam10 = alloca i64, align 8 + %taddr11 = alloca %"char[]", align 8 + %vararg14 = alloca %"variant[]", align 8 + %varargslots15 = alloca [2 x %variant], align 16 + %a23 = alloca [4 x i32], align 16 + %.anon24 = alloca i64, align 8 + %i28 = alloca i64, align 8 + %x29 = alloca i32, align 4 + %retparam30 = alloca i64, align 8 + %taddr31 = alloca %"char[]", align 8 + %vararg34 = alloca %"variant[]", align 8 + %varargslots35 = alloca [2 x %variant], align 16 + %a43 = alloca [2 x i32], align 4 + %.anon44 = alloca i64, align 8 + %i48 = alloca i64, align 8 + %x49 = alloca i32, align 4 + %retparam50 = alloca i64, align 8 + %taddr51 = alloca %"char[]", align 8 + %vararg54 = alloca %"variant[]", align 8 + %varargslots55 = alloca [2 x %variant], align 16 + %a63 = alloca [3 x i32], align 4 + %.anon64 = alloca i64, align 8 + %i68 = alloca i64, align 8 + %x69 = alloca i32, align 4 + %retparam70 = alloca i64, align 8 + %taddr71 = alloca %"char[]", align 8 + %vararg74 = alloca %"variant[]", align 8 + %varargslots75 = alloca [2 x %variant], align 16 + %a83 = alloca [1 x i32], align 4 + %.anon84 = alloca i64, align 8 + %i88 = alloca i64, align 8 + %x89 = alloca i32, align 4 + %retparam90 = alloca i64, align 8 + %taddr91 = alloca %"char[]", align 8 + %vararg94 = alloca %"variant[]", align 8 + %varargslots95 = alloca [2 x %variant], align 16 + %a103 = alloca [2 x i32], align 4 + %.anon104 = alloca i64, align 8 + %i108 = alloca i64, align 8 + %x109 = alloca i32, align 4 + %retparam110 = alloca i64, align 8 + %taddr111 = alloca %"char[]", align 8 + %vararg114 = alloca %"variant[]", align 8 + %varargslots115 = alloca [2 x %variant], align 16 + %a123 = alloca [5 x i32], align 16 + %.anon124 = alloca i64, align 8 + %i128 = alloca i64, align 8 + %x129 = alloca i32, align 4 + %retparam130 = alloca i64, align 8 + %taddr131 = alloca %"char[]", align 8 + %vararg134 = alloca %"variant[]", align 8 + %varargslots135 = alloca [2 x %variant], align 16 + %a143 = alloca [8 x i32], align 16 + %.anon144 = alloca i64, align 8 + %i148 = alloca i64, align 8 + %x149 = alloca i32, align 4 + %retparam150 = alloca i64, align 8 + %taddr151 = alloca %"char[]", align 8 + %vararg154 = alloca %"variant[]", align 8 + %varargslots155 = alloca [2 x %variant], align 16 + %b = alloca [7 x i32], align 16 + %.anon163 = alloca i64, align 8 + %i167 = alloca i64, align 8 + %x168 = alloca i32, align 4 + %retparam169 = alloca i64, align 8 + %taddr170 = alloca %"char[]", align 8 + %vararg173 = alloca %"variant[]", align 8 + %varargslots174 = alloca [2 x %variant], align 16 + %c = alloca [8 x i32], align 16 + %.anon182 = alloca i64, align 8 + %i186 = alloca i64, align 8 + %x187 = alloca i32, align 4 + %retparam188 = alloca i64, align 8 + %taddr189 = alloca %"char[]", align 8 + %vararg192 = alloca %"variant[]", align 8 + %varargslots193 = alloca [2 x %variant], align 16 + %a201 = alloca [6 x i32], align 16 + %.anon202 = alloca i64, align 8 + %i206 = alloca i64, align 8 + %x207 = alloca i32, align 4 + %retparam208 = alloca i64, align 8 + %taddr209 = alloca %"char[]", align 8 + %vararg212 = alloca %"variant[]", align 8 + %varargslots213 = alloca [2 x %variant], align 16 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %a, ptr align 4 @.__const, i32 12, i1 false) + store i64 0, ptr %.anon, align 8 + br label %loop.cond + +loop.cond: ; preds = %voiderr, %entry + %0 = load i64, ptr %.anon, align 8 + %gt = icmp ugt i64 3, %0 + br i1 %gt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %1 = load i64, ptr %.anon, align 8 + store i64 %1, ptr %i, align 8 + %2 = load i64, ptr %.anon, align 8 + %3 = getelementptr inbounds [3 x i32], ptr %a, i64 0, i64 %2 + %4 = load i32, ptr %3, align 4 + store i32 %4, ptr %x, align 4 + store %"char[]" { ptr @.str, i64 8 }, ptr %taddr, align 8 + %5 = getelementptr inbounds { ptr, i64 }, ptr %taddr, i32 0, i32 0 + %lo = load ptr, ptr %5, align 8 + %6 = getelementptr inbounds { ptr, i64 }, ptr %taddr, i32 0, i32 1 + %hi = load i64, ptr %6, align 8 + %7 = insertvalue %variant undef, ptr %i, 0 + %8 = insertvalue %variant %7, i64 ptrtoint (ptr @"ct$ulong" to i64), 1 + %9 = getelementptr inbounds [2 x %variant], ptr %varargslots, i64 0, i64 0 + store %variant %8, ptr %9, align 16 + %10 = insertvalue %variant undef, ptr %x, 0 + %11 = insertvalue %variant %10, i64 ptrtoint (ptr @"ct$int" to i64), 1 + %12 = getelementptr inbounds [2 x %variant], ptr %varargslots, i64 0, i64 1 + store %variant %11, ptr %12, align 16 + %13 = getelementptr inbounds %"variant[]", ptr %vararg, i32 0, i32 1 + store i64 2, ptr %13, align 8 + %14 = getelementptr inbounds %"variant[]", ptr %vararg, i32 0, i32 0 + store ptr %varargslots, ptr %14, align 8 + %15 = getelementptr inbounds { ptr, i64 }, ptr %vararg, i32 0, i32 0 + %lo1 = load ptr, ptr %15, align 8 + %16 = getelementptr inbounds { ptr, i64 }, ptr %vararg, i32 0, i32 1 + %hi2 = load i64, ptr %16, align 8 + %17 = call i64 @std_io_printfln(ptr %retparam, ptr %lo, i64 %hi, ptr %lo1, i64 %hi2) + %not_err = icmp eq i64 %17, 0 + br i1 %not_err, label %after_check, label %voiderr + +after_check: ; preds = %loop.body + br label %voiderr + +voiderr: ; preds = %after_check, %loop.body + %18 = load i64, ptr %.anon, align 8 + %add = add i64 %18, 1 + store i64 %add, ptr %.anon, align 8 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %a3, ptr align 4 @.__const.1, i32 4, i1 false) + store i64 0, ptr %.anon4, align 8 + br label %loop.cond5 + +loop.cond5: ; preds = %voiderr20, %loop.exit + %19 = load i64, ptr %.anon4, align 8 + %gt6 = icmp ugt i64 1, %19 + br i1 %gt6, label %loop.body7, label %loop.exit22 + +loop.body7: ; preds = %loop.cond5 + %20 = load i64, ptr %.anon4, align 8 + store i64 %20, ptr %i8, align 8 + %21 = load i64, ptr %.anon4, align 8 + %22 = getelementptr inbounds [1 x i32], ptr %a3, i64 0, i64 %21 + %23 = load i32, ptr %22, align 4 + store i32 %23, ptr %x9, align 4 + store %"char[]" { ptr @.str.2, i64 8 }, ptr %taddr11, align 8 + %24 = getelementptr inbounds { ptr, i64 }, ptr %taddr11, i32 0, i32 0 + %lo12 = load ptr, ptr %24, align 8 + %25 = getelementptr inbounds { ptr, i64 }, ptr %taddr11, i32 0, i32 1 + %hi13 = load i64, ptr %25, align 8 + %26 = insertvalue %variant undef, ptr %i8, 0 + %27 = insertvalue %variant %26, i64 ptrtoint (ptr @"ct$ulong" to i64), 1 + %28 = getelementptr inbounds [2 x %variant], ptr %varargslots15, i64 0, i64 0 + store %variant %27, ptr %28, align 16 + %29 = insertvalue %variant undef, ptr %x9, 0 + %30 = insertvalue %variant %29, i64 ptrtoint (ptr @"ct$int" to i64), 1 + %31 = getelementptr inbounds [2 x %variant], ptr %varargslots15, i64 0, i64 1 + store %variant %30, ptr %31, align 16 + %32 = getelementptr inbounds %"variant[]", ptr %vararg14, i32 0, i32 1 + store i64 2, ptr %32, align 8 + %33 = getelementptr inbounds %"variant[]", ptr %vararg14, i32 0, i32 0 + store ptr %varargslots15, ptr %33, align 8 + %34 = getelementptr inbounds { ptr, i64 }, ptr %vararg14, i32 0, i32 0 + %lo16 = load ptr, ptr %34, align 8 + %35 = getelementptr inbounds { ptr, i64 }, ptr %vararg14, i32 0, i32 1 + %hi17 = load i64, ptr %35, align 8 + %36 = call i64 @std_io_printfln(ptr %retparam10, ptr %lo12, i64 %hi13, ptr %lo16, i64 %hi17) + %not_err18 = icmp eq i64 %36, 0 + br i1 %not_err18, label %after_check19, label %voiderr20 + +after_check19: ; preds = %loop.body7 + br label %voiderr20 + +voiderr20: ; preds = %after_check19, %loop.body7 + %37 = load i64, ptr %.anon4, align 8 + %add21 = add i64 %37, 1 + store i64 %add21, ptr %.anon4, align 8 + br label %loop.cond5 + +loop.exit22: ; preds = %loop.cond5 + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %a23, ptr align 16 @.__const.3, i32 16, i1 false) + store i64 0, ptr %.anon24, align 8 + br label %loop.cond25 + +loop.cond25: ; preds = %voiderr40, %loop.exit22 + %38 = load i64, ptr %.anon24, align 8 + %gt26 = icmp ugt i64 4, %38 + br i1 %gt26, label %loop.body27, label %loop.exit42 + +loop.body27: ; preds = %loop.cond25 + %39 = load i64, ptr %.anon24, align 8 + store i64 %39, ptr %i28, align 8 + %40 = load i64, ptr %.anon24, align 8 + %41 = getelementptr inbounds [4 x i32], ptr %a23, i64 0, i64 %40 + %42 = load i32, ptr %41, align 4 + store i32 %42, ptr %x29, align 4 + store %"char[]" { ptr @.str.4, i64 6 }, ptr %taddr31, align 8 + %43 = getelementptr inbounds { ptr, i64 }, ptr %taddr31, i32 0, i32 0 + %lo32 = load ptr, ptr %43, align 8 + %44 = getelementptr inbounds { ptr, i64 }, ptr %taddr31, i32 0, i32 1 + %hi33 = load i64, ptr %44, align 8 + %45 = insertvalue %variant undef, ptr %i28, 0 + %46 = insertvalue %variant %45, i64 ptrtoint (ptr @"ct$ulong" to i64), 1 + %47 = getelementptr inbounds [2 x %variant], ptr %varargslots35, i64 0, i64 0 + store %variant %46, ptr %47, align 16 + %48 = insertvalue %variant undef, ptr %x29, 0 + %49 = insertvalue %variant %48, i64 ptrtoint (ptr @"ct$int" to i64), 1 + %50 = getelementptr inbounds [2 x %variant], ptr %varargslots35, i64 0, i64 1 + store %variant %49, ptr %50, align 16 + %51 = getelementptr inbounds %"variant[]", ptr %vararg34, i32 0, i32 1 + store i64 2, ptr %51, align 8 + %52 = getelementptr inbounds %"variant[]", ptr %vararg34, i32 0, i32 0 + store ptr %varargslots35, ptr %52, align 8 + %53 = getelementptr inbounds { ptr, i64 }, ptr %vararg34, i32 0, i32 0 + %lo36 = load ptr, ptr %53, align 8 + %54 = getelementptr inbounds { ptr, i64 }, ptr %vararg34, i32 0, i32 1 + %hi37 = load i64, ptr %54, align 8 + %55 = call i64 @std_io_printfln(ptr %retparam30, ptr %lo32, i64 %hi33, ptr %lo36, i64 %hi37) + %not_err38 = icmp eq i64 %55, 0 + br i1 %not_err38, label %after_check39, label %voiderr40 + +after_check39: ; preds = %loop.body27 + br label %voiderr40 + +voiderr40: ; preds = %after_check39, %loop.body27 + %56 = load i64, ptr %.anon24, align 8 + %add41 = add i64 %56, 1 + store i64 %add41, ptr %.anon24, align 8 + br label %loop.cond25 + +loop.exit42: ; preds = %loop.cond25 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %a43, ptr align 4 @.__const.5, i32 8, i1 false) + store i64 0, ptr %.anon44, align 8 + br label %loop.cond45 + +loop.cond45: ; preds = %voiderr60, %loop.exit42 + %57 = load i64, ptr %.anon44, align 8 + %gt46 = icmp ugt i64 2, %57 + br i1 %gt46, label %loop.body47, label %loop.exit62 + +loop.body47: ; preds = %loop.cond45 + %58 = load i64, ptr %.anon44, align 8 + store i64 %58, ptr %i48, align 8 + %59 = load i64, ptr %.anon44, align 8 + %60 = getelementptr inbounds [2 x i32], ptr %a43, i64 0, i64 %59 + %61 = load i32, ptr %60, align 4 + store i32 %61, ptr %x49, align 4 + store %"char[]" { ptr @.str.6, i64 6 }, ptr %taddr51, align 8 + %62 = getelementptr inbounds { ptr, i64 }, ptr %taddr51, i32 0, i32 0 + %lo52 = load ptr, ptr %62, align 8 + %63 = getelementptr inbounds { ptr, i64 }, ptr %taddr51, i32 0, i32 1 + %hi53 = load i64, ptr %63, align 8 + %64 = insertvalue %variant undef, ptr %i48, 0 + %65 = insertvalue %variant %64, i64 ptrtoint (ptr @"ct$ulong" to i64), 1 + %66 = getelementptr inbounds [2 x %variant], ptr %varargslots55, i64 0, i64 0 + store %variant %65, ptr %66, align 16 + %67 = insertvalue %variant undef, ptr %x49, 0 + %68 = insertvalue %variant %67, i64 ptrtoint (ptr @"ct$int" to i64), 1 + %69 = getelementptr inbounds [2 x %variant], ptr %varargslots55, i64 0, i64 1 + store %variant %68, ptr %69, align 16 + %70 = getelementptr inbounds %"variant[]", ptr %vararg54, i32 0, i32 1 + store i64 2, ptr %70, align 8 + %71 = getelementptr inbounds %"variant[]", ptr %vararg54, i32 0, i32 0 + store ptr %varargslots55, ptr %71, align 8 + %72 = getelementptr inbounds { ptr, i64 }, ptr %vararg54, i32 0, i32 0 + %lo56 = load ptr, ptr %72, align 8 + %73 = getelementptr inbounds { ptr, i64 }, ptr %vararg54, i32 0, i32 1 + %hi57 = load i64, ptr %73, align 8 + %74 = call i64 @std_io_printfln(ptr %retparam50, ptr %lo52, i64 %hi53, ptr %lo56, i64 %hi57) + %not_err58 = icmp eq i64 %74, 0 + br i1 %not_err58, label %after_check59, label %voiderr60 + +after_check59: ; preds = %loop.body47 + br label %voiderr60 + +voiderr60: ; preds = %after_check59, %loop.body47 + %75 = load i64, ptr %.anon44, align 8 + %add61 = add i64 %75, 1 + store i64 %add61, ptr %.anon44, align 8 + br label %loop.cond45 + +loop.exit62: ; preds = %loop.cond45 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %a63, ptr align 4 @.__const.7, i32 12, i1 false) + store i64 0, ptr %.anon64, align 8 + br label %loop.cond65 + +loop.cond65: ; preds = %voiderr80, %loop.exit62 + %76 = load i64, ptr %.anon64, align 8 + %gt66 = icmp ugt i64 3, %76 + br i1 %gt66, label %loop.body67, label %loop.exit82 + +loop.body67: ; preds = %loop.cond65 + %77 = load i64, ptr %.anon64, align 8 + store i64 %77, ptr %i68, align 8 + %78 = load i64, ptr %.anon64, align 8 + %79 = getelementptr inbounds [3 x i32], ptr %a63, i64 0, i64 %78 + %80 = load i32, ptr %79, align 4 + store i32 %80, ptr %x69, align 4 + store %"char[]" { ptr @.str.8, i64 8 }, ptr %taddr71, align 8 + %81 = getelementptr inbounds { ptr, i64 }, ptr %taddr71, i32 0, i32 0 + %lo72 = load ptr, ptr %81, align 8 + %82 = getelementptr inbounds { ptr, i64 }, ptr %taddr71, i32 0, i32 1 + %hi73 = load i64, ptr %82, align 8 + %83 = insertvalue %variant undef, ptr %i68, 0 + %84 = insertvalue %variant %83, i64 ptrtoint (ptr @"ct$ulong" to i64), 1 + %85 = getelementptr inbounds [2 x %variant], ptr %varargslots75, i64 0, i64 0 + store %variant %84, ptr %85, align 16 + %86 = insertvalue %variant undef, ptr %x69, 0 + %87 = insertvalue %variant %86, i64 ptrtoint (ptr @"ct$int" to i64), 1 + %88 = getelementptr inbounds [2 x %variant], ptr %varargslots75, i64 0, i64 1 + store %variant %87, ptr %88, align 16 + %89 = getelementptr inbounds %"variant[]", ptr %vararg74, i32 0, i32 1 + store i64 2, ptr %89, align 8 + %90 = getelementptr inbounds %"variant[]", ptr %vararg74, i32 0, i32 0 + store ptr %varargslots75, ptr %90, align 8 + %91 = getelementptr inbounds { ptr, i64 }, ptr %vararg74, i32 0, i32 0 + %lo76 = load ptr, ptr %91, align 8 + %92 = getelementptr inbounds { ptr, i64 }, ptr %vararg74, i32 0, i32 1 + %hi77 = load i64, ptr %92, align 8 + %93 = call i64 @std_io_printfln(ptr %retparam70, ptr %lo72, i64 %hi73, ptr %lo76, i64 %hi77) + %not_err78 = icmp eq i64 %93, 0 + br i1 %not_err78, label %after_check79, label %voiderr80 + +after_check79: ; preds = %loop.body67 + br label %voiderr80 + +voiderr80: ; preds = %after_check79, %loop.body67 + %94 = load i64, ptr %.anon64, align 8 + %add81 = add i64 %94, 1 + store i64 %add81, ptr %.anon64, align 8 + br label %loop.cond65 + +loop.exit82: ; preds = %loop.cond65 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %a83, ptr align 4 @.__const.9, i32 4, i1 false) + store i64 0, ptr %.anon84, align 8 + br label %loop.cond85 + +loop.cond85: ; preds = %voiderr100, %loop.exit82 + %95 = load i64, ptr %.anon84, align 8 + %gt86 = icmp ugt i64 1, %95 + br i1 %gt86, label %loop.body87, label %loop.exit102 + +loop.body87: ; preds = %loop.cond85 + %96 = load i64, ptr %.anon84, align 8 + store i64 %96, ptr %i88, align 8 + %97 = load i64, ptr %.anon84, align 8 + %98 = getelementptr inbounds [1 x i32], ptr %a83, i64 0, i64 %97 + %99 = load i32, ptr %98, align 4 + store i32 %99, ptr %x89, align 4 + store %"char[]" { ptr @.str.10, i64 8 }, ptr %taddr91, align 8 + %100 = getelementptr inbounds { ptr, i64 }, ptr %taddr91, i32 0, i32 0 + %lo92 = load ptr, ptr %100, align 8 + %101 = getelementptr inbounds { ptr, i64 }, ptr %taddr91, i32 0, i32 1 + %hi93 = load i64, ptr %101, align 8 + %102 = insertvalue %variant undef, ptr %i88, 0 + %103 = insertvalue %variant %102, i64 ptrtoint (ptr @"ct$ulong" to i64), 1 + %104 = getelementptr inbounds [2 x %variant], ptr %varargslots95, i64 0, i64 0 + store %variant %103, ptr %104, align 16 + %105 = insertvalue %variant undef, ptr %x89, 0 + %106 = insertvalue %variant %105, i64 ptrtoint (ptr @"ct$int" to i64), 1 + %107 = getelementptr inbounds [2 x %variant], ptr %varargslots95, i64 0, i64 1 + store %variant %106, ptr %107, align 16 + %108 = getelementptr inbounds %"variant[]", ptr %vararg94, i32 0, i32 1 + store i64 2, ptr %108, align 8 + %109 = getelementptr inbounds %"variant[]", ptr %vararg94, i32 0, i32 0 + store ptr %varargslots95, ptr %109, align 8 + %110 = getelementptr inbounds { ptr, i64 }, ptr %vararg94, i32 0, i32 0 + %lo96 = load ptr, ptr %110, align 8 + %111 = getelementptr inbounds { ptr, i64 }, ptr %vararg94, i32 0, i32 1 + %hi97 = load i64, ptr %111, align 8 + %112 = call i64 @std_io_printfln(ptr %retparam90, ptr %lo92, i64 %hi93, ptr %lo96, i64 %hi97) + %not_err98 = icmp eq i64 %112, 0 + br i1 %not_err98, label %after_check99, label %voiderr100 + +after_check99: ; preds = %loop.body87 + br label %voiderr100 + +voiderr100: ; preds = %after_check99, %loop.body87 + %113 = load i64, ptr %.anon84, align 8 + %add101 = add i64 %113, 1 + store i64 %add101, ptr %.anon84, align 8 + br label %loop.cond85 + +loop.exit102: ; preds = %loop.cond85 + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %a103, ptr align 4 @.__const.11, i32 8, i1 false) + store i64 0, ptr %.anon104, align 8 + br label %loop.cond105 + +loop.cond105: ; preds = %voiderr120, %loop.exit102 + %114 = load i64, ptr %.anon104, align 8 + %gt106 = icmp ugt i64 2, %114 + br i1 %gt106, label %loop.body107, label %loop.exit122 + +loop.body107: ; preds = %loop.cond105 + %115 = load i64, ptr %.anon104, align 8 + store i64 %115, ptr %i108, align 8 + %116 = load i64, ptr %.anon104, align 8 + %117 = getelementptr inbounds [2 x i32], ptr %a103, i64 0, i64 %116 + %118 = load i32, ptr %117, align 4 + store i32 %118, ptr %x109, align 4 + store %"char[]" { ptr @.str.12, i64 8 }, ptr %taddr111, align 8 + %119 = getelementptr inbounds { ptr, i64 }, ptr %taddr111, i32 0, i32 0 + %lo112 = load ptr, ptr %119, align 8 + %120 = getelementptr inbounds { ptr, i64 }, ptr %taddr111, i32 0, i32 1 + %hi113 = load i64, ptr %120, align 8 + %121 = insertvalue %variant undef, ptr %i108, 0 + %122 = insertvalue %variant %121, i64 ptrtoint (ptr @"ct$ulong" to i64), 1 + %123 = getelementptr inbounds [2 x %variant], ptr %varargslots115, i64 0, i64 0 + store %variant %122, ptr %123, align 16 + %124 = insertvalue %variant undef, ptr %x109, 0 + %125 = insertvalue %variant %124, i64 ptrtoint (ptr @"ct$int" to i64), 1 + %126 = getelementptr inbounds [2 x %variant], ptr %varargslots115, i64 0, i64 1 + store %variant %125, ptr %126, align 16 + %127 = getelementptr inbounds %"variant[]", ptr %vararg114, i32 0, i32 1 + store i64 2, ptr %127, align 8 + %128 = getelementptr inbounds %"variant[]", ptr %vararg114, i32 0, i32 0 + store ptr %varargslots115, ptr %128, align 8 + %129 = getelementptr inbounds { ptr, i64 }, ptr %vararg114, i32 0, i32 0 + %lo116 = load ptr, ptr %129, align 8 + %130 = getelementptr inbounds { ptr, i64 }, ptr %vararg114, i32 0, i32 1 + %hi117 = load i64, ptr %130, align 8 + %131 = call i64 @std_io_printfln(ptr %retparam110, ptr %lo112, i64 %hi113, ptr %lo116, i64 %hi117) + %not_err118 = icmp eq i64 %131, 0 + br i1 %not_err118, label %after_check119, label %voiderr120 + +after_check119: ; preds = %loop.body107 + br label %voiderr120 + +voiderr120: ; preds = %after_check119, %loop.body107 + %132 = load i64, ptr %.anon104, align 8 + %add121 = add i64 %132, 1 + store i64 %add121, ptr %.anon104, align 8 + br label %loop.cond105 + +loop.exit122: ; preds = %loop.cond105 + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %a123, ptr align 16 @.__const.13, i32 20, i1 false) + store i64 0, ptr %.anon124, align 8 + br label %loop.cond125 + +loop.cond125: ; preds = %voiderr140, %loop.exit122 + %133 = load i64, ptr %.anon124, align 8 + %gt126 = icmp ugt i64 5, %133 + br i1 %gt126, label %loop.body127, label %loop.exit142 + +loop.body127: ; preds = %loop.cond125 + %134 = load i64, ptr %.anon124, align 8 + store i64 %134, ptr %i128, align 8 + %135 = load i64, ptr %.anon124, align 8 + %136 = getelementptr inbounds [5 x i32], ptr %a123, i64 0, i64 %135 + %137 = load i32, ptr %136, align 4 + store i32 %137, ptr %x129, align 4 + store %"char[]" { ptr @.str.14, i64 8 }, ptr %taddr131, align 8 + %138 = getelementptr inbounds { ptr, i64 }, ptr %taddr131, i32 0, i32 0 + %lo132 = load ptr, ptr %138, align 8 + %139 = getelementptr inbounds { ptr, i64 }, ptr %taddr131, i32 0, i32 1 + %hi133 = load i64, ptr %139, align 8 + %140 = insertvalue %variant undef, ptr %i128, 0 + %141 = insertvalue %variant %140, i64 ptrtoint (ptr @"ct$ulong" to i64), 1 + %142 = getelementptr inbounds [2 x %variant], ptr %varargslots135, i64 0, i64 0 + store %variant %141, ptr %142, align 16 + %143 = insertvalue %variant undef, ptr %x129, 0 + %144 = insertvalue %variant %143, i64 ptrtoint (ptr @"ct$int" to i64), 1 + %145 = getelementptr inbounds [2 x %variant], ptr %varargslots135, i64 0, i64 1 + store %variant %144, ptr %145, align 16 + %146 = getelementptr inbounds %"variant[]", ptr %vararg134, i32 0, i32 1 + store i64 2, ptr %146, align 8 + %147 = getelementptr inbounds %"variant[]", ptr %vararg134, i32 0, i32 0 + store ptr %varargslots135, ptr %147, align 8 + %148 = getelementptr inbounds { ptr, i64 }, ptr %vararg134, i32 0, i32 0 + %lo136 = load ptr, ptr %148, align 8 + %149 = getelementptr inbounds { ptr, i64 }, ptr %vararg134, i32 0, i32 1 + %hi137 = load i64, ptr %149, align 8 + %150 = call i64 @std_io_printfln(ptr %retparam130, ptr %lo132, i64 %hi133, ptr %lo136, i64 %hi137) + %not_err138 = icmp eq i64 %150, 0 + br i1 %not_err138, label %after_check139, label %voiderr140 + +after_check139: ; preds = %loop.body127 + br label %voiderr140 + +voiderr140: ; preds = %after_check139, %loop.body127 + %151 = load i64, ptr %.anon124, align 8 + %add141 = add i64 %151, 1 + store i64 %add141, ptr %.anon124, align 8 + br label %loop.cond125 + +loop.exit142: ; preds = %loop.cond125 + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %a143, ptr align 16 @.__const.15, i32 32, i1 false) + store i64 0, ptr %.anon144, align 8 + br label %loop.cond145 + +loop.cond145: ; preds = %voiderr160, %loop.exit142 + %152 = load i64, ptr %.anon144, align 8 + %gt146 = icmp ugt i64 8, %152 + br i1 %gt146, label %loop.body147, label %loop.exit162 + +loop.body147: ; preds = %loop.cond145 + %153 = load i64, ptr %.anon144, align 8 + store i64 %153, ptr %i148, align 8 + %154 = load i64, ptr %.anon144, align 8 + %155 = getelementptr inbounds [8 x i32], ptr %a143, i64 0, i64 %154 + %156 = load i32, ptr %155, align 4 + store i32 %156, ptr %x149, align 4 + store %"char[]" { ptr @.str.16, i64 8 }, ptr %taddr151, align 8 + %157 = getelementptr inbounds { ptr, i64 }, ptr %taddr151, i32 0, i32 0 + %lo152 = load ptr, ptr %157, align 8 + %158 = getelementptr inbounds { ptr, i64 }, ptr %taddr151, i32 0, i32 1 + %hi153 = load i64, ptr %158, align 8 + %159 = insertvalue %variant undef, ptr %i148, 0 + %160 = insertvalue %variant %159, i64 ptrtoint (ptr @"ct$ulong" to i64), 1 + %161 = getelementptr inbounds [2 x %variant], ptr %varargslots155, i64 0, i64 0 + store %variant %160, ptr %161, align 16 + %162 = insertvalue %variant undef, ptr %x149, 0 + %163 = insertvalue %variant %162, i64 ptrtoint (ptr @"ct$int" to i64), 1 + %164 = getelementptr inbounds [2 x %variant], ptr %varargslots155, i64 0, i64 1 + store %variant %163, ptr %164, align 16 + %165 = getelementptr inbounds %"variant[]", ptr %vararg154, i32 0, i32 1 + store i64 2, ptr %165, align 8 + %166 = getelementptr inbounds %"variant[]", ptr %vararg154, i32 0, i32 0 + store ptr %varargslots155, ptr %166, align 8 + %167 = getelementptr inbounds { ptr, i64 }, ptr %vararg154, i32 0, i32 0 + %lo156 = load ptr, ptr %167, align 8 + %168 = getelementptr inbounds { ptr, i64 }, ptr %vararg154, i32 0, i32 1 + %hi157 = load i64, ptr %168, align 8 + %169 = call i64 @std_io_printfln(ptr %retparam150, ptr %lo152, i64 %hi153, ptr %lo156, i64 %hi157) + %not_err158 = icmp eq i64 %169, 0 + br i1 %not_err158, label %after_check159, label %voiderr160 + +after_check159: ; preds = %loop.body147 + br label %voiderr160 + +voiderr160: ; preds = %after_check159, %loop.body147 + %170 = load i64, ptr %.anon144, align 8 + %add161 = add i64 %170, 1 + store i64 %add161, ptr %.anon144, align 8 + br label %loop.cond145 + +loop.exit162: ; preds = %loop.cond145 + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %b, ptr align 16 @.__const.17, i32 28, i1 false) + store i64 0, ptr %.anon163, align 8 + br label %loop.cond164 + +loop.cond164: ; preds = %voiderr179, %loop.exit162 + %171 = load i64, ptr %.anon163, align 8 + %gt165 = icmp ugt i64 7, %171 + br i1 %gt165, label %loop.body166, label %loop.exit181 + +loop.body166: ; preds = %loop.cond164 + %172 = load i64, ptr %.anon163, align 8 + store i64 %172, ptr %i167, align 8 + %173 = load i64, ptr %.anon163, align 8 + %174 = getelementptr inbounds [7 x i32], ptr %b, i64 0, i64 %173 + %175 = load i32, ptr %174, align 4 + store i32 %175, ptr %x168, align 4 + store %"char[]" { ptr @.str.18, i64 8 }, ptr %taddr170, align 8 + %176 = getelementptr inbounds { ptr, i64 }, ptr %taddr170, i32 0, i32 0 + %lo171 = load ptr, ptr %176, align 8 + %177 = getelementptr inbounds { ptr, i64 }, ptr %taddr170, i32 0, i32 1 + %hi172 = load i64, ptr %177, align 8 + %178 = insertvalue %variant undef, ptr %i167, 0 + %179 = insertvalue %variant %178, i64 ptrtoint (ptr @"ct$ulong" to i64), 1 + %180 = getelementptr inbounds [2 x %variant], ptr %varargslots174, i64 0, i64 0 + store %variant %179, ptr %180, align 16 + %181 = insertvalue %variant undef, ptr %x168, 0 + %182 = insertvalue %variant %181, i64 ptrtoint (ptr @"ct$int" to i64), 1 + %183 = getelementptr inbounds [2 x %variant], ptr %varargslots174, i64 0, i64 1 + store %variant %182, ptr %183, align 16 + %184 = getelementptr inbounds %"variant[]", ptr %vararg173, i32 0, i32 1 + store i64 2, ptr %184, align 8 + %185 = getelementptr inbounds %"variant[]", ptr %vararg173, i32 0, i32 0 + store ptr %varargslots174, ptr %185, align 8 + %186 = getelementptr inbounds { ptr, i64 }, ptr %vararg173, i32 0, i32 0 + %lo175 = load ptr, ptr %186, align 8 + %187 = getelementptr inbounds { ptr, i64 }, ptr %vararg173, i32 0, i32 1 + %hi176 = load i64, ptr %187, align 8 + %188 = call i64 @std_io_printfln(ptr %retparam169, ptr %lo171, i64 %hi172, ptr %lo175, i64 %hi176) + %not_err177 = icmp eq i64 %188, 0 + br i1 %not_err177, label %after_check178, label %voiderr179 + +after_check178: ; preds = %loop.body166 + br label %voiderr179 + +voiderr179: ; preds = %after_check178, %loop.body166 + %189 = load i64, ptr %.anon163, align 8 + %add180 = add i64 %189, 1 + store i64 %add180, ptr %.anon163, align 8 + br label %loop.cond164 + +loop.exit181: ; preds = %loop.cond164 + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %c, ptr align 16 @.__const.19, i32 32, i1 false) + store i64 0, ptr %.anon182, align 8 + br label %loop.cond183 + +loop.cond183: ; preds = %voiderr198, %loop.exit181 + %190 = load i64, ptr %.anon182, align 8 + %gt184 = icmp ugt i64 8, %190 + br i1 %gt184, label %loop.body185, label %loop.exit200 + +loop.body185: ; preds = %loop.cond183 + %191 = load i64, ptr %.anon182, align 8 + store i64 %191, ptr %i186, align 8 + %192 = load i64, ptr %.anon182, align 8 + %193 = getelementptr inbounds [8 x i32], ptr %c, i64 0, i64 %192 + %194 = load i32, ptr %193, align 4 + store i32 %194, ptr %x187, align 4 + store %"char[]" { ptr @.str.20, i64 9 }, ptr %taddr189, align 8 + %195 = getelementptr inbounds { ptr, i64 }, ptr %taddr189, i32 0, i32 0 + %lo190 = load ptr, ptr %195, align 8 + %196 = getelementptr inbounds { ptr, i64 }, ptr %taddr189, i32 0, i32 1 + %hi191 = load i64, ptr %196, align 8 + %197 = insertvalue %variant undef, ptr %i186, 0 + %198 = insertvalue %variant %197, i64 ptrtoint (ptr @"ct$ulong" to i64), 1 + %199 = getelementptr inbounds [2 x %variant], ptr %varargslots193, i64 0, i64 0 + store %variant %198, ptr %199, align 16 + %200 = insertvalue %variant undef, ptr %x187, 0 + %201 = insertvalue %variant %200, i64 ptrtoint (ptr @"ct$int" to i64), 1 + %202 = getelementptr inbounds [2 x %variant], ptr %varargslots193, i64 0, i64 1 + store %variant %201, ptr %202, align 16 + %203 = getelementptr inbounds %"variant[]", ptr %vararg192, i32 0, i32 1 + store i64 2, ptr %203, align 8 + %204 = getelementptr inbounds %"variant[]", ptr %vararg192, i32 0, i32 0 + store ptr %varargslots193, ptr %204, align 8 + %205 = getelementptr inbounds { ptr, i64 }, ptr %vararg192, i32 0, i32 0 + %lo194 = load ptr, ptr %205, align 8 + %206 = getelementptr inbounds { ptr, i64 }, ptr %vararg192, i32 0, i32 1 + %hi195 = load i64, ptr %206, align 8 + %207 = call i64 @std_io_printfln(ptr %retparam188, ptr %lo190, i64 %hi191, ptr %lo194, i64 %hi195) + %not_err196 = icmp eq i64 %207, 0 + br i1 %not_err196, label %after_check197, label %voiderr198 + +after_check197: ; preds = %loop.body185 + br label %voiderr198 + +voiderr198: ; preds = %after_check197, %loop.body185 + %208 = load i64, ptr %.anon182, align 8 + %add199 = add i64 %208, 1 + store i64 %add199, ptr %.anon182, align 8 + br label %loop.cond183 + +loop.exit200: ; preds = %loop.cond183 + call void @llvm.memcpy.p0.p0.i32(ptr align 16 %a201, ptr align 16 @.__const.21, i32 24, i1 false) + store i64 0, ptr %.anon202, align 8 + br label %loop.cond203 + +loop.cond203: ; preds = %voiderr218, %loop.exit200 + %209 = load i64, ptr %.anon202, align 8 + %gt204 = icmp ugt i64 6, %209 + br i1 %gt204, label %loop.body205, label %loop.exit220 + +loop.body205: ; preds = %loop.cond203 + %210 = load i64, ptr %.anon202, align 8 + store i64 %210, ptr %i206, align 8 + %211 = load i64, ptr %.anon202, align 8 + %212 = getelementptr inbounds [6 x i32], ptr %a201, i64 0, i64 %211 + %213 = load i32, ptr %212, align 4 + store i32 %213, ptr %x207, align 4 + store %"char[]" { ptr @.str.22, i64 6 }, ptr %taddr209, align 8 + %214 = getelementptr inbounds { ptr, i64 }, ptr %taddr209, i32 0, i32 0 + %lo210 = load ptr, ptr %214, align 8 + %215 = getelementptr inbounds { ptr, i64 }, ptr %taddr209, i32 0, i32 1 + %hi211 = load i64, ptr %215, align 8 + %216 = insertvalue %variant undef, ptr %i206, 0 + %217 = insertvalue %variant %216, i64 ptrtoint (ptr @"ct$ulong" to i64), 1 + %218 = getelementptr inbounds [2 x %variant], ptr %varargslots213, i64 0, i64 0 + store %variant %217, ptr %218, align 16 + %219 = insertvalue %variant undef, ptr %x207, 0 + %220 = insertvalue %variant %219, i64 ptrtoint (ptr @"ct$int" to i64), 1 + %221 = getelementptr inbounds [2 x %variant], ptr %varargslots213, i64 0, i64 1 + store %variant %220, ptr %221, align 16 + %222 = getelementptr inbounds %"variant[]", ptr %vararg212, i32 0, i32 1 + store i64 2, ptr %222, align 8 + %223 = getelementptr inbounds %"variant[]", ptr %vararg212, i32 0, i32 0 + store ptr %varargslots213, ptr %223, align 8 + %224 = getelementptr inbounds { ptr, i64 }, ptr %vararg212, i32 0, i32 0 + %lo214 = load ptr, ptr %224, align 8 + %225 = getelementptr inbounds { ptr, i64 }, ptr %vararg212, i32 0, i32 1 + %hi215 = load i64, ptr %225, align 8 + %226 = call i64 @std_io_printfln(ptr %retparam208, ptr %lo210, i64 %hi211, ptr %lo214, i64 %hi215) + %not_err216 = icmp eq i64 %226, 0 + br i1 %not_err216, label %after_check217, label %voiderr218 + +after_check217: ; preds = %loop.body205 + br label %voiderr218 + +voiderr218: ; preds = %after_check217, %loop.body205 + %227 = load i64, ptr %.anon202, align 8 + %add219 = add i64 %227, 1 + store i64 %add219, ptr %.anon202, align 8 + br label %loop.cond203 + +loop.exit220: ; preds = %loop.cond203 + ret void +} +