pub trait ModuleEnvironment<'data> {
Show 43 methods fn declare_type_func(
        &mut self,
        wasm_func_type: WasmFuncType
    ) -> WasmResult<()>; fn declare_func_import(
        &mut self,
        index: TypeIndex,
        module: &'data str,
        field: &'data str
    ) -> WasmResult<()>; fn declare_table_import(
        &mut self,
        table: Table,
        module: &'data str,
        field: &'data str
    ) -> WasmResult<()>; fn declare_memory_import(
        &mut self,
        memory: Memory,
        module: &'data str,
        field: &'data str
    ) -> WasmResult<()>; fn declare_global_import(
        &mut self,
        global: Global,
        module: &'data str,
        field: &'data str
    ) -> WasmResult<()>; fn declare_func_type(&mut self, index: TypeIndex) -> WasmResult<()>; fn declare_table(&mut self, table: Table) -> WasmResult<()>; fn declare_memory(&mut self, memory: Memory) -> WasmResult<()>; fn declare_global(&mut self, global: Global) -> WasmResult<()>; fn declare_func_export(
        &mut self,
        func_index: FuncIndex,
        name: &'data str
    ) -> WasmResult<()>; fn declare_table_export(
        &mut self,
        table_index: TableIndex,
        name: &'data str
    ) -> WasmResult<()>; fn declare_memory_export(
        &mut self,
        memory_index: MemoryIndex,
        name: &'data str
    ) -> WasmResult<()>; fn declare_global_export(
        &mut self,
        global_index: GlobalIndex,
        name: &'data str
    ) -> WasmResult<()>; fn declare_start_func(&mut self, index: FuncIndex) -> WasmResult<()>; fn declare_table_elements(
        &mut self,
        table_index: TableIndex,
        base: Option<GlobalIndex>,
        offset: u32,
        elements: Box<[FuncIndex]>
    ) -> WasmResult<()>; fn declare_passive_element(
        &mut self,
        index: ElemIndex,
        elements: Box<[FuncIndex]>
    ) -> WasmResult<()>; fn declare_passive_data(
        &mut self,
        data_index: DataIndex,
        data: &'data [u8]
    ) -> WasmResult<()>; fn define_function_body(
        &mut self,
        validator: FuncValidator<ValidatorResources>,
        body: FunctionBody<'data>
    ) -> WasmResult<()>; fn declare_data_initialization(
        &mut self,
        memory_index: MemoryIndex,
        base: Option<GlobalIndex>,
        offset: u64,
        data: &'data [u8]
    ) -> WasmResult<()>; fn reserve_types(&mut self, _num: u32) -> WasmResult<()> { ... } fn type_to_signature(&self, index: TypeIndex) -> WasmResult<SignatureIndex> { ... } fn reserve_imports(&mut self, _num: u32) -> WasmResult<()> { ... } fn declare_tag_import(
        &mut self,
        tag: Tag,
        module: &'data str,
        field: &'data str
    ) -> WasmResult<()> { ... } fn finish_imports(&mut self) -> WasmResult<()> { ... } fn reserve_func_types(&mut self, _num: u32) -> WasmResult<()> { ... } fn reserve_tables(&mut self, _num: u32) -> WasmResult<()> { ... } fn reserve_memories(&mut self, _num: u32) -> WasmResult<()> { ... } fn reserve_tags(&mut self, _num: u32) -> WasmResult<()> { ... } fn declare_tag(&mut self, tag: Tag) -> WasmResult<()> { ... } fn reserve_globals(&mut self, _num: u32) -> WasmResult<()> { ... } fn reserve_exports(&mut self, _num: u32) -> WasmResult<()> { ... } fn declare_tag_export(
        &mut self,
        tag_index: TagIndex,
        name: &'data str
    ) -> WasmResult<()> { ... } fn finish_exports(&mut self) -> WasmResult<()> { ... } fn reserve_table_elements(&mut self, _num: u32) -> WasmResult<()> { ... } fn declare_elements(&mut self, elements: Box<[FuncIndex]>) -> WasmResult<()> { ... } fn reserve_passive_data(&mut self, count: u32) -> WasmResult<()> { ... } fn reserve_function_bodies(&mut self, bodies: u32, code_section_offset: u64) { ... } fn reserve_data_initializers(&mut self, _num: u32) -> WasmResult<()> { ... } fn declare_module_name(&mut self, _name: &'data str) { ... } fn declare_func_name(&mut self, _func_index: FuncIndex, _name: &'data str) { ... } fn declare_local_name(
        &mut self,
        _func_index: FuncIndex,
        _local_index: u32,
        _name: &'data str
    ) { ... } fn custom_section(
        &mut self,
        _name: &'data str,
        _data: &'data [u8]
    ) -> WasmResult<()> { ... } fn wasm_features(&self) -> WasmFeatures { ... }
}
Expand description

An object satisfying the ModuleEnvironment trait can be passed as argument to the translate_module function. These methods should not be called by the user, they are only for cranelift-wasm internal use.

Required Methods§

