cranelift_wasm/
module_translator.rs

1//! Translation skeleton that traverses the whole WebAssembly module and call helper functions
2//! to deal with each part of it.
3use crate::environ::ModuleEnvironment;
4use crate::sections_translator::{
5    parse_data_section, parse_element_section, parse_export_section, parse_function_section,
6    parse_global_section, parse_import_section, parse_memory_section, parse_start_section,
7    parse_table_section, parse_tag_section, parse_type_section,
8};
9use crate::WasmResult;
10use cranelift_codegen::timing;
11use std::prelude::v1::*;
12use wasmparser::{Parser, Payload, Validator};
13
14/// Translate a sequence of bytes forming a valid Wasm binary into a list of valid Cranelift IR
15/// [`Function`](cranelift_codegen::ir::Function).
16pub fn translate_module<'data>(
17    data: &'data [u8],
18    environ: &mut dyn ModuleEnvironment<'data>,
19) -> WasmResult<()> {
20    let _tt = timing::wasm_translate_module();
21    let mut validator = Validator::new_with_features(environ.wasm_features());
22
23    for payload in Parser::new(0).parse_all(data) {
24        match payload? {
25            Payload::Version {
26                num,
27                encoding,
28                range,
29            } => {
30                validator.version(num, encoding, &range)?;
31            }
32            Payload::End(offset) => {
33                validator.end(offset)?;
34            }
35
36            Payload::TypeSection(types) => {
37                validator.type_section(&types)?;
38                parse_type_section(types, environ)?;
39            }
40
41            Payload::ImportSection(imports) => {
42                validator.import_section(&imports)?;
43                parse_import_section(imports, environ)?;
44            }
45
46            Payload::FunctionSection(functions) => {
47                validator.function_section(&functions)?;
48                parse_function_section(functions, environ)?;
49            }
50
51            Payload::TableSection(tables) => {
52                validator.table_section(&tables)?;
53                parse_table_section(tables, environ)?;
54            }
55
56            Payload::MemorySection(memories) => {
57                validator.memory_section(&memories)?;
58                parse_memory_section(memories, environ)?;
59            }
60
61            Payload::TagSection(tags) => {
62                validator.tag_section(&tags)?;
63                parse_tag_section(tags, environ)?;
64            }
65
66            Payload::GlobalSection(globals) => {
67                validator.global_section(&globals)?;
68                parse_global_section(globals, environ)?;
69            }
70
71            Payload::ExportSection(exports) => {
72                validator.export_section(&exports)?;
73                parse_export_section(exports, environ)?;
74            }
75
76            Payload::StartSection { func, range } => {
77                validator.start_section(func, &range)?;
78                parse_start_section(func, environ)?;
79            }
80
81            Payload::ElementSection(elements) => {
82                validator.element_section(&elements)?;
83                parse_element_section(elements, environ)?;
84            }
85
86            Payload::CodeSectionStart { count, range, .. } => {
87                validator.code_section_start(count, &range)?;
88                environ.reserve_function_bodies(count, range.start as u64);
89            }
90
91            Payload::CodeSectionEntry(body) => {
92                let func_validator = validator
93                    .code_section_entry(&body)?
94                    .into_validator(Default::default());
95                environ.define_function_body(func_validator, body)?;
96            }
97
98            Payload::DataSection(data) => {
99                validator.data_section(&data)?;
100                parse_data_section(data, environ)?;
101            }
102
103            Payload::DataCountSection { count, range } => {
104                validator.data_count_section(count, &range)?;
105
106                // NOTE: the count here is the total segment count, not the passive segment count
107                environ.reserve_passive_data(count)?;
108            }
109
110            Payload::CustomSection(s) => environ.custom_section(s.name(), s.data())?,
111
112            other => {
113                validator.payload(&other)?;
114                panic!("unimplemented section {other:?}");
115            }
116        }
117    }
118
119    Ok(())
120}