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] <test_const>:
 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.
This commit is contained in:
Andrew Brown
2019-08-02 13:27:13 -07:00
committed by Dan Gohman
parent cb041407c1
commit 020e5987d3
2 changed files with 22 additions and 6 deletions

View File

@@ -275,7 +275,7 @@ impl Display for Uimm128 {
fn fmt(&self, f: &mut Formatter) -> fmt::Result { fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "0x")?; write!(f, "0x")?;
let mut anything_written = false; let mut anything_written = false;
for &b in self.0.iter() { for &b in self.0.iter().rev() {
if b == 0 && !anything_written { if b == 0 && !anything_written {
continue; continue;
} else { } else {
@@ -293,7 +293,7 @@ impl Display for Uimm128 {
impl From<u64> for Uimm128 { impl From<u64> for Uimm128 {
fn from(x: u64) -> Self { fn from(x: u64) -> Self {
let mut buffer: [u8; 16] = [0; 16]; // zero-fill 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) Uimm128(buffer)
} }
} }
@@ -316,15 +316,15 @@ impl FromStr for Uimm128 {
Err("Expected a hexadecimal string, e.g. 0x1234") Err("Expected a hexadecimal string, e.g. 0x1234")
} else if s.len() % 2 != 0 { } else if s.len() % 2 != 0 {
Err("Hexadecimal string must have an even number of digits") 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") Err("Hexadecimal string has too many digits to fit in a 128-bit vector")
} else { } else {
let mut buffer = [0; 16]; // zero-fill 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) { for i in (2..s.len()).step_by(2) {
let byte = u8::from_str_radix(&s[i..i + 2], 16) let byte = u8::from_str_radix(&s[i..i + 2], 16)
.or_else(|_| Err("Unable to parse as hexadecimal"))?; .or_else(|_| Err("Unable to parse as hexadecimal"))?;
let position = start_at + (i / 2); let position = start_at - (i / 2);
buffer[position] = byte; buffer[position] = byte;
} }
Ok(Uimm128(buffer)) Ok(Uimm128(buffer))
@@ -984,6 +984,22 @@ mod tests {
); );
} }
#[test]
fn uimm128_endianness() {
assert_eq!(
"0x42".parse::<Uimm128>().unwrap().0,
[0x42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
);
assert_eq!(
"0x00".parse::<Uimm128>().unwrap().0,
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
);
assert_eq!(
"0x12345678".parse::<Uimm128>().unwrap().0,
[0x78, 0x56, 0x34, 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
)
}
#[test] #[test]
fn format_offset32() { fn format_offset32() {
assert_eq!(Offset32(0).to_string(), ""); assert_eq!(Offset32(0).to_string(), "");

View File

@@ -10,4 +10,4 @@ ebb0:
return v0 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]