use crate::ast::*;
use crate::span::Spanned;
use crate::tir::TIROp;
use super::TIRBuilder;
pub(crate) fn parse_spill_effect(line: &str) -> TIROp {
let trimmed = line.trim();
if let Some(rest) = trimmed.strip_prefix("push ") {
if let Ok(val) = rest.trim().parse::<u64>() {
return TIROp::Push(val);
}
}
if let Some(rest) = trimmed.strip_prefix("swap ") {
if let Ok(val) = rest.trim().parse::<u32>() {
return TIROp::Swap(val);
}
}
if let Some(rest) = trimmed.strip_prefix("pop ") {
if let Ok(val) = rest.trim().parse::<u32>() {
return TIROp::Pop(val);
}
}
if let Some(rest) = trimmed.strip_prefix("write_mem ") {
if let Ok(val) = rest.trim().parse::<u32>() {
return TIROp::WriteMem(val);
}
}
if let Some(rest) = trimmed.strip_prefix("read_mem ") {
if let Ok(val) = rest.trim().parse::<u32>() {
return TIROp::ReadMem(val);
}
}
if let Some(rest) = trimmed.strip_prefix("dup ") {
if let Ok(val) = rest.trim().parse::<u32>() {
return TIROp::Dup(val);
}
}
TIROp::Asm {
lines: vec![trimmed.to_string()],
effect: 0,
}
}
impl TIRBuilder {
pub(crate) fn is_cfg_active(&self, cfg: &Option<Spanned<String>>) -> bool {
match cfg {
None => true,
Some(flag) => self.cfg_flags.contains(&flag.node),
}
}
pub(crate) fn is_item_cfg_active(&self, item: &Item) -> bool {
match item {
Item::Fn(f) => self.is_cfg_active(&f.cfg),
Item::Const(c) => self.is_cfg_active(&c.cfg),
Item::Struct(s) => self.is_cfg_active(&s.cfg),
Item::Event(e) => self.is_cfg_active(&e.cfg),
}
}
pub(crate) fn fresh_label(&mut self, prefix: &str) -> String {
self.label_counter += 1;
format!("{}__{}", prefix, self.label_counter)
}
pub(crate) fn flush_stack_effects(&mut self) {
for inst in self.stack.drain_side_effects() {
self.ops.push(parse_spill_effect(&inst));
}
}
pub(crate) fn emit_and_push(&mut self, op: TIROp, result_width: u32) {
if result_width > 0 {
self.stack.ensure_space(result_width);
self.flush_stack_effects();
}
self.ops.push(op);
self.stack.push_temp(result_width);
}
pub(crate) fn push_temp(&mut self, width: u32) {
self.stack.push_temp(width);
self.flush_stack_effects();
}
pub(crate) fn find_var_depth_and_width(&mut self, name: &str) -> Option<(u32, u32)> {
let r = self.stack.find_var_depth_and_width(name);
self.flush_stack_effects();
r
}
pub(crate) fn emit_pop(&mut self, n: u32) {
let mut remaining = n;
while remaining > 0 {
let batch = remaining.min(5);
self.ops.push(TIROp::Pop(batch));
remaining -= batch;
}
}
pub(crate) fn build_block_as_ir(&mut self, block: &Block) -> Vec<TIROp> {
let saved_ops = std::mem::take(&mut self.ops);
self.build_block(block);
let nested = std::mem::take(&mut self.ops);
self.ops = saved_ops;
nested
}
}