Add settings and isa command-line options to cton-util wasm. (#158)

* Add settings and isa command-line options to cton-util wasm.

* Use map_err to simplify error handling.

* Use `&*` instead of `.borrow()`.
This commit is contained in:
Dan Gohman
2017-09-14 17:41:43 -07:00
committed by GitHub
parent 0737aa48f2
commit 9e77af25a3
4 changed files with 47 additions and 21 deletions

View File

@@ -30,7 +30,7 @@ Usage:
cton-util cat <file>...
cton-util filecheck [-v] <file>
cton-util print-cfg <file>...
cton-util wasm [-cvo] [--enable=<flag>]... <file>...
cton-util wasm [-cvo] [--set <set>]... [--isa <isa>] <file>...
cton-util --help | --version
Options:
@@ -38,6 +38,8 @@ Options:
-c, --check checks the correctness of Cretonne IL translated from WebAssembly
-o, --optimize runs otpimization passes on translated WebAssembly functions
-h, --help print this help message
--set=<set> configure Cretonne settings
--isa=<isa> specify the Cretonne ISA
--version print the Cretonne version
";
@@ -53,7 +55,8 @@ struct Args {
flag_check: bool,
flag_optimize: bool,
flag_verbose: bool,
flag_enable: Vec<String>,
flag_set: Vec<String>,
flag_isa: String,
}
/// A command either succeeds or fails with an error message.
@@ -85,7 +88,8 @@ fn cton_util() -> CommandResult {
args.flag_verbose,
args.flag_optimize,
args.flag_check,
args.flag_enable,
args.flag_set,
args.flag_isa,
)
} else {
// Debugging / shouldn't happen with proper command line handling above.

View File

@@ -5,10 +5,12 @@
//! and tables, then emitting the translated code with hardcoded addresses to memory.
use cton_wasm::{translate_module, DummyRuntime, WasmRuntime};
use cton_reader::{parse_options, Location};
use std::path::PathBuf;
use cretonne::Context;
use cretonne::verifier;
use cretonne::settings::{self, Configurable};
use cretonne::settings;
use cretonne::isa::{self, TargetIsa};
use std::fs::File;
use std::error::Error;
use std::io;
@@ -50,16 +52,29 @@ pub fn run(
flag_verbose: bool,
flag_optimize: bool,
flag_check: bool,
flag_enable: Vec<String>,
flag_set: Vec<String>,
flag_isa: String,
) -> Result<(), String> {
let mut flag_builder = settings::builder();
for enable in flag_enable {
flag_builder.enable(&enable).map_err(|_| {
format!("unrecognized flag: {}", enable)
})?;
}
parse_options(
flag_set.iter().map(|x| x.as_str()),
&mut flag_builder,
&Location { line_number: 0 },
).map_err(|err| err.to_string())?;
let flags = settings::Flags::new(&flag_builder);
let mut words = flag_isa.trim().split_whitespace();
// Look for `isa foo`.
let isa_name = match words.next() {
None => return Err(String::from("expected ISA name")),
Some(w) => w,
};
let isa_builder = isa::lookup(isa_name).map_err(|err| match err {
isa::LookupError::Unknown => format!("unknown ISA '{}'", isa_name),
isa::LookupError::Unsupported => format!("support for ISA '{}' not enabled", isa_name),
})?;
let isa = isa_builder.finish(settings::Flags::new(&flag_builder));
for filename in files {
let path = Path::new(&filename);
let name = String::from(path.as_os_str().to_string_lossy());
@@ -70,6 +85,7 @@ pub fn run(
path.to_path_buf(),
name,
&flags,
&*isa,
)?;
}
Ok(())
@@ -82,6 +98,7 @@ fn handle_module(
path: PathBuf,
name: String,
flags: &settings::Flags,
isa: &TargetIsa,
) -> Result<(), String> {
let mut terminal = term::stdout().unwrap();
terminal.fg(term::color::YELLOW).unwrap();
@@ -140,8 +157,8 @@ fn handle_module(
vprint!(flag_verbose, "Checking... ");
terminal.reset().unwrap();
for func in &translation.functions {
verifier::verify_function(func, None).map_err(|err| {
pretty_verifier_error(func, None, err)
verifier::verify_function(func, Some(isa)).map_err(|err| {
pretty_verifier_error(func, Some(isa), err)
})?;
}
terminal.fg(term::color::GREEN).unwrap();
@@ -155,18 +172,18 @@ fn handle_module(
for func in &translation.functions {
let mut context = Context::new();
context.func = func.clone();
context.verify(None).map_err(|err| {
pretty_verifier_error(&context.func, None, err)
context.verify(Some(isa)).map_err(|err| {
pretty_verifier_error(&context.func, Some(isa), err)
})?;
context.flowgraph();
context.compute_loop_analysis();
context.licm();
context.verify(None).map_err(|err| {
pretty_verifier_error(&context.func, None, err)
context.verify(Some(isa)).map_err(|err| {
pretty_verifier_error(&context.func, Some(isa), err)
})?;
context.simple_gvn();
context.verify(None).map_err(|err| {
pretty_verifier_error(&context.func, None, err)
context.verify(Some(isa)).map_err(|err| {
pretty_verifier_error(&context.func, Some(isa), err)
})?;
}
terminal.fg(term::color::GREEN).unwrap();

View File

@@ -8,7 +8,8 @@ use std::result;
/// The location of a `Token` or `Error`.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct Location {
/// Line number, starting from 1.
/// Line number. Command-line arguments are line 0 and source file
/// lines start from 1.
pub line_number: usize,
}
@@ -23,8 +24,12 @@ pub struct Error {
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.location.line_number == 0 {
write!(f, "command-line arguments: {}", self.message)
} else {
write!(f, "{}: {}", self.location.line_number, self.message)
}
}
}
/// Result of a parser operation. The `Error` variant includes a location.

View File

@@ -11,7 +11,7 @@ pub use error::{Location, Result, Error};
pub use parser::{parse_functions, parse_test};
pub use testcommand::{TestCommand, TestOption};
pub use testfile::{TestFile, Details, Comment};
pub use isaspec::IsaSpec;
pub use isaspec::{IsaSpec, parse_options};
pub use sourcemap::SourceMap;
mod error;