1use super::{
7 CodeGen, CodeGenError, emit_runtime_decls, ffi_c_args, ffi_return_type, get_target_triple,
8};
9use crate::ast::Program;
10use crate::config::CompilerConfig;
11use crate::ffi::FfiBindings;
12use crate::types::Type;
13use std::collections::HashMap;
14use std::fmt::Write as _;
15
16impl CodeGen {
17 pub fn codegen_program(
19 &mut self,
20 program: &Program,
21 type_map: HashMap<usize, Type>,
22 statement_types: HashMap<(String, usize), Type>,
23 ) -> Result<String, CodeGenError> {
24 self.codegen_program_with_config(
25 program,
26 type_map,
27 statement_types,
28 &CompilerConfig::default(),
29 )
30 }
31
32 pub fn codegen_program_with_config(
37 &mut self,
38 program: &Program,
39 type_map: HashMap<usize, Type>,
40 statement_types: HashMap<(String, usize), Type>,
41 config: &CompilerConfig,
42 ) -> Result<String, CodeGenError> {
43 self.type_map = type_map;
45 self.statement_types = statement_types;
46 self.unions = program.unions.clone();
50
51 self.external_builtins = config
53 .external_builtins
54 .iter()
55 .map(|b| (b.seq_name.clone(), b.symbol.clone()))
56 .collect();
57
58 self.instrument = config.instrument;
60 if self.instrument {
61 for (id, word) in program.words.iter().enumerate() {
62 self.word_instrument_ids.insert(word.name.clone(), id);
63 }
64 }
65
66 if program.find_word("main").is_none() {
68 return Err(CodeGenError::Logic("No main word defined".to_string()));
69 }
70
71 for word in &program.words {
73 self.codegen_word(word)?;
74 }
75
76 self.codegen_main()?;
78
79 let mut ir = String::new();
81
82 writeln!(&mut ir, "; ModuleID = 'main'")?;
84 writeln!(&mut ir, "target triple = \"{}\"", get_target_triple())?;
85 writeln!(&mut ir)?;
86
87 self.emit_value_type_def(&mut ir)?;
89
90 self.emit_string_and_symbol_globals(&mut ir)?;
92
93 if self.instrument {
95 self.emit_instrumentation_globals(&mut ir)?;
96 }
97
98 emit_runtime_decls(&mut ir)?;
100
101 if !self.external_builtins.is_empty() {
103 writeln!(&mut ir, "; External builtin declarations")?;
104 for symbol in self.external_builtins.values() {
105 writeln!(&mut ir, "declare ptr @{}(ptr)", symbol)?;
107 }
108 writeln!(&mut ir)?;
109 }
110
111 if !self.quotation_functions.is_empty() {
113 writeln!(&mut ir, "; Quotation functions")?;
114 ir.push_str(&self.quotation_functions);
115 writeln!(&mut ir)?;
116 }
117
118 ir.push_str(&self.output);
120
121 Ok(ir)
122 }
123
124 pub fn codegen_program_with_ffi(
128 &mut self,
129 program: &Program,
130 type_map: HashMap<usize, Type>,
131 statement_types: HashMap<(String, usize), Type>,
132 config: &CompilerConfig,
133 ffi_bindings: &FfiBindings,
134 ) -> Result<String, CodeGenError> {
135 self.ffi_bindings = ffi_bindings.clone();
137
138 self.generate_ffi_wrappers()?;
140
141 self.type_map = type_map;
143 self.statement_types = statement_types;
144
145 self.unions = program.unions.clone();
147
148 self.external_builtins = config
150 .external_builtins
151 .iter()
152 .map(|b| (b.seq_name.clone(), b.symbol.clone()))
153 .collect();
154
155 self.instrument = config.instrument;
157 if self.instrument {
158 for (id, word) in program.words.iter().enumerate() {
159 self.word_instrument_ids.insert(word.name.clone(), id);
160 }
161 }
162
163 if program.find_word("main").is_none() {
165 return Err(CodeGenError::Logic("No main word defined".to_string()));
166 }
167
168 for word in &program.words {
170 self.codegen_word(word)?;
171 }
172
173 self.codegen_main()?;
175
176 let mut ir = String::new();
178
179 writeln!(&mut ir, "; ModuleID = 'main'")?;
181 writeln!(&mut ir, "target triple = \"{}\"", get_target_triple())?;
182 writeln!(&mut ir)?;
183
184 self.emit_value_type_def(&mut ir)?;
186
187 self.emit_string_and_symbol_globals(&mut ir)?;
189
190 if self.instrument {
192 self.emit_instrumentation_globals(&mut ir)?;
193 }
194
195 self.emit_runtime_declarations(&mut ir)?;
197
198 if !self.ffi_bindings.functions.is_empty() {
200 writeln!(&mut ir, "; FFI C function declarations")?;
201 writeln!(&mut ir, "declare ptr @malloc(i64)")?;
202 writeln!(&mut ir, "declare void @free(ptr)")?;
203 writeln!(&mut ir, "declare i64 @strlen(ptr)")?;
204 writeln!(&mut ir, "declare ptr @memcpy(ptr, ptr, i64)")?;
205 writeln!(
207 &mut ir,
208 "declare ptr @patch_seq_string_to_cstring(ptr, ptr)"
209 )?;
210 writeln!(
211 &mut ir,
212 "declare ptr @patch_seq_cstring_to_string(ptr, ptr)"
213 )?;
214 for func in self.ffi_bindings.functions.values() {
215 let c_ret_type = ffi_return_type(&func.return_spec);
216 let c_args = ffi_c_args(&func.args);
217 writeln!(
218 &mut ir,
219 "declare {} @{}({})",
220 c_ret_type, func.c_name, c_args
221 )?;
222 }
223 writeln!(&mut ir)?;
224 }
225
226 if !self.external_builtins.is_empty() {
228 writeln!(&mut ir, "; External builtin declarations")?;
229 for symbol in self.external_builtins.values() {
230 writeln!(&mut ir, "declare ptr @{}(ptr)", symbol)?;
231 }
232 writeln!(&mut ir)?;
233 }
234
235 if !self.ffi_wrapper_code.is_empty() {
237 writeln!(&mut ir, "; FFI wrapper functions")?;
238 ir.push_str(&self.ffi_wrapper_code);
239 writeln!(&mut ir)?;
240 }
241
242 if !self.quotation_functions.is_empty() {
244 writeln!(&mut ir, "; Quotation functions")?;
245 ir.push_str(&self.quotation_functions);
246 writeln!(&mut ir)?;
247 }
248
249 ir.push_str(&self.output);
251
252 Ok(ir)
253 }
254
255 pub(super) fn emit_runtime_declarations(&self, ir: &mut String) -> Result<(), CodeGenError> {
257 emit_runtime_decls(ir)
258 }
259
260 fn emit_instrumentation_globals(&self, ir: &mut String) -> Result<(), CodeGenError> {
267 let n = self.word_instrument_ids.len();
268 if n == 0 {
269 return Ok(());
270 }
271
272 writeln!(ir, "; Instrumentation globals (--instrument)")?;
273
274 writeln!(
276 ir,
277 "@seq_word_counters = global [{} x i64] zeroinitializer",
278 n
279 )?;
280
281 let mut words: Vec<(usize, &str)> = self
283 .word_instrument_ids
284 .iter()
285 .map(|(name, &id)| (id, name.as_str()))
286 .collect();
287 words.sort_by_key(|&(id, _)| id);
288
289 for &(id, name) in &words {
291 let name_bytes = name.as_bytes();
292 let len = name_bytes.len() + 1; let escaped: String = name_bytes
294 .iter()
295 .map(|&b| format!("\\{:02X}", b))
296 .collect::<String>();
297 writeln!(
298 ir,
299 "@seq_word_name_{} = private constant [{} x i8] c\"{}\\00\"",
300 id, len, escaped
301 )?;
302 }
303
304 let ptrs: Vec<String> = words
306 .iter()
307 .map(|&(id, _name)| format!("ptr @seq_word_name_{}", id))
308 .collect();
309 writeln!(
310 ir,
311 "@seq_word_names = private constant [{} x ptr] [{}]",
312 n,
313 ptrs.join(", ")
314 )?;
315
316 writeln!(ir)?;
317 Ok(())
318 }
319}