@@ -24,7 +24,6 @@ use rustc_borrowck as borrowck;
24
24
use rustc_resolve as resolve;
25
25
use rustc_trans:: back:: link;
26
26
use rustc_trans:: back:: write;
27
- use rustc_trans:: save;
28
27
use rustc_trans:: trans;
29
28
use rustc_typeck as typeck;
30
29
@@ -47,23 +46,43 @@ pub fn compile_input(sess: Session,
47
46
input : & Input ,
48
47
outdir : & Option < Path > ,
49
48
output : & Option < Path > ,
50
- addl_plugins : Option < Vec < String > > ) {
49
+ addl_plugins : Option < Vec < String > > ,
50
+ control : CompileController ) {
51
+ macro_rules! controller_entry_point{ ( $point: ident, $make_state: expr) => ( {
52
+ {
53
+ let state = $make_state;
54
+ ( control. $point. callback) ( state) ;
55
+ }
56
+ if control. $point. stop {
57
+ return ;
58
+ }
59
+ } ) }
60
+
51
61
// We need nested scopes here, because the intermediate results can keep
52
62
// large chunks of memory alive and we want to free them as soon as
53
63
// possible to keep the peak memory usage low
54
64
let ( outputs, trans, sess) = {
55
65
let ( outputs, expanded_crate, id) = {
56
66
let krate = phase_1_parse_input ( & sess, cfg, input) ;
57
- if stop_after_phase_1 ( & sess) { return ; }
67
+
68
+ controller_entry_point ! ( after_parse,
69
+ CompileState :: state_after_parse( input,
70
+ & sess,
71
+ outdir,
72
+ & krate) ) ;
73
+
58
74
let outputs = build_output_filenames ( input,
59
75
outdir,
60
76
output,
61
77
& krate. attrs [ ] ,
62
78
& sess) ;
63
- let id = link:: find_crate_name ( Some ( & sess) , & krate. attrs [ ] ,
79
+ let id = link:: find_crate_name ( Some ( & sess) ,
80
+ & krate. attrs [ ] ,
64
81
input) ;
65
82
let expanded_crate
66
- = match phase_2_configure_and_expand ( & sess, krate, & id[ ] ,
83
+ = match phase_2_configure_and_expand ( & sess,
84
+ krate,
85
+ & id[ ] ,
67
86
addl_plugins) {
68
87
None => return ,
69
88
Some ( k) => k
@@ -72,23 +91,37 @@ pub fn compile_input(sess: Session,
72
91
( outputs, expanded_crate, id)
73
92
} ;
74
93
94
+ controller_entry_point ! ( after_expand,
95
+ CompileState :: state_after_expand( input,
96
+ & sess,
97
+ outdir,
98
+ & expanded_crate,
99
+ & id[ ] ) ) ;
100
+
75
101
let mut forest = ast_map:: Forest :: new ( expanded_crate) ;
76
102
let ast_map = assign_node_ids_and_map ( & sess, & mut forest) ;
77
103
78
104
write_out_deps ( & sess, input, & outputs, & id[ ] ) ;
79
105
80
- if stop_after_phase_2 ( & sess) { return ; }
81
-
82
106
let arenas = ty:: CtxtArenas :: new ( ) ;
83
- let analysis = phase_3_run_analysis_passes ( sess, ast_map, & arenas, id) ;
84
- phase_save_analysis ( & analysis. ty_cx . sess , analysis. ty_cx . map . krate ( ) , & analysis, outdir) ;
107
+ let analysis = phase_3_run_analysis_passes ( sess,
108
+ ast_map,
109
+ & arenas,
110
+ id,
111
+ control. make_glob_map ) ;
112
+
113
+ controller_entry_point ! ( after_analysis,
114
+ CompileState :: state_after_analysis( input,
115
+ & analysis. ty_cx. sess,
116
+ outdir,
117
+ analysis. ty_cx. map. krate( ) ,
118
+ & analysis,
119
+ & analysis. ty_cx) ) ;
85
120
86
121
if log_enabled ! ( :: log:: INFO ) {
87
122
println ! ( "Pre-trans" ) ;
88
123
analysis. ty_cx . print_debug_stats ( ) ;
89
124
}
90
-
91
- if stop_after_phase_3 ( & analysis. ty_cx . sess ) { return ; }
92
125
let ( tcx, trans) = phase_4_translate_to_llvm ( analysis) ;
93
126
94
127
if log_enabled ! ( :: log:: INFO ) {
@@ -102,7 +135,13 @@ pub fn compile_input(sess: Session,
102
135
( outputs, trans, tcx. sess )
103
136
} ;
104
137
phase_5_run_llvm_passes ( & sess, & trans, & outputs) ;
105
- if stop_after_phase_5 ( & sess) { return ; }
138
+
139
+ controller_entry_point ! ( after_llvm,
140
+ CompileState :: state_after_llvm( input,
141
+ & sess,
142
+ outdir,
143
+ & trans) ) ;
144
+
106
145
phase_6_link_output ( & sess, & trans, & outputs) ;
107
146
}
108
147
@@ -120,6 +159,146 @@ pub fn source_name(input: &Input) -> String {
120
159
}
121
160
}
122
161
162
+ /// CompileController is used to customise compilation, it allows compilation to
163
+ /// be stopped and/or to call arbitrary code at various points in compilation.
164
+ /// It also allows for various flags to be set to influence what information gets
165
+ /// colelcted during compilation.
166
+ ///
167
+ /// This is a somewhat higher level controller than a Session - the Session
168
+ /// controls what happens in each phase, whereas the CompileController controls
169
+ /// whether a phase is run at all and whether other code (from outside the
170
+ /// the compiler) is run between phases.
171
+ ///
172
+ /// Note that if compilation is set to stop and a callback is provided for a
173
+ /// given entry point, the callback is called before compilation is stopped.
174
+ ///
175
+ /// Expect more entry points to be added in the future.
176
+ pub struct CompileController < ' a > {
177
+ pub after_parse : PhaseController < ' a > ,
178
+ pub after_expand : PhaseController < ' a > ,
179
+ pub after_analysis : PhaseController < ' a > ,
180
+ pub after_llvm : PhaseController < ' a > ,
181
+
182
+ pub make_glob_map : resolve:: MakeGlobMap ,
183
+ }
184
+
185
+ impl < ' a > CompileController < ' a > {
186
+ pub fn basic ( ) -> CompileController < ' a > {
187
+ CompileController {
188
+ after_parse : PhaseController :: basic ( ) ,
189
+ after_expand : PhaseController :: basic ( ) ,
190
+ after_analysis : PhaseController :: basic ( ) ,
191
+ after_llvm : PhaseController :: basic ( ) ,
192
+ make_glob_map : resolve:: MakeGlobMap :: No ,
193
+ }
194
+ }
195
+ }
196
+
197
+ pub struct PhaseController < ' a > {
198
+ pub stop : bool ,
199
+ pub callback : Box < Fn ( CompileState ) -> ( ) + ' a > ,
200
+ }
201
+
202
+ impl < ' a > PhaseController < ' a > {
203
+ pub fn basic ( ) -> PhaseController < ' a > {
204
+ PhaseController {
205
+ stop : false ,
206
+ callback : box |& : _| { } ,
207
+ }
208
+ }
209
+ }
210
+
211
+ /// State that is passed to a callback. What state is available depends on when
212
+ /// during compilation the callback is made. See the various constructor methods
213
+ /// (`state_*`) in the impl to see which data is provided for any given entry point.
214
+ pub struct CompileState < ' a , ' ast : ' a , ' tcx : ' a > {
215
+ pub input : & ' a Input ,
216
+ pub session : & ' a Session ,
217
+ pub cfg : Option < & ' a ast:: CrateConfig > ,
218
+ pub krate : Option < & ' a ast:: Crate > ,
219
+ pub crate_name : Option < & ' a str > ,
220
+ pub output_filenames : Option < & ' a OutputFilenames > ,
221
+ pub out_dir : Option < & ' a Path > ,
222
+ pub expanded_crate : Option < & ' a ast:: Crate > ,
223
+ pub ast_map : Option < & ' a ast_map:: Map < ' ast > > ,
224
+ pub analysis : Option < & ' a ty:: CrateAnalysis < ' tcx > > ,
225
+ pub tcx : Option < & ' a ty:: ctxt < ' tcx > > ,
226
+ pub trans : Option < & ' a trans:: CrateTranslation > ,
227
+ }
228
+
229
+ impl < ' a , ' ast , ' tcx > CompileState < ' a , ' ast , ' tcx > {
230
+ fn empty ( input : & ' a Input ,
231
+ session : & ' a Session ,
232
+ out_dir : & ' a Option < Path > )
233
+ -> CompileState < ' a , ' ast , ' tcx > {
234
+ CompileState {
235
+ input : input,
236
+ session : session,
237
+ out_dir : out_dir. as_ref ( ) ,
238
+ cfg : None ,
239
+ krate : None ,
240
+ crate_name : None ,
241
+ output_filenames : None ,
242
+ expanded_crate : None ,
243
+ ast_map : None ,
244
+ analysis : None ,
245
+ tcx : None ,
246
+ trans : None ,
247
+ }
248
+ }
249
+
250
+ fn state_after_parse ( input : & ' a Input ,
251
+ session : & ' a Session ,
252
+ out_dir : & ' a Option < Path > ,
253
+ krate : & ' a ast:: Crate )
254
+ -> CompileState < ' a , ' ast , ' tcx > {
255
+ CompileState {
256
+ krate : Some ( krate) ,
257
+ .. CompileState :: empty ( input, session, out_dir)
258
+ }
259
+ }
260
+
261
+ fn state_after_expand ( input : & ' a Input ,
262
+ session : & ' a Session ,
263
+ out_dir : & ' a Option < Path > ,
264
+ expanded_crate : & ' a ast:: Crate ,
265
+ crate_name : & ' a str )
266
+ -> CompileState < ' a , ' ast , ' tcx > {
267
+ CompileState {
268
+ crate_name : Some ( crate_name) ,
269
+ expanded_crate : Some ( expanded_crate) ,
270
+ .. CompileState :: empty ( input, session, out_dir)
271
+ }
272
+ }
273
+
274
+ fn state_after_analysis ( input : & ' a Input ,
275
+ session : & ' a Session ,
276
+ out_dir : & ' a Option < Path > ,
277
+ krate : & ' a ast:: Crate ,
278
+ analysis : & ' a ty:: CrateAnalysis < ' tcx > ,
279
+ tcx : & ' a ty:: ctxt < ' tcx > )
280
+ -> CompileState < ' a , ' ast , ' tcx > {
281
+ CompileState {
282
+ analysis : Some ( analysis) ,
283
+ tcx : Some ( tcx) ,
284
+ krate : Some ( krate) ,
285
+ .. CompileState :: empty ( input, session, out_dir)
286
+ }
287
+ }
288
+
289
+
290
+ fn state_after_llvm ( input : & ' a Input ,
291
+ session : & ' a Session ,
292
+ out_dir : & ' a Option < Path > ,
293
+ trans : & ' a trans:: CrateTranslation )
294
+ -> CompileState < ' a , ' ast , ' tcx > {
295
+ CompileState {
296
+ trans : Some ( trans) ,
297
+ .. CompileState :: empty ( input, session, out_dir)
298
+ }
299
+ }
300
+ }
301
+
123
302
pub fn phase_1_parse_input ( sess : & Session , cfg : ast:: CrateConfig , input : & Input )
124
303
-> ast:: Crate {
125
304
// These may be left in an incoherent state after a previous compile.
@@ -347,7 +526,9 @@ pub fn assign_node_ids_and_map<'ast>(sess: &Session,
347
526
pub fn phase_3_run_analysis_passes < ' tcx > ( sess : Session ,
348
527
ast_map : ast_map:: Map < ' tcx > ,
349
528
arenas : & ' tcx ty:: CtxtArenas < ' tcx > ,
350
- name : String ) -> ty:: CrateAnalysis < ' tcx > {
529
+ name : String ,
530
+ make_glob_map : resolve:: MakeGlobMap )
531
+ -> ty:: CrateAnalysis < ' tcx > {
351
532
let time_passes = sess. time_passes ( ) ;
352
533
let krate = ast_map. krate ( ) ;
353
534
@@ -357,11 +538,6 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
357
538
let lang_items = time ( time_passes, "language item collection" , ( ) , |_|
358
539
middle:: lang_items:: collect_language_items ( krate, & sess) ) ;
359
540
360
- let make_glob_map = if save_analysis ( & sess) {
361
- resolve:: MakeGlobMap :: Yes
362
- } else {
363
- resolve:: MakeGlobMap :: No
364
- } ;
365
541
let resolve:: CrateMap {
366
542
def_map,
367
543
freevars,
@@ -483,21 +659,6 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
483
659
}
484
660
}
485
661
486
- fn save_analysis ( sess : & Session ) -> bool {
487
- sess. opts . debugging_opts . save_analysis
488
- }
489
-
490
- pub fn phase_save_analysis ( sess : & Session ,
491
- krate : & ast:: Crate ,
492
- analysis : & ty:: CrateAnalysis ,
493
- odir : & Option < Path > ) {
494
- if !save_analysis ( sess) {
495
- return ;
496
- }
497
- time ( sess. time_passes ( ) , "save analysis" , krate, |krate|
498
- save:: process_crate ( sess, krate, analysis, odir) ) ;
499
- }
500
-
501
662
/// Run the translation phase to LLVM, after which the AST and analysis can
502
663
/// be discarded.
503
664
pub fn phase_4_translate_to_llvm < ' tcx > ( analysis : ty:: CrateAnalysis < ' tcx > )
@@ -559,41 +720,6 @@ pub fn phase_6_link_output(sess: &Session,
559
720
os:: setenv ( "PATH" , old_path) ;
560
721
}
561
722
562
- pub fn stop_after_phase_3 ( sess : & Session ) -> bool {
563
- if sess. opts . no_trans {
564
- debug ! ( "invoked with --no-trans, returning early from compile_input" ) ;
565
- return true ;
566
- }
567
- return false ;
568
- }
569
-
570
- pub fn stop_after_phase_1 ( sess : & Session ) -> bool {
571
- if sess. opts . parse_only {
572
- debug ! ( "invoked with --parse-only, returning early from compile_input" ) ;
573
- return true ;
574
- }
575
- if sess. opts . show_span . is_some ( ) {
576
- return true ;
577
- }
578
- return sess. opts . debugging_opts . ast_json_noexpand ;
579
- }
580
-
581
- pub fn stop_after_phase_2 ( sess : & Session ) -> bool {
582
- if sess. opts . no_analysis {
583
- debug ! ( "invoked with --no-analysis, returning early from compile_input" ) ;
584
- return true ;
585
- }
586
- return sess. opts . debugging_opts . ast_json ;
587
- }
588
-
589
- pub fn stop_after_phase_5 ( sess : & Session ) -> bool {
590
- if !sess. opts . output_types . iter ( ) . any ( |& i| i == config:: OutputTypeExe ) {
591
- debug ! ( "not building executable, returning early from compile_input" ) ;
592
- return true ;
593
- }
594
- return false ;
595
- }
596
-
597
723
fn escape_dep_filename ( filename : & str ) -> String {
598
724
// Apparently clang and gcc *only* escape spaces:
599
725
// http://llvm.org/klaus/clang/commit/9d50634cfc268ecc9a7250226dd5ca0e945240d4
0 commit comments