Skip to content

Commit a26e966

Browse files
committed
convert the inline pass to use the new multi result
This involves changing various details about that system, though the basic shape remains the same.
1 parent 1d675ce commit a26e966

File tree

8 files changed

+311
-117
lines changed

8 files changed

+311
-117
lines changed

src/librustc/mir/transform.rs

Lines changed: 53 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ use hir::def_id::DefId;
1313
use hir::map::DefPathData;
1414
use mir::{Mir, Promoted};
1515
use ty::TyCtxt;
16+
use ty::maps::Multi;
17+
use ty::steal::Steal;
1618
use std::cell::Ref;
1719
use std::rc::Rc;
1820
use syntax::ast::NodeId;
@@ -70,15 +72,6 @@ impl<'a, 'tcx> MirSource {
7072
}
7173
}
7274

73-
/// Various information about pass.
74-
pub trait Pass {
75-
fn name<'a>(&'a self) -> Cow<'a, str> {
76-
default_name::<Self>()
77-
}
78-
79-
fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>);
80-
}
81-
8275
/// Generates a default name for the pass based on the name of the
8376
/// type `T`.
8477
pub fn default_name<T: ?Sized>() -> Cow<'static, str> {
@@ -97,8 +90,20 @@ pub trait MirCtxt<'a, 'tcx: 'a> {
9790
fn suite(&self) -> MirSuite;
9891
fn pass_num(&self) -> MirPassIndex;
9992
fn source(&self) -> MirSource;
93+
94+
// Get a read-only view on the MIR of this def-id from the
95+
// previous pass.
10096
fn read_previous_mir(&self) -> Ref<'tcx, Mir<'tcx>>;
97+
98+
// Steal the MIR of this def-id from the previous pass; any future
99+
// attempt to access the MIR from the previous pass is a bug.
101100
fn steal_previous_mir(&self) -> Mir<'tcx>;
101+
102+
// Same as `read_previous_mir()`, but for any def-id you want.
103+
fn read_previous_mir_of(&self, def_id: DefId) -> Ref<'tcx, Mir<'tcx>>;
104+
105+
// Same as `steal_previous_mir()`, but for any def-id you want.
106+
fn steal_previous_mir_of(&self, def_id: DefId) -> Mir<'tcx>;
102107
}
103108

104109
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
@@ -116,17 +121,35 @@ pub struct MirPassIndex(pub usize);
116121
/// `mir_cx.read_previous_mir()`); after the pass executes, it will be
117122
/// `Some()` with the result of the pass (in which case the output
118123
/// from the previous pass is most likely stolen, so you would not
119-
/// want to try and access it).
124+
/// want to try and access it). If the pass is interprocedural, then
125+
/// the hook will be invoked once per output.
120126
pub trait PassHook {
121127
fn on_mir_pass<'a, 'tcx: 'a>(&self,
122128
mir_cx: &MirCtxt<'a, 'tcx>,
123-
mir: Option<&Mir<'tcx>>);
129+
mir: Option<(DefId, &Mir<'tcx>)>);
124130
}
125131

126-
/// A streamlined trait that you can implement to create a pass; the
127-
/// pass will be invoked to process the MIR with the given `def_id`.
128-
/// This lets you do things before we fetch the MIR itself. You may
129-
/// prefer `MirPass`.
132+
/// The full suite of types that identifies a particular
133+
/// application of a pass to a def-id.
134+
pub type PassId = (MirSuite, MirPassIndex, DefId);
135+
136+
/// The most generic sort of MIR pass. You only want to implement this
137+
/// rather general trait if you are doing an interprocedural pass that
138+
/// may inspect and affect the MIR of many def-ids. Otherwise, prefer
139+
/// the more steamlined `DefIdPass` or `MirPass`.
140+
pub trait Pass {
141+
fn name<'a>(&'a self) -> Cow<'a, str> {
142+
default_name::<Self>()
143+
}
144+
145+
fn run_pass<'a, 'tcx: 'a>(&self, mir_cx: &MirCtxt<'a, 'tcx>)
146+
-> Multi<PassId, &'tcx Steal<Mir<'tcx>>>;
147+
}
148+
149+
/// A streamlined trait that you can implement to create an
150+
/// intraprocedural pass; the pass will be invoked to process the MIR
151+
/// with the given `def_id`. This lets you do things before we fetch
152+
/// the MIR itself. You may prefer `MirPass`, which is even more streamlined.
130153
pub trait DefIdPass {
131154
fn name<'a>(&'a self) -> Cow<'a, str> {
132155
default_name::<Self>()
@@ -135,10 +158,21 @@ pub trait DefIdPass {
135158
fn run_pass<'a, 'tcx: 'a>(&self, mir_cx: &MirCtxt<'a, 'tcx>) -> Mir<'tcx>;
136159
}
137160

