浏览代码

Fix byte swapping for endian specific types in `-llvm-api`

gingerBill 4 年之前
父节点
当前提交
0ccf103160
共有 2 个文件被更改,包括 24 次插入4 次删除
  1. 13 4
      core/runtime/internal.odin
  2. 11 0
      src/llvm_backend.cpp

+ 13 - 4
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;
 }
 

+ 11 - 0
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);