Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/wizer/src/info.rs
2458 views
1
use std::convert::TryFrom;
2
use std::ops::Range;
3
4
/// Info that we keep track of on a per module-within-a-module-linking-bundle
5
/// basis.
6
///
7
/// These are created during our `parse` pass and then used throughout
8
/// our later passes.
9
#[derive(Default)]
10
pub struct ModuleContext<'a> {
11
/// The raw sections from the original Wasm input.
12
raw_sections: Vec<wasm_encoder::RawSection<'a>>,
13
14
/// Imports made by this module.
15
imports: Vec<wasmparser::Import<'a>>,
16
17
/// A map from global indices to each global's type for all defined,
18
/// imported, and aliased globals.
19
globals: Vec<wasmparser::GlobalType>,
20
21
/// The index within the global index space where defined globals (as
22
/// opposed to imported or aliased) begin.
23
///
24
/// If this is `None`, then there are no locally defined globals.
25
defined_globals_index: Option<u32>,
26
27
/// This module's exports.
28
///
29
/// This is used later on, in the rewrite phase, when we are inserting state
30
/// instance imports.
31
///
32
/// Note that this does *not* include the `__wizer_thing_N` exports that
33
/// this instrumentation pass adds.
34
exports: Vec<wasmparser::Export<'a>>,
35
36
/// Maps from function index to the function's type index for all functions
37
/// defined and imported in this module.
38
functions: Vec<u32>,
39
40
/// Maps from table index to the table's type for all tables defined,
41
/// imported, and aliased in this module.
42
tables: Vec<wasmparser::TableType>,
43
44
/// Maps from memory index to the memory's type for all memories defined,
45
/// imported, and aliased in this module.
46
memories: Vec<wasmparser::MemoryType>,
47
48
/// The index within the memory index space where defined memories (as
49
/// opposed to imported or aliased) begin.
50
///
51
/// If this is `None`, then there are no locally defined memories.
52
defined_memories_index: Option<u32>,
53
54
/// Export names of defined globals injected by the instrumentation pass.
55
///
56
/// Note that this only tracks defined mutable globals, not all globals.
57
pub(crate) defined_global_exports: Option<Vec<(u32, String)>>,
58
59
/// Export names of defined memories injected by the instrumentation pass.
60
pub(crate) defined_memory_exports: Option<Vec<String>>,
61
}
62
63
impl<'a> ModuleContext<'a> {
64
/// Add a new raw section to this module info during parsing.
65
pub(crate) fn add_raw_section(&mut self, id: u8, range: Range<usize>, full_wasm: &'a [u8]) {
66
self.raw_sections.push(wasm_encoder::RawSection {
67
id,
68
data: &full_wasm[range.start..range.end],
69
})
70
}
71
72
/// Push a new imported memory into this module's memory index space.
73
pub(crate) fn push_imported_memory(&mut self, memory_type: wasmparser::MemoryType) {
74
assert!(self.defined_memories_index.is_none());
75
self.memories.push(memory_type);
76
}
77
78
/// Push a new defined memory into this module's memory index space.
79
pub(crate) fn push_defined_memory(&mut self, memory_type: wasmparser::MemoryType) {
80
if self.defined_memories_index.is_none() {
81
self.defined_memories_index = Some(u32::try_from(self.memories.len()).unwrap());
82
}
83
self.memories.push(memory_type);
84
}
85
86
/// Push a new imported global into this module's global index space.
87
pub(crate) fn push_imported_global(&mut self, global_type: wasmparser::GlobalType) {
88
assert!(self.defined_globals_index.is_none());
89
self.globals.push(global_type);
90
}
91
92
/// Push a new defined global into this module's global index space.
93
pub(crate) fn push_defined_global(&mut self, global_type: wasmparser::GlobalType) {
94
if self.defined_globals_index.is_none() {
95
self.defined_globals_index = Some(u32::try_from(self.globals.len()).unwrap());
96
}
97
self.globals.push(global_type);
98
}
99
100
/// Push a new function into this module's function index space.
101
pub(crate) fn push_function(&mut self, func_type: u32) {
102
self.functions.push(func_type);
103
}
104
105
/// Push a new table into this module's table index space.
106
pub(crate) fn push_table(&mut self, table_type: wasmparser::TableType) {
107
self.tables.push(table_type);
108
}
109
110
/// Push a new import into this module.
111
pub(crate) fn push_import(&mut self, import: wasmparser::Import<'a>) {
112
self.imports.push(import);
113
114
// Add the import to the appropriate index space for our current module.
115
match import.ty {
116
wasmparser::TypeRef::Memory(ty) => {
117
self.push_imported_memory(ty);
118
}
119
wasmparser::TypeRef::Global(ty) => {
120
self.push_imported_global(ty);
121
}
122
wasmparser::TypeRef::Func(ty_idx) => {
123
self.push_function(ty_idx);
124
}
125
wasmparser::TypeRef::Table(ty) => {
126
self.push_table(ty);
127
}
128
wasmparser::TypeRef::Tag(_) => {
129
unreachable!("exceptions are unsupported; checked in validation")
130
}
131
wasmparser::TypeRef::FuncExact(_) => {
132
unreachable!("custom-descriptors are unsupported; checked in validation")
133
}
134
}
135
}
136
137
/// Push an export into this module.
138
pub(crate) fn push_export(&mut self, export: wasmparser::Export<'a>) {
139
self.exports.push(export);
140
}
141
142
/// The number of defined memories in this module.
143
pub(crate) fn defined_memories_len(&self) -> usize {
144
self.defined_memories_index.map_or(0, |n| {
145
let n = usize::try_from(n).unwrap();
146
assert!(self.memories.len() > n);
147
self.memories.len() - n
148
})
149
}
150
151
/// Iterate over the defined memories in this module.
152
pub(crate) fn defined_memories(
153
&self,
154
) -> impl Iterator<Item = (u32, wasmparser::MemoryType)> + '_ {
155
self.memories
156
.iter()
157
.copied()
158
.enumerate()
159
.skip(
160
self.defined_memories_index
161
.map_or(self.memories.len(), |i| usize::try_from(i).unwrap()),
162
)
163
.map(|(i, m)| (u32::try_from(i).unwrap(), m))
164
}
165
166
/// Iterate over the defined globals in this module.
167
pub(crate) fn defined_globals(
168
&self,
169
) -> impl Iterator<Item = (u32, wasmparser::GlobalType, Option<&str>)> + '_ {
170
let mut defined_global_exports = self
171
.defined_global_exports
172
.as_ref()
173
.map(|v| v.as_slice())
174
.unwrap_or(&[])
175
.iter()
176
.peekable();
177
178
self.globals
179
.iter()
180
.copied()
181
.enumerate()
182
.skip(
183
self.defined_globals_index
184
.map_or(self.globals.len(), |i| usize::try_from(i).unwrap()),
185
)
186
.map(move |(i, g)| {
187
let i = u32::try_from(i).unwrap();
188
let name = defined_global_exports
189
.next_if(|(j, _)| *j == i)
190
.map(|(_, name)| name.as_str());
191
(i, g, name)
192
})
193
}
194
195
/// Get a slice of this module's original raw sections.
196
pub(crate) fn raw_sections(&self) -> &[wasm_encoder::RawSection<'a>] {
197
&self.raw_sections
198
}
199
200
/// Get a slice of this module's imports.
201
pub(crate) fn imports(&self) -> &[wasmparser::Import<'a>] {
202
&self.imports
203
}
204
205
/// Get a slice of this module's exports.
206
pub(crate) fn exports(&self) -> &[wasmparser::Export<'a>] {
207
&self.exports
208
}
209
210
pub(crate) fn has_wasi_initialize(&self) -> bool {
211
self.exports.iter().any(|e| e.name == "_initialize")
212
}
213
}
214
215