1use super::{instructions::WasiInstruction, types::*};
2use gaia_types::{GaiaError, Result};
3use std::collections::HashMap;
4
5#[derive(Copy, Clone, Debug, Default)]
6pub struct WasmInfo {
7 pub magic_head: [u8; 4],
8}
9
10#[derive(Debug, Clone)]
14pub struct WasiProgram {
15 pub program_type: WasiProgramType,
17 pub name: Option<String>,
19 pub function_types: Vec<WasiFunctionType>,
21 pub functions: Vec<WasiFunction>,
23 pub exports: Vec<WasiExport>,
25 pub imports: Vec<WasiImport>,
27 pub memories: Vec<WasiMemory>,
29 pub tables: Vec<WasiTable>,
31 pub globals: Vec<WasiGlobal>,
33 pub custom_sections: Vec<WasiCustomSection>,
35 pub start_function: Option<u32>,
37 pub component_items: Vec<WasiComponentItem>,
39 pub core_modules: Vec<WasiCoreModule>,
41 pub instances: Vec<WasiInstance>,
43 pub aliases: Vec<WasiAlias>,
45 pub symbol_table: HashMap<String, WasiSymbol>,
47}
48
49impl WasiProgram {
50 pub fn new(program_type: WasiProgramType) -> Self {
52 Self {
53 program_type,
54 name: None,
55 function_types: Vec::new(),
56 functions: Vec::new(),
57 exports: Vec::new(),
58 imports: Vec::new(),
59 memories: Vec::new(),
60 tables: Vec::new(),
61 globals: Vec::new(),
62 custom_sections: Vec::new(),
63 start_function: None,
64 component_items: Vec::new(),
65 core_modules: Vec::new(),
66 instances: Vec::new(),
67 aliases: Vec::new(),
68 symbol_table: HashMap::new(),
69 }
70 }
71
72 pub fn new_component() -> Self {
74 Self::new(WasiProgramType::Component)
75 }
76
77 pub fn new_core_module() -> Self {
79 Self::new(WasiProgramType::CoreModule)
80 }
81
82 pub fn add_function_type(&mut self, func_type: WasiFunctionType) -> u32 {
84 for (index, existing_type) in self.function_types.iter().enumerate() {
86 if existing_type == &func_type {
87 return index as u32;
88 }
89 }
90
91 let index = self.function_types.len() as u32;
92 self.function_types.push(func_type);
93 index
94 }
95
96 pub fn add_function(&mut self, function: WasiFunction) -> u32 {
98 let index = self.functions.len() as u32;
99 self.functions.push(function);
100 index
101 }
102
103 pub fn add_export(&mut self, export: WasiExport) {
105 self.exports.push(export);
106 }
107
108 pub fn add_import(&mut self, import: WasiImport) {
110 self.imports.push(import);
111 }
112
113 pub fn add_memory(&mut self, memory: WasiMemory) -> u32 {
115 let index = self.memories.len() as u32;
116 self.memories.push(memory);
117 index
118 }
119
120 pub fn add_table(&mut self, table: WasiTable) -> u32 {
122 let index = self.tables.len() as u32;
123 self.tables.push(table);
124 index
125 }
126
127 pub fn add_global(&mut self, global: WasiGlobal) -> u32 {
129 let index = self.globals.len() as u32;
130 self.globals.push(global);
131 index
132 }
133
134 pub fn add_core_module(&mut self, core_module: WasiCoreModule) -> u32 {
136 let index = self.core_modules.len() as u32;
137 self.core_modules.push(core_module);
138 index
139 }
140
141 pub fn add_instance(&mut self, instance: WasiInstance) -> u32 {
143 let index = self.instances.len() as u32;
144 self.instances.push(instance);
145 index
146 }
147
148 pub fn add_alias(&mut self, alias: WasiAlias) {
150 self.aliases.push(alias);
151 }
152
153 pub fn add_symbol(&mut self, name: String, symbol_type: WasiSymbolType, index: u32) {
155 let symbol = WasiSymbol { name: name.clone(), symbol_type, index };
156 self.symbol_table.insert(name, symbol);
157 }
158
159 pub fn find_symbol(&self, name: &str) -> Option<&WasiSymbol> {
161 self.symbol_table.get(name)
162 }
163
164 pub fn validate(&self) -> Result<()> {
166 for function in &self.functions {
168 if function.type_index as usize >= self.function_types.len() {
169 return Err(GaiaError::custom_error(format!(
170 "函数类型索引 {} 超出范围,最大索引为 {}",
171 function.type_index,
172 self.function_types.len().saturating_sub(1)
173 )));
174 }
175 }
176
177 for export in &self.exports {
179 match &export.export_type {
180 WasmExportType::Function { function_index } => {
181 let total_functions =
182 self.imports.iter().filter(|imp| matches!(imp.import_type, WasmImportType::Function { .. })).count()
183 + self.functions.len();
184
185 if *function_index as usize >= total_functions {
186 return Err(GaiaError::custom_error(format!(
187 "导出函数索引 {} 超出范围,最大索引为 {}",
188 function_index,
189 total_functions.saturating_sub(1)
190 )));
191 }
192 }
193 _ => {} }
195 }
196
197 Ok(())
198 }
199
200 #[cfg(feature = "wat")]
202 pub fn to_wat(&self) -> Result<oak_wat::ast::WatRoot> {
203 use oak_wat::ast::{
204 WatExport, WatFunc, WatImport, WatInstruction, WatItem, WatLocal, WatModule, WatModuleField, WatParam, WatResult,
205 WatRoot, WatTypeKind,
206 };
207
208 let mut module_items = Vec::new();
209
210 for import in self.imports.iter() {
212 let kind = match import.import_type {
213 WasmImportType::Function { .. } => "func",
214 WasmImportType::Table { .. } => "table",
215 WasmImportType::Memory { .. } => "memory",
216 WasmImportType::Global { .. } => "global",
217 };
218
219 module_items.push(WatModuleField::Import(WatImport {
220 module: import.module.clone(),
221 name: import.field.clone(),
222 kind: kind.to_string(),
223 }));
224 }
225
226 for (i, func) in self.functions.iter().enumerate() {
228 let func_type = &self.function_types[func.type_index as usize];
229
230 let mut params = Vec::new();
231 for (j, param) in func_type.params.iter().enumerate() {
232 params.push(WatParam {
233 name: Some(format!("$p{}", j)),
234 ty: match param {
235 WasmValueType::I32 => WatTypeKind::I32,
236 WasmValueType::I64 => WatTypeKind::I64,
237 WasmValueType::F32 => WatTypeKind::F32,
238 WasmValueType::F64 => WatTypeKind::F64,
239 _ => WatTypeKind::I32, },
241 });
242 }
243
244 let mut results = Vec::new();
245 for result in &func_type.results {
246 results.push(WatResult {
247 ty: match result {
248 WasmValueType::I32 => WatTypeKind::I32,
249 WasmValueType::I64 => WatTypeKind::I64,
250 WasmValueType::F32 => WatTypeKind::F32,
251 WasmValueType::F64 => WatTypeKind::F64,
252 _ => WatTypeKind::I32, },
254 });
255 }
256
257 let mut locals = Vec::new();
258 let mut local_idx = 0;
259 for local_group in &func.locals {
260 for _ in 0..local_group.count {
261 locals.push(WatLocal {
262 name: Some(format!("$l{}", local_idx)),
263 ty: match local_group.value_type {
264 WasmValueType::I32 => WatTypeKind::I32,
265 WasmValueType::I64 => WatTypeKind::I64,
266 WasmValueType::F32 => WatTypeKind::F32,
267 WasmValueType::F64 => WatTypeKind::F64,
268 _ => WatTypeKind::I32, },
270 });
271 local_idx += 1;
272 }
273 }
274
275 let mut body = Vec::new();
276 for instr in &func.body {
277 let instr_str = match instr {
278 WasiInstruction::Nop => "nop".to_string(),
279 WasiInstruction::Unreachable => "unreachable".to_string(),
280 WasiInstruction::Return => "return".to_string(),
281 WasiInstruction::Drop => "drop".to_string(),
282 WasiInstruction::Select => "select".to_string(),
283 WasiInstruction::I32Add => "i32.add".to_string(),
284 WasiInstruction::I32Sub => "i32.sub".to_string(),
285 WasiInstruction::I32Mul => "i32.mul".to_string(),
286 WasiInstruction::I32DivS => "i32.div_s".to_string(),
287 WasiInstruction::I32DivU => "i32.div_u".to_string(),
288 WasiInstruction::I32RemS => "i32.rem_s".to_string(),
289 WasiInstruction::I32RemU => "i32.rem_u".to_string(),
290 WasiInstruction::I32And => "i32.and".to_string(),
291 WasiInstruction::I32Or => "i32.or".to_string(),
292 WasiInstruction::I32Xor => "i32.xor".to_string(),
293 WasiInstruction::I32Shl => "i32.shl".to_string(),
294 WasiInstruction::I32ShrS => "i32.shr_s".to_string(),
295 WasiInstruction::I32ShrU => "i32.shr_u".to_string(),
296 WasiInstruction::I32Rotl => "i32.rotl".to_string(),
297 WasiInstruction::I32Rotr => "i32.rotr".to_string(),
298 WasiInstruction::I32Eqz => "i32.eqz".to_string(),
299 WasiInstruction::I32Eq => "i32.eq".to_string(),
300 WasiInstruction::I32Ne => "i32.ne".to_string(),
301 WasiInstruction::I32LtS => "i32.lt_s".to_string(),
302 WasiInstruction::I32LtU => "i32.lt_u".to_string(),
303 WasiInstruction::I32GtS => "i32.gt_s".to_string(),
304 WasiInstruction::I32GtU => "i32.gt_u".to_string(),
305 WasiInstruction::I32LeS => "i32.le_s".to_string(),
306 WasiInstruction::I32LeU => "i32.le_u".to_string(),
307 WasiInstruction::I32GeS => "i32.ge_s".to_string(),
308 WasiInstruction::I32GeU => "i32.ge_u".to_string(),
309 WasiInstruction::I32Load { offset, align } => format!("i32.load offset={} align={}", offset, align),
310 WasiInstruction::I64Load { offset, align } => format!("i64.load offset={} align={}", offset, align),
311 WasiInstruction::F32Load { offset, align } => format!("f32.load offset={} align={}", offset, align),
312 WasiInstruction::F64Load { offset, align } => format!("f64.load offset={} align={}", offset, align),
313 WasiInstruction::I32Store { offset, align } => format!("i32.store offset={} align={}", offset, align),
314 WasiInstruction::I64Store { offset, align } => format!("i64.store offset={} align={}", offset, align),
315 WasiInstruction::F32Store { offset, align } => format!("f32.store offset={} align={}", offset, align),
316 WasiInstruction::F64Store { offset, align } => format!("f64.store offset={} align={}", offset, align),
317 WasiInstruction::StructNew { type_index } => format!("struct.new {}", type_index),
318 WasiInstruction::StructGet { type_index, field_index } => {
319 format!("struct.get {} {}", type_index, field_index)
320 }
321 WasiInstruction::StructSet { type_index, field_index } => {
322 format!("struct.set {} {}", type_index, field_index)
323 }
324 WasiInstruction::TaskBackpressure => "task.backpressure".to_string(),
325 WasiInstruction::TaskReturn => "task.return".to_string(),
326 WasiInstruction::TaskWait => "task.wait".to_string(),
327 WasiInstruction::TaskPoll => "task.poll".to_string(),
328 WasiInstruction::TaskYield => "task.yield".to_string(),
329 WasiInstruction::ErrorContextNew => "error_context.new".to_string(),
330 WasiInstruction::ErrorContextDebugMessage => "error_context.debug_message".to_string(),
331 WasiInstruction::LocalGet { local_index } => format!("local.get {}", local_index),
332 WasiInstruction::LocalSet { local_index } => format!("local.set {}", local_index),
333 WasiInstruction::I32Const { value } => format!("i32.const {}", value),
334 WasiInstruction::I64Const { value } => format!("i64.const {}", value),
335 WasiInstruction::F32Const { value } => format!("f32.const {}", value),
336 WasiInstruction::F64Const { value } => format!("f64.const {}", value),
337 WasiInstruction::Call { function_index } => format!("call {}", function_index),
338 WasiInstruction::Block { .. } => "block".to_string(),
339 WasiInstruction::Loop { .. } => "loop".to_string(),
340 WasiInstruction::If { .. } => "if".to_string(),
341 WasiInstruction::Else => "else".to_string(),
342 WasiInstruction::End => "end".to_string(),
343 WasiInstruction::Br { label_index } => format!("br {}", label_index),
344 WasiInstruction::BrIf { label_index } => format!("br_if {}", label_index),
345 _ => format!(";; unknown instruction {:?}", instr),
346 };
347 body.push(WatInstruction::Other(instr_str, vec![]));
348 }
349
350 module_items.push(WatModuleField::Func(WatFunc { name: Some(format!("$f{}", i)), params, results, locals, body }));
351 }
352
353 for export in &self.exports {
355 let (kind, index) = match export.export_type {
356 WasmExportType::Function { function_index } => ("func", function_index),
357 WasmExportType::Table { table_index } => ("table", table_index),
358 WasmExportType::Memory { memory_index } => ("memory", memory_index),
359 WasmExportType::Global { global_index } => ("global", global_index),
360 };
361 module_items.push(WatModuleField::Export(WatExport {
362 name: export.name.clone(),
363 kind: kind.to_string(),
364 id: index.to_string(),
365 }));
366 }
367
368 let mut items = Vec::new();
369 if self.program_type == WasiProgramType::CoreModule {
370 let module = WatModule { name: self.name.clone(), items: module_items };
371 items.push(WatItem::Module(module));
372 }
373
374 Ok(WatRoot { items })
375 }
376
377 pub fn to_wasm(&self) -> Result<Vec<u8>> {
379 let mut writer = crate::formats::wasm::writer::WasmWriter::new(Vec::new());
380 writer.write(self.clone()).result
381 }
382
383 pub fn builder(program_type: WasiProgramType) -> WasiProgramBuilder {
385 WasiProgramBuilder::new(program_type)
386 }
387}
388
389impl Default for WasiProgram {
390 fn default() -> Self {
391 Self::new_core_module()
392 }
393}
394
395pub struct WasiProgramBuilder {
397 program: WasiProgram,
398}
399
400impl WasiProgramBuilder {
401 pub fn new(program_type: WasiProgramType) -> Self {
403 Self { program: WasiProgram::new(program_type) }
404 }
405
406 pub fn with_name(mut self, name: impl Into<String>) -> Self {
408 self.program.name = Some(name.into());
409 self
410 }
411
412 pub fn with_function_type(mut self, func_type: WasiFunctionType) -> Self {
414 self.program.add_function_type(func_type);
415 self
416 }
417
418 pub fn with_function(mut self, function: WasiFunction) -> Self {
420 self.program.add_function(function);
421 self
422 }
423
424 pub fn with_export(mut self, export: WasiExport) -> Self {
426 self.program.add_export(export);
427 self
428 }
429
430 pub fn with_import(mut self, import: WasiImport) -> Self {
432 self.program.add_import(import);
433 self
434 }
435
436 pub fn with_memory(mut self, memory: WasiMemory) -> Self {
438 self.program.add_memory(memory);
439 self
440 }
441
442 pub fn with_table(mut self, table: WasiTable) -> Self {
444 self.program.add_table(table);
445 self
446 }
447
448 pub fn with_global(mut self, global: WasiGlobal) -> Self {
450 self.program.add_global(global);
451 self
452 }
453
454 pub fn with_custom_section(mut self, custom_section: WasiCustomSection) -> Self {
456 self.program.custom_sections.push(custom_section);
457 self
458 }
459
460 pub fn with_start_function(mut self, start_function_index: u32) -> Self {
462 self.program.start_function = Some(start_function_index);
463 self
464 }
465
466 pub fn with_component_item(mut self, item: WasiComponentItem) -> Self {
468 self.program.component_items.push(item);
469 self
470 }
471
472 pub fn with_core_module(mut self, core_module: WasiCoreModule) -> Self {
474 self.program.add_core_module(core_module);
475 self
476 }
477
478 pub fn with_instance(mut self, instance: WasiInstance) -> Self {
480 self.program.add_instance(instance);
481 self
482 }
483
484 pub fn with_alias(mut self, alias: WasiAlias) -> Self {
486 self.program.add_alias(alias);
487 self
488 }
489
490 pub fn with_symbol(mut self, name: impl Into<String>, symbol_type: WasiSymbolType, index: u32) -> Self {
492 self.program.add_symbol(name.into(), symbol_type, index);
493 self
494 }
495
496 pub fn build(self) -> Result<WasiProgram> {
498 self.program.validate().map(|_| self.program)
499 }
500}
501
502#[derive(Debug, Clone)]
504pub enum WasiComponentItem {
505 Type(WasiTypeDefinition),
507 Alias(WasiAlias),
509 Instance(WasiInstance),
511 CoreFunc(WasiCoreFunc),
513 CoreInstance(WasiCoreInstance),
515}
516
517#[derive(Debug, Clone)]
519pub struct WasiCoreModule {
520 pub name: Option<String>,
522 pub index: u32,
524 pub function_types: Vec<WasiFunctionType>,
526 pub functions: Vec<WasiFunction>,
528 pub exports: Vec<WasiExport>,
530 pub imports: Vec<WasiImport>,
532 pub memories: Vec<WasiMemory>,
534 pub tables: Vec<WasiTable>,
536 pub globals: Vec<WasiGlobal>,
538 pub data_segments: Vec<WasiDataSegment>,
540 pub element_segments: Vec<WasiElementSegment>,
542 pub start_function: Option<u32>,
544}
545
546#[derive(Debug, Clone)]
548pub struct WasiInstance {
549 pub name: Option<String>,
551 pub index: u32,
553 pub instantiate_target: String,
555 pub args: Vec<WasiInstanceArg>,
557 pub instance_type: WasiInstanceType,
559}
560
561#[derive(Debug, Clone)]
563pub struct WasiInstanceArg {
564 pub name: String,
566 pub value: String,
568}
569
570#[derive(Debug, Clone)]
572pub struct WasiAlias {
573 pub name: Option<String>,
575 pub target: WasiAliasTarget,
577}
578
579#[derive(Debug, Clone)]
581pub enum WasiAliasTarget {
582 Outer {
584 outer_index: u32,
586 item_index: u32,
588 },
589 Core {
591 core_type: WasiCoreType,
593 item_index: u32,
595 },
596 Export {
598 instance: String,
600 name: String,
602 },
603 CoreExport {
605 instance: String,
607 name: String,
609 },
610}
611
612#[derive(Debug, Clone)]
614pub struct WasiTypeDefinition {
615 pub name: Option<String>,
617 pub index: u32,
619 pub type_content: WasiType,
621}
622
623#[derive(Debug, Clone)]
625pub enum WasiType {
626 Func(WasiFunctionType),
628 Interface(String),
630 Instance(String),
632 Resource(WasiResourceType),
634 Record(Vec<WasiRecordField>),
636 Variant(Vec<WasiVariantCase>),
638 Enum(Vec<String>),
640 Union(Vec<WasiType>),
642 Option(Box<WasiType>),
644 List(Box<WasiType>),
646 Tuple(Vec<WasiType>),
648 Flags(Vec<String>),
650 Future(Option<Box<WasiType>>),
652 Stream(Option<Box<WasiType>>),
654 Primitive(WasiPrimitiveType),
656}
657
658#[derive(Debug, Clone)]
660pub struct WasiResourceType {
661 pub name: String,
663 pub methods: Vec<WasiResourceMethod>,
665}
666
667#[derive(Debug, Clone)]
669pub struct WasiResourceMethod {
670 pub name: String,
672 pub method_type: WasiFunctionType,
674}
675
676#[derive(Debug, Clone)]
678pub struct WasiRecordField {
679 pub name: String,
681 pub field_type: WasiType,
683}
684
685#[derive(Debug, Clone)]
687pub struct WasiVariantCase {
688 pub name: String,
690 pub case_type: Option<WasiType>,
692}
693
694#[derive(Debug, Clone)]
696pub struct WasiCoreFunc {
697 pub name: Option<String>,
699 pub index: u32,
701 pub func_type: WasiFunctionType,
703 pub canon: Option<WasiCanonicalOperation>,
705}
706
707#[derive(Debug, Clone)]
709pub enum WasiCanonicalOperation {
710 Lower {
712 func: String,
714 options: Vec<WasiCanonOption>,
716 },
717 Lift {
719 func: String,
721 options: Vec<WasiCanonOption>,
723 },
724 ResourceNew(String),
726 ResourceDrop(String),
728 ResourceRep(String),
730}
731
732#[derive(Debug, Clone)]
734pub enum WasiCanonOption {
735 StringEncoding(String),
737 Memory(String),
739 Realloc(String),
741 Async,
743 Callback(String),
745}
746
747#[derive(Debug, Clone)]
749pub struct WasiCoreInstance {
750 pub name: Option<String>,
752 pub index: u32,
754 pub instantiate_target: String,
756 pub args: Vec<WasiInstanceArg>,
758}
759
760#[derive(Debug, Clone)]
762pub struct WasiDataSegment {
763 pub name: Option<String>,
765 pub memory_index: Option<u32>,
767 pub offset: Vec<WasiInstruction>,
769 pub data: Vec<u8>,
771}
772
773#[derive(Debug, Clone)]
775pub struct WasiElementSegment {
776 pub name: Option<String>,
778 pub table_index: Option<u32>,
780 pub offset: Vec<WasiInstruction>,
782 pub elements: Vec<u32>,
784}
785
786#[derive(Debug, Clone)]
788pub struct WasiSymbol {
789 pub name: String,
791 pub symbol_type: WasiSymbolType,
793 pub index: u32,
795}
796
797#[derive(Debug, Clone)]
799pub struct WasiFunction {
800 pub type_index: u32,
802 pub locals: Vec<WasmLocal>,
804 pub body: Vec<WasiInstruction>,
806}
807
808#[derive(Copy, Debug, Clone)]
810pub struct WasmLocal {
811 pub count: u32,
813 pub value_type: WasmValueType,
815}
816
817#[derive(Debug, Clone)]
819pub struct WasiExport {
820 pub name: String,
822 pub export_type: WasmExportType,
824}
825
826#[derive(Debug, Clone)]
828pub struct WasiImport {
829 pub module: String,
831 pub field: String,
833 pub import_type: WasmImportType,
835}
836
837#[derive(Copy, Debug, Clone)]
839pub struct WasiMemory {
840 pub memory_type: WasmMemoryType,
841}
842
843#[derive(Copy, Debug, Clone)]
845pub struct WasiTable {
846 pub table_type: WasmTableType,
847}
848
849#[derive(Debug, Clone)]
851pub struct WasiGlobal {
852 pub global_type: WasmGlobalType,
853 pub init_expr: Vec<WasiInstruction>,
854}
855
856#[derive(Debug, Clone)]
858pub struct WasiCustomSection {
859 pub name: String,
861 pub data: Vec<u8>,
863}