161+
impl<T: DefIdPass> Pass for T {
162+
fn name<'a>(&'a self) -> Cow<'a, str> {
163+
DefIdPass::name(self)
164+
}
165+
166+
fn run_pass<'a, 'tcx: 'a>(&self, mir_cx: &MirCtxt<'a, 'tcx>)
167+
-> Multi<PassId, &'tcx Steal<Mir<'tcx>>> {
168+
Multi::from(mir_cx.tcx().alloc_steal_mir(DefIdPass::run_pass(self, mir_cx)))
169+
}
170+
}
171+
138172
/// A streamlined trait that you can implement to create a pass; the
139173
/// pass will be named after the type, and it will consist of a main
140174
/// loop that goes over each available MIR and applies `run_pass`.
141-
pub trait MirPass: DepGraphSafe {
175+
pub trait MirPass {
142176
fn name<'a>(&'a self) -> Cow<'a, str> {
143177
default_name::<Self>()
144178
}
@@ -174,7 +208,7 @@ impl<T: MirPass> DefIdPass for T {
174208
#[derive(Clone)]
175209
pub struct Passes {
176210
pass_hooks: Vec<Rc<PassHook>>,
177-
suites: Vec<Vec<Rc<DefIdPass>>>,
211+
suites: Vec<Vec<Rc<Pass>>>,
178212
}
179213

180214
/// The number of "pass suites" that we have:
@@ -202,7 +236,7 @@ impl<'a, 'tcx> Passes {
202236
}
203237

204238
/// Pushes a built-in pass.
205-
pub fn push_pass<T: DefIdPass + 'static>(&mut self, suite: MirSuite, pass: T) {
239+
pub fn push_pass<T: Pass + 'static>(&mut self, suite: MirSuite, pass: T) {
206240
self.suites[suite.0].push(Rc::new(pass));
207241
}
208242

@@ -215,7 +249,7 @@ impl<'a, 'tcx> Passes {
215249
self.suites[suite.0].len()
216250
}
217251

