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 .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 {
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 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 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 {
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
476pub 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
492pub 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}