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 {
106 result: self.program.take().ok_or(GaiaError::custom_error("unreachable")),
107 diagnostics: errors,
108 }
109 }
110 Err(e) => {
111 let errors = vec![]; GaiaDiagnostics { result: Err(e), diagnostics: errors }
113 }
114 }
115 }
116}
117
118impl<'config, R: Read + Seek> WasmReader<'config, R> {
119 pub fn get_program(&self) -> Result<&WasiProgram, GaiaError> {
120 self.program.get_or_try_init(|| self.read_program())
121 }
122 fn read_program(&self) -> Result<WasiProgram, GaiaError> {
123 let mut reader = self.reader.borrow_mut();
124
125 reader.seek(std::io::SeekFrom::Start(0))?;
127
128 self.validate_wasm_header(&mut reader)?;
130
131 let mut program = crate::program::WasiProgram::new_core_module();
133
134 self.parse_sections(&mut reader, &mut program)?;
136
137 Ok(program)
138 }
139
140 fn validate_wasm_header(&self, reader: &mut BinaryReader<R, LittleEndian>) -> Result<(), GaiaError> {
141 let magic = reader.read_u32()?;
143 if magic != 0x6D736100 {
144 return Err(GaiaError::invalid_data("Invalid WASM file magic number"));
146 }
147
148 let version = reader.read_u32()?;
149 if version != 1 {
150 return Err(GaiaError::invalid_data(&format!("Unsupported WASM version: {}", version)));
151 }
152
153 Ok(())
154 }
155
156 fn parse_sections(
157 &self,
158 reader: &mut BinaryReader<R, LittleEndian>,
159 program: &mut crate::program::WasiProgram,
160 ) -> Result<(), GaiaError> {
161 while let Ok(section_id) = reader.read_u8() {
162 let section_size = read_u32_leb128(reader)?;
163
164 match section_id {
165 0 => self.read_custom_section(reader, program, section_size)?,
166 1 => self.read_type_section(reader, program)?,
167 2 => self.read_import_section(reader, program)?,
168 3 => self.read_function_section(reader, program)?,
169 4 => self.read_table_section(reader, program)?,
170 5 => self.read_memory_section(reader, program)?,
171 6 => self.read_global_section(reader, program)?,
172 7 => self.read_export_section(reader, program)?,
173 8 => self.read_start_section(reader, program)?,
174 9 => self.skip_section(reader, section_size)?, 10 => self.read_code_section(reader, program)?,
176 11 => self.skip_section(reader, section_size)?, _ => self.skip_section(reader, section_size)?, }
179 }
180 Ok(())
181 }
182
183 fn read_custom_section(
184 &self,
185 reader: &mut BinaryReader<R, LittleEndian>,
186 program: &mut crate::program::WasiProgram,
187 section_size: u32,
188 ) -> Result<(), GaiaError> {
189 let name_len = read_u32_leb128(reader)?;
190 let mut name_bytes = vec![0u8; name_len as usize];
191 reader.read_exact(&mut name_bytes)?;
192 let name = String::from_utf8_lossy(&name_bytes).to_string();
193
194 let data_len = section_size - name_len - gaia_types::BinaryReader::<R, LittleEndian>::leb128_size(name_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, 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, 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, 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, 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, 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(&self, reader: &mut BinaryReader<R, LittleEndian>) -> Result<crate::program::WasmValueType, GaiaError> {
372 let type_byte = reader.read_u8()?;
373 crate::program::WasmValueType::try_from(type_byte)
374 }
375
376 fn read_import_section(
377 &self,
378 reader: &mut BinaryReader<R, LittleEndian>,
379 program: &mut crate::program::WasiProgram,
380 ) -> Result<(), GaiaError> {
381 let count = read_u32_leb128(reader)?;
382
383 for _ in 0..count {
384 let module_len = read_u32_leb128(reader)?;
386 let mut module_bytes = vec![0u8; module_len as usize];
387 reader.read_exact(&mut module_bytes)?;
388 let module = String::from_utf8_lossy(&module_bytes).to_string();
389
390 let field_len = read_u32_leb128(reader)?;
392 let mut field_bytes = vec![0u8; field_len as usize];
393 reader.read_exact(&mut field_bytes)?;
394 let field = String::from_utf8_lossy(&field_bytes).to_string();
395
396 let import_type = self.read_import_type(reader)?;
397
398 program.imports.push(crate::program::WasiImport { module, field, import_type });
399 }
400
401 Ok(())
402 }
403
404 fn read_import_type(
405 &self,
406 reader: &mut BinaryReader<R, LittleEndian>,
407 ) -> Result<crate::program::WasmImportType, GaiaError> {
408 let kind = reader.read_u8()?;
409 match kind {
410 0x00 => {
411 let type_index = read_u32_leb128(reader)?;
413 Ok(crate::program::WasmImportType::Function { type_index })
414 }
415 0x01 => {
416 let table_type = self.read_table_type(reader)?;
418 Ok(crate::program::WasmImportType::Table { table_type })
419 }
420 0x02 => {
421 let memory_type = self.read_memory_type(reader)?;
423 Ok(crate::program::WasmImportType::Memory { memory_type })
424 }
425 0x03 => {
426 let global_type = self.read_global_type(reader)?;
428 Ok(crate::program::WasmImportType::Global { global_type })
429 }
430 _ => Err(GaiaError::invalid_data(&format!("Unknown import kind: {}", kind))),
431 }
432 }
433
434 fn read_function_section(
435 &self,
436 reader: &mut BinaryReader<R, LittleEndian>,
437 program: &mut crate::program::WasiProgram,
438 ) -> Result<(), GaiaError> {
439 let count = read_u32_leb128(reader)?;
440
441 for _ in 0..count {
442 let type_index = read_u32_leb128(reader)?;
443 program.functions.push(crate::program::WasiFunction { type_index, locals: Vec::new(), body: Vec::new() });
445 }
446
447 Ok(())
448 }
449
450 fn read_table_section(
451 &self,
452 reader: &mut BinaryReader<R, LittleEndian>,
453 program: &mut crate::program::WasiProgram,
454 ) -> Result<(), GaiaError> {
455 let count = read_u32_leb128(reader)?;
456
457 for _ in 0..count {
458 let table_type = self.read_table_type(reader)?;
459 program.tables.push(crate::program::WasiTable { table_type });
460 }
461
462 Ok(())
463 }
464
465 fn read_table_type(&self, reader: &mut BinaryReader<R, LittleEndian>) -> Result<crate::program::WasmTableType, GaiaError> {
466 let element_type = reader.read_u8()?;
467 let element_type = match element_type {
468 0x70 => crate::program::WasmReferenceType::FuncRef,
469 0x6F => crate::program::WasmReferenceType::ExternRef,
470 _ => return Err(GaiaError::invalid_data(&format!("Unknown reference type: 0x{:02X}", element_type))),
471 };
472
473 let limits = self.read_limits(reader)?;
474
475 Ok(crate::program::WasmTableType { element_type, min: limits.0, max: limits.1 })
476 }
477
478 fn read_memory_section(
479 &self,
480 reader: &mut BinaryReader<R, LittleEndian>,
481 program: &mut crate::program::WasiProgram,
482 ) -> Result<(), GaiaError> {
483 let count = read_u32_leb128(reader)?;
484
485 for _ in 0..count {
486 let memory_type = self.read_memory_type(reader)?;
487 program.memories.push(crate::program::WasiMemory { memory_type });
488 }
489
490 Ok(())
491 }
492
493 fn read_memory_type(
494 &self,
495 reader: &mut BinaryReader<R, LittleEndian>,
496 ) -> Result<crate::program::WasmMemoryType, GaiaError> {
497 let limits = self.read_limits(reader)?;
498 Ok(crate::program::WasmMemoryType { min: limits.0, max: limits.1 })
499 }
500
501 fn read_limits(&self, reader: &mut BinaryReader<R, LittleEndian>) -> Result<(u32, Option<u32>), GaiaError> {
502 let flags = reader.read_u8()?;
503 let min = read_u32_leb128(reader)?;
504 let max = if flags & 0x01 != 0 { Some(read_u32_leb128(reader)?) } else { None };
505 Ok((min, max))
506 }
507
508 fn read_global_section(
509 &self,
510 reader: &mut BinaryReader<R, LittleEndian>,
511 program: &mut crate::program::WasiProgram,
512 ) -> Result<(), GaiaError> {
513 let count = read_u32_leb128(reader)?;
514
515 for _ in 0..count {
516 let global_type = self.read_global_type(reader)?;
517 let init_expr = self.read_init_expr(reader)?;
518 program.globals.push(crate::program::WasiGlobal { global_type, init_expr });
519 }
520
521 Ok(())
522 }
523
524 fn read_global_type(
525 &self,
526 reader: &mut BinaryReader<R, LittleEndian>,
527 ) -> Result<crate::program::WasmGlobalType, GaiaError> {
528 let value_type = self.read_value_type(reader)?;
529 let mutability = reader.read_u8()?;
530 let mutable = mutability != 0;
531
532 Ok(crate::program::WasmGlobalType { value_type, mutable })
533 }
534
535 fn read_init_expr(
536 &self,
537 reader: &mut BinaryReader<R, LittleEndian>,
538 ) -> Result<Vec<crate::program::WasiInstruction>, GaiaError> {
539 let mut instructions = Vec::new();
540
541 loop {
542 let opcode = reader.read_u8()?;
543 match opcode {
544 0x41 => {
545 let value = read_i32_leb128(reader)?;
547 instructions.push(crate::program::WasiInstruction::I32Const { value });
548 }
549 0x42 => {
550 let value = read_i64_leb128(reader)?;
552 instructions.push(crate::program::WasiInstruction::I64Const { value });
553 }
554 0x43 => {
555 let value = reader.read_f32()?;
557 instructions.push(crate::program::WasiInstruction::F32Const { value });
558 }
559 0x44 => {
560 let value = reader.read_f64()?;
562 instructions.push(crate::program::WasiInstruction::F64Const { value });
563 }
564 0x0B => {
565 instructions.push(crate::program::WasiInstruction::End);
567 break;
568 }
569 _ => {
570 return Err(GaiaError::invalid_data(&format!("Unsupported opcode in init expression: 0x{:02X}", opcode)));
571 }
572 }
573 }
574
575 Ok(instructions)
576 }
577
578 fn read_export_section(
579 &self,
580 reader: &mut BinaryReader<R, LittleEndian>,
581 program: &mut crate::program::WasiProgram,
582 ) -> Result<(), GaiaError> {
583 let count = read_u32_leb128(reader)?;
584
585 for _ in 0..count {
586 let name_len = read_u32_leb128(reader)?;
588 let mut name_bytes = vec![0u8; name_len as usize];
589 reader.read_exact(&mut name_bytes)?;
590 let name = String::from_utf8_lossy(&name_bytes).to_string();
591
592 let kind = reader.read_u8()?;
594 let index = read_u32_leb128(reader)?;
595
596 let export_type = match kind {
597 0x00 => crate::program::WasmExportType::Function { function_index: index },
598 0x01 => crate::program::WasmExportType::Table { table_index: index },
599 0x02 => crate::program::WasmExportType::Memory { memory_index: index },
600 0x03 => crate::program::WasmExportType::Global { global_index: index },
601 _ => return Err(GaiaError::invalid_data(&format!("Unknown export kind: {}", kind))),
602 };
603
604 program.exports.push(crate::program::WasiExport { name, export_type });
605 }
606
607 Ok(())
608 }
609
610 fn read_code_section(
611 &self,
612 reader: &mut BinaryReader<R, LittleEndian>,
613 program: &mut crate::program::WasiProgram,
614 ) -> Result<(), GaiaError> {
615 let count = read_u32_leb128(reader)?;
616
617 for i in 0..count {
618 let body_size = read_u32_leb128(reader)?;
620 let start_pos = reader.get_position();
621
622 let local_count = read_u32_leb128(reader)?;
624 let mut locals = Vec::new();
625 for _ in 0..local_count {
626 let count = read_u32_leb128(reader)?;
627 let value_type = self.read_value_type(reader)?;
628 locals.push(crate::program::WasmLocal { count, value_type });
629 }
630
631 let remaining_size = body_size - (reader.get_position() - start_pos) as u32;
634 let mut body_bytes = vec![0u8; remaining_size as usize];
635 reader.read_exact(&mut body_bytes)?;
636
637 program.functions[i as usize].locals = locals;
639
640 let mut body_reader = BinaryReader::new(std::io::Cursor::new(body_bytes));
642 program.functions[i as usize].body = self.read_instructions(&mut body_reader)?;
643 }
644
645 Ok(())
646 }
647
648 fn read_instructions<RR: Read + Seek>(
649 &self,
650 reader: &mut BinaryReader<RR, LittleEndian>,
651 ) -> Result<Vec<crate::program::WasiInstruction>, GaiaError> {
652 let mut instructions = Vec::new();
653 while let Ok(opcode) = reader.read_u8() {
654 match opcode {
655 0x00 => instructions.push(crate::program::WasiInstruction::Unreachable),
656 0x01 => instructions.push(crate::program::WasiInstruction::Nop),
657 0x02 => {
658 let _block_type = reader.read_u8()?; instructions.push(crate::program::WasiInstruction::Block { block_type: None });
660 }
661 0x03 => {
662 let _block_type = reader.read_u8()?; instructions.push(crate::program::WasiInstruction::Loop { block_type: None });
664 }
665 0x04 => {
666 let _block_type = reader.read_u8()?; instructions.push(crate::program::WasiInstruction::If { block_type: None });
668 }
669 0x05 => instructions.push(crate::program::WasiInstruction::Else),
670 0x0B => {
671 instructions.push(crate::program::WasiInstruction::End);
672 }
674 0x0C => {
675 let label_index = read_u32_leb128(reader)?;
676 instructions.push(crate::program::WasiInstruction::Br { label_index });
677 }
678 0x0D => {
679 let label_index = read_u32_leb128(reader)?;
680 instructions.push(crate::program::WasiInstruction::BrIf { label_index });
681 }
682 0x0F => instructions.push(crate::program::WasiInstruction::Return),
683 0x10 => {
684 let function_index = read_u32_leb128(reader)?;
685 instructions.push(crate::program::WasiInstruction::Call { function_index });
686 }
687 0x1A => instructions.push(crate::program::WasiInstruction::Drop),
688 0x1B => instructions.push(crate::program::WasiInstruction::Select),
689 0x20 => {
690 let local_index = read_u32_leb128(reader)?;
691 instructions.push(crate::program::WasiInstruction::LocalGet { local_index });
692 }
693 0x21 => {
694 let local_index = read_u32_leb128(reader)?;
695 instructions.push(crate::program::WasiInstruction::LocalSet { local_index });
696 }
697 0x41 => {
698 let value = read_i32_leb128(reader)?;
699 instructions.push(crate::program::WasiInstruction::I32Const { value });
700 }
701 0x42 => {
702 let value = read_i64_leb128(reader)?;
703 instructions.push(crate::program::WasiInstruction::I64Const { value });
704 }
705 0x6A => instructions.push(crate::program::WasiInstruction::I32Add),
706 0x6B => instructions.push(crate::program::WasiInstruction::I32Sub),
707 0x6C => instructions.push(crate::program::WasiInstruction::I32Mul),
708 0x45 => instructions.push(crate::program::WasiInstruction::I32Eqz),
709 0x46 => instructions.push(crate::program::WasiInstruction::I32Eq),
710 0x47 => instructions.push(crate::program::WasiInstruction::I32Ne),
711 0x48 => instructions.push(crate::program::WasiInstruction::I32LtS),
712 0x49 => instructions.push(crate::program::WasiInstruction::I32LtU),
713 0x4A => instructions.push(crate::program::WasiInstruction::I32GtS),
714 0x4B => instructions.push(crate::program::WasiInstruction::I32GtU),
715 0x4C => instructions.push(crate::program::WasiInstruction::I32LeS),
716 0x4D => instructions.push(crate::program::WasiInstruction::I32LeU),
717 0x4E => instructions.push(crate::program::WasiInstruction::I32GeS),
718 0x4F => instructions.push(crate::program::WasiInstruction::I32GeU),
719
720 0x5F => {
722 let sub_opcode = reader.read_u8()?;
723 match sub_opcode {
724 0x00 => instructions.push(crate::program::WasiInstruction::TaskBackpressure),
725 0x01 => instructions.push(crate::program::WasiInstruction::TaskReturn),
726 0x02 => instructions.push(crate::program::WasiInstruction::TaskWait),
727 0x03 => instructions.push(crate::program::WasiInstruction::TaskPoll),
728 0x04 => instructions.push(crate::program::WasiInstruction::TaskYield),
729 0x05 => instructions.push(crate::program::WasiInstruction::ErrorContextNew),
730 0x06 => instructions.push(crate::program::WasiInstruction::ErrorContextDebugMessage),
731 _ => {
732 return Err(GaiaError::invalid_data(&format!("Unknown sub-opcode for 0x5F: 0x{:02X}", sub_opcode)))
733 }
734 }
735 }
736 _ => {
737 }
740 }
741 }
742 Ok(instructions)
743 }
744}