wasmtime 0.3.0

Command-line interface for Wasmtime
Documentation
diff --git a/Cargo.toml b/Cargo.toml
index 36995d4..75e1578 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -38,5 +38,6 @@ target-lexicon = { version = "0.2.0", default-features = false }
 pretty_env_logger = "0.2.5"
 file-per-thread-logger = "0.1.1"
 wabt = "0.7"
+pbr = "1.0.1"
 
 [workspace]
diff --git a/lib/environ/src/compilation.rs b/lib/environ/src/compilation.rs
index 6540bc0..d80babe 100644
--- a/lib/environ/src/compilation.rs
+++ b/lib/environ/src/compilation.rs
@@ -9,6 +9,7 @@ use cranelift_codegen::Context;
 use cranelift_entity::{EntityRef, PrimaryMap};
 use cranelift_wasm::{DefinedFuncIndex, FuncIndex, FuncTranslator};
 use environ::{get_func_name, get_memory_grow_name, get_memory_size_name, ModuleTranslation};
+use progress::Progress;
 use std::string::{String, ToString};
 use std::vec::Vec;
 
@@ -121,9 +122,13 @@ pub type Relocations = PrimaryMap<DefinedFuncIndex, Vec<Relocation>>;
 pub fn compile_module<'data, 'module>(
     translation: &ModuleTranslation<'data, 'module>,
     isa: &isa::TargetIsa,
+    progress: &mut Progress,
 ) -> Result<(Compilation, Relocations), String> {
     let mut functions = PrimaryMap::new();
     let mut relocations = PrimaryMap::new();
+
+    progress.start(translation.lazy.function_body_inputs.len() as u64);
+
     for (i, input) in translation.lazy.function_body_inputs.iter() {
         let func_index = translation.module.func_index(i);
         let mut context = Context::new();
@@ -136,6 +141,8 @@ pub fn compile_module<'data, 'module>(
             .translate(input, &mut context.func, &mut translation.func_env())
             .map_err(|e| e.to_string())?;
 
+        progress.tick();
+
         let mut code_buf: Vec<u8> = Vec::new();
         let mut reloc_sink = RelocSink::new();
         let mut trap_sink = binemit::NullTrapSink {};
@@ -144,6 +151,11 @@ pub fn compile_module<'data, 'module>(
             .map_err(|e| e.to_string())?;
         functions.push(code_buf);
         relocations.push(reloc_sink.func_relocs);
+
+        progress.inc();
     }
+
+    progress.finish();
+
     Ok((Compilation::new(functions), relocations))
 }
diff --git a/lib/environ/src/lib.rs b/lib/environ/src/lib.rs
index 882537c..3c70049 100644
--- a/lib/environ/src/lib.rs
+++ b/lib/environ/src/lib.rs
@@ -41,6 +41,7 @@ extern crate cast;
 mod compilation;
 mod environ;
 mod module;
+mod progress;
 mod tunables;
 mod vmoffsets;
 
@@ -51,6 +52,7 @@ pub use environ::{ModuleEnvironment, ModuleTranslation};
 pub use module::{
     DataInitializer, Export, MemoryPlan, MemoryStyle, Module, TableElements, TablePlan, TableStyle,
 };
+pub use progress::{NullProgress, Progress};
 pub use tunables::Tunables;
 pub use vmoffsets::VMOffsets;
 
diff --git a/lib/execute/src/execute.rs b/lib/execute/src/execute.rs
index 1ac5e88..4ff4990 100644
--- a/lib/execute/src/execute.rs
+++ b/lib/execute/src/execute.rs
@@ -15,7 +15,7 @@ use std::string::String;
 use std::vec::Vec;
 use vmcontext::VMContext;
 use wasmtime_environ::{
-    compile_module, Compilation, Module, ModuleTranslation, Relocation, RelocationTarget,
+    compile_module, Compilation, Module, ModuleTranslation, Progress, Relocation, RelocationTarget,
 };
 
 /// Executes a module that has been translated with the `wasmtime-environ` environment
@@ -23,12 +23,13 @@ use wasmtime_environ::{
 pub fn compile_and_link_module<'data, 'module, F>(
     isa: &TargetIsa,
     translation: &ModuleTranslation<'data, 'module>,
+    progress: &mut Progress,
     imports: F,
 ) -> Result<Compilation, String>
 where
     F: Fn(&str, &str) -> Option<usize>,
 {
-    let (mut compilation, relocations) = compile_module(&translation, isa)?;
+    let (mut compilation, relocations) = compile_module(&translation, isa, progress)?;
 
     // Apply relocations, now that we have virtual addresses for everything.
     relocate(&mut compilation, &relocations, &translation.module, imports);
diff --git a/lib/execute/src/world.rs b/lib/execute/src/world.rs
index 15f5a6b..08cba8a 100644
--- a/lib/execute/src/world.rs
+++ b/lib/execute/src/world.rs
@@ -1,6 +1,6 @@
 use cranelift_codegen::isa;
 use std::str;
-use wasmtime_environ::{Compilation, Module, ModuleEnvironment, Tunables};
+use wasmtime_environ::{Compilation, Module, ModuleEnvironment, Progress, Tunables};
 use {compile_and_link_module, finish_instantiation, invoke, Code, Instance, InvokeOutcome, Value};
 
 /// A module, an instance of that module, and accompanying compilation artifacts.
@@ -14,7 +14,12 @@ pub struct InstanceWorld {
 
 impl InstanceWorld {
     /// Create a new `InstanceWorld` by compiling the wasm module in `data` and instatiating it.
-    pub fn new(code: &mut Code, isa: &isa::TargetIsa, data: &[u8]) -> Result<Self, String> {
+    pub fn new(
+        code: &mut Code,
+        isa: &isa::TargetIsa,
+        data: &[u8],
+        progress: &mut Progress,
+    ) -> Result<Self, String> {
         let mut module = Module::new();
         let tunables = Tunables::default();
         let (instance, compilation) = {
@@ -26,7 +31,8 @@ impl InstanceWorld {
 
             let imports_resolver = |_env: &str, _function: &str| None;
 
-            let compilation = compile_and_link_module(isa, &translation, &imports_resolver)?;
+            let compilation =
+                compile_and_link_module(isa, &translation, progress, &imports_resolver)?;
             let mut instance = Instance::new(
                 translation.module,
                 &compilation,
diff --git a/lib/wast/Cargo.toml b/lib/wast/Cargo.toml
index ab4ba1a..14d5549 100644
--- a/lib/wast/Cargo.toml
+++ b/lib/wast/Cargo.toml
@@ -13,6 +13,7 @@ readme = "README.md"
 cranelift-codegen = { git = "https://github.com/sunfishcode/cranelift.git", branch = "guard-offset" }
 cranelift-native = { git = "https://github.com/sunfishcode/cranelift.git", branch = "guard-offset" }
 wasmtime-execute = { path = "../execute" }
+wasmtime-environ = { path = "../environ" }
 wabt = "0.7"
 
 [badges]
diff --git a/lib/wast/src/lib.rs b/lib/wast/src/lib.rs
index 2ec3560..b4c31a7 100644
--- a/lib/wast/src/lib.rs
+++ b/lib/wast/src/lib.rs
@@ -27,6 +27,7 @@
 
 extern crate cranelift_codegen;
 extern crate wabt;
+extern crate wasmtime_environ;
 extern crate wasmtime_execute;
 
 mod wast;
diff --git a/lib/wast/src/wast.rs b/lib/wast/src/wast.rs
index c6811e0..cbb96af 100644
--- a/lib/wast/src/wast.rs
+++ b/lib/wast/src/wast.rs
@@ -6,6 +6,7 @@ use std::io::Read;
 use std::path::Path;
 use std::str;
 use wabt::script::{self, Action, Command, CommandKind, ModuleBinary, ScriptParser};
+use wasmtime_environ::NullProgress;
 use wasmtime_execute::{Code, InstanceWorld, InvokeOutcome, Value};
 
 struct Instances {
@@ -24,7 +25,12 @@ impl Instances {
     }
 
     fn instantiate(&mut self, isa: &isa::TargetIsa, module: ModuleBinary) -> InstanceWorld {
-        InstanceWorld::new(&mut self.code, isa, &module.into_vec()).unwrap()
+        InstanceWorld::new(
+            &mut self.code,
+            isa,
+            &module.into_vec(),
+            &mut NullProgress {},
+        ).unwrap()
     }
 
     pub fn define_unnamed_module(&mut self, isa: &isa::TargetIsa, module: ModuleBinary) {
diff --git a/src/wasm2obj.rs b/src/wasm2obj.rs
index 59ad748..36dc82c 100644
--- a/src/wasm2obj.rs
+++ b/src/wasm2obj.rs
@@ -56,7 +56,7 @@ use std::path::PathBuf;
 use std::process;
 use std::str::FromStr;
 use target_lexicon::Triple;
-use wasmtime_environ::{compile_module, Module, ModuleEnvironment, Tunables};
+use wasmtime_environ::{compile_module, Module, ModuleEnvironment, NullProgress, Tunables};
 use wasmtime_obj::emit_module;
 
 const USAGE: &str = "
@@ -148,7 +148,7 @@ fn handle_module(path: PathBuf, target: &Option<String>, output: &str) -> Result
             .map_err(|err| format!("{}", err))?;
     }
 
-    let (compilation, relocations) = compile_module(&translation, &*isa)?;
+    let (compilation, relocations) = compile_module(&translation, &*isa, &mut NullProgress {})?;
 
     emit_module(&mut obj, &translation.module, &compilation, &relocations)?;
 
diff --git a/src/wasmtime.rs b/src/wasmtime.rs
index cc09f96..8d73ffa 100644
--- a/src/wasmtime.rs
+++ b/src/wasmtime.rs
@@ -43,15 +43,19 @@ extern crate wasmtime_execute;
 #[macro_use]
 extern crate serde_derive;
 extern crate file_per_thread_logger;
+extern crate pbr;
 extern crate pretty_env_logger;
 extern crate wabt;
 
+mod pbr_progress;
+
 use cranelift_codegen::isa::TargetIsa;
 use cranelift_codegen::settings;
 use cranelift_codegen::settings::Configurable;
 use cranelift_entity::EntityRef;
 use cranelift_wasm::MemoryIndex;
 use docopt::Docopt;
+use pbr_progress::PbrProgress;
 use std::error::Error;
 use std::fs::File;
 use std::io;
@@ -160,40 +164,43 @@ fn handle_module(args: &Args, path: PathBuf, isa: &TargetIsa) -> Result<(), Stri
 
     let mut code = Code::new();
 
-    let instance = match compile_and_link_module(isa, &translation, &imports_resolver) {
-        Ok(compilation) => {
-            let mut instance = Instance::new(
-                translation.module,
-                &compilation,
-                &translation.lazy.data_initializers,
-            )?;
-
-            finish_instantiation(
-                &mut code,
-                isa,
-                &translation.module,
-                &compilation,
-                &mut instance,
-            )?;
-
-            if let Some(ref f) = args.flag_function {
-                invoke(
+    let mut progress = PbrProgress::new();
+
+    let instance =
+        match compile_and_link_module(isa, &translation, &mut progress, &imports_resolver) {
+            Ok(compilation) => {
+                let mut instance = Instance::new(
+                    translation.module,
+                    &compilation,
+                    &translation.lazy.data_initializers,
+                )?;
+
+                finish_instantiation(
                     &mut code,
                     isa,
                     &translation.module,
                     &compilation,
-                    instance.vmctx(),
-                    &f,
-                    &[],
+                    &mut instance,
                 )?;
-            }
 
-            instance
-        }
-        Err(s) => {
-            return Err(s);
-        }
-    };
+                if let Some(ref f) = args.flag_function {
+                    invoke(
+                        &mut code,
+                        isa,
+                        &translation.module,
+                        &compilation,
+                        instance.vmctx(),
+                        &f,
+                        &[],
+                    )?;
+                }
+
+                instance
+            }
+            Err(s) => {
+                return Err(s);
+            }
+        };
     if args.flag_memory {
         let mut input = String::new();
         println!("Inspecting memory");