Skip to content

Commit 14efbf1

Browse files
committed
mir: prepare for rvalue promotion support.
1 parent e1eca0a commit 14efbf1

File tree

17 files changed

+236
-95
lines changed

17 files changed

+236
-95
lines changed

src/librustc/dep_graph/dep_node.rs

+2
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ pub enum DepNode<D: Clone + Debug> {
6464
IntrinsicCheck(D),
6565
MatchCheck(D),
6666
MirMapConstruction(D),
67+
MirPass(D),
6768
MirTypeck(D),
6869
BorrowCheck(D),
6970
RvalueCheck(D),
@@ -186,6 +187,7 @@ impl<D: Clone + Debug> DepNode<D> {
186187
IntrinsicCheck(ref d) => op(d).map(IntrinsicCheck),
187188
MatchCheck(ref d) => op(d).map(MatchCheck),
188189
MirMapConstruction(ref d) => op(d).map(MirMapConstruction),
190+
MirPass(ref d) => op(d).map(MirPass),
189191
MirTypeck(ref d) => op(d).map(MirTypeck),
190192
BorrowCheck(ref d) => op(d).map(BorrowCheck),
191193
RvalueCheck(ref d) => op(d).map(RvalueCheck),

src/librustc/mir/repr.rs

+12
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ pub struct Mir<'tcx> {
3636
/// used (eventually) for debuginfo. Indexed by a `ScopeId`.
3737
pub scopes: Vec<ScopeData>,
3838

39+
/// Rvalues promoted from this function, such as borrows of constants.
40+
/// Each of them is the Mir of a constant with the fn's type parameters
41+
/// in scope, but no vars or args and a separate set of temps.
42+
pub promoted: Vec<Mir<'tcx>>,
43+
3944
/// Return type of the function.
4045
pub return_ty: FnOutput<'tcx>,
4146

@@ -987,6 +992,10 @@ pub enum Literal<'tcx> {
987992
Value {
988993
value: ConstVal,
989994
},
995+
Promoted {
996+
// Index into the `promoted` vector of `Mir`.
997+
index: usize
998+
},
990999
}
9911000

9921001
impl<'tcx> Debug for Constant<'tcx> {
@@ -1007,6 +1016,9 @@ impl<'tcx> Debug for Literal<'tcx> {
10071016
write!(fmt, "const ")?;
10081017
fmt_const_val(fmt, value)
10091018
}
1019+
Promoted { index } => {
1020+
write!(fmt, "promoted{}", index)
1021+
}
10101022
}
10111023
}
10121024
}

src/librustc/mir/transform.rs

+74-3
Original file line numberDiff line numberDiff line change
@@ -8,31 +8,102 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
use dep_graph::DepNode;
12+
use hir;
13+
use hir::map::DefPathData;
14+
use hir::def_id::DefId;
1115
use mir::mir_map::MirMap;
1216
use mir::repr::Mir;
1317
use ty::TyCtxt;
1418
use syntax::ast::NodeId;
1519

20+
/// Where a specific Mir comes from.
21+
#[derive(Copy, Clone)]
22+
pub enum MirSource {
23+
/// Functions and methods.
24+
Fn(NodeId),
25+
26+
/// Constants and associated constants.
27+
Const(NodeId),
28+
29+
/// Initializer of a `static` item.
30+
Static(NodeId, hir::Mutability),
31+
32+
/// Promoted rvalues within a function.
33+
Promoted(NodeId, usize)
34+
}
35+
36+
impl MirSource {
37+
pub fn from_node(tcx: &TyCtxt, id: NodeId) -> MirSource {
38+
use hir::*;
39+
40+
// Handle constants in enum discriminants, types, and repeat expressions.
41+
let def_id = tcx.map.local_def_id(id);
42+
let def_key = tcx.def_key(def_id);
43+
if def_key.disambiguated_data.data == DefPathData::Initializer {
44+
return MirSource::Const(id);
45+
}
46+
47+
match tcx.map.get(id) {
48+
map::NodeItem(&Item { node: ItemConst(..), .. }) |
49+
map::NodeTraitItem(&TraitItem { node: ConstTraitItem(..), .. }) |
50+
map::NodeImplItem(&ImplItem { node: ImplItemKind::Const(..), .. }) => {
51+
MirSource::Const(id)
52+
}
53+
map::NodeItem(&Item { node: ItemStatic(_, m, _), .. }) => {
54+
MirSource::Static(id, m)
55+
}
56+
// Default to function if it's not a constant or static.
57+
_ => MirSource::Fn(id)
58+
}
59+
}
60+
61+
pub fn item_id(&self) -> NodeId {
62+
match *self {
63+
MirSource::Fn(id) |
64+
MirSource::Const(id) |
65+
MirSource::Static(id, _) |
66+
MirSource::Promoted(id, _) => id
67+
}
68+
}
69+
}
70+
1671
/// Various information about pass.
1772
pub trait Pass {
1873
// fn name() for printouts of various sorts?
1974
// fn should_run(Session) to check if pass should run?
75+
fn dep_node(&self, def_id: DefId) -> DepNode<DefId> {
76+
DepNode::MirPass(def_id)
77+
}
2078
}
2179

