1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
use std::cell::RefCell;
use std::rc::Rc;
use crate::code::CodeObject;
use crate::gen::ModuleMeta;
use crate::var::Variable;
use super::*;
pub struct HirLoweringRuntime<'lir> {
code: Vec<LirElement<'lir>>,
counter: LabelCounterRef,
meta: ModuleMeta,
optimizer: Box<dyn Optimizer>,
branch_stack: Vec<HirLoweringBranch>,
locals: Vec<&'lir Variable>,
loop_stack: Vec<HirLoweringRepeat>,
}
impl<'lir> HirLoweringRuntime<'lir> {
pub fn new(meta: ModuleMeta, options: CompileOptions) -> Self {
let optimizer = if options.optimize {
Box::new(StandardOptimizer::new()) as Box<dyn Optimizer>
} else {
Box::new(NoOptimizer) as Box<dyn Optimizer>
};
Self {
code: vec![],
counter: Rc::new(RefCell::new(LabelCounter::default())),
meta,
optimizer,
branch_stack: vec![],
locals: vec![],
loop_stack: vec![],
}
}
pub fn create_new_label(&mut self) -> Label {
self.counter.borrow_mut().create_new_label()
}
pub fn add_hir(&mut self, hir: &'lir Hir) -> Lovm2CompileResult<()> {
self.locals.clear();
for arg in hir.args.iter().rev() {
self.emit(LirElement::store(Scope::Local, arg));
}
hir.block.lower(self);
match self.code.last_mut() {
Some(LirElement::Ret) => {}
_ => {
self.emit(LirElement::push_constant_owned(Value::Nil));
self.emit(LirElement::Ret);
}
}
Ok(())
}
pub fn complete(mut self) -> Lovm2CompileResult<CodeObject> {
let lir_runtime = LirLoweringRuntime::from(self.meta);
self.optimizer.postprocess(&mut self.code);
lir_runtime.lower(self.code)
}
pub fn emit(&mut self, elem: LirElement<'lir>) {
if let LirElement::StoreDynamic {
ident,
scope: Scope::Local,
} = &elem
{
if !self.has_local(ident) {
self.locals.push(ident);
}
}
self.code.push(elem);
self.optimizer.transform(&mut self.code);
}
pub fn has_local(&self, var: &Variable) -> bool {
self.locals.contains(&var)
}
pub fn loop_mut(&mut self) -> Option<&mut HirLoweringRepeat> {
self.loop_stack.last_mut()
}
pub fn push_loop(&mut self) -> &HirLoweringRepeat {
self.loop_stack
.push(HirLoweringRepeat::new(self.counter.clone()));
self.loop_stack.last_mut().unwrap()
}
pub fn pop_loop(&mut self) -> Option<HirLoweringRepeat> {
self.loop_stack.pop()
}
pub fn branch_mut(&mut self) -> Option<&mut HirLoweringBranch> {
self.branch_stack.last_mut()
}
pub fn push_branch(&mut self) -> &HirLoweringBranch {
self.branch_stack
.push(HirLoweringBranch::new(self.counter.clone()));
self.branch_stack.last_mut().unwrap()
}
pub fn pop_branch(&mut self) -> Option<HirLoweringBranch> {
self.branch_stack.pop()
}
}