cranelift: Add support for i128 immediates in parser

This commit is contained in:
Afonso Bordado
2021-09-14 15:21:37 +01:00
parent 47490b4383
commit 8115e7252d
2 changed files with 51 additions and 0 deletions

View File

@@ -86,6 +86,7 @@ impl DataValue {
DataValue::I16(i) => dst[..2].copy_from_slice(&i.to_ne_bytes()[..]), DataValue::I16(i) => dst[..2].copy_from_slice(&i.to_ne_bytes()[..]),
DataValue::I32(i) => dst[..4].copy_from_slice(&i.to_ne_bytes()[..]), DataValue::I32(i) => dst[..4].copy_from_slice(&i.to_ne_bytes()[..]),
DataValue::I64(i) => dst[..8].copy_from_slice(&i.to_ne_bytes()[..]), DataValue::I64(i) => dst[..8].copy_from_slice(&i.to_ne_bytes()[..]),
DataValue::I128(i) => dst[..16].copy_from_slice(&i.to_ne_bytes()[..]),
DataValue::F32(f) => dst[..4].copy_from_slice(&f.bits().to_ne_bytes()[..]), DataValue::F32(f) => dst[..4].copy_from_slice(&f.bits().to_ne_bytes()[..]),
DataValue::F64(f) => dst[..8].copy_from_slice(&f.bits().to_ne_bytes()[..]), DataValue::F64(f) => dst[..8].copy_from_slice(&f.bits().to_ne_bytes()[..]),
DataValue::V128(v) => dst[..16].copy_from_slice(&v[..]), DataValue::V128(v) => dst[..16].copy_from_slice(&v[..]),
@@ -104,6 +105,7 @@ impl DataValue {
types::I16 => DataValue::I16(i16::from_ne_bytes(src[..2].try_into().unwrap())), types::I16 => DataValue::I16(i16::from_ne_bytes(src[..2].try_into().unwrap())),
types::I32 => DataValue::I32(i32::from_ne_bytes(src[..4].try_into().unwrap())), types::I32 => DataValue::I32(i32::from_ne_bytes(src[..4].try_into().unwrap())),
types::I64 => DataValue::I64(i64::from_ne_bytes(src[..8].try_into().unwrap())), types::I64 => DataValue::I64(i64::from_ne_bytes(src[..8].try_into().unwrap())),
types::I128 => DataValue::I128(i128::from_ne_bytes(src[..16].try_into().unwrap())),
types::F32 => DataValue::F32(Ieee32::with_bits(u32::from_ne_bytes( types::F32 => DataValue::F32(Ieee32::with_bits(u32::from_ne_bytes(
src[..4].try_into().unwrap(), src[..4].try_into().unwrap(),
))), ))),

View File

@@ -921,6 +921,49 @@ impl<'a> Parser<'a> {
} }
} }
// Match and consume an i128 immediate.
fn match_imm128(&mut self, err_msg: &str) -> ParseResult<i128> {
if let Some(Token::Integer(text)) = self.token() {
self.consume();
let negative = text.starts_with('-');
let positive = text.starts_with('+');
let text = if negative || positive {
// Strip sign prefix.
&text[1..]
} else {
text
};
// Parse the text value; the lexer gives us raw text that looks like an integer.
let value = if text.starts_with("0x") {
// Skip underscores.
let text = text.replace("_", "");
// Parse it as a i128 in hexadecimal form.
u128::from_str_radix(&text[2..], 16)
.map_err(|_| self.error("unable to parse i128 as a hexadecimal immediate"))?
} else {
// Parse it as a i128 to check for overflow and other issues.
text.parse()
.map_err(|_| self.error("expected i128 decimal immediate"))?
};
// Apply sign if necessary.
let signed = if negative {
let value = value.wrapping_neg() as i128;
if value > 0 {
return Err(self.error("negative number too small"));
}
value
} else {
value as i128
};
Ok(signed)
} else {
err!(self.loc, err_msg)
}
}
// Match and consume an optional offset32 immediate. // Match and consume an optional offset32 immediate.
// //
// Note that this will match an empty string as an empty offset, and that if an offset is // Note that this will match an empty string as an empty offset, and that if an offset is
@@ -2805,6 +2848,7 @@ impl<'a> Parser<'a> {
I16 => DataValue::from(self.match_imm16("expected an i16")?), I16 => DataValue::from(self.match_imm16("expected an i16")?),
I32 => DataValue::from(self.match_imm32("expected an i32")?), I32 => DataValue::from(self.match_imm32("expected an i32")?),
I64 => DataValue::from(Into::<i64>::into(self.match_imm64("expected an i64")?)), I64 => DataValue::from(Into::<i64>::into(self.match_imm64("expected an i64")?)),
I128 => DataValue::from(self.match_imm128("expected an i64")?),
F32 => DataValue::from(self.match_ieee32("expected an f32")?), F32 => DataValue::from(self.match_ieee32("expected an f32")?),
F64 => DataValue::from(self.match_ieee64("expected an f64")?), F64 => DataValue::from(self.match_ieee64("expected an f64")?),
_ if ty.is_vector() => { _ if ty.is_vector() => {
@@ -4126,6 +4170,11 @@ mod tests {
assert_eq!(parse("16", I16).to_string(), "16"); assert_eq!(parse("16", I16).to_string(), "16");
assert_eq!(parse("32", I32).to_string(), "32"); assert_eq!(parse("32", I32).to_string(), "32");
assert_eq!(parse("64", I64).to_string(), "64"); assert_eq!(parse("64", I64).to_string(), "64");
assert_eq!(
parse("0x01234567_01234567_01234567_01234567", I128).to_string(),
"1512366032949150931280199141537564007"
);
assert_eq!(parse("1234567", I128).to_string(), "1234567");
assert_eq!(parse("0x32.32", F32).to_string(), "0x1.919000p5"); assert_eq!(parse("0x32.32", F32).to_string(), "0x1.919000p5");
assert_eq!(parse("0x64.64", F64).to_string(), "0x1.9190000000000p6"); assert_eq!(parse("0x64.64", F64).to_string(), "0x1.9190000000000p6");
assert_eq!(parse("true", B1).to_string(), "true"); assert_eq!(parse("true", B1).to_string(), "true");