From 0ccf103160f0aaf8854306979efdee6a02562236 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 27 Mar 2021 12:48:29 +0000 Subject: [PATCH] Fix byte swapping for endian specific types in `-llvm-api` --- core/runtime/internal.odin | 17 +++++++++++++---- src/llvm_backend.cpp | 11 +++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/core/runtime/internal.odin b/core/runtime/internal.odin index d04c6997b..f9328bdb0 100644 --- a/core/runtime/internal.odin +++ b/core/runtime/internal.odin @@ -9,24 +9,33 @@ bswap_32 :: proc "none" (x: u32) -> u32 { } bswap_64 :: proc "none" (x: u64) -> u64 { - return u64(bswap_32(u32(x))) | u64(bswap_32(u32(x>>32))); + z := x; + z = (z & 0x00000000ffffffff) << 32 | (z & 0xffffffff00000000) >> 32; + z = (z & 0x0000ffff0000ffff) << 16 | (z & 0xffff0000ffff0000) >> 16; + z = (z & 0x00ff00ff00ff00ff) << 8 | (z & 0xff00ff00ff00ff00) >> 8; + return z; } bswap_128 :: proc "none" (x: u128) -> u128 { - return u128(bswap_64(u64(x))) | u128(bswap_64(u64(x>>64))); + z := transmute([4]u32)x; + z[0] = bswap_32(z[3]); + z[1] = bswap_32(z[2]); + z[2] = bswap_32(z[1]); + z[3] = bswap_32(z[0]); + return transmute(u128)z; } bswap_f32 :: proc "none" (f: f32) -> f32 { x := transmute(u32)f; - z := x>>24 | (x>>8)&0xff00 | (x<<8)&0xff0000 | x<<24; + z := bswap_32(x); return transmute(f32)z; } bswap_f64 :: proc "none" (f: f64) -> f64 { x := transmute(u64)f; - z := u64(bswap_32(u32(x))) | u64(bswap_32(u32(x>>32))); + z := bswap_64(x); return transmute(f64)z; } diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index e7ba224b3..e199b01a0 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -6886,6 +6886,17 @@ lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) { i64 sz = type_size_of(default_type(src)); i64 dz = type_size_of(default_type(dst)); + + if (sz == dz) { + if (dz > 1 && !types_have_same_internal_endian(src, dst)) { + return lb_emit_byte_swap(p, value, t); + } + lbValue res = {}; + res.value = value.value; + res.type = t; + return res; + } + if (sz > 1 && is_type_different_to_arch_endianness(src)) { Type *platform_src_type = integer_endian_type_to_platform_type(src); value = lb_emit_byte_swap(p, value, platform_src_type);