Declares a function signature to the environment.

Declares a function import to the environment.

Declares a table import to the environment.

Declares a memory import to the environment.

Declares a global import to the environment.

Declares the type (signature) of a local function in the module.

Declares a table to the environment.

Declares a memory to the environment

Declares a global to the environment.

Declares a function export to the environment.

Declares a table export to the environment.

Declares a memory export to the environment.

Declares a global export to the environment.

Declares the optional start function.

Fills a declared table with references to functions in the module.

Declare a passive element segment.

Declare a passive data segment.

Provides the contents of a function body.

Fills a declared memory with bytes at module instantiation.

Provided Methods§

Provides the number of types up front. By default this does nothing, but implementations can use this to preallocate memory if desired.

Examples found in repository?
src/sections_translator.rs (line 69)
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
pub fn parse_type_section<'a>(
    types: TypeSectionReader<'a>,
    environ: &mut dyn ModuleEnvironment<'a>,
) -> WasmResult<()> {
    let count = types.get_count();
    environ.reserve_types(count)?;

    for entry in types {
        match entry? {
            Type::Func(wasm_func_ty) => {
                environ.declare_type_func(wasm_func_ty.clone().try_into()?)?;
            }
        }
    }
    Ok(())
}

Translates a type index to its signature index, only called for type indices which point to functions.

Provides the number of imports up front. By default this does nothing, but implementations can use this to preallocate memory if desired.

Examples found in repository?
src/sections_translator.rs (line 86)
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
pub fn parse_import_section<'data>(
    imports: ImportSectionReader<'data>,
    environ: &mut dyn ModuleEnvironment<'data>,
) -> WasmResult<()> {
    environ.reserve_imports(imports.get_count())?;

    for entry in imports {
        let import = entry?;
        match import.ty {
            TypeRef::Func(sig) => {
                environ.declare_func_import(
                    TypeIndex::from_u32(sig),
                    import.module,
                    import.name,
                )?;
            }
            TypeRef::Memory(ty) => {
                environ.declare_memory_import(memory(ty), import.module, import.name)?;
            }
            TypeRef::Tag(e) => {
                environ.declare_tag_import(tag(e), import.module, import.name)?;
            }
            TypeRef::Global(ty) => {
                let ty = global(ty, GlobalInit::Import)?;
                environ.declare_global_import(ty, import.module, import.name)?;
            }
            TypeRef::Table(ty) => {
                let ty = table(ty)?;
                environ.declare_table_import(ty, import.module, import.name)?;
            }
        }
    }

    environ.finish_imports()?;
    Ok(())
}

Declares an tag import to the environment.

Examples found in repository?
src/sections_translator.rs (line 102)
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
pub fn parse_import_section<'data>(
    imports: ImportSectionReader<'data>,
    environ: &mut dyn ModuleEnvironment<'data>,
) -> WasmResult<()> {
    environ.reserve_imports(imports.get_count())?;

    for entry in imports {
        let import = entry?;
        match import.ty {
            TypeRef::Func(sig) => {
                environ.declare_func_import(
                    TypeIndex::from_u32(sig),
                    import.module,
                    import.name,
                )?;
            }
            TypeRef::Memory(ty) => {
                environ.declare_memory_import(memory(ty), import.module, import.name)?;
            }
            TypeRef::Tag(e) => {
                environ.declare_tag_import(tag(e), import.module, import.name)?;
            }
            TypeRef::Global(ty) => {
                let ty = global(ty, GlobalInit::Import)?;
                environ.declare_global_import(ty, import.module, import.name)?;
            }
            TypeRef::Table(ty) => {
                let ty = table(ty)?;
                environ.declare_table_import(ty, import.module, import.name)?;
            }
        }
    }

    environ.finish_imports()?;
    Ok(())
}

Notifies the implementation that all imports have been declared.

Examples found in repository?
src/sections_translator.rs (line 115)
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
pub fn parse_import_section<'data>(
    imports: ImportSectionReader<'data>,
    environ: &mut dyn ModuleEnvironment<'data>,
) -> WasmResult<()> {
    environ.reserve_imports(imports.get_count())?;

    for entry in imports {
        let import = entry?;
        match import.ty {
            TypeRef::Func(sig) => {
                environ.declare_func_import(
                    TypeIndex::from_u32(sig),
                    import.module,
                    import.name,
                )?;
            }
            TypeRef::Memory(ty) => {
                environ.declare_memory_import(memory(ty), import.module, import.name)?;
            }
            TypeRef::Tag(e) => {
                environ.declare_tag_import(tag(e), import.module, import.name)?;
            }
            TypeRef::Global(ty) => {
                let ty = global(ty, GlobalInit::Import)?;
                environ.declare_global_import(ty, import.module, import.name)?;
            }
            TypeRef::Table(ty) => {
                let ty = table(ty)?;
                environ.declare_table_import(ty, import.module, import.name)?;
            }
        }
    }

    environ.finish_imports()?;
    Ok(())
}

Provides the number of defined functions up front. By default this does nothing, but implementations can use this to preallocate memory if desired.

