WARNING! Access to this system is limited to authorised users only.
Unauthorised users may be subject to prosecution.
Unauthorised access to this system is a criminal offence under Australian law (Federal Crimes Act 1914 Part VIA)
It is a criminal offence to:
(1) Obtain access to data without authority. -Penalty 2 years imprisonment.
(2) Damage, delete, alter or insert data without authority. -Penalty 10 years imprisonment.
User activity is monitored and recorded. Anyone using this system expressly consents to such monitoring and recording.

To protect your data, the CISO officer has suggested users to enable 2FA as soon as possible.
Currently 2.2% of users enabled 2FA.

Commit f83e4dde authored by qinsoon's avatar qinsoon
Browse files

[wip] debugging

parent b77b1887
...@@ -5,7 +5,7 @@ authors = [ "Your name <you@example.com>" ] ...@@ -5,7 +5,7 @@ authors = [ "Your name <you@example.com>" ]
build = "build.rs" build = "build.rs"
[lib] [lib]
crate-type = ["staticlib", "rlib"] crate-type = ["staticlib", "rlib", "dylib"]
[features] [features]
default = ["aot"] default = ["aot"]
......
...@@ -256,7 +256,14 @@ impl FunctionContext { ...@@ -256,7 +256,14 @@ impl FunctionContext {
op: pick_op_code_for_ssa(&val.ty), op: pick_op_code_for_ssa(&val.ty),
v: TreeNode_::Value(val) v: TreeNode_::Value(val)
}) })
} }
pub fn get_temp_display(&self, id: MuID) -> String {
match self.get_value(id) {
Some(entry) => format!("{}", entry.value()),
None => "CANT_FOUND_ID".to_string()
}
}
pub fn get_value(&self, id: MuID) -> Option<&SSAVarEntry> { pub fn get_value(&self, id: MuID) -> Option<&SSAVarEntry> {
self.values.get(&id) self.values.get(&id)
......
...@@ -21,6 +21,7 @@ use compiler::machine_code::CompiledFunction; ...@@ -21,6 +21,7 @@ use compiler::machine_code::CompiledFunction;
use compiler::frame::Frame; use compiler::frame::Frame;
use std::collections::HashMap; use std::collections::HashMap;
use std::any::Any;
pub struct InstructionSelection { pub struct InstructionSelection {
name: &'static str, name: &'static str,
...@@ -1286,6 +1287,10 @@ impl CompilerPass for InstructionSelection { ...@@ -1286,6 +1287,10 @@ impl CompilerPass for InstructionSelection {
self.name self.name
} }
fn as_any(&self) -> &Any {
self
}
#[allow(unused_variables)] #[allow(unused_variables)]
fn start_function(&mut self, vm: &VM, func_ver: &mut MuFunctionVersion) { fn start_function(&mut self, vm: &VM, func_ver: &mut MuFunctionVersion) {
debug!("{}", self.name()); debug!("{}", self.name());
......
...@@ -5,6 +5,8 @@ use ast::ir::*; ...@@ -5,6 +5,8 @@ use ast::ir::*;
use vm::VM; use vm::VM;
use compiler::backend::emit_code; use compiler::backend::emit_code;
use std::any::Any;
pub struct CodeEmission { pub struct CodeEmission {
name: &'static str name: &'static str
} }
...@@ -22,6 +24,10 @@ impl CompilerPass for CodeEmission { ...@@ -22,6 +24,10 @@ impl CompilerPass for CodeEmission {
self.name self.name
} }
fn as_any(&self) -> &Any {
self
}
fn visit_function(&mut self, vm: &VM, func: &mut MuFunctionVersion) { fn visit_function(&mut self, vm: &VM, func: &mut MuFunctionVersion) {
emit_code(func, vm); emit_code(func, vm);
} }
......
...@@ -3,6 +3,8 @@ use ast::ir::*; ...@@ -3,6 +3,8 @@ use ast::ir::*;
use vm::VM; use vm::VM;
use compiler::machine_code::CompiledFunction; use compiler::machine_code::CompiledFunction;
use std::any::Any;
pub struct PeepholeOptimization { pub struct PeepholeOptimization {
name: &'static str name: &'static str
} }
...@@ -54,6 +56,10 @@ impl CompilerPass for PeepholeOptimization { ...@@ -54,6 +56,10 @@ impl CompilerPass for PeepholeOptimization {
fn name(&self) -> &'static str { fn name(&self) -> &'static str {
self.name self.name
} }
fn as_any(&self) -> &Any {
self
}
fn visit_function(&mut self, vm: &VM, func: &mut MuFunctionVersion) { fn visit_function(&mut self, vm: &VM, func: &mut MuFunctionVersion) {
let compiled_funcs = vm.compiled_funcs().read().unwrap(); let compiled_funcs = vm.compiled_funcs().read().unwrap();
......
...@@ -15,7 +15,11 @@ use std::collections::HashMap; ...@@ -15,7 +15,11 @@ use std::collections::HashMap;
const COALESCING : bool = true; const COALESCING : bool = true;
pub struct GraphColoring { pub struct GraphColoring<'a> {
pub func: &'a mut MuFunctionVersion,
pub cf: &'a mut CompiledFunction,
pub vm: &'a VM,
pub ig: InterferenceGraph, pub ig: InterferenceGraph,
precolored: LinkedHashSet<Node>, precolored: LinkedHashSet<Node>,
...@@ -44,12 +48,18 @@ pub struct GraphColoring { ...@@ -44,12 +48,18 @@ pub struct GraphColoring {
select_stack: Vec<Node> select_stack: Vec<Node>
} }
impl GraphColoring { impl <'a> GraphColoring<'a> {
pub fn start (func: &mut MuFunctionVersion, cf: &mut CompiledFunction, vm: &VM) -> Result<GraphColoring, RegAllocFailure> { pub fn start (func: &'a mut MuFunctionVersion, cf: &'a mut CompiledFunction, vm: &'a VM) -> Result<GraphColoring<'a>, RegAllocFailure> {
cf.mc().trace_mc(); cf.mc().trace_mc();
let ig = graph_coloring::build_inteference_graph(cf, func);
let mut coloring = GraphColoring { let mut coloring = GraphColoring {
ig: graph_coloring::build_inteference_graph(cf, func), func: func,
cf: cf,
vm: vm,
ig: ig,
precolored: LinkedHashSet::new(), precolored: LinkedHashSet::new(),
colors: { colors: {
...@@ -82,21 +92,14 @@ impl GraphColoring { ...@@ -82,21 +92,14 @@ impl GraphColoring {
select_stack: Vec::new() select_stack: Vec::new()
}; };
match coloring.regalloc(func, cf, vm) { coloring.regalloc()
Ok(_) => Ok(coloring),
Err(fail) => Err(fail)
}
} }
fn regalloc(&mut self, func: &mut MuFunctionVersion, cf: &mut CompiledFunction, vm: &VM) -> Result<(), RegAllocFailure> { fn regalloc(mut self) -> Result<GraphColoring<'a>, RegAllocFailure> {
trace!("Initializing coloring allocator..."); trace!("Initializing coloring allocator...");
trace!("---InterenceGraph---"); trace!("---InterenceGraph---");
self.ig.print(); self.ig.print(&self.func.context);
trace!("---All temps---");
for entry in func.context.values.values() {
trace!("{}", entry);
}
// precolor for all machine registers // precolor for all machine registers
for reg in backend::all_regs().values() { for reg in backend::all_regs().values() {
...@@ -117,7 +120,11 @@ impl GraphColoring { ...@@ -117,7 +120,11 @@ impl GraphColoring {
self.initial.push(node); self.initial.push(node);
let outdegree = self.ig.outdegree_of(node); let outdegree = self.ig.outdegree_of(node);
self.degree.insert(node, outdegree); self.degree.insert(node, outdegree);
trace!("{} has a degree of {}", self.node_info(node), outdegree);
trace!("{} has a degree of {}", {
let id = self.ig.get_temp_of(node);
self.func.context.get_temp_display(id)
}, outdegree);
} }
} }
...@@ -152,12 +159,12 @@ impl GraphColoring { ...@@ -152,12 +159,12 @@ impl GraphColoring {
} }
} }
self.rewrite_program(func, cf, vm); self.rewrite_program();
GraphColoring::start(func, cf, vm); return GraphColoring::start(self.func, self.cf, self.vm);
} }
Ok(()) Ok(self)
} }
fn build(&mut self) { fn build(&mut self) {
...@@ -612,23 +619,23 @@ impl GraphColoring { ...@@ -612,23 +619,23 @@ impl GraphColoring {
Ok(()) Ok(())
} }
fn rewrite_program(&mut self, func: &mut MuFunctionVersion, cf: &mut CompiledFunction, vm: &VM) { fn rewrite_program(&mut self) {
let spills = self.spills(); let spills = self.spills();
let mut spilled_mem = HashMap::new(); let mut spilled_mem = HashMap::new();
// allocating frame slots for every spilled temp // allocating frame slots for every spilled temp
for reg_id in spills.iter() { for reg_id in spills.iter() {
let ssa_entry = match func.context.get_value(*reg_id) { let ssa_entry = match self.func.context.get_value(*reg_id) {
Some(entry) => entry, Some(entry) => entry,
None => panic!("The spilled register {} is not in func context", reg_id) None => panic!("The spilled register {} is not in func context", reg_id)
}; };
let mem = cf.frame.alloc_slot_for_spilling(ssa_entry.value().clone(), vm); let mem = self.cf.frame.alloc_slot_for_spilling(ssa_entry.value().clone(), self.vm);
spilled_mem.insert(*reg_id, mem); spilled_mem.insert(*reg_id, mem);
} }
let new_temps = backend::spill_rewrite(&spilled_mem, func, cf, vm); let new_temps = backend::spill_rewrite(&spilled_mem, self.func, self.cf, self.vm);
// //
// self.spilled_nodes.clear(); // self.spilled_nodes.clear();
// //
......
...@@ -124,14 +124,19 @@ impl InterferenceGraph { ...@@ -124,14 +124,19 @@ impl InterferenceGraph {
fn add_move(&mut self, src: Node, dst: Node) { fn add_move(&mut self, src: Node, dst: Node) {
self.moves.insert(Move{from: src, to: dst}); self.moves.insert(Move{from: src, to: dst});
} }
pub fn is_same_group(&self, node1: Node, node2: Node) -> bool {
self.nodes_property.get(&node1).unwrap().group
== self.nodes_property.get(&node2).unwrap().group
}
pub fn add_interference_edge(&mut self, from: Node, to: Node) { pub fn add_interference_edge(&mut self, from: Node, to: Node) {
// only if two nodes are from the same RegGroup, self.matrix.as_mut().unwrap()[(from.0, to.0)] = true;
// they may interefere }
if self.nodes_property.get(&from).unwrap().group
== self.nodes_property.get(&to).unwrap().group { pub fn is_interferenced_with(&self, node1: Node, node2: Node) -> bool {
self.matrix.as_mut().unwrap()[(from.0, to.0)] = true; self.matrix.as_ref().unwrap()[(node1.0, node2.0)]
} || self.matrix.as_ref().unwrap()[(node2.0, node1.0)]
} }
pub fn color_node(&mut self, node: Node, color: MuID) { pub fn color_node(&mut self, node: Node, color: MuID) {
...@@ -207,18 +212,21 @@ impl InterferenceGraph { ...@@ -207,18 +212,21 @@ impl InterferenceGraph {
self.outdegree_of(node) + self.indegree_of(node) self.outdegree_of(node) + self.indegree_of(node)
} }
pub fn print(&self) { pub fn print(&self, context: &FunctionContext) {
println!(""); println!("");
println!("Interference Graph"); println!("Interference Graph");
println!("nodes:"); println!("nodes:");
for id in self.nodes.keys() { for id in self.nodes.keys() {
println!("Reg {} -> {:?}", id, self.nodes.get(&id).unwrap()); let val = context.get_value(*id).unwrap().value();
println!("Reg {} -> {:?}", val, self.nodes.get(&id).unwrap());
} }
println!("color:"); println!("color:");
for (n, c) in self.nodes_property.iter() { for (node, color) in self.nodes_property.iter() {
println!("{:?} -> Color/Reg {:?}", n, c); let node_val = context.get_value(self.get_temp_of(*node)).unwrap().value();
let color_val = context.get_value(color.temp).unwrap().value();
println!("Reg {} of {:?} -> Color/Reg {}", node_val, node, color_val);
} }
println!("moves:"); println!("moves:");
for mov in self.moves.iter() { for mov in self.moves.iter() {
...@@ -242,8 +250,11 @@ impl InterferenceGraph { ...@@ -242,8 +250,11 @@ impl InterferenceGraph {
if matrix[(i, j)] { if matrix[(i, j)] {
let from_node = node_to_reg_id.get(&Node(i)).unwrap(); let from_node = node_to_reg_id.get(&Node(i)).unwrap();
let to_node = node_to_reg_id.get(&Node(j)).unwrap(); let to_node = node_to_reg_id.get(&Node(j)).unwrap();
println!("Reg {} -> Reg {}", from_node, to_node); let from_val = context.get_value(*from_node).unwrap().value();
let to_val = context.get_value(*to_node).unwrap().value();
println!("Reg {} -> Reg {}", from_val, to_val);
} }
} }
} }
...@@ -355,14 +366,29 @@ pub fn build_chaitin_briggs (cf: &mut CompiledFunction, func: &MuFunctionVersion ...@@ -355,14 +366,29 @@ pub fn build_chaitin_briggs (cf: &mut CompiledFunction, func: &MuFunctionVersion
Some(liveout) => liveout.to_vec(), Some(liveout) => liveout.to_vec(),
None => panic!("cannot find liveout for block {}", block) None => panic!("cannot find liveout for block {}", block)
}); });
if cfg!(debug_assertions) {
trace!("Block{}: live out", block);
for ele in current_live.iter() {
trace!("{}", func.context.get_temp_display(*ele));
}
}
let range = cf.mc().get_block_range(&block); let range = cf.mc().get_block_range(&block);
if range.is_none() { if range.is_none() {
warn!("Block{}: has no range (no instructions?)", block);
continue; continue;
} }
trace!("Block{}: range = {:?}", block, range.as_ref().unwrap());
// for every inst I in reverse order // for every inst I in reverse order
for i in range.unwrap().rev() { for i in range.unwrap().rev() {
if cfg!(debug_assertions) {
trace!("Block{}: Inst{}: start. current_live:", block, i);
for ele in current_live.iter() {
trace!("{}", func.context.get_temp_display(*ele));
}
}
let src : Option<MuID> = { let src : Option<MuID> = {
if cf.mc().is_move(i) { if cf.mc().is_move(i) {
let src = cf.mc().get_inst_reg_uses(i); let src = cf.mc().get_inst_reg_uses(i);
...@@ -377,6 +403,9 @@ pub fn build_chaitin_briggs (cf: &mut CompiledFunction, func: &MuFunctionVersion ...@@ -377,6 +403,9 @@ pub fn build_chaitin_briggs (cf: &mut CompiledFunction, func: &MuFunctionVersion
if src.len() == 1 { if src.len() == 1 {
let node1 = ig.get_node(src[0]); let node1 = ig.get_node(src[0]);
let node2 = ig.get_node(dst[0]); let node2 = ig.get_node(dst[0]);
trace!("add move between {} and {}",
func.context.get_temp_display(src[0]),
func.context.get_temp_display(dst[0]));
ig.add_move(node1, node2); ig.add_move(node1, node2);
Some(src[0]) Some(src[0])
...@@ -388,21 +417,34 @@ pub fn build_chaitin_briggs (cf: &mut CompiledFunction, func: &MuFunctionVersion ...@@ -388,21 +417,34 @@ pub fn build_chaitin_briggs (cf: &mut CompiledFunction, func: &MuFunctionVersion
None None
} }
}; };
trace!("Block{}: Inst{}: src={:?}", block, i, src);
// for every definition D in I // for every definition D in I
for d in cf.mc().get_inst_reg_defines(i) { for d in cf.mc().get_inst_reg_defines(i) {
trace!("Block{}: Inst{}: for definition {}", block, i, func.context.get_temp_display(d));
// add an interference from D to every element E in Current_Live - {D} // add an interference from D to every element E in Current_Live - {D}
// creating nodes if necessary // creating nodes if necessary
for e in current_live.iter() { for e in current_live.iter() {
trace!("Block{}: Inst{}: for each live {}",
block, i,
func.context.get_temp_display(*e));
if src.is_none() || (src.is_some() && *e != src.unwrap()) { if src.is_none() || (src.is_some() && *e != src.unwrap()) {
let from = ig.get_node(d); let from = ig.get_node(d);
let to = ig.get_node(*e); let to = ig.get_node(*e);
if !ig.is_same_node(from, to) && !ig.is_adj(from, to) { if !ig.is_same_node(from, to) &&ig.is_same_group(from, to) && !ig.is_adj(from, to) {
if !ig.is_colored(from) { if !ig.is_colored(from) {
trace!("Block{}: Inst{}: add interference between {} and {}",
block, i,
func.context.get_temp_display(d),
func.context.get_temp_display(*e));
ig.add_interference_edge(from, to); ig.add_interference_edge(from, to);
} }
if !ig.is_colored(to) { if !ig.is_colored(to) {
trace!("Block{}: Inst{}: add interference between {} and {}",
block, i,
func.context.get_temp_display(*e),
func.context.get_temp_display(d));
ig.add_interference_edge(to, from); ig.add_interference_edge(to, from);
} }
} }
...@@ -412,15 +454,28 @@ pub fn build_chaitin_briggs (cf: &mut CompiledFunction, func: &MuFunctionVersion ...@@ -412,15 +454,28 @@ pub fn build_chaitin_briggs (cf: &mut CompiledFunction, func: &MuFunctionVersion
// for every definition D in I // for every definition D in I
for d in cf.mc().get_inst_reg_defines(i) { for d in cf.mc().get_inst_reg_defines(i) {
trace!("Block{}: Inst{}: remove define {} from current_live",
block, i,
func.context.get_temp_display(d));
// remove D from Current_Live // remove D from Current_Live
current_live.remove(&d); current_live.remove(&d);
} }
// for every use U in I // for every use U in I
for u in cf.mc().get_inst_reg_uses(i) { for u in cf.mc().get_inst_reg_uses(i) {
trace!("Block{}: Inst{}: add use {} to current_live",
block, i,
func.context.get_temp_display(u));
// add U to Current_live // add U to Current_live
current_live.insert(u); current_live.insert(u);
} }
if cfg!(debug_assertions) {
trace!("Block{}: Inst{}: done. current_live:", block, i);
for ele in current_live.iter() {
trace!("{}", func.context.get_temp_display(*ele));
}
}
} }
} }
......
...@@ -5,3 +5,92 @@ pub use compiler::backend::reg_alloc::graph_coloring::liveness::InterferenceGrap ...@@ -5,3 +5,92 @@ pub use compiler::backend::reg_alloc::graph_coloring::liveness::InterferenceGrap
//pub use compiler::backend::reg_alloc::graph_coloring::liveness::build as build_inteference_graph; //pub use compiler::backend::reg_alloc::graph_coloring::liveness::build as build_inteference_graph;
pub use compiler::backend::reg_alloc::graph_coloring::liveness::build_chaitin_briggs as build_inteference_graph; pub use compiler::backend::reg_alloc::graph_coloring::liveness::build_chaitin_briggs as build_inteference_graph;
pub use compiler::backend::reg_alloc::graph_coloring::coloring::GraphColoring; pub use compiler::backend::reg_alloc::graph_coloring::coloring::GraphColoring;
use ast::ir::*;
use vm::VM;
use compiler;
use compiler::CompilerPass;
use compiler::PassExecutionResult;
use compiler::backend::init_machine_regs_for_func;
use compiler::backend;
use compiler::backend::reg_alloc::RegAllocFailure;
use std::collections::HashMap;
use std::any::Any;
pub struct RegisterAllocation {
name: &'static str,
}
impl RegisterAllocation {
pub fn new() -> RegisterAllocation {
RegisterAllocation {
name: "Register Allocation",
}
}
#[allow(unused_variables)]
fn coloring(&mut self, vm: &VM, func: &mut MuFunctionVersion) -> Result<(), RegAllocFailure> {
let compiled_funcs = vm.compiled_funcs().read().unwrap();
let mut cf = compiled_funcs.get(&func.id()).unwrap().write().unwrap();
// initialize machine registers for the function context
init_machine_regs_for_func(&mut func.context);
let coloring = match GraphColoring::start(func, &mut cf, vm) {
Ok(coloring) => coloring,
Err(_) => panic!("error during coloring - unexpected")
};
// replace regs
trace!("Replacing Registers...");
for node in coloring.ig.nodes() {
let temp = coloring.ig.get_temp_of(node);
// skip machine registers
if temp < MACHINE_ID_END {
continue;
} else {
let alias = coloring.get_alias(node);
let machine_reg = match coloring.ig.get_color_of(alias) {
Some(reg) => reg,
None => panic!(
"Reg{}/{:?} (aliased as Reg{}/{:?}) is not assigned with a color",
coloring.ig.get_temp_of(node), node,
coloring.ig.get_temp_of(alias), alias)
};