From 020e5987d30be6bbb15d07c18db185e0b12ee1ec Mon Sep 17 00:00:00 2001 From: Andrew Brown Date: Fri, 2 Aug 2019 13:27:13 -0700 Subject: [PATCH] Use little-endian ordering for CLIF vconst immediate Examining wasm-objdump revealed that it stores SIMD constants in little-endian order, e.g.: 000071 func[2] : 000072: fd 02 01 00 00 00 02 00 00 | v128.const 0x00000001 0x00000002 0x00000003 0x00000004 00007b: 00 03 00 00 00 04 00 00 00 | 000084: fd 0d 03 | i32x4.extract_lane 3 000087: 0b | end This change avoids confusion by making the CLIF representation use little-endian order as well. --- cranelift/codegen/src/ir/immediates.rs | 26 +++++++++++++++---- .../filetests/isa/x86/rodata-vconst.clif | 2 +- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/cranelift/codegen/src/ir/immediates.rs b/cranelift/codegen/src/ir/immediates.rs index 5c36f362ab..8917d96d4b 100644 --- a/cranelift/codegen/src/ir/immediates.rs +++ b/cranelift/codegen/src/ir/immediates.rs @@ -275,7 +275,7 @@ impl Display for Uimm128 { fn fmt(&self, f: &mut Formatter) -> fmt::Result { write!(f, "0x")?; let mut anything_written = false; - for &b in self.0.iter() { + for &b in self.0.iter().rev() { if b == 0 && !anything_written { continue; } else { @@ -293,7 +293,7 @@ impl Display for Uimm128 { impl From for Uimm128 { fn from(x: u64) -> Self { let mut buffer: [u8; 16] = [0; 16]; // zero-fill - (0..8).for_each(|byte| buffer[15 - byte] = (x >> (byte as u64 * 8) & 0xff) as u8); // insert each byte from the u64 into v after byte position 8 + (0..8).for_each(|byte| buffer[byte] = (x >> (byte as u64 * 8) & 0xff) as u8); // insert each byte from the u64 into v in little-endian order Uimm128(buffer) } } @@ -316,15 +316,15 @@ impl FromStr for Uimm128 { Err("Expected a hexadecimal string, e.g. 0x1234") } else if s.len() % 2 != 0 { Err("Hexadecimal string must have an even number of digits") - } else if s.len() > 32 { + } else if s.len() > 34 { Err("Hexadecimal string has too many digits to fit in a 128-bit vector") } else { let mut buffer = [0; 16]; // zero-fill - let start_at = 16 - s.len() / 2; + let start_at = s.len() / 2 - 1; for i in (2..s.len()).step_by(2) { let byte = u8::from_str_radix(&s[i..i + 2], 16) .or_else(|_| Err("Unable to parse as hexadecimal"))?; - let position = start_at + (i / 2); + let position = start_at - (i / 2); buffer[position] = byte; } Ok(Uimm128(buffer)) @@ -984,6 +984,22 @@ mod tests { ); } + #[test] + fn uimm128_endianness() { + assert_eq!( + "0x42".parse::().unwrap().0, + [0x42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + ); + assert_eq!( + "0x00".parse::().unwrap().0, + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + ); + assert_eq!( + "0x12345678".parse::().unwrap().0, + [0x78, 0x56, 0x34, 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + ) + } + #[test] fn format_offset32() { assert_eq!(Offset32(0).to_string(), ""); diff --git a/cranelift/filetests/filetests/isa/x86/rodata-vconst.clif b/cranelift/filetests/filetests/isa/x86/rodata-vconst.clif index 772cf3b03c..fd029b678d 100644 --- a/cranelift/filetests/filetests/isa/x86/rodata-vconst.clif +++ b/cranelift/filetests/filetests/isa/x86/rodata-vconst.clif @@ -10,4 +10,4 @@ ebb0: return v0 } -; sameln: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 34] +; sameln: [34, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]