Introduce the wasmtime-explorer crate (#5975)

This implements Godbolt Compiler Explorer-like functionality for Wasmtime and
Cranelift. Given a Wasm module, it compiles the module to native code and then
writes a standalone HTML file that gives a split pane view between the WAT and
ASM disassemblies.
This commit is contained in:
Nick Fitzgerald
2023-03-10 16:33:06 -08:00
committed by GitHub
parent 264089e29d
commit 9ed441e657
11 changed files with 544 additions and 6 deletions

View File

@@ -6,7 +6,7 @@
use anyhow::Result;
use clap::{ErrorKind, Parser};
use wasmtime_cli::commands::{
CompileCommand, ConfigCommand, RunCommand, SettingsCommand, WastCommand,
CompileCommand, ConfigCommand, ExploreCommand, RunCommand, SettingsCommand, WastCommand,
};
/// Wasmtime WebAssembly Runtime
@@ -35,6 +35,8 @@ enum Wasmtime {
Config(ConfigCommand),
/// Compiles a WebAssembly module.
Compile(CompileCommand),
/// Explore the compilation of a WebAssembly module to native code.
Explore(ExploreCommand),
/// Runs a WebAssembly module
Run(RunCommand),
/// Displays available Cranelift settings for a target.
@@ -49,6 +51,7 @@ impl Wasmtime {
match self {
Self::Config(c) => c.execute(),
Self::Compile(c) => c.execute(),
Self::Explore(c) => c.execute(),
Self::Run(c) => c.execute(),
Self::Settings(c) => c.execute(),
Self::Wast(c) => c.execute(),

View File

@@ -2,8 +2,9 @@
mod compile;
mod config;
mod explore;
mod run;
mod settings;
mod wast;
pub use self::{compile::*, config::*, run::*, settings::*, wast::*};
pub use self::{compile::*, config::*, explore::*, run::*, settings::*, wast::*};

51
src/commands/explore.rs Normal file
View File

@@ -0,0 +1,51 @@
//! The module that implements the `wasmtime explore` command.
use anyhow::{Context, Result};
use clap::Parser;
use std::path::PathBuf;
use wasmtime_cli_flags::CommonOptions;
/// Explore the compilation of a WebAssembly module to native code.
#[derive(Parser)]
#[clap(name = "explore")]
pub struct ExploreCommand {
#[clap(flatten)]
common: CommonOptions,
/// The target triple; default is the host triple
#[clap(long, value_name = "TARGET")]
target: Option<String>,
/// The path of the WebAssembly module to compile
#[clap(required = true, value_name = "MODULE")]
module: PathBuf,
/// The path of the explorer output (derived from the MODULE name if none
/// provided)
#[clap(short, long)]
output: Option<PathBuf>,
}
impl ExploreCommand {
/// Executes the command.
pub fn execute(&self) -> Result<()> {
self.common.init_logging();
let config = self.common.config(self.target.as_deref())?;
let wasm = std::fs::read(&self.module)
.with_context(|| format!("failed to read Wasm module: {}", self.module.display()))?;
let output = self
.output
.clone()
.unwrap_or_else(|| self.module.with_extension("explore.html"));
let output_file = std::fs::File::create(&output)
.with_context(|| format!("failed to create file: {}", output.display()))?;
let mut output_file = std::io::BufWriter::new(output_file);
wasmtime_explorer::generate(&config, self.target.as_deref(), &wasm, &mut output_file)?;
println!("Exploration written to {}", output.display());
Ok(())
}
}