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