Skip to main content

gaia_assembler/backends/nyar/
mod.rs

1use crate::{
2    backends::{Backend, GeneratedFiles},
3    config::GaiaConfig,
4    instruction::{CastKind, CmpCondition, CoreInstruction, GaiaInstruction, ManagedInstruction},
5    program::{GaiaFunction, GaiaModule},
6    types::GaiaType,
7};
8use gaia_binary::{BinaryWriter, Leb128};
9use gaia_types::{
10    helpers::{Architecture, ArtifactType, CompilationTarget},
11    Result,
12};
13use nyar_assembler::program::{
14    instructions::NyarCodec,
15    pool::NyarConstantPool,
16    types::{NyarChunk, NyarConstant, NyarModule},
17    NyarInstruction,
18};
19use std::collections::HashMap;
20
21/// Nyar backend for Gaia assembler.
22///
23/// This backend translates Gaia IR into Nyar VM instructions.
24pub struct NyarBackend;
25
26impl Backend for NyarBackend {
27    fn name(&self) -> &'static str {
28        "nyar"
29    }
30
31    fn primary_target(&self) -> CompilationTarget {
32        CompilationTarget::new("nyar", "nyar", "nyar")
33    }
34
35    fn artifact_type(&self) -> ArtifactType {
36        ArtifactType::Executable
37    }
38
39    fn match_score(&self, target: &CompilationTarget) -> f32 {
40        if target.build == Architecture::Nyar {
41            100.0
42        }
43        else {
44            0.0
45        }
46    }
47
48    fn generate(&self, program: &GaiaModule, config: &GaiaConfig) -> Result<GeneratedFiles> {
49        let mut nyar_module = NyarModule::default();
50        let mut constant_pool = NyarConstantPool::new();
51
52        for func in &program.functions {
53            let chunk = self.translate_function(func, &mut constant_pool)?;
54            nyar_module.chunks.push(chunk);
55        }
56
57        nyar_module.constants = constant_pool.pool;
58
59        Ok(GeneratedFiles {
60            artifact_type: ArtifactType::Executable,
61            files: HashMap::new(),
62            custom: Some(std::sync::Arc::new(nyar_module)),
63            diagnostics: vec![],
64        })
65    }
66}
67
68impl NyarBackend {
69    fn translate_function(&self, func: &GaiaFunction, pool: &mut NyarConstantPool) -> Result<NyarChunk> {
70        let mut chunk = NyarChunk::default();
71        let mut instructions = Vec::new();
72        let mut label_positions = std::collections::HashMap::new();
73
74        // First pass: collect label positions and translate instructions
75        for block in &func.blocks {
76            // Record label position
77            label_positions.insert(block.label.clone(), instructions.len());
78
79            for inst in &block.instructions {
80                self.translate_instruction(inst, &mut instructions, pool)?;
81            }
82            // Handle terminator
83            self.translate_terminator(&block.terminator, &mut instructions, pool)?;
84        }
85
86        // Second pass: fix up jump offsets
87        let mut fixed_instructions = Vec::new();
88        for (i, inst) in instructions.iter().enumerate() {
89            match inst {
90                NyarInstruction::Jump(_) => {
91                    // For now, keep as 0, we'll implement proper offset calculation later
92                    fixed_instructions.push(NyarInstruction::Jump(0));
93                }
94                NyarInstruction::JumpIfFalse(_) => {
95                    fixed_instructions.push(NyarInstruction::JumpIfFalse(0));
96                }
97                NyarInstruction::JumpIfTrue(_) => {
98                    fixed_instructions.push(NyarInstruction::JumpIfTrue(0));
99                }
100                _ => {
101                    fixed_instructions.push(inst.clone());
102                }
103            }
104        }
105
106        let mut writer = BinaryWriter::<Vec<u8>, Leb128>::new(Vec::new());
107        for inst in fixed_instructions {
108            inst.encode(&mut writer).map_err(|e| gaia_types::GaiaError::custom_error(e.to_string()))?;
109        }
110        chunk.code = writer.into_inner();
111
112        Ok(chunk)
113    }
114
115
116    fn translate_instruction(
117        &self,
118        inst: &GaiaInstruction,
119        out: &mut Vec<NyarInstruction>,
120        pool: &mut NyarConstantPool,
121    ) -> Result<()> {
122        match inst {
123            GaiaInstruction::Core(core) => self.translate_core(core, out, pool),
124            GaiaInstruction::Managed(managed) => self.translate_managed(managed, out, pool),
125            GaiaInstruction::Domain(_) => Ok(()),
126        }
127    }
128
129    fn translate_core(
130        &self,
131        inst: &CoreInstruction,
132        out: &mut Vec<NyarInstruction>,
133        pool: &mut NyarConstantPool,
134    ) -> Result<()> {
135        use crate::program::GaiaConstant;
136        match inst {
137            CoreInstruction::PushConstant(c) => match c {
138                GaiaConstant::I64(v) => out.push(NyarInstruction::I64Const(*v)),
139                GaiaConstant::F64(v) => out.push(NyarInstruction::F64Const(*v)),
140                GaiaConstant::I32(v) => out.push(NyarInstruction::I32Const(*v)),
141                GaiaConstant::F32(v) => out.push(NyarInstruction::F32Const(*v)),
142                GaiaConstant::String(s) => {
143                    let idx = pool.add(NyarConstant::String(s.clone()));
144                    out.push(NyarInstruction::Push(idx));
145                }
146                other => {
147                    // 警告:未处理的常量类型
148                    eprintln!("Warning: Unhandled constant type: {:?}", other);
149                }
150            },
151            CoreInstruction::Add(ty) => {
152                match ty {
153                    GaiaType::I32 => out.push(NyarInstruction::I32Add),
154                    GaiaType::I64 => out.push(NyarInstruction::I64Add),
155                    GaiaType::F32 => out.push(NyarInstruction::F32Add),
156                    GaiaType::F64 => out.push(NyarInstruction::F64Add),
157                    other => {
158                        // 警告:未处理的类型
159                        eprintln!("Warning: Unhandled type in Add: {:?}", other);
160                    }
161                }
162            }
163            CoreInstruction::Sub(ty) => {
164                match ty {
165                    GaiaType::I32 => out.push(NyarInstruction::I32Sub),
166                    GaiaType::I64 => out.push(NyarInstruction::I64Sub),
167                    GaiaType::F32 => out.push(NyarInstruction::F32Sub),
168                    GaiaType::F64 => out.push(NyarInstruction::F64Sub),
169                    other => {
170                        eprintln!("Warning: Unhandled type in Sub: {:?}", other);
171                    }
172                }
173            }
174            CoreInstruction::Mul(ty) => {
175                match ty {
176                    GaiaType::I32 => out.push(NyarInstruction::I32Mul),
177                    GaiaType::I64 => out.push(NyarInstruction::I64Mul),
178                    GaiaType::F32 => out.push(NyarInstruction::F32Mul),
179                    GaiaType::F64 => out.push(NyarInstruction::F64Mul),
180                    other => {
181                        eprintln!("Warning: Unhandled type in Mul: {:?}", other);
182                    }
183                }
184            }
185            CoreInstruction::Div(ty) => {
186                match ty {
187                    GaiaType::I32 => out.push(NyarInstruction::I32DivS),
188                    GaiaType::I64 => out.push(NyarInstruction::I64DivS),
189                    GaiaType::F32 => out.push(NyarInstruction::F32Div),
190                    GaiaType::F64 => out.push(NyarInstruction::F64Div),
191                    other => {
192                        eprintln!("Warning: Unhandled type in Div: {:?}", other);
193                    }
194                }
195            }
196            CoreInstruction::Rem(ty) => {
197                match ty {
198                    GaiaType::I32 => out.push(NyarInstruction::I32RemS),
199                    GaiaType::I64 => out.push(NyarInstruction::I64RemS),
200                    other => {
201                        eprintln!("Warning: Unhandled type in Rem: {:?}", other);
202                    }
203                }
204            }
205            CoreInstruction::And(ty) => {
206                match ty {
207                    GaiaType::I32 => out.push(NyarInstruction::I32And),
208                    GaiaType::I64 => out.push(NyarInstruction::I64And),
209                    other => {
210                        eprintln!("Warning: Unhandled type in And: {:?}", other);
211                    }
212                }
213            }
214            CoreInstruction::Or(ty) => {
215                match ty {
216                    GaiaType::I32 => out.push(NyarInstruction::I32Or),
217                    GaiaType::I64 => out.push(NyarInstruction::I64Or),
218                    other => {
219                        eprintln!("Warning: Unhandled type in Or: {:?}", other);
220                    }
221                }
222            }
223            CoreInstruction::Xor(ty) => {
224                match ty {
225                    GaiaType::I32 => out.push(NyarInstruction::I32Xor),
226                    GaiaType::I64 => out.push(NyarInstruction::I64Xor),
227                    other => {
228                        eprintln!("Warning: Unhandled type in Xor: {:?}", other);
229                    }
230                }
231            }
232            CoreInstruction::Shl(ty) => {
233                match ty {
234                    GaiaType::I32 => out.push(NyarInstruction::I32Shl),
235                    GaiaType::I64 => out.push(NyarInstruction::I64Shl),
236                    other => {
237                        eprintln!("Warning: Unhandled type in Shl: {:?}", other);
238                    }
239                }
240            }
241            CoreInstruction::Shr(ty) => {
242                match ty {
243                    GaiaType::I32 => out.push(NyarInstruction::I32ShrS),
244                    GaiaType::I64 => out.push(NyarInstruction::I64ShrS),
245                    other => {
246                        eprintln!("Warning: Unhandled type in Shr: {:?}", other);
247                    }
248                }
249            }
250            CoreInstruction::Neg(ty) => {
251                match ty {
252                    GaiaType::I32 => out.push(NyarInstruction::I32Neg),
253                    GaiaType::I64 => out.push(NyarInstruction::I64Neg),
254                    GaiaType::F32 => out.push(NyarInstruction::F32Neg),
255                    GaiaType::F64 => out.push(NyarInstruction::F64Neg),
256                    other => {
257                        eprintln!("Warning: Unhandled type in Neg: {:?}", other);
258                    }
259                }
260            }
261            CoreInstruction::Not(ty) => {
262                match ty {
263                    GaiaType::I32 => out.push(NyarInstruction::I32Not),
264                    GaiaType::I64 => out.push(NyarInstruction::I64Not),
265                    other => {
266                        eprintln!("Warning: Unhandled type in Not: {:?}", other);
267                    }
268                }
269            }
270            CoreInstruction::Ret => out.push(NyarInstruction::Return),
271            CoreInstruction::LoadLocal(idx, _) => out.push(NyarInstruction::LoadLocal(*idx as u8)),
272            CoreInstruction::StoreLocal(idx, _) => out.push(NyarInstruction::StoreLocal(*idx as u8)),
273            CoreInstruction::LoadArg(idx, _) => out.push(NyarInstruction::LoadLocal(*idx as u8)),
274            CoreInstruction::StoreArg(idx, _) => out.push(NyarInstruction::StoreLocal(*idx as u8)),
275            CoreInstruction::Pop => out.push(NyarInstruction::Pop),
276            CoreInstruction::Dup => out.push(NyarInstruction::Dup(0)),
277            CoreInstruction::Cmp(cond, ty) => {
278                match ty {
279                    GaiaType::I32 => match cond {
280                        CmpCondition::Eq => out.push(NyarInstruction::I32Eq),
281                        CmpCondition::Ne => out.push(NyarInstruction::I32Ne),
282                        CmpCondition::Lt => out.push(NyarInstruction::I32LtS),
283                        CmpCondition::Le => out.push(NyarInstruction::I32LeS),
284                        CmpCondition::Gt => out.push(NyarInstruction::I32GtS),
285                        CmpCondition::Ge => out.push(NyarInstruction::I32GeS),
286                    },
287                    GaiaType::I64 => match cond {
288                        CmpCondition::Eq => out.push(NyarInstruction::I64Eq),
289                        CmpCondition::Ne => out.push(NyarInstruction::I64Ne),
290                        CmpCondition::Lt => out.push(NyarInstruction::I64LtS),
291                        CmpCondition::Le => out.push(NyarInstruction::I64LeS),
292                        CmpCondition::Gt => out.push(NyarInstruction::I64GtS),
293                        CmpCondition::Ge => out.push(NyarInstruction::I64GeS),
294                    },
295                    GaiaType::F32 => match cond {
296                        CmpCondition::Eq => out.push(NyarInstruction::F32Eq),
297                        CmpCondition::Ne => out.push(NyarInstruction::F32Ne),
298                        CmpCondition::Lt => out.push(NyarInstruction::F32Lt),
299                        CmpCondition::Le => out.push(NyarInstruction::F32Le),
300                        CmpCondition::Gt => out.push(NyarInstruction::F32Gt),
301                        CmpCondition::Ge => out.push(NyarInstruction::F32Ge),
302                    },
303                    GaiaType::F64 => match cond {
304                        CmpCondition::Eq => out.push(NyarInstruction::F64Eq),
305                        CmpCondition::Ne => out.push(NyarInstruction::F64Ne),
306                        CmpCondition::Lt => out.push(NyarInstruction::F64Lt),
307                        CmpCondition::Le => out.push(NyarInstruction::F64Le),
308                        CmpCondition::Gt => out.push(NyarInstruction::F64Gt),
309                        CmpCondition::Ge => out.push(NyarInstruction::F64Ge),
310                    },
311                    other => {
312                        eprintln!("Warning: Unhandled type in Cmp: {:?}", other);
313                    }
314                }
315            }
316            CoreInstruction::Br(label) => {
317                // 暂时使用 0 作为偏移量,后续需要计算实际偏移量
318                out.push(NyarInstruction::Jump(0));
319            }
320            CoreInstruction::BrTrue(_label) => {
321                // 暂时使用 0 作为偏移量,后续需要计算实际偏移量
322                out.push(NyarInstruction::JumpIfTrue(0));
323            }
324            CoreInstruction::BrFalse(_label) => {
325                // 暂时使用 0 作为偏移量,后续需要计算实际偏移量
326                out.push(NyarInstruction::JumpIfFalse(0));
327            }
328            CoreInstruction::Call(func_name, args_count) => {
329                let idx = pool.add(NyarConstant::String(func_name.clone()));
330                out.push(NyarInstruction::Call(idx, *args_count as u8));
331            }
332            CoreInstruction::CallIndirect(args_count) => {
333                out.push(NyarInstruction::CallClosure(*args_count as u8));
334            }
335            CoreInstruction::New(type_name) => {
336                let idx = pool.add(NyarConstant::String(type_name.clone()));
337                out.push(NyarInstruction::NewObject(idx));
338            }
339            CoreInstruction::NewArray(_ty, _is_length_on_stack) => {
340                // 暂时使用 0 作为长度,后续需要处理长度计算
341                out.push(NyarInstruction::NewArray(0));
342            }
343            CoreInstruction::LoadField(_obj_type, field_name) => {
344                let idx = pool.add(NyarConstant::String(field_name.clone()));
345                out.push(NyarInstruction::GetField(idx));
346            }
347            CoreInstruction::StoreField(_obj_type, field_name) => {
348                let idx = pool.add(NyarConstant::String(field_name.clone()));
349                out.push(NyarInstruction::SetField(idx));
350            }
351            CoreInstruction::LoadElement(_ty) => {
352                out.push(NyarInstruction::GetElement);
353            }
354            CoreInstruction::StoreElement(_ty) => {
355                out.push(NyarInstruction::SetElement);
356            }
357            CoreInstruction::ArrayLength => {
358                out.push(NyarInstruction::SizeOf);
359            }
360            CoreInstruction::ArrayPush => {
361                out.push(NyarInstruction::PushElementRight);
362            }
363            CoreInstruction::StructNew(struct_name) => {
364                let idx = pool.add(NyarConstant::String(struct_name.clone()));
365                out.push(NyarInstruction::NewObject(idx));
366            }
367            CoreInstruction::StructGet { struct_name: _, field_index, is_signed: _ } => {
368                // 暂时使用字段名作为索引,后续需要优化
369                let idx = pool.add(NyarConstant::String(format!("field_{}", field_index)));
370                out.push(NyarInstruction::GetField(idx));
371            }
372            CoreInstruction::StructSet { struct_name: _, field_index } => {
373                // 暂时使用字段名作为索引,后续需要优化
374                let idx = pool.add(NyarConstant::String(format!("field_{}", field_index)));
375                out.push(NyarInstruction::SetField(idx));
376            }
377            CoreInstruction::ArrayNew(array_name) => {
378                pool.add(NyarConstant::String(array_name.clone()));
379                out.push(NyarInstruction::NewArray(0));
380            }
381            CoreInstruction::ArrayGet { array_name: _, is_signed: _ } => {
382                out.push(NyarInstruction::GetElement);
383            }
384            CoreInstruction::ArraySet(_array_name) => {
385                out.push(NyarInstruction::SetElement);
386            }
387            CoreInstruction::Cast { from, to, kind: _ } => {
388                // 实现类型转换指令
389                match (from, to) {
390                    (GaiaType::I32, GaiaType::I64) => out.push(NyarInstruction::I32Extend64S),
391                    (GaiaType::I32, GaiaType::F32) => out.push(NyarInstruction::I32ToF32S),
392                    (GaiaType::I32, GaiaType::F64) => out.push(NyarInstruction::I32ToF64S),
393                    (GaiaType::I64, GaiaType::I32) => out.push(NyarInstruction::I32Trunc64S),
394                    (GaiaType::I64, GaiaType::F32) => out.push(NyarInstruction::I64ToF32S),
395                    (GaiaType::I64, GaiaType::F64) => out.push(NyarInstruction::I64ToF64S),
396                    (GaiaType::F32, GaiaType::I32) => out.push(NyarInstruction::F32ToI32S),
397                    (GaiaType::F32, GaiaType::I64) => out.push(NyarInstruction::F32ToI64S),
398                    (GaiaType::F32, GaiaType::F64) => out.push(NyarInstruction::F32ToF64),
399                    (GaiaType::F64, GaiaType::I32) => out.push(NyarInstruction::F64ToI32S),
400                    (GaiaType::F64, GaiaType::I64) => out.push(NyarInstruction::F64ToI64S),
401                    (GaiaType::F64, GaiaType::F32) => out.push(NyarInstruction::F64ToF32),
402                    _ => {
403                        // 对于其他类型转换,使用通用的 Cast 指令
404                        let idx = pool.add(NyarConstant::String(to.to_string()));
405                        out.push(NyarInstruction::Cast(idx));
406                    }
407                }
408            }
409            CoreInstruction::Alloca(_ty, count) => {
410                // 内存分配指令,在 Nyar 中使用局部变量模拟
411                for _ in 0..*count {
412                    out.push(NyarInstruction::PushNone);
413                }
414            }
415            CoreInstruction::Load(_ty) => {
416                // 加载指令,在 Nyar 中使用 GetElement 模拟
417                out.push(NyarInstruction::GetElement);
418            }
419            CoreInstruction::Store(_ty) => {
420                // 存储指令,在 Nyar 中使用 SetElement 模拟
421                out.push(NyarInstruction::SetElement);
422            }
423            CoreInstruction::Gep { base_type: _, indices } => {
424                //  gep 指令,在 Nyar 中使用 GetElement 模拟
425                for _ in 0..indices.len() {
426                    out.push(NyarInstruction::GetElement);
427                }
428            }
429
430            CoreInstruction::Label(_label) => {
431                // 标签,暂时不处理
432            }
433            CoreInstruction::Throw => {
434                // 抛出异常指令,使用 Halt 作为替代
435                out.push(NyarInstruction::Halt);
436            }
437        }
438        Ok(())
439    }
440
441    fn translate_managed(
442        &self,
443        inst: &ManagedInstruction,
444        out: &mut Vec<NyarInstruction>,
445        pool: &mut NyarConstantPool,
446    ) -> Result<()> {
447        match inst {
448            ManagedInstruction::Initiate(args) => out.push(NyarInstruction::Initiate(*args as u8)),
449            ManagedInstruction::Finalize => out.push(NyarInstruction::Finalize),
450            ManagedInstruction::CallMethod { target: _, method, signature, is_virtual, call_site_id: _ } => {
451                let idx = pool.add(NyarConstant::String(method.clone()));
452                if *is_virtual {
453                    out.push(NyarInstruction::CallVirtual(idx, signature.params.len() as u8));
454                } else {
455                    out.push(NyarInstruction::InvokeMethod(idx, signature.params.len() as u8));
456                }
457            }
458            ManagedInstruction::CallStatic { target, method, signature } => {
459                let idx = pool.add(NyarConstant::String(format!("{}.{}", target, method)));
460                out.push(NyarInstruction::Call(idx, signature.params.len() as u8));
461            }
462            ManagedInstruction::Box(_ty) => {
463                // 装箱操作,暂时不处理
464            }
465            ManagedInstruction::Unbox(_ty) => {
466                // 拆箱操作,暂时不处理
467            }
468            ManagedInstruction::InstanceOf(ty) => {
469                let idx = pool.add(NyarConstant::String(ty.to_string()));
470                out.push(NyarInstruction::InstanceOf(idx));
471            }
472            ManagedInstruction::CheckCast(ty) => {
473                let idx = pool.add(NyarConstant::String(ty.to_string()));
474                out.push(NyarInstruction::CheckCast(idx));
475            }
476        }
477        Ok(())
478    }
479
480    fn translate_terminator(
481        &self,
482        term: &crate::program::GaiaTerminator,
483        out: &mut Vec<NyarInstruction>,
484        pool: &mut NyarConstantPool,
485    ) -> Result<()> {
486        use crate::program::GaiaTerminator::*;
487        match term {
488            Return => out.push(NyarInstruction::Return),
489            Halt => out.push(NyarInstruction::Halt),
490            Jump(_) => {
491                out.push(NyarInstruction::Jump(0));
492            }
493            Branch { .. } => {
494                out.push(NyarInstruction::JumpIfFalse(0));
495            }
496            Call { callee, args_count, .. } => {
497                let idx = pool.add(NyarConstant::String(callee.clone()));
498                out.push(NyarInstruction::Call(idx, *args_count as u8));
499            }
500        }
501        Ok(())
502    }
503}