1#![doc = include_str!("readme.md")]
2
3use crate::{
4 formats::wasm::WasmReadConfig,
5 program::{WasiProgram, WasmInfo},
6};
7use gaia_binary::{BinaryReader, Fixed, LittleEndian};
8use gaia_types::{GaiaDiagnostics, GaiaError};
9use std::{
10 cell::{OnceCell, RefCell},
11 io::{Read, Seek},
12};
13
14pub fn read_u32_leb128<R: Read + Seek, F: gaia_binary::BinaryFormat>(reader: &mut BinaryReader<R, F>) -> std::io::Result<u32> {
16 let mut result = 0u32;
17 let mut shift = 0;
18 loop {
19 let b = reader.read_u8().map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e.to_string()))?;
20 result |= ((b & 0x7F) as u32) << shift;
21 if b & 0x80 == 0 {
22 break;
23 }
24 shift += 7;
25 if shift >= 32 {
26 return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "LEB128 value too large for u32"));
27 }
28 }
29 Ok(result)
30}
31
32fn read_i32_leb128<R: Read + Seek, F: gaia_binary::BinaryFormat>(reader: &mut BinaryReader<R, F>) -> std::io::Result<i32> {
33 let mut result = 0i32;
34 let mut shift = 0;
35 let mut byte;
36 loop {
37 byte = reader.read_u8().map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e.to_string()))?;
38 result |= ((byte & 0x7F) as i32) << shift;
39 shift += 7;
40 if byte & 0x80 == 0 {
41 break;
42 }
43 }
44 if shift < 32 && (byte & 0x40) != 0 {
45 result |= !0 << shift;
46 }
47 Ok(result)
48}
49
50fn read_i64_leb128<R: Read + Seek, F: gaia_binary::BinaryFormat>(reader: &mut BinaryReader<R, F>) -> std::io::Result<i64> {
51 let mut result = 0i64;
52 let mut shift = 0;
53 let mut byte;
54 loop {
55 byte = reader.read_u8().map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e.to_string()))?;
56 result |= ((byte & 0x7F) as i64) << shift;
57 shift += 7;
58 if byte & 0x80 == 0 {
59 break;
60 }
61 }
62 if shift < 64 && (byte & 0x40) != 0 {
63 result |= !0 << shift;
64 }
65 Ok(result)
66}
67
68pub struct WasmReader<'config, R: Read + Seek> {
70 config: &'config WasmReadConfig,
71 reader: RefCell<BinaryReader<R, Fixed<LittleEndian>>>,
72 program: OnceCell<WasiProgram>,
73 view: OnceCell<WasmInfo>,
74}
75
76impl WasmReadConfig {
77 pub fn as_reader<R: Read + Seek>(&self, reader: R) -> WasmReader<'_, R> {
78 WasmReader::new(reader, self)
79 }
80}
81
82impl<'config, R: Read + Seek> WasmReader<'config, R> {
83 pub fn new(reader: R, config: &'config WasmReadConfig) -> Self {
84 Self {
85 reader: RefCell::new(BinaryReader::<R, Fixed<LittleEndian>>::new(reader)),
86 view: Default::default(),
87 program: Default::default(),
88 config: config,
89 }
90 }
91 pub fn finish(mut self) -> GaiaDiagnostics<WasiProgram>
92 where
93 R: Read + Seek,
94 {
95 match self.get_program() {
96 Ok(_) => {
97 let errors = self.reader.borrow_mut().take_errors();
98 GaiaDiagnostics {
99 result: self.program.take().ok_or(GaiaError::custom_error("unreachable")),
100 diagnostics: errors,
101 }
102 }
103 Err(e) => {
104 let errors = self.reader.borrow_mut().take_errors();
105 GaiaDiagnostics { result: Err(e), diagnostics: errors }
106 }
107 }
108 }
109}
110
111impl<'config, R: Read + Seek> WasmReader<'config, R> {
112 pub fn get_program(&self) -> Result<&WasiProgram, GaiaError> {
113 self.program.get_or_try_init(|| self.read_program())
114 }
115 fn read_program(&self) -> Result<WasiProgram, GaiaError> {
116 let mut reader = self.reader.borrow_mut();
117
118 reader.seek(std::io::SeekFrom::Start(0)).map_err(|e| GaiaError::custom_error(format!("I/O error: {:?}", e)))?;
120
121 self.validate_wasm_header(&mut reader)?;
123
124 let mut program = crate::program::WasiProgram::new_core_module();
126
127 self.parse_sections(&mut reader, &mut program)?;
129
130 Ok(program)
131 }
132
133 fn validate_wasm_header(&self, reader: &mut BinaryReader<R, Fixed<LittleEndian>>) -> Result<(), GaiaError> {
134 let magic = reader.read_u32().map_err(|e| GaiaError::custom_error(format!("I/O error: {:?}", e)))?;
136 if magic != 0x6D736100 {
137 return Err(GaiaError::invalid_data("Invalid WASM file magic number"));
139 }
140
141 let version = reader.read_u32().map_err(|e| GaiaError::custom_error(format!("I/O error: {:?}", e)))?;
142 if version != 1 {
143 return Err(GaiaError::invalid_data(&format!("Unsupported WASM version: {}", version)));
144 }
145
146 Ok(())
147 }
148
149 fn parse_sections(
150 &self,
151 reader: &mut BinaryReader<R, Fixed<LittleEndian>>,
152 program: &mut crate::program::WasiProgram,
153 ) -> Result<(), GaiaError> {
154 while let Ok(section_id) = reader.read_u8() {
155 let section_size = read_u32_leb128(reader).map_err(|e| GaiaError::custom_error(format!("I/O error: {:?}", e)))?;
156
157 match section_id {
158 0 => self.read_custom_section(reader, program, section_size)?,
159 1 => self.read_type_section(reader, program)?,
160 2 => self.read_import_section(reader, program)?,
161 3 => self.read_function_section(reader, program)?,
162 4 => self.read_table_section(reader, program)?,
163 5 => self.read_memory_section(reader, program)?,
164 6 => self.read_global_section(reader, program)?,
165 7 => self.read_export_section(reader, program)?,
166 8 => self.read_start_section(reader, program)?,
167 9 => self.skip_section(reader, section_size)?, 10 => self.read_code_section(reader, program)?,
169 11 => self.skip_section(reader, section_size)?, _ => self.skip_section(reader, section_size)?, }
172 }
173 Ok(())
174 }
175
176 fn read_custom_section(
177 &self,
178 reader: &mut BinaryReader<R, Fixed<LittleEndian>>,
179 program: &mut crate::program::WasiProgram,
180 section_size: u32,
181 ) -> Result<(), GaiaError> {
182 let name_len = read_u32_leb128(reader)?;
183 let mut name_bytes = vec![0u8; name_len as usize];
184 reader.read_exact(&mut name_bytes)?;
185 let name = String::from_utf8_lossy(&name_bytes).to_string();
186
187 let mut len = name_len;
189 let mut temp = name_len;
190 while temp > 0 {
191 len += 1;
192 temp >>= 7;
193 }
194 let data_len = section_size - len;
195 let mut data = vec![0u8; data_len as usize];
196 reader.read_exact(&mut data)?;
197
198 program.custom_sections.push(crate::program::WasiCustomSection { name, data });
199 Ok(())
200 }
201
202 fn read_start_section(
203 &self,
204 reader: &mut BinaryReader<R, Fixed<LittleEndian>>,
205 program: &mut crate::program::WasiProgram,
206 ) -> Result<(), GaiaError> {
207 let start_func = read_u32_leb128(reader)?;
208 program.start_function = Some(start_func);
209 Ok(())
210 }
211
212 pub fn get_view(&self) -> Result<&WasmInfo, GaiaError> {
213 self.view.get_or_try_init(|| self.read_view())
214 }
215
216 fn read_view(&self) -> Result<WasmInfo, GaiaError> {
217 let mut reader = self.reader.borrow_mut();
218
219 reader.seek(std::io::SeekFrom::Start(0))?;
221
222 let magic = reader.read_u32()?;
224 if magic != 0x6D736100 {
225 return Err(GaiaError::invalid_data("Invalid WASM file magic number"));
227 }
228
229 let _version = reader.read_u32()?;
230
231 Ok(WasmInfo {
232 magic_head: [0x00, 0x61, 0x73, 0x6D], })
234 }
235
236 fn skip_section(&self, reader: &mut BinaryReader<R, Fixed<LittleEndian>>, size: u32) -> Result<(), GaiaError> {
238 let mut buffer = vec![0u8; size as usize];
239 reader.read_exact(&mut buffer)?;
240 Ok(())
241 }
242
243 fn read_type_section(
244 &self,
245 reader: &mut BinaryReader<R, Fixed<LittleEndian>>,
246 program: &mut crate::program::WasiProgram,
247 ) -> Result<(), GaiaError> {
248 let count = read_u32_leb128(reader)?;
249
250 for _ in 0..count {
251 let form = reader.read_u8()?;
252 if form != 0x60 {
253 return Err(GaiaError::invalid_data("Unsupported type form"));
255 }
256
257 let param_count = read_u32_leb128(reader)?;
258 let mut params = Vec::new();
259 for _ in 0..param_count {
260 let param_type = self.read_value_type(reader)?;
261 params.push(param_type);
262 }
263
264 let result_count = read_u32_leb128(reader)?;
265 let mut results = Vec::new();
266 for _ in 0..result_count {
267 let result_type = self.read_value_type(reader)?;
268 results.push(result_type);
269 }
270
271 program.function_types.push(crate::program::WasiFunctionType { params, results });
272 }
273
274 Ok(())
275 }
276
277 fn read_type(&self, reader: &mut BinaryReader<R, Fixed<LittleEndian>>) -> Result<crate::program::WasiType, GaiaError> {
278 let tag = reader.read_u8()?;
279 match tag {
280 0x7F | 0x7E | 0x7D | 0x7C | 0x7B | 0x7A | 0x79 | 0x78 | 0x77 | 0x76 | 0x75 | 0x74 | 0x73 => {
281 let prim = match tag {
282 0x7F => crate::program::WasiPrimitiveType::Bool,
283 0x7E => crate::program::WasiPrimitiveType::S8,
284 0x7D => crate::program::WasiPrimitiveType::U8,
285 0x7C => crate::program::WasiPrimitiveType::S16,
286 0x7B => crate::program::WasiPrimitiveType::U16,
287 0x7A => crate::program::WasiPrimitiveType::S32,
288 0x79 => crate::program::WasiPrimitiveType::U32,
289 0x78 => crate::program::WasiPrimitiveType::S64,
290 0x77 => crate::program::WasiPrimitiveType::U64,
291 0x76 => crate::program::WasiPrimitiveType::F32,
292 0x75 => crate::program::WasiPrimitiveType::F64,
293 0x74 => crate::program::WasiPrimitiveType::Char,
294 0x73 => crate::program::WasiPrimitiveType::String,
295 _ => unreachable!(),
296 };
297 Ok(crate::program::WasiType::Primitive(prim))
298 }
299 0x72 => {
300 let count = read_u32_leb128(reader)?;
302 let mut fields = Vec::new();
303 for _ in 0..count {
304 let name_len = read_u32_leb128(reader)?;
305 let mut name_bytes = vec![0u8; name_len as usize];
306 reader.read_exact(&mut name_bytes)?;
307 let name = String::from_utf8_lossy(&name_bytes).to_string();
308 let field_type = self.read_type(reader)?;
309 fields.push(crate::program::WasiRecordField { name, field_type });
310 }
311 Ok(crate::program::WasiType::Record(fields))
312 }
313 0x69 => {
314 let has_type = reader.read_u8()?;
316 let inner = if has_type == 0x01 { Some(Box::new(self.read_type(reader)?)) } else { None };
317 Ok(crate::program::WasiType::Future(inner))
318 }
319 0x68 => {
320 let has_type = reader.read_u8()?;
322 let inner = if has_type == 0x01 { Some(Box::new(self.read_type(reader)?)) } else { None };
323 Ok(crate::program::WasiType::Stream(inner))
324 }
325 _ => Err(GaiaError::invalid_data(&format!("Unsupported type tag: 0x{:02X}", tag))),
326 }
327 }
328
329 fn read_canon_options(
330 &self,
331 reader: &mut BinaryReader<R, Fixed<LittleEndian>>,
332 ) -> Result<Vec<crate::program::WasiCanonOption>, GaiaError> {
333 let count = read_u32_leb128(reader)?;
334 let mut options = Vec::new();
335 for _ in 0..count {
336 let tag = reader.read_u8()?;
337 match tag {
338 0x00 => {
339 let enc_tag = reader.read_u8()?;
340 let enc = match enc_tag {
341 0x00 => "utf8",
342 0x01 => "utf16",
343 0x02 => "compact-utf16",
344 _ => "utf8",
345 };
346 options.push(crate::program::WasiCanonOption::StringEncoding(enc.to_string()));
347 }
348 0x01 => {
349 let _mem_index = read_u32_leb128(reader)?;
350 options.push(crate::program::WasiCanonOption::Memory("0".to_string()));
351 }
352 0x02 => {
353 let _realloc_index = read_u32_leb128(reader)?;
354 options.push(crate::program::WasiCanonOption::Realloc("0".to_string()));
355 }
356 0x04 => {
357 options.push(crate::program::WasiCanonOption::Async);
359 }
360 0x05 => {
361 let _callback_index = read_u32_leb128(reader)?;
363 options.push(crate::program::WasiCanonOption::Callback("0".to_string()));
364 }
365 _ => return Err(GaiaError::invalid_data(&format!("Unsupported canon option tag: 0x{:02X}", tag))),
366 }
367 }
368 Ok(options)
369 }
370
371 fn read_value_type(
372 &self,
373 reader: &mut BinaryReader<R, Fixed<LittleEndian>>,
374 ) -> Result<crate::program::WasmValueType, GaiaError> {
375 let type_byte = reader.read_u8()?;
376 crate::program::WasmValueType::try_from(type_byte)
377 }
378
379 fn read_import_section(
380 &self,
381 reader: &mut BinaryReader<R, Fixed<LittleEndian>>,
382 program: &mut crate::program::WasiProgram,
383 ) -> Result<(), GaiaError> {
384 let count = read_u32_leb128(reader)?;
385
386 for _ in 0..count {
387 let module_len = read_u32_leb128(reader)?;
389 let mut module_bytes = vec![0u8; module_len as usize];
390 reader.read_exact(&mut module_bytes)?;
391 let module = String::from_utf8_lossy(&module_bytes).to_string();
392
393 let field_len = read_u32_leb128(reader)?;
395 let mut field_bytes = vec![0u8; field_len as usize];
396 reader.read_exact(&mut field_bytes)?;
397 let field = String::from_utf8_lossy(&field_bytes).to_string();
398
399 let import_type = self.read_import_type(reader)?;
400
401 program.imports.push(crate::program::WasiImport { module, field, import_type });
402 }
403
404 Ok(())
405 }
406
407 fn read_import_type(
408 &self,
409 reader: &mut BinaryReader<R, Fixed<LittleEndian>>,
410 ) -> Result<crate::program::WasmImportType, GaiaError> {
411 let kind = reader.read_u8()?;
412 match kind {
413 0x00 => {
414 let type_index = read_u32_leb128(reader)?;
416 Ok(crate::program::WasmImportType::Function { type_index })
417 }
418 0x01 => {
419 let table_type = self.read_table_type(reader)?;
421 Ok(crate::program::WasmImportType::Table { table_type })
422 }
423 0x02 => {
424 let memory_type = self.read_memory_type(reader)?;
426 Ok(crate::program::WasmImportType::Memory { memory_type })
427 }
428 0x03 => {
429 let global_type = self.read_global_type(reader)?;
431 Ok(crate::program::WasmImportType::Global { global_type })
432 }
433 _ => Err(GaiaError::invalid_data(&format!("Unknown import kind: {}", kind))),
434 }
435 }
436
437 fn read_function_section(
438 &self,
439 reader: &mut BinaryReader<R, Fixed<LittleEndian>>,
440 program: &mut crate::program::WasiProgram,
441 ) -> Result<(), GaiaError> {
442 let count = read_u32_leb128(reader)?;
443
444 for _ in 0..count {
445 let type_index = read_u32_leb128(reader)?;
446 program.functions.push(crate::program::WasiFunction { type_index, locals: Vec::new(), body: Vec::new() });
448 }
449
450 Ok(())
451 }
452
453 fn read_table_section(
454 &self,
455 reader: &mut BinaryReader<R, Fixed<LittleEndian>>,
456 program: &mut crate::program::WasiProgram,
457 ) -> Result<(), GaiaError> {
458 let count = read_u32_leb128(reader)?;
459
460 for _ in 0..count {
461 let table_type = self.read_table_type(reader)?;
462 program.tables.push(crate::program::WasiTable { table_type });
463 }
464
465 Ok(())
466 }
467
468 fn read_table_type(
469 &self,
470 reader: &mut BinaryReader<R, Fixed<LittleEndian>>,
471 ) -> Result<crate::program::WasmTableType, GaiaError> {
472 let element_type = reader.read_u8()?;
473 let element_type = match element_type {
474 0x70 => crate::program::WasmReferenceType::FuncRef,
475 0x6F => crate::program::WasmReferenceType::ExternRef,
476 _ => return Err(GaiaError::invalid_data(&format!("Unknown reference type: 0x{:02X}", element_type))),
477 };
478
479 let limits = self.read_limits(reader)?;
480
481 Ok(crate::program::WasmTableType { element_type, min: limits.0, max: limits.1 })
482 }
483
484 fn read_memory_section(
485 &self,
486 reader: &mut BinaryReader<R, Fixed<LittleEndian>>,
487 program: &mut crate::program::WasiProgram,
488 ) -> Result<(), GaiaError> {
489 let count = read_u32_leb128(reader)?;
490
491 for _ in 0..count {
492 let memory_type = self.read_memory_type(reader)?;
493 program.memories.push(crate::program::WasiMemory { memory_type });
494 }
495
496 Ok(())
497 }
498
499 fn read_memory_type(
500 &self,
501 reader: &mut BinaryReader<R, Fixed<LittleEndian>>,
502 ) -> Result<crate::program::WasmMemoryType, GaiaError> {
503 let limits = self.read_limits(reader)?;
504 Ok(crate::program::WasmMemoryType { min: limits.0, max: limits.1 })
505 }
506
507 fn read_limits(&self, reader: &mut BinaryReader<R, Fixed<LittleEndian>>) -> Result<(u32, Option<u32>), GaiaError> {
508 let flags = reader.read_u8()?;
509 let min = read_u32_leb128(reader)?;
510 let max = if flags & 0x01 != 0 { Some(read_u32_leb128(reader)?) } else { None };
511 Ok((min, max))
512 }
513
514 fn read_global_section(
515 &self,
516 reader: &mut BinaryReader<R, Fixed<LittleEndian>>,
517 program: &mut crate::program::WasiProgram,
518 ) -> Result<(), GaiaError> {
519 let count = read_u32_leb128(reader)?;
520
521 for _ in 0..count {
522 let global_type = self.read_global_type(reader)?;
523 let init_expr = self.read_init_expr(reader)?;
524 program.globals.push(crate::program::WasiGlobal { global_type, init_expr });
525 }
526
527 Ok(())
528 }
529
530 fn read_global_type(
531 &self,
532 reader: &mut BinaryReader<R, Fixed<LittleEndian>>,
533 ) -> Result<crate::program::WasmGlobalType, GaiaError> {
534 let value_type = self.read_value_type(reader)?;
535 let mutability = reader.read_u8()?;
536 let mutable = mutability != 0;
537
538 Ok(crate::program::WasmGlobalType { value_type, mutable })
539 }
540
541 fn read_init_expr(
542 &self,
543 reader: &mut BinaryReader<R, Fixed<LittleEndian>>,
544 ) -> Result<Vec<crate::program::WasiInstruction>, GaiaError> {
545 let mut instructions = Vec::new();
546
547 loop {
548 let opcode = reader.read_u8()?;
549 match opcode {
550 0x41 => {
551 let value = read_i32_leb128(reader)?;
553 instructions.push(crate::program::WasiInstruction::I32Const { value });
554 }
555 0x42 => {
556 let value = read_i64_leb128(reader)?;
558 instructions.push(crate::program::WasiInstruction::I64Const { value });
559 }
560 0x43 => {
561 let value = reader.read_f32()?;
563 instructions.push(crate::program::WasiInstruction::F32Const { value });
564 }
565 0x44 => {
566 let value = reader.read_f64()?;
568 instructions.push(crate::program::WasiInstruction::F64Const { value });
569 }
570 0x0B => {
571 instructions.push(crate::program::WasiInstruction::End);
573 break;
574 }
575 _ => {
576 return Err(GaiaError::invalid_data(&format!("Unsupported opcode in init expression: 0x{:02X}", opcode)));
577 }
578 }
579 }
580
581 Ok(instructions)
582 }
583
584 fn read_export_section(
585 &self,
586 reader: &mut BinaryReader<R, Fixed<LittleEndian>>,
587 program: &mut crate::program::WasiProgram,
588 ) -> Result<(), GaiaError> {
589 let count = read_u32_leb128(reader)?;
590
591 for _ in 0..count {
592 let name_len = read_u32_leb128(reader)?;
594 let mut name_bytes = vec![0u8; name_len as usize];
595 reader.read_exact(&mut name_bytes)?;
596 let name = String::from_utf8_lossy(&name_bytes).to_string();
597
598 let kind = reader.read_u8()?;
600 let index = read_u32_leb128(reader)?;
601
602 let export_type = match kind {
603 0x00 => crate::program::WasmExportType::Function { function_index: index },
604 0x01 => crate::program::WasmExportType::Table { table_index: index },
605 0x02 => crate::program::WasmExportType::Memory { memory_index: index },
606 0x03 => crate::program::WasmExportType::Global { global_index: index },
607 _ => return Err(GaiaError::invalid_data(&format!("Unknown export kind: {}", kind))),
608 };
609
610 program.exports.push(crate::program::WasiExport { name, export_type });
611 }
612
613 Ok(())
614 }
615
616 fn read_code_section(
617 &self,
618 reader: &mut BinaryReader<R, Fixed<LittleEndian>>,
619 program: &mut crate::program::WasiProgram,
620 ) -> Result<(), GaiaError> {
621 let count = read_u32_leb128(reader)?;
622
623 for i in 0..count {
624 let body_size = read_u32_leb128(reader)?;
626 let start_pos = reader.get_position();
627
628 let local_count = read_u32_leb128(reader)?;
630 let mut locals = Vec::new();
631 for _ in 0..local_count {
632 let count = read_u32_leb128(reader)?;
633 let value_type = self.read_value_type(reader)?;
634 locals.push(crate::program::WasmLocal { count, value_type });
635 }
636
637 let remaining_size = body_size - (reader.position() - start_pos) as u32;
640 let mut body_bytes = vec![0u8; remaining_size as usize];
641 reader.read_exact(&mut body_bytes)?;
642
643 program.functions[i as usize].locals = locals;
645
646 let mut body_reader = BinaryReader::new(std::io::Cursor::new(body_bytes));
648 program.functions[i as usize].body = self.read_instructions(&mut body_reader)?;
649 }
650
651 Ok(())
652 }
653
654 fn read_instructions<RR: Read + Seek>(
655 &self,
656 reader: &mut BinaryReader<RR, Fixed<LittleEndian>>,
657 ) -> Result<Vec<crate::program::WasiInstruction>, GaiaError> {
658 let mut instructions = Vec::new();
659 while let Ok(opcode) = reader.read_u8() {
660 match opcode {
661 0x00 => instructions.push(crate::program::WasiInstruction::Unreachable),
662 0x01 => instructions.push(crate::program::WasiInstruction::Nop),
663 0x02 => {
664 let _block_type = reader.read_u8()?; instructions.push(crate::program::WasiInstruction::Block { block_type: None });
666 }
667 0x03 => {
668 let _block_type = reader.read_u8()?; instructions.push(crate::program::WasiInstruction::Loop { block_type: None });
670 }
671 0x04 => {
672 let _block_type = reader.read_u8()?; instructions.push(crate::program::WasiInstruction::If { block_type: None });
674 }
675 0x05 => instructions.push(crate::program::WasiInstruction::Else),
676 0x0B => {
677 instructions.push(crate::program::WasiInstruction::End);
678 }
680 0x0C => {
681 let label_index = read_u32_leb128(reader)?;
682 instructions.push(crate::program::WasiInstruction::Br { label_index });
683 }
684 0x0D => {
685 let label_index = read_u32_leb128(reader)?;
686 instructions.push(crate::program::WasiInstruction::BrIf { label_index });
687 }
688 0x0F => instructions.push(crate::program::WasiInstruction::Return),
689 0x10 => {
690 let function_index = read_u32_leb128(reader)?;
691 instructions.push(crate::program::WasiInstruction::Call { function_index });
692 }
693 0x1A => instructions.push(crate::program::WasiInstruction::Drop),
694 0x1B => instructions.push(crate::program::WasiInstruction::Select),
695 0x20 => {
696 let local_index = read_u32_leb128(reader)?;
697 instructions.push(crate::program::WasiInstruction::LocalGet { local_index });
698 }
699 0x21 => {
700 let local_index = read_u32_leb128(reader)?;
701 instructions.push(crate::program::WasiInstruction::LocalSet { local_index });
702 }
703 0x41 => {
704 let value = read_i32_leb128(reader)?;
705 instructions.push(crate::program::WasiInstruction::I32Const { value });
706 }
707 0x42 => {
708 let value = read_i64_leb128(reader)?;
709 instructions.push(crate::program::WasiInstruction::I64Const { value });
710 }
711 0x6A => instructions.push(crate::program::WasiInstruction::I32Add),
712 0x6B => instructions.push(crate::program::WasiInstruction::I32Sub),
713 0x6C => instructions.push(crate::program::WasiInstruction::I32Mul),
714 0x45 => instructions.push(crate::program::WasiInstruction::I32Eqz),
715 0x46 => instructions.push(crate::program::WasiInstruction::I32Eq),
716 0x47 => instructions.push(crate::program::WasiInstruction::I32Ne),
717 0x48 => instructions.push(crate::program::WasiInstruction::I32LtS),
718 0x49 => instructions.push(crate::program::WasiInstruction::I32LtU),
719 0x4A => instructions.push(crate::program::WasiInstruction::I32GtS),
720 0x4B => instructions.push(crate::program::WasiInstruction::I32GtU),
721 0x4C => instructions.push(crate::program::WasiInstruction::I32LeS),
722 0x4D => instructions.push(crate::program::WasiInstruction::I32LeU),
723 0x4E => instructions.push(crate::program::WasiInstruction::I32GeS),
724 0x4F => instructions.push(crate::program::WasiInstruction::I32GeU),
725
726 0x5F => {
728 let sub_opcode = reader.read_u8()?;
729 match sub_opcode {
730 0x00 => instructions.push(crate::program::WasiInstruction::TaskBackpressure),
731 0x01 => instructions.push(crate::program::WasiInstruction::TaskReturn),
732 0x02 => instructions.push(crate::program::WasiInstruction::TaskWait),
733 0x03 => instructions.push(crate::program::WasiInstruction::TaskPoll),
734 0x04 => instructions.push(crate::program::WasiInstruction::TaskYield),
735 0x05 => instructions.push(crate::program::WasiInstruction::ErrorContextNew),
736 0x06 => instructions.push(crate::program::WasiInstruction::ErrorContextDebugMessage),
737 _ => {
738 return Err(GaiaError::invalid_data(&format!("Unknown sub-opcode for 0x5F: 0x{:02X}", sub_opcode)))
739 }
740 }
741 }
742 _ => {
743 }
746 }
747 }
748 Ok(instructions)
749 }
750}