2021-11-13 02:52:35 -06:00
|
|
|
//! WAFFLE command-line tool.
|
|
|
|
|
|
|
|
use anyhow::Result;
|
|
|
|
use log::debug;
|
|
|
|
use std::path::PathBuf;
|
|
|
|
use structopt::StructOpt;
|
2021-11-13 19:52:30 -06:00
|
|
|
use waffle::Module;
|
2021-11-13 02:52:35 -06:00
|
|
|
|
|
|
|
#[derive(Debug, StructOpt)]
|
|
|
|
#[structopt(name = "waffle-util", about = "WAFFLE utility.")]
|
|
|
|
struct Options {
|
|
|
|
#[structopt(short, long)]
|
|
|
|
debug: bool,
|
|
|
|
|
2022-12-02 13:58:04 -06:00
|
|
|
#[structopt(
|
|
|
|
help = "Do basic optimizations: GVN and const-prop",
|
|
|
|
long = "basic-opts"
|
|
|
|
)]
|
|
|
|
basic_opts: bool,
|
|
|
|
|
|
|
|
#[structopt(help = "Transform to maximal SSA", long = "max-ssa")]
|
|
|
|
max_ssa: bool,
|
|
|
|
|
2021-11-13 02:52:35 -06:00
|
|
|
#[structopt(subcommand)]
|
|
|
|
command: Command,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, StructOpt)]
|
|
|
|
enum Command {
|
|
|
|
#[structopt(name = "print-ir", about = "Parse Wasm and print resulting IR")]
|
|
|
|
PrintIR {
|
|
|
|
#[structopt(help = "Wasm file to parse")]
|
|
|
|
wasm: PathBuf,
|
|
|
|
},
|
2021-12-24 16:12:49 -06:00
|
|
|
#[structopt(name = "roundtrip", about = "Round-trip Wasm through IR")]
|
|
|
|
RoundTrip {
|
|
|
|
#[structopt(help = "Wasm file to parse", short = "i")]
|
|
|
|
input: PathBuf,
|
|
|
|
#[structopt(help = "Wasm file to produce", short = "o")]
|
|
|
|
output: PathBuf,
|
|
|
|
},
|
2021-11-13 02:52:35 -06:00
|
|
|
}
|
|
|
|
|
2023-02-07 19:31:52 -06:00
|
|
|
fn apply_options(opts: &Options, module: &mut Module) -> Result<()> {
|
2023-02-14 21:24:03 -06:00
|
|
|
module.expand_all_funcs()?;
|
2023-02-07 19:31:52 -06:00
|
|
|
if opts.basic_opts {
|
|
|
|
module.per_func_body(|body| body.optimize());
|
|
|
|
}
|
|
|
|
if opts.max_ssa {
|
|
|
|
module.per_func_body(|body| body.convert_to_max_ssa());
|
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2021-11-13 02:52:35 -06:00
|
|
|
fn main() -> Result<()> {
|
|
|
|
let opts = Options::from_args();
|
|
|
|
|
|
|
|
let mut logger = env_logger::Builder::from_default_env();
|
|
|
|
if opts.debug {
|
|
|
|
logger.filter_level(log::LevelFilter::Debug);
|
|
|
|
}
|
|
|
|
let _ = logger.try_init();
|
|
|
|
|
2023-02-07 19:31:52 -06:00
|
|
|
match &opts.command {
|
2021-11-13 02:52:35 -06:00
|
|
|
Command::PrintIR { wasm } => {
|
|
|
|
let bytes = std::fs::read(wasm)?;
|
|
|
|
debug!("Loaded {} bytes of Wasm data", bytes.len());
|
2022-12-02 13:58:04 -06:00
|
|
|
let mut module = Module::from_wasm_bytes(&bytes[..])?;
|
2023-02-07 19:31:52 -06:00
|
|
|
apply_options(&opts, &mut module)?;
|
2022-11-02 14:38:45 -05:00
|
|
|
println!("{}", module.display());
|
2021-11-13 02:52:35 -06:00
|
|
|
}
|
2021-12-24 16:12:49 -06:00
|
|
|
Command::RoundTrip { input, output } => {
|
|
|
|
let bytes = std::fs::read(input)?;
|
|
|
|
debug!("Loaded {} bytes of Wasm data", bytes.len());
|
2022-12-02 13:58:04 -06:00
|
|
|
let mut module = Module::from_wasm_bytes(&bytes[..])?;
|
2023-02-07 19:31:52 -06:00
|
|
|
apply_options(&opts, &mut module)?;
|
2022-10-27 00:15:15 -05:00
|
|
|
let produced = module.to_wasm_bytes()?;
|
2021-12-24 16:12:49 -06:00
|
|
|
std::fs::write(output, &produced[..])?;
|
|
|
|
}
|
2021-11-13 02:52:35 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|