GitLab will continue to be upgraded from 11.4.5-ce.0 on November 25th 2019 at 4.00pm (AEDT) to 5.00pm (AEDT) due to Critical Security Patch Availability. During the update, GitLab and Mattermost services will not be available.

Commit 832c8b0e authored by qinsoon's avatar qinsoon

[wip] output machine code as dot graph as well

parent a82c8931
Pipeline #321 failed with stage
in 42 minutes and 1 second
......@@ -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