cranelift: Add support for i128 immediates in parser
This commit is contained in:
@@ -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.
|
||||
//
|
||||
// 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")?),
|
||||
I32 => DataValue::from(self.match_imm32("expected an i32")?),
|
||||
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")?),
|
||||
F64 => DataValue::from(self.match_ieee64("expected an f64")?),
|
||||
_ if ty.is_vector() => {
|
||||
@@ -4126,6 +4170,11 @@ mod tests {
|
||||
assert_eq!(parse("16", I16).to_string(), "16");
|
||||
assert_eq!(parse("32", I32).to_string(), "32");
|
||||
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("0x64.64", F64).to_string(), "0x1.9190000000000p6");
|
||||
assert_eq!(parse("true", B1).to_string(), "true");
|
||||
|
||||
Reference in New Issue
Block a user