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.
73 lines
2.1 KiB
Rust
73 lines
2.1 KiB
Rust
//! Helper for autogenerated unit tests.
|
|
|
|
use cranelift_isle::error::Result;
|
|
use cranelift_isle::{compile, lexer, parser};
|
|
use std::default::Default;
|
|
|
|
fn build(filename: &str) -> Result<String> {
|
|
let lexer = lexer::Lexer::from_files(vec![filename])?;
|
|
let defs = parser::parse(lexer)?;
|
|
compile::compile(&defs, &Default::default())
|
|
}
|
|
|
|
pub fn run_pass(filename: &str) {
|
|
assert!(build(filename).is_ok());
|
|
}
|
|
|
|
pub fn run_fail(filename: &str) {
|
|
assert!(build(filename).is_err());
|
|
}
|
|
|
|
fn build_and_link_isle(isle_filename: &str) -> (tempfile::TempDir, std::path::PathBuf) {
|
|
let tempdir = tempfile::tempdir().unwrap();
|
|
let code = build(isle_filename).unwrap();
|
|
|
|
let isle_filename_base = std::path::Path::new(isle_filename)
|
|
.file_stem()
|
|
.unwrap()
|
|
.to_str()
|
|
.unwrap()
|
|
.to_string();
|
|
let isle_generated_code = tempdir
|
|
.path()
|
|
.to_path_buf()
|
|
.join(isle_filename_base.clone() + ".rs");
|
|
std::fs::write(isle_generated_code, code).unwrap();
|
|
|
|
let rust_filename = isle_filename.replace(".isle", "").to_string() + "_main.rs";
|
|
let rust_filename_base = std::path::Path::new(&rust_filename).file_name().unwrap();
|
|
let rust_driver = tempdir.path().to_path_buf().join(&rust_filename_base);
|
|
println!("copying {} to {:?}", rust_filename, rust_driver);
|
|
std::fs::copy(&rust_filename, &rust_driver).unwrap();
|
|
|
|
let output = tempdir.path().to_path_buf().join("out");
|
|
|
|
let mut rustc = std::process::Command::new("rustc")
|
|
.arg(&rust_driver)
|
|
.arg("-o")
|
|
.arg(output.clone())
|
|
.spawn()
|
|
.unwrap();
|
|
assert!(rustc.wait().unwrap().success());
|
|
|
|
(tempdir, output)
|
|
}
|
|
|
|
pub fn run_link(isle_filename: &str) {
|
|
build_and_link_isle(isle_filename);
|
|
}
|
|
|
|
pub fn run_run(isle_filename: &str) {
|
|
let (_tempdir, exe) = build_and_link_isle(isle_filename);
|
|
|
|
assert!(std::process::Command::new(exe)
|
|
.spawn()
|
|
.unwrap()
|
|
.wait()
|
|
.unwrap()
|
|
.success());
|
|
}
|
|
|
|
// Generated by build.rs.
|
|
include!(concat!(env!("OUT_DIR"), "/isle_tests.rs"));
|