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