1
- #![ feature( rustc_private, i128_type ) ]
1
+ #![ feature( rustc_private) ]
2
2
3
3
extern crate getopts;
4
4
extern crate miri;
5
5
extern crate rustc;
6
6
extern crate rustc_driver;
7
7
extern crate rustc_errors;
8
+ extern crate rustc_trans_utils;
8
9
extern crate env_logger;
9
10
extern crate log_settings;
10
11
extern crate syntax;
@@ -17,11 +18,16 @@ use rustc_driver::driver::{CompileState, CompileController};
17
18
use rustc:: session:: config:: { self , Input , ErrorOutputType } ;
18
19
use rustc:: hir:: { self , itemlikevisit} ;
19
20
use rustc:: ty:: TyCtxt ;
20
- use syntax:: ast:: { self , MetaItemKind , NestedMetaItemKind } ;
21
+ use rustc_trans_utils:: trans_crate:: TransCrate ;
22
+ use syntax:: ast;
21
23
use std:: path:: PathBuf ;
22
24
23
25
struct MiriCompilerCalls {
24
26
default : RustcDefaultCalls ,
27
+ /// Whether to begin interpretation at the start_fn lang item or not
28
+ ///
29
+ /// If false, the interpretation begins at the `main` function
30
+ start_fn : bool ,
25
31
}
26
32
27
33
impl < ' a > CompilerCalls < ' a > for MiriCompilerCalls {
@@ -61,14 +67,15 @@ impl<'a> CompilerCalls<'a> for MiriCompilerCalls {
61
67
}
62
68
fn late_callback (
63
69
& mut self ,
70
+ trans : & TransCrate ,
64
71
matches : & getopts:: Matches ,
65
72
sess : & Session ,
66
73
cstore : & CrateStore ,
67
74
input : & Input ,
68
75
odir : & Option < PathBuf > ,
69
76
ofile : & Option < PathBuf > ,
70
77
) -> Compilation {
71
- self . default . late_callback ( matches, sess, cstore, input, odir, ofile)
78
+ self . default . late_callback ( trans , matches, sess, cstore, input, odir, ofile)
72
79
}
73
80
fn build_controller (
74
81
& mut self ,
@@ -77,7 +84,8 @@ impl<'a> CompilerCalls<'a> for MiriCompilerCalls {
77
84
) -> CompileController < ' a > {
78
85
let mut control = self . default . build_controller ( sess, matches) ;
79
86
control. after_hir_lowering . callback = Box :: new ( after_hir_lowering) ;
80
- control. after_analysis . callback = Box :: new ( after_analysis) ;
87
+ let start_fn = self . start_fn ;
88
+ control. after_analysis . callback = Box :: new ( move |state| after_analysis ( state, start_fn) ) ;
81
89
if sess. target . target != sess. host {
82
90
// only fully compile targets on the host. linking will fail for cross-compilation.
83
91
control. after_analysis . stop = Compilation :: Stop ;
@@ -94,135 +102,92 @@ fn after_hir_lowering(state: &mut CompileState) {
94
102
state. session . plugin_attributes . borrow_mut ( ) . push ( attr) ;
95
103
}
96
104
97
- fn after_analysis < ' a , ' tcx > ( state : & mut CompileState < ' a , ' tcx > ) {
105
+ fn after_analysis < ' a , ' tcx > ( state : & mut CompileState < ' a , ' tcx > , use_start_fn : bool ) {
98
106
state. session . abort_if_errors ( ) ;
99
107
100
108
let tcx = state. tcx . unwrap ( ) ;
101
- let limits = resource_limits_from_attributes ( state) ;
102
109
103
110
if std:: env:: args ( ) . any ( |arg| arg == "--test" ) {
104
111
struct Visitor < ' a , ' tcx : ' a > (
105
- miri:: ResourceLimits ,
106
112
TyCtxt < ' a , ' tcx , ' tcx > ,
107
113
& ' a CompileState < ' a , ' tcx >
108
114
) ;
109
115
impl < ' a , ' tcx : ' a , ' hir > itemlikevisit:: ItemLikeVisitor < ' hir > for Visitor < ' a , ' tcx > {
110
116
fn visit_item ( & mut self , i : & ' hir hir:: Item ) {
111
117
if let hir:: Item_ :: ItemFn ( _, _, _, _, _, body_id) = i. node {
112
118
if i. attrs . iter ( ) . any ( |attr| {
113
- attr. name ( ) . map_or ( false , |n| n == "test" )
119
+ attr. name ( ) == "test"
114
120
} )
115
121
{
116
- let did = self . 1 . hir . body_owner_def_id ( body_id) ;
122
+ let did = self . 0 . hir . body_owner_def_id ( body_id) ;
117
123
println ! (
118
124
"running test: {}" ,
119
- self . 1 . def_path_debug_str( did) ,
125
+ self . 0 . def_path_debug_str( did) ,
120
126
) ;
121
- miri:: eval_main ( self . 1 , did, None , self . 0 ) ;
122
- self . 2 . session . abort_if_errors ( ) ;
127
+ miri:: eval_main ( self . 0 , did, None ) ;
128
+ self . 1 . session . abort_if_errors ( ) ;
123
129
}
124
130
}
125
131
}
126
132
fn visit_trait_item ( & mut self , _trait_item : & ' hir hir:: TraitItem ) { }
127
133
fn visit_impl_item ( & mut self , _impl_item : & ' hir hir:: ImplItem ) { }
128
134
}
129
135
state. hir_crate . unwrap ( ) . visit_all_item_likes (
130
- & mut Visitor ( limits , tcx, state) ,
136
+ & mut Visitor ( tcx, state) ,
131
137
) ;
132
- } else if let Some ( ( entry_node_id, _) ) = * state. session . entry_fn . borrow ( ) {
138
+ } else if let Some ( ( entry_node_id, _, _ ) ) = * state. session . entry_fn . borrow ( ) {
133
139
let entry_def_id = tcx. hir . local_def_id ( entry_node_id) ;
134
140
let start_wrapper = tcx. lang_items ( ) . start_fn ( ) . and_then ( |start_fn| {
135
- if tcx . is_mir_available ( start_fn ) {
141
+ if use_start_fn {
136
142
Some ( start_fn)
137
143
} else {
138
144
None
139
145
}
140
146
} ) ;
141
- miri:: eval_main ( tcx, entry_def_id, start_wrapper, limits ) ;
147
+ miri:: eval_main ( tcx, entry_def_id, start_wrapper) ;
142
148
143
149
state. session . abort_if_errors ( ) ;
144
150
} else {
145
151
println ! ( "no main function found, assuming auxiliary build" ) ;
146
152
}
147
153
}
148
154
149
- fn resource_limits_from_attributes ( state : & CompileState ) -> miri:: ResourceLimits {
150
- let mut limits = miri:: ResourceLimits :: default ( ) ;
151
- let krate = state. hir_crate . as_ref ( ) . unwrap ( ) ;
152
- let err_msg = "miri attributes need to be in the form `miri(key = value)`" ;
153
- let extract_int = |lit : & syntax:: ast:: Lit | -> u128 {
154
- match lit. node {
155
- syntax:: ast:: LitKind :: Int ( i, _) => i,
156
- _ => {
157
- state. session . span_fatal (
158
- lit. span ,
159
- "expected an integer literal" ,
160
- )
161
- }
162
- }
163
- } ;
164
-
165
- for attr in krate. attrs . iter ( ) . filter ( |a| {
166
- a. name ( ) . map_or ( false , |n| n == "miri" )
167
- } )
168
- {
169
- if let Some ( items) = attr. meta_item_list ( ) {
170
- for item in items {
171
- if let NestedMetaItemKind :: MetaItem ( ref inner) = item. node {
172
- if let MetaItemKind :: NameValue ( ref value) = inner. node {
173
- match & inner. name ( ) . as_str ( ) [ ..] {
174
- "memory_size" => limits. memory_size = extract_int ( value) as u64 ,
175
- "step_limit" => limits. step_limit = extract_int ( value) as u64 ,
176
- "stack_limit" => limits. stack_limit = extract_int ( value) as usize ,
177
- _ => state. session . span_err ( item. span , "unknown miri attribute" ) ,
178
- }
179
- } else {
180
- state. session . span_err ( inner. span , err_msg) ;
181
- }
182
- } else {
183
- state. session . span_err ( item. span , err_msg) ;
184
- }
185
- }
186
- } else {
187
- state. session . span_err ( attr. span , err_msg) ;
188
- }
189
- }
190
- limits
191
- }
192
-
193
155
fn init_logger ( ) {
194
- let format = |record : & log:: LogRecord | {
195
- if record. level ( ) == log:: LogLevel :: Trace {
156
+ let format = |formatter : & mut env_logger:: fmt:: Formatter , record : & log:: Record | {
157
+ use std:: io:: Write ;
158
+ if record. level ( ) == log:: Level :: Trace {
196
159
// prepend frame number
197
160
let indentation = log_settings:: settings ( ) . indentation ;
198
- format ! (
161
+ writeln ! (
162
+ formatter,
199
163
"{indentation}:{lvl}:{module}: {text}" ,
200
164
lvl = record. level( ) ,
201
- module = record. location ( ) . module_path ( ) ,
165
+ module = record. module_path ( ) . unwrap_or ( "<unknown module>" ) ,
202
166
indentation = indentation,
203
167
text = record. args( ) ,
204
168
)
205
169
} else {
206
- format ! (
170
+ writeln ! (
171
+ formatter,
207
172
"{lvl}:{module}: {text}" ,
208
173
lvl = record. level( ) ,
209
- module = record. location ( ) . module_path ( ) ,
174
+ module = record. module_path ( ) . unwrap_or ( "<unknown_module>" ) ,
210
175
text = record. args( ) ,
211
176
)
212
177
}
213
178
} ;
214
179
215
- let mut builder = env_logger:: LogBuilder :: new ( ) ;
180
+ let mut builder = env_logger:: Builder :: new ( ) ;
216
181
builder. format ( format) . filter (
217
182
None ,
218
- log:: LogLevelFilter :: Info ,
183
+ log:: LevelFilter :: Info ,
219
184
) ;
220
185
221
186
if std:: env:: var ( "MIRI_LOG" ) . is_ok ( ) {
222
187
builder. parse ( & std:: env:: var ( "MIRI_LOG" ) . unwrap ( ) ) ;
223
188
}
224
189
225
- builder. init ( ) . unwrap ( ) ;
190
+ builder. init ( ) ;
226
191
}
227
192
228
193
fn find_sysroot ( ) -> String {
@@ -246,6 +211,7 @@ fn find_sysroot() -> String {
246
211
}
247
212
248
213
fn main ( ) {
214
+ rustc_driver:: init_rustc_env_logger ( ) ;
249
215
init_logger ( ) ;
250
216
let mut args: Vec < String > = std:: env:: args ( ) . collect ( ) ;
251
217
@@ -255,10 +221,21 @@ fn main() {
255
221
args. push ( find_sysroot ( ) ) ;
256
222
}
257
223
224
+ let mut start_fn = false ;
225
+ args. retain ( |arg| {
226
+ if arg == "-Zmiri-start-fn" {
227
+ start_fn = true ;
228
+ false
229
+ } else {
230
+ true
231
+ }
232
+ } ) ;
233
+
258
234
// Make sure we always have all the MIR (e.g. for auxilary builds in unit tests).
259
235
args. push ( "-Zalways-encode-mir" . to_owned ( ) ) ;
260
236
261
237
rustc_driver:: run_compiler ( & args, & mut MiriCompilerCalls {
262
238
default : RustcDefaultCalls ,
239
+ start_fn,
263
240
} , None , None ) ;
264
241
}
0 commit comments