wasmer_runtime_core_fl/
parse.rs

1//! The parse module contains common data structures and functions using to parse wasm files into
2//! runtime data structures.
3
4use crate::codegen::*;
5use crate::{
6    backend::{CompilerConfig, RunnableModule},
7    error::CompileError,
8    module::{
9        DataInitializer, ExportIndex, ImportName, ModuleInfo, NameIndex, NamespaceIndex,
10        StringTable, StringTableBuilder, TableInitializer,
11    },
12    structures::{Map, TypedIndex},
13    types::{
14        ElementType, FuncIndex, FuncSig, GlobalDescriptor, GlobalIndex, GlobalInit,
15        ImportedGlobalIndex, Initializer, MemoryDescriptor, MemoryIndex, SigIndex, TableDescriptor,
16        TableIndex, Type, Value,
17    },
18    units::Pages,
19};
20use std::collections::HashMap;
21use std::fmt::Debug;
22use std::sync::{Arc, RwLock};
23use wasmparser::{
24    BinaryReaderError, ElemSectionEntryTable, ElementItem, ExternalKind, FuncType,
25    ImportSectionEntryType, Operator, Type as WpType, WasmDecoder,
26};
27
28/// Kind of load error.
29#[derive(Debug)]
30pub enum LoadError {
31    /// Parse error.
32    Parse(String),
33    /// Code generation error.
34    Codegen(String),
35}
36
37impl From<LoadError> for CompileError {
38    fn from(other: LoadError) -> CompileError {
39        CompileError::InternalError {
40            msg: format!("{:?}", other),
41        }
42    }
43}
44
45impl From<BinaryReaderError> for LoadError {
46    fn from(other: BinaryReaderError) -> LoadError {
47        LoadError::Parse(format!("{:?}", other))
48    }
49}
50
51impl From<&BinaryReaderError> for LoadError {
52    fn from(other: &BinaryReaderError) -> LoadError {
53        LoadError::Parse(format!("{:?}", other))
54    }
55}
56
57/// Read wasm binary into module data using the given backend, module code generator, middlewares,
58/// and compiler configuration.
59pub fn read_module<
60    MCG: ModuleCodeGenerator<FCG, RM, E>,
61    FCG: FunctionCodeGenerator<E>,
62    RM: RunnableModule,
63    E: Debug,
64>(
65    wasm: &[u8],
66    mcg: &mut MCG,
67    middlewares: &mut MiddlewareChain,
68    compiler_config: &CompilerConfig,
69) -> Result<Arc<RwLock<ModuleInfo>>, LoadError> {
70    mcg.feed_compiler_config(compiler_config)
71        .map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
72    let info = Arc::new(RwLock::new(ModuleInfo {
73        memories: Map::new(),
74        globals: Map::new(),
75        tables: Map::new(),
76
77        imported_functions: Map::new(),
78        imported_memories: Map::new(),
79        imported_tables: Map::new(),
80        imported_globals: Map::new(),
81
82        exports: Default::default(),
83
84        data_initializers: Vec::new(),
85        elem_initializers: Vec::new(),
86
87        start_func: None,
88
89        func_assoc: Map::new(),
90        signatures: Map::new(),
91        backend: MCG::backend_id().to_string(),
92
93        namespace_table: StringTable::new(),
94        name_table: StringTable::new(),
95
96        em_symbol_map: compiler_config.symbol_map.clone(),
97
98        custom_sections: HashMap::new(),
99
100        generate_debug_info: compiler_config.should_generate_debug_info(),
101        #[cfg(feature = "generate-debug-information")]
102        debug_info_manager: crate::jit_debug::JitCodeDebugInfoManager::new(),
103    }));
104
105    let mut parser = wasmparser::ValidatingParser::new(
106        wasm,
107        Some(validating_parser_config(&compiler_config.features)),
108    );
109
110    let mut namespace_builder = Some(StringTableBuilder::new());
111    let mut name_builder = Some(StringTableBuilder::new());
112    let mut func_count: usize = 0;
113
114    let mut feed_mcg_signatures: Option<_> = Some(|mcg: &mut MCG| -> Result<(), LoadError> {
115        let info_read = info.read().unwrap();
116        mcg.feed_signatures(info_read.signatures.clone())
117            .map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
118        Ok(())
119    });
120    let mut feed_mcg_info: Option<_> = Some(
121        |mcg: &mut MCG,
122         ns_builder: StringTableBuilder<NamespaceIndex>,
123         name_builder: StringTableBuilder<NameIndex>|
124         -> Result<(), LoadError> {
125            {
126                let mut info_write = info.write().unwrap();
127                info_write.namespace_table = ns_builder.finish();
128                info_write.name_table = name_builder.finish();
129            }
130            let info_read = info.read().unwrap();
131            mcg.feed_function_signatures(info_read.func_assoc.clone())
132                .map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
133            mcg.check_precondition(&info_read)
134                .map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
135            Ok(())
136        },
137    );
138
139    loop {
140        use wasmparser::ParserState;
141        let state = parser.read();
142
143        match *state {
144            ParserState::Error(ref err) => return Err(err.clone().into()),
145            ParserState::TypeSectionEntry(ref ty) => {
146                info.write()
147                    .unwrap()
148                    .signatures
149                    .push(func_type_to_func_sig(ty)?);
150            }
151            ParserState::ImportSectionEntry { module, field, ty } => {
152                if let Some(f) = feed_mcg_signatures.take() {
153                    f(mcg)?;
154                }
155
156                let namespace_index = namespace_builder.as_mut().unwrap().register(module);
157                let name_index = name_builder.as_mut().unwrap().register(field);
158                let import_name = ImportName {
159                    namespace_index,
160                    name_index,
161                };
162
163                match ty {
164                    ImportSectionEntryType::Function(sigindex) => {
165                        let sigindex = SigIndex::new(sigindex as usize);
166                        info.write().unwrap().imported_functions.push(import_name);
167                        info.write().unwrap().func_assoc.push(sigindex);
168                        mcg.feed_import_function(sigindex)
169                            .map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
170                    }
171                    ImportSectionEntryType::Table(table_ty) => {
172                        assert_eq!(table_ty.element_type, WpType::AnyFunc);
173                        let table_desc = TableDescriptor {
174                            element: ElementType::Anyfunc,
175                            minimum: table_ty.limits.initial,
176                            maximum: table_ty.limits.maximum,
177                        };
178
179                        info.write()
180                            .unwrap()
181                            .imported_tables
182                            .push((import_name, table_desc));
183                    }
184                    ImportSectionEntryType::Memory(memory_ty) => {
185                        let mem_desc = MemoryDescriptor::new(
186                            Pages(memory_ty.limits.initial),
187                            memory_ty.limits.maximum.map(Pages),
188                            memory_ty.shared,
189                        )
190                        .map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
191
192                        info.write()
193                            .unwrap()
194                            .imported_memories
195                            .push((import_name, mem_desc));
196                    }
197                    ImportSectionEntryType::Global(global_ty) => {
198                        let global_desc = GlobalDescriptor {
199                            mutable: global_ty.mutable,
200                            ty: wp_type_to_type(global_ty.content_type)?,
201                        };
202                        info.write()
203                            .unwrap()
204                            .imported_globals
205                            .push((import_name, global_desc));
206                    }
207                }
208            }
209            ParserState::FunctionSectionEntry(sigindex) => {
210                let sigindex = SigIndex::new(sigindex as usize);
211                info.write().unwrap().func_assoc.push(sigindex);
212            }
213            ParserState::TableSectionEntry(table_ty) => {
214                let table_desc = TableDescriptor {
215                    element: ElementType::Anyfunc,
216                    minimum: table_ty.limits.initial,
217                    maximum: table_ty.limits.maximum,
218                };
219
220                info.write().unwrap().tables.push(table_desc);
221            }
222            ParserState::MemorySectionEntry(memory_ty) => {
223                let mem_desc = MemoryDescriptor::new(
224                    Pages(memory_ty.limits.initial),
225                    memory_ty.limits.maximum.map(Pages),
226                    memory_ty.shared,
227                )
228                .map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
229
230                info.write().unwrap().memories.push(mem_desc);
231            }
232            ParserState::ExportSectionEntry { field, kind, index } => {
233                let export_index = match kind {
234                    ExternalKind::Function => ExportIndex::Func(FuncIndex::new(index as usize)),
235                    ExternalKind::Table => ExportIndex::Table(TableIndex::new(index as usize)),
236                    ExternalKind::Memory => ExportIndex::Memory(MemoryIndex::new(index as usize)),
237                    ExternalKind::Global => ExportIndex::Global(GlobalIndex::new(index as usize)),
238                };
239
240                info.write()
241                    .unwrap()
242                    .exports
243                    .insert(field.to_string(), export_index);
244            }
245            ParserState::StartSectionEntry(start_index) => {
246                info.write().unwrap().start_func = Some(FuncIndex::new(start_index as usize));
247            }
248            ParserState::BeginFunctionBody { range } => {
249                if let Some(f) = feed_mcg_signatures.take() {
250                    f(mcg)?;
251                }
252                if let Some(f) = feed_mcg_info.take() {
253                    f(
254                        mcg,
255                        namespace_builder.take().unwrap(),
256                        name_builder.take().unwrap(),
257                    )?;
258                }
259                let id = func_count;
260                let fcg = mcg
261                    .next_function(
262                        Arc::clone(&info),
263                        WasmSpan::new(range.start as u32, range.end as u32),
264                    )
265                    .map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
266
267                {
268                    let info_read = info.read().unwrap();
269                    let sig = info_read
270                        .signatures
271                        .get(
272                            *info
273                                .read()
274                                .unwrap()
275                                .func_assoc
276                                .get(FuncIndex::new(
277                                    id as usize + info_read.imported_functions.len(),
278                                ))
279                                .unwrap(),
280                        )
281                        .unwrap();
282                    for ret in sig.returns() {
283                        fcg.feed_return(type_to_wp_type(*ret))
284                            .map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
285                    }
286                    for param in sig.params() {
287                        fcg.feed_param(type_to_wp_type(*param))
288                            .map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
289                    }
290                }
291
292                let info_read = info.read().unwrap();
293                let mut cur_pos = parser.current_position() as u32;
294                let mut state = parser.read();
295                // loop until the function body starts
296                loop {
297                    match state {
298                        ParserState::Error(err) => return Err(err.into()),
299                        ParserState::FunctionBodyLocals { ref locals } => {
300                            for &(count, ty) in locals.iter() {
301                                fcg.feed_local(ty, count as usize, cur_pos)
302                                    .map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
303                            }
304                        }
305                        ParserState::CodeOperator(_) => {
306                            // the body of the function has started
307                            fcg.begin_body(&info_read)
308                                .map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
309                            middlewares
310                                .run(
311                                    Some(fcg),
312                                    Event::Internal(InternalEvent::FunctionBegin(id as u32)),
313                                    &info_read,
314                                    cur_pos,
315                                )
316                                .map_err(LoadError::Codegen)?;
317                            // go to other loop
318                            break;
319                        }
320                        ParserState::EndFunctionBody => break,
321                        _ => unreachable!(),
322                    }
323                    cur_pos = parser.current_position() as u32;
324                    state = parser.read();
325                }
326
327                // loop until the function body ends
328                loop {
329                    match state {
330                        ParserState::Error(err) => return Err(err.into()),
331                        ParserState::CodeOperator(op) => {
332                            middlewares
333                                .run(Some(fcg), Event::Wasm(op), &info_read, cur_pos)
334                                .map_err(LoadError::Codegen)?;
335                        }
336                        ParserState::EndFunctionBody => break,
337                        _ => unreachable!(),
338                    }
339                    cur_pos = parser.current_position() as u32;
340                    state = parser.read();
341                }
342                middlewares
343                    .run(
344                        Some(fcg),
345                        Event::Internal(InternalEvent::FunctionEnd),
346                        &info_read,
347                        cur_pos,
348                    )
349                    .map_err(LoadError::Codegen)?;
350
351                fcg.finalize()
352                    .map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
353                func_count = func_count.wrapping_add(1);
354            }
355            ParserState::BeginElementSectionEntry {
356                table: ElemSectionEntryTable::Active(table_index_raw),
357                ty: WpType::AnyFunc,
358            } => {
359                let table_index = TableIndex::new(table_index_raw as usize);
360                let mut elements: Option<Vec<FuncIndex>> = None;
361                let mut base: Option<Initializer> = None;
362
363                loop {
364                    let state = parser.read();
365                    match *state {
366                        ParserState::Error(ref err) => return Err(err.into()),
367                        ParserState::InitExpressionOperator(ref op) => {
368                            base = Some(eval_init_expr(op)?)
369                        }
370                        ParserState::ElementSectionEntryBody(ref _elements) => {
371                            elements = Some(
372                                _elements
373                                    .iter()
374                                    .map(|elem_idx| match elem_idx {
375                                        ElementItem::Null => Err(LoadError::Parse(format!("Error at table {}: null entries in tables are not yet supported", table_index_raw))),
376                                        ElementItem::Func(idx) => Ok(FuncIndex::new(*idx as usize)),
377                                    })
378                                    .collect::<Result<Vec<FuncIndex>, LoadError>>()?,
379                            );
380                        }
381                        ParserState::BeginInitExpressionBody
382                        | ParserState::EndInitExpressionBody => {}
383                        ParserState::EndElementSectionEntry => break,
384                        _ => unreachable!(),
385                    }
386                }
387
388                let table_init = TableInitializer {
389                    table_index,
390                    base: base.unwrap(),
391                    elements: elements.unwrap(),
392                };
393
394                info.write().unwrap().elem_initializers.push(table_init);
395            }
396            ParserState::BeginElementSectionEntry {
397                table: ElemSectionEntryTable::Active(table_index),
398                ty,
399            } => {
400                return Err(LoadError::Parse(format!(
401                    "Error at table {}: type \"{:?}\" is not supported in tables yet",
402                    table_index, ty
403                )));
404            }
405            ParserState::BeginActiveDataSectionEntry(memory_index) => {
406                let memory_index = MemoryIndex::new(memory_index as usize);
407                let mut base: Option<Initializer> = None;
408                let mut data: Vec<u8> = vec![];
409
410                loop {
411                    let state = parser.read();
412                    match *state {
413                        ParserState::Error(ref err) => return Err(err.into()),
414                        ParserState::InitExpressionOperator(ref op) => {
415                            base = Some(eval_init_expr(op)?)
416                        }
417                        ParserState::DataSectionEntryBodyChunk(chunk) => {
418                            data.extend_from_slice(chunk);
419                        }
420                        ParserState::BeginInitExpressionBody
421                        | ParserState::EndInitExpressionBody => {}
422                        ParserState::BeginDataSectionEntryBody(_)
423                        | ParserState::EndDataSectionEntryBody => {}
424                        ParserState::EndDataSectionEntry => break,
425                        _ => unreachable!(),
426                    }
427                }
428
429                let data_init = DataInitializer {
430                    memory_index,
431                    base: base.unwrap(),
432                    data,
433                };
434                info.write().unwrap().data_initializers.push(data_init);
435            }
436            ParserState::BeginGlobalSectionEntry(ty) => {
437                let init = loop {
438                    let state = parser.read();
439                    match *state {
440                        ParserState::Error(ref err) => return Err(err.into()),
441                        ParserState::InitExpressionOperator(ref op) => {
442                            break eval_init_expr(op)?;
443                        }
444                        ParserState::BeginInitExpressionBody => {}
445                        _ => unreachable!(),
446                    }
447                };
448                let desc = GlobalDescriptor {
449                    mutable: ty.mutable,
450                    ty: wp_type_to_type(ty.content_type)?,
451                };
452
453                let global_init = GlobalInit { desc, init };
454
455                info.write().unwrap().globals.push(global_init);
456            }
457            ParserState::EndWasm => {
458                if let Some(f) = feed_mcg_signatures.take() {
459                    f(mcg)?;
460                }
461                if let Some(f) = feed_mcg_info.take() {
462                    f(
463                        mcg,
464                        namespace_builder.take().unwrap(),
465                        name_builder.take().unwrap(),
466                    )?;
467                }
468                break;
469            }
470            _ => {}
471        }
472    }
473    Ok(info)
474}
475
476/// Convert given `WpType` to `Type`.
477pub fn wp_type_to_type(ty: WpType) -> Result<Type, LoadError> {
478    match ty {
479        WpType::I32 => Ok(Type::I32),
480        WpType::I64 => Ok(Type::I64),
481        WpType::F32 => Ok(Type::F32),
482        WpType::F64 => Ok(Type::F64),
483        WpType::V128 => Ok(Type::V128),
484        _ => {
485            return Err(LoadError::Parse(
486                "broken invariant, invalid type".to_string(),
487            ));
488        }
489    }
490}
491
492/// Convert given `Type` to `WpType`.
493pub fn type_to_wp_type(ty: Type) -> WpType {
494    match ty {
495        Type::I32 => WpType::I32,
496        Type::I64 => WpType::I64,
497        Type::F32 => WpType::F32,
498        Type::F64 => WpType::F64,
499        Type::V128 => WpType::V128,
500    }
501}
502
503fn func_type_to_func_sig(func_ty: &FuncType) -> Result<FuncSig, LoadError> {
504    assert_eq!(func_ty.form, WpType::Func);
505
506    Ok(FuncSig::new(
507        func_ty
508            .params
509            .iter()
510            .cloned()
511            .map(wp_type_to_type)
512            .collect::<Result<Vec<_>, _>>()?,
513        func_ty
514            .returns
515            .iter()
516            .cloned()
517            .map(wp_type_to_type)
518            .collect::<Result<Vec<_>, _>>()?,
519    ))
520}
521
522fn eval_init_expr(op: &Operator) -> Result<Initializer, LoadError> {
523    Ok(match *op {
524        Operator::GlobalGet { global_index } => {
525            Initializer::GetGlobal(ImportedGlobalIndex::new(global_index as usize))
526        }
527        Operator::I32Const { value } => Initializer::Const(Value::I32(value)),
528        Operator::I64Const { value } => Initializer::Const(Value::I64(value)),
529        Operator::F32Const { value } => {
530            Initializer::Const(Value::F32(f32::from_bits(value.bits())))
531        }
532        Operator::F64Const { value } => {
533            Initializer::Const(Value::F64(f64::from_bits(value.bits())))
534        }
535        Operator::V128Const { value } => {
536            Initializer::Const(Value::V128(u128::from_le_bytes(*value.bytes())))
537        }
538        _ => {
539            return Err(LoadError::Parse(
540                "init expr evaluation failed: unsupported opcode".to_string(),
541            ));
542        }
543    })
544}