diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 18e5ebbd1..38ae9d292 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -2072,6 +2072,7 @@ Decl *decl_find_enum_constant(Decl *decl, const char *name); Expr *expr_new(ExprKind kind, SourceSpan start); Expr *expr_new_const_int(SourceSpan span, Type *type, uint64_t v, bool narrowable); Expr *expr_new_const_bool(SourceSpan span, Type *type, bool value); +Expr *expr_new_const_typeid(SourceSpan span, Type *type); bool expr_is_simple(Expr *expr); bool expr_is_pure(Expr *expr); bool expr_is_constant_eval(Expr *expr, ConstantEvalKind eval_kind); @@ -2105,7 +2106,9 @@ INLINE void expr_rewrite_const_null(Expr *expr, Type *type); INLINE void expr_rewrite_const_bool(Expr *expr, Type *type, bool b); INLINE void expr_rewrite_const_float(Expr *expr, Type *type, Real d); INLINE void expr_rewrite_const_int(Expr *expr, Type *type, uint64_t v, bool narrowable); +INLINE void expr_rewrite_const_typeid(Expr *expr, Type *type); INLINE void expr_rewrite_const_initializer(Expr *expr, Type *type, ConstInitializer *initializer); +INLINE void expr_rewrite_const_untyped_list(Expr *expr, Expr **elements); void expr_rewrite_to_builtin_access(Expr *expr, Expr *parent, BuiltinAccessKind kind, Type *type); void expr_rewrite_to_string(Expr *expr_to_rewrite, const char *string); @@ -2896,6 +2899,14 @@ INLINE void expr_rewrite_const_null(Expr *expr, Type *type) expr->resolve_status = RESOLVE_DONE; } +INLINE void expr_rewrite_const_untyped_list(Expr *expr, Expr **elements) +{ + expr->expr_kind = EXPR_CONST; + expr->type = type_untypedlist; + expr->const_expr = (ExprConst) { .untyped_list = elements, .const_kind = CONST_UNTYPED_LIST }; + expr->resolve_status = RESOLVE_DONE; +} + INLINE void expr_rewrite_const_initializer(Expr *expr, Type *type, ConstInitializer *initializer) { expr->expr_kind = EXPR_CONST; @@ -2904,6 +2915,16 @@ INLINE void expr_rewrite_const_initializer(Expr *expr, Type *type, ConstInitiali expr->resolve_status = RESOLVE_DONE; } +INLINE void expr_rewrite_const_typeid(Expr *expr, Type *type) +{ + expr->expr_kind = EXPR_CONST; + expr->const_expr.const_kind = CONST_TYPEID; + expr->const_expr.typeid = type->canonical; + expr->type = type_typeid; + expr->resolve_status = RESOLVE_DONE; +} + + INLINE void expr_rewrite_const_int(Expr *expr, Type *type, uint64_t v, bool narrowable) { expr->expr_kind = EXPR_CONST; diff --git a/src/compiler/enums.h b/src/compiler/enums.h index cb54cd0a9..19d5d67ff 100644 --- a/src/compiler/enums.h +++ b/src/compiler/enums.h @@ -883,12 +883,15 @@ typedef enum TYPE_PROPERTY_ELEMENTS, TYPE_PROPERTY_INF, TYPE_PROPERTY_LEN, - TYPE_PROPERTY_MIN, TYPE_PROPERTY_MAX, + TYPE_PROPERTY_MEMBERSOF, + TYPE_PROPERTY_MIN, TYPE_PROPERTY_NAN, TYPE_PROPERTY_INNER, TYPE_PROPERTY_KIND, TYPE_PROPERTY_NAMES, + TYPE_PROPERTY_PARAMS, + TYPE_PROPERTY_RETURNS, TYPE_PROPERTY_SIZEOF, TYPE_PROPERTY_VALUES, TYPE_PROPERTY_NONE, diff --git a/src/compiler/expr.c b/src/compiler/expr.c index 702b4d8ce..787375c47 100644 --- a/src/compiler/expr.c +++ b/src/compiler/expr.c @@ -825,6 +825,18 @@ Expr *expr_new_const_int(SourceSpan span, Type *type, uint64_t v, bool narrowabl return expr; } +Expr *expr_new_const_typeid(SourceSpan span, Type *type) +{ + Expr *expr = expr_calloc(); + expr->expr_kind = EXPR_CONST; + expr->span = span; + expr->type = type_typeid; + expr->const_expr.const_kind = CONST_TYPEID; + expr->const_expr.typeid = type; + expr->resolve_status = RESOLVE_DONE; + return expr; +} + Expr *expr_new_const_bool(SourceSpan span, Type *type, bool value) { Expr *expr = expr_calloc(); diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index d4642054a..2f37a817a 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -171,6 +171,8 @@ static inline bool sema_create_const_len(SemaContext *context, Expr *expr, Type static inline bool sema_create_const_inner(SemaContext *context, Expr *expr, Type *type); static inline bool sema_create_const_min(SemaContext *context, Expr *expr, Type *type, Type *flat); static inline bool sema_create_const_max(SemaContext *context, Expr *expr, Type *type, Type *flat); +static inline bool sema_create_const_params(SemaContext *context, Expr *expr, Type *type); +static inline bool sema_create_const_membersof(SemaContext *context, Expr *expr, Type *type); void expr_insert_widening_type(Expr *expr, Type *infer_type); static Expr *expr_access_inline_member(Expr *parent, Decl *parent_decl); @@ -2853,10 +2855,7 @@ static inline bool sema_create_const_inner(SemaContext *context, Expr *expr, Typ default: return false; } - expr->expr_kind = EXPR_CONST; - expr->const_expr.const_kind = CONST_TYPEID; - expr->const_expr.typeid = inner->canonical; - expr->type = type_typeid; + expr_rewrite_const_typeid(expr, inner); return true; } @@ -2922,6 +2921,50 @@ static inline bool sema_create_const_min(SemaContext *context, Expr *expr, Type return false; } +static inline bool sema_create_const_params(SemaContext *context, Expr *expr, Type *type) +{ + if (type->type_kind != TYPE_POINTER || type->pointer->type_kind != TYPE_FUNC) return false; + type = type->pointer; + Signature *sig = type->function.signature; + unsigned params = vec_size(sig->params); + Expr **param_exprs = params ? VECNEW(Expr*, params) : NULL; + for (unsigned i = 0; i < params; i++) + { + Decl *decl = sig->params[i]; + Expr *expr_element = expr_new_const_typeid(expr->span, decl->type->canonical); + vec_add(param_exprs, expr_element); + } + expr_rewrite_const_untyped_list(expr, param_exprs); + return true; +} + +static inline bool sema_create_const_membersof(SemaContext *context, Expr *expr, Type *type) +{ + Decl **members = NULL; + if (type_is_union_or_strukt(type)) + { + members = type->decl->strukt.members; + } + else if (type->type_kind == TYPE_BITSTRUCT) + { + members = type->decl->bitstruct.members; + } + else + { + return false; + } + unsigned count = vec_size(members); + Expr **member_exprs = count ? VECNEW(Expr*, count) : NULL; + for (unsigned i = 0; i < count; i++) + { + Decl *decl = members[i]; + Expr *expr_element = expr_new_const_typeid(expr->span, decl->type->canonical); + vec_add(member_exprs, expr_element); + } + expr_rewrite_const_untyped_list(expr, member_exprs); + return true; +} + static inline bool sema_create_const_max(SemaContext *context, Expr *expr, Type *type, Type *flat) { if (type_is_integer(flat)) @@ -3032,6 +3075,9 @@ static bool sema_expr_rewrite_to_typeid_property(SemaContext *context, Expr *exp case TYPE_PROPERTY_NAN: case TYPE_PROPERTY_ELEMENTS: case TYPE_PROPERTY_VALUES: + case TYPE_PROPERTY_RETURNS: + case TYPE_PROPERTY_PARAMS: + case TYPE_PROPERTY_MEMBERSOF: // Not supported by dynamic typeid case TYPE_PROPERTY_NONE: return false; @@ -3142,6 +3188,15 @@ static bool sema_expr_rewrite_to_type_property(SemaContext *context, Expr *expr, expr->type = type; expr->resolve_status = RESOLVE_DONE; return true; + case TYPE_PROPERTY_MEMBERSOF: + return sema_create_const_membersof(context, expr, flat); + case TYPE_PROPERTY_PARAMS: + return sema_create_const_params(context, expr, flat); + case TYPE_PROPERTY_RETURNS: + if (flat->type_kind != TYPE_POINTER || flat->pointer->type_kind != TYPE_FUNC) return false; + flat = flat->pointer; + expr_rewrite_const_typeid(expr, type_infoptr(flat->function.signature->rtype)->type); + return true; case TYPE_PROPERTY_SIZEOF: expr_rewrite_const_int(expr, type_usize, type_size(type), true); return true; diff --git a/src/compiler/symtab.c b/src/compiler/symtab.c index a8877dfc3..88c39bf28 100644 --- a/src/compiler/symtab.c +++ b/src/compiler/symtab.c @@ -167,7 +167,10 @@ void symtab_init(uint32_t capacity) type_property_list[TYPE_PROPERTY_NAMES] = KW_DEF("names"); type_property_list[TYPE_PROPERTY_INNER] = KW_DEF("inner"); type_property_list[TYPE_PROPERTY_KIND] = KW_DEF("kind"); + type_property_list[TYPE_PROPERTY_MEMBERSOF] = KW_DEF("membersof"); type_property_list[TYPE_PROPERTY_INF] = KW_DEF("inf"); + type_property_list[TYPE_PROPERTY_PARAMS] = KW_DEF("params"); + type_property_list[TYPE_PROPERTY_RETURNS] = KW_DEF("returns"); type_property_list[TYPE_PROPERTY_SIZEOF] = KW_DEF("sizeof"); type_property_list[TYPE_PROPERTY_VALUES] = KW_DEF("values"); diff --git a/src/version.h b/src/version.h index c56c1ee64..3d48441a0 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define COMPILER_VERSION "0.3.71" \ No newline at end of file +#define COMPILER_VERSION "0.3.72" \ No newline at end of file diff --git a/test/test_suite/compile_time/ct_memberof.c3t b/test/test_suite/compile_time/ct_memberof.c3t new file mode 100644 index 000000000..624737fd5 --- /dev/null +++ b/test/test_suite/compile_time/ct_memberof.c3t @@ -0,0 +1,371 @@ +// #target: macos-x64 +module test; +import std::io; + +fn int hell() { return 1; } + +macro print_args($Type) +{ + var $params = $Type.params; + $foreach ($param : $params): + io::println($nameof($typefrom($param))); + $endforeach +} + +bitstruct Bar : ulong +{ + int x : 1..4; + short y : 6..10; +} + +struct Foo +{ + int x; + union test { + int y; + double z; + } + struct { + int abc; + int bcd; + } + double q; +} +macro print_fields($Type) +{ + io::printfln("Type: %s", $nameof($Type)); + var $params = $Type.membersof; + $foreach ($param : $params): + io::printfln("Member: %s", $nameof($typefrom($param))); + $endforeach +} + +fn void hello(int a, double b, int[4] d, args...) {} +fn void test(int x) +{ + print_args($typeof(&test)); + print_args($typeof(&hell)); + print_args($typeof(&hello)); + io::println($nameof($typefrom($typeof(&test).returns))); + io::println($nameof($typefrom($typeof(&hell).returns))); + print_fields(Foo); + print_fields(Bar); +} + +fn void main() +{ + test(10); +} + +/* #expect: test.ll + +; Function Attrs: nounwind +define void @test_hello(i32 %0, double %1, i64 %2, i64 %3, i8* %4, i64 %5) #0 { +entry: + %d = alloca [4 x i32], align 4 + %args = alloca %"variant[]", align 8 + %pair = bitcast [4 x i32]* %d to { i64, i64 }* + %6 = getelementptr inbounds { i64, i64 }, { i64, i64 }* %pair, i32 0, i32 0 + store i64 %2, i64* %6, align 4 + %7 = getelementptr inbounds { i64, i64 }, { i64, i64 }* %pair, i32 0, i32 1 + store i64 %3, i64* %7, align 4 + %pair1 = bitcast %"variant[]"* %args to { i8*, i64 }* + %8 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %pair1, i32 0, i32 0 + store i8* %4, i8** %8, align 8 + %9 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %pair1, i32 0, i32 1 + store i64 %5, i64* %9, align 8 + ret void +} + +; Function Attrs: nounwind +define void @test_test(i32 %0) #0 { +entry: + %retparam = alloca i64, align 8 + %taddr = alloca %"char[]", align 8 + %vararg = alloca %"variant[]", align 8 + %varargslots = alloca [1 x %variant], align 16 + %taddr1 = alloca [3 x i8]*, align 8 + %retparam4 = alloca i64, align 8 + %taddr5 = alloca %"char[]", align 8 + %vararg8 = alloca %"variant[]", align 8 + %varargslots9 = alloca [1 x %variant], align 16 + %taddr10 = alloca [3 x i8]*, align 8 + %retparam16 = alloca i64, align 8 + %taddr17 = alloca %"char[]", align 8 + %vararg20 = alloca %"variant[]", align 8 + %varargslots21 = alloca [1 x %variant], align 16 + %taddr22 = alloca [4 x i8]*, align 8 + %retparam28 = alloca i64, align 8 + %taddr29 = alloca %"char[]", align 8 + %vararg32 = alloca %"variant[]", align 8 + %varargslots33 = alloca [1 x %variant], align 16 + %taddr34 = alloca [5 x i8]*, align 8 + %retparam40 = alloca i64, align 8 + %taddr41 = alloca %"char[]", align 8 + %vararg44 = alloca %"variant[]", align 8 + %varargslots45 = alloca [1 x %variant], align 16 + %taddr46 = alloca [6 x i8]*, align 8 + %retparam52 = alloca i64, align 8 + %taddr53 = alloca %"char[]", align 8 + %vararg56 = alloca %"variant[]", align 8 + %varargslots57 = alloca [1 x %variant], align 16 + %taddr58 = alloca [3 x i8]*, align 8 + %retparam64 = alloca i64, align 8 + %taddr65 = alloca %"char[]", align 8 + %vararg68 = alloca %"variant[]", align 8 + %varargslots69 = alloca [1 x %variant], align 16 + %taddr70 = alloca [3 x i8]*, align 8 + %retparam76 = alloca i64, align 8 + %taddr77 = alloca %"char[]", align 8 + %vararg80 = alloca %"variant[]", align 8 + %varargslots81 = alloca [1 x %variant], align 16 + %taddr82 = alloca [5 x i8]*, align 8 + %1 = call i32 @std_io_println(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i32 0, i32 0)) #1 + %2 = call i32 @std_io_println(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.3, i32 0, i32 0)) #1 + %3 = call i32 @std_io_println(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.4, i32 0, i32 0)) #1 + %4 = call i32 @std_io_println(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.5, i32 0, i32 0)) #1 + %5 = call i32 @std_io_println(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str.6, i32 0, i32 0)) #1 + %6 = call i32 @std_io_println(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str.7, i32 0, i32 0)) #1 + %7 = call i32 @std_io_println(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.8, i32 0, i32 0)) #1 + store %"char[]" { i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.9, i32 0, i32 0), i64 8 }, %"char[]"* %taddr, align 8 + %8 = bitcast %"char[]"* %taddr to { i8*, i64 }* + %9 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %8, i32 0, i32 0 + %lo = load i8*, i8** %9, align 8 + %10 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %8, i32 0, i32 1 + %hi = load i64, i64* %10, align 8 + store [3 x i8]* bitcast ([4 x i8]* @.str.10 to [3 x i8]*), [3 x i8]** %taddr1, align 8 + %11 = bitcast [3 x i8]** %taddr1 to i8* + %12 = insertvalue %variant undef, i8* %11, 0 + %13 = insertvalue %variant %12, i64 ptrtoint (%.introspect* @"ct$p$a3$char" to i64), 1 + %14 = getelementptr inbounds [1 x %variant], [1 x %variant]* %varargslots, i64 0, i64 0 + store %variant %13, %variant* %14, align 16 + %15 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg, i32 0, i32 1 + store i64 1, i64* %15, align 8 + %16 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg, i32 0, i32 0 + %17 = bitcast [1 x %variant]* %varargslots to %variant* + store %variant* %17, %variant** %16, align 8 + %18 = bitcast %"variant[]"* %vararg to { i8*, i64 }* + %19 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %18, i32 0, i32 0 + %lo2 = load i8*, i8** %19, align 8 + %20 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %18, i32 0, i32 1 + %hi3 = load i64, i64* %20, align 8 + %21 = call i64 @std_io_printfln(i64* %retparam, i8* %lo, i64 %hi, i8* %lo2, i64 %hi3) + %not_err = icmp eq i64 %21, 0 + br i1 %not_err, label %after_check, label %voiderr + +after_check: ; preds = %entry + br label %voiderr + +voiderr: ; preds = %after_check, %entry + store %"char[]" { i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.11, i32 0, i32 0), i64 10 }, %"char[]"* %taddr5, align 8 + %22 = bitcast %"char[]"* %taddr5 to { i8*, i64 }* + %23 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %22, i32 0, i32 0 + %lo6 = load i8*, i8** %23, align 8 + %24 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %22, i32 0, i32 1 + %hi7 = load i64, i64* %24, align 8 + store [3 x i8]* bitcast ([4 x i8]* @.str.12 to [3 x i8]*), [3 x i8]** %taddr10, align 8 + %25 = bitcast [3 x i8]** %taddr10 to i8* + %26 = insertvalue %variant undef, i8* %25, 0 + %27 = insertvalue %variant %26, i64 ptrtoint (%.introspect* @"ct$p$a3$char" to i64), 1 + %28 = getelementptr inbounds [1 x %variant], [1 x %variant]* %varargslots9, i64 0, i64 0 + store %variant %27, %variant* %28, align 16 + %29 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg8, i32 0, i32 1 + store i64 1, i64* %29, align 8 + %30 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg8, i32 0, i32 0 + %31 = bitcast [1 x %variant]* %varargslots9 to %variant* + store %variant* %31, %variant** %30, align 8 + %32 = bitcast %"variant[]"* %vararg8 to { i8*, i64 }* + %33 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %32, i32 0, i32 0 + %lo11 = load i8*, i8** %33, align 8 + %34 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %32, i32 0, i32 1 + %hi12 = load i64, i64* %34, align 8 + %35 = call i64 @std_io_printfln(i64* %retparam4, i8* %lo6, i64 %hi7, i8* %lo11, i64 %hi12) + %not_err13 = icmp eq i64 %35, 0 + br i1 %not_err13, label %after_check14, label %voiderr15 + +after_check14: ; preds = %voiderr + br label %voiderr15 + +voiderr15: ; preds = %after_check14, %voiderr + store %"char[]" { i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.13, i32 0, i32 0), i64 10 }, %"char[]"* %taddr17, align 8 + %36 = bitcast %"char[]"* %taddr17 to { i8*, i64 }* + %37 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %36, i32 0, i32 0 + %lo18 = load i8*, i8** %37, align 8 + %38 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %36, i32 0, i32 1 + %hi19 = load i64, i64* %38, align 8 + store [4 x i8]* bitcast ([5 x i8]* @.str.14 to [4 x i8]*), [4 x i8]** %taddr22, align 8 + %39 = bitcast [4 x i8]** %taddr22 to i8* + %40 = insertvalue %variant undef, i8* %39, 0 + %41 = insertvalue %variant %40, i64 ptrtoint (%.introspect* @"ct$p$a4$char" to i64), 1 + %42 = getelementptr inbounds [1 x %variant], [1 x %variant]* %varargslots21, i64 0, i64 0 + store %variant %41, %variant* %42, align 16 + %43 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg20, i32 0, i32 1 + store i64 1, i64* %43, align 8 + %44 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg20, i32 0, i32 0 + %45 = bitcast [1 x %variant]* %varargslots21 to %variant* + store %variant* %45, %variant** %44, align 8 + %46 = bitcast %"variant[]"* %vararg20 to { i8*, i64 }* + %47 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %46, i32 0, i32 0 + %lo23 = load i8*, i8** %47, align 8 + %48 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %46, i32 0, i32 1 + %hi24 = load i64, i64* %48, align 8 + %49 = call i64 @std_io_printfln(i64* %retparam16, i8* %lo18, i64 %hi19, i8* %lo23, i64 %hi24) + %not_err25 = icmp eq i64 %49, 0 + br i1 %not_err25, label %after_check26, label %voiderr27 + +after_check26: ; preds = %voiderr15 + br label %voiderr27 + +voiderr27: ; preds = %after_check26, %voiderr15 + store %"char[]" { i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.15, i32 0, i32 0), i64 10 }, %"char[]"* %taddr29, align 8 + %50 = bitcast %"char[]"* %taddr29 to { i8*, i64 }* + %51 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %50, i32 0, i32 0 + %lo30 = load i8*, i8** %51, align 8 + %52 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %50, i32 0, i32 1 + %hi31 = load i64, i64* %52, align 8 + store [5 x i8]* bitcast ([6 x i8]* @.str.16 to [5 x i8]*), [5 x i8]** %taddr34, align 8 + %53 = bitcast [5 x i8]** %taddr34 to i8* + %54 = insertvalue %variant undef, i8* %53, 0 + %55 = insertvalue %variant %54, i64 ptrtoint (%.introspect* @"ct$p$a5$char" to i64), 1 + %56 = getelementptr inbounds [1 x %variant], [1 x %variant]* %varargslots33, i64 0, i64 0 + store %variant %55, %variant* %56, align 16 + %57 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg32, i32 0, i32 1 + store i64 1, i64* %57, align 8 + %58 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg32, i32 0, i32 0 + %59 = bitcast [1 x %variant]* %varargslots33 to %variant* + store %variant* %59, %variant** %58, align 8 + %60 = bitcast %"variant[]"* %vararg32 to { i8*, i64 }* + %61 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %60, i32 0, i32 0 + %lo35 = load i8*, i8** %61, align 8 + %62 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %60, i32 0, i32 1 + %hi36 = load i64, i64* %62, align 8 + %63 = call i64 @std_io_printfln(i64* %retparam28, i8* %lo30, i64 %hi31, i8* %lo35, i64 %hi36) + %not_err37 = icmp eq i64 %63, 0 + br i1 %not_err37, label %after_check38, label %voiderr39 + +after_check38: ; preds = %voiderr27 + br label %voiderr39 + +voiderr39: ; preds = %after_check38, %voiderr27 + store %"char[]" { i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.17, i32 0, i32 0), i64 10 }, %"char[]"* %taddr41, align 8 + %64 = bitcast %"char[]"* %taddr41 to { i8*, i64 }* + %65 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %64, i32 0, i32 0 + %lo42 = load i8*, i8** %65, align 8 + %66 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %64, i32 0, i32 1 + %hi43 = load i64, i64* %66, align 8 + store [6 x i8]* bitcast ([7 x i8]* @.str.18 to [6 x i8]*), [6 x i8]** %taddr46, align 8 + %67 = bitcast [6 x i8]** %taddr46 to i8* + %68 = insertvalue %variant undef, i8* %67, 0 + %69 = insertvalue %variant %68, i64 ptrtoint (%.introspect* @"ct$p$a6$char" to i64), 1 + %70 = getelementptr inbounds [1 x %variant], [1 x %variant]* %varargslots45, i64 0, i64 0 + store %variant %69, %variant* %70, align 16 + %71 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg44, i32 0, i32 1 + store i64 1, i64* %71, align 8 + %72 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg44, i32 0, i32 0 + %73 = bitcast [1 x %variant]* %varargslots45 to %variant* + store %variant* %73, %variant** %72, align 8 + %74 = bitcast %"variant[]"* %vararg44 to { i8*, i64 }* + %75 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %74, i32 0, i32 0 + %lo47 = load i8*, i8** %75, align 8 + %76 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %74, i32 0, i32 1 + %hi48 = load i64, i64* %76, align 8 + %77 = call i64 @std_io_printfln(i64* %retparam40, i8* %lo42, i64 %hi43, i8* %lo47, i64 %hi48) + %not_err49 = icmp eq i64 %77, 0 + br i1 %not_err49, label %after_check50, label %voiderr51 + +after_check50: ; preds = %voiderr39 + br label %voiderr51 + +voiderr51: ; preds = %after_check50, %voiderr39 + store %"char[]" { i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.19, i32 0, i32 0), i64 8 }, %"char[]"* %taddr53, align 8 + %78 = bitcast %"char[]"* %taddr53 to { i8*, i64 }* + %79 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %78, i32 0, i32 0 + %lo54 = load i8*, i8** %79, align 8 + %80 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %78, i32 0, i32 1 + %hi55 = load i64, i64* %80, align 8 + store [3 x i8]* bitcast ([4 x i8]* @.str.20 to [3 x i8]*), [3 x i8]** %taddr58, align 8 + %81 = bitcast [3 x i8]** %taddr58 to i8* + %82 = insertvalue %variant undef, i8* %81, 0 + %83 = insertvalue %variant %82, i64 ptrtoint (%.introspect* @"ct$p$a3$char" to i64), 1 + %84 = getelementptr inbounds [1 x %variant], [1 x %variant]* %varargslots57, i64 0, i64 0 + store %variant %83, %variant* %84, align 16 + %85 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg56, i32 0, i32 1 + store i64 1, i64* %85, align 8 + %86 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg56, i32 0, i32 0 + %87 = bitcast [1 x %variant]* %varargslots57 to %variant* + store %variant* %87, %variant** %86, align 8 + %88 = bitcast %"variant[]"* %vararg56 to { i8*, i64 }* + %89 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %88, i32 0, i32 0 + %lo59 = load i8*, i8** %89, align 8 + %90 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %88, i32 0, i32 1 + %hi60 = load i64, i64* %90, align 8 + %91 = call i64 @std_io_printfln(i64* %retparam52, i8* %lo54, i64 %hi55, i8* %lo59, i64 %hi60) + %not_err61 = icmp eq i64 %91, 0 + br i1 %not_err61, label %after_check62, label %voiderr63 + +after_check62: ; preds = %voiderr51 + br label %voiderr63 + +voiderr63: ; preds = %after_check62, %voiderr51 + store %"char[]" { i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.21, i32 0, i32 0), i64 10 }, %"char[]"* %taddr65, align 8 + %92 = bitcast %"char[]"* %taddr65 to { i8*, i64 }* + %93 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %92, i32 0, i32 0 + %lo66 = load i8*, i8** %93, align 8 + %94 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %92, i32 0, i32 1 + %hi67 = load i64, i64* %94, align 8 + store [3 x i8]* bitcast ([4 x i8]* @.str.22 to [3 x i8]*), [3 x i8]** %taddr70, align 8 + %95 = bitcast [3 x i8]** %taddr70 to i8* + %96 = insertvalue %variant undef, i8* %95, 0 + %97 = insertvalue %variant %96, i64 ptrtoint (%.introspect* @"ct$p$a3$char" to i64), 1 + %98 = getelementptr inbounds [1 x %variant], [1 x %variant]* %varargslots69, i64 0, i64 0 + store %variant %97, %variant* %98, align 16 + %99 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg68, i32 0, i32 1 + store i64 1, i64* %99, align 8 + %100 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg68, i32 0, i32 0 + %101 = bitcast [1 x %variant]* %varargslots69 to %variant* + store %variant* %101, %variant** %100, align 8 + %102 = bitcast %"variant[]"* %vararg68 to { i8*, i64 }* + %103 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %102, i32 0, i32 0 + %lo71 = load i8*, i8** %103, align 8 + %104 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %102, i32 0, i32 1 + %hi72 = load i64, i64* %104, align 8 + %105 = call i64 @std_io_printfln(i64* %retparam64, i8* %lo66, i64 %hi67, i8* %lo71, i64 %hi72) + %not_err73 = icmp eq i64 %105, 0 + br i1 %not_err73, label %after_check74, label %voiderr75 + +after_check74: ; preds = %voiderr63 + br label %voiderr75 + +voiderr75: ; preds = %after_check74, %voiderr63 + store %"char[]" { i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.23, i32 0, i32 0), i64 10 }, %"char[]"* %taddr77, align 8 + %106 = bitcast %"char[]"* %taddr77 to { i8*, i64 }* + %107 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %106, i32 0, i32 0 + %lo78 = load i8*, i8** %107, align 8 + %108 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %106, i32 0, i32 1 + %hi79 = load i64, i64* %108, align 8 + store [5 x i8]* bitcast ([6 x i8]* @.str.24 to [5 x i8]*), [5 x i8]** %taddr82, align 8 + %109 = bitcast [5 x i8]** %taddr82 to i8* + %110 = insertvalue %variant undef, i8* %109, 0 + %111 = insertvalue %variant %110, i64 ptrtoint (%.introspect* @"ct$p$a5$char" to i64), 1 + %112 = getelementptr inbounds [1 x %variant], [1 x %variant]* %varargslots81, i64 0, i64 0 + store %variant %111, %variant* %112, align 16 + %113 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg80, i32 0, i32 1 + store i64 1, i64* %113, align 8 + %114 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg80, i32 0, i32 0 + %115 = bitcast [1 x %variant]* %varargslots81 to %variant* + store %variant* %115, %variant** %114, align 8 + %116 = bitcast %"variant[]"* %vararg80 to { i8*, i64 }* + %117 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %116, i32 0, i32 0 + %lo83 = load i8*, i8** %117, align 8 + %118 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %116, i32 0, i32 1 + %hi84 = load i64, i64* %118, align 8 + %119 = call i64 @std_io_printfln(i64* %retparam76, i8* %lo78, i64 %hi79, i8* %lo83, i64 %hi84) + %not_err85 = icmp eq i64 %119, 0 + br i1 %not_err85, label %after_check86, label %voiderr87 + +after_check86: ; preds = %voiderr75 + br label %voiderr87 + +voiderr87: ; preds = %after_check86, %voiderr75 + ret void +} diff --git a/test/test_suite2/compile_time/ct_memberof.c3t b/test/test_suite2/compile_time/ct_memberof.c3t new file mode 100644 index 000000000..7e6dcbb8d --- /dev/null +++ b/test/test_suite2/compile_time/ct_memberof.c3t @@ -0,0 +1,319 @@ +// #target: macos-x64 +module test; +import std::io; + +fn int hell() { return 1; } + +macro print_args($Type) +{ + var $params = $Type.params; + $foreach ($param : $params): + io::println($nameof($typefrom($param))); + $endforeach +} + +bitstruct Bar : ulong +{ + int x : 1..4; + short y : 6..10; +} + +struct Foo +{ + int x; + union test { + int y; + double z; + } + struct { + int abc; + int bcd; + } + double q; +} +macro print_fields($Type) +{ + io::printfln("Type: %s", $nameof($Type)); + var $params = $Type.membersof; + $foreach ($param : $params): + io::printfln("Member: %s", $nameof($typefrom($param))); + $endforeach +} + +fn void hello(int a, double b, int[4] d, args...) {} +fn void test(int x) +{ + print_args($typeof(&test)); + print_args($typeof(&hell)); + print_args($typeof(&hello)); + io::println($nameof($typefrom($typeof(&test).returns))); + io::println($nameof($typefrom($typeof(&hell).returns))); + print_fields(Foo); + print_fields(Bar); +} + +fn void main() +{ + test(10); +} + +/* #expect: test.ll + +define void @test_hello(i32 %0, double %1, i64 %2, i64 %3, ptr %4, i64 %5) #0 { +entry: + %d = alloca [4 x i32], align 4 + %args = alloca %"variant[]", align 8 + %6 = getelementptr inbounds { i64, i64 }, ptr %d, i32 0, i32 0 + store i64 %2, ptr %6, align 4 + %7 = getelementptr inbounds { i64, i64 }, ptr %d, i32 0, i32 1 + store i64 %3, ptr %7, align 4 + %8 = getelementptr inbounds { ptr, i64 }, ptr %args, i32 0, i32 0 + store ptr %4, ptr %8, align 8 + %9 = getelementptr inbounds { ptr, i64 }, ptr %args, i32 0, i32 1 + store i64 %5, ptr %9, align 8 + ret void +} +; Function Attrs: nounwind +define void @test_test(i32 %0) #0 { +entry: + %retparam = alloca i64, align 8 + %taddr = alloca %"char[]", align 8 + %vararg = alloca %"variant[]", align 8 + %varargslots = alloca [1 x %variant], align 16 + %taddr1 = alloca ptr, align 8 + %retparam4 = alloca i64, align 8 + %taddr5 = alloca %"char[]", align 8 + %vararg8 = alloca %"variant[]", align 8 + %varargslots9 = alloca [1 x %variant], align 16 + %taddr10 = alloca ptr, align 8 + %retparam16 = alloca i64, align 8 + %taddr17 = alloca %"char[]", align 8 + %vararg20 = alloca %"variant[]", align 8 + %varargslots21 = alloca [1 x %variant], align 16 + %taddr22 = alloca ptr, align 8 + %retparam28 = alloca i64, align 8 + %taddr29 = alloca %"char[]", align 8 + %vararg32 = alloca %"variant[]", align 8 + %varargslots33 = alloca [1 x %variant], align 16 + %taddr34 = alloca ptr, align 8 + %retparam40 = alloca i64, align 8 + %taddr41 = alloca %"char[]", align 8 + %vararg44 = alloca %"variant[]", align 8 + %varargslots45 = alloca [1 x %variant], align 16 + %taddr46 = alloca ptr, align 8 + %retparam52 = alloca i64, align 8 + %taddr53 = alloca %"char[]", align 8 + %vararg56 = alloca %"variant[]", align 8 + %varargslots57 = alloca [1 x %variant], align 16 + %taddr58 = alloca ptr, align 8 + %retparam64 = alloca i64, align 8 + %taddr65 = alloca %"char[]", align 8 + %vararg68 = alloca %"variant[]", align 8 + %varargslots69 = alloca [1 x %variant], align 16 + %taddr70 = alloca ptr, align 8 + %retparam76 = alloca i64, align 8 + %taddr77 = alloca %"char[]", align 8 + %vararg80 = alloca %"variant[]", align 8 + %varargslots81 = alloca [1 x %variant], align 16 + %taddr82 = alloca ptr, align 8 + %1 = call i32 @std_io_println(ptr @.str) #1 + %2 = call i32 @std_io_println(ptr @.str.3) #1 + %3 = call i32 @std_io_println(ptr @.str.4) #1 + %4 = call i32 @std_io_println(ptr @.str.5) #1 + %5 = call i32 @std_io_println(ptr @.str.6) #1 + %6 = call i32 @std_io_println(ptr @.str.7) #1 + %7 = call i32 @std_io_println(ptr @.str.8) #1 + store %"char[]" { ptr @.str.9, i64 8 }, ptr %taddr, align 8 + %8 = getelementptr inbounds { ptr, i64 }, ptr %taddr, i32 0, i32 0 + %lo = load ptr, ptr %8, align 8 + %9 = getelementptr inbounds { ptr, i64 }, ptr %taddr, i32 0, i32 1 + %hi = load i64, ptr %9, align 8 + store ptr @.str.10, ptr %taddr1, align 8 + %10 = insertvalue %variant undef, ptr %taddr1, 0 + %11 = insertvalue %variant %10, i64 ptrtoint (ptr @"ct$p$a3$char" to i64), 1 + %12 = getelementptr inbounds [1 x %variant], ptr %varargslots, i64 0, i64 0 + store %variant %11, ptr %12, align 16 + %13 = getelementptr inbounds %"variant[]", ptr %vararg, i32 0, i32 1 + store i64 1, 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 + %lo2 = load ptr, ptr %15, align 8 + %16 = getelementptr inbounds { ptr, i64 }, ptr %vararg, i32 0, i32 1 + %hi3 = load i64, ptr %16, align 8 + %17 = call i64 @std_io_printfln(ptr %retparam, ptr %lo, i64 %hi, ptr %lo2, i64 %hi3) + %not_err = icmp eq i64 %17, 0 + br i1 %not_err, label %after_check, label %voiderr +after_check: ; preds = %entry + br label %voiderr +voiderr: ; preds = %after_check, %entry + store %"char[]" { ptr @.str.11, i64 10 }, ptr %taddr5, align 8 + %18 = getelementptr inbounds { ptr, i64 }, ptr %taddr5, i32 0, i32 0 + %lo6 = load ptr, ptr %18, align 8 + %19 = getelementptr inbounds { ptr, i64 }, ptr %taddr5, i32 0, i32 1 + %hi7 = load i64, ptr %19, align 8 + store ptr @.str.12, ptr %taddr10, align 8 + %20 = insertvalue %variant undef, ptr %taddr10, 0 + %21 = insertvalue %variant %20, i64 ptrtoint (ptr @"ct$p$a3$char" to i64), 1 + %22 = getelementptr inbounds [1 x %variant], ptr %varargslots9, i64 0, i64 0 + store %variant %21, ptr %22, align 16 + %23 = getelementptr inbounds %"variant[]", ptr %vararg8, i32 0, i32 1 + store i64 1, ptr %23, align 8 + %24 = getelementptr inbounds %"variant[]", ptr %vararg8, i32 0, i32 0 + store ptr %varargslots9, ptr %24, align 8 + %25 = getelementptr inbounds { ptr, i64 }, ptr %vararg8, i32 0, i32 0 + %lo11 = load ptr, ptr %25, align 8 + %26 = getelementptr inbounds { ptr, i64 }, ptr %vararg8, i32 0, i32 1 + %hi12 = load i64, ptr %26, align 8 + %27 = call i64 @std_io_printfln(ptr %retparam4, ptr %lo6, i64 %hi7, ptr %lo11, i64 %hi12) + %not_err13 = icmp eq i64 %27, 0 + br i1 %not_err13, label %after_check14, label %voiderr15 +after_check14: ; preds = %voiderr + br label %voiderr15 +voiderr15: ; preds = %after_check14, %voiderr + store %"char[]" { ptr @.str.13, i64 10 }, ptr %taddr17, align 8 + %28 = getelementptr inbounds { ptr, i64 }, ptr %taddr17, i32 0, i32 0 + %lo18 = load ptr, ptr %28, align 8 + %29 = getelementptr inbounds { ptr, i64 }, ptr %taddr17, i32 0, i32 1 + %hi19 = load i64, ptr %29, align 8 + store ptr @.str.14, ptr %taddr22, align 8 + %30 = insertvalue %variant undef, ptr %taddr22, 0 + %31 = insertvalue %variant %30, i64 ptrtoint (ptr @"ct$p$a4$char" to i64), 1 + %32 = getelementptr inbounds [1 x %variant], ptr %varargslots21, i64 0, i64 0 + store %variant %31, ptr %32, align 16 + %33 = getelementptr inbounds %"variant[]", ptr %vararg20, i32 0, i32 1 + store i64 1, ptr %33, align 8 + %34 = getelementptr inbounds %"variant[]", ptr %vararg20, i32 0, i32 0 + store ptr %varargslots21, ptr %34, align 8 + %35 = getelementptr inbounds { ptr, i64 }, ptr %vararg20, i32 0, i32 0 + %lo23 = load ptr, ptr %35, align 8 + %36 = getelementptr inbounds { ptr, i64 }, ptr %vararg20, i32 0, i32 1 + %hi24 = load i64, ptr %36, align 8 + %37 = call i64 @std_io_printfln(ptr %retparam16, ptr %lo18, i64 %hi19, ptr %lo23, i64 %hi24) + %not_err25 = icmp eq i64 %37, 0 + br i1 %not_err25, label %after_check26, label %voiderr27 +after_check26: ; preds = %voiderr15 + br label %voiderr27 +voiderr27: ; preds = %after_check26, %voiderr15 + store %"char[]" { ptr @.str.15, i64 10 }, ptr %taddr29, align 8 + %38 = getelementptr inbounds { ptr, i64 }, ptr %taddr29, i32 0, i32 0 + %lo30 = load ptr, ptr %38, align 8 + %39 = getelementptr inbounds { ptr, i64 }, ptr %taddr29, i32 0, i32 1 + %hi31 = load i64, ptr %39, align 8 + store ptr @.str.16, ptr %taddr34, align 8 + %40 = insertvalue %variant undef, ptr %taddr34, 0 + %41 = insertvalue %variant %40, i64 ptrtoint (ptr @"ct$p$a5$char" to i64), 1 + %42 = getelementptr inbounds [1 x %variant], ptr %varargslots33, i64 0, i64 0 + store %variant %41, ptr %42, align 16 + %43 = getelementptr inbounds %"variant[]", ptr %vararg32, i32 0, i32 1 + store i64 1, ptr %43, align 8 + %44 = getelementptr inbounds %"variant[]", ptr %vararg32, i32 0, i32 0 + store ptr %varargslots33, ptr %44, align 8 + %45 = getelementptr inbounds { ptr, i64 }, ptr %vararg32, i32 0, i32 0 + %lo35 = load ptr, ptr %45, align 8 + %46 = getelementptr inbounds { ptr, i64 }, ptr %vararg32, i32 0, i32 1 + %hi36 = load i64, ptr %46, align 8 + %47 = call i64 @std_io_printfln(ptr %retparam28, ptr %lo30, i64 %hi31, ptr %lo35, i64 %hi36) + %not_err37 = icmp eq i64 %47, 0 + br i1 %not_err37, label %after_check38, label %voiderr39 +after_check38: ; preds = %voiderr27 + br label %voiderr39 +voiderr39: ; preds = %after_check38, %voiderr27 + store %"char[]" { ptr @.str.17, i64 10 }, ptr %taddr41, align 8 + %48 = getelementptr inbounds { ptr, i64 }, ptr %taddr41, i32 0, i32 0 + %lo42 = load ptr, ptr %48, align 8 + %49 = getelementptr inbounds { ptr, i64 }, ptr %taddr41, i32 0, i32 1 + %hi43 = load i64, ptr %49, align 8 + store ptr @.str.18, ptr %taddr46, align 8 + %50 = insertvalue %variant undef, ptr %taddr46, 0 + %51 = insertvalue %variant %50, i64 ptrtoint (ptr @"ct$p$a6$char" to i64), 1 + %52 = getelementptr inbounds [1 x %variant], ptr %varargslots45, i64 0, i64 0 + store %variant %51, ptr %52, align 16 + %53 = getelementptr inbounds %"variant[]", ptr %vararg44, i32 0, i32 1 + store i64 1, ptr %53, align 8 + %54 = getelementptr inbounds %"variant[]", ptr %vararg44, i32 0, i32 0 + store ptr %varargslots45, ptr %54, align 8 + %55 = getelementptr inbounds { ptr, i64 }, ptr %vararg44, i32 0, i32 0 + %lo47 = load ptr, ptr %55, align 8 + %56 = getelementptr inbounds { ptr, i64 }, ptr %vararg44, i32 0, i32 1 + %hi48 = load i64, ptr %56, align 8 + %57 = call i64 @std_io_printfln(ptr %retparam40, ptr %lo42, i64 %hi43, ptr %lo47, i64 %hi48) + %not_err49 = icmp eq i64 %57, 0 + br i1 %not_err49, label %after_check50, label %voiderr51 +after_check50: ; preds = %voiderr39 + br label %voiderr51 +voiderr51: ; preds = %after_check50, %voiderr39 + store %"char[]" { ptr @.str.19, i64 8 }, ptr %taddr53, align 8 + %58 = getelementptr inbounds { ptr, i64 }, ptr %taddr53, i32 0, i32 0 + %lo54 = load ptr, ptr %58, align 8 + %59 = getelementptr inbounds { ptr, i64 }, ptr %taddr53, i32 0, i32 1 + %hi55 = load i64, ptr %59, align 8 + store ptr @.str.20, ptr %taddr58, align 8 + %60 = insertvalue %variant undef, ptr %taddr58, 0 + %61 = insertvalue %variant %60, i64 ptrtoint (ptr @"ct$p$a3$char" to i64), 1 + %62 = getelementptr inbounds [1 x %variant], ptr %varargslots57, i64 0, i64 0 + store %variant %61, ptr %62, align 16 + %63 = getelementptr inbounds %"variant[]", ptr %vararg56, i32 0, i32 1 + store i64 1, ptr %63, align 8 + %64 = getelementptr inbounds %"variant[]", ptr %vararg56, i32 0, i32 0 + store ptr %varargslots57, ptr %64, align 8 + %65 = getelementptr inbounds { ptr, i64 }, ptr %vararg56, i32 0, i32 0 + %lo59 = load ptr, ptr %65, align 8 + %66 = getelementptr inbounds { ptr, i64 }, ptr %vararg56, i32 0, i32 1 + %hi60 = load i64, ptr %66, align 8 + %67 = call i64 @std_io_printfln(ptr %retparam52, ptr %lo54, i64 %hi55, ptr %lo59, i64 %hi60) + %not_err61 = icmp eq i64 %67, 0 + br i1 %not_err61, label %after_check62, label %voiderr63 +after_check62: ; preds = %voiderr51 + br label %voiderr63 +voiderr63: ; preds = %after_check62, %voiderr51 + store %"char[]" { ptr @.str.21, i64 10 }, ptr %taddr65, align 8 + %68 = getelementptr inbounds { ptr, i64 }, ptr %taddr65, i32 0, i32 0 + %lo66 = load ptr, ptr %68, align 8 + %69 = getelementptr inbounds { ptr, i64 }, ptr %taddr65, i32 0, i32 1 + %hi67 = load i64, ptr %69, align 8 + store ptr @.str.22, ptr %taddr70, align 8 + %70 = insertvalue %variant undef, ptr %taddr70, 0 + %71 = insertvalue %variant %70, i64 ptrtoint (ptr @"ct$p$a3$char" to i64), 1 + %72 = getelementptr inbounds [1 x %variant], ptr %varargslots69, i64 0, i64 0 + store %variant %71, ptr %72, align 16 + %73 = getelementptr inbounds %"variant[]", ptr %vararg68, i32 0, i32 1 + store i64 1, ptr %73, align 8 + %74 = getelementptr inbounds %"variant[]", ptr %vararg68, i32 0, i32 0 + store ptr %varargslots69, ptr %74, align 8 + %75 = getelementptr inbounds { ptr, i64 }, ptr %vararg68, i32 0, i32 0 + %lo71 = load ptr, ptr %75, align 8 + %76 = getelementptr inbounds { ptr, i64 }, ptr %vararg68, i32 0, i32 1 + %hi72 = load i64, ptr %76, align 8 + %77 = call i64 @std_io_printfln(ptr %retparam64, ptr %lo66, i64 %hi67, ptr %lo71, i64 %hi72) + %not_err73 = icmp eq i64 %77, 0 + br i1 %not_err73, label %after_check74, label %voiderr75 +after_check74: ; preds = %voiderr63 + br label %voiderr75 +voiderr75: ; preds = %after_check74, %voiderr63 + store %"char[]" { ptr @.str.23, i64 10 }, ptr %taddr77, align 8 + %78 = getelementptr inbounds { ptr, i64 }, ptr %taddr77, i32 0, i32 0 + %lo78 = load ptr, ptr %78, align 8 + %79 = getelementptr inbounds { ptr, i64 }, ptr %taddr77, i32 0, i32 1 + %hi79 = load i64, ptr %79, align 8 + store ptr @.str.24, ptr %taddr82, align 8 + %80 = insertvalue %variant undef, ptr %taddr82, 0 + %81 = insertvalue %variant %80, i64 ptrtoint (ptr @"ct$p$a5$char" to i64), 1 + %82 = getelementptr inbounds [1 x %variant], ptr %varargslots81, i64 0, i64 0 + store %variant %81, ptr %82, align 16 + %83 = getelementptr inbounds %"variant[]", ptr %vararg80, i32 0, i32 1 + store i64 1, ptr %83, align 8 + %84 = getelementptr inbounds %"variant[]", ptr %vararg80, i32 0, i32 0 + store ptr %varargslots81, ptr %84, align 8 + %85 = getelementptr inbounds { ptr, i64 }, ptr %vararg80, i32 0, i32 0 + %lo83 = load ptr, ptr %85, align 8 + %86 = getelementptr inbounds { ptr, i64 }, ptr %vararg80, i32 0, i32 1 + %hi84 = load i64, ptr %86, align 8 + %87 = call i64 @std_io_printfln(ptr %retparam76, ptr %lo78, i64 %hi79, ptr %lo83, i64 %hi84) + %not_err85 = icmp eq i64 %87, 0 + br i1 %not_err85, label %after_check86, label %voiderr87 +after_check86: ; preds = %voiderr75 + br label %voiderr87 +voiderr87: ; preds = %after_check86, %voiderr75 + ret void +} \ No newline at end of file