Examples found in repository?
src/sections_translator.rs (line 130)
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
pub fn parse_function_section(
    functions: FunctionSectionReader,
    environ: &mut dyn ModuleEnvironment,
) -> WasmResult<()> {
    let num_functions = functions.get_count();
    if num_functions == std::u32::MAX {
        // We reserve `u32::MAX` for our own use in cranelift-entity.
        return Err(WasmError::ImplLimitExceeded);
    }

    environ.reserve_func_types(num_functions)?;

    for entry in functions {
        let sigindex = entry?;
        environ.declare_func_type(TypeIndex::from_u32(sigindex))?;
    }

    Ok(())
}

Provides the number of defined tables up front. By default this does nothing, but implementations can use this to preallocate memory if desired.

Examples found in repository?
src/sections_translator.rs (line 145)
141
142
143
144
145
146
147
148
149
150
151
152
153
pub fn parse_table_section(
    tables: TableSectionReader,
    environ: &mut dyn ModuleEnvironment,
) -> WasmResult<()> {
    environ.reserve_tables(tables.get_count())?;

    for entry in tables {
        let ty = table(entry?)?;
        environ.declare_table(ty)?;
    }

    Ok(())
}

Provides the number of defined memories up front. By default this does nothing, but implementations can use this to preallocate memory if desired.

Examples found in repository?
src/sections_translator.rs (line 160)
156
157
158
159
160
161
162
163
164
165
166
167
168
pub fn parse_memory_section(
    memories: MemorySectionReader,
    environ: &mut dyn ModuleEnvironment,
) -> WasmResult<()> {
    environ.reserve_memories(memories.get_count())?;

    for entry in memories {
        let memory = memory(entry?);
        environ.declare_memory(memory)?;
    }

    Ok(())
}

Provides the number of defined tags up front. By default this does nothing, but implementations can use this to preallocate memory if desired.

Examples found in repository?
src/sections_translator.rs (line 175)
171
172
173
174
175
176
177
178
179
180
181
182
183
pub fn parse_tag_section(
    tags: TagSectionReader,
    environ: &mut dyn ModuleEnvironment,
) -> WasmResult<()> {
    environ.reserve_tags(tags.get_count())?;

    for entry in tags {
        let tag = tag(entry?);
        environ.declare_tag(tag)?;
    }

    Ok(())
}

Declares an tag to the environment

Examples found in repository?
src/sections_translator.rs (line 179)
171
172
173
174
175
176
177
178
179
180
181
182
183
pub fn parse_tag_section(
    tags: TagSectionReader,
    environ: &mut dyn ModuleEnvironment,
) -> WasmResult<()> {
    environ.reserve_tags(tags.get_count())?;

    for entry in tags {
        let tag = tag(entry?);
        environ.declare_tag(tag)?;
    }

    Ok(())
}

Provides the number of defined globals up front. By default this does nothing, but implementations can use this to preallocate memory if desired.

Examples found in repository?
src/sections_translator.rs (line 190)
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
pub fn parse_global_section(
    globals: GlobalSectionReader,
    environ: &mut dyn ModuleEnvironment,
) -> WasmResult<()> {
    environ.reserve_globals(globals.get_count())?;

    for entry in globals {
        let wasmparser::Global { ty, init_expr } = entry?;
        let mut init_expr_reader = init_expr.get_binary_reader();
        let initializer = match init_expr_reader.read_operator()? {
            Operator::I32Const { value } => GlobalInit::I32Const(value),
            Operator::I64Const { value } => GlobalInit::I64Const(value),
            Operator::F32Const { value } => GlobalInit::F32Const(value.bits()),
            Operator::F64Const { value } => GlobalInit::F64Const(value.bits()),
            Operator::V128Const { value } => {
                GlobalInit::V128Const(u128::from_le_bytes(*value.bytes()))
            }
            Operator::RefNull { ty: _ } => GlobalInit::RefNullConst,
            Operator::RefFunc { function_index } => {
                GlobalInit::RefFunc(FuncIndex::from_u32(function_index))
            }
            Operator::GlobalGet { global_index } => {
                GlobalInit::GetGlobal(GlobalIndex::from_u32(global_index))
            }
            ref s => {
                return Err(wasm_unsupported!(
                    "unsupported init expr in global section: {:?}",
                    s
                ));
            }
        };
        let ty = global(ty, initializer)?;
        environ.declare_global(ty)?;
    }

    Ok(())
}

Provides the number of exports up front. By default this does nothing, but implementations can use this to preallocate memory if desired.

