Conform to Cargo's conventional file layout
Move `src/*.rs` to `src/bin/*.rs` which are automatically inferred as binaries and move `src/utils.rs` to `src/lib.rs` which is compiled as a reusable library for each of the binaries we're building.
This commit is contained in:
committed by
Dan Gohman
parent
e7fd72bd5c
commit
5fe550f533
232
src/bin/wasm2obj.rs
Normal file
232
src/bin/wasm2obj.rs
Normal file
@@ -0,0 +1,232 @@
|
||||
//! Translation from wasm to native object files.
|
||||
//!
|
||||
//! Reads a Wasm binary file, translates the functions' code to Cranelift
|
||||
//! IL, then translates it to native code, and writes it out to a native
|
||||
//! object file with relocations.
|
||||
|
||||
#![deny(
|
||||
missing_docs,
|
||||
trivial_numeric_casts,
|
||||
unused_extern_crates,
|
||||
unstable_features
|
||||
)]
|
||||
#![warn(unused_import_braces)]
|
||||
#![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../clippy.toml")))]
|
||||
#![cfg_attr(
|
||||
feature = "cargo-clippy",
|
||||
allow(clippy::new_without_default, clippy::new_without_default_derive)
|
||||
)]
|
||||
#![cfg_attr(
|
||||
feature = "cargo-clippy",
|
||||
warn(
|
||||
clippy::float_arithmetic,
|
||||
clippy::mut_mut,
|
||||
clippy::nonminimal_bool,
|
||||
clippy::option_map_unwrap_or,
|
||||
clippy::option_map_unwrap_or_else,
|
||||
clippy::unicode_not_nfc,
|
||||
clippy::use_self
|
||||
)
|
||||
)]
|
||||
|
||||
use cranelift_codegen::isa;
|
||||
use cranelift_codegen::settings;
|
||||
use cranelift_codegen::settings::Configurable;
|
||||
use cranelift_entity::EntityRef;
|
||||
use cranelift_native;
|
||||
use cranelift_wasm::DefinedMemoryIndex;
|
||||
use docopt::Docopt;
|
||||
use faerie::Artifact;
|
||||
use serde::Deserialize;
|
||||
use std::error::Error;
|
||||
use std::fmt::format;
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::io::prelude::*;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::process;
|
||||
use std::str;
|
||||
use std::str::FromStr;
|
||||
use target_lexicon::Triple;
|
||||
use wasmtime_debug::{emit_debugsections, read_debuginfo};
|
||||
use wasmtime_environ::cache_conf;
|
||||
use wasmtime_environ::{
|
||||
Compiler, Cranelift, ModuleEnvironment, ModuleVmctxInfo, Tunables, VMOffsets,
|
||||
};
|
||||
use wasmtime_obj::emit_module;
|
||||
|
||||
const USAGE: &str = "
|
||||
Wasm to native object translation utility.
|
||||
Takes a binary WebAssembly module into a native object file.
|
||||
The translation is dependent on the environment chosen.
|
||||
The default is a dummy environment that produces placeholder values.
|
||||
|
||||
Usage:
|
||||
wasm2obj [--target TARGET] [-cdg] [--enable-simd] <file> -o <output>
|
||||
wasm2obj --help | --version
|
||||
|
||||
Options:
|
||||
-v, --verbose displays the module and translated functions
|
||||
-h, --help print this help message
|
||||
--target <TARGET> build for the target triple; default is the host machine
|
||||
-g generate debug information
|
||||
-c, --cache enable caching system
|
||||
--enable-simd enable proposed SIMD instructions
|
||||
--version print the Cranelift version
|
||||
-d, --debug enable debug output on stderr/stdout
|
||||
";
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
struct Args {
|
||||
arg_file: String,
|
||||
arg_output: String,
|
||||
arg_target: Option<String>,
|
||||
flag_g: bool,
|
||||
flag_debug: bool,
|
||||
flag_cache: bool,
|
||||
flag_enable_simd: bool,
|
||||
}
|
||||
|
||||
fn read_wasm_file(path: PathBuf) -> Result<Vec<u8>, io::Error> {
|
||||
let mut buf: Vec<u8> = Vec::new();
|
||||
let mut file = File::open(path)?;
|
||||
file.read_to_end(&mut buf)?;
|
||||
Ok(buf)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let version = env!("CARGO_PKG_VERSION");
|
||||
let args: Args = Docopt::new(USAGE)
|
||||
.and_then(|d| {
|
||||
d.help(true)
|
||||
.version(Some(String::from(version)))
|
||||
.deserialize()
|
||||
})
|
||||
.unwrap_or_else(|e| e.exit());
|
||||
|
||||
if args.flag_debug {
|
||||
pretty_env_logger::init();
|
||||
} else {
|
||||
wasmtime::init_file_per_thread_logger("wasm2obj.dbg.");
|
||||
}
|
||||
|
||||
cache_conf::init(args.flag_cache);
|
||||
|
||||
let path = Path::new(&args.arg_file);
|
||||
match handle_module(
|
||||
path.to_path_buf(),
|
||||
&args.arg_target,
|
||||
&args.arg_output,
|
||||
args.flag_g,
|
||||
args.flag_enable_simd,
|
||||
) {
|
||||
Ok(()) => {}
|
||||
Err(message) => {
|
||||
println!(" error: {}", message);
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_module(
|
||||
path: PathBuf,
|
||||
target: &Option<String>,
|
||||
output: &str,
|
||||
generate_debug_info: bool,
|
||||
enable_simd: bool,
|
||||
) -> Result<(), String> {
|
||||
let data = match read_wasm_file(path) {
|
||||
Ok(data) => data,
|
||||
Err(err) => {
|
||||
return Err(String::from(err.description()));
|
||||
}
|
||||
};
|
||||
|
||||
let isa_builder = match *target {
|
||||
Some(ref target) => {
|
||||
let target = Triple::from_str(&target).map_err(|_| "could not parse --target")?;
|
||||
isa::lookup(target).map_err(|err| match err {
|
||||
isa::LookupError::SupportDisabled => {
|
||||
"support for architecture disabled at compile time"
|
||||
}
|
||||
isa::LookupError::Unsupported => "unsupported architecture",
|
||||
})?
|
||||
}
|
||||
None => cranelift_native::builder().unwrap_or_else(|_| {
|
||||
panic!("host machine is not a supported target");
|
||||
}),
|
||||
};
|
||||
let mut flag_builder = settings::builder();
|
||||
if enable_simd {
|
||||
flag_builder.enable("enable_simd").unwrap();
|
||||
}
|
||||
let isa = isa_builder.finish(settings::Flags::new(flag_builder));
|
||||
|
||||
let mut obj = Artifact::new(isa.triple().clone(), String::from(output));
|
||||
|
||||
// TODO: Expose the tunables as command-line flags.
|
||||
let tunables = Tunables::default();
|
||||
|
||||
let (module, lazy_function_body_inputs, lazy_data_initializers, target_config) = {
|
||||
let environ = ModuleEnvironment::new(isa.frontend_config(), tunables);
|
||||
|
||||
let translation = environ
|
||||
.translate(&data)
|
||||
.map_err(|error| error.to_string())?;
|
||||
|
||||
(
|
||||
translation.module,
|
||||
translation.function_body_inputs,
|
||||
translation.data_initializers,
|
||||
translation.target_config,
|
||||
)
|
||||
};
|
||||
|
||||
let (compilation, relocations, address_transform, value_ranges, stack_slots) =
|
||||
Cranelift::compile_module(
|
||||
&module,
|
||||
lazy_function_body_inputs,
|
||||
&*isa,
|
||||
generate_debug_info,
|
||||
)
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
let module_vmctx_info = {
|
||||
let ofs = VMOffsets::new(target_config.pointer_bytes(), &module);
|
||||
let memory_offset = ofs.vmctx_vmmemory_definition_base(DefinedMemoryIndex::new(0)) as i64;
|
||||
ModuleVmctxInfo {
|
||||
memory_offset,
|
||||
stack_slots,
|
||||
}
|
||||
};
|
||||
|
||||
emit_module(
|
||||
&mut obj,
|
||||
&module,
|
||||
&compilation,
|
||||
&relocations,
|
||||
&lazy_data_initializers,
|
||||
&target_config,
|
||||
)?;
|
||||
|
||||
if generate_debug_info {
|
||||
let debug_data = read_debuginfo(&data);
|
||||
emit_debugsections(
|
||||
&mut obj,
|
||||
&module_vmctx_info,
|
||||
&target_config,
|
||||
&debug_data,
|
||||
&address_transform,
|
||||
&value_ranges,
|
||||
)
|
||||
.map_err(|e| e.to_string())?;
|
||||
}
|
||||
|
||||
// FIXME: Make the format a parameter.
|
||||
let file =
|
||||
::std::fs::File::create(Path::new(output)).map_err(|x| format(format_args!("{}", x)))?;
|
||||
obj.write(file).map_err(|e| e.to_string())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
315
src/bin/wasmtime.rs
Normal file
315
src/bin/wasmtime.rs
Normal file
@@ -0,0 +1,315 @@
|
||||
//! CLI tool to use the functions provided by the [wasmtime](../wasmtime/index.html)
|
||||
//! crate.
|
||||
//!
|
||||
//! Reads Wasm binary files (one Wasm module per file), translates the functions' code to Cranelift
|
||||
//! IL. Can also executes the `start` function of the module by laying out the memories, globals
|
||||
//! and tables, then emitting the translated code with hardcoded addresses to memory.
|
||||
|
||||
#![deny(
|
||||
missing_docs,
|
||||
trivial_numeric_casts,
|
||||
unused_extern_crates,
|
||||
unstable_features
|
||||
)]
|
||||
#![warn(unused_import_braces)]
|
||||
#![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../clippy.toml")))]
|
||||
#![cfg_attr(
|
||||
feature = "cargo-clippy",
|
||||
allow(clippy::new_without_default, clippy::new_without_default_derive)
|
||||
)]
|
||||
#![cfg_attr(
|
||||
feature = "cargo-clippy",
|
||||
warn(
|
||||
clippy::float_arithmetic,
|
||||
clippy::mut_mut,
|
||||
clippy::nonminimal_bool,
|
||||
clippy::option_map_unwrap_or,
|
||||
clippy::option_map_unwrap_or_else,
|
||||
clippy::unicode_not_nfc,
|
||||
clippy::use_self
|
||||
)
|
||||
)]
|
||||
|
||||
use cranelift_codegen::settings;
|
||||
use cranelift_codegen::settings::Configurable;
|
||||
use cranelift_native;
|
||||
use docopt::Docopt;
|
||||
use pretty_env_logger;
|
||||
use serde::Deserialize;
|
||||
use std::error::Error;
|
||||
use std::ffi::OsStr;
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::io::prelude::*;
|
||||
use std::path::Component;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::exit;
|
||||
use wabt;
|
||||
use wasi_common::preopen_dir;
|
||||
use wasmtime_environ::cache_conf;
|
||||
use wasmtime_jit::{ActionOutcome, Context, Features};
|
||||
use wasmtime_wasi::instantiate_wasi;
|
||||
use wasmtime_wast::instantiate_spectest;
|
||||
|
||||
#[cfg(feature = "wasi-c")]
|
||||
use wasmtime_wasi_c::instantiate_wasi_c;
|
||||
|
||||
const USAGE: &str = "
|
||||
Wasm runner.
|
||||
|
||||
Takes a binary (wasm) or text (wat) WebAssembly module and instantiates it,
|
||||
including calling the start function if one is present. Additional functions
|
||||
given with --invoke are then called.
|
||||
|
||||
Usage:
|
||||
wasmtime [-ocdg] [--enable-simd] [--wasi-c] [--preload=<wasm>...] [--env=<env>...] [--dir=<dir>...] [--mapdir=<mapping>...] <file> [<arg>...]
|
||||
wasmtime [-ocdg] [--enable-simd] [--wasi-c] [--preload=<wasm>...] [--env=<env>...] [--dir=<dir>...] [--mapdir=<mapping>...] --invoke=<fn> <file> [<arg>...]
|
||||
wasmtime --help | --version
|
||||
|
||||
Options:
|
||||
--invoke=<fn> name of function to run
|
||||
-o, --optimize runs optimization passes on the translated functions
|
||||
-c, --cache enable caching system
|
||||
-g generate debug information
|
||||
-d, --debug enable debug output on stderr/stdout
|
||||
--enable-simd enable proposed SIMD instructions
|
||||
--wasi-c enable the wasi-c implementation of WASI
|
||||
--preload=<wasm> load an additional wasm module before loading the main module
|
||||
--env=<env> pass an environment variable (\"key=value\") to the program
|
||||
--dir=<dir> grant access to the given host directory
|
||||
--mapdir=<mapping> where <mapping> has the form <wasmdir>::<hostdir>, grant access to
|
||||
the given host directory with the given wasm directory name
|
||||
-h, --help print this help message
|
||||
--version print the Cranelift version
|
||||
";
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
struct Args {
|
||||
arg_file: String,
|
||||
arg_arg: Vec<String>,
|
||||
flag_optimize: bool,
|
||||
flag_cache: bool,
|
||||
flag_debug: bool,
|
||||
flag_g: bool,
|
||||
flag_enable_simd: bool,
|
||||
flag_invoke: Option<String>,
|
||||
flag_preload: Vec<String>,
|
||||
flag_env: Vec<String>,
|
||||
flag_dir: Vec<String>,
|
||||
flag_mapdir: Vec<String>,
|
||||
flag_wasi_c: bool,
|
||||
}
|
||||
|
||||
fn read_to_end(path: PathBuf) -> Result<Vec<u8>, io::Error> {
|
||||
let mut buf: Vec<u8> = Vec::new();
|
||||
let mut file = File::open(path)?;
|
||||
file.read_to_end(&mut buf)?;
|
||||
Ok(buf)
|
||||
}
|
||||
|
||||
fn read_wasm(path: PathBuf) -> Result<Vec<u8>, String> {
|
||||
let data = read_to_end(path).map_err(|err| err.to_string())?;
|
||||
|
||||
// If data is a wasm binary, use that. If it's using wat format, convert it
|
||||
// to a wasm binary with wat2wasm.
|
||||
Ok(if data.starts_with(&[b'\0', b'a', b's', b'm']) {
|
||||
data
|
||||
} else {
|
||||
wabt::wat2wasm(data).map_err(|err| String::from(err.description()))?
|
||||
})
|
||||
}
|
||||
|
||||
fn compute_preopen_dirs(flag_dir: &[String], flag_mapdir: &[String]) -> Vec<(String, File)> {
|
||||
let mut preopen_dirs = Vec::new();
|
||||
|
||||
for dir in flag_dir {
|
||||
let preopen_dir = preopen_dir(dir).unwrap_or_else(|err| {
|
||||
println!("error while pre-opening directory {}: {}", dir, err);
|
||||
exit(1);
|
||||
});
|
||||
preopen_dirs.push((dir.clone(), preopen_dir));
|
||||
}
|
||||
|
||||
for mapdir in flag_mapdir {
|
||||
let parts: Vec<&str> = mapdir.split("::").collect();
|
||||
if parts.len() != 2 {
|
||||
println!("--mapdir argument must contain exactly one double colon ('::'), separating a guest directory name and a host directory name");
|
||||
exit(1);
|
||||
}
|
||||
let (key, value) = (parts[0], parts[1]);
|
||||
let preopen_dir = preopen_dir(value).unwrap_or_else(|err| {
|
||||
println!("error while pre-opening directory {}: {}", value, err);
|
||||
exit(1);
|
||||
});
|
||||
preopen_dirs.push((key.to_string(), preopen_dir));
|
||||
}
|
||||
|
||||
preopen_dirs
|
||||
}
|
||||
|
||||
/// Compute the argv array values.
|
||||
fn compute_argv(argv0: &str, arg_arg: &[String]) -> Vec<String> {
|
||||
let mut result = Vec::new();
|
||||
|
||||
// Add argv[0], which is the program name. Only include the base name of the
|
||||
// main wasm module, to avoid leaking path information.
|
||||
result.push(
|
||||
Path::new(argv0)
|
||||
.components()
|
||||
.next_back()
|
||||
.map(Component::as_os_str)
|
||||
.and_then(OsStr::to_str)
|
||||
.unwrap_or("")
|
||||
.to_owned(),
|
||||
);
|
||||
|
||||
// Add the remaining arguments.
|
||||
for arg in arg_arg {
|
||||
result.push(arg.to_owned());
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
/// Compute the environ array values.
|
||||
fn compute_environ(flag_env: &[String]) -> Vec<(String, String)> {
|
||||
let mut result = Vec::new();
|
||||
|
||||
// Add the environment variables, which must be of the form "key=value".
|
||||
for env in flag_env {
|
||||
let split = env.splitn(2, '=').collect::<Vec<_>>();
|
||||
if split.len() != 2 {
|
||||
println!(
|
||||
"environment variables must be of the form \"key=value\"; got \"{}\"",
|
||||
env
|
||||
);
|
||||
}
|
||||
result.push((split[0].to_owned(), split[1].to_owned()));
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let version = env!("CARGO_PKG_VERSION");
|
||||
let args: Args = Docopt::new(USAGE)
|
||||
.and_then(|d| {
|
||||
d.help(true)
|
||||
.version(Some(String::from(version)))
|
||||
.deserialize()
|
||||
})
|
||||
.unwrap_or_else(|e| e.exit());
|
||||
|
||||
if args.flag_debug {
|
||||
pretty_env_logger::init();
|
||||
} else {
|
||||
wasmtime::init_file_per_thread_logger("wasmtime.dbg.");
|
||||
}
|
||||
|
||||
cache_conf::init(args.flag_cache);
|
||||
|
||||
let isa_builder = cranelift_native::builder().unwrap_or_else(|_| {
|
||||
panic!("host machine is not a supported target");
|
||||
});
|
||||
let mut flag_builder = settings::builder();
|
||||
let mut features: Features = Default::default();
|
||||
|
||||
// Enable verifier passes in debug mode.
|
||||
if cfg!(debug_assertions) {
|
||||
flag_builder.enable("enable_verifier").unwrap();
|
||||
}
|
||||
|
||||
// Enable SIMD if requested
|
||||
if args.flag_enable_simd {
|
||||
flag_builder.enable("enable_simd").unwrap();
|
||||
features.simd = true;
|
||||
}
|
||||
|
||||
// Enable optimization if requested.
|
||||
if args.flag_optimize {
|
||||
flag_builder.set("opt_level", "best").unwrap();
|
||||
}
|
||||
|
||||
let isa = isa_builder.finish(settings::Flags::new(flag_builder));
|
||||
let mut context = Context::with_isa(isa).with_features(features);
|
||||
|
||||
// Make spectest available by default.
|
||||
context.name_instance(
|
||||
"spectest".to_owned(),
|
||||
instantiate_spectest().expect("instantiating spectest"),
|
||||
);
|
||||
|
||||
// Make wasi available by default.
|
||||
let global_exports = context.get_global_exports();
|
||||
let preopen_dirs = compute_preopen_dirs(&args.flag_dir, &args.flag_mapdir);
|
||||
let argv = compute_argv(&args.arg_file, &args.arg_arg);
|
||||
let environ = compute_environ(&args.flag_env);
|
||||
|
||||
let wasi = if args.flag_wasi_c {
|
||||
#[cfg(feature = "wasi-c")]
|
||||
{
|
||||
instantiate_wasi_c("", global_exports, &preopen_dirs, &argv, &environ)
|
||||
}
|
||||
#[cfg(not(feature = "wasi-c"))]
|
||||
{
|
||||
panic!("wasi-c feature not enabled at build time")
|
||||
}
|
||||
} else {
|
||||
instantiate_wasi("", global_exports, &preopen_dirs, &argv, &environ)
|
||||
}
|
||||
.expect("instantiating wasi");
|
||||
|
||||
context.name_instance("wasi_unstable".to_owned(), wasi);
|
||||
|
||||
// Enable/disable producing of debug info.
|
||||
context.set_debug_info(args.flag_g);
|
||||
|
||||
// Load the preload wasm modules.
|
||||
for filename in &args.flag_preload {
|
||||
let path = Path::new(&filename);
|
||||
match handle_module(&mut context, &args, path) {
|
||||
Ok(()) => {}
|
||||
Err(message) => {
|
||||
let name = path.as_os_str().to_string_lossy();
|
||||
println!("error while processing preload {}: {}", name, message);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load the main wasm module.
|
||||
let path = Path::new(&args.arg_file);
|
||||
match handle_module(&mut context, &args, path) {
|
||||
Ok(()) => {}
|
||||
Err(message) => {
|
||||
let name = path.as_os_str().to_string_lossy();
|
||||
println!("error while processing main module {}: {}", name, message);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_module(context: &mut Context, args: &Args, path: &Path) -> Result<(), String> {
|
||||
// Read the wasm module binary.
|
||||
let data = read_wasm(path.to_path_buf())?;
|
||||
|
||||
// Compile and instantiating a wasm module.
|
||||
let mut instance = context
|
||||
.instantiate_module(None, &data)
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
// If a function to invoke was given, invoke it.
|
||||
if let Some(ref f) = args.flag_invoke {
|
||||
match context
|
||||
.invoke(&mut instance, f, &[])
|
||||
.map_err(|e| e.to_string())?
|
||||
{
|
||||
ActionOutcome::Returned { .. } => {}
|
||||
ActionOutcome::Trapped { message } => {
|
||||
return Err(format!("Trap from within function {}: {}", f, message));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
122
src/bin/wast.rs
Normal file
122
src/bin/wast.rs
Normal file
@@ -0,0 +1,122 @@
|
||||
//! CLI tool to run wast tests using the wasmtime libraries.
|
||||
|
||||
#![deny(
|
||||
missing_docs,
|
||||
trivial_numeric_casts,
|
||||
unused_extern_crates,
|
||||
unstable_features
|
||||
)]
|
||||
#![warn(unused_import_braces)]
|
||||
#![cfg_attr(feature = "clippy", plugin(clippy(conf_file = "../../clippy.toml")))]
|
||||
#![cfg_attr(
|
||||
feature = "cargo-clippy",
|
||||
allow(clippy::new_without_default, clippy::new_without_default_derive)
|
||||
)]
|
||||
#![cfg_attr(
|
||||
feature = "cargo-clippy",
|
||||
warn(
|
||||
clippy::float_arithmetic,
|
||||
clippy::mut_mut,
|
||||
clippy::nonminimal_bool,
|
||||
clippy::option_map_unwrap_or,
|
||||
clippy::option_map_unwrap_or_else,
|
||||
clippy::unicode_not_nfc,
|
||||
clippy::use_self
|
||||
)
|
||||
)]
|
||||
|
||||
use cranelift_codegen::settings;
|
||||
use cranelift_codegen::settings::Configurable;
|
||||
use cranelift_native;
|
||||
use docopt::Docopt;
|
||||
use pretty_env_logger;
|
||||
use serde::Deserialize;
|
||||
use std::path::Path;
|
||||
use std::process;
|
||||
use wasmtime_environ::cache_conf;
|
||||
use wasmtime_jit::{Compiler, Features};
|
||||
use wasmtime_wast::WastContext;
|
||||
|
||||
const USAGE: &str = "
|
||||
Wast test runner.
|
||||
|
||||
Usage:
|
||||
run_wast [-cdo] [--enable-simd] <file>...
|
||||
run_wast --help | --version
|
||||
|
||||
Options:
|
||||
-h, --help print this help message
|
||||
--version print the Cranelift version
|
||||
-o, --optimize runs optimization passes on the translated functions
|
||||
-c, --cache enable caching system
|
||||
-d, --debug enable debug output on stderr/stdout
|
||||
--enable-simd enable proposed SIMD instructions
|
||||
";
|
||||
|
||||
#[derive(Deserialize, Debug, Clone)]
|
||||
struct Args {
|
||||
arg_file: Vec<String>,
|
||||
flag_debug: bool,
|
||||
flag_function: Option<String>,
|
||||
flag_optimize: bool,
|
||||
flag_cache: bool,
|
||||
flag_enable_simd: bool,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let version = env!("CARGO_PKG_VERSION");
|
||||
let args: Args = Docopt::new(USAGE)
|
||||
.and_then(|d| {
|
||||
d.help(true)
|
||||
.version(Some(String::from(version)))
|
||||
.deserialize()
|
||||
})
|
||||
.unwrap_or_else(|e| e.exit());
|
||||
|
||||
if args.flag_debug {
|
||||
pretty_env_logger::init();
|
||||
} else {
|
||||
wasmtime::init_file_per_thread_logger("cranelift.dbg.");
|
||||
}
|
||||
|
||||
cache_conf::init(args.flag_cache);
|
||||
|
||||
let isa_builder = cranelift_native::builder().unwrap_or_else(|_| {
|
||||
panic!("host machine is not a supported target");
|
||||
});
|
||||
let mut flag_builder = settings::builder();
|
||||
let mut features: Features = Default::default();
|
||||
|
||||
// Enable verifier passes in debug mode.
|
||||
if cfg!(debug_assertions) {
|
||||
flag_builder.enable("enable_verifier").unwrap();
|
||||
}
|
||||
|
||||
// Enable optimization if requested.
|
||||
if args.flag_optimize {
|
||||
flag_builder.set("opt_level", "best").unwrap();
|
||||
}
|
||||
|
||||
// Enable SIMD if requested
|
||||
if args.flag_enable_simd {
|
||||
flag_builder.enable("enable_simd").unwrap();
|
||||
features.simd = true;
|
||||
}
|
||||
|
||||
let isa = isa_builder.finish(settings::Flags::new(flag_builder));
|
||||
let engine = Compiler::new(isa);
|
||||
let mut wast_context = WastContext::new(Box::new(engine)).with_features(features);
|
||||
|
||||
wast_context
|
||||
.register_spectest()
|
||||
.expect("error instantiating \"spectest\"");
|
||||
|
||||
for filename in &args.arg_file {
|
||||
wast_context
|
||||
.run_file(Path::new(&filename))
|
||||
.unwrap_or_else(|e| {
|
||||
eprintln!("{}", e);
|
||||
process::exit(1)
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user