Fable rewrite
This commit is contained in:
+66
-1
@@ -4,7 +4,7 @@ use std::fmt::Debug;
|
||||
|
||||
use crate::{
|
||||
flatten::{Capture, FlatFn},
|
||||
parse::{ImmOperand, Instr, JsValue, opcodes::OpCode},
|
||||
parse::{AtomRef, ImmOperand, Instr, JsValue, opcodes::OpCode},
|
||||
};
|
||||
|
||||
pub struct RegInstr {
|
||||
@@ -104,3 +104,68 @@ pub fn regify(flat_fns: Vec<FlatFn>) -> Vec<RegFn> {
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
// ─── shared by the de* passes ──────────────────────────────────────────────
|
||||
|
||||
impl RegInstr {
|
||||
pub fn new(op: OpCode, imm: ImmOperand, dsts: Vec<usize>, args: Vec<usize>) -> Self {
|
||||
RegInstr {
|
||||
dsts,
|
||||
op,
|
||||
imm,
|
||||
args,
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether this instruction reads or writes `value`.
|
||||
pub fn mentions(&self, value: usize) -> bool {
|
||||
self.args.contains(&value) || self.dsts.contains(&value)
|
||||
}
|
||||
}
|
||||
|
||||
/// Hands out value numbers that nothing in the function uses yet.
|
||||
pub struct Fresh(usize);
|
||||
|
||||
impl Fresh {
|
||||
/// Start just past the highest value the function already uses.
|
||||
pub fn for_fn(f: &RegFn) -> Fresh {
|
||||
let highest = f
|
||||
.code
|
||||
.iter()
|
||||
.flat_map(|i| i.dsts.iter().chain(i.args.iter()))
|
||||
.copied()
|
||||
.max()
|
||||
.unwrap_or(0);
|
||||
Fresh(highest + 1)
|
||||
}
|
||||
|
||||
pub fn new_value(&mut self) -> usize {
|
||||
let v = self.0;
|
||||
self.0 += 1;
|
||||
v
|
||||
}
|
||||
}
|
||||
|
||||
/// A call with no receiver. `call_method` and `call_constructor` carry one and
|
||||
/// are handled by the class passes instead.
|
||||
pub fn is_plain_call(op: OpCode) -> bool {
|
||||
use OpCode::*;
|
||||
matches!(op, Call | Call0 | Call1 | Call2 | Call3 | TailCall)
|
||||
}
|
||||
|
||||
/// The generic form of a call opcode: any tail variant becomes `tail_call`,
|
||||
/// everything else `call`.
|
||||
pub fn as_plain_call(op: OpCode) -> OpCode {
|
||||
use OpCode::*;
|
||||
if matches!(op, TailCall | TailCallMethod) {
|
||||
TailCall
|
||||
} else {
|
||||
Call
|
||||
}
|
||||
}
|
||||
|
||||
/// An integer-named field. The synthetic objects these passes build use
|
||||
/// integer names so no new atoms have to be minted.
|
||||
pub fn int_field(index: u32) -> ImmOperand {
|
||||
ImmOperand::Atom(AtomRef::TaggedInt(index))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user