ISLE: support more flexible integer constants. (#4559)
The ISLE language's lexer previously used a very primitive `i64::from_str_radix` call to parse integer constants, allowing values in the range -2^63..2^63 only. Also, underscores to separate digits (as is allwoed in Rust) were not supported. Finally, 128-bit constants were not supported at all. This PR addresses all issues above: - Integer constants are internally stored as 128-bit values. - Parsing supports either signed (-2^127..2^127) or unsigned (0..2^128) range. Negation works independently of that, so one can write `-0xffff..ffff` (128 bits wide, i.e., -(2^128-1)) to get a `1`. - Underscores are supported to separate groups of digits, so one can write `0xffff_ffff`. - A minor oversight was fixed: hex constants can start with `0X` (uppercase) as well as `0x`, for consistency with Rust and C. This PR also adds a new kind of ISLE test that actually runs a driver linked to compiled ISLE code; we previously didn't have any such tests, but it is now quite useful to assert correct interpretation of constant values.
This commit is contained in:
17
cranelift/isle/isle/isle_examples/run/iconst.isle
Normal file
17
cranelift/isle/isle/isle_examples/run/iconst.isle
Normal file
@@ -0,0 +1,17 @@
|
||||
(type i64 (primitive i64))
|
||||
|
||||
(decl X (i64) i64)
|
||||
(rule (X -1) -2)
|
||||
(rule (X -2) -3)
|
||||
(rule (X 0x7fff_ffff_ffff_ffff) 0x8000_0000_0000_0000)
|
||||
(rule (X 0xffff_ffff_ffff_fff0) 1)
|
||||
|
||||
(type i128 (primitive i128))
|
||||
|
||||
(decl Y (i128) i128)
|
||||
|
||||
(rule (Y 0x1000_0000_0000_0000_1234_5678_9abc_def0) -1)
|
||||
(rule (Y 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff) 3)
|
||||
|
||||
(rule (Y -0x1000_0000_0000_0000_1234_5678_9abc_def0) 1)
|
||||
(rule (Y -0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff) -3)
|
||||
18
cranelift/isle/isle/isle_examples/run/iconst_main.rs
Normal file
18
cranelift/isle/isle/isle_examples/run/iconst_main.rs
Normal file
@@ -0,0 +1,18 @@
|
||||
mod iconst;
|
||||
|
||||
struct Context;
|
||||
impl iconst::Context for Context {}
|
||||
|
||||
fn main() {
|
||||
let mut ctx = Context;
|
||||
|
||||
assert_eq!(iconst::constructor_X(&mut ctx, -1), Some(-2));
|
||||
assert_eq!(iconst::constructor_X(&mut ctx, -2), Some(-3));
|
||||
assert_eq!(iconst::constructor_X(&mut ctx, 0x7fff_ffff_ffff_ffff), Some(0x8000_0000_0000_0000u64 as i64));
|
||||
assert_eq!(iconst::constructor_X(&mut ctx, 0xffff_ffff_ffff_fff0_u64 as i64), Some(1));
|
||||
|
||||
assert_eq!(iconst::constructor_Y(&mut ctx, 0x1000_0000_0000_0000_1234_5678_9abc_def0), Some(-1));
|
||||
assert_eq!(iconst::constructor_Y(&mut ctx, 0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ffffu128 as i128), Some(3));
|
||||
assert_eq!(iconst::constructor_Y(&mut ctx, -0x1000_0000_0000_0000_1234_5678_9abc_def0), Some(1));
|
||||
assert_eq!(iconst::constructor_Y(&mut ctx, -(0xffff_ffff_ffff_ffff_ffff_ffff_ffff_ffffu128 as i128)), Some(-3));
|
||||
}
|
||||
Reference in New Issue
Block a user