218-
pub fn pass(&self, suite: MirSuite, pass: MirPassIndex) -> &DefIdPass {
252+
pub fn pass(&self, suite: MirSuite, pass: MirPassIndex) -> &Pass {
219253
&*self.suites[suite.0][pass.0]
220254
}
221255

src/librustc/ty/maps.rs

Lines changed: 65 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,21 @@ use ty::steal::Steal;
2424
use ty::subst::Substs;
2525
use util::nodemap::{DefIdSet, NodeSet};
2626

27-
use rustc_data_structures::fx::FxHashMap;
2827
use rustc_data_structures::indexed_vec::IndexVec;
2928
use std::cell::{RefCell, RefMut};
29+
use std::option;
3030
use std::fmt::Debug;
3131
use std::hash::Hash;
3232
use std::iter::{self, Once};
3333
use std::mem;
3434
use std::collections::BTreeMap;
3535
use std::ops::Deref;
3636
use std::rc::Rc;
37+
use std::vec;
3738
use syntax_pos::{Span, DUMMY_SP};
3839
use syntax::symbol::Symbol;
3940

40-
trait Key: Clone + Hash + Eq + Debug {
41+
pub trait Key: Clone + Hash + Eq + Debug {
4142
fn map_crate(&self) -> CrateNum;
4243
fn default_span(&self, tcx: TyCtxt) -> Span;
4344
}
@@ -163,27 +164,61 @@ impl<'tcx> Value<'tcx> for ty::SymbolName {
163164
trait IntoKeyValues<K: Key, V> {
164165
type KeyValues: IntoIterator<Item=(K, V)>;
165166

166-
fn into_key_values(tcx: TyCtxt, key: &K, value: Self) -> Self::KeyValues;
167+
fn into_key_values(key: &K, value: Self) -> Self::KeyValues;
167168
}
168169

169170
impl<K: Key, V> IntoKeyValues<K, V> for V {
170171
type KeyValues = Once<(K, V)>;
171172

172-
fn into_key_values(_: TyCtxt, key: &K, value: Self) -> Self::KeyValues {
173+
fn into_key_values(key: &K, value: Self) -> Self::KeyValues {
173174
iter::once((key.clone(), value))
174175
}
175176
}
176177

177-
impl<K: Key, V> IntoKeyValues<K, V> for FxHashMap<K, V> {
178-
type KeyValues = Self;
178+
/// Return type for a multi-query, which is a query which may (if it
179+
/// chooses) return more than one (key, value) pair. Construct a
180+
/// `Multi` using `Multi::from(...)`.
181+
pub struct Multi<K: Key, V> {
182+
single: Option<V>,
183+
map: Vec<(K, V)>,
184+
}
179185

180-
fn into_key_values(tcx: TyCtxt, key: &K, value: Self) -> Self {
181-
if !value.contains_key(key) {
182-
span_bug!(key.default_span(tcx),
183-
"multi-generation function for `{:?}` did not generate a value for `{:?}`",
184-
key, key)
186+
impl<K: Key, V> Multi<K, V> {
187+
pub fn iter<'a>(&'a self, key: &'a K) -> impl Iterator<Item = (&'a K, &'a V)> + 'a {
188+
self.single.iter()
189+
.map(move |v| (key, v))
190+
.chain(self.map.iter().map(move |&(ref k, ref v)| (k, v)))
191+
}
192+
}
193+
194+
/// Construct a `Multi` from a single value.
195+
impl<K: Key, V> From<V> for Multi<K, V> {
196+
fn from(value: V) -> Self {
197+
Multi {
198+
single: Some(value),
199+
map: vec![],
185200
}
186-
value
201+
}
202+
}
203+
204+
/// Construct a `Multi` from a hashmap of (K, V) pairs.
205+
impl<K: Key, V> From<Vec<(K, V)>> for Multi<K, V> {
206+
fn from(value: Vec<(K, V)>) -> Self {
207+
Multi {
208+
single: None,
209+
map: value
210+
}
211+
}
212+
}
213+
214+
impl<K: Key, V> IntoKeyValues<K, V> for Multi<K, V> {
215+
type KeyValues = iter::Chain<option::IntoIter<(K, V)>, vec::IntoIter<(K, V)>>;
216+
217+
fn into_key_values(key: &K, value: Self) -> Self::KeyValues {
218+
value.single
219+
.map(|v| (key.clone(), v))
220+
.into_iter()
221+
.chain(value.map)
187222
}
188223
}
189224

@@ -469,7 +504,7 @@ macro_rules! define_maps {
469504

470505
{
471506
let map = &mut *tcx.maps.$name.borrow_mut();
472-
for (k, v) in IntoKeyValues::<$K, $V>::into_key_values(tcx, &key, result) {
507+
for (k, v) in IntoKeyValues::<$K, $V>::into_key_values(&key, result) {
473508
map.insert(k, v);
474509
}
475510
}
@@ -545,16 +580,6 @@ macro_rules! define_maps {
545580
impl<$tcx> Clone for Providers<$tcx> {
546581
fn clone(&self) -> Self { *self }
547582
}
548-
549-
impl<$tcx> Default for Providers<$tcx> {
550-
fn default() -> Self {
551-
$(fn $name<'a, $tcx>(_: TyCtxt<'a, $tcx, $tcx>, key: $K) -> $V {
552-
bug!("tcx.maps.{}({:?}) unsupported by its crate",
553-
stringify!($name), key);
554-
})*
555-
Providers { $($name),* }
556-
}
557-
}
558583
}
559584
}
560585

@@ -642,34 +667,43 @@ macro_rules! define_provider_struct {
642667
// Final state:
643668
(tcx: $tcx:tt,
644669
input: (),
645-
output: ($($output:tt)*)) => {
670+
output: ($(([$name:ident] [$K:ty] [$R:ty]))*)) => {
646671
pub struct Providers<$tcx> {
647-
$($output)*
672+
$(pub $name: for<'a> fn(TyCtxt<'a, $tcx, $tcx>, $K) -> $R,)*
673+
}
674+
675+
impl<$tcx> Default for Providers<$tcx> {
676+
fn default() -> Self {
677+
$(fn $name<'a, $tcx>(_: TyCtxt<'a, $tcx, $tcx>, key: $K) -> $R {
678+
bug!("tcx.maps.{}({:?}) unsupported by its crate",
679+
stringify!($name), key);
680+
})*
681+
Providers { $($name),* }
682+
}
648683
}
649684
};
650685

651686
// Something ready to shift:
652687
(tcx: $tcx:tt,
653-
ready: ([$name:ident] [$K:ty] [$R:ty]),
688+
ready: ($name:tt $K:tt $V:tt),
654689
input: $input:tt,
655690
output: ($($output:tt)*)) => {
656691
define_provider_struct! {
657692
tcx: $tcx,
658693
input: $input,
659-
output: ($($output)*
660-
pub $name: for<'a> fn(TyCtxt<'a, $tcx, $tcx>, $K) -> $R,)
694+
output: ($($output)* ($name $K $V))
661695
}
662696
};
663697

664698
// The `multi` modifier indicates a **multiquery**, in which case
665-
// the function returns a `FxHashMap<K,V>` instead of just a value
699+
// the function returns a `Multi<K,V>` instead of just a value
666700
// `V`.
667701
(tcx: $tcx:tt,
668702
input: (([multi $($other_modifiers:tt)*] $name:tt [$K:ty] [$V:ty]) $($input:tt)*),
669703
output: $output:tt) => {
670704
define_provider_struct! {
671705
tcx: $tcx,
672-
ready: ($name [$K] [FxHashMap<$K,$V>]),
706+
ready: ($name [$K] [Multi<$K,$V>]),
673707
input: ($($input)*),
674708
output: $output
675709
}
@@ -778,7 +812,7 @@ define_maps! { <'tcx>
778812
/// Fetch the MIR for a given def-id after a given pass has been executed. This is
779813
/// **only** intended to be used by the `mir_suite` provider -- if you are using it
780814
/// manually, you're doing it wrong.
781-
[] mir_pass: mir_pass((MirSuite, MirPassIndex, DefId)) -> &'tcx Steal<mir::Mir<'tcx>>,
815+
[multi] mir_pass: mir_pass((MirSuite, MirPassIndex, DefId)) -> &'tcx Steal<mir::Mir<'tcx>>,
782816

783817
/// MIR after our optimization passes have run. This is MIR that is ready
784818
/// for trans. This is also the only query that can fetch non-local MIR, at present.

src/librustc_driver/driver.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -929,7 +929,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
929929
passes.push_pass(MIR_OPTIMIZED, mir::transform::simplify::SimplifyCfg::new("elaborate-drops"));
930930

931931
// No lifetime analysis based on borrowing can be done from here on out.
932-
// passes.push_pass(MIR_OPTIMIZED, mir::transform::inline::Inline); // TODO re-enable
932+
passes.push_pass(MIR_OPTIMIZED, mir::transform::inline::Inline);
933933
passes.push_pass(MIR_OPTIMIZED, mir::transform::instcombine::InstCombine);
934934
passes.push_pass(MIR_OPTIMIZED, mir::transform::deaggregator::Deaggregator);
935935
passes.push_pass(MIR_OPTIMIZED, mir::transform::copy_prop::CopyPropagation);

src/librustc_mir/callgraph.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,30 +22,31 @@ use rustc::ty;
2222

2323
use rustc::util::nodemap::DefIdMap;
2424

25+
use transform::interprocedural::InterproceduralCx;
26+
2527
pub struct CallGraph {
2628
node_map: DefIdMap<graph::NodeIndex>,
2729
graph: graph::Graph<DefId, ()>
2830
}
2931

3032
impl CallGraph {
31-
// FIXME: allow for construction of a callgraph that inspects
32-
// cross-crate MIRs if available.
33-
pub fn build<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>) -> CallGraph {
33+
pub fn build<'a, 'mir, 'tcx>(cx: &mut InterproceduralCx<'a, 'mir, 'tcx>) -> CallGraph {
3434
let mut callgraph = CallGraph {
3535
node_map: DefIdMap(),
3636
graph: graph::Graph::new()
3737
};
3838

39-
for &def_id in tcx.mir_keys(LOCAL_CRATE).iter() {
39+
for &def_id in cx.tcx.mir_keys(LOCAL_CRATE).iter() {
4040
let idx = callgraph.add_node(def_id);
4141

4242
let mut call_visitor = CallVisitor {
4343
caller: idx,
4444
graph: &mut callgraph
4545
};
4646

47-
let mir = tcx.item_mir(def_id);
48-
call_visitor.visit_mir(&mir);
47+
if let Some(mir) = cx.ensure_mir_and_read(def_id) {
48+
call_visitor.visit_mir(mir);
49+
}
4950
}
5051

5152
callgraph

0 commit comments

Comments
 (0)