Add basic ssa analyzer
This commit is contained in:
parent
72fa53bac3
commit
f4e622cedc
6 changed files with 86 additions and 12 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -409,6 +409,7 @@ name = "rustc_codegen_cranelift"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ar 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ar 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"cranelift 0.18.1 (git+https://github.com/CraneStation/cranelift.git)",
|
"cranelift 0.18.1 (git+https://github.com/CraneStation/cranelift.git)",
|
||||||
"cranelift-faerie 0.18.1 (git+https://github.com/CraneStation/cranelift.git)",
|
"cranelift-faerie 0.18.1 (git+https://github.com/CraneStation/cranelift.git)",
|
||||||
"cranelift-module 0.18.1 (git+https://github.com/CraneStation/cranelift.git)",
|
"cranelift-module 0.18.1 (git+https://github.com/CraneStation/cranelift.git)",
|
||||||
|
|
|
@ -23,3 +23,4 @@ target-lexicon = "0.0.3"
|
||||||
#goblin = "0.0.17"
|
#goblin = "0.0.17"
|
||||||
faerie = "0.4.4"
|
faerie = "0.4.4"
|
||||||
ar = "0.6.0"
|
ar = "0.6.0"
|
||||||
|
bitflags = "1.0.3"
|
||||||
|
|
29
src/abi.rs
29
src/abi.rs
|
@ -186,17 +186,15 @@ impl<'a, 'tcx: 'a> FunctionCx<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn codegen_fn_prelude<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, start_ebb: Ebb) {
|
pub fn codegen_fn_prelude<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, start_ebb: Ebb) {
|
||||||
|
let ssa_analyzed = crate::analyze::analyze(fx);
|
||||||
|
fx.tcx.sess.warn(&format!("ssa {:?}", ssa_analyzed));
|
||||||
|
|
||||||
match fx.self_sig().abi {
|
match fx.self_sig().abi {
|
||||||
Abi::Rust | Abi::RustCall => {}
|
Abi::Rust | Abi::RustCall => {}
|
||||||
_ => unimplemented!("declared function with non \"rust\" or \"rust-call\" abi"),
|
_ => unimplemented!("declared function with non \"rust\" or \"rust-call\" abi"),
|
||||||
}
|
}
|
||||||
|
|
||||||
let ret_param = fx.bcx.append_ebb_param(start_ebb, types::I64);
|
let ret_param = fx.bcx.append_ebb_param(start_ebb, types::I64);
|
||||||
let _ = fx.bcx.create_stack_slot(StackSlotData {
|
|
||||||
kind: StackSlotKind::ExplicitSlot,
|
|
||||||
size: 0,
|
|
||||||
offset: None,
|
|
||||||
}); // Dummy stack slot for debugging
|
|
||||||
|
|
||||||
enum ArgKind {
|
enum ArgKind {
|
||||||
Normal(Value),
|
Normal(Value),
|
||||||
|
@ -237,6 +235,17 @@ pub fn codegen_fn_prelude<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, start_ebb
|
||||||
|
|
||||||
for (local, arg_kind, ty) in func_params {
|
for (local, arg_kind, ty) in func_params {
|
||||||
let layout = fx.layout_of(ty);
|
let layout = fx.layout_of(ty);
|
||||||
|
|
||||||
|
if let ArgKind::Normal(ebb_param) = arg_kind {
|
||||||
|
if !ssa_analyzed.get(&local).unwrap().contains(crate::analyze::Flags::NOT_SSA) {
|
||||||
|
let var = Variable(local);
|
||||||
|
fx.bcx.declare_var(var, fx.cton_type(ty).unwrap());
|
||||||
|
fx.bcx.def_var(var, ebb_param);
|
||||||
|
fx.local_map.insert(local, CPlace::Var(var, layout));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let stack_slot = fx.bcx.create_stack_slot(StackSlotData {
|
let stack_slot = fx.bcx.create_stack_slot(StackSlotData {
|
||||||
kind: StackSlotKind::ExplicitSlot,
|
kind: StackSlotKind::ExplicitSlot,
|
||||||
size: layout.size.bytes() as u32,
|
size: layout.size.bytes() as u32,
|
||||||
|
@ -270,12 +279,20 @@ pub fn codegen_fn_prelude<'a, 'tcx: 'a>(fx: &mut FunctionCx<'a, 'tcx>, start_ebb
|
||||||
for local in fx.mir.vars_and_temps_iter() {
|
for local in fx.mir.vars_and_temps_iter() {
|
||||||
let ty = fx.mir.local_decls[local].ty;
|
let ty = fx.mir.local_decls[local].ty;
|
||||||
let layout = fx.layout_of(ty);
|
let layout = fx.layout_of(ty);
|
||||||
|
|
||||||
|
let place = if ssa_analyzed.get(&local).unwrap().contains(crate::analyze::Flags::NOT_SSA) {
|
||||||
let stack_slot = fx.bcx.create_stack_slot(StackSlotData {
|
let stack_slot = fx.bcx.create_stack_slot(StackSlotData {
|
||||||
kind: StackSlotKind::ExplicitSlot,
|
kind: StackSlotKind::ExplicitSlot,
|
||||||
size: layout.size.bytes() as u32,
|
size: layout.size.bytes() as u32,
|
||||||
offset: None,
|
offset: None,
|
||||||
});
|
});
|
||||||
let place = CPlace::from_stack_slot(fx, stack_slot, ty);
|
CPlace::from_stack_slot(fx, stack_slot, ty)
|
||||||
|
} else {
|
||||||
|
let var = Variable(local);
|
||||||
|
fx.bcx.declare_var(var, fx.cton_type(ty).unwrap());
|
||||||
|
CPlace::Var(var, layout)
|
||||||
|
};
|
||||||
|
|
||||||
fx.local_map.insert(local, place);
|
fx.local_map.insert(local, place);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
52
src/analyze.rs
Normal file
52
src/analyze.rs
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
use rustc::mir::{StatementKind::*};
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
pub struct Flags: u8 {
|
||||||
|
const NOT_SSA = 0b00000001;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn analyze<'a, 'tcx: 'a>(fx: &FunctionCx<'a, 'tcx>) -> HashMap<Local, Flags> {
|
||||||
|
let mut flag_map = HashMap::new();
|
||||||
|
|
||||||
|
for local in fx.mir.local_decls.indices() {
|
||||||
|
flag_map.insert(local, Flags::empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
not_ssa(&mut flag_map, RETURN_PLACE);
|
||||||
|
|
||||||
|
for (local, local_decl) in fx.mir.local_decls.iter_enumerated() {
|
||||||
|
if fx.cton_type(local_decl.ty).is_none() {
|
||||||
|
not_ssa(&mut flag_map, local);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for bb in fx.mir.basic_blocks().iter() {
|
||||||
|
for stmt in bb.statements.iter() {
|
||||||
|
match &stmt.kind {
|
||||||
|
Assign(_, Rvalue::Ref(_, _, place)) => analyze_non_ssa_place(&mut flag_map, place),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match &bb.terminator().kind {
|
||||||
|
TerminatorKind::Call { destination: Some((place, _)), .. } => analyze_non_ssa_place(&mut flag_map, place),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
flag_map
|
||||||
|
}
|
||||||
|
|
||||||
|
fn analyze_non_ssa_place(flag_map: &mut HashMap<Local, Flags>, place: &Place) {
|
||||||
|
match place {
|
||||||
|
Place::Local(local) => not_ssa(flag_map, local),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn not_ssa<L: ::std::borrow::Borrow<Local>>(flag_map: &mut HashMap<Local, Flags>, local: L) {
|
||||||
|
*flag_map.get_mut(local.borrow()).unwrap() |= Flags::NOT_SSA;
|
||||||
|
}
|
|
@ -9,7 +9,7 @@ use crate::prelude::*;
|
||||||
pub type CurrentBackend = ::cranelift_simplejit::SimpleJITBackend;
|
pub type CurrentBackend = ::cranelift_simplejit::SimpleJITBackend;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
pub struct Variable(Local);
|
pub struct Variable(pub Local);
|
||||||
|
|
||||||
impl EntityRef for Variable {
|
impl EntityRef for Variable {
|
||||||
fn new(u: usize) -> Self {
|
fn new(u: usize) -> Self {
|
||||||
|
|
|
@ -12,6 +12,8 @@ extern crate rustc_target;
|
||||||
extern crate rustc_data_structures;
|
extern crate rustc_data_structures;
|
||||||
|
|
||||||
extern crate ar;
|
extern crate ar;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate bitflags;
|
||||||
extern crate faerie;
|
extern crate faerie;
|
||||||
//extern crate goblin;
|
//extern crate goblin;
|
||||||
extern crate cranelift;
|
extern crate cranelift;
|
||||||
|
@ -49,6 +51,7 @@ macro_rules! unimpl {
|
||||||
}
|
}
|
||||||
|
|
||||||
mod abi;
|
mod abi;
|
||||||
|
mod analyze;
|
||||||
mod base;
|
mod base;
|
||||||
mod common;
|
mod common;
|
||||||
mod constant;
|
mod constant;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue