Skip to main content

citadel_backend/asm/utils/
mod.rs

1pub mod codegen;
2
3use std::{fs::File, io::Write, path::PathBuf};
4
5use citadel_frontend::ir::{irgen::HIRStream, IRStmt};
6
7use crate::{
8    api::Target,
9    asm::{
10        codegen::CodeGenerator,
11        elements::{AsmElement, BuiltinFunction},
12    },
13};
14
15use super::elements::{Declaration, Directive, DirectiveType, Operand};
16
17pub fn compile_program(input: HIRStream, _target: impl Target) -> Vec<AsmElement> {
18    let mut codegen = CodeGenerator::new(input.types);
19
20    gen_code(&input.stream, &mut codegen);
21
22    gen_defined_functions(&mut codegen);
23
24    let rodata = codegen.rodata;
25    let data = codegen.data;
26    let mut out = codegen.out;
27
28    // Add data sections
29    add_data_section(rodata, DirectiveType::Rodata, &mut out);
30    add_data_section(data, DirectiveType::Data, &mut out);
31
32    out
33}
34
35fn gen_code<'c>(input: &'c [IRStmt<'c>], codegen: &mut CodeGenerator<'c>) {
36    for stmt in input.iter() {
37        codegen.gen_stmt(stmt);
38    }
39}
40
41// TODO: Optimize insertion at front
42fn add_data_section(data: Vec<Declaration>, _type: DirectiveType, out: &mut Vec<AsmElement>) {
43    if !data.is_empty() {
44        out.insert(0, AsmElement::Directive(Directive { _type }));
45        for (i, decl) in data.into_iter().enumerate() {
46            out.insert(i + 1, AsmElement::Declaration(decl));
47        }
48    }
49}
50
51fn gen_defined_functions(codegen: &mut CodeGenerator) {
52    for func in codegen.defined_functions.clone() {
53        func.generate(codegen);
54    }
55}
56
57pub fn compiler_output(asm: String, location: PathBuf) {
58    let mut file = File::create(&location).unwrap_or_else(|err| {
59        panic!(
60            "Failed to create a new file at {}, error: {}",
61            location.display(),
62            err
63        )
64    });
65    file.write_all(asm.as_bytes())
66        .expect("Failed to write to file");
67}
68
69pub fn format(asm: &[AsmElement]) -> String{
70    let mut out = String::new();
71    for elem in asm{
72        match elem {
73            AsmElement::Directive(_) | AsmElement::Label(_) => (),
74            _ => out.push_str("    "),
75        }
76        out.push_str(&elem.to_string());
77        out.push('\n');
78    }
79    out
80}
81
82pub fn op_vec_to_string(vec: &[Operand]) -> String {
83    let str: String = vec
84        .iter()
85        .map(|op| {
86            let mut str = op.to_string();
87            str.push(',');
88            str
89        })
90        .collect();
91    if !vec.is_empty() {
92        (&str[..str.len() - 1]).into()
93    } else {
94        String::new()
95    }
96}
97
98/*
99pub fn decl_vec_to_string(vec: &Vec<Declaration>) -> String {
100    let str: String = vec
101        .iter()
102        .map(|decl| {
103            let mut str = decl.to_string();
104            str.push('\n');
105            str
106        })
107        .collect();
108    (&str[..str.len() - 1]).into()
109}
110*/