Commit e91f7785 authored by qinsoon's avatar qinsoon

[wip] debugging. Some coloring choices are still wrong

parent def9deb3
#![allow(unused_variables)]
use compiler::backend;
use compiler::backend::x86_64;
use compiler::backend::x86_64::CodeGenerator;
use vm::machine_code::MachineCode;
use utils::string_utils;
use ast::ptr::P;
use ast::ir::*;
use ast::inst::*;
......@@ -56,6 +59,35 @@ impl MachineCode for ASMCode {
&self.code[index].defines
}
fn replace_reg(&mut self, from: MuID, to: MuID) {
let to_reg_tag : MuTag = backend::all_regs()[to].tag;
let to_reg_string = "%".to_string() + to_reg_tag;
match self.reg_defines.get(&from) {
Some(defines) => {
for loc in defines {
let ref mut inst_to_patch = self.code[loc.line];
for i in 0..loc.len {
string_utils::replace(&mut inst_to_patch.code, loc.index, &to_reg_string, to_reg_string.len());
}
}
},
None => {}
}
match self.reg_uses.get(&from) {
Some(uses) => {
for loc in uses {
let ref mut inst_to_patch = self.code[loc.line];
for i in 0..loc.len {
string_utils::replace(&mut inst_to_patch.code, loc.index, &to_reg_string, to_reg_string.len());
}
}
},
None => {}
}
}
fn print(&self) {
println!("");
......@@ -142,7 +174,7 @@ pub struct ASMCodeGen {
cur: Option<Box<ASMCode>>
}
const REG_PLACEHOLDER_LEN : usize = 3;
const REG_PLACEHOLDER_LEN : usize = 5;
lazy_static! {
pub static ref REG_PLACEHOLDER : String = {
let blank_spaces = [' ' as u8; REG_PLACEHOLDER_LEN];
......@@ -170,18 +202,6 @@ impl ASMCodeGen {
self.cur().code.len()
}
fn replace(s: &mut String, index: usize, replace: &str, replace_len: usize) {
let vec = unsafe {s.as_mut_vec()};
for i in 0..replace_len {
if i < replace.len() {
vec[index + i] = replace.as_bytes()[i] as u8;
} else {
vec[index + i] = ' ' as u8;
}
}
}
fn add_asm_block_label(&mut self, code: String, block_name: &'static str) {
let l = self.line();
self.cur_mut().code.push(ASM::symbolic(code));
......@@ -489,10 +509,10 @@ impl CodeGenerator for ASMCodeGen {
fn emit_mov_r64_r64(&mut self, dest: &P<Value>, src: &P<Value>) {
trace!("emit: mov {} -> {}", src, dest);
let (reg1, id1, loc1) = self.prepare_op(dest, 4 + 1);
let (reg2, id2, loc2) = self.prepare_op(src, 4 + 1 + reg1.len() + 1);
let (reg1, id1, loc1) = self.prepare_op(src, 4 + 1);
let (reg2, id2, loc2) = self.prepare_op(dest, 4 + 1 + reg1.len() + 1);
let asm = format!("movq {} {}", reg2, reg1);
let asm = format!("movq {} {}", reg1, reg2);
self.add_asm_inst(
asm,
......@@ -506,10 +526,10 @@ impl CodeGenerator for ASMCodeGen {
fn emit_add_r64_r64(&mut self, dest: &P<Value>, src: &P<Value>) {
trace!("emit: add {}, {} -> {}", dest, src, dest);
let (reg1, id1, loc1) = self.prepare_op(dest, 4 + 1);
let (reg2, id2, loc2) = self.prepare_op(src, 4 + 1 + reg1.len() + 1);
let (reg1, id1, loc1) = self.prepare_op(src, 4 + 1);
let (reg2, id2, loc2) = self.prepare_op(dest, 4 + 1 + reg1.len() + 1);
let asm = format!("addq {} {}", reg2, reg1);
let asm = format!("addq {} {}", reg1, reg2);
self.add_asm_inst(
asm,
......@@ -544,10 +564,10 @@ impl CodeGenerator for ASMCodeGen {
fn emit_sub_r64_r64(&mut self, dest: &P<Value>, src: &P<Value>) {
trace!("emit: sub {}, {} -> {}", dest, src, dest);
let (reg1, id1, loc1) = self.prepare_op(dest, 4 + 1);
let (reg2, id2, loc2) = self.prepare_op(src, 4 + 1 + reg1.len() + 1);
let (reg1, id1, loc1) = self.prepare_op(src, 4 + 1);
let (reg2, id2, loc2) = self.prepare_op(dest, 4 + 1 + reg1.len() + 1);
let asm = format!("subq {} {}", reg2, reg1);
let asm = format!("subq {} {}", reg1, reg2);
self.add_asm_inst(
asm,
......@@ -566,9 +586,9 @@ impl CodeGenerator for ASMCodeGen {
fn emit_sub_r64_imm32(&mut self, dest: &P<Value>, src: u32) {
trace!("emit: sub {}, {} -> {}", dest, src, dest);
let (reg1, id1, loc1) = self.prepare_op(dest, 4 + 1);
let (reg1, id1, loc1) = self.prepare_op(dest, 4 + 1 + 1 + src.to_string().len() + 1);
let asm = format!("subq {} ${}", src, reg1);
let asm = format!("subq ${} {}", src, reg1);
self.add_asm_inst(
asm,
......
......@@ -13,13 +13,12 @@ use std::collections::HashMap;
const COALESCING : bool = true;
pub struct GraphColoring <'a> {
ig: InterferenceGraph,
cur_cf: &'a CompiledFunction,
pub struct GraphColoring {
pub ig: InterferenceGraph,
precolored: HashSet<Node>,
colors: HashMap<backend::RegGroup, HashSet<MuID>>,
colored_nodes: Vec<Node>,
pub colored_nodes: Vec<Node>,
initial: Vec<Node>,
degree: HashMap<Node, isize>,
......@@ -43,11 +42,10 @@ pub struct GraphColoring <'a> {
select_stack: Vec<Node>
}
impl <'a> GraphColoring <'a> {
pub fn start (cf: &CompiledFunction, ig: InterferenceGraph) -> GraphColoring {
impl GraphColoring {
pub fn start (ig: InterferenceGraph) -> GraphColoring {
let mut coloring = GraphColoring {
ig: ig,
cur_cf: cf,
precolored: HashSet::new(),
colors: {
......@@ -359,7 +357,7 @@ impl <'a> GraphColoring <'a> {
}
}
fn get_alias(&self, node: Node) -> Node {
pub fn get_alias(&self, node: Node) -> Node {
if self.coalesced_nodes.contains(&node) {
self.get_alias(*self.alias.get(&node).unwrap())
} else {
......
......@@ -92,6 +92,14 @@ impl InterferenceGraph {
}
}
pub fn temps(&self) -> Vec<MuID>{
let mut ret = vec![];
for reg in self.nodes.keys() {
ret.push(*reg);
}
ret
}
pub fn nodes(&self) -> Vec<Node> {
let mut ret = vec![];
for node in self.nodes.values() {
......
......@@ -28,7 +28,7 @@ impl CompilerPass for RegisterAllocation {
#[allow(unused_variables)]
fn visit_function(&mut self, vm_context: &VMContext, func: &mut MuFunction) {
let mut compiled_funcs = vm_context.compiled_funcs().read().unwrap();
let compiled_funcs = vm_context.compiled_funcs().read().unwrap();
let mut cf = compiled_funcs.get(func.fn_name).unwrap().borrow_mut();
cf.mc.print();
......@@ -39,7 +39,30 @@ impl CompilerPass for RegisterAllocation {
let liveness = liveness::build(&mut cf, func);
liveness.print();
let coloring = coloring::GraphColoring::start(&mut cf, liveness);
let coloring = coloring::GraphColoring::start(liveness);
let spills = coloring.spills();
if !spills.is_empty() {
unimplemented!();
}
// replace regs
trace!("Replacing Registers...");
for node in coloring.ig.nodes() {
let temp = coloring.ig.get_temp_of(node);
// skip machine registers
if temp < RESERVED_NODE_IDS_FOR_MACHINE {
continue;
} else {
let alias = coloring.get_alias(node);
let machine_reg = coloring.ig.get_color_of(alias).unwrap();
trace!("replacing {} with {}", temp, machine_reg);
cf.mc.replace_reg(temp, machine_reg);
}
}
cf.mc.print();
}
}
\ No newline at end of file
#![allow(dead_code)]
// This porvides some missing operations on Vec.
// They are not included in the standard libarary.
// (because they are likely inefficient?)
......@@ -45,4 +47,19 @@ pub mod hashset_utils {
set.take(&next)
}
}
}
pub mod string_utils {
pub fn replace(s: &mut String, index: usize, replace: &String, replace_len: usize) {
let vec = unsafe {s.as_mut_vec()};
let vec_replace = replace.as_bytes();
for i in 0..replace_len {
if i < replace.len() {
vec[index + i] = vec_replace[i] as u8;
} else {
vec[index + i] = ' ' as u8;
}
}
}
}
\ No newline at end of file
......@@ -16,4 +16,6 @@ pub trait MachineCode {
fn get_inst_reg_uses(&self, index: usize) -> &Vec<MuID>;
fn get_inst_reg_defines(&self, index: usize) -> &Vec<MuID>;
fn replace_reg(&mut self, from: MuID, to: MuID);
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment