-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #12 from binary-banter/new_type_checking
New type checking
- Loading branch information
Showing
335 changed files
with
5,556 additions
and
4,489 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
use crate::passes::assign::{Arg, X86Assigned}; | ||
use crate::passes::select::{Block, Instr, VarArg, X86Selected}; | ||
use crate::utils::gen_sym::UniqueSym; | ||
use crate::*; | ||
use std::collections::HashMap; | ||
|
||
impl<'p> X86Selected<'p> { | ||
#[must_use] | ||
pub fn assign(self) -> X86Assigned<'p> { | ||
let program = self.include_liveness(); | ||
let interference = program.compute_interference(); | ||
let (color_map, stack_space) = interference.color(); | ||
|
||
let blocks = program | ||
.blocks | ||
.into_iter() | ||
.map(|(lbl, block)| (lbl, assign_block(block.into(), &color_map))) | ||
.collect(); | ||
|
||
X86Assigned { | ||
blocks, | ||
entry: program.entry, | ||
stack_space, | ||
std: program.std, | ||
} | ||
} | ||
} | ||
|
||
fn assign_block<'p>( | ||
block: Block<'p, VarArg>, | ||
color_map: &HashMap<UniqueSym, Arg>, | ||
) -> Block<'p, Arg> { | ||
Block { | ||
instrs: block | ||
.instrs | ||
.into_iter() | ||
.map(|instr| assign_instr(instr, color_map)) | ||
.collect(), | ||
} | ||
} | ||
|
||
fn assign_instr<'p>( | ||
instr: Instr<'p, VarArg>, | ||
color_map: &HashMap<UniqueSym, Arg>, | ||
) -> Instr<'p, Arg> { | ||
let map = |arg: VarArg| -> Arg { | ||
match arg { | ||
VarArg::Imm { val } => Arg::Imm { val }, | ||
VarArg::Reg { reg } => Arg::Reg { reg }, | ||
VarArg::Deref { reg, off } => Arg::Deref { reg, off }, | ||
VarArg::XVar { sym } => color_map[&sym].clone(), | ||
} | ||
}; | ||
|
||
match instr { | ||
Instr::Addq { src, dst } => addq!(map(src), map(dst)), | ||
Instr::Subq { src, dst } => subq!(map(src), map(dst)), | ||
Instr::Divq { divisor } => divq!(map(divisor)), | ||
Instr::Mulq { src } => mulq!(map(src)), | ||
Instr::Negq { dst } => negq!(map(dst)), | ||
Instr::Movq { src, dst } => movq!(map(src), map(dst)), | ||
Instr::Pushq { src } => pushq!(map(src)), | ||
Instr::Popq { dst } => popq!(map(dst)), | ||
Instr::CallqDirect { lbl, arity } => callq_direct!(lbl, arity), | ||
Instr::Retq => retq!(), | ||
Instr::Syscall { arity } => syscall!(arity), | ||
Instr::Jmp { lbl } => jmp!(lbl), | ||
Instr::Jcc { lbl, cnd } => jcc!(lbl, cnd), | ||
Instr::Cmpq { src, dst } => cmpq!(map(src), map(dst)), | ||
Instr::Andq { src, dst } => andq!(map(src), map(dst)), | ||
Instr::Orq { src, dst } => orq!(map(src), map(dst)), | ||
Instr::Xorq { src, dst } => xorq!(map(src), map(dst)), | ||
Instr::Notq { dst } => notq!(map(dst)), | ||
Instr::Setcc { cnd } => setcc!(cnd), | ||
Instr::LoadLbl { sym, dst } => load_lbl!(sym, map(dst)), | ||
Instr::CallqIndirect { src, arity } => callq_indirect!(map(src), arity), | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
use crate::passes::assign::{Arg, InterferenceGraph, LArg}; | ||
use crate::passes::select::Reg; | ||
use crate::utils::gen_sym::UniqueSym; | ||
use itertools::Itertools; | ||
use std::collections::{HashMap, HashSet}; | ||
|
||
impl<'p> InterferenceGraph<'p> { | ||
#[must_use] | ||
pub fn color(self) -> (HashMap<UniqueSym<'p>, Arg>, usize) { | ||
let graph = self.0; | ||
let mut queue = Vec::new(); | ||
let mut node_map = HashMap::<LArg, isize>::new(); | ||
|
||
for node in graph.nodes() { | ||
match node { | ||
LArg::Var { .. } => { | ||
queue.push(node); | ||
} | ||
LArg::Reg { reg } => { | ||
let node_weight = match reg { | ||
Reg::RCX => 0, | ||
Reg::RDX => 1, | ||
Reg::RSI => 2, | ||
Reg::RDI => 3, | ||
Reg::R8 => 4, | ||
Reg::R9 => 5, | ||
Reg::R10 => 6, | ||
Reg::RBX => 7, | ||
Reg::R12 => 8, | ||
Reg::R13 => 9, | ||
Reg::R14 => 10, | ||
Reg::RAX => -1, | ||
Reg::RSP => -2, | ||
Reg::RBP => -3, | ||
Reg::R11 => -4, | ||
Reg::R15 => -5, | ||
}; | ||
node_map.insert(node, node_weight); | ||
} | ||
} | ||
} | ||
|
||
while let Some(node) = queue.pop() { | ||
let used_colors = graph | ||
.neighbors(node) | ||
.filter_map(|nb| node_map.get(&nb)) | ||
.collect::<HashSet<_>>(); | ||
|
||
let chosen_color = (0..) | ||
.find(|i| !used_colors.contains(i)) | ||
.expect("there are infinite numbers, lol"); | ||
|
||
node_map.insert(node, chosen_color); | ||
|
||
queue.sort_by_key(|node| { | ||
graph | ||
.neighbors(*node) | ||
.filter_map(|nb| node_map.get(&nb)) | ||
.unique() | ||
.count() | ||
}); | ||
} | ||
|
||
let used_vars = node_map | ||
.values() | ||
.filter(|&&n| n >= 10) | ||
.map(|&n| n - 10) | ||
.max() | ||
.unwrap_or_default() as usize; | ||
|
||
let stack_space = (8 * used_vars).div_ceil(16) * 16; | ||
|
||
let colors = node_map | ||
.into_iter() | ||
.filter_map(|(node, color)| match node { | ||
LArg::Var { sym } => Some((sym, arg_from_color(color))), | ||
LArg::Reg { .. } => None, | ||
}) | ||
.collect(); | ||
|
||
(colors, stack_space) | ||
} | ||
} | ||
|
||
fn arg_from_color(i: isize) -> Arg { | ||
match i { | ||
-5 => Arg::Reg { reg: Reg::R15 }, | ||
-4 => Arg::Reg { reg: Reg::R11 }, | ||
-3 => Arg::Reg { reg: Reg::RBP }, | ||
-2 => Arg::Reg { reg: Reg::RSP }, | ||
-1 => Arg::Reg { reg: Reg::RAX }, | ||
0 => Arg::Reg { reg: Reg::RCX }, | ||
1 => Arg::Reg { reg: Reg::RDX }, | ||
2 => Arg::Reg { reg: Reg::RSI }, | ||
3 => Arg::Reg { reg: Reg::RDI }, | ||
4 => Arg::Reg { reg: Reg::R8 }, | ||
5 => Arg::Reg { reg: Reg::R9 }, | ||
6 => Arg::Reg { reg: Reg::R10 }, | ||
7 => Arg::Reg { reg: Reg::RBX }, | ||
8 => Arg::Reg { reg: Reg::R12 }, | ||
9 => Arg::Reg { reg: Reg::R13 }, | ||
10 => Arg::Reg { reg: Reg::R14 }, | ||
i => { | ||
assert!( | ||
i > 10, | ||
"Something went wrong while coloring the assign graph." | ||
); | ||
Arg::Deref { | ||
reg: Reg::RBP, | ||
off: (-8 * (i - 10)) as i64, | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.