diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index 74cb46ceb..c5b7ebae1 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -2407,6 +2407,13 @@ gb_internal lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) { // boolean -> boolean/integer if (is_type_boolean(src) && (is_type_boolean(dst) || is_type_integer(dst))) { LLVMValueRef b = LLVMBuildICmp(p->builder, LLVMIntNE, value.value, LLVMConstNull(lb_type(m, value.type)), ""); + if (type_size_of(default_type(dst)) > 1 && is_type_different_to_arch_endianness(dst)) { + Type *platform_dst_type = integer_endian_type_to_platform_type(dst); + lbValue res = {}; + res.value = LLVMBuildIntCast2(p->builder, b, lb_type(m, platform_dst_type), false, ""); + res.type = t; + return lb_emit_byte_swap(p, res, t); + } lbValue res = {}; res.value = LLVMBuildIntCast2(p->builder, b, lb_type(m, t), false, ""); res.type = t; diff --git a/tests/issues/run.sh b/tests/issues/run.sh index f7fcfe4cc..2138e3f0b 100755 --- a/tests/issues/run.sh +++ b/tests/issues/run.sh @@ -95,6 +95,7 @@ $ODIN test ../test_issue_7356.odin $COMMON $ODIN build ../test_issue_7167.odin $COMMON $ODIN build ../test_issue_7188.odin $COMMON $ODIN check ../test_issue_7260.odin -no-entry-point $COMMON_CHECK +$ODIN test ../test_issue_bool_to_be_conversion.odin $COMMON $ODIN check ../test_issue_foreign_redeclaration.odin -no-entry-point $COMMON_CHECK if [[ $($ODIN check ../test_issue_foreign_redeclaration_mismatch.odin -no-entry-point $COMMON_CHECK 2>&1 >/dev/null | grep -c "Error:") -eq 1 ]]; then diff --git a/tests/issues/test_issue_bool_to_be_conversion.odin b/tests/issues/test_issue_bool_to_be_conversion.odin new file mode 100644 index 000000000..5801ebe20 --- /dev/null +++ b/tests/issues/test_issue_bool_to_be_conversion.odin @@ -0,0 +1,37 @@ +package test_issues + +import "core:testing" + +// Converting a boolean to a big-endian integer skipped the endian fixup that the integer source +// path performs, so the result carried a native bit pattern labelled big-endian. The checker +// folded the same conversion to the right value, so only the runtime disagreed. + +@(test) +bool_to_big_endian :: proc(t: ^testing.T) { + b: bool = true + f: bool = false + b8v: b8 = true + b16v: b16 = true + b32v: b32 = true + b64v: b64 = true + i: int = 1 + + testing.expect_value(t, int(i16be(b)), 1) + testing.expect_value(t, int(u32be(b)), 1) + testing.expect_value(t, int(u64be(b)), 1) + testing.expect_value(t, int(u128be(b)), 1) + testing.expect_value(t, int(i16be(f)), 0) + + testing.expect_value(t, int(i16be(b8v)), 1) + testing.expect_value(t, int(i16be(b16v)), 1) + testing.expect_value(t, int(i16be(b32v)), 1) + testing.expect_value(t, int(i16be(b64v)), 1) + + // the little-endian target and the integer source were already correct + testing.expect_value(t, int(i16le(b)), 1) + testing.expect_value(t, int(i16be(i)), 1) + + // the bytes have to actually be big-endian, not a native pattern relabelled + testing.expect_value(t, transmute([4]u8)u32be(b), transmute([4]u8)u32be(i)) + testing.expect_value(t, transmute([4]u8)u32be(b), [4]u8{0, 0, 0, 1}) +}