From db5ffdedf7ed64bde30a55e14e67efbb0f6ea538 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 17 Nov 2018 18:52:47 +0100 Subject: [PATCH] Implement bswap intrinsic --- example/mini_core.rs | 11 ++++ example/mini_core_hello_world.rs | 5 ++ patches/0013-Patch-away-bswap-usage.patch | 25 -------- src/intrinsics.rs | 73 +++++++++++++++++++++++ 4 files changed, 89 insertions(+), 25 deletions(-) delete mode 100644 patches/0013-Patch-away-bswap-usage.patch diff --git a/example/mini_core.rs b/example/mini_core.rs index dd42257b194..56ab9578e78 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -208,6 +208,16 @@ impl PartialEq for u32 { } } + +impl PartialEq for u64 { + fn eq(&self, other: &u64) -> bool { + (*self) == (*other) + } + fn ne(&self, other: &u64) -> bool { + (*self) != (*other) + } +} + impl PartialEq for usize { fn eq(&self, other: &usize) -> bool { (*self) == (*other) @@ -375,6 +385,7 @@ pub mod intrinsics { pub fn ctlz_nonzero(x: T) -> T; pub fn needs_drop() -> bool; pub fn bitreverse(x: T) -> T; + pub fn bswap(x: T) -> T; } } diff --git a/example/mini_core_hello_world.rs b/example/mini_core_hello_world.rs index fdd26f8791d..f9e820da76c 100644 --- a/example/mini_core_hello_world.rs +++ b/example/mini_core_hello_world.rs @@ -139,6 +139,11 @@ fn main() { assert_eq!(intrinsics::bitreverse(0b10101000u8), 0b00010101u8); + assert_eq!(intrinsics::bswap(0xabu8), 0xabu8); + assert_eq!(intrinsics::bswap(0xddccu16), 0xccddu16); + assert_eq!(intrinsics::bswap(0xffee_ddccu32), 0xccdd_eeffu32); + assert_eq!(intrinsics::bswap(0x1234_5678_ffee_ddccu64), 0xccdd_eeff_7856_3412u64); + assert_eq!(intrinsics::size_of_val(hello) as u8, 6); let chars = &['C', 'h', 'a', 'r', 's']; diff --git a/patches/0013-Patch-away-bswap-usage.patch b/patches/0013-Patch-away-bswap-usage.patch deleted file mode 100644 index e29042c7297..00000000000 --- a/patches/0013-Patch-away-bswap-usage.patch +++ /dev/null @@ -1,25 +0,0 @@ -From da996dae0b95f986de46a916aca00e03257ba4f9 Mon Sep 17 00:00:00 2001 -From: bjorn3 -Date: Wed, 30 Jan 2019 14:51:57 +0100 -Subject: [PATCH] Patch away bswap usage - ---- - src/libcore/num/mod.rs | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs -index f928d40..6a146f5 100644 ---- a/src/libcore/num/mod.rs -+++ b/src/libcore/num/mod.rs -@@ -2303,7 +2303,7 @@ assert_eq!(m, ", $swapped, "); - #[stable(feature = "rust1", since = "1.0.0")] - #[inline] - pub const fn swap_bytes(self) -> Self { -- intrinsics::bswap(self as $ActualT) as Self -+ 42 // bswap is unsupported by cg_clif - } - } - --- -2.11.0 - diff --git a/src/intrinsics.rs b/src/intrinsics.rs index 18a300ed12e..4f455454a2f 100644 --- a/src/intrinsics.rs +++ b/src/intrinsics.rs @@ -415,6 +415,79 @@ pub fn codegen_intrinsic_call<'a, 'tcx: 'a>( let res = CValue::by_val(fx.bcx.ins().bitrev(arg), fx.layout_of(T)); ret.write_cvalue(fx, res); }; + bswap, (v arg) { + // FIXME(CraneStation/cranelift#794) add bswap instruction to cranelift + fn swap(bcx: &mut FunctionBuilder, v: Value) -> Value { + match bcx.func.dfg.value_type(v) { + types::I8 => v, + + // https://code.woboq.org/gcc/include/bits/byteswap.h.html + types::I16 => { + let tmp1 = bcx.ins().ishl_imm(v, 8); + let n1 = bcx.ins().band_imm(tmp1, 0xFF00); + + let tmp2 = bcx.ins().ushr_imm(v, 8); + let n2 = bcx.ins().band_imm(tmp2, 0x00FF); + + bcx.ins().bor(n1, n2) + } + types::I32 => { + let tmp1 = bcx.ins().ishl_imm(v, 24); + let n1 = bcx.ins().band_imm(tmp1, 0xFF00_0000); + + let tmp2 = bcx.ins().ishl_imm(v, 8); + let n2 = bcx.ins().band_imm(tmp2, 0x00FF_0000); + + let tmp3 = bcx.ins().ushr_imm(v, 8); + let n3 = bcx.ins().band_imm(tmp3, 0x0000_FF00); + + let tmp4 = bcx.ins().ushr_imm(v, 24); + let n4 = bcx.ins().band_imm(tmp4, 0x0000_00FF); + + let or_tmp1 = bcx.ins().bor(n1, n2); + let or_tmp2 = bcx.ins().bor(n3, n4); + bcx.ins().bor(or_tmp1, or_tmp2) + } + types::I64 => { + let tmp1 = bcx.ins().ishl_imm(v, 56); + let n1 = bcx.ins().band_imm(tmp1, 0xFF00_0000_0000_0000u64 as i64); + + let tmp2 = bcx.ins().ishl_imm(v, 40); + let n2 = bcx.ins().band_imm(tmp2, 0x00FF_0000_0000_0000u64 as i64); + + let tmp3 = bcx.ins().ishl_imm(v, 24); + let n3 = bcx.ins().band_imm(tmp3, 0x0000_FF00_0000_0000u64 as i64); + + let tmp4 = bcx.ins().ishl_imm(v, 8); + let n4 = bcx.ins().band_imm(tmp4, 0x0000_00FF_0000_0000u64 as i64); + + let tmp5 = bcx.ins().ushr_imm(v, 8); + let n5 = bcx.ins().band_imm(tmp5, 0x0000_0000_FF00_0000u64 as i64); + + let tmp6 = bcx.ins().ushr_imm(v, 24); + let n6 = bcx.ins().band_imm(tmp6, 0x0000_0000_00FF_0000u64 as i64); + + let tmp7 = bcx.ins().ushr_imm(v, 40); + let n7 = bcx.ins().band_imm(tmp7, 0x0000_0000_0000_FF00u64 as i64); + + let tmp8 = bcx.ins().ushr_imm(v, 56); + let n8 = bcx.ins().band_imm(tmp8, 0x0000_0000_0000_00FFu64 as i64); + + let or_tmp1 = bcx.ins().bor(n1, n2); + let or_tmp2 = bcx.ins().bor(n3, n4); + let or_tmp3 = bcx.ins().bor(n5, n6); + let or_tmp4 = bcx.ins().bor(n7, n8); + + let or_tmp5 = bcx.ins().bor(or_tmp1, or_tmp2); + let or_tmp6 = bcx.ins().bor(or_tmp3, or_tmp4); + bcx.ins().bor(or_tmp5, or_tmp6) + } + ty => unimplemented!("bwap {}", ty), + } + }; + let res = CValue::by_val(swap(&mut fx.bcx, arg), fx.layout_of(T)); + ret.write_cvalue(fx, res); + }; needs_drop, () { let needs_drop = if T.needs_drop(fx.tcx, ParamEnv::reveal_all()) { 1