1use crate::opcode::Opcode;
2use crate::instruction::Instruction;
3use crate::lexer::{Token, ImmediateValue};
4use crate::debuginfo::{DebugInfo, RegisterHint, RegisterType};
5use std::collections::HashMap;
6use std::ops::Range;
7use crate::errors::CompileError;
8
9#[derive(Debug, Clone)]
10pub enum ASTNode {
11 Directive {
13 directive: Directive,
14 },
15 GlobalDecl {
16 global_decl: GlobalDecl,
17 },
18 EquDecl {
19 equ_decl: EquDecl,
20 },
21 ExternDecl {
22 extern_decl: ExternDecl,
23 },
24 RodataDecl {
25 rodata_decl: RodataDecl,
26 },
27 Label {
28 label: Label,
29 offset: u64,
30 },
31 ROData {
33 rodata: ROData,
34 offset: u64,
35 },
36 Instruction {
37 instruction: Instruction,
38 offset: u64,
39 },
40
41}
42
43#[derive(Debug, Clone)]
44pub struct Directive {
45 pub name: String,
46 pub args: Vec<Token>,
47 pub span: Range<usize>,
48}
49
50#[derive(Debug, Clone)]
51pub struct GlobalDecl {
52 pub entry_label: String,
53 pub span: Range<usize>,
54}
55
56impl GlobalDecl {
57 pub fn get_entry_label(&self) -> String {
58 self.entry_label.clone()
59 }
60}
61
62#[derive(Debug, Clone)]
63pub struct EquDecl {
64 pub name: String,
65 pub value: Token,
66 pub span: Range<usize>,
67}
68
69impl EquDecl {
70 pub fn get_name(&self) -> String {
71 self.name.clone()
72 }
73 pub fn get_val(&self) -> ImmediateValue {
74 match &self.value {
75 Token::ImmediateValue(val, _) => val.clone(),
76 _ => panic!("Invalid Equ declaration"),
77 }
78 }
79}
80
81#[derive(Debug, Clone)]
82pub struct ExternDecl {
83 pub args: Vec<Token>,
84 pub span: Range<usize>,
85}
86
87#[derive(Debug, Clone)]
88pub struct RodataDecl {
89 pub span: Range<usize>,
90}
91
92#[derive(Debug, Clone)]
93pub struct Label {
94 pub name: String,
95 pub span: Range<usize>,
96}
97
98#[derive(Debug, Clone)]
99pub struct ROData {
100 pub name: String,
101 pub args: Vec<Token>,
102 pub span: Range<usize>,
103}
104
105impl ROData {
106 fn validate_immediate_range(
108 value: &ImmediateValue,
109 min: i64,
110 max: i64,
111 span: Range<usize>,
112 ) -> Result<(), CompileError> {
113 match value {
114 ImmediateValue::Int(val) => {
115 if *val < min || *val > max {
116 return Err(CompileError::OutOfRangeLiteral { span, custom_label: None });
117 }
118 }
119 ImmediateValue::Addr(val) => {
120 if *val < min || *val > max {
121 return Err(CompileError::OutOfRangeLiteral { span, custom_label: None });
122 }
123 }
124 }
125 Ok(())
126 }
127
128 pub fn get_size(&self) -> u64 {
129 let size: u64;
130 match (
131 &self.args[0],
132 &self.args[1],
133 ) {
134 (Token::Directive(_, _), Token::StringLiteral(s, _)) => {
135 size = s.len() as u64;
136 }
137 (Token::Directive(directive, _), Token::VectorLiteral(values, _)) => {
138 match directive.as_str() {
139 "byte" => {
140 size = values.len() as u64 * 1;
141 }
142 "short" => {
143 size = values.len() as u64 * 2;
144 }
145 "int" | "long" => {
146 size = values.len() as u64 * 4;
147 }
148 "quad" => {
149 size = values.len() as u64 * 8;
150 }
151 _ => panic!("Invalid ROData declaration"),
152 }
153 }
154 _ => panic!("Invalid ROData declaration"),
155 }
156 size
157 }
158 pub fn verify(&self) -> Result<(), CompileError> {
159 match (
160 &self.args[0],
161 &self.args[1],
162 ) {
163 (Token::Directive(directive, directive_span), Token::StringLiteral(_, _)) => {
164 if directive.as_str() != "ascii" {
165 return Err(CompileError::InvalidRODataDirective { span: directive_span.clone(), custom_label: None });
166 }
167 }
168 (Token::Directive(directive, directive_span), Token::VectorLiteral(values, vector_literal_span)) => {
169 match directive.as_str() {
170 "byte" => {
171 for value in values {
172 Self::validate_immediate_range(value, i8::MIN as i64, i8::MAX as i64, vector_literal_span.clone())?;
173 }
174 }
175 "short" => {
176 for value in values {
177 Self::validate_immediate_range(value, i16::MIN as i64, i16::MAX as i64, vector_literal_span.clone())?;
178 }
179 }
180 "int" | "long" => {
181 for value in values {
182 Self::validate_immediate_range(value, i32::MIN as i64, i32::MAX as i64, vector_literal_span.clone())?;
183 }
184 }
185 "quad" => {
186 for value in values {
187 Self::validate_immediate_range(value, i64::MIN as i64, i64::MAX as i64, vector_literal_span.clone())?;
188 }
189 }
190 _ => {
191 return Err(CompileError::InvalidRODataDirective { span: directive_span.clone(), custom_label: None });
192 }
193 }
194 }
195 _ => {
196 return Err(CompileError::InvalidRodataDecl { span: self.span.clone(), custom_label: None });
197 }
198 }
199 Ok(())
200 }
201}
202
203impl ASTNode {
204 pub fn bytecode_with_debug_map(&self) -> Option<(Vec<u8>, HashMap<u64, DebugInfo>)> {
205 match self {
206 ASTNode::Instruction { instruction: Instruction { opcode, operands, span }, offset } => {
207 let mut bytes = Vec::new();
208 let mut debug_map = HashMap::new();
209 let mut debug_info = DebugInfo::new(span.clone());
210 bytes.push(opcode.to_bytecode()); if *opcode == Opcode::Call {
213 bytes.extend_from_slice(&[0x10, 0x00, 0x00]);
214 if let Some(Token::ImmediateValue(imm, _)) = operands.last() {
215 let imm32 = match imm {
216 ImmediateValue::Int(val) => *val as i32,
217 ImmediateValue::Addr(val) => *val as i32,
218 };
219 bytes.extend_from_slice(&imm32.to_le_bytes());
220 } else {
221 bytes.extend_from_slice(&[0xFF, 0xFF, 0xFF, 0xFF]);
223 }
224 } else if *opcode == Opcode::Lddw {
225 match &operands[..] {
226 [Token::Register(reg, _), Token::ImmediateValue(imm, _)] => {
227 bytes.push(*reg);
229
230 bytes.extend_from_slice(&[0, 0]);
232
233 let imm64 = match imm {
235 ImmediateValue::Int(val) => *val as i64,
236 ImmediateValue::Addr(val) => *val as i64,
237 };
238 bytes.extend_from_slice(&imm64.to_le_bytes()[..4]);
239 bytes.extend_from_slice(&[0, 0, 0, 0]);
240 bytes.extend_from_slice(&imm64.to_le_bytes()[4..8]);
241 }
242 _ => {}
243 }
244 } else {
245 match &operands[..] {
246 [Token::ImmediateValue(imm, _)] => {
247 bytes.push(0);
249
250 if *opcode == Opcode::Ja {
251 let imm16 = match imm {
253 ImmediateValue::Int(val) => *val as i16,
254 ImmediateValue::Addr(val) => *val as i16,
255 };
256 bytes.extend_from_slice(&imm16.to_le_bytes());
257 } else {
258 let imm32 = match imm {
260 ImmediateValue::Int(val) => *val as i32,
261 ImmediateValue::Addr(val) => *val as i32,
262 };
263 bytes.extend_from_slice(&imm32.to_le_bytes());
264 }
265 },
266
267 [Token::Register(reg, _)] => {
268 bytes.push(*reg);
269 bytes.extend_from_slice(&[0, 0, 0, 0, 0, 0]);
270 },
271
272 [Token::Register(reg, _), Token::ImmediateValue(imm, _)] => {
273 bytes.push(*reg);
275
276 bytes.extend_from_slice(&[0, 0]);
278
279 let imm32 = match imm {
281 ImmediateValue::Int(val) => *val as i32,
282 ImmediateValue::Addr(val) => {
283 debug_info.register_hint = RegisterHint {
284 register: *reg as usize,
285 register_type: RegisterType::Addr
286 };
287 *val as i32
288 }
289 };
290 bytes.extend_from_slice(&imm32.to_le_bytes());
291 },
292
293 [Token::Register(reg, _), Token::ImmediateValue(imm, _), Token::ImmediateValue(offset, _)] => {
294 bytes.push(*reg);
296
297 let offset16 = match offset {
299 ImmediateValue::Int(val) => *val as u16,
300 ImmediateValue::Addr(val) => *val as u16,
301 };
302 bytes.extend_from_slice(&offset16.to_le_bytes());
303
304 let imm32 = match imm {
306 ImmediateValue::Int(val) => *val as i32,
307 ImmediateValue::Addr(val) => {
308 debug_info.register_hint = RegisterHint {
309 register: *reg as usize,
310 register_type: RegisterType::Addr
311 };
312 *val as i32
313 }
314 };
315 bytes.extend_from_slice(&imm32.to_le_bytes());
316 },
317
318 [Token::Register(dst, _), Token::Register(src, _)] => {
319 let dst_num = dst;
321 let src_num = src;
322
323 let reg_byte = (src_num << 4) | dst_num;
325 bytes.push(reg_byte);
326 },
327 [Token::Register(dst, _), Token::Register(reg, _), Token::ImmediateValue(offset, _)] => {
328 let reg_byte = (reg << 4) | dst;
330 bytes.push(reg_byte);
331
332 let offset16 = match offset {
334 ImmediateValue::Int(val) => *val as u16,
335 ImmediateValue::Addr(val) => *val as u16,
336 };
337 bytes.extend_from_slice(&offset16.to_le_bytes());
338 },
339 [Token::Register(reg, _), Token::ImmediateValue(offset, _), Token::Register(dst, _)] => {
340 let reg_byte = (dst << 4) | reg;
342 bytes.push(reg_byte);
343
344 let offset16 = match offset {
346 ImmediateValue::Int(val) => *val as u16,
347 ImmediateValue::Addr(val) => *val as u16,
348 };
349 bytes.extend_from_slice(&offset16.to_le_bytes());
350 }
351
352 _ => {}
353 }
354 }
355
356 let target_len = if *opcode == Opcode::Lddw { 16 } else { 8 };
358 while bytes.len() < target_len {
359 bytes.push(0);
360 }
361
362 debug_map.insert(*offset, debug_info);
363
364 Some((bytes, debug_map))
365 },
366 ASTNode::ROData { rodata: ROData { name: _, args, .. }, .. } => {
367 let mut bytes = Vec::new();
368 let debug_map = HashMap::<u64, DebugInfo>::new();
369 match (
370 &args[0],
371 &args[1],
372 ) {
373 (Token::Directive(_, _), Token::StringLiteral(str_literal, _)) => {
374 let str_bytes = str_literal.as_bytes().to_vec();
375 bytes.extend(str_bytes);
376 }
377 (Token::Directive(directive, _), Token::VectorLiteral(values, _)) => {
378 if directive == "byte" {
379 for value in values {
380 let imm8 = match value {
381 ImmediateValue::Int(val) => *val as i8,
382 ImmediateValue::Addr(val) => *val as i8,
383 };
384 bytes.extend(imm8.to_le_bytes());
385 }
386 } else if directive == "short" {
387 for value in values {
388 let imm16 = match value {
389 ImmediateValue::Int(val) => *val as i16,
390 ImmediateValue::Addr(val) => *val as i16,
391 };
392 bytes.extend(imm16.to_le_bytes());
393 }
394 } else if directive == "int" || directive == "long" {
395 for value in values {
396 let imm32 = match value {
397 ImmediateValue::Int(val) => *val as i32,
398 ImmediateValue::Addr(val) => *val as i32,
399 };
400 bytes.extend(imm32.to_le_bytes());
401 }
402 } else if directive == "quad" {
403 for value in values {
404 let imm64 = match value {
405 ImmediateValue::Int(val) => *val as i64,
406 ImmediateValue::Addr(val) => *val as i64,
407 };
408 bytes.extend(imm64.to_le_bytes());
409 }
410 } else {
411 panic!("Invalid ROData declaration");
412 }
413 }
414
415 _ => panic!("Invalid ROData declaration"),
416 }
417 Some((bytes, debug_map))
418 },
419 _ => None
420 }
421 }
422
423 pub fn bytecode(&self) -> Option<Vec<u8>> {
425 self.bytecode_with_debug_map().map(|(bytes, _)| bytes)
426 }
427}