GitLab will be upgraded on June 2nd 2020 at 2.00 pm (AEDT) to 3.00 pm (AEDT) due to Critical Security Patch Availability. During the update, GitLab and Mattermost services will not be available. If you have any concerns with this, please talk to local Gitlab admin team.

Commit 1461e472 authored by qinsoon's avatar qinsoon

[wip] finish refactoring

parent 4a9a7ff9
......@@ -11,7 +11,6 @@ use compiler::machine_code::MachineCode;
use vm::VM;
use runtime::ValueLocation;
use utils::vec_utils;
use utils::string_utils;
use ast::ptr::P;
use ast::ir::*;
......@@ -25,16 +24,8 @@ use std::ops;
struct ASMCode {
name: MuName,
code: Vec<ASMInst>,
idx_to_blk: HashMap<usize, MuName>,
blk_to_idx: HashMap<MuName, usize>,
blocks: Vec<MuName>,
block_start: HashMap<MuName, usize>,
block_range: HashMap<MuName, ops::Range<usize>>,
block_livein: HashMap<MuName, Vec<MuID>>,
block_liveout: HashMap<MuName, Vec<MuID>>
blocks: HashMap<MuName, ASMBlock>
}
unsafe impl Send for ASMCode {}
......@@ -71,6 +62,25 @@ impl ASMCode {
ret
}
fn is_block_start(&self, inst: usize) -> bool {
for block in self.blocks.values() {
if block.start_inst == inst {
return true;
}
}
false
}
fn get_block_by_start_inst(&self, inst: usize) -> Option<&ASMBlock> {
for block in self.blocks.values() {
if block.start_inst == inst {
return Some(block);
}
}
None
}
fn rewrite_insert(
&self,
insert_before: HashMap<usize, Vec<Box<ASMCode>>>,
......@@ -79,13 +89,7 @@ impl ASMCode {
let mut ret = ASMCode {
name: self.name.clone(),
code: vec![],
idx_to_blk: HashMap::new(),
blk_to_idx: HashMap::new(),
blocks: vec![],
block_start: HashMap::new(),
block_range: HashMap::new(),
block_livein: HashMap::new(),
block_liveout: HashMap::new()
blocks: hashmap!{},
};
// iterate through old machine code
......@@ -266,28 +270,36 @@ impl MachineCode for ASMCode {
}
fn get_ir_block_livein(&self, block: &str) -> Option<&Vec<MuID>> {
self.block_livein.get(&block.to_string())
match self.blocks.get(block) {
Some(ref block) => Some(&block.livein),
None => None
}
}
fn get_ir_block_liveout(&self, block: &str) -> Option<&Vec<MuID>> {
self.block_liveout.get(&block.to_string())
match self.blocks.get(block) {
Some(ref block) => Some(&block.liveout),
None => None
}
}
fn set_ir_block_livein(&mut self, block: &str, set: Vec<MuID>) {
self.block_livein.insert(block.to_string(), set);
let block = self.blocks.get_mut(block).unwrap();
block.livein = set;
}
fn set_ir_block_liveout(&mut self, block: &str, set: Vec<MuID>) {
self.block_liveout.insert(block.to_string(), set);
let block = self.blocks.get_mut(block).unwrap();
block.liveout = set;
}
fn get_all_blocks(&self) -> &Vec<MuName> {
&self.blocks
fn get_all_blocks(&self) -> Vec<MuName> {
self.blocks.keys().map(|x| x.clone()).collect()
}
fn get_block_range(&self, block: &str) -> Option<ops::Range<usize>> {
match self.block_range.get(&block.to_string()) {
Some(r) => Some(r.clone()),
match self.blocks.get(block) {
Some(ref block) => Some(block.start_inst..block.end_inst),
None => None
}
}
......@@ -374,6 +386,27 @@ impl ASMLocation {
}
}
#[derive(Clone, Debug)]
/// [start_inst, end_inst)
struct ASMBlock {
start_inst: usize,
end_inst: usize,
livein: Vec<MuID>,
liveout: Vec<MuID>
}
impl ASMBlock {
fn new() -> ASMBlock {
ASMBlock {
start_inst: usize::MAX,
end_inst: usize::MAX,
livein: vec![],
liveout: vec![]
}
}
}
pub struct ASMCodeGen {
cur: Option<Box<ASMCode>>
}
......@@ -414,9 +447,6 @@ impl ASMCodeGen {
fn add_asm_block_label(&mut self, code: String, block_name: MuName) {
let l = self.line();
self.cur_mut().code.push(ASMInst::symbolic(code));
self.cur_mut().idx_to_blk.insert(l, block_name.clone());
self.cur_mut().blk_to_idx.insert(block_name, l);
}
fn add_asm_symbolic(&mut self, code: String){
......@@ -460,7 +490,7 @@ impl ASMCodeGen {
}
fn add_asm_ret(&mut self, code: String) {
let mut uses : HashMap<MuID, Vec<ASMLocation>> = {
let uses : HashMap<MuID, Vec<ASMLocation>> = {
let mut ret = HashMap::new();
for reg in x86_64::RETURN_GPRs.iter() {
ret.insert(reg.id(), vec![]);
......@@ -690,12 +720,21 @@ impl ASMCodeGen {
let n_insts = self.line();
let code = self.cur_mut();
let ref blocks = code.blocks;
let ref mut asm = code.code;
let block_start = {
let mut ret = vec![];
for block in blocks.values() {
ret.push(block.start_inst);
}
ret
};
for i in 0..n_insts {
// determine predecessor - if cur is not block start, its predecessor is previous insts
let is_block_start = code.idx_to_blk.get(&i);
if is_block_start.is_none() {
let is_block_start = block_start.contains(&i);
if !is_block_start {
if i > 0 {
trace!("inst {}: not a block start", i);
trace!("inst {}: set PREDS as previous inst {}", i, i-1);
......@@ -713,26 +752,26 @@ impl ASMCodeGen {
// branch to target
trace!("inst {}: is a branch to {}", i, target);
let target_n = code.blk_to_idx.get(target).unwrap();
let target_n = code.blocks.get(target).unwrap().start_inst;
trace!("inst {}: branch target index is {}", i, target_n);
// cur inst's succ is target
trace!("inst {}: set SUCCS as branch target {}", i, target_n);
asm[i].succs.push(*target_n);
asm[i].succs.push(target_n);
// target's pred is cur
trace!("inst {}: set PREDS as branch source {}", target_n, i);
asm[*target_n].preds.push(i);
asm[target_n].preds.push(i);
},
ASMBranchTarget::Conditional(ref target) => {
// branch to target
trace!("inst {}: is a cond branch to {}", i, target);
let target_n = code.blk_to_idx.get(target).unwrap();
let target_n = code.blocks.get(target).unwrap().start_inst;
trace!("inst {}: branch target index is {}", i, target_n);
// cur insts' succ is target and next inst
asm[i].succs.push(*target_n);
asm[i].succs.push(target_n);
trace!("inst {}: set SUCCS as branch target {}", i, target_n);
if i < n_insts - 1 {
trace!("inst {}: set SUCCS as next inst", i + 1);
......@@ -740,8 +779,8 @@ impl ASMCodeGen {
}
// target's pred is cur
asm[*target_n].preds.push(i);
trace!("inst {}: set PREDS as {}", *target_n, i);
asm[target_n].preds.push(i);
trace!("inst {}: set PREDS as {}", target_n, i);
},
ASMBranchTarget::None => {
// not branch nor cond branch, succ is next inst
......@@ -772,16 +811,7 @@ impl CodeGenerator for ASMCodeGen {
self.cur = Some(Box::new(ASMCode {
name: func_name.clone(),
code: vec![],
idx_to_blk: HashMap::new(),
blk_to_idx: HashMap::new(),
blocks: vec![],
block_start: HashMap::new(),
block_range: HashMap::new(),
block_livein: HashMap::new(),
block_liveout: HashMap::new()
blocks: hashmap!{},
}));
// to link with C sources via gcc
......@@ -813,16 +843,7 @@ impl CodeGenerator for ASMCodeGen {
self.cur = Some(Box::new(ASMCode {
name: "snippet".to_string(),
code: vec![],
idx_to_blk: HashMap::new(),
blk_to_idx: HashMap::new(),
blocks: vec![],
block_start: HashMap::new(),
block_range: HashMap::new(),
block_livein: HashMap::new(),
block_liveout: HashMap::new()
blocks: hashmap!{}
}));
}
......@@ -852,10 +873,10 @@ impl CodeGenerator for ASMCodeGen {
fn start_block(&mut self, block_name: MuName) {
let label = format!("{}:", self.asm_block_label(block_name.clone()));
self.add_asm_block_label(label, block_name.clone());
self.cur_mut().blocks.push(block_name.clone());
self.cur_mut().blocks.insert(block_name.clone(), ASMBlock::new());
let start = self.line();
self.cur_mut().block_start.insert(block_name, start);
self.cur_mut().blocks.get_mut(&block_name).unwrap().start_inst = start;
}
fn start_exception_block(&mut self, block_name: MuName) -> ValueLocation {
......@@ -869,49 +890,63 @@ impl CodeGenerator for ASMCodeGen {
}
fn end_block(&mut self, block_name: MuName) {
let start : usize = *self.cur().block_start.get(&block_name).unwrap();
let end : usize = self.line();
self.cur_mut().block_range.insert(block_name, (start..end));
let line = self.line();
match self.cur_mut().blocks.get_mut(&block_name) {
Some(ref mut block) => {
block.end_inst = line;
}
None => panic!("trying to end block {} which hasnt been started", block_name)
}
}
fn set_block_livein(&mut self, block_name: MuName, live_in: &Vec<P<Value>>) {
let cur = self.cur_mut();
let mut res = {
if !cur.block_livein.contains_key(&block_name) {
cur.block_livein.insert(block_name.clone(), vec![]);
} else {
panic!("seems we are inserting livein to block {} twice", block_name);
match cur.blocks.get_mut(&block_name) {
Some(ref mut block) => {
if block.livein.is_empty() {
let mut live_in = {
let mut ret = vec![];
for p in live_in {
match p.extract_ssa_id() {
Some(id) => ret.push(id),
None => warn!("{} as live-in of block {} is not SSA", p, block_name)
}
}
ret
};
block.livein.append(&mut live_in);
} else {
panic!("seems we are inserting livein to block {} twice", block_name);
}
}
cur.block_livein.get_mut(&block_name).unwrap()
};
for value in live_in {
res.push(value.extract_ssa_id().unwrap());
None => panic!("haven't created ASMBlock for {}", block_name)
}
}
fn set_block_liveout(&mut self, block_name: MuName, live_out: &Vec<P<Value>>) {
let cur = self.cur_mut();
let mut res = {
if !cur.block_liveout.contains_key(&block_name) {
cur.block_liveout.insert(block_name.clone(), vec![]);
} else {
panic!("seems we are inserting livein to block {} twice", block_name);
}
cur.block_liveout.get_mut(&block_name).unwrap()
};
for value in live_out {
match value.extract_ssa_id() {
Some(id) => res.push(id),
None => {}
match cur.blocks.get_mut(&block_name) {
Some(ref mut block) => {
if block.liveout.is_empty() {
let mut live_out = {
let mut ret = vec![];
for p in live_out {
match p.extract_ssa_id() {
Some(id) => ret.push(id),
None => warn!("{} as live-out of block {} is not SSA", p, block_name)
}
}
ret
};
block.liveout.append(&mut live_out);
} else {
panic!("seems we are inserting liveout to block {} twice", block_name);
}
}
}
None => panic!("haven't created ASMBlock for {}", block_name)
}
}
fn emit_nop(&mut self, bytes: usize) {
......
......@@ -3,7 +3,6 @@ use ast::ir::*;
use runtime::ValueLocation;
use compiler::machine_code::MachineCode;
use compiler::backend::x86_64::ASMCodeGen;
pub trait CodeGenerator {
fn start_code(&mut self, func_name: MuName) -> ValueLocation;
......
#![allow(dead_code)]
use ast::ir::*;
use ast::ptr::*;
use vm::VM;
use compiler;
use compiler::CompilerPass;
use compiler::machine_code::CompiledFunction;
use compiler::PassExecutionResult;
use compiler::backend::init_machine_regs_for_func;
use compiler::backend;
......
......@@ -115,7 +115,8 @@ pub trait MachineCode {
fn set_ir_block_livein(&mut self, block: &str, set: Vec<MuID>);
fn set_ir_block_liveout(&mut self, block: &str, set: Vec<MuID>);
fn get_all_blocks(&self) -> &Vec<MuName>;
fn get_all_blocks(&self) -> Vec<MuName>;
// returns [start_inst, end_inst), inclusive at both end
fn get_block_range(&self, block: &str) -> Option<ops::Range<usize>>;
// functions for rewrite
......
......@@ -3,7 +3,6 @@ use ast::ptr::*;
use vm::VM;
use compiler::CompilerPass;
use std::sync::atomic::Ordering;
pub struct DefUse {
name: &'static str,
......
......@@ -6,8 +6,6 @@ use vm::VM;
use compiler::CompilerPass;
use compiler::PassExecutionResult;
use std::sync::atomic::Ordering;
pub struct TreeGen {
name: &'static str
}
......
......@@ -58,6 +58,8 @@ fn test_ir_liveness_fac() {
let block_1_liveout = cf.mc().get_ir_block_liveout("blk_1").unwrap();
let blk_1_v52 = vm.id_of("blk_1_v52");
trace!("lhs: {:?}", block_1_liveout);
trace!("rhs: {:?}", vec![blk_1_v52]);
assert!(vec_utils::is_identical_to_str_ignore_order(block_1_liveout, vec![blk_1_v52]));
// block 2
......
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