Examples found in repository?
src/sections_translator.rs (line 229)
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
pub fn parse_export_section<'data>(
    exports: ExportSectionReader<'data>,
    environ: &mut dyn ModuleEnvironment<'data>,
) -> WasmResult<()> {
    environ.reserve_exports(exports.get_count())?;

    for entry in exports {
        let Export {
            name,
            ref kind,
            index,
        } = entry?;

        // The input has already been validated, so we should be able to
        // assume valid UTF-8 and use `from_utf8_unchecked` if performance
        // becomes a concern here.
        let index = index as usize;
        match *kind {
            ExternalKind::Func => environ.declare_func_export(FuncIndex::new(index), name)?,
            ExternalKind::Table => environ.declare_table_export(TableIndex::new(index), name)?,
            ExternalKind::Memory => environ.declare_memory_export(MemoryIndex::new(index), name)?,
            ExternalKind::Tag => environ.declare_tag_export(TagIndex::new(index), name)?,
            ExternalKind::Global => environ.declare_global_export(GlobalIndex::new(index), name)?,
        }
    }

    environ.finish_exports()?;
    Ok(())
}

Declares an tag export to the environment.

Examples found in repository?
src/sections_translator.rs (line 246)
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
pub fn parse_export_section<'data>(
    exports: ExportSectionReader<'data>,
    environ: &mut dyn ModuleEnvironment<'data>,
) -> WasmResult<()> {
    environ.reserve_exports(exports.get_count())?;

    for entry in exports {
        let Export {
            name,
            ref kind,
            index,
        } = entry?;

        // The input has already been validated, so we should be able to
        // assume valid UTF-8 and use `from_utf8_unchecked` if performance
        // becomes a concern here.
        let index = index as usize;
        match *kind {
            ExternalKind::Func => environ.declare_func_export(FuncIndex::new(index), name)?,
            ExternalKind::Table => environ.declare_table_export(TableIndex::new(index), name)?,
            ExternalKind::Memory => environ.declare_memory_export(MemoryIndex::new(index), name)?,
            ExternalKind::Tag => environ.declare_tag_export(TagIndex::new(index), name)?,
            ExternalKind::Global => environ.declare_global_export(GlobalIndex::new(index), name)?,
        }
    }

    environ.finish_exports()?;
    Ok(())
}

Notifies the implementation that all exports have been declared.

Examples found in repository?
src/sections_translator.rs (line 251)
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
pub fn parse_export_section<'data>(
    exports: ExportSectionReader<'data>,
    environ: &mut dyn ModuleEnvironment<'data>,
) -> WasmResult<()> {
    environ.reserve_exports(exports.get_count())?;

    for entry in exports {
        let Export {
            name,
            ref kind,
            index,
        } = entry?;

        // The input has already been validated, so we should be able to
        // assume valid UTF-8 and use `from_utf8_unchecked` if performance
        // becomes a concern here.
        let index = index as usize;
        match *kind {
            ExternalKind::Func => environ.declare_func_export(FuncIndex::new(index), name)?,
            ExternalKind::Table => environ.declare_table_export(TableIndex::new(index), name)?,
            ExternalKind::Memory => environ.declare_memory_export(MemoryIndex::new(index), name)?,
            ExternalKind::Tag => environ.declare_tag_export(TagIndex::new(index), name)?,
            ExternalKind::Global => environ.declare_global_export(GlobalIndex::new(index), name)?,
        }
    }

    environ.finish_exports()?;
    Ok(())
}

Provides the number of element initializers up front. By default this does nothing, but implementations can use this to preallocate memory if desired.

Examples found in repository?
src/sections_translator.rs (line 288)
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
pub fn parse_element_section<'data>(
    elements: ElementSectionReader<'data>,
    environ: &mut dyn ModuleEnvironment,
) -> WasmResult<()> {
    environ.reserve_table_elements(elements.get_count())?;

    for (index, entry) in elements.into_iter().enumerate() {
        let Element {
            kind,
            items,
            ty: _,
            range: _,
        } = entry?;
        let segments = read_elems(&items)?;
        match kind {
            ElementKind::Active {
                table_index,
                offset_expr,
            } => {
                let mut offset_expr_reader = offset_expr.get_binary_reader();
                let (base, offset) = match offset_expr_reader.read_operator()? {
                    Operator::I32Const { value } => (None, value as u32),
                    Operator::GlobalGet { global_index } => {
                        (Some(GlobalIndex::from_u32(global_index)), 0)
                    }
                    ref s => {
                        return Err(wasm_unsupported!(
                            "unsupported init expr in element section: {:?}",
                            s
                        ));
                    }
                };
                environ.declare_table_elements(
                    TableIndex::from_u32(table_index),
                    base,
                    offset,
                    segments,
                )?
            }
            ElementKind::Passive => {
                let index = ElemIndex::from_u32(index as u32);
                environ.declare_passive_element(index, segments)?;
            }
            ElementKind::Declared => {
                environ.declare_elements(segments)?;
            }
        }
    }
    Ok(())
}

Indicates that a declarative element segment was seen in the wasm module.