2280
/// A pass which inspects the whole MirMap.
2381
pub trait MirMapPass<'tcx>: Pass {
24-
fn run_pass(&mut self, cx: &TyCtxt<'tcx>, map: &mut MirMap<'tcx>);
82+
fn run_pass(&mut self, tcx: &TyCtxt<'tcx>, map: &mut MirMap<'tcx>);
2583
}
2684

2785
/// A pass which inspects Mir of functions in isolation.
2886
pub trait MirPass<'tcx>: Pass {
29-
fn run_pass(&mut self, cx: &TyCtxt<'tcx>, id: NodeId, mir: &mut Mir<'tcx>);
87+
fn run_pass_on_promoted(&mut self, tcx: &TyCtxt<'tcx>,
88+
item_id: NodeId, index: usize,
89+
mir: &mut Mir<'tcx>) {
90+
self.run_pass(tcx, MirSource::Promoted(item_id, index), mir);
91+
}
92+
fn run_pass(&mut self, tcx: &TyCtxt<'tcx>, src: MirSource, mir: &mut Mir<'tcx>);
3093
}
3194

3295
impl<'tcx, T: MirPass<'tcx>> MirMapPass<'tcx> for T {
3396
fn run_pass(&mut self, tcx: &TyCtxt<'tcx>, map: &mut MirMap<'tcx>) {
3497
for (&id, mir) in &mut map.map {
35-
MirPass::run_pass(self, tcx, id, mir);
98+
let def_id = tcx.map.local_def_id(id);
99+
let _task = tcx.dep_graph.in_task(self.dep_node(def_id));
100+
101+
let src = MirSource::from_node(tcx, id);
102+
MirPass::run_pass(self, tcx, src, mir);
103+
104+
for (i, mir) in mir.promoted.iter_mut().enumerate() {
105+
self.run_pass_on_promoted(tcx, id, i, mir);
106+
}
36107
}
37108
}
38109
}

src/librustc/mir/visit.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ macro_rules! make_mir_visitor {
244244
let Mir {
245245
ref $($mutability)* basic_blocks,
246246
ref $($mutability)* scopes,
247+
promoted: _, // Visited by passes separately.
247248
ref $($mutability)* return_ty,
248249
ref $($mutability)* var_decls,
249250
ref $($mutability)* arg_decls,
@@ -649,10 +650,11 @@ macro_rules! make_mir_visitor {
649650
ref $($mutability)* substs } => {
650651
self.visit_def_id(def_id);
651652
self.visit_substs(substs);
652-
},
653+
}
653654
Literal::Value { ref $($mutability)* value } => {
654655
self.visit_const_val(value);
655656
}
657+
Literal::Promoted { index: _ } => {}
656658
}
657659
}
658660

src/librustc_metadata/decoder.rs

+3
Original file line numberDiff line numberDiff line change
@@ -855,6 +855,9 @@ pub fn maybe_get_item_mir<'tcx>(cdata: Cmd,
855855
};
856856

857857
def_id_and_span_translator.visit_mir(&mut mir);
858+
for promoted in &mut mir.promoted {
859+
def_id_and_span_translator.visit_mir(promoted);
860+
}
858861

859862
mir
860863
});

