1use 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#[derive(Debug)]
30pub enum LoadError {
31 Parse(String),
33 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
57pub 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 {
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 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 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 {
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
477pub 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
493pub 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}