Examples found in repository?
src/sections_translator.rs (line 328)
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
pub fn parse_element_section<'data>(
    elements: ElementSectionReader<'data>,
    environ: &mut dyn ModuleEnvironment,
) -> WasmResult<()> {
    environ.reserve_table_elements(elements.get_count())?;

    for (index, entry) in elements.into_iter().enumerate() {
        let Element {
            kind,
            items,
            ty: _,
            range: _,
        } = entry?;
        let segments = read_elems(&items)?;
        match kind {
            ElementKind::Active {
                table_index,
                offset_expr,
            } => {
                let mut offset_expr_reader = offset_expr.get_binary_reader();
                let (base, offset) = match offset_expr_reader.read_operator()? {
                    Operator::I32Const { value } => (None, value as u32),
                    Operator::GlobalGet { global_index } => {
                        (Some(GlobalIndex::from_u32(global_index)), 0)
                    }
                    ref s => {
                        return Err(wasm_unsupported!(
                            "unsupported init expr in element section: {:?}",
                            s
                        ));
                    }
                };
                environ.declare_table_elements(
                    TableIndex::from_u32(table_index),
                    base,
                    offset,
                    segments,
                )?
            }
            ElementKind::Passive => {
                let index = ElemIndex::from_u32(index as u32);
                environ.declare_passive_element(index, segments)?;
            }
            ElementKind::Declared => {
                environ.declare_elements(segments)?;
            }
        }
    }
    Ok(())
}

Provides the number of passive data segments up front.

By default this does nothing, but implementations may use this to pre-allocate memory if desired.

Examples found in repository?
src/module_translator.rs (line 107)
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
pub fn translate_module<'data>(
    data: &'data [u8],
    environ: &mut dyn ModuleEnvironment<'data>,
) -> WasmResult<()> {
    let _tt = timing::wasm_translate_module();
    let mut validator = Validator::new_with_features(environ.wasm_features());

    for payload in Parser::new(0).parse_all(data) {
        match payload? {
            Payload::Version {
                num,
                encoding,
                range,
            } => {
                validator.version(num, encoding, &range)?;
            }
            Payload::End(offset) => {
                validator.end(offset)?;
            }

            Payload::TypeSection(types) => {
                validator.type_section(&types)?;
                parse_type_section(types, environ)?;
            }

            Payload::ImportSection(imports) => {
                validator.import_section(&imports)?;
                parse_import_section(imports, environ)?;
            }

            Payload::FunctionSection(functions) => {
                validator.function_section(&functions)?;
                parse_function_section(functions, environ)?;
            }

            Payload::TableSection(tables) => {
                validator.table_section(&tables)?;
                parse_table_section(tables, environ)?;
            }

            Payload::MemorySection(memories) => {
                validator.memory_section(&memories)?;
                parse_memory_section(memories, environ)?;
            }

            Payload::TagSection(tags) => {
                validator.tag_section(&tags)?;
                parse_tag_section(tags, environ)?;
            }

            Payload::GlobalSection(globals) => {
                validator.global_section(&globals)?;
                parse_global_section(globals, environ)?;
            }

            Payload::ExportSection(exports) => {
                validator.export_section(&exports)?;
                parse_export_section(exports, environ)?;
            }

            Payload::StartSection { func, range } => {
                validator.start_section(func, &range)?;
                parse_start_section(func, environ)?;
            }

            Payload::ElementSection(elements) => {
                validator.element_section(&elements)?;
                parse_element_section(elements, environ)?;
            }

            Payload::CodeSectionStart { count, range, .. } => {
                validator.code_section_start(count, &range)?;
                environ.reserve_function_bodies(count, range.start as u64);
            }

            Payload::CodeSectionEntry(body) => {
                let func_validator = validator
                    .code_section_entry(&body)?
                    .into_validator(Default::default());
                environ.define_function_body(func_validator, body)?;
            }

            Payload::DataSection(data) => {
                validator.data_section(&data)?;
                parse_data_section(data, environ)?;
            }

            Payload::DataCountSection { count, range } => {
                validator.data_count_section(count, &range)?;

                // NOTE: the count here is the total segment count, not the passive segment count
                environ.reserve_passive_data(count)?;
            }

            Payload::CustomSection(s) if s.name() == "name" => {
                let result = NameSectionReader::new(s.data(), s.data_offset())
                    .map_err(|e| e.into())
                    .and_then(|s| parse_name_section(s, environ));
                if let Err(e) = result {
                    log::warn!("failed to parse name section {:?}", e);
                }
            }

            Payload::CustomSection(s) => environ.custom_section(s.name(), s.data())?,

            other => {
                validator.payload(&other)?;
                panic!("unimplemented section {:?}", other);
            }
        }
    }

    Ok(())
}

Indicates how many functions the code section reports and the byte offset of where the code sections starts.

