To protect your data, the CISO officer has suggested users to enable 2FA as soon as possible.
Currently 2.7% 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"]
......
...@@ -258,6 +258,13 @@ impl FunctionContext { ...@@ -258,6 +258,13 @@ impl FunctionContext {
}) })
} }
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
} }
...@@ -55,6 +57,10 @@ impl CompilerPass for PeepholeOptimization { ...@@ -55,6 +57,10 @@ impl CompilerPass for PeepholeOptimization {
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();
let mut cf = compiled_funcs.get(&func.id()).unwrap().write().unwrap(); let mut cf = compiled_funcs.get(&func.id()).unwrap().write().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();
// //
......
...@@ -125,13 +125,18 @@ impl InterferenceGraph { ...@@ -125,13 +125,18 @@ impl InterferenceGraph {
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,
// they may interefere
if self.nodes_property.get(&from).unwrap().group
== self.nodes_property.get(&to).unwrap().group {
self.matrix.as_mut().unwrap()[(from.0, to.0)] = true; self.matrix.as_mut().unwrap()[(from.0, to.0)] = true;
} }
pub fn is_interferenced_with(&self, node1: Node, node2: Node) -> bool {
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() {
...@@ -243,7 +251,10 @@ impl InterferenceGraph { ...@@ -243,7 +251,10 @@ impl InterferenceGraph {
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)
};
trace!("replacing {} with {}", temp, machine_reg);
coloring.cf.mc_mut().replace_reg(temp, machine_reg);
coloring.cf.temps.insert(temp, machine_reg);
}
}
coloring.cf.mc().trace_mc();