1use crate::ast::{ArraySize, AssignTarget, BinOp, Expr, Function, Item, Pattern, Program, Stmt, Type, UnaryOp};
5use crate::errors::{CompileError, Result};
6use std::collections::HashMap;
7use std::path::PathBuf;
8
9pub struct LLVMTextBackend {
11 module_name: String,
12 string_constants: Vec<(String, String)>, string_counter: i32,
16 var_map: HashMap<String, VarInfo>,
18 ssa_counter: i32,
20 label_counter: i32,
22}
23
24#[derive(Clone, Debug)]
25struct VarInfo {
26 ptr: String, ty: String, #[allow(dead_code)]
29 is_param: bool, }
31
32impl LLVMTextBackend {
33 pub fn new(module_name: &str) -> Result<Self> {
34 Ok(Self {
35 module_name: module_name.to_string(),
36 string_constants: Vec::new(),
37 string_counter: 0,
38 var_map: HashMap::new(),
39 ssa_counter: 0,
40 label_counter: 0,
41 })
42 }
43
44 fn fresh_ssa(&mut self) -> String {
46 let reg = format!("%{}", self.ssa_counter);
47 self.ssa_counter += 1;
48 reg
49 }
50
51 fn fresh_label(&mut self, prefix: &str) -> String {
53 let label = format!("{}{}", prefix, self.label_counter);
54 self.label_counter += 1;
55 label
56 }
57
58 pub fn compile(&mut self, program: &Program) -> Result<String> {
60 self.collect_string_constants(program)?;
62
63 let mut ir = String::new();
65
66 ir.push_str(&format!("; ModuleID = '{}'\n", self.module_name));
68 ir.push_str("source_filename = \"palladium\"\n");
69
70 ir.push_str("target datalayout = \"e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128\"\n");
72 ir.push_str("target triple = \"x86_64-pc-linux-gnu\"\n\n");
73
74 ir.push_str("; External function declarations\n");
76 ir.push_str("declare i32 @printf(i8*, ...)\n");
77 ir.push_str("declare i8* @malloc(i64)\n");
78 ir.push_str("declare void @free(i8*)\n");
79 ir.push_str("declare i64 @strlen(i8*)\n");
80 ir.push_str("declare i8* @strcpy(i8*, i8*)\n");
81 ir.push_str("declare i8* @strcat(i8*, i8*)\n");
82 ir.push_str("declare i32 @strcmp(i8*, i8*)\n\n");
83
84 ir.push_str("; String constants\n");
86 ir.push_str(
87 "@.str_fmt = private unnamed_addr constant [4 x i8] c\"%s\\0A\\00\", align 1\n",
88 );
89 ir.push_str(
90 "@.int_fmt = private unnamed_addr constant [6 x i8] c\"%lld\\0A\\00\", align 1\n",
91 );
92
93 for (name, value) in &self.string_constants {
95 let escaped = value
96 .replace("\\", "\\\\")
97 .replace("\"", "\\\"")
98 .replace("\n", "\\n");
99 ir.push_str(&format!(
100 "{} = private unnamed_addr constant [{} x i8] c\"{}\\00\", align 1\n",
101 name,
102 value.len() + 1,
103 escaped
104 ));
105 }
106 ir.push('\n');
107
108 for item in &program.items {
110 match item {
111 Item::Function(func) => {
112 self.ssa_counter = 0; self.var_map.clear();
114 ir.push_str(&self.generate_function(func)?);
115 ir.push('\n');
116 }
117 _ => {
118 }
120 }
121 }
122
123 Ok(ir)
124 }
125
126 fn collect_string_constants(&mut self, program: &Program) -> Result<()> {
128 for item in &program.items {
129 if let Item::Function(func) = item {
130 self.collect_strings_from_stmts(&func.body);
131 }
132 }
133 Ok(())
134 }
135
136 fn collect_strings_from_stmts(&mut self, stmts: &[Stmt]) {
137 for stmt in stmts {
138 match stmt {
139 Stmt::Expr(expr) | Stmt::Return(Some(expr)) => {
140 self.collect_strings_from_expr(expr);
141 }
142 Stmt::Let { value, .. } => {
143 self.collect_strings_from_expr(value);
144 }
145 Stmt::If {
146 condition,
147 then_branch,
148 else_branch,
149 ..
150 } => {
151 self.collect_strings_from_expr(condition);
152 self.collect_strings_from_stmts(then_branch);
153 if let Some(else_stmts) = else_branch {
154 self.collect_strings_from_stmts(else_stmts);
155 }
156 }
157 Stmt::While {
158 condition, body, ..
159 } => {
160 self.collect_strings_from_expr(condition);
161 self.collect_strings_from_stmts(body);
162 }
163 Stmt::For { iter, body, .. } => {
164 self.collect_strings_from_expr(iter);
165 self.collect_strings_from_stmts(body);
166 }
167 Stmt::Assign { value, .. } => {
168 self.collect_strings_from_expr(value);
169 }
170 _ => {}
171 }
172 }
173 }
174
175 fn collect_strings_from_expr(&mut self, expr: &Expr) {
176 match expr {
177 Expr::String(s) => {
178 let exists = self.string_constants.iter().any(|(_, v)| v == s);
180 if !exists {
181 let name = format!("@.str.{}", self.string_counter);
182 self.string_counter += 1;
183 self.string_constants.push((name, s.clone()));
184 }
185 }
186 Expr::Binary { left, right, .. } => {
187 self.collect_strings_from_expr(left);
188 self.collect_strings_from_expr(right);
189 }
190 Expr::Call { func, args, .. } => {
191 self.collect_strings_from_expr(func);
192 for arg in args {
193 self.collect_strings_from_expr(arg);
194 }
195 }
196 Expr::ArrayLiteral { elements, .. } => {
197 for elem in elements {
198 self.collect_strings_from_expr(elem);
199 }
200 }
201 Expr::Index { array, index, .. } => {
202 self.collect_strings_from_expr(array);
203 self.collect_strings_from_expr(index);
204 }
205 Expr::Range { start, end, .. } => {
206 self.collect_strings_from_expr(start);
207 self.collect_strings_from_expr(end);
208 }
209 _ => {}
210 }
211 }
212
213 fn generate_function(&mut self, func: &Function) -> Result<String> {
215 let mut ir = String::new();
216
217 let ret_type = self.type_to_llvm(&func.return_type);
219 ir.push_str(&format!("define {} @{}(", ret_type, func.name));
220
221 for (i, param) in func.params.iter().enumerate() {
223 if i > 0 {
224 ir.push_str(", ");
225 }
226 let param_type = self.type_to_llvm(&Some(param.ty.clone()));
227 let param_reg = format!("%{}", param.name);
228 ir.push_str(&format!("{} {}", param_type, param_reg));
229 }
230
231 ir.push_str(") {\n");
232 ir.push_str("entry:\n");
233
234 for param in &func.params {
236 let param_type = self.type_to_llvm(&Some(param.ty.clone()));
237 let param_reg = format!("%{}", param.name);
238 let alloca = self.fresh_ssa();
239
240 ir.push_str(&format!(" {} = alloca {}\n", alloca, param_type));
241 ir.push_str(&format!(
242 " store {} {}, {}* {}\n",
243 param_type, param_reg, param_type, alloca
244 ));
245
246 self.var_map.insert(
247 param.name.clone(),
248 VarInfo {
249 ptr: alloca,
250 ty: param_type,
251 is_param: true,
252 },
253 );
254 }
255
256 for stmt in &func.body {
258 ir.push_str(&self.generate_statement(stmt)?);
259 }
260
261 if func.return_type.is_none() && !func.body.iter().any(|s| matches!(s, Stmt::Return(_))) {
263 ir.push_str(" ret void\n");
264 }
265
266 ir.push_str("}\n");
267
268 Ok(ir)
269 }
270
271 #[allow(clippy::only_used_in_recursion)]
273 fn type_to_llvm(&self, ty: &Option<Type>) -> String {
274 match ty {
275 None => "void".to_string(),
276 Some(Type::I32) => "i32".to_string(),
277 Some(Type::I64) => "i64".to_string(),
278 Some(Type::U32) => "i32".to_string(),
279 Some(Type::U64) => "i64".to_string(),
280 Some(Type::Bool) => "i1".to_string(),
281 Some(Type::String) => "i8*".to_string(),
282 Some(Type::Unit) => "void".to_string(),
283 Some(Type::Array(elem_ty, size)) => {
284 match size {
285 ArraySize::Literal(n) => {
286 format!(
287 "[{} x {}]",
288 n,
289 self.type_to_llvm(&Some(elem_ty.as_ref().clone()))
290 )
291 }
292 _ => {
293 format!("{}*", self.type_to_llvm(&Some(elem_ty.as_ref().clone())))
295 }
296 }
297 }
298 _ => "i8*".to_string(), }
300 }
301
302 fn generate_statement(&mut self, stmt: &Stmt) -> Result<String> {
304 let mut ir = String::new();
305
306 match stmt {
307 Stmt::Expr(expr) => {
308 let (expr_ir, _) = self.generate_expression(expr)?;
309 ir.push_str(&expr_ir);
310 }
311
312 Stmt::Let {
313 name, value, ty, ..
314 } => {
315 let (expr_ir, result_var, result_type) = self.generate_expression_typed(value)?;
317 ir.push_str(&expr_ir);
318
319 let alloca_type = if let Some(t) = ty {
321 self.type_to_llvm(&Some(t.clone()))
322 } else {
323 self.infer_expr_type(value)
325 };
326
327 let ptr = self.fresh_ssa();
329 ir.push_str(&format!(" {} = alloca {}\n", ptr, alloca_type));
330
331 if alloca_type.starts_with('[') && alloca_type.ends_with(']') {
333 if matches!(value, Expr::ArrayLiteral { .. }) || matches!(value, Expr::ArrayRepeat { .. }) {
336 let array_size = if let Some(start) = alloca_type.find('[') {
339 if let Some(end) = alloca_type[start+1..].find(' ') {
340 alloca_type[start+1..start+1+end].parse::<usize>().unwrap_or(1)
341 } else {
342 1
343 }
344 } else {
345 1
346 };
347
348 for i in 0..array_size {
350 let src_ptr = self.fresh_ssa();
351 let dst_ptr = self.fresh_ssa();
352 let val = self.fresh_ssa();
353
354 ir.push_str(&format!(
355 " {} = getelementptr {}, {}* {}, i64 0, i64 {}\n",
356 src_ptr, alloca_type, alloca_type, result_var, i
357 ));
358 ir.push_str(&format!(
359 " {} = getelementptr {}, {}* {}, i64 0, i64 {}\n",
360 dst_ptr, alloca_type, alloca_type, ptr, i
361 ));
362 ir.push_str(&format!(
363 " {} = load i64, i64* {}\n",
364 val, src_ptr
365 ));
366 ir.push_str(&format!(
367 " store i64 {}, i64* {}\n",
368 val, dst_ptr
369 ));
370 }
371 } else {
372 ir.push_str(" ; TODO: Proper array copy for non-literal arrays\n");
375 }
376 } else {
377 ir.push_str(&format!(
378 " store {} {}, {}* {}\n",
379 result_type, result_var, alloca_type, ptr
380 ));
381 }
382
383 self.var_map.insert(
385 name.clone(),
386 VarInfo {
387 ptr,
388 ty: alloca_type,
389 is_param: false,
390 },
391 );
392 }
393
394 Stmt::Return(Some(expr)) => {
395 let (expr_ir, result) = self.generate_expression(expr)?;
396 ir.push_str(&expr_ir);
397
398 let ret_type = self.infer_expr_type(expr);
400 ir.push_str(&format!(" ret {} {}\n", ret_type, result));
401 }
402
403 Stmt::Return(None) => {
404 ir.push_str(" ret void\n");
405 }
406
407 Stmt::If {
408 condition,
409 then_branch,
410 else_branch,
411 ..
412 } => {
413 let then_label = self.fresh_label("then");
414 let else_label = self.fresh_label("else");
415 let end_label = self.fresh_label("endif");
416
417 let (cond_ir, cond_result) = self.generate_expression(condition)?;
418 ir.push_str(&cond_ir);
419
420 if else_branch.is_some() {
421 ir.push_str(&format!(
422 " br i1 {}, label %{}, label %{}\n",
423 cond_result, then_label, else_label
424 ));
425 } else {
426 ir.push_str(&format!(
427 " br i1 {}, label %{}, label %{}\n",
428 cond_result, then_label, end_label
429 ));
430 }
431
432 ir.push_str(&format!("{}:\n", then_label));
434 for stmt in then_branch {
435 ir.push_str(&self.generate_statement(stmt)?);
436 }
437 ir.push_str(&format!(" br label %{}\n", end_label));
438
439 if let Some(else_stmts) = else_branch {
441 ir.push_str(&format!("{}:\n", else_label));
442 for stmt in else_stmts {
443 ir.push_str(&self.generate_statement(stmt)?);
444 }
445 ir.push_str(&format!(" br label %{}\n", end_label));
446 }
447
448 ir.push_str(&format!("{}:\n", end_label));
450 }
451
452 Stmt::While {
453 condition, body, ..
454 } => {
455 let cond_label = self.fresh_label("while_cond");
456 let body_label = self.fresh_label("while_body");
457 let end_label = self.fresh_label("while_end");
458
459 ir.push_str(&format!(" br label %{}\n", cond_label));
461
462 ir.push_str(&format!("{}:\n", cond_label));
464 let (cond_ir, cond_result) = self.generate_expression(condition)?;
465 ir.push_str(&cond_ir);
466 ir.push_str(&format!(
467 " br i1 {}, label %{}, label %{}\n",
468 cond_result, body_label, end_label
469 ));
470
471 ir.push_str(&format!("{}:\n", body_label));
473 for stmt in body {
474 ir.push_str(&self.generate_statement(stmt)?);
475 }
476 ir.push_str(&format!(" br label %{}\n", cond_label));
477
478 ir.push_str(&format!("{}:\n", end_label));
480 }
481
482 Stmt::For {
483 var, iter, body, ..
484 } => {
485 match iter {
486 Expr::Range { start, end, .. } => {
488 let (start_ir, start_val) = self.generate_expression(start)?;
489 let (end_ir, end_val) = self.generate_expression(end)?;
490 ir.push_str(&start_ir);
491 ir.push_str(&end_ir);
492
493 let loop_var_ptr = self.fresh_ssa();
495 ir.push_str(&format!(" {} = alloca i64\n", loop_var_ptr));
496 ir.push_str(&format!(
497 " store i64 {}, i64* {}\n",
498 start_val, loop_var_ptr
499 ));
500
501 self.var_map.insert(
502 var.clone(),
503 VarInfo {
504 ptr: loop_var_ptr.clone(),
505 ty: "i64".to_string(),
506 is_param: false,
507 },
508 );
509
510 let cond_label = self.fresh_label("for_cond");
511 let body_label = self.fresh_label("for_body");
512 let inc_label = self.fresh_label("for_inc");
513 let end_label = self.fresh_label("for_end");
514
515 ir.push_str(&format!(" br label %{}\n", cond_label));
517
518 ir.push_str(&format!("{}:\n", cond_label));
520 let i_val = self.fresh_ssa();
521 ir.push_str(&format!(" {} = load i64, i64* {}\n", i_val, loop_var_ptr));
522 let cmp = self.fresh_ssa();
523 ir.push_str(&format!(
524 " {} = icmp slt i64 {}, {}\n",
525 cmp, i_val, end_val
526 ));
527 ir.push_str(&format!(
528 " br i1 {}, label %{}, label %{}\n",
529 cmp, body_label, end_label
530 ));
531
532 ir.push_str(&format!("{}:\n", body_label));
534 for stmt in body {
535 ir.push_str(&self.generate_statement(stmt)?);
536 }
537 ir.push_str(&format!(" br label %{}\n", inc_label));
538
539 ir.push_str(&format!("{}:\n", inc_label));
541 let curr_val = self.fresh_ssa();
542 let next_val = self.fresh_ssa();
543 ir.push_str(&format!(
544 " {} = load i64, i64* {}\n",
545 curr_val, loop_var_ptr
546 ));
547 ir.push_str(&format!(" {} = add i64 {}, 1\n", next_val, curr_val));
548 ir.push_str(&format!(
549 " store i64 {}, i64* {}\n",
550 next_val, loop_var_ptr
551 ));
552 ir.push_str(&format!(" br label %{}\n", cond_label));
553
554 ir.push_str(&format!("{}:\n", end_label));
556 }
557
558 Expr::Ident(array_name) => {
560 if let Some(var_info) = self.var_map.get(array_name).cloned() {
561 if var_info.ty.starts_with('[') && var_info.ty.contains(" x ") {
563 let array_type = &var_info.ty;
565 let size_end = array_type.find(" x ").unwrap();
566 let size: usize = array_type[1..size_end].parse().unwrap_or(0);
567 let elem_type = array_type[size_end + 3..array_type.len() - 1].to_string();
568
569 let idx_ptr = self.fresh_ssa();
571 ir.push_str(&format!(" {} = alloca i64\n", idx_ptr));
572 ir.push_str(&format!(" store i64 0, i64* {}\n", idx_ptr));
573
574 let loop_var_ptr = self.fresh_ssa();
576 ir.push_str(&format!(" {} = alloca {}\n", loop_var_ptr, elem_type));
577
578 self.var_map.insert(
579 var.clone(),
580 VarInfo {
581 ptr: loop_var_ptr.clone(),
582 ty: elem_type.clone(),
583 is_param: false,
584 },
585 );
586
587 let cond_label = self.fresh_label("for_cond");
588 let body_label = self.fresh_label("for_body");
589 let inc_label = self.fresh_label("for_inc");
590 let end_label = self.fresh_label("for_end");
591
592 ir.push_str(&format!(" br label %{}\n", cond_label));
594
595 ir.push_str(&format!("{}:\n", cond_label));
597 let idx_val = self.fresh_ssa();
598 ir.push_str(&format!(" {} = load i64, i64* {}\n", idx_val, idx_ptr));
599 let cmp = self.fresh_ssa();
600 ir.push_str(&format!(" {} = icmp slt i64 {}, {}\n", cmp, idx_val, size));
601 ir.push_str(&format!(
602 " br i1 {}, label %{}, label %{}\n",
603 cmp, body_label, end_label
604 ));
605
606 ir.push_str(&format!("{}:\n", body_label));
608 let elem_ptr = self.fresh_ssa();
609 let elem_val = self.fresh_ssa();
610 ir.push_str(&format!(
611 " {} = getelementptr {}, {}* {}, i64 0, i64 {}\n",
612 elem_ptr, array_type, array_type, var_info.ptr, idx_val
613 ));
614 ir.push_str(&format!(
615 " {} = load {}, {}* {}\n",
616 elem_val, elem_type, elem_type, elem_ptr
617 ));
618 ir.push_str(&format!(
619 " store {} {}, {}* {}\n",
620 elem_type, elem_val, elem_type, loop_var_ptr
621 ));
622
623 for stmt in body {
625 ir.push_str(&self.generate_statement(stmt)?);
626 }
627 ir.push_str(&format!(" br label %{}\n", inc_label));
628
629 ir.push_str(&format!("{}:\n", inc_label));
631 let curr_idx = self.fresh_ssa();
632 let next_idx = self.fresh_ssa();
633 ir.push_str(&format!(" {} = load i64, i64* {}\n", curr_idx, idx_ptr));
634 ir.push_str(&format!(" {} = add i64 {}, 1\n", next_idx, curr_idx));
635 ir.push_str(&format!(" store i64 {}, i64* {}\n", next_idx, idx_ptr));
636 ir.push_str(&format!(" br label %{}\n", cond_label));
637
638 ir.push_str(&format!("{}:\n", end_label));
640 } else {
641 return Err(CompileError::Generic(format!(
642 "Cannot iterate over non-array type: {}",
643 var_info.ty
644 )));
645 }
646 } else {
647 return Err(CompileError::Generic(format!(
648 "Undefined variable: {}",
649 array_name
650 )));
651 }
652 }
653
654 Expr::ArrayLiteral { elements, .. } => {
656 let elem_type = "i64"; let array_type = format!("[{} x {}]", elements.len(), elem_type);
659 let temp_array = self.fresh_ssa();
660
661 ir.push_str(&format!(" {} = alloca {}\n", temp_array, array_type));
662
663 for (i, elem) in elements.iter().enumerate() {
665 let (elem_ir, elem_val) = self.generate_expression(elem)?;
666 ir.push_str(&elem_ir);
667 let ptr = self.fresh_ssa();
668 ir.push_str(&format!(
669 " {} = getelementptr {}, {}* {}, i64 0, i64 {}\n",
670 ptr, array_type, array_type, temp_array, i
671 ));
672 ir.push_str(&format!(
673 " store {} {}, {}* {}\n",
674 elem_type, elem_val, elem_type, ptr
675 ));
676 }
677
678 let idx_ptr = self.fresh_ssa();
681 ir.push_str(&format!(" {} = alloca i64\n", idx_ptr));
682 ir.push_str(&format!(" store i64 0, i64* {}\n", idx_ptr));
683
684 let loop_var_ptr = self.fresh_ssa();
685 ir.push_str(&format!(" {} = alloca {}\n", loop_var_ptr, elem_type));
686
687 self.var_map.insert(
688 var.clone(),
689 VarInfo {
690 ptr: loop_var_ptr.clone(),
691 ty: elem_type.to_string(),
692 is_param: false,
693 },
694 );
695
696 let cond_label = self.fresh_label("for_cond");
697 let body_label = self.fresh_label("for_body");
698 let inc_label = self.fresh_label("for_inc");
699 let end_label = self.fresh_label("for_end");
700
701 ir.push_str(&format!(" br label %{}\n", cond_label));
702
703 ir.push_str(&format!("{}:\n", cond_label));
704 let idx_val = self.fresh_ssa();
705 ir.push_str(&format!(" {} = load i64, i64* {}\n", idx_val, idx_ptr));
706 let cmp = self.fresh_ssa();
707 ir.push_str(&format!(" {} = icmp slt i64 {}, {}\n", cmp, idx_val, elements.len()));
708 ir.push_str(&format!(
709 " br i1 {}, label %{}, label %{}\n",
710 cmp, body_label, end_label
711 ));
712
713 ir.push_str(&format!("{}:\n", body_label));
714 let elem_ptr = self.fresh_ssa();
715 let elem_val = self.fresh_ssa();
716 ir.push_str(&format!(
717 " {} = getelementptr {}, {}* {}, i64 0, i64 {}\n",
718 elem_ptr, array_type, array_type, temp_array, idx_val
719 ));
720 ir.push_str(&format!(
721 " {} = load {}, {}* {}\n",
722 elem_val, elem_type, elem_type, elem_ptr
723 ));
724 ir.push_str(&format!(
725 " store {} {}, {}* {}\n",
726 elem_type, elem_val, elem_type, loop_var_ptr
727 ));
728
729 for stmt in body {
730 ir.push_str(&self.generate_statement(stmt)?);
731 }
732 ir.push_str(&format!(" br label %{}\n", inc_label));
733
734 ir.push_str(&format!("{}:\n", inc_label));
735 let curr_idx = self.fresh_ssa();
736 let next_idx = self.fresh_ssa();
737 ir.push_str(&format!(" {} = load i64, i64* {}\n", curr_idx, idx_ptr));
738 ir.push_str(&format!(" {} = add i64 {}, 1\n", next_idx, curr_idx));
739 ir.push_str(&format!(" store i64 {}, i64* {}\n", next_idx, idx_ptr));
740 ir.push_str(&format!(" br label %{}\n", cond_label));
741
742 ir.push_str(&format!("{}:\n", end_label));
743 }
744
745 _ => {
746 return Err(CompileError::Generic(
747 "Unsupported iterator type in for loop".to_string(),
748 ));
749 }
750 }
751 }
752
753 Stmt::Assign { target, value, .. } => {
754 let (value_ir, value_var, value_type) = self.generate_expression_typed(value)?;
755 ir.push_str(&value_ir);
756
757 match target {
758 AssignTarget::Ident(name) => {
759 if let Some(var_info) = self.var_map.get(name).cloned() {
760 ir.push_str(&format!(
761 " store {} {}, {}* {}\n",
762 value_type, value_var, var_info.ty, var_info.ptr
763 ));
764 } else {
765 return Err(CompileError::Generic(format!(
766 "Undefined variable: {}",
767 name
768 )));
769 }
770 }
771 AssignTarget::Index { array, index } => {
772 let (index_ir, index_var) = self.generate_expression(index)?;
773 ir.push_str(&index_ir);
774
775 if let Expr::Ident(array_name) = array.as_ref() {
776 if let Some(var_info) = self.var_map.get(array_name).cloned() {
777 let ptr = self.fresh_ssa();
778 if let Some(array_type) = var_info
780 .ty
781 .strip_prefix('[')
782 .and_then(|s| s.find(" x "))
783 .map(|i| &var_info.ty[1..i])
784 {
785 let _size: usize = array_type.parse().unwrap_or(5);
786 ir.push_str(&format!(
787 " {} = getelementptr {}, {}* {}, i64 0, i64 {}\n",
788 ptr, var_info.ty, var_info.ty, var_info.ptr, index_var
789 ));
790 ir.push_str(&format!(
791 " store {} {}, {}* {}\n",
792 value_type, value_var, value_type, ptr
793 ));
794 }
795 }
796 }
797 }
798 AssignTarget::FieldAccess { object, field: _ } => {
799 let (obj_ir, obj_var) = self.generate_expression(object)?;
801 ir.push_str(&obj_ir);
802
803 let field_idx = 0; let field_ptr = self.fresh_ssa();
806
807 let struct_type = if let Expr::Ident(name) = object.as_ref() {
809 if let Some(var_info) = self.var_map.get(name) {
810 var_info.ty.clone()
811 } else {
812 "%struct.Unknown".to_string()
813 }
814 } else {
815 "%struct.Unknown".to_string()
816 };
817
818 ir.push_str(&format!(
819 " {} = getelementptr {}, {}* {}, i32 0, i32 {}\n",
820 field_ptr, struct_type, struct_type, obj_var, field_idx
821 ));
822 ir.push_str(&format!(
823 " store {} {}, {}* {}\n",
824 value_type, value_var, value_type, field_ptr
825 ));
826 }
827 AssignTarget::Deref { expr } => {
828 let (ptr_ir, ptr_var) = self.generate_expression(expr)?;
829 ir.push_str(&ptr_ir);
830 ir.push_str(&format!(
831 " store {} {}, {}* {}\n",
832 value_type, value_var, value_type, ptr_var
833 ));
834 }
835 }
836 }
837
838 Stmt::Break { .. } => {
839 ir.push_str(" ; TODO: Implement break with proper loop context\n");
842 ir.push_str(" br label %loop_end_placeholder\n");
843 }
844
845 Stmt::Continue { .. } => {
846 ir.push_str(" ; TODO: Implement continue with proper loop context\n");
849 ir.push_str(" br label %loop_inc_placeholder\n");
850 }
851
852 Stmt::Match { expr, arms, .. } => {
853 let (expr_ir, _expr_var) = self.generate_expression(expr)?;
855 ir.push_str(&expr_ir);
856
857 let end_label = self.fresh_label("match_end");
858
859 for (i, arm) in arms.iter().enumerate() {
862 let arm_label = self.fresh_label(&format!("match_arm{}", i));
863 let next_label = if i + 1 < arms.len() {
864 self.fresh_label(&format!("match_arm{}", i + 1))
865 } else {
866 end_label.clone()
867 };
868
869 match &arm.pattern {
871 Pattern::Wildcard => {
872 ir.push_str(&format!(" br label %{}\n", arm_label));
874 }
875 Pattern::Ident(_) => {
876 ir.push_str(&format!(" br label %{}\n", arm_label));
878 }
879 _ => {
880 ir.push_str(" ; TODO: Complex pattern matching\n");
882 ir.push_str(&format!(" br label %{}\n", next_label));
883 }
884 }
885
886 ir.push_str(&format!("{}:\n", arm_label));
887 for stmt in &arm.body {
888 ir.push_str(&self.generate_statement(stmt)?);
889 }
890 ir.push_str(&format!(" br label %{}\n", end_label));
891 }
892
893 ir.push_str(&format!("{}:\n", end_label));
894 }
895
896 Stmt::Unsafe { body, .. } => {
897 ir.push_str(" ; Unsafe block\n");
900 for stmt in body {
901 ir.push_str(&self.generate_statement(stmt)?);
902 }
903 }
904 }
905
906 Ok(ir)
907 }
908
909 fn generate_expression_typed(&mut self, expr: &Expr) -> Result<(String, String, String)> {
911 let (ir, val) = self.generate_expression(expr)?;
912 let ty = self.infer_expr_type(expr);
913 Ok((ir, val, ty))
914 }
915
916 fn generate_expression(&mut self, expr: &Expr) -> Result<(String, String)> {
919 let mut ir = String::new();
920
921 match expr {
922 Expr::Integer(n) => Ok((String::new(), n.to_string())),
923
924 Expr::Bool(b) => Ok((String::new(), if *b { "1" } else { "0" }.to_string())),
925
926 Expr::String(s) => {
927 let const_name = self
929 .string_constants
930 .iter()
931 .find(|(_, v)| v == s)
932 .map(|(n, _)| n.clone())
933 .unwrap_or_else(|| "@.str.unknown".to_string());
934
935 let ptr_var = self.fresh_ssa();
936 ir.push_str(&format!(
937 " {} = getelementptr [{} x i8], [{} x i8]* {}, i32 0, i32 0\n",
938 ptr_var,
939 s.len() + 1,
940 s.len() + 1,
941 const_name
942 ));
943
944 Ok((ir, ptr_var))
945 }
946
947 Expr::Ident(name) => {
948 if let Some(var_info) = self.var_map.get(name).cloned() {
949 if var_info.ty.starts_with('[') && var_info.ty.ends_with(']') {
951 Ok((ir, var_info.ptr))
953 } else {
954 let load_var = self.fresh_ssa();
955 ir.push_str(&format!(
956 " {} = load {}, {}* {}\n",
957 load_var, var_info.ty, var_info.ty, var_info.ptr
958 ));
959 Ok((ir, load_var))
960 }
961 } else {
962 Err(CompileError::UndefinedVariable {
963 name: name.clone(),
964 span: None,
965 })
966 }
967 }
968
969 Expr::Binary {
970 left, op, right, ..
971 } => {
972 let (left_ir, left_var) = self.generate_expression(left)?;
973 let (right_ir, right_var) = self.generate_expression(right)?;
974
975 ir.push_str(&left_ir);
976 ir.push_str(&right_ir);
977
978 let result_var = self.fresh_ssa();
979
980 let op_str = match op {
981 BinOp::Add => "add",
982 BinOp::Sub => "sub",
983 BinOp::Mul => "mul",
984 BinOp::Div => "sdiv",
985 BinOp::Mod => "srem",
986 BinOp::Lt => "icmp slt",
987 BinOp::Le => "icmp sle",
988 BinOp::Gt => "icmp sgt",
989 BinOp::Ge => "icmp sge",
990 BinOp::Eq => "icmp eq",
991 BinOp::Ne => "icmp ne",
992 _ => {
993 return Err(CompileError::Generic(
994 "Unsupported binary operator".to_string(),
995 ))
996 }
997 };
998
999 let op_type = "i64";
1002
1003 ir.push_str(&format!(
1004 " {} = {} {} {}, {}\n",
1005 result_var, op_str, op_type, left_var, right_var
1006 ));
1007
1008 Ok((ir, result_var))
1009 }
1010
1011 Expr::ArrayLiteral { elements, .. } => {
1012 let elem_type = "i64"; let array_type = format!("[{} x {}]", elements.len(), elem_type);
1015
1016 let array_var = self.fresh_ssa();
1018 ir.push_str(&format!(" {} = alloca {}\n", array_var, array_type));
1019
1020 for (i, elem) in elements.iter().enumerate() {
1022 let (elem_ir, elem_val) = self.generate_expression(elem)?;
1023 ir.push_str(&elem_ir);
1024
1025 let ptr = self.fresh_ssa();
1026 ir.push_str(&format!(
1027 " {} = getelementptr {}, {}* {}, i64 0, i64 {}\n",
1028 ptr, array_type, array_type, array_var, i
1029 ));
1030 ir.push_str(&format!(
1031 " store {} {}, {}* {}\n",
1032 elem_type, elem_val, elem_type, ptr
1033 ));
1034 }
1035
1036 Ok((ir, array_var))
1037 }
1038
1039 Expr::Index { array, index, .. } => {
1040 let (idx_ir, idx_var) = self.generate_expression(index)?;
1041 ir.push_str(&idx_ir);
1042
1043 if let Expr::Ident(name) = array.as_ref() {
1045 if let Some(var_info) = self.var_map.get(name).cloned() {
1046 let ptr = self.fresh_ssa();
1047 let val = self.fresh_ssa();
1048
1049 ir.push_str(&format!(
1051 " {} = getelementptr {}, {}* {}, i64 0, i64 {}\n",
1052 ptr, var_info.ty, var_info.ty, var_info.ptr, idx_var
1053 ));
1054 ir.push_str(&format!(" {} = load i64, i64* {}\n", val, ptr));
1055
1056 Ok((ir, val))
1057 } else {
1058 Err(CompileError::Generic(format!("Undefined array: {}", name)))
1059 }
1060 } else {
1061 let (array_ir, array_var) = self.generate_expression(array)?;
1063 ir.push_str(&array_ir);
1064
1065 let ptr = self.fresh_ssa();
1066 let val = self.fresh_ssa();
1067
1068 ir.push_str(&format!(
1070 " {} = getelementptr [5 x i64], [5 x i64]* {}, i64 0, i64 {}\n",
1071 ptr, array_var, idx_var
1072 ));
1073 ir.push_str(&format!(" {} = load i64, i64* {}\n", val, ptr));
1074
1075 Ok((ir, val))
1076 }
1077 }
1078
1079 Expr::Call { func, args, .. } => {
1080 if let Expr::Ident(func_name) = func.as_ref() {
1081 match func_name.as_str() {
1082 "print" => {
1083 if args.len() == 1 {
1084 let (arg_ir, arg_var) = self.generate_expression(&args[0])?;
1085 ir.push_str(&arg_ir);
1086 ir.push_str(&format!(" call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.str_fmt, i32 0, i32 0), i8* {})\n", arg_var));
1087 }
1088 Ok((ir, "0".to_string())) }
1090 "print_int" => {
1091 if args.len() == 1 {
1092 let (arg_ir, arg_var) = self.generate_expression(&args[0])?;
1093 ir.push_str(&arg_ir);
1094 ir.push_str(&format!(" call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.int_fmt, i32 0, i32 0), i64 {})\n", arg_var));
1095 }
1096 Ok((ir, "0".to_string())) }
1098 _ => {
1099 let mut arg_vars = Vec::new();
1101 let mut arg_types = Vec::new();
1102
1103 for arg in args {
1104 let (arg_ir, arg_var, arg_type) =
1105 self.generate_expression_typed(arg)?;
1106 ir.push_str(&arg_ir);
1107 arg_vars.push(arg_var);
1108 arg_types.push(arg_type);
1109 }
1110
1111 let result_var = self.fresh_ssa();
1112
1113 let ret_type = "i64"; ir.push_str(&format!(
1117 " {} = call {} @{}(",
1118 result_var, ret_type, func_name
1119 ));
1120 for (i, (arg_var, arg_type)) in
1121 arg_vars.iter().zip(arg_types.iter()).enumerate()
1122 {
1123 if i > 0 {
1124 ir.push_str(", ");
1125 }
1126 ir.push_str(&format!("{} {}", arg_type, arg_var));
1127 }
1128 ir.push_str(")\n");
1129
1130 Ok((ir, result_var))
1131 }
1132 }
1133 } else {
1134 Err(CompileError::Generic(
1135 "Complex function calls not yet supported".to_string(),
1136 ))
1137 }
1138 }
1139
1140 Expr::Range { start, end, .. } => {
1141 let (start_ir, start_val) = self.generate_expression(start)?;
1143 let (end_ir, end_val) = self.generate_expression(end)?;
1144 ir.push_str(&start_ir);
1145 ir.push_str(&end_ir);
1146 Ok((ir, format!("range({}, {})", start_val, end_val)))
1147 }
1148
1149 Expr::StructLiteral { name, fields, .. } => {
1150 let struct_type = format!("%struct.{}", name);
1152 let struct_var = self.fresh_ssa();
1153 ir.push_str(&format!(" {} = alloca {}\n", struct_var, struct_type));
1154
1155 for (i, (_field_name, field_expr)) in fields.iter().enumerate() {
1157 let (field_ir, field_val) = self.generate_expression(field_expr)?;
1158 ir.push_str(&field_ir);
1159
1160 let field_ptr = self.fresh_ssa();
1161 ir.push_str(&format!(
1162 " {} = getelementptr {}, {}* {}, i32 0, i32 {}\n",
1163 field_ptr, struct_type, struct_type, struct_var, i
1164 ));
1165
1166 let field_type = self.infer_expr_type(field_expr);
1167 ir.push_str(&format!(
1168 " store {} {}, {}* {}\n",
1169 field_type, field_val, field_type, field_ptr
1170 ));
1171 }
1172
1173 Ok((ir, struct_var))
1174 }
1175
1176 Expr::FieldAccess { object, field: _, .. } => {
1177 let (obj_ir, obj_var) = self.generate_expression(object)?;
1178 ir.push_str(&obj_ir);
1179
1180 let field_idx = 0; let field_ptr = self.fresh_ssa();
1183 let field_val = self.fresh_ssa();
1184
1185 let struct_type = if let Expr::Ident(name) = object.as_ref() {
1187 if let Some(var_info) = self.var_map.get(name) {
1188 var_info.ty.clone()
1189 } else {
1190 "%struct.Unknown".to_string()
1191 }
1192 } else {
1193 "%struct.Unknown".to_string()
1194 };
1195
1196 ir.push_str(&format!(
1197 " {} = getelementptr {}, {}* {}, i32 0, i32 {}\n",
1198 field_ptr, struct_type, struct_type, obj_var, field_idx
1199 ));
1200 ir.push_str(&format!(" {} = load i64, i64* {}\n", field_val, field_ptr));
1201
1202 Ok((ir, field_val))
1203 }
1204
1205 Expr::ArrayRepeat { value, count, .. } => {
1206 let (count_ir, _count_val) = self.generate_expression(count)?;
1207 ir.push_str(&count_ir);
1208
1209 if let Expr::Integer(n) = count.as_ref() {
1211 let elem_type = "i64";
1212 let array_type = format!("[{} x {}]", n, elem_type);
1213 let array_var = self.fresh_ssa();
1214
1215 ir.push_str(&format!(" {} = alloca {}\n", array_var, array_type));
1216
1217 let (val_ir, val_var) = self.generate_expression(value)?;
1219 ir.push_str(&val_ir);
1220
1221 for i in 0..*n {
1223 let ptr = self.fresh_ssa();
1224 ir.push_str(&format!(
1225 " {} = getelementptr {}, {}* {}, i64 0, i64 {}\n",
1226 ptr, array_type, array_type, array_var, i
1227 ));
1228 ir.push_str(&format!(
1229 " store {} {}, {}* {}\n",
1230 elem_type, val_var, elem_type, ptr
1231 ));
1232 }
1233
1234 Ok((ir, array_var))
1235 } else {
1236 Err(CompileError::Generic(
1237 "Dynamic array repeat not yet supported".to_string()
1238 ))
1239 }
1240 }
1241
1242 Expr::Unary { op, operand, .. } => {
1243 let (op_ir, op_var) = self.generate_expression(operand)?;
1244 ir.push_str(&op_ir);
1245
1246 let result_var = self.fresh_ssa();
1247
1248 match op {
1249 UnaryOp::Neg => {
1250 ir.push_str(&format!(
1251 " {} = sub i64 0, {}\n",
1252 result_var, op_var
1253 ));
1254 }
1255 UnaryOp::Not => {
1256 ir.push_str(&format!(
1257 " {} = xor i1 {}, true\n",
1258 result_var, op_var
1259 ));
1260 }
1261 }
1262
1263 Ok((ir, result_var))
1264 }
1265
1266 Expr::Reference { mutable: _, expr, .. } => {
1267 if let Expr::Ident(name) = expr.as_ref() {
1269 if let Some(var_info) = self.var_map.get(name) {
1270 Ok((String::new(), var_info.ptr.clone()))
1271 } else {
1272 Err(CompileError::Generic(format!("Undefined variable: {}", name)))
1273 }
1274 } else {
1275 Err(CompileError::Generic(
1276 "Complex reference expressions not yet supported".to_string()
1277 ))
1278 }
1279 }
1280
1281 Expr::Deref { expr, .. } => {
1282 let (expr_ir, expr_var) = self.generate_expression(expr)?;
1283 ir.push_str(&expr_ir);
1284
1285 let result_var = self.fresh_ssa();
1286 ir.push_str(&format!(" {} = load i64, i64* {}\n", result_var, expr_var));
1287
1288 Ok((ir, result_var))
1289 }
1290
1291 _ => {
1292 Ok((String::new(), "0".to_string()))
1294 }
1295 }
1296 }
1297
1298 fn infer_expr_type(&self, expr: &Expr) -> String {
1300 match expr {
1301 Expr::Integer(_) => "i64".to_string(),
1302 Expr::Bool(_) => "i1".to_string(),
1303 Expr::String(_) => "i8*".to_string(),
1304 Expr::ArrayLiteral { elements, .. } => {
1305 format!("[{} x i64]", elements.len())
1306 }
1307 Expr::ArrayRepeat { count, .. } => {
1308 if let Expr::Integer(n) = count.as_ref() {
1309 format!("[{} x i64]", n)
1310 } else {
1311 "i64".to_string() }
1313 }
1314 Expr::Binary { op, .. } => {
1315 if matches!(op, BinOp::Lt | BinOp::Le | BinOp::Gt | BinOp::Ge | BinOp::Eq | BinOp::Ne) {
1316 "i1".to_string()
1317 } else {
1318 "i64".to_string()
1319 }
1320 }
1321 Expr::Call { .. } => "i64".to_string(), Expr::Ident(name) => {
1323 if let Some(var_info) = self.var_map.get(name) {
1324 var_info.ty.clone()
1325 } else {
1326 "i64".to_string() }
1328 }
1329 _ => "i64".to_string(), }
1331 }
1332
1333 pub fn write_output(&self, ir: &str) -> Result<PathBuf> {
1335 let build_dir = PathBuf::from("build_output");
1336 if !build_dir.exists() {
1337 std::fs::create_dir_all(&build_dir)?;
1338 }
1339
1340 let output_path = build_dir.join(format!("{}.ll", self.module_name));
1341 std::fs::write(&output_path, ir)?;
1342
1343 Ok(output_path)
1344 }
1345}