Examples found in repository?
src/module_translator.rs (line 88)
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
pub fn translate_module<'data>(
    data: &'data [u8],
    environ: &mut dyn ModuleEnvironment<'data>,
) -> WasmResult<()> {
    let _tt = timing::wasm_translate_module();
    let mut validator = Validator::new_with_features(environ.wasm_features());

    for payload in Parser::new(0).parse_all(data) {
        match payload? {
            Payload::Version {
                num,
                encoding,
                range,
            } => {
                validator.version(num, encoding, &range)?;
            }
            Payload::End(offset) => {
                validator.end(offset)?;
            }

            Payload::TypeSection(types) => {
                validator.type_section(&types)?;
                parse_type_section(types, environ)?;
            }

            Payload::ImportSection(imports) => {
                validator.import_section(&imports)?;
                parse_import_section(imports, environ)?;
            }

            Payload::FunctionSection(functions) => {
                validator.function_section(&functions)?;
                parse_function_section(functions, environ)?;
            }

            Payload::TableSection(tables) => {
                validator.table_section(&tables)?;
                parse_table_section(tables, environ)?;
            }

            Payload::MemorySection(memories) => {
                validator.memory_section(&memories)?;
                parse_memory_section(memories, environ)?;
            }

            Payload::TagSection(tags) => {
                validator.tag_section(&tags)?;
                parse_tag_section(tags, environ)?;
            }

            Payload::GlobalSection(globals) => {
                validator.global_section(&globals)?;
                parse_global_section(globals, environ)?;
            }

            Payload::ExportSection(exports) => {
                validator.export_section(&exports)?;
                parse_export_section(exports, environ)?;
            }

            Payload::StartSection { func, range } => {
                validator.start_section(func, &range)?;
                parse_start_section(func, environ)?;
            }

            Payload::ElementSection(elements) => {
                validator.element_section(&elements)?;
                parse_element_section(elements, environ)?;
            }

            Payload::CodeSectionStart { count, range, .. } => {
                validator.code_section_start(count, &range)?;
                environ.reserve_function_bodies(count, range.start as u64);
            }

            Payload::CodeSectionEntry(body) => {
                let func_validator = validator
                    .code_section_entry(&body)?
                    .into_validator(Default::default());
                environ.define_function_body(func_validator, body)?;
            }

            Payload::DataSection(data) => {
                validator.data_section(&data)?;
                parse_data_section(data, environ)?;
            }

            Payload::DataCountSection { count, range } => {
                validator.data_count_section(count, &range)?;

                // NOTE: the count here is the total segment count, not the passive segment count
                environ.reserve_passive_data(count)?;
            }

            Payload::CustomSection(s) if s.name() == "name" => {
                let result = NameSectionReader::new(s.data(), s.data_offset())
                    .map_err(|e| e.into())
                    .and_then(|s| parse_name_section(s, environ));
                if let Err(e) = result {
                    log::warn!("failed to parse name section {:?}", e);
                }
            }

            Payload::CustomSection(s) => environ.custom_section(s.name(), s.data())?,

            other => {
                validator.payload(&other)?;
                panic!("unimplemented section {:?}", other);
            }
        }
    }

    Ok(())
}

Provides the number of data initializers up front. By default this does nothing, but implementations can use this to preallocate memory if desired.

Examples found in repository?
src/sections_translator.rs (line 340)
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
pub fn parse_data_section<'data>(
    data: DataSectionReader<'data>,
    environ: &mut dyn ModuleEnvironment<'data>,
) -> WasmResult<()> {
    environ.reserve_data_initializers(data.get_count())?;

    for (index, entry) in data.into_iter().enumerate() {
        let Data {
            kind,
            data,
            range: _,
        } = entry?;
        match kind {
            DataKind::Active {
                memory_index,
                offset_expr,
            } => {
                let mut offset_expr_reader = offset_expr.get_binary_reader();
                let (base, offset) = match offset_expr_reader.read_operator()? {
                    Operator::I32Const { value } => (None, value as u64),
                    Operator::I64Const { value } => (None, value as u64),
                    Operator::GlobalGet { global_index } => {
                        (Some(GlobalIndex::from_u32(global_index)), 0)
                    }
                    ref s => {
                        return Err(wasm_unsupported!(
                            "unsupported init expr in data section: {:?}",
                            s
                        ))
                    }
                };
                environ.declare_data_initialization(
                    MemoryIndex::from_u32(memory_index),
                    base,
                    offset,
                    data,
                )?;
            }
            DataKind::Passive => {
                let index = DataIndex::from_u32(index as u32);
                environ.declare_passive_data(index, data)?;
            }
        }
    }

    Ok(())
}

Declares the name of a module to the environment.

By default this does nothing, but implementations can use this to read the module name subsection of the custom name section if desired.

Examples found in repository?
src/sections_translator.rs (line 401)
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
pub fn parse_name_section<'data>(
    names: NameSectionReader<'data>,
    environ: &mut dyn ModuleEnvironment<'data>,
) -> WasmResult<()> {
    for subsection in names {
        match subsection? {
            wasmparser::Name::Function(names) => {
                for name in names {
                    let Naming { index, name } = name?;
                    // We reserve `u32::MAX` for our own use in cranelift-entity.
                    if index != u32::max_value() {
                        environ.declare_func_name(FuncIndex::from_u32(index), name);
                    }
                }
            }
            wasmparser::Name::Module { name, .. } => {
                environ.declare_module_name(name);
            }
            wasmparser::Name::Local(reader) => {
                for f in reader {
                    let f = f?;
                    if f.index == u32::max_value() {
                        continue;
                    }
                    for name in f.names {
                        let Naming { index, name } = name?;
                        environ.declare_local_name(FuncIndex::from_u32(f.index), index, name)
                    }
                }
            }
            wasmparser::Name::Label(_)
            | wasmparser::Name::Type(_)
            | wasmparser::Name::Table(_)
            | wasmparser::Name::Global(_)
            | wasmparser::Name::Memory(_)
            | wasmparser::Name::Element(_)
            | wasmparser::Name::Data(_)
            | wasmparser::Name::Unknown { .. } => {}
        }
    }
    Ok(())
}

