1use cardinal_codegen::entities::{AbiType, Named, NamedProperty, Type, Value, ValueInfo};
4use cardinal_codegen::function::{Function};
5use cardinal_codegen::instruction::{InstructionInfo, InstBlock, Opcode};
6use cardinal_codegen::module::Module;
7
8pub struct CBackend {
10
11 module: Module,
13
14 imports: Vec<String>,
16
17}
18
19impl CBackend {
20
21 pub fn new(module: Module) -> Self {
23 Self {
24 module,
25 imports: vec![],
26 }
27 }
28
29 fn display_instruction(&self, inst: &InstructionInfo, block: &InstBlock) -> String {
31 match inst.opcode {
32 Opcode::Add => {
33 self.display_value(inst.arguments[0], block) + " + " + &self.display_value(inst.arguments[1], block)
34 },
35 Opcode::Sub => {
36 self.display_value(inst.arguments[0], block) + " - " + &self.display_value(inst.arguments[1], block)
37 },
38 Opcode::Mul => {
39 self.display_value(inst.arguments[0], block) + " * " + &self.display_value(inst.arguments[1], block)
40 },
41 Opcode::Div => {
42 self.display_value(inst.arguments[0], block) + " / " + &self.display_value(inst.arguments[1], block)
43 },
44 Opcode::Mod => {
45 self.display_value(inst.arguments[0], block) + " % " + &self.display_value(inst.arguments[1], block)
46 },
47 Opcode::BitAnd => {
48 self.display_value(inst.arguments[0], block) + " & " + &self.display_value(inst.arguments[1], block)
49 },
50 Opcode::BitOr => {
51 self.display_value(inst.arguments[0], block) + " | " + &self.display_value(inst.arguments[1], block)
52 },
53 Opcode::BitXor => {
54 self.display_value(inst.arguments[0], block) + " ^ " + &self.display_value(inst.arguments[1], block)
55 },
56 Opcode::BitNot => {
57 "~".to_string() + &self.display_value(inst.arguments[0], block)
58 },
59 Opcode::BitLeft => {
60 self.display_value(inst.arguments[0], block) + " << " + &self.display_value(inst.arguments[1], block)
61 },
62 Opcode::BitRight => {
63 self.display_value(inst.arguments[0], block) + " >> " + &self.display_value(inst.arguments[1], block)
64 },
65 Opcode::TestEq => {
66 self.display_value(inst.arguments[0], block) + " == " + &self.display_value(inst.arguments[1], block)
67 },
68 Opcode::TestNeq => {
69 self.display_value(inst.arguments[0], block) + " != " + &self.display_value(inst.arguments[1], block)
70 },
71 Opcode::TestGt => {
72 self.display_value(inst.arguments[0], block) + " > " + &self.display_value(inst.arguments[1], block)
73 },
74 Opcode::TestGtEq => {
75 self.display_value(inst.arguments[0], block) + " >= " + &self.display_value(inst.arguments[1], block)
76 },
77 Opcode::TestLt => {
78 self.display_value(inst.arguments[0], block) + " < " + &self.display_value(inst.arguments[1], block)
79 },
80 Opcode::TestLtEq => {
81 self.display_value(inst.arguments[0], block) + " <= " + &self.display_value(inst.arguments[1], block)
82 },
83 Opcode::Not => {
84 "!".to_string() + &self.display_value(inst.arguments[0], block)
85 },
86 Opcode::Or => {
87 self.display_value(inst.arguments[0], block) + " || " + &self.display_value(inst.arguments[1], block)
88 },
89 Opcode::And => {
90 self.display_value(inst.arguments[0], block) + " && " + &self.display_value(inst.arguments[1], block)
91 },
92 Opcode::Jmp => {
93 "goto".to_string() + &self.display_value(inst.arguments[0], block)
94 },
95 Opcode::Set => {
96 self.display_value(inst.arguments[0], block) + " = " + &self.display_value(inst.arguments[1], block)
97 },
98 Opcode::Call => {
99 let mut args = vec![];
100
101 let mut i = 1;
102 while i < inst.arguments.len() {
103 args.push(self.display_value(inst.arguments[i], block));
104 i += 1;
105 }
106
107 self.display_value(inst.arguments[0], block) + "(" + &args.join(", ") + ")"
108 },
109 Opcode::Ret => {
110 "return ".to_string() + &self.display_value(inst.arguments[0], block)
111 },
112 }
113 }
114
115 fn display_value(&self, val: Value, block: &InstBlock) -> String {
117 let v = &block.values[val.0 as usize];
118
119 match v {
120 ValueInfo::Block(b) => {
121 format!("block{}", b.0)
122 },
123 ValueInfo::BooleanConstant(b) => {
124 b.to_string()
125 },
126 ValueInfo::DoubleConstant(b) => {
127 b.to_string()
128 },
129 ValueInfo::IntegerConstant(b) => {
130 b.to_string()
131 },
132 ValueInfo::FloatConstant(b) => {
133 b.to_string()
134 },
135 ValueInfo::Instruction(b) => {
136 self.display_instruction(b, block)
137 },
138 ValueInfo::Named(b) => {
139 self.display_named(b, block)
140 },
141 ValueInfo::StringConstant(b) => {
142 "\"".to_string() + &b + "\""
143 },
144 ValueInfo::CharConstant(b) => {
145 "'".to_string() + &b + "'"
146 },
147 }
148 }
149
150 fn display_named(&self, named: &Named, block: &InstBlock) -> String {
151 let mut name = named.name.to_string();
152
153 for item in &named.properties {
154 match item {
155 NamedProperty::Basic(n) => {
156 name.push('.');
157 name.push_str(&n);
158 },
159 NamedProperty::Index(n) => {
160 name.push('[');
161 name.push_str(&self.display_value(*n, block));
162 name.push(']');
163 },
164 NamedProperty::Pointer(n) => {
165 name.push_str("->");
166 name.push_str(&n);
167 },
168 NamedProperty::Static(_) => {
169 panic!("Static indexing isn't allowed with the C emitter.");
170 }
173 }
174 }
175
176 name.to_string()
177 }
178
179 fn display_abitype(&self, abitype: &AbiType) -> String {
180 let t = &abitype.1;
181
182 match t {
183 Type::Plain => {
184 abitype.0.to_string()
185 },
186 Type::Array(n) => {
187 if n > &-1 {
188 abitype.0.to_string() + "[]".into()
189 } else {
190 abitype.0.to_string() + &format!("[{}]", n)
191 }
192 },
193 Type::Pointer => {
194 abitype.0.to_string() + "*".into()
195 }
196 }
197 }
198
199 pub fn compile_function(&self, func: &Function) -> (String, Vec<String>) {
201 let mut args = vec![];
202
203 for item in &func.signature.arguments {
204 args.push(format!("{} {}", self.display_abitype(&item.1), item.0));
205 }
206
207 let mut header = format!("{} {}({})", self.display_abitype(&func.signature.returns), func.name, args.join(", "));
208 if func.blocks.len() == 0 {
209 return (header, vec![]);
210 } else {
211 header.push_str(" {\n");
212 let mut imports = vec![];
213 let mut insts = vec![];
214
215 for (i, v) in func.blocks.iter().enumerate() {
216 let mut block = vec![];
217 imports.append(&mut v.imports.clone());
218 for inst in &v.insts {
219 block.push(self.display_instruction(inst, v));
220 }
221
222 insts.push(format!("block{}: {{\n", i) + &block.join(";\n") + ";\n}\n");
223 }
224
225 let mut vars = vec![];
226
227 for var in &func.variables {
228 vars.push(self.display_abitype(&var.1) + " " + var.0);
229 }
230
231 header.push_str(&(vars.join(";\n")));
232
233 if vars.len() > 0 {
234 header.push_str(";\n");
235 }
236
237 header.push_str(&(insts.join("\n")));
238
239 header.push('}');
240
241 return (header, imports);
242 }
243
244
245 }
246
247 pub fn emit(&mut self) -> String {
249 let mut str = String::new();
250
251 let mut f = vec![];
252
253 for item in &self.module.functions {
254 let x = item.1;
255 let mut res = self.compile_function(x);
256 f.push(res.0);
257
258 self.imports.append(&mut res.1);
259 }
260
261 let mut includes = vec![];
262
263 for item in &self.imports {
264 includes.push(format!("#include <{}>", item));
265 }
266
267 str.push_str(&includes.join("\n"));
268 str.push('\n');
269
270 str.push_str(&f.join("\n"));
271
272 str
273 }
274
275}