From f4e622cedc921395ccd1c73f6a8283973752a210 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Thu, 9 Aug 2018 10:46:56 +0200 Subject: [PATCH] Add basic ssa analyzer --- Cargo.lock | 1 + Cargo.toml | 1 + src/abi.rs | 39 ++++++++++++++++++++++++++----------- src/analyze.rs | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/common.rs | 2 +- src/lib.rs | 3 +++ 6 files changed, 86 insertions(+), 12 deletions(-) create mode 100644 src/analyze.rs diff --git a/Cargo.lock b/Cargo.lock index 62e1607beebb..8f5ee20d2544 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -409,6 +409,7 @@ name = "rustc_codegen_cranelift" version = "0.1.0" dependencies = [ "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-faerie 0.18.1 (git+https://github.com/CraneStation/cranelift.git)", "cranelift-module 0.18.1 (git+https://github.com/CraneStation/cranelift.git)", diff --git a/Cargo.toml b/Cargo.toml index 3ccf00cb9657..f15acbc16d90 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,3 +23,4 @@ target-lexicon = "0.0.3" #goblin = "0.0.17" faerie = "0.4.4" ar = "0.6.0" +bitflags = "1.0.3" diff --git a/src/abi.rs b/src/abi.rs index b6a29d074752..0680ccb6e586 100644 --- a/src/abi.rs +++ b/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) { + let ssa_analyzed = crate::analyze::analyze(fx); + fx.tcx.sess.warn(&format!("ssa {:?}", ssa_analyzed)); + match fx.self_sig().abi { Abi::Rust | Abi::RustCall => {} _ => unimplemented!("declared function with non \"rust\" or \"rust-call\" abi"), } 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 { 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 { 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 { kind: StackSlotKind::ExplicitSlot, 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() { let ty = fx.mir.local_decls[local].ty; let layout = fx.layout_of(ty); - let stack_slot = fx.bcx.create_stack_slot(StackSlotData { - kind: StackSlotKind::ExplicitSlot, - size: layout.size.bytes() as u32, - offset: None, - }); - let place = CPlace::from_stack_slot(fx, stack_slot, ty); + + let place = if ssa_analyzed.get(&local).unwrap().contains(crate::analyze::Flags::NOT_SSA) { + let stack_slot = fx.bcx.create_stack_slot(StackSlotData { + kind: StackSlotKind::ExplicitSlot, + size: layout.size.bytes() as u32, + offset: None, + }); + 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); } } diff --git a/src/analyze.rs b/src/analyze.rs new file mode 100644 index 000000000000..646bc69df3cf --- /dev/null +++ b/src/analyze.rs @@ -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 { + 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, place: &Place) { + match place { + Place::Local(local) => not_ssa(flag_map, local), + _ => {} + } +} + +fn not_ssa>(flag_map: &mut HashMap, local: L) { + *flag_map.get_mut(local.borrow()).unwrap() |= Flags::NOT_SSA; +} \ No newline at end of file diff --git a/src/common.rs b/src/common.rs index 35a41dd8a6f6..033300455c14 100644 --- a/src/common.rs +++ b/src/common.rs @@ -9,7 +9,7 @@ use crate::prelude::*; pub type CurrentBackend = ::cranelift_simplejit::SimpleJITBackend; #[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub struct Variable(Local); +pub struct Variable(pub Local); impl EntityRef for Variable { fn new(u: usize) -> Self { diff --git a/src/lib.rs b/src/lib.rs index 2572fee5c0b7..b55497394a62 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,6 +12,8 @@ extern crate rustc_target; extern crate rustc_data_structures; extern crate ar; +#[macro_use] +extern crate bitflags; extern crate faerie; //extern crate goblin; extern crate cranelift; @@ -49,6 +51,7 @@ macro_rules! unimpl { } mod abi; +mod analyze; mod base; mod common; mod constant;