Declares the name of a function to the environment.

By default this does nothing, but implementations can use this to read the function name subsection of the custom name section if desired.

Examples found in repository?
src/sections_translator.rs (line 396)
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
pub fn parse_name_section<'data>(
    names: NameSectionReader<'data>,
    environ: &mut dyn ModuleEnvironment<'data>,
) -> WasmResult<()> {
    for subsection in names {
        match subsection? {
            wasmparser::Name::Function(names) => {
                for name in names {
                    let Naming { index, name } = name?;
                    // We reserve `u32::MAX` for our own use in cranelift-entity.
                    if index != u32::max_value() {
                        environ.declare_func_name(FuncIndex::from_u32(index), name);
                    }
                }
            }
            wasmparser::Name::Module { name, .. } => {
                environ.declare_module_name(name);
            }
            wasmparser::Name::Local(reader) => {
                for f in reader {
                    let f = f?;
                    if f.index == u32::max_value() {
                        continue;
                    }
                    for name in f.names {
                        let Naming { index, name } = name?;
                        environ.declare_local_name(FuncIndex::from_u32(f.index), index, name)
                    }
                }
            }
            wasmparser::Name::Label(_)
            | wasmparser::Name::Type(_)
            | wasmparser::Name::Table(_)
            | wasmparser::Name::Global(_)
            | wasmparser::Name::Memory(_)
            | wasmparser::Name::Element(_)
            | wasmparser::Name::Data(_)
            | wasmparser::Name::Unknown { .. } => {}
        }
    }
    Ok(())
}

Declares the name of a function’s local to the environment.

By default this does nothing, but implementations can use this to read the local name subsection of the custom name section if desired.

Examples found in repository?
src/sections_translator.rs (line 411)
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
pub fn parse_name_section<'data>(
    names: NameSectionReader<'data>,
    environ: &mut dyn ModuleEnvironment<'data>,
) -> WasmResult<()> {
    for subsection in names {
        match subsection? {
            wasmparser::Name::Function(names) => {
                for name in names {
                    let Naming { index, name } = name?;
                    // We reserve `u32::MAX` for our own use in cranelift-entity.
                    if index != u32::max_value() {
                        environ.declare_func_name(FuncIndex::from_u32(index), name);
                    }
                }
            }
            wasmparser::Name::Module { name, .. } => {
                environ.declare_module_name(name);
            }
            wasmparser::Name::Local(reader) => {
                for f in reader {
                    let f = f?;
                    if f.index == u32::max_value() {
                        continue;
                    }
                    for name in f.names {
                        let Naming { index, name } = name?;
                        environ.declare_local_name(FuncIndex::from_u32(f.index), index, name)
                    }
                }
            }
            wasmparser::Name::Label(_)
            | wasmparser::Name::Type(_)
            | wasmparser::Name::Table(_)
            | wasmparser::Name::Global(_)
            | wasmparser::Name::Memory(_)
            | wasmparser::Name::Element(_)
            | wasmparser::Name::Data(_)
            | wasmparser::Name::Unknown { .. } => {}
        }
    }
    Ok(())
}

Indicates that a custom section has been found in the wasm file