src/librustc_mir/build/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
296296
(Mir {
297297
basic_blocks: self.cfg.basic_blocks,
298298
scopes: self.scope_datas,
299+
promoted: vec![],
299300
var_decls: self.var_decls,
300301
arg_decls: arg_decls,
301302
temp_decls: self.temp_decls,

src/librustc_mir/mir_map.rs

+24-11
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use build;
2020
use rustc::dep_graph::DepNode;
2121
use rustc::mir::repr::Mir;
22+
use rustc::mir::transform::MirSource;
2223
use pretty;
2324
use hair::cx::Cx;
2425

@@ -55,20 +56,20 @@ struct BuildMir<'a, 'tcx: 'a> {
5556
}
5657

5758
impl<'a, 'tcx> BuildMir<'a, 'tcx> {
58-
fn build<F>(&mut self, id: ast::NodeId, f: F)
59+
fn build<F>(&mut self, src: MirSource, f: F)
5960
where F: for<'b> FnOnce(Cx<'b, 'tcx>) -> (Mir<'tcx>, build::ScopeAuxiliaryVec)
6061
{
61-
let param_env = ty::ParameterEnvironment::for_item(self.tcx, id);
62+
let param_env = ty::ParameterEnvironment::for_item(self.tcx, src.item_id());
6263
let infcx = infer::new_infer_ctxt(self.tcx,
6364
&self.tcx.tables,
6465
Some(param_env),
6566
ProjectionMode::AnyFinal);
6667

6768
let (mir, scope_auxiliary) = f(Cx::new(&infcx));
6869

69-
pretty::dump_mir(self.tcx, "mir_map", &0, id, &mir, Some(&scope_auxiliary));
70+
pretty::dump_mir(self.tcx, "mir_map", &0, src, &mir, Some(&scope_auxiliary));
7071

71-
assert!(self.map.map.insert(id, mir).is_none())
72+
assert!(self.map.map.insert(src.item_id(), mir).is_none())
7273
}
7374

7475
fn build_const_integer(&mut self, expr: &'tcx hir::Expr) {
@@ -79,17 +80,25 @@ impl<'a, 'tcx> BuildMir<'a, 'tcx> {
7980
if let hir::ExprClosure(..) = expr.node {
8081
return;
8182
}
82-
self.build(expr.id, |cx| build::construct_const(cx, expr.id, expr));
83+
self.build(MirSource::Const(expr.id), |cx| {
84+
build::construct_const(cx, expr.id, expr)
85+
});
8386
}
8487
}
8588

8689
impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> {
8790
// Const and static items.
8891
fn visit_item(&mut self, item: &'tcx hir::Item) {
8992
match item.node {
90-
hir::ItemConst(_, ref expr) |
91-
hir::ItemStatic(_, _, ref expr) => {
92-
self.build(item.id, |cx| build::construct_const(cx, item.id, expr));
93+
hir::ItemConst(_, ref expr) => {
94+
self.build(MirSource::Const(item.id), |cx| {
95+
build::construct_const(cx, item.id, expr)
96+
});
97+
}
98+
hir::ItemStatic(_, m, ref expr) => {
99+
self.build(MirSource::Static(item.id, m), |cx| {
100+
build::construct_const(cx, item.id, expr)
101+
});
93102
}
94103
_ => {}
95104
}
@@ -99,15 +108,19 @@ impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> {
99108
// Trait associated const defaults.
100109
fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) {
101110
if let hir::ConstTraitItem(_, Some(ref expr)) = item.node {
102-
self.build(item.id, |cx| build::construct_const(cx, item.id, expr));
111+
self.build(MirSource::Const(item.id), |cx| {
112+
build::construct_const(cx, item.id, expr)
113+
});
103114
}
104115
intravisit::walk_trait_item(self, item);
105116
}
106117

107118
// Impl associated const.
108119
fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) {
109120
if let hir::ImplItemKind::Const(_, ref expr) = item.node {
110-
self.build(item.id, |cx| build::construct_const(cx, item.id, expr));
121+
self.build(MirSource::Const(item.id), |cx| {
122+
build::construct_const(cx, item.id, expr)
123+
});
111124
}
112125
intravisit::walk_impl_item(self, item);
113126
}
@@ -166,7 +179,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> {
166179
(fn_sig.inputs[index], Some(&*arg.pat))
167180
});
168181

169-
self.build(id, |cx| {
182+
self.build(MirSource::Fn(id), |cx| {
170183
let arguments = implicit_argument.into_iter().chain(explicit_arguments);
171184
build::construct_fn(cx, id, arguments, fn_sig.output, body)
172185
});

0 commit comments

Comments
 (0)