Commit 832c8b0e authored by qinsoon's avatar qinsoon

[wip] output machine code as dot graph as well

parent a82c8931
......@@ -650,8 +650,9 @@ impl MachineCode for ASMCode {
}
fn set_inst_nop(&mut self, index: usize) {
self.code.remove(index);
self.code.insert(index, ASMInst::nop());
self.code[index].code.clear();
// self.code.remove(index);
// self.code.insert(index, ASMInst::nop());
}
fn remove_unnecessary_callee_saved(&mut self, used_callee_saved: Vec<MuID>) -> Vec<MuID> {
......@@ -738,6 +739,20 @@ impl MachineCode for ASMCode {
ret
}
fn emit_inst(&self, index: usize) -> Vec<u8> {
let mut ret = vec![];
let ref inst = self.code[index];
if !inst.is_symbol {
ret.append(&mut "\t".to_string().into_bytes());
}
ret.append(&mut inst.code.clone().into_bytes());
ret
}
fn trace_mc(&self) {
trace!("");
......@@ -797,6 +812,16 @@ impl MachineCode for ASMCode {
}
}
fn get_block_for_inst(&self, index: usize) -> Option<MuName> {
for (name, block) in self.blocks.iter() {
if index >= block.start_inst && index < block.end_inst {
return Some(name.clone());
}
}
None
}
fn get_next_inst(&self, index: usize) -> Option<usize> {
ASMCode::find_next_inst(index, &self.code)
}
......
......@@ -9,8 +9,10 @@ use std::any::Any;
use std::path;
use std::io::prelude::*;
use std::fs::File;
use std::collections::HashMap;
const EMIT_MUIR : bool = true;
const EMIT_MC_DOT : bool = true;
pub fn create_emit_directory(vm: &VM) {
use std::fs;
......@@ -20,6 +22,17 @@ pub fn create_emit_directory(vm: &VM) {
}
}
fn create_emit_file(name: String, vm: &VM) -> File {
let mut file_path = path::PathBuf::new();
file_path.push(&vm.vm_options.flag_aot_emit_dir);
file_path.push(name);
match File::create(file_path.as_path()) {
Err(why) => panic!("couldn't create emit file {}: {}", file_path.to_str().unwrap(), why),
Ok(file) => file
}
}
pub struct CodeEmission {
name: &'static str
}
......@@ -128,12 +141,12 @@ fn emit_muir_dot_inner(file: &mut File,
file.write_fmt(format_args!("digraph {} {{\n", f_name)).unwrap();
// node shape: rect
file.write("node [shape=rect];".as_bytes()).unwrap();
file.write("node [shape=rect];\n".as_bytes()).unwrap();
// every graph node (basic block)
for (id, block) in f_content.blocks.iter() {
let block_name = block.name().unwrap();
// BBid: [label = "name
// BBid [label = "name
file.write_fmt(format_args!("BB{} [label = \"{} ", *id, &block_name)).unwrap();
let block_content = block.content.as_ref().unwrap();
......@@ -257,6 +270,77 @@ fn emit_muir_dot_inner(file: &mut File,
file.write("}".as_bytes()).unwrap();
}
fn emit_mc_dot(func: &MuFunctionVersion, vm: &VM) {
let func_name = match func.name() {
Some(name) => name,
None => {
// use func name
vm.name_of(func.func_id)
}
};
// create emit directory/file
create_emit_directory(vm);
let mut file = create_emit_file(func_name.clone() + "_mc.dot", &vm);
// diagraph func {
file.write_fmt(format_args!("digraph {} {{\n", func_name)).unwrap();
// node shape: rect
file.write("node [shape=rect];\n".as_bytes()).unwrap();
let compiled_funcs = vm.compiled_funcs().read().unwrap();
let cf = compiled_funcs.get(&func.id()).unwrap().read().unwrap();
let mc = cf.mc();
let blocks = mc.get_all_blocks();
type DotID = usize;
let name_id_map : HashMap<MuName, DotID> = {
let mut ret = HashMap::new();
let mut index = 0;
for block_name in blocks.iter() {
ret.insert(block_name.clone(), index);
index += 1;
}
ret
};
let id = |x: MuName| name_id_map.get(&x).unwrap();
for block_name in blocks.iter() {
// BB [label = "
file.write_fmt(format_args!("{} [label = \"{}:\\n\\n", id(block_name.clone()), block_name)).unwrap();
for inst in mc.get_block_range(&block_name).unwrap() {
file.write(&mc.emit_inst(inst)).unwrap();
file.write("\\l".as_bytes()).unwrap();
}
// "];
file.write("\"];\n".as_bytes()).unwrap();
}
for block_name in blocks.iter() {
let end_inst = mc.get_block_range(block_name).unwrap().end;
for succ in mc.get_succs(mc.get_last_inst(end_inst).unwrap()).into_iter() {
match mc.get_block_for_inst(*succ) {
Some(target) => {
let source_id = id(block_name.clone());
let target_id = id(target.clone());
file.write_fmt(format_args!("{} -> {};\n", source_id, target_id)).unwrap();
}
None => {
panic!("cannot find block for inst {}", succ);
}
}
}
}
file.write("}".as_bytes()).unwrap();
}
impl CompilerPass for CodeEmission {
fn name(&self) -> &'static str {
self.name
......@@ -272,5 +356,9 @@ impl CompilerPass for CodeEmission {
if EMIT_MUIR {
emit_muir_dot(func, vm);
}
if EMIT_MC_DOT {
emit_mc_dot(func, vm);
}
}
}
......@@ -146,6 +146,7 @@ pub trait MachineCode {
fn trace_inst(&self, index: usize);
fn emit(&self) -> Vec<u8>;
fn emit_inst(&self, index: usize) -> Vec<u8>;
fn number_of_insts(&self) -> usize;
......@@ -175,6 +176,7 @@ pub trait MachineCode {
fn get_entry_block(&self) -> MuName;
// returns [start_inst, end_inst) // end_inst not included
fn get_block_range(&self, block: &str) -> Option<ops::Range<usize>>;
fn get_block_for_inst(&self, index: usize) -> Option<MuName>;
// functions for rewrite
......
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