Examples found in repository?
src/module_translator.rs (line 119)
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
pub fn translate_module<'data>(
    data: &'data [u8],
    environ: &mut dyn ModuleEnvironment<'data>,
) -> WasmResult<()> {
    let _tt = timing::wasm_translate_module();
    let mut validator = Validator::new_with_features(environ.wasm_features());

    for payload in Parser::new(0).parse_all(data) {
        match payload? {
            Payload::Version {
                num,
                encoding,
                range,
            } => {
                validator.version(num, encoding, &range)?;
            }
            Payload::End(offset) => {
                validator.end(offset)?;
            }

            Payload::TypeSection(types) => {
                validator.type_section(&types)?;
                parse_type_section(types, environ)?;
            }

            Payload::ImportSection(imports) => {
                validator.import_section(&imports)?;
                parse_import_section(imports, environ)?;
            }

            Payload::FunctionSection(functions) => {
                validator.function_section(&functions)?;
                parse_function_section(functions, environ)?;
            }

            Payload::TableSection(tables) => {
                validator.table_section(&tables)?;
                parse_table_section(tables, environ)?;
            }

            Payload::MemorySection(memories) => {
                validator.memory_section(&memories)?;
                parse_memory_section(memories, environ)?;
            }

            Payload::TagSection(tags) => {
                validator.tag_section(&tags)?;
                parse_tag_section(tags, environ)?;
            }

            Payload::GlobalSection(globals) => {
                validator.global_section(&globals)?;
                parse_global_section(globals, environ)?;
            }

            Payload::ExportSection(exports) => {
                validator.export_section(&exports)?;
                parse_export_section(exports, environ)?;
            }

            Payload::StartSection { func, range } => {
                validator.start_section(func, &range)?;
                parse_start_section(func, environ)?;
            }

            Payload::ElementSection(elements) => {
                validator.element_section(&elements)?;
                parse_element_section(elements, environ)?;
            }

            Payload::CodeSectionStart { count, range, .. } => {
                validator.code_section_start(count, &range)?;
                environ.reserve_function_bodies(count, range.start as u64);
            }

            Payload::CodeSectionEntry(body) => {
                let func_validator = validator
                    .code_section_entry(&body)?
                    .into_validator(Default::default());
                environ.define_function_body(func_validator, body)?;
            }

            Payload::DataSection(data) => {
                validator.data_section(&data)?;
                parse_data_section(data, environ)?;
            }

            Payload::DataCountSection { count, range } => {
                validator.data_count_section(count, &range)?;

                // NOTE: the count here is the total segment count, not the passive segment count
                environ.reserve_passive_data(count)?;
            }

            Payload::CustomSection(s) if s.name() == "name" => {
                let result = NameSectionReader::new(s.data(), s.data_offset())
                    .map_err(|e| e.into())
                    .and_then(|s| parse_name_section(s, environ));
                if let Err(e) = result {
                    log::warn!("failed to parse name section {:?}", e);
                }
            }

            Payload::CustomSection(s) => environ.custom_section(s.name(), s.data())?,

            other => {
                validator.payload(&other)?;
                panic!("unimplemented section {:?}", other);
            }
        }
    }

    Ok(())
}

Returns the list of enabled wasm features this translation will be using.

Examples found in repository?
src/module_translator.rs (line 21)
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
pub fn translate_module<'data>(
    data: &'data [u8],
    environ: &mut dyn ModuleEnvironment<'data>,
) -> WasmResult<()> {
    let _tt = timing::wasm_translate_module();
    let mut validator = Validator::new_with_features(environ.wasm_features());

    for payload in Parser::new(0).parse_all(data) {
        match payload? {
            Payload::Version {
                num,
                encoding,
                range,
            } => {
                validator.version(num, encoding, &range)?;
            }
            Payload::End(offset) => {
                validator.end(offset)?;
            }

            Payload::TypeSection(types) => {
                validator.type_section(&types)?;
                parse_type_section(types, environ)?;
            }

            Payload::ImportSection(imports) => {
                validator.import_section(&imports)?;
                parse_import_section(imports, environ)?;
            }

            Payload::FunctionSection(functions) => {
                validator.function_section(&functions)?;
                parse_function_section(functions, environ)?;
            }

            Payload::TableSection(tables) => {
                validator.table_section(&tables)?;
                parse_table_section(tables, environ)?;
            }

            Payload::MemorySection(memories) => {
                validator.memory_section(&memories)?;
                parse_memory_section(memories, environ)?;
            }

            Payload::TagSection(tags) => {
                validator.tag_section(&tags)?;
                parse_tag_section(tags, environ)?;
            }

            Payload::GlobalSection(globals) => {
                validator.global_section(&globals)?;
                parse_global_section(globals, environ)?;
            }

            Payload::ExportSection(exports) => {
                validator.export_section(&exports)?;
                parse_export_section(exports, environ)?;
            }

            Payload::StartSection { func, range } => {
                validator.start_section(func, &range)?;
                parse_start_section(func, environ)?;
            }

            Payload::ElementSection(elements) => {
                validator.element_section(&elements)?;
                parse_element_section(elements, environ)?;
            }

            Payload::CodeSectionStart { count, range, .. } => {
                validator.code_section_start(count, &range)?;
                environ.reserve_function_bodies(count, range.start as u64);
            }

            Payload::CodeSectionEntry(body) => {
                let func_validator = validator
                    .code_section_entry(&body)?
                    .into_validator(Default::default());
                environ.define_function_body(func_validator, body)?;
            }

            Payload::DataSection(data) => {
                validator.data_section(&data)?;
                parse_data_section(data, environ)?;
            }

            Payload::DataCountSection { count, range } => {
                validator.data_count_section(count, &range)?;

                // NOTE: the count here is the total segment count, not the passive segment count
                environ.reserve_passive_data(count)?;
            }

            Payload::CustomSection(s) if s.name() == "name" => {
                let result = NameSectionReader::new(s.data(), s.data_offset())
                    .map_err(|e| e.into())
                    .and_then(|s| parse_name_section(s, environ));
                if let Err(e) = result {
                    log::warn!("failed to parse name section {:?}", e);
                }
            }

            Payload::CustomSection(s) => environ.custom_section(s.name(), s.data())?,

            other => {
                validator.payload(&other)?;
                panic!("unimplemented section {:?}", other);
            }
        }
    }

    Ok(())
}

Implementors§