gaia_assembler/backends/nyar/
mod.rs1use crate::{
2 backends::{Backend, GeneratedFiles},
3 config::GaiaConfig,
4 instruction::{CmpCondition, CoreInstruction, GaiaInstruction, ManagedInstruction},
5 program::{GaiaFunction, GaiaModule},
6};
7use gaia_binary::{BinaryWriter, Leb128};
8use gaia_types::{
9 helpers::{Architecture, ArtifactType, CompilationTarget},
10 Result,
11};
12use nyar_assembler::program::{
13 instructions::NyarCodec,
14 pool::NyarConstantPool,
15 types::{NyarChunk, NyarConstant, NyarInstruction, NyarModule},
16};
17use std::collections::HashMap;
18
19pub struct NyarBackend;
23
24impl Backend for NyarBackend {
25 fn name(&self) -> &'static str {
26 "nyar"
27 }
28
29 fn primary_target(&self) -> CompilationTarget {
30 CompilationTarget::new("nyar", "nyar", "nyar")
31 }
32
33 fn artifact_type(&self) -> ArtifactType {
34 ArtifactType::Executable
35 }
36
37 fn match_score(&self, target: &CompilationTarget) -> f32 {
38 if target.build == Architecture::Nyar {
39 100.0
40 }
41 else {
42 0.0
43 }
44 }
45
46 fn generate(&self, program: &GaiaModule, _config: &GaiaConfig) -> Result<GeneratedFiles> {
47 let mut nyar_module = NyarModule::default();
48 let mut constant_pool = NyarConstantPool::new();
49
50 for func in &program.functions {
51 let chunk = self.translate_function(func, &mut constant_pool)?;
52 nyar_module.chunks.push(chunk);
53 }
54
55 nyar_module.constants = constant_pool.pool;
56
57 Ok(GeneratedFiles {
58 artifact_type: ArtifactType::Executable,
59 files: HashMap::new(),
60 custom: Some(std::sync::Arc::new(nyar_module)),
61 diagnostics: vec![],
62 })
63 }
64}
65
66impl NyarBackend {
67 fn translate_function(&self, func: &GaiaFunction, pool: &mut NyarConstantPool) -> Result<NyarChunk> {
68 let mut chunk = NyarChunk::default();
69 let mut instructions = Vec::new();
70
71 for block in &func.blocks {
72 for inst in &block.instructions {
73 self.translate_instruction(inst, &mut instructions, pool)?;
74 }
75 self.translate_terminator(&block.terminator, &mut instructions, pool)?;
77 }
78
79 let mut writer = BinaryWriter::<Vec<u8>, Leb128>::new(Vec::new());
80 for inst in instructions {
81 inst.encode(&mut writer).map_err(|e| gaia_types::GaiaError::custom_error(e.to_string()))?;
82 }
83 chunk.code = writer.into_inner();
84
85 Ok(chunk)
86 }
87
88 fn translate_instruction(
89 &self,
90 inst: &GaiaInstruction,
91 out: &mut Vec<NyarInstruction>,
92 pool: &mut NyarConstantPool,
93 ) -> Result<()> {
94 match inst {
95 GaiaInstruction::Core(core) => self.translate_core(core, out, pool),
96 GaiaInstruction::Managed(managed) => self.translate_managed(managed, out, pool),
97 GaiaInstruction::Domain(_) => Ok(()),
98 }
99 }
100
101 fn translate_core(
102 &self,
103 inst: &CoreInstruction,
104 out: &mut Vec<NyarInstruction>,
105 pool: &mut NyarConstantPool,
106 ) -> Result<()> {
107 use crate::program::GaiaConstant;
108 match inst {
109 CoreInstruction::PushConstant(c) => match c {
110 GaiaConstant::I64(v) => out.push(NyarInstruction::I64Const(*v)),
111 GaiaConstant::F64(v) => out.push(NyarInstruction::F64Const(*v)),
112 GaiaConstant::I32(v) => out.push(NyarInstruction::I64Const(*v as i64)),
113 GaiaConstant::F32(v) => out.push(NyarInstruction::F64Const(*v as f64)),
114 GaiaConstant::String(s) => {
115 let idx = pool.add(NyarConstant::String(s.clone()));
116 out.push(NyarInstruction::Push(idx));
117 }
118 _ => {}
119 },
120 CoreInstruction::Add(ty) => {
121 if ty.is_integer() {
122 out.push(NyarInstruction::I64Add);
123 }
124 else if ty.is_float() {
125 out.push(NyarInstruction::F64Add);
126 }
127 }
128 CoreInstruction::Sub(ty) => {
129 if ty.is_integer() {
130 out.push(NyarInstruction::I64Sub);
131 }
132 else if ty.is_float() {
133 out.push(NyarInstruction::F64Sub);
134 }
135 }
136 CoreInstruction::Mul(ty) => {
137 if ty.is_integer() {
138 out.push(NyarInstruction::I64Mul);
139 }
140 else if ty.is_float() {
141 out.push(NyarInstruction::F64Mul);
142 }
143 }
144 CoreInstruction::Div(ty) => {
145 if ty.is_integer() {
146 out.push(NyarInstruction::I64DivS);
147 }
148 else if ty.is_float() {
149 out.push(NyarInstruction::F64Div);
150 }
151 }
152 CoreInstruction::Ret => out.push(NyarInstruction::Return),
153 CoreInstruction::LoadLocal(idx, _) => out.push(NyarInstruction::LoadLocal(*idx as u8)),
154 CoreInstruction::StoreLocal(idx, _) => out.push(NyarInstruction::StoreLocal(*idx as u8)),
155 CoreInstruction::LoadArg(idx, _) => out.push(NyarInstruction::LoadLocal(*idx as u8)),
156 CoreInstruction::StoreArg(idx, _) => out.push(NyarInstruction::StoreLocal(*idx as u8)),
157 CoreInstruction::Pop => out.push(NyarInstruction::Pop),
158 CoreInstruction::Dup => out.push(NyarInstruction::Dup(0)),
159 CoreInstruction::Cmp(cond, ty) => {
160 if ty.is_integer() {
161 match cond {
162 CmpCondition::Eq => out.push(NyarInstruction::I64Eq),
163 CmpCondition::Ne => out.push(NyarInstruction::I64Ne),
164 CmpCondition::Lt => out.push(NyarInstruction::I64LtS),
165 CmpCondition::Le => out.push(NyarInstruction::I64LeS),
166 CmpCondition::Gt => out.push(NyarInstruction::I64GtS),
167 CmpCondition::Ge => out.push(NyarInstruction::I64GeS),
168 }
169 }
170 else if ty.is_float() {
171 match cond {
172 CmpCondition::Eq => out.push(NyarInstruction::F64Eq),
173 CmpCondition::Ne => out.push(NyarInstruction::F64Ne),
174 CmpCondition::Lt => out.push(NyarInstruction::F64Lt),
175 CmpCondition::Le => out.push(NyarInstruction::F64Le),
176 CmpCondition::Gt => out.push(NyarInstruction::F64Gt),
177 CmpCondition::Ge => out.push(NyarInstruction::F64Ge),
178 }
179 }
180 }
181 _ => {}
182 }
183 Ok(())
184 }
185
186 fn translate_managed(
187 &self,
188 inst: &ManagedInstruction,
189 out: &mut Vec<NyarInstruction>,
190 pool: &mut NyarConstantPool,
191 ) -> Result<()> {
192 match inst {
193 ManagedInstruction::Initiate(args) => out.push(NyarInstruction::Initiate(*args as u8)),
194 ManagedInstruction::Finalize => out.push(NyarInstruction::Finalize),
195 _ => {}
196 }
197 Ok(())
198 }
199
200 fn translate_terminator(
201 &self,
202 term: &crate::program::GaiaTerminator,
203 out: &mut Vec<NyarInstruction>,
204 pool: &mut NyarConstantPool,
205 ) -> Result<()> {
206 use crate::program::GaiaTerminator::*;
207 match term {
208 Return => out.push(NyarInstruction::Return),
209 Halt => out.push(NyarInstruction::Halt),
210 Jump(_) => {
211 out.push(NyarInstruction::Jump(0));
212 }
213 Branch { .. } => {
214 out.push(NyarInstruction::JumpIfFalse(0));
215 }
216 Call { callee, args_count, .. } => {
217 let idx = pool.add(NyarConstant::String(callee.clone()));
218 out.push(NyarInstruction::Call(idx, *args_count as u8));
219 }
220 }
221 Ok(())
222 }
223}