17
17
//! - `#[rustc_mir(pretty="file.mir")]`
18
18
19
19
use build;
20
+ use rustc:: hir:: def_id:: DefId ;
20
21
use rustc:: dep_graph:: DepNode ;
21
22
use rustc:: mir:: Mir ;
22
23
use rustc:: mir:: transform:: MirSource ;
23
24
use rustc:: mir:: visit:: MutVisitor ;
24
25
use pretty;
25
26
use hair:: cx:: Cx ;
26
27
27
- use rustc:: infer:: InferCtxt ;
28
28
use rustc:: traits:: Reveal ;
29
29
use rustc:: ty:: { self , Ty , TyCtxt } ;
30
+ use rustc:: ty:: maps:: Providers ;
30
31
use rustc:: ty:: subst:: Substs ;
31
32
use rustc:: hir;
32
33
use rustc:: hir:: intravisit:: { Visitor , NestedVisitorMap } ;
33
34
use syntax:: abi:: Abi ;
34
35
use syntax:: ast;
35
36
use syntax_pos:: Span ;
36
37
38
+ use std:: cell:: RefCell ;
37
39
use std:: mem;
38
40
39
41
pub fn build_mir_for_crate < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ) {
@@ -42,6 +44,103 @@ pub fn build_mir_for_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
42
44
} . as_deep_visitor ( ) ) ;
43
45
}
44
46
47
+ pub fn provide ( providers : & mut Providers ) {
48
+ providers. mir = build_mir;
49
+ }
50
+
51
+ fn build_mir < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > , def_id : DefId )
52
+ -> & ' tcx RefCell < Mir < ' tcx > > {
53
+ let id = tcx. hir . as_local_node_id ( def_id) . unwrap ( ) ;
54
+ let unsupported = || {
55
+ span_bug ! ( tcx. hir. span( id) , "can't build MIR for {:?}" , def_id) ;
56
+ } ;
57
+
58
+ // Figure out what primary body this item has.
59
+ let body_id = match tcx. hir . get ( id) {
60
+ hir:: map:: NodeItem ( item) => {
61
+ match item. node {
62
+ hir:: ItemConst ( _, body) |
63
+ hir:: ItemStatic ( _, _, body) |
64
+ hir:: ItemFn ( .., body) => body,
65
+ _ => unsupported ( )
66
+ }
67
+ }
68
+ hir:: map:: NodeTraitItem ( item) => {
69
+ match item. node {
70
+ hir:: TraitItemKind :: Const ( _, Some ( body) ) |
71
+ hir:: TraitItemKind :: Method ( _,
72
+ hir:: TraitMethod :: Provided ( body) ) => body,
73
+ _ => unsupported ( )
74
+ }
75
+ }
76
+ hir:: map:: NodeImplItem ( item) => {
77
+ match item. node {
78
+ hir:: ImplItemKind :: Const ( _, body) |
79
+ hir:: ImplItemKind :: Method ( _, body) => body,
80
+ _ => unsupported ( )
81
+ }
82
+ }
83
+ hir:: map:: NodeExpr ( expr) => {
84
+ // FIXME(eddyb) Closures should have separate
85
+ // function definition IDs and expression IDs.
86
+ // Type-checking should not let closures get
87
+ // this far in a constant position.
88
+ // Assume that everything other than closures
89
+ // is a constant "initializer" expression.
90
+ match expr. node {
91
+ hir:: ExprClosure ( _, _, body, _) => body,
92
+ _ => hir:: BodyId { node_id : expr. id }
93
+ }
94
+ }
95
+ _ => unsupported ( )
96
+ } ;
97
+
98
+ let src = MirSource :: from_node ( tcx, id) ;
99
+ tcx. infer_ctxt ( body_id, Reveal :: NotSpecializable ) . enter ( |infcx| {
100
+ let cx = Cx :: new ( & infcx, src) ;
101
+ let mut mir = if let MirSource :: Fn ( id) = src {
102
+ // fetch the fully liberated fn signature (that is, all bound
103
+ // types/lifetimes replaced)
104
+ let fn_sig = cx. tables ( ) . liberated_fn_sigs [ & id] . clone ( ) ;
105
+
106
+ let ty = tcx. item_type ( tcx. hir . local_def_id ( id) ) ;
107
+ let ( abi, implicit_argument) = if let ty:: TyClosure ( ..) = ty. sty {
108
+ ( Abi :: Rust , Some ( ( closure_self_ty ( tcx, id, body_id) , None ) ) )
109
+ } else {
110
+ ( ty. fn_abi ( ) , None )
111
+ } ;
112
+
113
+ let body = tcx. hir . body ( body_id) ;
114
+ let explicit_arguments =
115
+ body. arguments
116
+ . iter ( )
117
+ . enumerate ( )
118
+ . map ( |( index, arg) | {
119
+ ( fn_sig. inputs ( ) [ index] , Some ( & * arg. pat ) )
120
+ } ) ;
121
+
122
+ let arguments = implicit_argument. into_iter ( ) . chain ( explicit_arguments) ;
123
+ build:: construct_fn ( cx, id, arguments, abi, fn_sig. output ( ) , body)
124
+ } else {
125
+ build:: construct_const ( cx, body_id)
126
+ } ;
127
+
128
+ // Convert the Mir to global types.
129
+ let mut globalizer = GlobalizeMir {
130
+ tcx : tcx,
131
+ span : mir. span
132
+ } ;
133
+ globalizer. visit_mir ( & mut mir) ;
134
+ let mir = unsafe {
135
+ mem:: transmute :: < Mir , Mir < ' tcx > > ( mir)
136
+ } ;
137
+
138
+ pretty:: dump_mir ( tcx, "mir_map" , & 0 , src, & mir) ;
139
+
140
+ tcx. alloc_mir ( mir)
141
+ } )
142
+ }
143
+
45
144
/// A pass to lift all the types and substitutions in a Mir
46
145
/// to the global tcx. Sadly, we don't have a "folder" that
47
146
/// can change 'tcx so we have to transmute afterwards.
@@ -79,68 +178,13 @@ struct BuildMir<'a, 'tcx: 'a> {
79
178
tcx : TyCtxt < ' a , ' tcx , ' tcx >
80
179
}
81
180
82
- fn build < ' a , ' gcx , ' tcx > ( infcx : & InferCtxt < ' a , ' gcx , ' tcx > ,
83
- body_id : hir:: BodyId )
84
- -> ( Mir < ' tcx > , MirSource ) {
85
- let tcx = infcx. tcx . global_tcx ( ) ;
86
-
87
- let item_id = tcx. hir . body_owner ( body_id) ;
88
- let src = MirSource :: from_node ( tcx, item_id) ;
89
- let cx = Cx :: new ( infcx, src) ;
90
- if let MirSource :: Fn ( id) = src {
91
- // fetch the fully liberated fn signature (that is, all bound
92
- // types/lifetimes replaced)
93
- let fn_sig = cx. tables ( ) . liberated_fn_sigs [ & id] . clone ( ) ;
94
-
95
- let ty = tcx. item_type ( tcx. hir . local_def_id ( id) ) ;
96
- let ( abi, implicit_argument) = if let ty:: TyClosure ( ..) = ty. sty {
97
- ( Abi :: Rust , Some ( ( closure_self_ty ( tcx, id, body_id) , None ) ) )
98
- } else {
99
- ( ty. fn_abi ( ) , None )
100
- } ;
101
-
102
- let body = tcx. hir . body ( body_id) ;
103
- let explicit_arguments =
104
- body. arguments
105
- . iter ( )
106
- . enumerate ( )
107
- . map ( |( index, arg) | {
108
- ( fn_sig. inputs ( ) [ index] , Some ( & * arg. pat ) )
109
- } ) ;
110
-
111
- let arguments = implicit_argument. into_iter ( ) . chain ( explicit_arguments) ;
112
- ( build:: construct_fn ( cx, id, arguments, abi, fn_sig. output ( ) , body) , src)
113
- } else {
114
- ( build:: construct_const ( cx, body_id) , src)
115
- }
116
- }
117
-
118
181
impl < ' a , ' tcx > Visitor < ' tcx > for BuildMir < ' a , ' tcx > {
119
182
fn nested_visit_map < ' this > ( & ' this mut self ) -> NestedVisitorMap < ' this , ' tcx > {
120
183
NestedVisitorMap :: None
121
184
}
122
185
123
186
fn visit_nested_body ( & mut self , body_id : hir:: BodyId ) {
124
- self . tcx . infer_ctxt ( body_id, Reveal :: NotSpecializable ) . enter ( |infcx| {
125
- let ( mut mir, src) = build ( & infcx, body_id) ;
126
-
127
- // Convert the Mir to global types.
128
- let tcx = infcx. tcx . global_tcx ( ) ;
129
- let mut globalizer = GlobalizeMir {
130
- tcx : tcx,
131
- span : mir. span
132
- } ;
133
- globalizer. visit_mir ( & mut mir) ;
134
- let mir = unsafe {
135
- mem:: transmute :: < Mir , Mir < ' tcx > > ( mir)
136
- } ;
137
-
138
- pretty:: dump_mir ( tcx, "mir_map" , & 0 , src, & mir) ;
139
-
140
- let mir = tcx. alloc_mir ( mir) ;
141
- let def_id = tcx. hir . local_def_id ( src. item_id ( ) ) ;
142
- tcx. maps . mir . borrow_mut ( ) . insert ( def_id, mir) ;
143
- } ) ;
187
+ self . tcx . item_mir ( self . tcx . hir . body_owner_def_id ( body_id) ) ;
144
188
145
189
let body = self . tcx . hir . body ( body_id) ;
146
190
self . visit_body ( body) ;
0 commit comments