wasmer_runtime_core_near/
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                    .map
244                    .insert(field.to_string(), export_index);
245            }
246            ParserState::StartSectionEntry(start_index) => {
247                info.write().unwrap().start_func = Some(FuncIndex::new(start_index as usize));
248            }
249            ParserState::BeginFunctionBody { range } => {
250                if let Some(f) = feed_mcg_signatures.take() {
251                    f(mcg)?;
252                }
253                if let Some(f) = feed_mcg_info.take() {
254                    f(
255                        mcg,
256                        namespace_builder.take().unwrap(),
257                        name_builder.take().unwrap(),
258                    )?;
259                }
260                let id = func_count;
261                let fcg = mcg
262                    .next_function(
263                        Arc::clone(&info),
264                        WasmSpan::new(range.start as u32, range.end as u32),
265                    )
266                    .map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
267
268                {
269                    let info_read = info.read().unwrap();
270                    let sig = info_read
271                        .signatures
272                        .get(
273                            *info
274                                .read()
275                                .unwrap()
276                                .func_assoc
277                                .get(FuncIndex::new(
278                                    id as usize + info_read.imported_functions.len(),
279                                ))
280                                .unwrap(),
281                        )
282                        .unwrap();
283                    for ret in sig.returns() {
284                        fcg.feed_return(type_to_wp_type(*ret))
285                            .map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
286                    }
287                    for param in sig.params() {
288                        fcg.feed_param(type_to_wp_type(*param))
289                            .map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
290                    }
291                }
292
293                let info_read = info.read().unwrap();
294                let mut cur_pos = parser.current_position() as u32;
295                let mut state = parser.read();
296                // loop until the function body starts
297                loop {
298                    match state {
299                        ParserState::Error(err) => return Err(err.into()),
300                        ParserState::FunctionBodyLocals { ref locals } => {
301                            for &(count, ty) in locals.iter() {
302                                fcg.feed_local(ty, count as usize, cur_pos)
303                                    .map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
304                            }
305                        }
306                        ParserState::CodeOperator(_) => {
307                            // the body of the function has started
308                            fcg.begin_body(&info_read)
309                                .map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
310                            middlewares
311                                .run(
312                                    Some(fcg),
313                                    Event::Internal(InternalEvent::FunctionBegin(id as u32)),
314                                    &info_read,
315                                    cur_pos,
316                                )
317                                .map_err(LoadError::Codegen)?;
318                            // go to other loop
319                            break;
320                        }
321                        ParserState::EndFunctionBody => break,
322                        _ => unreachable!(),
323                    }
324                    cur_pos = parser.current_position() as u32;
325                    state = parser.read();
326                }
327
328                // loop until the function body ends
329                loop {
330                    match state {
331                        ParserState::Error(err) => return Err(err.into()),
332                        ParserState::CodeOperator(op) => {
333                            middlewares
334                                .run(Some(fcg), Event::Wasm(op), &info_read, cur_pos)
335                                .map_err(LoadError::Codegen)?;
336                        }
337                        ParserState::EndFunctionBody => break,
338                        _ => unreachable!(),
339                    }
340                    cur_pos = parser.current_position() as u32;
341                    state = parser.read();
342                }
343                middlewares
344                    .run(
345                        Some(fcg),
346                        Event::Internal(InternalEvent::FunctionEnd),
347                        &info_read,
348                        cur_pos,
349                    )
350                    .map_err(LoadError::Codegen)?;
351
352                fcg.finalize()
353                    .map_err(|x| LoadError::Codegen(format!("{:?}", x)))?;
354                func_count = func_count.wrapping_add(1);
355            }
356            ParserState::BeginElementSectionEntry {
357                table: ElemSectionEntryTable::Active(table_index_raw),
358                ty: WpType::AnyFunc,
359            } => {
360                let table_index = TableIndex::new(table_index_raw as usize);
361                let mut elements: Option<Vec<FuncIndex>> = None;
362                let mut base: Option<Initializer> = None;
363
364                loop {
365                    let state = parser.read();
366                    match *state {
367                        ParserState::Error(ref err) => return Err(err.into()),
368                        ParserState::InitExpressionOperator(ref op) => {
369                            base = Some(eval_init_expr(op)?)
370                        }
371                        ParserState::ElementSectionEntryBody(ref _elements) => {
372                            elements = Some(
373                                _elements
374                                    .iter()
375                                    .map(|elem_idx| match elem_idx {
376                                        ElementItem::Null => Err(LoadError::Parse(format!("Error at table {}: null entries in tables are not yet supported", table_index_raw))),
377                                        ElementItem::Func(idx) => Ok(FuncIndex::new(*idx as usize)),
378                                    })
379                                    .collect::<Result<Vec<FuncIndex>, LoadError>>()?,
380                            );
381                        }
382                        ParserState::BeginInitExpressionBody
383                        | ParserState::EndInitExpressionBody => {}
384                        ParserState::EndElementSectionEntry => break,
385                        _ => unreachable!(),
386                    }
387                }
388
389                let table_init = TableInitializer {
390                    table_index,
391                    base: base.unwrap(),
392                    elements: elements.unwrap(),
393                };
394
395                info.write().unwrap().elem_initializers.push(table_init);
396            }
397            ParserState::BeginElementSectionEntry {
398                table: ElemSectionEntryTable::Active(table_index),
399                ty,
400            } => {
401                return Err(LoadError::Parse(format!(
402                    "Error at table {}: type \"{:?}\" is not supported in tables yet",
403                    table_index, ty
404                )));
405            }
406            ParserState::BeginActiveDataSectionEntry(memory_index) => {
407                let memory_index = MemoryIndex::new(memory_index as usize);
408                let mut base: Option<Initializer> = None;
409                let mut data: Vec<u8> = vec![];
410
411                loop {
412                    let state = parser.read();
413                    match *state {
414                        ParserState::Error(ref err) => return Err(err.into()),
415                        ParserState::InitExpressionOperator(ref op) => {
416                            base = Some(eval_init_expr(op)?)
417                        }
418                        ParserState::DataSectionEntryBodyChunk(chunk) => {
419                            data.extend_from_slice(chunk);
420                        }
421                        ParserState::BeginInitExpressionBody
422                        | ParserState::EndInitExpressionBody => {}
423                        ParserState::BeginDataSectionEntryBody(_)
424                        | ParserState::EndDataSectionEntryBody => {}
425                        ParserState::EndDataSectionEntry => break,
426                        _ => unreachable!(),
427                    }
428                }
429
430                let data_init = DataInitializer {
431                    memory_index,
432                    base: base.unwrap(),
433                    data,
434                };
435                info.write().unwrap().data_initializers.push(data_init);
436            }
437            ParserState::BeginGlobalSectionEntry(ty) => {
438                let init = loop {
439                    let state = parser.read();
440                    match *state {
441                        ParserState::Error(ref err) => return Err(err.into()),
442                        ParserState::InitExpressionOperator(ref op) => {
443                            break eval_init_expr(op)?;
444                        }
445                        ParserState::BeginInitExpressionBody => {}
446                        _ => unreachable!(),
447                    }
448                };
449                let desc = GlobalDescriptor {
450                    mutable: ty.mutable,
451                    ty: wp_type_to_type(ty.content_type)?,
452                };
453
454                let global_init = GlobalInit { desc, init };
455
456                info.write().unwrap().globals.push(global_init);
457            }
458            ParserState::EndWasm => {
459                if let Some(f) = feed_mcg_signatures.take() {
460                    f(mcg)?;
461                }
462                if let Some(f) = feed_mcg_info.take() {
463                    f(
464                        mcg,
465                        namespace_builder.take().unwrap(),
466                        name_builder.take().unwrap(),
467                    )?;
468                }
469                break;
470            }
471            _ => {}
472        }
473    }
474    Ok(info)
475}
476
477/// Convert given `WpType` to `Type`.
478pub fn wp_type_to_type(ty: WpType) -> Result<Type, LoadError> {
479    match ty {
480        WpType::I32 => Ok(Type::I32),
481        WpType::I64 => Ok(Type::I64),
482        WpType::F32 => Ok(Type::F32),
483        WpType::F64 => Ok(Type::F64),
484        WpType::V128 => Ok(Type::V128),
485        _ => {
486            return Err(LoadError::Parse(
487                "broken invariant, invalid type".to_string(),
488            ));
489        }
490    }
491}
492
493/// Convert given `Type` to `WpType`.
494pub fn type_to_wp_type(ty: Type) -> WpType {
495    match ty {
496        Type::I32 => WpType::I32,
497        Type::I64 => WpType::I64,
498        Type::F32 => WpType::F32,
499        Type::F64 => WpType::F64,
500        Type::V128 => WpType::V128,
501    }
502}
503
504fn func_type_to_func_sig(func_ty: &FuncType) -> Result<FuncSig, LoadError> {
505    assert_eq!(func_ty.form, WpType::Func);
506
507    Ok(FuncSig::new(
508        func_ty
509            .params
510            .iter()
511            .cloned()
512            .map(wp_type_to_type)
513            .collect::<Result<Vec<_>, _>>()?,
514        func_ty
515            .returns
516            .iter()
517            .cloned()
518            .map(wp_type_to_type)
519            .collect::<Result<Vec<_>, _>>()?,
520    ))
521}
522
523fn eval_init_expr(op: &Operator) -> Result<Initializer, LoadError> {
524    Ok(match *op {
525        Operator::GlobalGet { global_index } => {
526            Initializer::GetGlobal(ImportedGlobalIndex::new(global_index as usize))
527        }
528        Operator::I32Const { value } => Initializer::Const(Value::I32(value)),
529        Operator::I64Const { value } => Initializer::Const(Value::I64(value)),
530        Operator::F32Const { value } => {
531            Initializer::Const(Value::F32(f32::from_bits(value.bits())))
532        }
533        Operator::F64Const { value } => {
534            Initializer::Const(Value::F64(f64::from_bits(value.bits())))
535        }
536        Operator::V128Const { value } => {
537            Initializer::Const(Value::V128(u128::from_le_bytes(*value.bytes())))
538        }
539        _ => {
540            return Err(LoadError::Parse(
541                "init expr evaluation failed: unsupported opcode".to_string(),
542            ));
543        }
544    })
545}