diff --git a/lib/std/core/bitorder.c3 b/lib/std/core/bitorder.c3 new file mode 100644 index 000000000..a47f5572a --- /dev/null +++ b/lib/std/core/bitorder.c3 @@ -0,0 +1,61 @@ +module std::core::bitorder; + +bitstruct ShortBE : short @bigendian +{ + short val : 0..15; +} + +bitstruct UShortBE : ushort @bigendian +{ + ushort val : 0..15; +} + +bitstruct IntBE : int @bigendian +{ + int val : 0..31; +} + +bitstruct UIntBE : int @bigendian +{ + uint val : 0..31; +} + +bitstruct LongBE : long @bigendian +{ + long val : 0..63; +} + +bitstruct ULongBE : ulong @bigendian +{ + ulong val : 0..63; +} + +bitstruct ShortLE : short @littleendian +{ + short val : 0..15; +} + +bitstruct UShortLE : ushort @littleendian +{ + ushort val : 0..15; +} + +bitstruct IntLE : int @littleendian +{ + int val : 0..31; +} + +bitstruct UIntLE : int @littleendian +{ + uint val : 0..31; +} + +bitstruct LongLE : long @littleendian +{ + long val : 0..63; +} + +bitstruct ULongLE : ulong @littleendian +{ + ulong val : 0..63; +} diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index ed1ce2999..a64179a3a 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -18,6 +18,7 @@ static void llvm_emit_initialize_designated(GenContext *c, BEValue *ref, AlignSi static inline void llvm_emit_const_initialize_reference(GenContext *c, BEValue *ref, Expr *expr); static inline void llvm_emit_initialize_reference(GenContext *c, BEValue *ref, Expr *expr); static void llvm_convert_vector_comparison(GenContext *c, BEValue *be_value, LLVMValueRef val, Type *vector_type); +static bool bitstruct_requires_bitswap(Decl *decl); BEValue llvm_emit_assign_expr(GenContext *c, BEValue *ref, Expr *expr, LLVMValueRef failable) { @@ -207,7 +208,7 @@ LLVMValueRef llvm_mask_low_bits(GenContext *c, LLVMValueRef value, unsigned low_ BitSize type_bits = llvm_bitsize(c, type); if (type_bits <= low_bits) return value; LLVMValueRef mask = llvm_emit_lshr_fixed(c, llvm_get_ones_raw(type), type_bits - low_bits); - return LLVMBuildAnd(c->builder, mask, value, ""); + return llvm_emit_and_raw(c, mask, value); } LLVMTypeRef llvm_const_padding_type(GenContext *c, AlignSize size) @@ -743,9 +744,7 @@ static inline void llvm_extract_bitvalue_from_array(GenContext *c, BEValue *be_v llvm_extract_bool_bit_from_array(c, be_value, member); return; } - bool big_endian = platform_target.big_endian; - if (parent_decl->bitstruct.big_endian) big_endian = true; - if (parent_decl->bitstruct.little_endian) big_endian = false; + bool bswap = bitstruct_requires_bitswap(parent_decl); unsigned start = member->var.start_bit; unsigned end = member->var.end_bit; LLVMValueRef array_ptr = be_value->value; @@ -780,9 +779,9 @@ static inline void llvm_extract_bitvalue_from_array(GenContext *c, BEValue *be_v continue; } - if (!llvm_is_const_null(element)) res = LLVMBuildOr(c->builder, element, res, ""); + res = llvm_emit_or_raw(c, element, res); } - if (big_endian) + if (bswap) { res = llvm_bswap_non_integral(c, res, end - start + 1); } @@ -812,12 +811,8 @@ static inline void llvm_extract_bitvalue(GenContext *c, BEValue *be_value, Expr llvm_extract_bitvalue_from_array(c, be_value, member, parent_decl); return; } - bool bswap = false; - if (parent_decl->bitstruct.big_endian && !platform_target.big_endian) bswap = true; - if (parent_decl->bitstruct.little_endian && platform_target.big_endian) bswap = true; LLVMValueRef value = llvm_load_value_store(c, be_value); - if (bswap) value = llvm_emit_bswap(c, value); - LLVMTypeRef container_type = LLVMTypeOf(value); + if (bitstruct_requires_bitswap(parent_decl)) value = llvm_emit_bswap(c, value); BitSize container_size = type_size(be_value->type); BitSize container_bit_size = container_size * 8; unsigned start = (unsigned)member->var.start_bit; @@ -882,18 +877,16 @@ static inline void llvm_emit_bitassign_array(GenContext *c, BEValue *result, BEV LLVMValueRef byte_ptr = llvm_emit_array_gep_raw(c, array_ptr, array_type, start_bit / 8, parent.alignment, &alignment); LLVMValueRef current = llvm_load(c, c->byte_type, byte_ptr, alignment, ""); LLVMValueRef bit = llvm_emit_shl_fixed(c, LLVMConstInt(c->byte_type, 1, 0), start_bit % 8); - current = LLVMBuildAnd(c->builder, current, LLVMBuildNot(c->builder, bit, ""), ""); - if (!llvm_is_const_null(value)) current = LLVMBuildOr(c->builder, current, value, ""); + current = llvm_emit_and_raw(c, current, LLVMBuildNot(c->builder, bit, "")); + current = llvm_emit_or_raw(c, current, value); llvm_store_to_ptr_raw_aligned(c, byte_ptr, current, alignment); return; } - bool big_endian = platform_target.big_endian; - if (parent_decl->bitstruct.big_endian) big_endian = true; - if (parent_decl->bitstruct.little_endian) big_endian = false; + bool need_bitswap = bitstruct_requires_bitswap(parent_decl); unsigned bit_size = end_bit - start_bit + 1; - if (big_endian) + if (need_bitswap) { value = llvm_bswap_non_integral(c, value, bit_size); } @@ -924,15 +917,15 @@ static inline void llvm_emit_bitassign_array(GenContext *c, BEValue *result, BEV // We might need to mask the top bits if (i == end_byte && end_mod != 7) { - res = LLVMBuildAnd(c->builder, res, llvm_const_low_bitmask(c, c->byte_type, 8, end_mod + 1), ""); - mask = LLVMBuildOr(c->builder, mask, llvm_const_high_bitmask(c, c->byte_type, 8, 7 - (int)end_bit), ""); + res = llvm_emit_and_raw(c, res, llvm_const_low_bitmask(c, c->byte_type, 8, end_mod + 1)); + mask = llvm_emit_or_raw(c, mask, llvm_const_high_bitmask(c, c->byte_type, 8, 7 - (int)end_bit)); } // Load the current value. LLVMValueRef current = llvm_load(c, c->byte_type, byte_ptr, alignment, ""); // Empty the top bits. - current = LLVMBuildAnd(c->builder, current, mask, ""); + current = llvm_emit_and_raw(c, current, mask); // Use *or* with the top bits from "res": - if (!llvm_is_const_null(res)) current = LLVMBuildOr(c->builder, current, res, ""); + current = llvm_emit_or_raw(c, current, res); // And store it back. llvm_store_to_ptr_raw_aligned(c, byte_ptr, current, alignment); // We now shift the value by the number of bits we used. @@ -946,13 +939,13 @@ static inline void llvm_emit_bitassign_array(GenContext *c, BEValue *result, BEV value = llvm_zext_trunc(c, value, c->byte_type); // Create a mask for the lower bits. LLVMValueRef mask = llvm_const_low_bitmask(c, c->byte_type, 8, end_mod + 1); - value = LLVMBuildAnd(c->builder, value, mask, ""); + value = llvm_emit_and_raw(c, value, mask); // Load the current value. LLVMValueRef current = llvm_load(c, c->byte_type, byte_ptr, alignment, ""); // Clear the lower bits. - current = LLVMBuildAnd(c->builder, current, LLVMBuildNot(c->builder, mask, ""), ""); + current = llvm_emit_and_raw(c, current, LLVMBuildNot(c->builder, mask, "")); // Use *or* with the bottom bits from "value": - if (!llvm_is_const_null(value)) current = LLVMBuildOr(c->builder, current, value, ""); + llvm_emit_or_raw(c, current, value); // And store it back. llvm_store_to_ptr_raw_aligned(c, byte_ptr, current, alignment); continue; @@ -989,15 +982,17 @@ static inline void llvm_emit_bitassign_expr(GenContext *c, BEValue *be_value, Ex llvm_emit_expr(c, be_value, exprptr(expr->binary_expr.right)); } - if (type_lowering(parent_expr->type)->type_kind == TYPE_ARRAY) + Type *parent_type = type_flatten_distinct(parent_expr->type); + if (type_lowering(parent_type)->type_kind == TYPE_ARRAY) { - llvm_emit_bitassign_array(c, be_value, parent, type_flatten_distinct(parent_expr->type)->decl, member); + llvm_emit_bitassign_array(c, be_value, parent, parent_type->decl, member); return; } // To start the assign, pull out the current value. LLVMValueRef current_value = llvm_load_value_store(c, &parent); - + bool bswap = bitstruct_requires_bitswap(parent_type->decl); + if (bswap) current_value = llvm_emit_bswap(c, current_value); // Get the type. LLVMTypeRef struct_type = LLVMTypeOf(current_value); @@ -1021,10 +1016,11 @@ static inline void llvm_emit_bitassign_expr(GenContext *c, BEValue *be_value, Ex // Shift to the correct location. value = llvm_emit_shl_fixed(c, value, start_bit); // And combine using ((current_value & ~mask) | (value & mask)) - value = LLVMBuildAnd(c->builder, value, mask, ""); - current_value = LLVMBuildAnd(c->builder, current_value, LLVMBuildNot(c->builder, mask, ""), ""); + value = llvm_emit_and_raw(c, value, mask); + current_value = llvm_emit_and_raw(c, current_value, LLVMBuildNot(c->builder, mask, "")); // Skip this op for LLVM14 if zero. - if (!llvm_is_const_null(value)) current_value = LLVMBuildOr(c->builder, current_value, value, ""); + current_value = llvm_emit_or_raw(c, current_value, value); + if (bswap) current_value = llvm_emit_bswap(c, current_value); llvm_store_raw(c, &parent, current_value); } static inline void llvm_emit_bitaccess(GenContext *c, BEValue *be_value, Expr *expr) @@ -1693,13 +1689,18 @@ static inline void llvm_emit_initialize_reference_designated(GenContext *c, BEVa #define MAX_AGG 16 +static bool bitstruct_requires_bitswap(Decl *decl) +{ + bool big_endian = platform_target.big_endian; + if (decl->bitstruct.big_endian) return !big_endian; + if (decl->bitstruct.little_endian) return big_endian; + return false; +} + LLVMValueRef llvm_emit_const_bitstruct_array(GenContext *c, ConstInitializer *initializer) { Decl *decl = initializer->type->decl; Type *base_type = decl->bitstruct.base_type->type; - bool big_endian = platform_target.big_endian; - if (decl->bitstruct.big_endian) big_endian = true; - if (decl->bitstruct.little_endian) big_endian = false; unsigned elements = base_type->array.len; LLVMValueRef stack_data[MAX_AGG]; LLVMValueRef* slots = elements > MAX_AGG ? MALLOC(elements * sizeof(LLVMValueRef)) : stack_data; @@ -1730,7 +1731,7 @@ LLVMValueRef llvm_emit_const_bitstruct_array(GenContext *c, ConstInitializer *in LLVMValueRef bit = llvm_emit_shl_fixed(c, LLVMConstInt(c->byte_type, 1, 0), start_bit % 8); unsigned byte = start_bit / 8; LLVMValueRef current_value = slots[byte]; - slots[byte] = LLVMBuildOr(c->builder, current_value, bit, ""); + slots[byte] = llvm_emit_or_raw(c, current_value, bit); continue; } unsigned bit_size = end_bit - start_bit + 1; @@ -1743,7 +1744,7 @@ LLVMValueRef llvm_emit_const_bitstruct_array(GenContext *c, ConstInitializer *in int end_byte = end_bit / 8; ByteSize member_type_bitsize = type_size(member_type) * 8; value = llvm_mask_low_bits(c, value, bit_size); - if (big_endian && bit_size > 8) + if (bitstruct_requires_bitswap(decl) && bit_size > 8) { value = llvm_bswap_non_integral(c, value, bit_size); } @@ -1765,7 +1766,7 @@ LLVMValueRef llvm_emit_const_bitstruct_array(GenContext *c, ConstInitializer *in } if (member_type_bitsize > 8) to_or = LLVMBuildTrunc(c->builder, to_or, c->byte_type, ""); LLVMValueRef current_value = slots[(unsigned)j]; - slots[(unsigned)j] = LLVMBuildOr(c->builder, to_or, current_value, ""); + slots[(unsigned)j] = llvm_emit_or_raw(c, to_or, current_value); } } return llvm_get_array(c->byte_type, slots, elements); @@ -1811,19 +1812,15 @@ LLVMValueRef llvm_emit_const_bitstruct(GenContext *c, ConstInitializer *initiali if (bit_size < base_type_bitsize) { LLVMValueRef mask = llvm_emit_lshr_fixed(c, llvm_get_ones_raw(llvm_base_type), base_type_bitsize - bit_size); - value = LLVMBuildAnd(c->builder, mask, value, ""); + value = llvm_emit_and_raw(c, mask, value); } if (start_bit > 0) { value = llvm_emit_shl_fixed(c, value, start_bit); } - result = LLVMBuildOr(c->builder, value, result, ""); + result = llvm_emit_or_raw(c, value, result); } - if (decl->bitstruct.little_endian && platform_target.big_endian) - { - return LLVMConstBswap(result); - } - if (decl->bitstruct.big_endian && !platform_target.big_endian) + if (bitstruct_requires_bitswap(decl)) { return LLVMConstBswap(result); } diff --git a/src/compiler/llvm_codegen_internal.h b/src/compiler/llvm_codegen_internal.h index 92698d039..198881649 100644 --- a/src/compiler/llvm_codegen_internal.h +++ b/src/compiler/llvm_codegen_internal.h @@ -386,6 +386,8 @@ INLINE LLVMValueRef llvm_emit_lshr(GenContext *c, LLVMValueRef value, LLVMValueR INLINE LLVMValueRef llvm_emit_trunc(GenContext *c, LLVMValueRef value, Type *type); INLINE LLVMValueRef llvm_emit_trunc_bool(GenContext *c, LLVMValueRef value); INLINE LLVMValueRef llvm_emit_and(GenContext *c, BEValue *lhs, BEValue *rhs); +INLINE LLVMValueRef llvm_emit_and_raw(GenContext *c, LLVMValueRef lhs, LLVMValueRef rhs); +INLINE LLVMValueRef llvm_emit_or_raw(GenContext *c, LLVMValueRef lhs, LLVMValueRef rhs); // -- Mem ops -- LLVMValueRef llvm_emit_memclear_size_align(GenContext *c, LLVMValueRef ptr, uint64_t size, AlignSize align); diff --git a/src/compiler/llvm_codegen_internal_impl.h b/src/compiler/llvm_codegen_internal_impl.h index de7db843b..c25721f15 100644 --- a/src/compiler/llvm_codegen_internal_impl.h +++ b/src/compiler/llvm_codegen_internal_impl.h @@ -172,9 +172,23 @@ INLINE LLVMTypeRef llvm_get_ptr_type(GenContext *c, Type *type) return llvm_get_type(c, type_get_ptr(type)); } +INLINE LLVMValueRef llvm_emit_and_raw(GenContext *c, LLVMValueRef lhs, LLVMValueRef rhs) +{ + if (llvm_is_const_null(lhs)) return lhs; + if (llvm_is_const_null(rhs)) return rhs; + return LLVMBuildAnd(c->builder, lhs, rhs, ""); +} + +INLINE LLVMValueRef llvm_emit_or_raw(GenContext *c, LLVMValueRef lhs, LLVMValueRef rhs) +{ + if (llvm_is_const_null(lhs)) return rhs; + if (llvm_is_const_null(rhs)) return lhs; + return LLVMBuildOr(c->builder, lhs, rhs, ""); +} + INLINE LLVMValueRef llvm_emit_and(GenContext *c, BEValue *lhs, BEValue *rhs) { - return LLVMBuildAnd(c->builder, lhs->value, rhs->value, ""); + return llvm_emit_and_raw(c, lhs->value, rhs->value); } INLINE LLVMValueRef llvm_get_zero(GenContext *c, Type *type) diff --git a/test/test_suite/bitstruct/bitstruct_arrays.c3t b/test/test_suite/bitstruct/bitstruct_arrays.c3t index af2d9b83f..e661e9837 100644 --- a/test/test_suite/bitstruct/bitstruct_arrays.c3t +++ b/test/test_suite/bitstruct/bitstruct_arrays.c3t @@ -350,7 +350,7 @@ entry: %1 = load i8, i8* %0, align 1 %2 = and i8 %1, -8 %3 = or i8 %2, 3 - store i8 %3, i8* %0, align 1 + store i8 %2, i8* %0, align 1 %4 = getelementptr inbounds [3 x i8], [3 x i8]* %xx, i64 0, i64 0 %5 = load i8, i8* %4, align 1 %zext = zext i8 %5 to i32 @@ -380,7 +380,7 @@ entry: %15 = load i8, i8* %13, align 1 %16 = and i8 %15, -8 %17 = or i8 %16, %14 - store i8 %17, i8* %13, align 1 + store i8 %16, i8* %13, align 1 %18 = getelementptr inbounds [3 x i8], [3 x i8]* %xx, i64 0, i64 0 %19 = load i8, i8* %18, align 1 %zext9 = zext i8 %19 to i32 @@ -424,7 +424,7 @@ entry: %36 = load i8, i8* %34, align 1 %37 = and i8 %36, -2 %38 = or i8 %37, %35 - store i8 %38, i8* %34, align 1 + store i8 %37, i8* %34, align 1 %39 = getelementptr inbounds [3 x i8], [3 x i8]* %xx, i64 0, i64 0 %40 = load i8, i8* %39, align 1 %zext28 = zext i8 %40 to i32 @@ -468,7 +468,7 @@ entry: %57 = load i8, i8* %55, align 1 %58 = and i8 %57, -2 %59 = or i8 %58, %56 - store i8 %59, i8* %55, align 1 + store i8 %58, i8* %55, align 1 %60 = getelementptr inbounds [3 x i8], [3 x i8]* %xx, i64 0, i64 0 %61 = load i8, i8* %60, align 1 %zext47 = zext i8 %61 to i32 @@ -512,7 +512,7 @@ entry: %78 = load i8, i8* %76, align 1 %79 = and i8 %78, -2 %80 = or i8 %79, %77 - store i8 %80, i8* %76, align 1 + store i8 %79, i8* %76, align 1 %81 = getelementptr inbounds [3 x i8], [3 x i8]* %xx, i64 0, i64 0 %82 = load i8, i8* %81, align 1 %zext66 = zext i8 %82 to i32 @@ -557,7 +557,7 @@ entry: %100 = load i8, i8* %98, align 1 %101 = and i8 %100, -2 %102 = or i8 %101, %99 - store i8 %102, i8* %98, align 1 + store i8 %101, i8* %98, align 1 %103 = getelementptr inbounds [3 x i8], [3 x i8]* %xx, i64 0, i64 0 %104 = load i8, i8* %103, align 1 %zext86 = zext i8 %104 to i32 @@ -602,7 +602,7 @@ entry: %122 = load i8, i8* %120, align 1 %123 = and i8 %122, -2 %124 = or i8 %123, %121 - store i8 %124, i8* %120, align 1 + store i8 %123, i8* %120, align 1 %125 = getelementptr inbounds [3 x i8], [3 x i8]* %xx, i64 0, i64 0 %126 = load i8, i8* %125, align 1 %zext106 = zext i8 %126 to i32 @@ -646,7 +646,7 @@ entry: %143 = load i8, i8* %141, align 1 %144 = and i8 %143, -2 %145 = or i8 %144, %142 - store i8 %145, i8* %141, align 1 + store i8 %144, i8* %141, align 1 %146 = getelementptr inbounds [3 x i8], [3 x i8]* %xx, i64 0, i64 0 %147 = load i8, i8* %146, align 1 %zext125 = zext i8 %147 to i32 @@ -690,7 +690,7 @@ entry: %164 = load i8, i8* %162, align 1 %165 = and i8 %164, -2 %166 = or i8 %165, %163 - store i8 %166, i8* %162, align 1 + store i8 %165, i8* %162, align 1 %167 = getelementptr inbounds [3 x i8], [3 x i8]* %xx, i64 0, i64 0 %168 = load i8, i8* %167, align 1 %zext144 = zext i8 %168 to i32 @@ -826,7 +826,7 @@ entry: %36 = load i8, i8* %34, align 1 %37 = and i8 %36, -4 %38 = or i8 %37, %35 - store i8 %38, i8* %34, align 1 + store i8 %37, i8* %34, align 1 %39 = getelementptr inbounds [3 x i8], [3 x i8]* %xx, i64 0, i64 0 %40 = load i8, i8* %39, align 1 %zext33 = zext i8 %40 to i32 @@ -871,7 +871,7 @@ entry: %57 = load i8, i8* %55, align 1 %58 = and i8 %57, -4 %59 = or i8 %58, %56 - store i8 %59, i8* %55, align 1 + store i8 %58, i8* %55, align 1 %60 = getelementptr inbounds [3 x i8], [3 x i8]* %xx, i64 0, i64 0 %61 = load i8, i8* %60, align 1 %zext53 = zext i8 %61 to i32 @@ -916,7 +916,7 @@ entry: %78 = load i8, i8* %76, align 1 %79 = and i8 %78, -4 %80 = or i8 %79, %77 - store i8 %80, i8* %76, align 1 + store i8 %79, i8* %76, align 1 %81 = getelementptr inbounds [3 x i8], [3 x i8]* %xx, i64 0, i64 0 %82 = load i8, i8* %81, align 1 %zext73 = zext i8 %82 to i32 @@ -962,7 +962,7 @@ entry: %100 = load i8, i8* %98, align 1 %101 = and i8 %100, -4 %102 = or i8 %101, %99 - store i8 %102, i8* %98, align 1 + store i8 %101, i8* %98, align 1 %103 = getelementptr inbounds [3 x i8], [3 x i8]* %xx, i64 0, i64 0 %104 = load i8, i8* %103, align 1 %zext94 = zext i8 %104 to i32 @@ -1008,7 +1008,7 @@ entry: %122 = load i8, i8* %120, align 1 %123 = and i8 %122, -4 %124 = or i8 %123, %121 - store i8 %124, i8* %120, align 1 + store i8 %123, i8* %120, align 1 %125 = getelementptr inbounds [3 x i8], [3 x i8]* %xx, i64 0, i64 0 %126 = load i8, i8* %125, align 1 %zext115 = zext i8 %126 to i32 @@ -1053,7 +1053,7 @@ entry: %143 = load i8, i8* %141, align 1 %144 = and i8 %143, -4 %145 = or i8 %144, %142 - store i8 %145, i8* %141, align 1 + store i8 %144, i8* %141, align 1 %146 = getelementptr inbounds [3 x i8], [3 x i8]* %xx, i64 0, i64 0 %147 = load i8, i8* %146, align 1 %zext135 = zext i8 %147 to i32 @@ -1098,7 +1098,7 @@ entry: %164 = load i8, i8* %162, align 1 %165 = and i8 %164, -4 %166 = or i8 %165, %163 - store i8 %166, i8* %162, align 1 + store i8 %165, i8* %162, align 1 %167 = getelementptr inbounds [3 x i8], [3 x i8]* %xx, i64 0, i64 0 %168 = load i8, i8* %167, align 1 %zext155 = zext i8 %168 to i32 diff --git a/test/test_suite/bitstruct/bitstruct_arrays_be.c3t b/test/test_suite/bitstruct/bitstruct_arrays_be.c3t index 158a7f762..9e5b7a254 100644 --- a/test/test_suite/bitstruct/bitstruct_arrays_be.c3t +++ b/test/test_suite/bitstruct/bitstruct_arrays_be.c3t @@ -95,7 +95,7 @@ entry: %26 = load i8, i8* %25, align 1 %27 = and i8 %26, -16 %28 = or i8 %27, 11 - store i8 %28, i8* %25, align 1 + store i8 %27, i8* %25, align 1 %29 = getelementptr inbounds [4 x i8], [4 x i8]* %xy, i64 0, i64 0 %30 = load i8, i8* %29, align 1 %zext12 = zext i8 %30 to i32 @@ -123,7 +123,7 @@ entry: %44 = load i8, i8* %43, align 1 %45 = and i8 %44, -16 %46 = or i8 %45, 14 - store i8 %46, i8* %43, align 1 + store i8 %45, i8* %43, align 1 %47 = getelementptr inbounds [4 x i8], [4 x i8]* %xx, i64 0, i64 0 %48 = load i8, i8* %47, align 1 %zext18 = zext i8 %48 to i32 diff --git a/test/test_suite/bitstruct/bitstruct_be.c3t b/test/test_suite/bitstruct/bitstruct_be.c3t new file mode 100644 index 000000000..c2a0764be --- /dev/null +++ b/test/test_suite/bitstruct/bitstruct_be.c3t @@ -0,0 +1,364 @@ +// #target: macos-x64 +module test; +import std::io; + +bitstruct Test : int @bigendian +{ + ushort a : 0..15; + ushort b : 16..31; +} + +bitstruct Test2 : char[4] @bigendian +{ + ushort a : 0..15; + ushort b : 16..31; +} + +fn void main() +{ + IntBE x; + x.val = 123; + + io::printf("BE 123 => %d (%d)\n", (int)x, x.val); + Test abc = { .a = 0x1234, .b = 0x5678 }; + Test2 abc2 = { .a = 0x1234, .b = 0x5678 }; + char[4]* z = (char[4]*)&abc; + char[4]* z2 = (char[4]*)&abc2; + foreach (d : z2) io::printf(" %x", d); + io::println(""); + foreach (d : z) io::printf(" %x", d); + io::println(""); + io::printfln("abc.a = %x", abc.a); + abc.a = 0x1234; + abc.b = 0x5678; + io::printfln("->abc.a = %x", abc.a); + foreach (d : z) io::printf(" %x", d); + io::println(""); + + IntLE y; + y.val = 123; + io::printf("LE 123 => %d (%d)\n", (int)y, y.val); + +} + +/* #expect: test.ll + + %0 = load i32, i32* %x, align 4 + %1 = call i32 @llvm.bswap.i32(i32 %0) + store i32 2063597568, i32* %x, align 4 + store %"char[]" { i8* getelementptr inbounds ([19 x i8], [19 x i8]* @.str, i32 0, i32 0), i64 18 }, %"char[]"* %taddr, align 8 + %2 = bitcast %"char[]"* %taddr to { i8*, i64 }* + %3 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %2, i32 0, i32 0 + %lo = load i8*, i8** %3, align 8 + %4 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %2, i32 0, i32 1 + %hi = load i64, i64* %4, align 8 + %5 = bitcast i32* %x to i8* + %6 = insertvalue %variant undef, i8* %5, 0 + %7 = insertvalue %variant %6, i64 ptrtoint (%.introspect* @"ct$int" to i64), 1 + %8 = getelementptr inbounds [2 x %variant], [2 x %variant]* %varargslots, i64 0, i64 0 + store %variant %7, %variant* %8, align 16 + %9 = load i32, i32* %x, align 4 + %10 = call i32 @llvm.bswap.i32(i32 %9) + store i32 %10, i32* %taddr1, align 4 + %11 = bitcast i32* %taddr1 to i8* + %12 = insertvalue %variant undef, i8* %11, 0 + %13 = insertvalue %variant %12, i64 ptrtoint (%.introspect* @"ct$int" to i64), 1 + %14 = getelementptr inbounds [2 x %variant], [2 x %variant]* %varargslots, i64 0, i64 1 + store %variant %13, %variant* %14, align 16 + %15 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg, i32 0, i32 1 + store i64 2, i64* %15, align 8 + %16 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg, i32 0, i32 0 + %17 = bitcast [2 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_printf(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 i32 873625686, i32* %abc, align 4 + store [4 x i8] c"\124Vx", [4 x i8]* %abc2, align 1 + %ptrptr = bitcast i32* %abc to [4 x i8]* + store [4 x i8]* %ptrptr, [4 x i8]** %z, align 8 + store [4 x i8]* %abc2, [4 x i8]** %z2, align 8 + %22 = load [4 x i8]*, [4 x i8]** %z2, align 8 + store [4 x i8]* %22, [4 x i8]** %.anon, align 8 + store i64 0, i64* %.anon4, align 8 + br label %loop.cond + +loop.cond: ; preds = %voiderr15, %voiderr + %23 = load i64, i64* %.anon4, align 8 + %gt = icmp ugt i64 4, %23 + br i1 %gt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %24 = load [4 x i8]*, [4 x i8]** %.anon, align 8 + %25 = load i64, i64* %.anon4, align 8 + %26 = getelementptr inbounds [4 x i8], [4 x i8]* %24, i64 0, i64 %25 + %27 = load i8, i8* %26, align 1 + store i8 %27, i8* %d, align 1 + store %"char[]" { i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.1, i32 0, i32 0), i64 3 }, %"char[]"* %taddr6, align 8 + %28 = bitcast %"char[]"* %taddr6 to { i8*, i64 }* + %29 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %28, i32 0, i32 0 + %lo7 = load i8*, i8** %29, align 8 + %30 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %28, i32 0, i32 1 + %hi8 = load i64, i64* %30, align 8 + %31 = insertvalue %variant undef, i8* %d, 0 + %32 = insertvalue %variant %31, i64 ptrtoint (%.introspect* @"ct$char" to i64), 1 + %33 = getelementptr inbounds [1 x %variant], [1 x %variant]* %varargslots10, i64 0, i64 0 + store %variant %32, %variant* %33, align 16 + %34 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg9, i32 0, i32 1 + store i64 1, i64* %34, align 8 + %35 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg9, i32 0, i32 0 + %36 = bitcast [1 x %variant]* %varargslots10 to %variant* + store %variant* %36, %variant** %35, align 8 + %37 = bitcast %"variant[]"* %vararg9 to { i8*, i64 }* + %38 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %37, i32 0, i32 0 + %lo11 = load i8*, i8** %38, align 8 + %39 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %37, i32 0, i32 1 + %hi12 = load i64, i64* %39, align 8 + %40 = call i64 @std_io_printf(i64* %retparam5, i8* %lo7, i64 %hi8, i8* %lo11, i64 %hi12) + %not_err13 = icmp eq i64 %40, 0 + br i1 %not_err13, label %after_check14, label %voiderr15 + +after_check14: ; preds = %loop.body + br label %voiderr15 + +voiderr15: ; preds = %after_check14, %loop.body + %41 = load i64, i64* %.anon4, align 8 + %add = add i64 %41, 1 + store i64 %add, i64* %.anon4, align 8 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + %42 = call i32 @std_io_println(i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str.2, i32 0, i32 0)) #2 + %43 = load [4 x i8]*, [4 x i8]** %z, align 8 + store [4 x i8]* %43, [4 x i8]** %.anon16, align 8 + store i64 0, i64* %.anon17, align 8 + br label %loop.cond18 + +loop.cond18: ; preds = %voiderr32, %loop.exit + %44 = load i64, i64* %.anon17, align 8 + %gt19 = icmp ugt i64 4, %44 + br i1 %gt19, label %loop.body20, label %loop.exit34 + +loop.body20: ; preds = %loop.cond18 + %45 = load [4 x i8]*, [4 x i8]** %.anon16, align 8 + %46 = load i64, i64* %.anon17, align 8 + %47 = getelementptr inbounds [4 x i8], [4 x i8]* %45, i64 0, i64 %46 + %48 = load i8, i8* %47, align 1 + store i8 %48, i8* %d21, align 1 + store %"char[]" { i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.3, i32 0, i32 0), i64 3 }, %"char[]"* %taddr23, align 8 + %49 = bitcast %"char[]"* %taddr23 to { i8*, i64 }* + %50 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %49, i32 0, i32 0 + %lo24 = load i8*, i8** %50, align 8 + %51 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %49, i32 0, i32 1 + %hi25 = load i64, i64* %51, align 8 + %52 = insertvalue %variant undef, i8* %d21, 0 + %53 = insertvalue %variant %52, i64 ptrtoint (%.introspect* @"ct$char" to i64), 1 + %54 = getelementptr inbounds [1 x %variant], [1 x %variant]* %varargslots27, i64 0, i64 0 + store %variant %53, %variant* %54, align 16 + %55 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg26, i32 0, i32 1 + store i64 1, i64* %55, align 8 + %56 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg26, i32 0, i32 0 + %57 = bitcast [1 x %variant]* %varargslots27 to %variant* + store %variant* %57, %variant** %56, align 8 + %58 = bitcast %"variant[]"* %vararg26 to { i8*, i64 }* + %59 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %58, i32 0, i32 0 + %lo28 = load i8*, i8** %59, align 8 + %60 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %58, i32 0, i32 1 + %hi29 = load i64, i64* %60, align 8 + %61 = call i64 @std_io_printf(i64* %retparam22, i8* %lo24, i64 %hi25, i8* %lo28, i64 %hi29) + %not_err30 = icmp eq i64 %61, 0 + br i1 %not_err30, label %after_check31, label %voiderr32 + +after_check31: ; preds = %loop.body20 + br label %voiderr32 + +voiderr32: ; preds = %after_check31, %loop.body20 + %62 = load i64, i64* %.anon17, align 8 + %add33 = add i64 %62, 1 + store i64 %add33, i64* %.anon17, align 8 + br label %loop.cond18 + +loop.exit34: ; preds = %loop.cond18 + %63 = call i32 @std_io_println(i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str.4, i32 0, i32 0)) #2 + store %"char[]" { i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str.5, i32 0, i32 0), i64 10 }, %"char[]"* %taddr36, align 8 + %64 = bitcast %"char[]"* %taddr36 to { i8*, i64 }* + %65 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %64, i32 0, i32 0 + %lo37 = load i8*, i8** %65, align 8 + %66 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %64, i32 0, i32 1 + %hi38 = load i64, i64* %66, align 8 + %67 = load i32, i32* %abc, align 4 + %68 = call i32 @llvm.bswap.i32(i32 %67) + %69 = and i32 65535, %68 + %ztrunc = trunc i32 %69 to i16 + store i16 %ztrunc, i16* %taddr41, align 2 + %70 = bitcast i16* %taddr41 to i8* + %71 = insertvalue %variant undef, i8* %70, 0 + %72 = insertvalue %variant %71, i64 ptrtoint (%.introspect* @"ct$ushort" to i64), 1 + %73 = getelementptr inbounds [1 x %variant], [1 x %variant]* %varargslots40, i64 0, i64 0 + store %variant %72, %variant* %73, align 16 + %74 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg39, i32 0, i32 1 + store i64 1, i64* %74, align 8 + %75 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg39, i32 0, i32 0 + %76 = bitcast [1 x %variant]* %varargslots40 to %variant* + store %variant* %76, %variant** %75, align 8 + %77 = bitcast %"variant[]"* %vararg39 to { i8*, i64 }* + %78 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %77, i32 0, i32 0 + %lo42 = load i8*, i8** %78, align 8 + %79 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %77, i32 0, i32 1 + %hi43 = load i64, i64* %79, align 8 + %80 = call i64 @std_io_printfln(i64* %retparam35, i8* %lo37, i64 %hi38, i8* %lo42, i64 %hi43) + %not_err44 = icmp eq i64 %80, 0 + br i1 %not_err44, label %after_check45, label %voiderr46 + +after_check45: ; preds = %loop.exit34 + br label %voiderr46 + +voiderr46: ; preds = %after_check45, %loop.exit34 + %81 = load i32, i32* %abc, align 4 + %82 = call i32 @llvm.bswap.i32(i32 %81) + %83 = and i32 %82, -65536 + %84 = or i32 %83, 4660 + %85 = call i32 @llvm.bswap.i32(i32 %84) + store i32 %85, i32* %abc, align 4 + %86 = load i32, i32* %abc, align 4 + %87 = call i32 @llvm.bswap.i32(i32 %86) + %88 = and i32 %87, 65535 + %89 = or i32 %88, 1450704896 + %90 = call i32 @llvm.bswap.i32(i32 %89) + store i32 %90, i32* %abc, align 4 + store %"char[]" { i8* getelementptr inbounds ([13 x i8], [13 x i8]* @.str.6, i32 0, i32 0), i64 12 }, %"char[]"* %taddr48, align 8 + %91 = bitcast %"char[]"* %taddr48 to { i8*, i64 }* + %92 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %91, i32 0, i32 0 + %lo49 = load i8*, i8** %92, align 8 + %93 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %91, i32 0, i32 1 + %hi50 = load i64, i64* %93, align 8 + %94 = load i32, i32* %abc, align 4 + %95 = call i32 @llvm.bswap.i32(i32 %94) + %96 = and i32 65535, %95 + %ztrunc53 = trunc i32 %96 to i16 + store i16 %ztrunc53, i16* %taddr54, align 2 + %97 = bitcast i16* %taddr54 to i8* + %98 = insertvalue %variant undef, i8* %97, 0 + %99 = insertvalue %variant %98, i64 ptrtoint (%.introspect* @"ct$ushort" to i64), 1 + %100 = getelementptr inbounds [1 x %variant], [1 x %variant]* %varargslots52, i64 0, i64 0 + store %variant %99, %variant* %100, align 16 + %101 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg51, i32 0, i32 1 + store i64 1, i64* %101, align 8 + %102 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg51, i32 0, i32 0 + %103 = bitcast [1 x %variant]* %varargslots52 to %variant* + store %variant* %103, %variant** %102, align 8 + %104 = bitcast %"variant[]"* %vararg51 to { i8*, i64 }* + %105 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %104, i32 0, i32 0 + %lo55 = load i8*, i8** %105, align 8 + %106 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %104, i32 0, i32 1 + %hi56 = load i64, i64* %106, align 8 + %107 = call i64 @std_io_printfln(i64* %retparam47, i8* %lo49, i64 %hi50, i8* %lo55, i64 %hi56) + %not_err57 = icmp eq i64 %107, 0 + br i1 %not_err57, label %after_check58, label %voiderr59 + +after_check58: ; preds = %voiderr46 + br label %voiderr59 + +voiderr59: ; preds = %after_check58, %voiderr46 + %108 = load [4 x i8]*, [4 x i8]** %z, align 8 + store [4 x i8]* %108, [4 x i8]** %.anon60, align 8 + store i64 0, i64* %.anon61, align 8 + br label %loop.cond62 + +loop.cond62: ; preds = %voiderr76, %voiderr59 + %109 = load i64, i64* %.anon61, align 8 + %gt63 = icmp ugt i64 4, %109 + br i1 %gt63, label %loop.body64, label %loop.exit78 + +loop.body64: ; preds = %loop.cond62 + %110 = load [4 x i8]*, [4 x i8]** %.anon60, align 8 + %111 = load i64, i64* %.anon61, align 8 + %112 = getelementptr inbounds [4 x i8], [4 x i8]* %110, i64 0, i64 %111 + %113 = load i8, i8* %112, align 1 + store i8 %113, i8* %d65, align 1 + store %"char[]" { i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str.7, i32 0, i32 0), i64 3 }, %"char[]"* %taddr67, align 8 + %114 = bitcast %"char[]"* %taddr67 to { i8*, i64 }* + %115 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %114, i32 0, i32 0 + %lo68 = load i8*, i8** %115, align 8 + %116 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %114, i32 0, i32 1 + %hi69 = load i64, i64* %116, align 8 + %117 = insertvalue %variant undef, i8* %d65, 0 + %118 = insertvalue %variant %117, i64 ptrtoint (%.introspect* @"ct$char" to i64), 1 + %119 = getelementptr inbounds [1 x %variant], [1 x %variant]* %varargslots71, i64 0, i64 0 + store %variant %118, %variant* %119, align 16 + %120 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg70, i32 0, i32 1 + store i64 1, i64* %120, align 8 + %121 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg70, i32 0, i32 0 + %122 = bitcast [1 x %variant]* %varargslots71 to %variant* + store %variant* %122, %variant** %121, align 8 + %123 = bitcast %"variant[]"* %vararg70 to { i8*, i64 }* + %124 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %123, i32 0, i32 0 + %lo72 = load i8*, i8** %124, align 8 + %125 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %123, i32 0, i32 1 + %hi73 = load i64, i64* %125, align 8 + %126 = call i64 @std_io_printf(i64* %retparam66, i8* %lo68, i64 %hi69, i8* %lo72, i64 %hi73) + %not_err74 = icmp eq i64 %126, 0 + br i1 %not_err74, label %after_check75, label %voiderr76 + +after_check75: ; preds = %loop.body64 + br label %voiderr76 + +voiderr76: ; preds = %after_check75, %loop.body64 + %127 = load i64, i64* %.anon61, align 8 + %add77 = add i64 %127, 1 + store i64 %add77, i64* %.anon61, align 8 + br label %loop.cond62 + +loop.exit78: ; preds = %loop.cond62 + %128 = call i32 @std_io_println(i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str.8, i32 0, i32 0)) #2 + store i32 0, i32* %y, align 4 + %129 = load i32, i32* %y, align 4 + store i32 123, i32* %y, align 4 + store %"char[]" { i8* getelementptr inbounds ([19 x i8], [19 x i8]* @.str.9, i32 0, i32 0), i64 18 }, %"char[]"* %taddr80, align 8 + %130 = bitcast %"char[]"* %taddr80 to { i8*, i64 }* + %131 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %130, i32 0, i32 0 + %lo81 = load i8*, i8** %131, align 8 + %132 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %130, i32 0, i32 1 + %hi82 = load i64, i64* %132, align 8 + %133 = bitcast i32* %y to i8* + %134 = insertvalue %variant undef, i8* %133, 0 + %135 = insertvalue %variant %134, i64 ptrtoint (%.introspect* @"ct$int" to i64), 1 + %136 = getelementptr inbounds [2 x %variant], [2 x %variant]* %varargslots84, i64 0, i64 0 + store %variant %135, %variant* %136, align 16 + %137 = load i32, i32* %y, align 4 + store i32 %137, i32* %taddr85, align 4 + %138 = bitcast i32* %taddr85 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]* %varargslots84, i64 0, i64 1 + store %variant %140, %variant* %141, align 16 + %142 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg83, i32 0, i32 1 + store i64 2, i64* %142, align 8 + %143 = getelementptr inbounds %"variant[]", %"variant[]"* %vararg83, i32 0, i32 0 + %144 = bitcast [2 x %variant]* %varargslots84 to %variant* + store %variant* %144, %variant** %143, align 8 + %145 = bitcast %"variant[]"* %vararg83 to { i8*, i64 }* + %146 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %145, i32 0, i32 0 + %lo86 = load i8*, i8** %146, align 8 + %147 = getelementptr inbounds { i8*, i64 }, { i8*, i64 }* %145, i32 0, i32 1 + %hi87 = load i64, i64* %147, align 8 + %148 = call i64 @std_io_printf(i64* %retparam79, i8* %lo81, i64 %hi82, i8* %lo86, i64 %hi87) + %not_err88 = icmp eq i64 %148, 0 + br i1 %not_err88, label %after_check89, label %voiderr90 + +after_check89: ; preds = %loop.exit78 + br label %voiderr90 + +voiderr90: ; preds = %after_check89, %loop.exit78 + ret void +} \ No newline at end of file diff --git a/test/test_suite2/bitstruct/bitstruct_arrays.c3t b/test/test_suite2/bitstruct/bitstruct_arrays.c3t index 15e5d33bc..066ba1e77 100644 --- a/test/test_suite2/bitstruct/bitstruct_arrays.c3t +++ b/test/test_suite2/bitstruct/bitstruct_arrays.c3t @@ -122,15 +122,6 @@ fn void test3() /* #expect: foo.ll -define void @foo_main() #0 { -entry: - call void @foo_test1() - call void @foo_test2() - call void @foo_test3() - ret void -} - -; Function Attrs: nounwind define void @foo_test1() #0 { entry: %xx = alloca i64, align 8 @@ -350,7 +341,7 @@ entry: %1 = load i8, ptr %0, align 1 %2 = and i8 %1, -8 %3 = or i8 %2, 3 - store i8 %3, ptr %0, align 1 + store i8 %2, ptr %0, align 1 %4 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 %5 = load i8, ptr %4, align 1 %zext = zext i8 %5 to i32 @@ -380,7 +371,7 @@ entry: %15 = load i8, ptr %13, align 1 %16 = and i8 %15, -8 %17 = or i8 %16, %14 - store i8 %17, ptr %13, align 1 + store i8 %16, ptr %13, align 1 %18 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 %19 = load i8, ptr %18, align 1 %zext9 = zext i8 %19 to i32 @@ -424,7 +415,7 @@ entry: %36 = load i8, ptr %34, align 1 %37 = and i8 %36, -2 %38 = or i8 %37, %35 - store i8 %38, ptr %34, align 1 + store i8 %37, ptr %34, align 1 %39 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 %40 = load i8, ptr %39, align 1 %zext28 = zext i8 %40 to i32 @@ -468,7 +459,7 @@ entry: %57 = load i8, ptr %55, align 1 %58 = and i8 %57, -2 %59 = or i8 %58, %56 - store i8 %59, ptr %55, align 1 + store i8 %58, ptr %55, align 1 %60 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 %61 = load i8, ptr %60, align 1 %zext47 = zext i8 %61 to i32 @@ -512,7 +503,7 @@ entry: %78 = load i8, ptr %76, align 1 %79 = and i8 %78, -2 %80 = or i8 %79, %77 - store i8 %80, ptr %76, align 1 + store i8 %79, ptr %76, align 1 %81 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 %82 = load i8, ptr %81, align 1 %zext66 = zext i8 %82 to i32 @@ -557,7 +548,7 @@ entry: %100 = load i8, ptr %98, align 1 %101 = and i8 %100, -2 %102 = or i8 %101, %99 - store i8 %102, ptr %98, align 1 + store i8 %101, ptr %98, align 1 %103 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 %104 = load i8, ptr %103, align 1 %zext86 = zext i8 %104 to i32 @@ -602,7 +593,7 @@ entry: %122 = load i8, ptr %120, align 1 %123 = and i8 %122, -2 %124 = or i8 %123, %121 - store i8 %124, ptr %120, align 1 + store i8 %123, ptr %120, align 1 %125 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 %126 = load i8, ptr %125, align 1 %zext106 = zext i8 %126 to i32 @@ -646,7 +637,7 @@ entry: %143 = load i8, ptr %141, align 1 %144 = and i8 %143, -2 %145 = or i8 %144, %142 - store i8 %145, ptr %141, align 1 + store i8 %144, ptr %141, align 1 %146 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 %147 = load i8, ptr %146, align 1 %zext125 = zext i8 %147 to i32 @@ -690,7 +681,7 @@ entry: %164 = load i8, ptr %162, align 1 %165 = and i8 %164, -2 %166 = or i8 %165, %163 - store i8 %166, ptr %162, align 1 + store i8 %165, ptr %162, align 1 %167 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 %168 = load i8, ptr %167, align 1 %zext144 = zext i8 %168 to i32 @@ -826,7 +817,7 @@ entry: %36 = load i8, ptr %34, align 1 %37 = and i8 %36, -4 %38 = or i8 %37, %35 - store i8 %38, ptr %34, align 1 + store i8 %37, ptr %34, align 1 %39 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 %40 = load i8, ptr %39, align 1 %zext33 = zext i8 %40 to i32 @@ -871,7 +862,7 @@ entry: %57 = load i8, ptr %55, align 1 %58 = and i8 %57, -4 %59 = or i8 %58, %56 - store i8 %59, ptr %55, align 1 + store i8 %58, ptr %55, align 1 %60 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 %61 = load i8, ptr %60, align 1 %zext53 = zext i8 %61 to i32 @@ -916,7 +907,7 @@ entry: %78 = load i8, ptr %76, align 1 %79 = and i8 %78, -4 %80 = or i8 %79, %77 - store i8 %80, ptr %76, align 1 + store i8 %79, ptr %76, align 1 %81 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 %82 = load i8, ptr %81, align 1 %zext73 = zext i8 %82 to i32 @@ -962,7 +953,7 @@ entry: %100 = load i8, ptr %98, align 1 %101 = and i8 %100, -4 %102 = or i8 %101, %99 - store i8 %102, ptr %98, align 1 + store i8 %101, ptr %98, align 1 %103 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 %104 = load i8, ptr %103, align 1 %zext94 = zext i8 %104 to i32 @@ -1008,7 +999,7 @@ entry: %122 = load i8, ptr %120, align 1 %123 = and i8 %122, -4 %124 = or i8 %123, %121 - store i8 %124, ptr %120, align 1 + store i8 %123, ptr %120, align 1 %125 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 %126 = load i8, ptr %125, align 1 %zext115 = zext i8 %126 to i32 @@ -1053,7 +1044,7 @@ entry: %143 = load i8, ptr %141, align 1 %144 = and i8 %143, -4 %145 = or i8 %144, %142 - store i8 %145, ptr %141, align 1 + store i8 %144, ptr %141, align 1 %146 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 %147 = load i8, ptr %146, align 1 %zext135 = zext i8 %147 to i32 @@ -1098,7 +1089,7 @@ entry: %164 = load i8, ptr %162, align 1 %165 = and i8 %164, -4 %166 = or i8 %165, %163 - store i8 %166, ptr %162, align 1 + store i8 %165, ptr %162, align 1 %167 = getelementptr inbounds [3 x i8], ptr %xx, i64 0, i64 0 %168 = load i8, ptr %167, align 1 %zext155 = zext i8 %168 to i32 diff --git a/test/test_suite2/bitstruct/bitstruct_arrays_be.c3t b/test/test_suite2/bitstruct/bitstruct_arrays_be.c3t index 4c686ad02..d2325338b 100644 --- a/test/test_suite2/bitstruct/bitstruct_arrays_be.c3t +++ b/test/test_suite2/bitstruct/bitstruct_arrays_be.c3t @@ -93,7 +93,7 @@ entry: %26 = load i8, ptr %25, align 1 %27 = and i8 %26, -16 %28 = or i8 %27, 11 - store i8 %28, ptr %25, align 1 + store i8 %27, ptr %25, align 1 %29 = getelementptr inbounds [4 x i8], ptr %xy, i64 0, i64 0 %30 = load i8, ptr %29, align 1 %zext11 = zext i8 %30 to i32 @@ -121,7 +121,7 @@ entry: %44 = load i8, ptr %43, align 1 %45 = and i8 %44, -16 %46 = or i8 %45, 14 - store i8 %46, ptr %43, align 1 + store i8 %45, ptr %43, align 1 %47 = getelementptr inbounds [4 x i8], ptr %xx, i64 0, i64 0 %48 = load i8, ptr %47, align 1 %zext17 = zext i8 %48 to i32 diff --git a/test/test_suite2/bitstruct/bitstruct_be.c3t b/test/test_suite2/bitstruct/bitstruct_be.c3t new file mode 100644 index 000000000..e35021983 --- /dev/null +++ b/test/test_suite2/bitstruct/bitstruct_be.c3t @@ -0,0 +1,336 @@ +// #target: macos-x64 +module test; +import std::io; + +bitstruct Test : int @bigendian +{ + ushort a : 0..15; + ushort b : 16..31; +} + +bitstruct Test2 : char[4] @bigendian +{ + ushort a : 0..15; + ushort b : 16..31; +} + +fn void main() +{ + IntBE x; + x.val = 123; + + io::printf("BE 123 => %d (%d)\n", (int)x, x.val); + Test abc = { .a = 0x1234, .b = 0x5678 }; + Test2 abc2 = { .a = 0x1234, .b = 0x5678 }; + char[4]* z = (char[4]*)&abc; + char[4]* z2 = (char[4]*)&abc2; + foreach (d : z2) io::printf(" %x", d); + io::println(""); + foreach (d : z) io::printf(" %x", d); + io::println(""); + io::printfln("abc.a = %x", abc.a); + abc.a = 0x1234; + abc.b = 0x5678; + io::printfln("->abc.a = %x", abc.a); + foreach (d : z) io::printf(" %x", d); + io::println(""); + + IntLE y; + y.val = 123; + io::printf("LE 123 => %d (%d)\n", (int)y, y.val); + +} + +/* #expect: test.ll + + %0 = load i32, ptr %x, align 4 + %1 = call i32 @llvm.bswap.i32(i32 %0) + store i32 2063597568, ptr %x, align 4 + store %"char[]" { ptr @.str, i64 18 }, ptr %taddr, align 8 + %2 = getelementptr inbounds { ptr, i64 }, ptr %taddr, i32 0, i32 0 + %lo = load ptr, ptr %2, align 8 + %3 = getelementptr inbounds { ptr, i64 }, ptr %taddr, i32 0, i32 1 + %hi = load i64, ptr %3, align 8 + %4 = insertvalue %variant undef, ptr %x, 0 + %5 = insertvalue %variant %4, i64 ptrtoint (ptr @"ct$int" to i64), 1 + %6 = getelementptr inbounds [2 x %variant], ptr %varargslots, i64 0, i64 0 + store %variant %5, ptr %6, align 16 + %7 = load i32, ptr %x, align 4 + %8 = call i32 @llvm.bswap.i32(i32 %7) + store i32 %8, ptr %taddr1, align 4 + %9 = insertvalue %variant undef, ptr %taddr1, 0 + %10 = insertvalue %variant %9, i64 ptrtoint (ptr @"ct$int" to i64), 1 + %11 = getelementptr inbounds [2 x %variant], ptr %varargslots, i64 0, i64 1 + store %variant %10, ptr %11, align 16 + %12 = getelementptr inbounds %"variant[]", ptr %vararg, i32 0, i32 1 + store i64 2, ptr %12, align 8 + %13 = getelementptr inbounds %"variant[]", ptr %vararg, i32 0, i32 0 + store ptr %varargslots, ptr %13, align 8 + %14 = getelementptr inbounds { ptr, i64 }, ptr %vararg, i32 0, i32 0 + %lo2 = load ptr, ptr %14, align 8 + %15 = getelementptr inbounds { ptr, i64 }, ptr %vararg, i32 0, i32 1 + %hi3 = load i64, ptr %15, align 8 + %16 = call i64 @std_io_printf(ptr %retparam, ptr %lo, i64 %hi, ptr %lo2, i64 %hi3) + %not_err = icmp eq i64 %16, 0 + br i1 %not_err, label %after_check, label %voiderr + +after_check: ; preds = %entry + br label %voiderr + +voiderr: ; preds = %after_check, %entry + store i32 873625686, ptr %abc, align 4 + store [4 x i8] c"\124Vx", ptr %abc2, align 1 + store ptr %abc, ptr %z, align 8 + store ptr %abc2, ptr %z2, align 8 + %17 = load ptr, ptr %z2, align 8 + store ptr %17, ptr %.anon, align 8 + store i64 0, ptr %.anon4, align 8 + br label %loop.cond + +loop.cond: ; preds = %voiderr15, %voiderr + %18 = load i64, ptr %.anon4, align 8 + %gt = icmp ugt i64 4, %18 + br i1 %gt, label %loop.body, label %loop.exit + +loop.body: ; preds = %loop.cond + %19 = load ptr, ptr %.anon, align 8 + %20 = load i64, ptr %.anon4, align 8 + %21 = getelementptr inbounds [4 x i8], ptr %19, i64 0, i64 %20 + %22 = load i8, ptr %21, align 1 + store i8 %22, ptr %d, align 1 + store %"char[]" { ptr @.str.1, i64 3 }, ptr %taddr6, align 8 + %23 = getelementptr inbounds { ptr, i64 }, ptr %taddr6, i32 0, i32 0 + %lo7 = load ptr, ptr %23, align 8 + %24 = getelementptr inbounds { ptr, i64 }, ptr %taddr6, i32 0, i32 1 + %hi8 = load i64, ptr %24, align 8 + %25 = insertvalue %variant undef, ptr %d, 0 + %26 = insertvalue %variant %25, i64 ptrtoint (ptr @"ct$char" to i64), 1 + %27 = getelementptr inbounds [1 x %variant], ptr %varargslots10, i64 0, i64 0 + store %variant %26, ptr %27, align 16 + %28 = getelementptr inbounds %"variant[]", ptr %vararg9, i32 0, i32 1 + store i64 1, ptr %28, align 8 + %29 = getelementptr inbounds %"variant[]", ptr %vararg9, i32 0, i32 0 + store ptr %varargslots10, ptr %29, align 8 + %30 = getelementptr inbounds { ptr, i64 }, ptr %vararg9, i32 0, i32 0 + %lo11 = load ptr, ptr %30, align 8 + %31 = getelementptr inbounds { ptr, i64 }, ptr %vararg9, i32 0, i32 1 + %hi12 = load i64, ptr %31, align 8 + %32 = call i64 @std_io_printf(ptr %retparam5, ptr %lo7, i64 %hi8, ptr %lo11, i64 %hi12) + %not_err13 = icmp eq i64 %32, 0 + br i1 %not_err13, label %after_check14, label %voiderr15 + +after_check14: ; preds = %loop.body + br label %voiderr15 + +voiderr15: ; preds = %after_check14, %loop.body + %33 = load i64, ptr %.anon4, align 8 + %add = add i64 %33, 1 + store i64 %add, ptr %.anon4, align 8 + br label %loop.cond + +loop.exit: ; preds = %loop.cond + %34 = call i32 @std_io_println(ptr @.str.2) #2 + %35 = load ptr, ptr %z, align 8 + store ptr %35, ptr %.anon16, align 8 + store i64 0, ptr %.anon17, align 8 + br label %loop.cond18 + +loop.cond18: ; preds = %voiderr32, %loop.exit + %36 = load i64, ptr %.anon17, align 8 + %gt19 = icmp ugt i64 4, %36 + br i1 %gt19, label %loop.body20, label %loop.exit34 + +loop.body20: ; preds = %loop.cond18 + %37 = load ptr, ptr %.anon16, align 8 + %38 = load i64, ptr %.anon17, align 8 + %39 = getelementptr inbounds [4 x i8], ptr %37, i64 0, i64 %38 + %40 = load i8, ptr %39, align 1 + store i8 %40, ptr %d21, align 1 + store %"char[]" { ptr @.str.3, i64 3 }, ptr %taddr23, align 8 + %41 = getelementptr inbounds { ptr, i64 }, ptr %taddr23, i32 0, i32 0 + %lo24 = load ptr, ptr %41, align 8 + %42 = getelementptr inbounds { ptr, i64 }, ptr %taddr23, i32 0, i32 1 + %hi25 = load i64, ptr %42, align 8 + %43 = insertvalue %variant undef, ptr %d21, 0 + %44 = insertvalue %variant %43, i64 ptrtoint (ptr @"ct$char" to i64), 1 + %45 = getelementptr inbounds [1 x %variant], ptr %varargslots27, i64 0, i64 0 + store %variant %44, ptr %45, align 16 + %46 = getelementptr inbounds %"variant[]", ptr %vararg26, i32 0, i32 1 + store i64 1, ptr %46, align 8 + %47 = getelementptr inbounds %"variant[]", ptr %vararg26, i32 0, i32 0 + store ptr %varargslots27, ptr %47, align 8 + %48 = getelementptr inbounds { ptr, i64 }, ptr %vararg26, i32 0, i32 0 + %lo28 = load ptr, ptr %48, align 8 + %49 = getelementptr inbounds { ptr, i64 }, ptr %vararg26, i32 0, i32 1 + %hi29 = load i64, ptr %49, align 8 + %50 = call i64 @std_io_printf(ptr %retparam22, ptr %lo24, i64 %hi25, ptr %lo28, i64 %hi29) + %not_err30 = icmp eq i64 %50, 0 + br i1 %not_err30, label %after_check31, label %voiderr32 + +after_check31: ; preds = %loop.body20 + br label %voiderr32 + +voiderr32: ; preds = %after_check31, %loop.body20 + %51 = load i64, ptr %.anon17, align 8 + %add33 = add i64 %51, 1 + store i64 %add33, ptr %.anon17, align 8 + br label %loop.cond18 + +loop.exit34: ; preds = %loop.cond18 + %52 = call i32 @std_io_println(ptr @.str.4) #2 + store %"char[]" { ptr @.str.5, i64 10 }, ptr %taddr36, align 8 + %53 = getelementptr inbounds { ptr, i64 }, ptr %taddr36, i32 0, i32 0 + %lo37 = load ptr, ptr %53, align 8 + %54 = getelementptr inbounds { ptr, i64 }, ptr %taddr36, i32 0, i32 1 + %hi38 = load i64, ptr %54, align 8 + %55 = load i32, ptr %abc, align 4 + %56 = call i32 @llvm.bswap.i32(i32 %55) + %57 = and i32 65535, %56 + %ztrunc = trunc i32 %57 to i16 + store i16 %ztrunc, ptr %taddr41, align 2 + %58 = insertvalue %variant undef, ptr %taddr41, 0 + %59 = insertvalue %variant %58, i64 ptrtoint (ptr @"ct$ushort" to i64), 1 + %60 = getelementptr inbounds [1 x %variant], ptr %varargslots40, i64 0, i64 0 + store %variant %59, ptr %60, align 16 + %61 = getelementptr inbounds %"variant[]", ptr %vararg39, i32 0, i32 1 + store i64 1, ptr %61, align 8 + %62 = getelementptr inbounds %"variant[]", ptr %vararg39, i32 0, i32 0 + store ptr %varargslots40, ptr %62, align 8 + %63 = getelementptr inbounds { ptr, i64 }, ptr %vararg39, i32 0, i32 0 + %lo42 = load ptr, ptr %63, align 8 + %64 = getelementptr inbounds { ptr, i64 }, ptr %vararg39, i32 0, i32 1 + %hi43 = load i64, ptr %64, align 8 + %65 = call i64 @std_io_printfln(ptr %retparam35, ptr %lo37, i64 %hi38, ptr %lo42, i64 %hi43) + %not_err44 = icmp eq i64 %65, 0 + br i1 %not_err44, label %after_check45, label %voiderr46 + +after_check45: ; preds = %loop.exit34 + br label %voiderr46 + +voiderr46: ; preds = %after_check45, %loop.exit34 + %66 = load i32, ptr %abc, align 4 + %67 = call i32 @llvm.bswap.i32(i32 %66) + %68 = and i32 %67, -65536 + %69 = or i32 %68, 4660 + %70 = call i32 @llvm.bswap.i32(i32 %69) + store i32 %70, ptr %abc, align 4 + %71 = load i32, ptr %abc, align 4 + %72 = call i32 @llvm.bswap.i32(i32 %71) + %73 = and i32 %72, 65535 + %74 = or i32 %73, 1450704896 + %75 = call i32 @llvm.bswap.i32(i32 %74) + store i32 %75, ptr %abc, align 4 + store %"char[]" { ptr @.str.6, i64 12 }, ptr %taddr48, align 8 + %76 = getelementptr inbounds { ptr, i64 }, ptr %taddr48, i32 0, i32 0 + %lo49 = load ptr, ptr %76, align 8 + %77 = getelementptr inbounds { ptr, i64 }, ptr %taddr48, i32 0, i32 1 + %hi50 = load i64, ptr %77, align 8 + %78 = load i32, ptr %abc, align 4 + %79 = call i32 @llvm.bswap.i32(i32 %78) + %80 = and i32 65535, %79 + %ztrunc53 = trunc i32 %80 to i16 + store i16 %ztrunc53, ptr %taddr54, align 2 + %81 = insertvalue %variant undef, ptr %taddr54, 0 + %82 = insertvalue %variant %81, i64 ptrtoint (ptr @"ct$ushort" to i64), 1 + %83 = getelementptr inbounds [1 x %variant], ptr %varargslots52, i64 0, i64 0 + store %variant %82, ptr %83, align 16 + %84 = getelementptr inbounds %"variant[]", ptr %vararg51, i32 0, i32 1 + store i64 1, ptr %84, align 8 + %85 = getelementptr inbounds %"variant[]", ptr %vararg51, i32 0, i32 0 + store ptr %varargslots52, ptr %85, align 8 + %86 = getelementptr inbounds { ptr, i64 }, ptr %vararg51, i32 0, i32 0 + %lo55 = load ptr, ptr %86, align 8 + %87 = getelementptr inbounds { ptr, i64 }, ptr %vararg51, i32 0, i32 1 + %hi56 = load i64, ptr %87, align 8 + %88 = call i64 @std_io_printfln(ptr %retparam47, ptr %lo49, i64 %hi50, ptr %lo55, i64 %hi56) + %not_err57 = icmp eq i64 %88, 0 + br i1 %not_err57, label %after_check58, label %voiderr59 + +after_check58: ; preds = %voiderr46 + br label %voiderr59 + +voiderr59: ; preds = %after_check58, %voiderr46 + %89 = load ptr, ptr %z, align 8 + store ptr %89, ptr %.anon60, align 8 + store i64 0, ptr %.anon61, align 8 + br label %loop.cond62 + +loop.cond62: ; preds = %voiderr76, %voiderr59 + %90 = load i64, ptr %.anon61, align 8 + %gt63 = icmp ugt i64 4, %90 + br i1 %gt63, label %loop.body64, label %loop.exit78 + +loop.body64: ; preds = %loop.cond62 + %91 = load ptr, ptr %.anon60, align 8 + %92 = load i64, ptr %.anon61, align 8 + %93 = getelementptr inbounds [4 x i8], ptr %91, i64 0, i64 %92 + %94 = load i8, ptr %93, align 1 + store i8 %94, ptr %d65, align 1 + store %"char[]" { ptr @.str.7, i64 3 }, ptr %taddr67, align 8 + %95 = getelementptr inbounds { ptr, i64 }, ptr %taddr67, i32 0, i32 0 + %lo68 = load ptr, ptr %95, align 8 + %96 = getelementptr inbounds { ptr, i64 }, ptr %taddr67, i32 0, i32 1 + %hi69 = load i64, ptr %96, align 8 + %97 = insertvalue %variant undef, ptr %d65, 0 + %98 = insertvalue %variant %97, i64 ptrtoint (ptr @"ct$char" to i64), 1 + %99 = getelementptr inbounds [1 x %variant], ptr %varargslots71, i64 0, i64 0 + store %variant %98, ptr %99, align 16 + %100 = getelementptr inbounds %"variant[]", ptr %vararg70, i32 0, i32 1 + store i64 1, ptr %100, align 8 + %101 = getelementptr inbounds %"variant[]", ptr %vararg70, i32 0, i32 0 + store ptr %varargslots71, ptr %101, align 8 + %102 = getelementptr inbounds { ptr, i64 }, ptr %vararg70, i32 0, i32 0 + %lo72 = load ptr, ptr %102, align 8 + %103 = getelementptr inbounds { ptr, i64 }, ptr %vararg70, i32 0, i32 1 + %hi73 = load i64, ptr %103, align 8 + %104 = call i64 @std_io_printf(ptr %retparam66, ptr %lo68, i64 %hi69, ptr %lo72, i64 %hi73) + %not_err74 = icmp eq i64 %104, 0 + br i1 %not_err74, label %after_check75, label %voiderr76 + +after_check75: ; preds = %loop.body64 + br label %voiderr76 + +voiderr76: ; preds = %after_check75, %loop.body64 + %105 = load i64, ptr %.anon61, align 8 + %add77 = add i64 %105, 1 + store i64 %add77, ptr %.anon61, align 8 + br label %loop.cond62 + +loop.exit78: ; preds = %loop.cond62 + %106 = call i32 @std_io_println(ptr @.str.8) #2 + store i32 0, ptr %y, align 4 + %107 = load i32, ptr %y, align 4 + store i32 123, ptr %y, align 4 + store %"char[]" { ptr @.str.9, i64 18 }, ptr %taddr80, align 8 + %108 = getelementptr inbounds { ptr, i64 }, ptr %taddr80, i32 0, i32 0 + %lo81 = load ptr, ptr %108, align 8 + %109 = getelementptr inbounds { ptr, i64 }, ptr %taddr80, i32 0, i32 1 + %hi82 = load i64, ptr %109, align 8 + %110 = insertvalue %variant undef, ptr %y, 0 + %111 = insertvalue %variant %110, i64 ptrtoint (ptr @"ct$int" to i64), 1 + %112 = getelementptr inbounds [2 x %variant], ptr %varargslots84, i64 0, i64 0 + store %variant %111, ptr %112, align 16 + %113 = load i32, ptr %y, align 4 + store i32 %113, ptr %taddr85, align 4 + %114 = insertvalue %variant undef, ptr %taddr85, 0 + %115 = insertvalue %variant %114, i64 ptrtoint (ptr @"ct$int" to i64), 1 + %116 = getelementptr inbounds [2 x %variant], ptr %varargslots84, i64 0, i64 1 + store %variant %115, ptr %116, align 16 + %117 = getelementptr inbounds %"variant[]", ptr %vararg83, i32 0, i32 1 + store i64 2, ptr %117, align 8 + %118 = getelementptr inbounds %"variant[]", ptr %vararg83, i32 0, i32 0 + store ptr %varargslots84, ptr %118, align 8 + %119 = getelementptr inbounds { ptr, i64 }, ptr %vararg83, i32 0, i32 0 + %lo86 = load ptr, ptr %119, align 8 + %120 = getelementptr inbounds { ptr, i64 }, ptr %vararg83, i32 0, i32 1 + %hi87 = load i64, ptr %120, align 8 + %121 = call i64 @std_io_printf(ptr %retparam79, ptr %lo81, i64 %hi82, ptr %lo86, i64 %hi87) + %not_err88 = icmp eq i64 %121, 0 + br i1 %not_err88, label %after_check89, label %voiderr90 + +after_check89: ; preds = %loop.exit78 + br label %voiderr90 + +voiderr90: ; preds = %after_check89, %loop.exit78 + ret void +} \ No newline at end of file