Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/environ/examples/factc.rs
1691 views
1
use anyhow::{Context, Result, bail};
2
use clap::Parser;
3
use std::io::{IsTerminal, Write};
4
use std::path::{Path, PathBuf};
5
use wasmparser::{Validator, WasmFeatures};
6
use wasmtime_environ::{ScopeVec, Tunables, component::*};
7
8
/// A small helper utility to explore generated adapter modules from Wasmtime's
9
/// adapter fusion compiler.
10
///
11
/// This utility takes a `*.wat` file as input which is expected to be a valid
12
/// WebAssembly component. The component is parsed and any type definition for a
13
/// component function gets a generated adapter for it as if the caller/callee
14
/// used that type as the adapter.
15
///
16
/// For example with an input that looks like:
17
///
18
/// (component
19
/// (type (func (param u32) (result (list u8))))
20
/// )
21
///
22
/// This tool can be used to generate an adapter for that signature.
23
#[derive(Parser)]
24
struct Factc {
25
/// Whether or not debug code is inserted into the generated adapter.
26
#[arg(long)]
27
debug: bool,
28
29
/// Whether or not to skip validation of the generated adapter module.
30
#[arg(long)]
31
skip_validate: bool,
32
33
/// Where to place the generated adapter module. Standard output is used if
34
/// this is not specified.
35
#[arg(short, long)]
36
output: Option<PathBuf>,
37
38
/// Output the text format for WebAssembly instead of the binary format.
39
#[arg(short, long)]
40
text: bool,
41
42
/// The input component to generate adapters for.
43
input: PathBuf,
44
}
45
46
fn main() -> Result<()> {
47
Factc::parse().execute()
48
}
49
50
impl Factc {
51
fn execute(self) -> Result<()> {
52
env_logger::init();
53
54
let input = wat::parse_file(&self.input)?;
55
56
let tunables = Tunables::default_host();
57
let mut validator =
58
wasmparser::Validator::new_with_features(wasmparser::WasmFeatures::all());
59
let mut component_types = ComponentTypesBuilder::new(&validator);
60
let adapters = ScopeVec::new();
61
62
Translator::new(&tunables, &mut validator, &mut component_types, &adapters)
63
.translate(&input)?;
64
65
let (out_name, mut out_file): (_, Box<dyn std::io::Write>) = match &self.output {
66
Some(file) => (
67
file.as_path(),
68
Box::new(std::io::BufWriter::new(
69
std::fs::File::create(file)
70
.with_context(|| format!("failed to create {}", file.display()))?,
71
)),
72
),
73
None => (Path::new("stdout"), Box::new(std::io::stdout())),
74
};
75
76
for wasm in adapters.into_iter() {
77
let output = if self.text {
78
wasmprinter::print_bytes(&wasm)
79
.context("failed to convert binary wasm to text")?
80
.into_bytes()
81
} else if self.output.is_none() && std::io::stdout().is_terminal() {
82
bail!("cannot print binary wasm output to a terminal unless `-t` flag is passed")
83
} else {
84
wasm.to_vec()
85
};
86
87
out_file
88
.write_all(&output)
89
.with_context(|| format!("failed to write to {}", out_name.display()))?;
90
91
if !self.skip_validate {
92
Validator::new_with_features(WasmFeatures::default() | WasmFeatures::MEMORY64)
93
.validate_all(&wasm)
94
.context("failed to validate generated module")?;
95
}
96
}
97
98
Ok(())
99
}
100
}
101
102