1
1
use crate :: interface:: { Compiler , Result } ;
2
- use crate :: passes:: { self , BoxedResolver , BoxedGlobalCtxt } ;
2
+ use crate :: passes:: { self , BoxedResolver , QueryContext } ;
3
3
4
4
use rustc_incremental:: DepGraphFuture ;
5
- use rustc_data_structures:: sync:: Lrc ;
5
+ use rustc_data_structures:: sync:: { Lrc , Once , WorkerLocal } ;
6
+ use rustc_codegen_utils:: codegen_backend:: CodegenBackend ;
6
7
use rustc:: session:: config:: { OutputFilenames , OutputType } ;
7
8
use rustc:: util:: common:: { time, ErrorReported } ;
9
+ use rustc:: arena:: Arena ;
8
10
use rustc:: hir;
9
11
use rustc:: lint;
10
12
use rustc:: session:: Session ;
11
13
use rustc:: lint:: LintStore ;
12
14
use rustc:: hir:: def_id:: LOCAL_CRATE ;
13
15
use rustc:: ty:: steal:: Steal ;
14
- use rustc:: ty:: ResolverOutputs ;
16
+ use rustc:: ty:: { AllArenas , ResolverOutputs , GlobalCtxt } ;
15
17
use rustc:: dep_graph:: DepGraph ;
16
18
use std:: cell:: { Ref , RefMut , RefCell } ;
17
19
use std:: rc:: Rc ;
@@ -44,13 +46,6 @@ impl<T> Query<T> {
44
46
. unwrap ( )
45
47
}
46
48
47
- /// Returns a stolen query result. Panics if there's already a result.
48
- pub fn give ( & self , value : T ) {
49
- let mut result = self . result . borrow_mut ( ) ;
50
- assert ! ( result. is_none( ) , "a result already exists" ) ;
51
- * result = Some ( Ok ( value) ) ;
52
- }
53
-
54
49
/// Borrows the query result using the RefCell. Panics if the result is stolen.
55
50
pub fn peek ( & self ) -> Ref < ' _ , T > {
56
51
Ref :: map ( self . result . borrow ( ) , |r| {
@@ -74,24 +69,54 @@ impl<T> Default for Query<T> {
74
69
}
75
70
}
76
71
77
- #[ derive( Default ) ]
78
- pub ( crate ) struct Queries {
72
+ pub struct Queries < ' tcx > {
73
+ compiler : & ' tcx Compiler ,
74
+ gcx : Once < GlobalCtxt < ' tcx > > ,
75
+
76
+ all_arenas : AllArenas ,
77
+ arena : WorkerLocal < Arena < ' tcx > > ,
78
+
79
79
dep_graph_future : Query < Option < DepGraphFuture > > ,
80
80
parse : Query < ast:: Crate > ,
81
81
crate_name : Query < String > ,
82
82
register_plugins : Query < ( ast:: Crate , Lrc < LintStore > ) > ,
83
83
expansion : Query < ( ast:: Crate , Steal < Rc < RefCell < BoxedResolver > > > , Lrc < LintStore > ) > ,
84
84
dep_graph : Query < DepGraph > ,
85
- lower_to_hir : Query < ( Steal < hir:: map:: Forest > , Steal < ResolverOutputs > ) > ,
85
+ lower_to_hir : Query < ( & ' tcx hir:: map:: Forest , Steal < ResolverOutputs > ) > ,
86
86
prepare_outputs : Query < OutputFilenames > ,
87
- global_ctxt : Query < BoxedGlobalCtxt > ,
87
+ global_ctxt : Query < QueryContext < ' tcx > > ,
88
88
ongoing_codegen : Query < Box < dyn Any > > ,
89
- link : Query < ( ) > ,
90
89
}
91
90
92
- impl Compiler {
91
+ impl < ' tcx > Queries < ' tcx > {
92
+ pub fn new ( compiler : & ' tcx Compiler ) -> Queries < ' tcx > {
93
+ Queries {
94
+ compiler,
95
+ gcx : Once :: new ( ) ,
96
+ all_arenas : AllArenas :: new ( ) ,
97
+ arena : WorkerLocal :: new ( |_| Arena :: default ( ) ) ,
98
+ dep_graph_future : Default :: default ( ) ,
99
+ parse : Default :: default ( ) ,
100
+ crate_name : Default :: default ( ) ,
101
+ register_plugins : Default :: default ( ) ,
102
+ expansion : Default :: default ( ) ,
103
+ dep_graph : Default :: default ( ) ,
104
+ lower_to_hir : Default :: default ( ) ,
105
+ prepare_outputs : Default :: default ( ) ,
106
+ global_ctxt : Default :: default ( ) ,
107
+ ongoing_codegen : Default :: default ( ) ,
108
+ }
109
+ }
110
+
111
+ fn session ( & self ) -> & Lrc < Session > {
112
+ & self . compiler . sess
113
+ }
114
+ fn codegen_backend ( & self ) -> & Lrc < Box < dyn CodegenBackend > > {
115
+ & self . compiler . codegen_backend ( )
116
+ }
117
+
93
118
pub fn dep_graph_future ( & self ) -> Result < & Query < Option < DepGraphFuture > > > {
94
- self . queries . dep_graph_future . compute ( || {
119
+ self . dep_graph_future . compute ( || {
95
120
Ok ( if self . session ( ) . opts . build_dep_graph ( ) {
96
121
Some ( rustc_incremental:: load_dep_graph ( self . session ( ) ) )
97
122
} else {
@@ -101,8 +126,8 @@ impl Compiler {
101
126
}
102
127
103
128
pub fn parse ( & self ) -> Result < & Query < ast:: Crate > > {
104
- self . queries . parse . compute ( || {
105
- passes:: parse ( self . session ( ) , & self . input ) . map_err (
129
+ self . parse . compute ( || {
130
+ passes:: parse ( self . session ( ) , & self . compiler . input ) . map_err (
106
131
|mut parse_error| {
107
132
parse_error. emit ( ) ;
108
133
ErrorReported
@@ -112,15 +137,15 @@ impl Compiler {
112
137
}
113
138
114
139
pub fn register_plugins ( & self ) -> Result < & Query < ( ast:: Crate , Lrc < LintStore > ) > > {
115
- self . queries . register_plugins . compute ( || {
140
+ self . register_plugins . compute ( || {
116
141
let crate_name = self . crate_name ( ) ?. peek ( ) . clone ( ) ;
117
142
let krate = self . parse ( ) ?. take ( ) ;
118
143
119
144
let empty: & ( dyn Fn ( & Session , & mut lint:: LintStore ) + Sync + Send ) = & |_, _| { } ;
120
145
let result = passes:: register_plugins (
121
146
self . session ( ) ,
122
147
& * self . codegen_backend ( ) . metadata_loader ( ) ,
123
- self . register_lints
148
+ self . compiler . register_lints
124
149
. as_ref ( )
125
150
. map ( |p| & * * p)
126
151
. unwrap_or_else ( || empty) ,
@@ -140,16 +165,16 @@ impl Compiler {
140
165
}
141
166
142
167
pub fn crate_name ( & self ) -> Result < & Query < String > > {
143
- self . queries . crate_name . compute ( || {
144
- Ok ( match self . crate_name {
168
+ self . crate_name . compute ( || {
169
+ Ok ( match self . compiler . crate_name {
145
170
Some ( ref crate_name) => crate_name. clone ( ) ,
146
171
None => {
147
172
let parse_result = self . parse ( ) ?;
148
173
let krate = parse_result. peek ( ) ;
149
174
rustc_codegen_utils:: link:: find_crate_name (
150
175
Some ( self . session ( ) ) ,
151
176
& krate. attrs ,
152
- & self . input
177
+ & self . compiler . input
153
178
)
154
179
}
155
180
} )
@@ -159,11 +184,11 @@ impl Compiler {
159
184
pub fn expansion (
160
185
& self
161
186
) -> Result < & Query < ( ast:: Crate , Steal < Rc < RefCell < BoxedResolver > > > , Lrc < LintStore > ) > > {
162
- self . queries . expansion . compute ( || {
187
+ self . expansion . compute ( || {
163
188
let crate_name = self . crate_name ( ) ?. peek ( ) . clone ( ) ;
164
189
let ( krate, lint_store) = self . register_plugins ( ) ?. take ( ) ;
165
190
passes:: configure_and_expand (
166
- self . sess . clone ( ) ,
191
+ self . session ( ) . clone ( ) ,
167
192
lint_store. clone ( ) ,
168
193
self . codegen_backend ( ) . metadata_loader ( ) ,
169
194
krate,
@@ -175,7 +200,7 @@ impl Compiler {
175
200
}
176
201
177
202
pub fn dep_graph ( & self ) -> Result < & Query < DepGraph > > {
178
- self . queries . dep_graph . compute ( || {
203
+ self . dep_graph . compute ( || {
179
204
Ok ( match self . dep_graph_future ( ) ?. take ( ) {
180
205
None => DepGraph :: new_disabled ( ) ,
181
206
Some ( future) => {
@@ -192,57 +217,63 @@ impl Compiler {
192
217
}
193
218
194
219
pub fn lower_to_hir (
195
- & self ,
196
- ) -> Result < & Query < ( Steal < hir:: map:: Forest > , Steal < ResolverOutputs > ) > > {
197
- self . queries . lower_to_hir . compute ( || {
220
+ & ' tcx self ,
221
+ ) -> Result < & Query < ( & ' tcx hir:: map:: Forest , Steal < ResolverOutputs > ) > > {
222
+ self . lower_to_hir . compute ( || {
198
223
let expansion_result = self . expansion ( ) ?;
199
224
let peeked = expansion_result. peek ( ) ;
200
225
let krate = & peeked. 0 ;
201
226
let resolver = peeked. 1 . steal ( ) ;
202
227
let lint_store = & peeked. 2 ;
203
- let hir = Steal :: new ( resolver. borrow_mut ( ) . access ( |resolver| {
228
+ let hir = resolver. borrow_mut ( ) . access ( |resolver| {
204
229
passes:: lower_to_hir (
205
230
self . session ( ) ,
206
231
lint_store,
207
232
resolver,
208
233
& * self . dep_graph ( ) ?. peek ( ) ,
209
234
& krate
210
235
)
211
- } ) ?) ;
236
+ } ) ?;
237
+ let hir = self . arena . alloc ( hir) ;
212
238
Ok ( ( hir, Steal :: new ( BoxedResolver :: to_resolver_outputs ( resolver) ) ) )
213
239
} )
214
240
}
215
241
216
242
pub fn prepare_outputs ( & self ) -> Result < & Query < OutputFilenames > > {
217
- self . queries . prepare_outputs . compute ( || {
243
+ self . prepare_outputs . compute ( || {
218
244
let expansion_result = self . expansion ( ) ?;
219
245
let ( krate, boxed_resolver, _) = & * expansion_result. peek ( ) ;
220
246
let crate_name = self . crate_name ( ) ?;
221
247
let crate_name = crate_name. peek ( ) ;
222
- passes:: prepare_outputs ( self . session ( ) , self , & krate, & boxed_resolver, & crate_name)
248
+ passes:: prepare_outputs (
249
+ self . session ( ) , self . compiler , & krate, & boxed_resolver, & crate_name
250
+ )
223
251
} )
224
252
}
225
253
226
- pub fn global_ctxt ( & self ) -> Result < & Query < BoxedGlobalCtxt > > {
227
- self . queries . global_ctxt . compute ( || {
254
+ pub fn global_ctxt ( & ' tcx self ) -> Result < & Query < QueryContext < ' tcx > > > {
255
+ self . global_ctxt . compute ( || {
228
256
let crate_name = self . crate_name ( ) ?. peek ( ) . clone ( ) ;
229
257
let outputs = self . prepare_outputs ( ) ?. peek ( ) . clone ( ) ;
230
258
let lint_store = self . expansion ( ) ?. peek ( ) . 2 . clone ( ) ;
231
- let hir = self . lower_to_hir ( ) ?;
232
- let hir = hir. peek ( ) ;
233
- let ( hir_forest, resolver_outputs) = & * hir;
259
+ let hir = self . lower_to_hir ( ) ?. peek ( ) ;
260
+ let ( ref hir_forest, ref resolver_outputs) = & * hir;
234
261
Ok ( passes:: create_global_ctxt (
235
- self ,
262
+ self . compiler ,
236
263
lint_store,
237
- hir_forest. steal ( ) ,
264
+ hir_forest,
238
265
resolver_outputs. steal ( ) ,
239
266
outputs,
240
- & crate_name) )
267
+ & crate_name,
268
+ & self . gcx ,
269
+ & self . all_arenas ,
270
+ & self . arena ,
271
+ ) )
241
272
} )
242
273
}
243
274
244
- pub fn ongoing_codegen ( & self ) -> Result < & Query < Box < dyn Any > > > {
245
- self . queries . ongoing_codegen . compute ( || {
275
+ pub fn ongoing_codegen ( & ' tcx self ) -> Result < & Query < Box < dyn Any > > > {
276
+ self . ongoing_codegen . compute ( || {
246
277
let outputs = self . prepare_outputs ( ) ?;
247
278
self . global_ctxt ( ) ?. peek_mut ( ) . enter ( |tcx| {
248
279
tcx. analysis ( LOCAL_CRATE ) . ok ( ) ;
@@ -259,47 +290,89 @@ impl Compiler {
259
290
} )
260
291
}
261
292
262
- pub fn link ( & self ) -> Result < & Query < ( ) > > {
263
- self . queries . link . compute ( || {
264
- let sess = self . session ( ) ;
265
-
266
- let ongoing_codegen = self . ongoing_codegen ( ) ?. take ( ) ;
293
+ pub fn linker ( & ' tcx self ) -> Result < Linker > {
294
+ let dep_graph = self . dep_graph ( ) ?;
295
+ let prepare_outputs = self . prepare_outputs ( ) ?;
296
+ let ongoing_codegen = self . ongoing_codegen ( ) ?;
267
297
268
- self . codegen_backend ( ) . join_codegen_and_link (
269
- ongoing_codegen,
270
- sess,
271
- & * self . dep_graph ( ) ?. peek ( ) ,
272
- & * self . prepare_outputs ( ) ?. peek ( ) ,
273
- ) . map_err ( |_| ErrorReported ) ?;
298
+ let sess = self . session ( ) . clone ( ) ;
299
+ let codegen_backend = self . codegen_backend ( ) . clone ( ) ;
274
300
275
- Ok ( ( ) )
301
+ Ok ( Linker {
302
+ sess,
303
+ dep_graph : dep_graph. peek ( ) . clone ( ) ,
304
+ prepare_outputs : prepare_outputs. take ( ) ,
305
+ ongoing_codegen : ongoing_codegen. take ( ) ,
306
+ codegen_backend,
276
307
} )
277
308
}
309
+ }
310
+
311
+ pub struct Linker {
312
+ sess : Lrc < Session > ,
313
+ dep_graph : DepGraph ,
314
+ prepare_outputs : OutputFilenames ,
315
+ ongoing_codegen : Box < dyn Any > ,
316
+ codegen_backend : Lrc < Box < dyn CodegenBackend > > ,
317
+ }
318
+
319
+ impl Linker {
320
+ pub fn link ( self ) -> Result < ( ) > {
321
+ self . codegen_backend . join_codegen_and_link (
322
+ self . ongoing_codegen ,
323
+ & self . sess ,
324
+ & self . dep_graph ,
325
+ & self . prepare_outputs ,
326
+ ) . map_err ( |_| ErrorReported )
327
+ }
328
+ }
329
+
330
+ impl Compiler {
331
+ pub fn enter < F , T > ( & self , f : F ) -> T
332
+ where F : for < ' tcx > FnOnce ( & ' tcx Queries < ' tcx > ) -> T
333
+ {
334
+ let queries = Queries :: new ( & self ) ;
335
+ let ret = f ( & queries) ;
336
+
337
+ if self . session ( ) . opts . debugging_opts . query_stats {
338
+ if let Ok ( gcx) = queries. global_ctxt ( ) {
339
+ gcx. peek ( ) . print_stats ( ) ;
340
+ }
341
+ }
342
+
343
+ ret
344
+ }
278
345
279
346
// This method is different to all the other methods in `Compiler` because
280
347
// it lacks a `Queries` entry. It's also not currently used. It does serve
281
348
// as an example of how `Compiler` can be used, with additional steps added
282
349
// between some passes. And see `rustc_driver::run_compiler` for a more
283
350
// complex example.
284
351
pub fn compile ( & self ) -> Result < ( ) > {
285
- self . prepare_outputs ( ) ?;
352
+ let linker = self . enter ( |queries| {
353
+ queries. prepare_outputs ( ) ?;
286
354
287
- if self . session ( ) . opts . output_types . contains_key ( & OutputType :: DepInfo )
288
- && self . session ( ) . opts . output_types . len ( ) == 1
289
- {
290
- return Ok ( ( ) )
291
- }
355
+ if self . session ( ) . opts . output_types . contains_key ( & OutputType :: DepInfo )
356
+ && self . session ( ) . opts . output_types . len ( ) == 1
357
+ {
358
+ return Ok ( None )
359
+ }
360
+
361
+ queries. global_ctxt ( ) ?;
292
362
293
- self . global_ctxt ( ) ?;
363
+ // Drop AST after creating GlobalCtxt to free memory.
364
+ mem:: drop ( queries. expansion ( ) ?. take ( ) ) ;
294
365
295
- // Drop AST after creating GlobalCtxt to free memory.
296
- mem:: drop ( self . expansion ( ) ?. take ( ) ) ;
366
+ queries. ongoing_codegen ( ) ?;
297
367
298
- self . ongoing_codegen ( ) ?;
368
+ let linker = queries. linker ( ) ?;
369
+ Ok ( Some ( linker) )
370
+ } ) ?;
299
371
300
- // Drop GlobalCtxt after starting codegen to free memory.
301
- mem:: drop ( self . global_ctxt ( ) ?. take ( ) ) ;
372
+ if let Some ( linker) = linker {
373
+ linker. link ( ) ?
374
+ }
302
375
303
- self . link ( ) . map ( |_| ( ) )
376
+ Ok ( ( ) )
304
377
}
305
378
}
0 commit comments