clif-util: Switch to using structopt for CLI arguments
This commit is contained in:
@@ -9,7 +9,6 @@
|
||||
|
||||
use crate::disasm::{print_all, PrintRelocs, PrintStackMaps, PrintTraps};
|
||||
use crate::utils::parse_sets_and_triple;
|
||||
use crate::UseTerminalColor;
|
||||
use anyhow::{Context as _, Result};
|
||||
use cranelift_codegen::ir::DisplayFunctionAnnotations;
|
||||
use cranelift_codegen::print_errors::{pretty_error, pretty_verifier_error};
|
||||
@@ -21,6 +20,7 @@ use cranelift_wasm::{translate_module, DummyEnvironment, FuncIndex, ReturnMode};
|
||||
use std::io::Read;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use structopt::StructOpt;
|
||||
use term;
|
||||
|
||||
/// For verbose printing: only print if the `$x` expression is true.
|
||||
@@ -60,69 +60,108 @@ macro_rules! vcprint {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn run(
|
||||
files: Vec<String>,
|
||||
use_terminal_color: UseTerminalColor,
|
||||
flag_verbose: bool,
|
||||
flag_just_decode: bool,
|
||||
flag_check_translation: bool,
|
||||
flag_print: bool,
|
||||
flag_print_disasm: bool,
|
||||
flag_set: &[String],
|
||||
flag_triple: &str,
|
||||
flag_print_size: bool,
|
||||
flag_report_times: bool,
|
||||
flag_calc_value_ranges: bool,
|
||||
) -> Result<()> {
|
||||
let parsed = parse_sets_and_triple(flag_set, flag_triple)?;
|
||||
for filename in files {
|
||||
let path = Path::new(&filename);
|
||||
/// Compiles Wasm binary/text into Cranelift IR and then into target language
|
||||
#[derive(StructOpt)]
|
||||
pub struct Options {
|
||||
/// Be more verbose
|
||||
#[structopt(short = "v", long = "verbose")]
|
||||
verbose: bool,
|
||||
|
||||
/// Print the resulting Cranelift IR
|
||||
#[structopt(short("p"))]
|
||||
print: bool,
|
||||
|
||||
/// Print pass timing report
|
||||
#[structopt(short("T"))]
|
||||
report_times: bool,
|
||||
|
||||
/// Print machine code disassembly
|
||||
#[structopt(short("D"), long("disasm"))]
|
||||
disasm: bool,
|
||||
|
||||
/// Configure Cranelift settings
|
||||
#[structopt(long("set"))]
|
||||
settings: Vec<String>,
|
||||
|
||||
/// Specify the Cranelift target
|
||||
#[structopt(long("target"))]
|
||||
target: String,
|
||||
|
||||
/// Specify an input file to be used. Use '-' for stdin.
|
||||
#[structopt(parse(from_os_str))]
|
||||
files: Vec<PathBuf>,
|
||||
|
||||
/// Enable debug output on stderr/stdout
|
||||
#[structopt(short = "d")]
|
||||
debug: bool,
|
||||
|
||||
/// Print bytecode size
|
||||
#[structopt(short("X"))]
|
||||
print_size: bool,
|
||||
|
||||
/// Juse decode Wasm into Cranelift IR, don't compile it to native code
|
||||
#[structopt(short("t"))]
|
||||
just_decode: bool,
|
||||
|
||||
/// Just checks the correctness of Cranelift IR translated from Wasm
|
||||
#[structopt(short("c"))]
|
||||
check_translation: bool,
|
||||
|
||||
/// Display values' ranges and their locations
|
||||
#[structopt(long("value-ranges"))]
|
||||
value_ranges: bool,
|
||||
|
||||
/// Use colors in output? [options: auto/never/always; default: auto]
|
||||
#[structopt(long("color"), default_value("auto"))]
|
||||
color: Color,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
enum Color {
|
||||
Auto,
|
||||
Never,
|
||||
Always,
|
||||
}
|
||||
|
||||
impl std::str::FromStr for Color {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let s = s.to_lowercase();
|
||||
match s.as_str() {
|
||||
"auto" => Ok(Color::Auto),
|
||||
"never" => Ok(Color::Never),
|
||||
"always" => Ok(Color::Always),
|
||||
_ => Err(format!("expected auto/never/always, found: {}", s)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run(options: &Options) -> Result<()> {
|
||||
crate::handle_debug_flag(options.debug);
|
||||
|
||||
let parsed = parse_sets_and_triple(&options.settings, &options.target)?;
|
||||
for path in &options.files {
|
||||
let name = String::from(path.as_os_str().to_string_lossy());
|
||||
handle_module(
|
||||
use_terminal_color,
|
||||
flag_verbose,
|
||||
flag_just_decode,
|
||||
flag_check_translation,
|
||||
flag_print,
|
||||
flag_print_size,
|
||||
flag_print_disasm,
|
||||
flag_report_times,
|
||||
flag_calc_value_ranges,
|
||||
&path.to_path_buf(),
|
||||
&name,
|
||||
parsed.as_fisa(),
|
||||
)?;
|
||||
handle_module(options, path, &name, parsed.as_fisa())?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_module(
|
||||
use_terminal_color: UseTerminalColor,
|
||||
flag_verbose: bool,
|
||||
flag_just_decode: bool,
|
||||
flag_check_translation: bool,
|
||||
flag_print: bool,
|
||||
flag_print_size: bool,
|
||||
flag_print_disasm: bool,
|
||||
flag_report_times: bool,
|
||||
flag_calc_value_ranges: bool,
|
||||
path: &PathBuf,
|
||||
name: &str,
|
||||
fisa: FlagsOrIsa,
|
||||
) -> Result<()> {
|
||||
fn handle_module(options: &Options, path: &Path, name: &str, fisa: FlagsOrIsa) -> Result<()> {
|
||||
let mut terminal = term::stdout().unwrap();
|
||||
let use_color = terminal.supports_color() && use_terminal_color == UseTerminalColor::Auto
|
||||
|| use_terminal_color == UseTerminalColor::Always;
|
||||
let use_color =
|
||||
terminal.supports_color() && options.color == Color::Auto || options.color == Color::Always;
|
||||
vcprint!(
|
||||
flag_verbose,
|
||||
options.verbose,
|
||||
use_color,
|
||||
terminal,
|
||||
term::color::YELLOW,
|
||||
"Handling: "
|
||||
);
|
||||
vprintln!(flag_verbose, "\"{}\"", name);
|
||||
vprintln!(options.verbose, "\"{}\"", name);
|
||||
vcprint!(
|
||||
flag_verbose,
|
||||
options.verbose,
|
||||
use_color,
|
||||
terminal,
|
||||
term::color::MAGENTA,
|
||||
@@ -148,15 +187,21 @@ fn handle_module(
|
||||
}
|
||||
};
|
||||
|
||||
let debug_info = flag_calc_value_ranges;
|
||||
let debug_info = options.value_ranges;
|
||||
let mut dummy_environ =
|
||||
DummyEnvironment::new(isa.frontend_config(), ReturnMode::NormalReturns, debug_info);
|
||||
translate_module(&module_binary, &mut dummy_environ)?;
|
||||
|
||||
vcprintln!(flag_verbose, use_color, terminal, term::color::GREEN, "ok");
|
||||
vcprintln!(
|
||||
options.verbose,
|
||||
use_color,
|
||||
terminal,
|
||||
term::color::GREEN,
|
||||
"ok"
|
||||
);
|
||||
|
||||
if flag_just_decode {
|
||||
if !flag_print {
|
||||
if options.just_decode {
|
||||
if !options.print {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@@ -170,22 +215,22 @@ fn handle_module(
|
||||
println!("; Selected as wasm start function");
|
||||
}
|
||||
}
|
||||
vprintln!(flag_verbose, "");
|
||||
vprintln!(options.verbose, "");
|
||||
for export_name in
|
||||
&dummy_environ.info.functions[FuncIndex::new(func_index)].export_names
|
||||
{
|
||||
println!("; Exported as \"{}\"", export_name);
|
||||
}
|
||||
println!("{}", context.func.display(None));
|
||||
vprintln!(flag_verbose, "");
|
||||
vprintln!(options.verbose, "");
|
||||
}
|
||||
let _ = terminal.reset();
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if flag_check_translation {
|
||||
if options.check_translation {
|
||||
vcprint!(
|
||||
flag_verbose,
|
||||
options.verbose,
|
||||
use_color,
|
||||
terminal,
|
||||
term::color::MAGENTA,
|
||||
@@ -193,7 +238,7 @@ fn handle_module(
|
||||
);
|
||||
} else {
|
||||
vcprint!(
|
||||
flag_verbose,
|
||||
options.verbose,
|
||||
use_color,
|
||||
terminal,
|
||||
term::color::MAGENTA,
|
||||
@@ -201,8 +246,8 @@ fn handle_module(
|
||||
);
|
||||
}
|
||||
|
||||
if flag_print_size {
|
||||
vprintln!(flag_verbose, "");
|
||||
if options.print_size {
|
||||
vprintln!(options.verbose, "");
|
||||
}
|
||||
|
||||
let num_func_imports = dummy_environ.get_num_func_imports();
|
||||
@@ -214,10 +259,10 @@ fn handle_module(
|
||||
let mut saved_sizes = None;
|
||||
let func_index = num_func_imports + def_index.index();
|
||||
let mut mem = vec![];
|
||||
let mut relocs = PrintRelocs::new(flag_print);
|
||||
let mut traps = PrintTraps::new(flag_print);
|
||||
let mut stack_maps = PrintStackMaps::new(flag_print);
|
||||
if flag_check_translation {
|
||||
let mut relocs = PrintRelocs::new(options.print);
|
||||
let mut traps = PrintTraps::new(options.print);
|
||||
let mut stack_maps = PrintStackMaps::new(options.print);
|
||||
if options.check_translation {
|
||||
if let Err(errors) = context.verify(fisa) {
|
||||
anyhow::bail!(
|
||||
"{}",
|
||||
@@ -229,7 +274,7 @@ fn handle_module(
|
||||
.compile_and_emit(isa, &mut mem, &mut relocs, &mut traps, &mut stack_maps)
|
||||
.map_err(|err| anyhow::anyhow!("{}", pretty_error(&context.func, fisa.isa, err)))?;
|
||||
|
||||
if flag_print_size {
|
||||
if options.print_size {
|
||||
println!(
|
||||
"Function #{} code size: {} bytes",
|
||||
func_index, code_info.total_size,
|
||||
@@ -242,7 +287,7 @@ fn handle_module(
|
||||
);
|
||||
}
|
||||
|
||||
if flag_print_disasm {
|
||||
if options.disasm {
|
||||
saved_sizes = Some((
|
||||
code_info.code_size,
|
||||
code_info.jumptables_size + code_info.rodata_size,
|
||||
@@ -250,8 +295,8 @@ fn handle_module(
|
||||
}
|
||||
}
|
||||
|
||||
if flag_print {
|
||||
vprintln!(flag_verbose, "");
|
||||
if options.print {
|
||||
vprintln!(options.verbose, "");
|
||||
if let Some(start_func) = dummy_environ.info.start_func {
|
||||
if func_index == start_func.index() {
|
||||
println!("; Selected as wasm start function");
|
||||
@@ -262,7 +307,7 @@ fn handle_module(
|
||||
{
|
||||
println!("; Exported as \"{}\"", export_name);
|
||||
}
|
||||
let value_ranges = if flag_calc_value_ranges {
|
||||
let value_ranges = if options.value_ranges {
|
||||
Some(
|
||||
context
|
||||
.build_value_labels_ranges(isa)
|
||||
@@ -278,7 +323,7 @@ fn handle_module(
|
||||
value_ranges: value_ranges.as_ref(),
|
||||
})
|
||||
);
|
||||
vprintln!(flag_verbose, "");
|
||||
vprintln!(options.verbose, "");
|
||||
}
|
||||
|
||||
if let Some((code_size, rodata_size)) = saved_sizes {
|
||||
@@ -296,16 +341,22 @@ fn handle_module(
|
||||
context.clear();
|
||||
}
|
||||
|
||||
if !flag_check_translation && flag_print_size {
|
||||
if !options.check_translation && options.print_size {
|
||||
println!("Total module code size: {} bytes", total_module_code_size);
|
||||
let total_bytecode_size: usize = dummy_environ.func_bytecode_sizes.iter().sum();
|
||||
println!("Total module bytecode size: {} bytes", total_bytecode_size);
|
||||
}
|
||||
|
||||
if flag_report_times {
|
||||
if options.report_times {
|
||||
println!("{}", timing::take_current());
|
||||
}
|
||||
|
||||
vcprintln!(flag_verbose, use_color, terminal, term::color::GREEN, "ok");
|
||||
vcprintln!(
|
||||
options.verbose,
|
||||
use_color,
|
||||
terminal,
|
||||
term::color::GREEN,
|
||||
"ok"
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user