1use super::CodeGen;
14use super::context::RegisterContext;
15use super::types::{RegisterType, SpecSignature};
16use crate::ast::{Statement, WordDef};
17use crate::codegen::CodeGenError;
18use crate::codegen::mangle_name;
19use std::fmt::Write as _;
20use std::ops::{Deref, DerefMut};
21
22pub(super) struct SpecializedEmitter<'a> {
32 codegen: &'a mut CodeGen,
33 word_name: &'a str,
34 sig: &'a SpecSignature,
35}
36
37impl<'a> SpecializedEmitter<'a> {
38 pub(super) fn new(
39 codegen: &'a mut CodeGen,
40 word_name: &'a str,
41 sig: &'a SpecSignature,
42 ) -> Self {
43 Self {
44 codegen,
45 word_name,
46 sig,
47 }
48 }
49
50 pub(super) fn word_name(&self) -> &str {
52 self.word_name
53 }
54
55 pub(super) fn sig(&self) -> &SpecSignature {
58 self.sig
59 }
60}
61
62impl Deref for SpecializedEmitter<'_> {
63 type Target = CodeGen;
64 fn deref(&self) -> &CodeGen {
65 self.codegen
66 }
67}
68
69impl DerefMut for SpecializedEmitter<'_> {
70 fn deref_mut(&mut self) -> &mut CodeGen {
71 self.codegen
72 }
73}
74
75impl CodeGen {
76 pub fn codegen_specialized_word(
87 &mut self,
88 word: &WordDef,
89 sig: &SpecSignature,
90 ) -> Result<(), CodeGenError> {
91 SpecializedEmitter::new(self, &word.name, sig).emit_word(word)
92 }
93}
94
95impl SpecializedEmitter<'_> {
96 fn emit_word(&mut self, word: &WordDef) -> Result<(), CodeGenError> {
99 let base_name = format!("seq_{}", mangle_name(self.word_name));
100 let spec_name = format!("{}{}", base_name, self.sig.suffix());
101
102 let return_type = if self.sig.outputs.len() == 1 {
106 self.sig.outputs[0].llvm_type().to_string()
107 } else {
108 let types: Vec<_> = self.sig.outputs.iter().map(|t| t.llvm_type()).collect();
109 format!("{{ {} }}", types.join(", "))
110 };
111
112 let params: Vec<String> = self
113 .sig
114 .inputs
115 .iter()
116 .enumerate()
117 .map(|(i, ty)| format!("{} %arg{}", ty.llvm_type(), i))
118 .collect();
119
120 writeln!(
121 &mut self.output,
122 "define {} @{}({}) {{",
123 return_type,
124 spec_name,
125 params.join(", ")
126 )?;
127 writeln!(&mut self.output, "entry:")?;
128
129 let initial_params: Vec<(String, RegisterType)> = self
130 .sig
131 .inputs
132 .iter()
133 .enumerate()
134 .map(|(i, ty)| (format!("arg{}", i), *ty))
135 .collect();
136 let mut ctx = RegisterContext::from_params(&initial_params);
137
138 let body_len = word.body.len();
139 let mut prev_int_literal: Option<i64> = None;
140 for (i, stmt) in word.body.iter().enumerate() {
141 let is_last = i == body_len - 1;
142 self.emit_statement(&mut ctx, stmt, is_last, &mut prev_int_literal)?;
143 }
144
145 writeln!(&mut self.output, "}}")?;
146 writeln!(&mut self.output)?;
147
148 let key = self.word_name.to_string();
153 let sig = self.sig.clone();
154 self.specialized_words.insert(key, sig);
155
156 Ok(())
157 }
158
159 pub(super) fn emit_statement(
161 &mut self,
162 ctx: &mut RegisterContext,
163 stmt: &Statement,
164 is_last: bool,
165 prev_int_literal: &mut Option<i64>,
166 ) -> Result<(), CodeGenError> {
167 let prev_int = *prev_int_literal;
169 *prev_int_literal = None; match stmt {
172 Statement::IntLiteral(n) => {
173 let var = self.fresh_temp();
174 writeln!(&mut self.output, " %{} = add i64 0, {}", var, n)?;
175 ctx.push(var, RegisterType::I64);
176 *prev_int_literal = Some(*n); }
178
179 Statement::FloatLiteral(f) => {
180 let var = self.fresh_temp();
181 let bits = f.to_bits();
186 writeln!(
187 &mut self.output,
188 " %{} = bitcast i64 {} to double",
189 var, bits
190 )?;
191 ctx.push(var, RegisterType::Double);
192 }
193
194 Statement::BoolLiteral(b) => {
195 let var = self.fresh_temp();
196 let val = if *b { 1 } else { 0 };
197 writeln!(&mut self.output, " %{} = add i64 0, {}", var, val)?;
198 ctx.push(var, RegisterType::I64);
199 }
200
201 Statement::WordCall { name, .. } => {
202 self.emit_word_call(ctx, name, is_last, prev_int)?;
203 }
204
205 Statement::If {
206 then_branch,
207 else_branch,
208 span: _,
209 } => {
210 self.emit_if(ctx, then_branch, else_branch.as_deref(), is_last)?;
211 }
212
213 Statement::StringLiteral(_)
215 | Statement::Symbol(_)
216 | Statement::Quotation { .. }
217 | Statement::Match { .. } => {
218 return Err(CodeGenError::Logic(format!(
219 "Non-specializable statement in specialized word: {:?}",
220 stmt
221 )));
222 }
223 }
224
225 let already_returns = match stmt {
228 Statement::If { .. } => true,
229 Statement::WordCall { name, .. } if name == self.word_name => true,
230 _ => false,
231 };
232 if is_last && !already_returns {
233 self.emit_return(ctx)?;
234 }
235
236 Ok(())
237 }
238
239 pub(super) fn emit_return(&mut self, ctx: &RegisterContext) -> Result<(), CodeGenError> {
241 let output_count = self.sig.outputs.len();
242
243 if output_count == 0 {
244 writeln!(&mut self.output, " ret void")?;
245 } else if output_count == 1 {
246 let (var, ty) = ctx
247 .values
248 .last()
249 .ok_or_else(|| CodeGenError::Logic("Empty context at return".to_string()))?;
250 writeln!(&mut self.output, " ret {} %{}", ty.llvm_type(), var)?;
251 } else {
252 if ctx.values.len() < output_count {
255 return Err(CodeGenError::Logic(format!(
256 "Not enough values for multi-output return: need {}, have {}",
257 output_count,
258 ctx.values.len()
259 )));
260 }
261
262 let start_idx = ctx.values.len() - output_count;
263 let return_values: Vec<_> = ctx.values[start_idx..].to_vec();
264
265 let struct_type = self.sig.llvm_return_type();
266
267 let mut current_struct = "undef".to_string();
268 for (i, (var, ty)) in return_values.iter().enumerate() {
269 let new_struct = self.fresh_temp();
270 writeln!(
271 &mut self.output,
272 " %{} = insertvalue {} {}, {} %{}, {}",
273 new_struct,
274 struct_type,
275 current_struct,
276 ty.llvm_type(),
277 var,
278 i
279 )?;
280 current_struct = format!("%{}", new_struct);
281 }
282
283 writeln!(&mut self.output, " ret {} {}", struct_type, current_struct)?;
284 }
285 Ok(())
286 }
287
288 fn emit_branch(
299 &mut self,
300 parent_ctx: &RegisterContext,
301 branch: &[Statement],
302 branch_label: &str,
303 merge_label: &str,
304 is_last: bool,
305 ) -> Result<(RegisterContext, Option<String>), CodeGenError> {
306 writeln!(&mut self.output, "{}:", branch_label)?;
307 let mut branch_ctx = parent_ctx.clone();
308 let mut branch_prev_int: Option<i64> = None;
309 for (i, stmt) in branch.iter().enumerate() {
310 let is_stmt_last = i == branch.len() - 1 && is_last;
311 self.emit_statement(&mut branch_ctx, stmt, is_stmt_last, &mut branch_prev_int)?;
312 }
313 if is_last && branch.is_empty() {
316 self.emit_return(&branch_ctx)?;
317 }
318 let predecessor = if is_last {
319 None
320 } else {
321 writeln!(&mut self.output, " br label %{}", merge_label)?;
322 Some(branch_label.to_string())
323 };
324 Ok((branch_ctx, predecessor))
325 }
326
327 pub(super) fn emit_if(
329 &mut self,
330 ctx: &mut RegisterContext,
331 then_branch: &[Statement],
332 else_branch: Option<&[Statement]>,
333 is_last: bool,
334 ) -> Result<(), CodeGenError> {
335 let (cond_var, _) = ctx
336 .pop()
337 .ok_or_else(|| CodeGenError::Logic("Empty context at if condition".to_string()))?;
338
339 let cmp_result = self.fresh_temp();
340 writeln!(
341 &mut self.output,
342 " %{} = icmp ne i64 %{}, 0",
343 cmp_result, cond_var
344 )?;
345
346 let then_label = self.fresh_block("if_then");
347 let else_label = self.fresh_block("if_else");
348 let merge_label = self.fresh_block("if_merge");
349
350 writeln!(
351 &mut self.output,
352 " br i1 %{}, label %{}, label %{}",
353 cmp_result, then_label, else_label
354 )?;
355
356 let (then_ctx, then_pred) =
357 self.emit_branch(ctx, then_branch, &then_label, &merge_label, is_last)?;
358
359 let else_slice: &[Statement] = else_branch.unwrap_or(&[]);
361 let (else_ctx, else_pred) =
362 self.emit_branch(ctx, else_slice, &else_label, &merge_label, is_last)?;
363
364 if then_pred.is_some() || else_pred.is_some() {
366 writeln!(&mut self.output, "{}:", merge_label)?;
367
368 if let (Some(then_p), Some(else_p)) = (&then_pred, &else_pred) {
369 if then_ctx.values.len() != else_ctx.values.len() {
371 return Err(CodeGenError::Logic(format!(
372 "Stack depth mismatch in if branches: then has {}, else has {}",
373 then_ctx.values.len(),
374 else_ctx.values.len()
375 )));
376 }
377
378 ctx.values.clear();
379 for i in 0..then_ctx.values.len() {
380 let (then_var, then_ty) = &then_ctx.values[i];
381 let (else_var, else_ty) = &else_ctx.values[i];
382
383 if then_ty != else_ty {
384 return Err(CodeGenError::Logic(format!(
385 "Type mismatch at position {} in if branches: {:?} vs {:?}",
386 i, then_ty, else_ty
387 )));
388 }
389
390 if then_var == else_var {
391 ctx.push(then_var.clone(), *then_ty);
392 } else {
393 let phi_result = self.fresh_temp();
394 writeln!(
395 &mut self.output,
396 " %{} = phi {} [ %{}, %{} ], [ %{}, %{} ]",
397 phi_result,
398 then_ty.llvm_type(),
399 then_var,
400 then_p,
401 else_var,
402 else_p
403 )?;
404 ctx.push(phi_result, *then_ty);
405 }
406 }
407 } else if then_pred.is_some() {
408 *ctx = then_ctx;
409 } else {
410 *ctx = else_ctx;
411 }
412
413 if is_last && (then_pred.is_some() || else_pred.is_some()) {
414 self.emit_return(ctx)?;
415 }
416 }
417
418 Ok(())
419 }
420}