Peepmatic was an early attempt at a DSL for peephole optimizations, with the idea that maybe sometime in the future we could user it for instruction selection as well. It didn't really pan out, however: * Peepmatic wasn't quite flexible enough, and adding new operators or snippets of code implemented externally in Rust was a bit of a pain. * The performance was never competitive with the hand-written peephole optimizers. It was *very* size efficient, but that came at the cost of run-time efficiency. Everything was table-based and interpreted, rather than generating any Rust code. Ultimately, because of these reasons, we never turned Peepmatic on by default. These days, we just landed the ISLE domain-specific language, and it is better suited than Peepmatic for all the things that Peepmatic was originally designed to do. It is more flexible and easy to integrate with external Rust code. It is has better time efficiency, meeting or even beating hand-written code. I think a small part of the reason why ISLE excels in these things is because its design was informed by Peepmatic's failures. I still plan on continuing Peepmatic's mission to make Cranelift's peephole optimizer passes generated from DSL rewrite rules, but using ISLE instead of Peepmatic. Thank you Peepmatic, rest in peace!
163 lines
4.2 KiB
Rust
Executable File
163 lines
4.2 KiB
Rust
Executable File
#![deny(trivial_numeric_casts)]
|
|
#![warn(unused_import_braces, unstable_features, unused_extern_crates)]
|
|
#![cfg_attr(
|
|
feature = "cargo-clippy",
|
|
warn(
|
|
clippy::float_arithmetic,
|
|
clippy::mut_mut,
|
|
clippy::nonminimal_bool,
|
|
clippy::map_unwrap_or,
|
|
clippy::clippy::unicode_not_nfc,
|
|
clippy::use_self
|
|
)
|
|
)]
|
|
|
|
use cranelift_codegen::dbg::LOG_FILENAME_PREFIX;
|
|
use std::{option::Option, path::PathBuf};
|
|
use structopt::StructOpt;
|
|
|
|
mod bugpoint;
|
|
mod cat;
|
|
mod compile;
|
|
mod disasm;
|
|
mod interpret;
|
|
mod print_cfg;
|
|
mod run;
|
|
mod utils;
|
|
|
|
#[cfg(feature = "souper-harvest")]
|
|
mod souper_harvest;
|
|
|
|
#[cfg(feature = "wasm")]
|
|
mod wasm;
|
|
|
|
fn handle_debug_flag(debug: bool) {
|
|
if debug {
|
|
pretty_env_logger::init();
|
|
} else {
|
|
file_per_thread_logger::initialize(LOG_FILENAME_PREFIX);
|
|
}
|
|
}
|
|
|
|
/// Cranelift code generator utility.
|
|
#[derive(StructOpt)]
|
|
enum Commands {
|
|
Test(TestOptions),
|
|
Run(run::Options),
|
|
Interpret(interpret::Options),
|
|
Cat(cat::Options),
|
|
PrintCfg(print_cfg::Options),
|
|
Compile(compile::Options),
|
|
Pass(PassOptions),
|
|
Bugpoint(bugpoint::Options),
|
|
|
|
#[cfg(feature = "wasm")]
|
|
Wasm(wasm::Options),
|
|
#[cfg(not(feature = "wasm"))]
|
|
Wasm(CompiledWithoutSupportOptions),
|
|
|
|
#[cfg(feature = "souper-harvest")]
|
|
SouperHarvest(souper_harvest::Options),
|
|
#[cfg(not(feature = "souper-harvest"))]
|
|
SouperHarvest(CompiledWithoutSupportOptions),
|
|
}
|
|
|
|
/// Run Cranelift tests
|
|
#[derive(StructOpt)]
|
|
struct TestOptions {
|
|
/// Be more verbose
|
|
#[structopt(short = "v", long = "verbose")]
|
|
verbose: bool,
|
|
|
|
/// Print pass timing report for test
|
|
#[structopt(short = "T")]
|
|
time_passes: bool,
|
|
|
|
/// Enable debug output on stderr/stdout
|
|
#[structopt(short = "d")]
|
|
debug: bool,
|
|
|
|
/// Specify an input file to be used. Use '-' for stdin.
|
|
#[structopt(required(true), parse(from_os_str))]
|
|
files: Vec<PathBuf>,
|
|
}
|
|
|
|
/// Run specified pass(es) on an input file.
|
|
#[derive(StructOpt)]
|
|
struct PassOptions {
|
|
/// Be more verbose
|
|
#[structopt(short = "v", long = "verbose")]
|
|
verbose: bool,
|
|
|
|
/// Print pass timing report for test
|
|
#[structopt(short = "T")]
|
|
time_passes: bool,
|
|
|
|
/// Enable debug output on stderr/stdout
|
|
#[structopt(short = "d")]
|
|
debug: bool,
|
|
|
|
/// Specify an input file to be used. Use '-' for stdin.
|
|
#[structopt(parse(from_os_str))]
|
|
file: PathBuf,
|
|
|
|
/// Specify the target architecture.
|
|
target: String,
|
|
|
|
/// Specify pass(es) to be run on the input file
|
|
#[structopt(required(true))]
|
|
passes: Vec<String>,
|
|
}
|
|
|
|
/// (Compiled without support for this subcommand)
|
|
#[derive(StructOpt)]
|
|
struct CompiledWithoutSupportOptions {}
|
|
|
|
fn main() -> anyhow::Result<()> {
|
|
match Commands::from_args() {
|
|
Commands::Cat(c) => cat::run(&c)?,
|
|
Commands::Run(r) => run::run(&r)?,
|
|
Commands::Interpret(i) => interpret::run(&i)?,
|
|
Commands::PrintCfg(p) => print_cfg::run(&p)?,
|
|
Commands::Compile(c) => compile::run(&c)?,
|
|
Commands::Bugpoint(b) => bugpoint::run(&b)?,
|
|
|
|
#[cfg(feature = "wasm")]
|
|
Commands::Wasm(w) => wasm::run(&w)?,
|
|
#[cfg(not(feature = "wasm"))]
|
|
Commands::Wasm(_) => anyhow::bail!("Error: clif-util was compiled without wasm support."),
|
|
|
|
#[cfg(feature = "souper-harvest")]
|
|
Commands::SouperHarvest(s) => souper_harvest::run(&s)?,
|
|
#[cfg(not(feature = "souper-harvest"))]
|
|
Commands::SouperHarvest(_) => anyhow::bail!(
|
|
"Error: clif-util was compiled without support for the `souper-harvest` \
|
|
subcommand",
|
|
),
|
|
|
|
Commands::Test(t) => {
|
|
handle_debug_flag(t.debug);
|
|
cranelift_filetests::run(
|
|
t.verbose,
|
|
t.time_passes,
|
|
&t.files
|
|
.iter()
|
|
.map(|f| f.display().to_string())
|
|
.collect::<Vec<_>>(),
|
|
)?;
|
|
}
|
|
Commands::Pass(p) => {
|
|
handle_debug_flag(p.debug);
|
|
cranelift_filetests::run_passes(
|
|
p.verbose,
|
|
p.time_passes,
|
|
&p.passes,
|
|
&p.target,
|
|
&p.file.display().to_string(),
|
|
)?;
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|