@@ -104,6 +104,7 @@ pub struct ModuleConfig {
104
104
pub emit_ir : bool ,
105
105
pub emit_asm : bool ,
106
106
pub emit_obj : EmitObj ,
107
+
107
108
// Miscellaneous flags. These are mostly copied from command-line
108
109
// options.
109
110
pub verify_llvm_ir : bool ,
@@ -118,77 +119,144 @@ pub struct ModuleConfig {
118
119
}
119
120
120
121
impl ModuleConfig {
121
- fn new ( passes : Vec < String > ) -> ModuleConfig {
122
- ModuleConfig {
123
- passes,
124
- opt_level : None ,
125
- opt_size : None ,
126
-
127
- pgo_gen : SwitchWithOptPath :: Disabled ,
128
- pgo_use : None ,
129
-
130
- sanitizer : None ,
131
- sanitizer_recover : Default :: default ( ) ,
132
- sanitizer_memory_track_origins : 0 ,
133
-
134
- emit_no_opt_bc : false ,
135
- emit_pre_lto_bc : false ,
136
- emit_bc : false ,
137
- emit_bc_compressed : false ,
138
- emit_ir : false ,
139
- emit_asm : false ,
140
- emit_obj : EmitObj :: None ,
141
-
142
- verify_llvm_ir : false ,
143
- no_prepopulate_passes : false ,
144
- no_builtins : false ,
145
- time_module : true ,
146
- vectorize_loop : false ,
147
- vectorize_slp : false ,
148
- merge_functions : false ,
149
- inline_threshold : None ,
150
- new_llvm_pass_manager : None ,
122
+ fn new ( kind : ModuleKind , sess : & Session , no_builtins : bool ) -> ModuleConfig {
123
+ // If it's a regular module, use `$regular`, otherwise use `$other`.
124
+ // `$regular` and `$other` are evaluated lazily.
125
+ macro_rules! if_regular {
126
+ ( $regular: expr, $other: expr) => {
127
+ if let ModuleKind :: Regular = kind { $regular } else { $other }
128
+ } ;
151
129
}
152
- }
153
130
154
- fn set_flags ( & mut self , sess : & Session , no_builtins : bool ) {
155
- self . verify_llvm_ir = sess. verify_llvm_ir ( ) ;
156
- self . no_prepopulate_passes = sess. opts . cg . no_prepopulate_passes ;
157
- self . no_builtins = no_builtins || sess. target . target . options . no_builtins ;
158
- self . inline_threshold = sess. opts . cg . inline_threshold ;
159
- self . new_llvm_pass_manager = sess. opts . debugging_opts . new_llvm_pass_manager ;
160
-
161
- // Copy what clang does by turning on loop vectorization at O2 and
162
- // slp vectorization at O3. Otherwise configure other optimization aspects
163
- // of this pass manager builder.
164
- self . vectorize_loop = !sess. opts . cg . no_vectorize_loops
165
- && ( sess. opts . optimize == config:: OptLevel :: Default
166
- || sess. opts . optimize == config:: OptLevel :: Aggressive ) ;
167
-
168
- self . vectorize_slp =
169
- !sess. opts . cg . no_vectorize_slp && sess. opts . optimize == config:: OptLevel :: Aggressive ;
170
-
171
- // Some targets (namely, NVPTX) interact badly with the MergeFunctions
172
- // pass. This is because MergeFunctions can generate new function calls
173
- // which may interfere with the target calling convention; e.g. for the
174
- // NVPTX target, PTX kernels should not call other PTX kernels.
175
- // MergeFunctions can also be configured to generate aliases instead,
176
- // but aliases are not supported by some backends (again, NVPTX).
177
- // Therefore, allow targets to opt out of the MergeFunctions pass,
178
- // but otherwise keep the pass enabled (at O2 and O3) since it can be
179
- // useful for reducing code size.
180
- self . merge_functions = match sess
181
- . opts
182
- . debugging_opts
183
- . merge_functions
184
- . unwrap_or ( sess. target . target . options . merge_functions )
131
+ let opt_level_and_size = if_regular ! ( Some ( sess. opts. optimize) , None ) ;
132
+
133
+ let save_temps = sess. opts . cg . save_temps ;
134
+
135
+ let should_emit_obj = sess. opts . output_types . contains_key ( & OutputType :: Exe )
136
+ || match kind {
137
+ ModuleKind :: Regular => sess. opts . output_types . contains_key ( & OutputType :: Object ) ,
138
+ ModuleKind :: Allocator => false ,
139
+ ModuleKind :: Metadata => sess. opts . output_types . contains_key ( & OutputType :: Metadata ) ,
140
+ } ;
141
+
142
+ let emit_obj = if !should_emit_obj {
143
+ EmitObj :: None
144
+ } else if sess. target . target . options . obj_is_bitcode
145
+ || sess. opts . cg . linker_plugin_lto . enabled ( )
185
146
{
186
- MergeFunctions :: Disabled => false ,
187
- MergeFunctions :: Trampolines | MergeFunctions :: Aliases => {
188
- sess. opts . optimize == config:: OptLevel :: Default
189
- || sess. opts . optimize == config:: OptLevel :: Aggressive
147
+ EmitObj :: Bitcode
148
+ } else if sess. opts . debugging_opts . embed_bitcode {
149
+ match sess. opts . optimize {
150
+ config:: OptLevel :: No | config:: OptLevel :: Less => {
151
+ EmitObj :: ObjectCode ( BitcodeSection :: Marker )
152
+ }
153
+ _ => EmitObj :: ObjectCode ( BitcodeSection :: Full ) ,
190
154
}
155
+ } else {
156
+ EmitObj :: ObjectCode ( BitcodeSection :: None )
191
157
} ;
158
+
159
+ ModuleConfig {
160
+ passes : if_regular ! (
161
+ {
162
+ let mut passes = sess. opts. cg. passes. clone( ) ;
163
+ if sess. opts. debugging_opts. profile {
164
+ passes. push( "insert-gcov-profiling" . to_owned( ) ) ;
165
+ }
166
+ passes
167
+ } ,
168
+ vec![ ]
169
+ ) ,
170
+
171
+ opt_level : opt_level_and_size,
172
+ opt_size : opt_level_and_size,
173
+
174
+ pgo_gen : if_regular ! (
175
+ sess. opts. cg. profile_generate. clone( ) ,
176
+ SwitchWithOptPath :: Disabled
177
+ ) ,
178
+ pgo_use : if_regular ! ( sess. opts. cg. profile_use. clone( ) , None ) ,
179
+
180
+ sanitizer : if_regular ! ( sess. opts. debugging_opts. sanitizer. clone( ) , None ) ,
181
+ sanitizer_recover : if_regular ! (
182
+ sess. opts. debugging_opts. sanitizer_recover. clone( ) ,
183
+ vec![ ]
184
+ ) ,
185
+ sanitizer_memory_track_origins : if_regular ! (
186
+ sess. opts. debugging_opts. sanitizer_memory_track_origins,
187
+ 0
188
+ ) ,
189
+
190
+ emit_pre_lto_bc : if_regular ! (
191
+ save_temps || need_pre_lto_bitcode_for_incr_comp( sess) ,
192
+ false
193
+ ) ,
194
+ emit_no_opt_bc : if_regular ! ( save_temps, false ) ,
195
+ emit_bc : if_regular ! (
196
+ save_temps || sess. opts. output_types. contains_key( & OutputType :: Bitcode ) ,
197
+ save_temps
198
+ ) ,
199
+ emit_bc_compressed : match kind {
200
+ ModuleKind :: Regular | ModuleKind :: Allocator => {
201
+ // Emit compressed bitcode files for the crate if we're
202
+ // emitting an rlib. Whenever an rlib is created, the
203
+ // bitcode is inserted into the archive in order to allow
204
+ // LTO against it.
205
+ need_crate_bitcode_for_rlib ( sess)
206
+ }
207
+ ModuleKind :: Metadata => false ,
208
+ } ,
209
+ emit_ir : if_regular ! (
210
+ sess. opts. output_types. contains_key( & OutputType :: LlvmAssembly ) ,
211
+ false
212
+ ) ,
213
+ emit_asm : if_regular ! (
214
+ sess. opts. output_types. contains_key( & OutputType :: Assembly ) ,
215
+ false
216
+ ) ,
217
+ emit_obj,
218
+
219
+ verify_llvm_ir : sess. verify_llvm_ir ( ) ,
220
+ no_prepopulate_passes : sess. opts . cg . no_prepopulate_passes ,
221
+ no_builtins : no_builtins || sess. target . target . options . no_builtins ,
222
+
223
+ // Exclude metadata and allocator modules from time_passes output,
224
+ // since they throw off the "LLVM passes" measurement.
225
+ time_module : if_regular ! ( true , false ) ,
226
+
227
+ // Copy what clang does by turning on loop vectorization at O2 and
228
+ // slp vectorization at O3.
229
+ vectorize_loop : !sess. opts . cg . no_vectorize_loops
230
+ && ( sess. opts . optimize == config:: OptLevel :: Default
231
+ || sess. opts . optimize == config:: OptLevel :: Aggressive ) ,
232
+ vectorize_slp : !sess. opts . cg . no_vectorize_slp
233
+ && sess. opts . optimize == config:: OptLevel :: Aggressive ,
234
+
235
+ // Some targets (namely, NVPTX) interact badly with the
236
+ // MergeFunctions pass. This is because MergeFunctions can generate
237
+ // new function calls which may interfere with the target calling
238
+ // convention; e.g. for the NVPTX target, PTX kernels should not
239
+ // call other PTX kernels. MergeFunctions can also be configured to
240
+ // generate aliases instead, but aliases are not supported by some
241
+ // backends (again, NVPTX). Therefore, allow targets to opt out of
242
+ // the MergeFunctions pass, but otherwise keep the pass enabled (at
243
+ // O2 and O3) since it can be useful for reducing code size.
244
+ merge_functions : match sess
245
+ . opts
246
+ . debugging_opts
247
+ . merge_functions
248
+ . unwrap_or ( sess. target . target . options . merge_functions )
249
+ {
250
+ MergeFunctions :: Disabled => false ,
251
+ MergeFunctions :: Trampolines | MergeFunctions :: Aliases => {
252
+ sess. opts . optimize == config:: OptLevel :: Default
253
+ || sess. opts . optimize == config:: OptLevel :: Aggressive
254
+ }
255
+ } ,
256
+
257
+ inline_threshold : sess. opts . cg . inline_threshold ,
258
+ new_llvm_pass_manager : sess. opts . debugging_opts . new_llvm_pass_manager ,
259
+ }
192
260
}
193
261
194
262
pub fn bitcode_needed ( & self ) -> bool {
@@ -353,99 +421,9 @@ pub fn start_async_codegen<B: ExtraBackendMethods>(
353
421
let linker_info = LinkerInfo :: new ( tcx) ;
354
422
let crate_info = CrateInfo :: new ( tcx) ;
355
423
356
- // Figure out what we actually need to build.
357
- let mut modules_config = ModuleConfig :: new ( sess. opts . cg . passes . clone ( ) ) ;
358
- let mut metadata_config = ModuleConfig :: new ( vec ! [ ] ) ;
359
- let mut allocator_config = ModuleConfig :: new ( vec ! [ ] ) ;
360
-
361
- if sess. opts . debugging_opts . profile {
362
- modules_config. passes . push ( "insert-gcov-profiling" . to_owned ( ) )
363
- }
364
-
365
- modules_config. pgo_gen = sess. opts . cg . profile_generate . clone ( ) ;
366
- modules_config. pgo_use = sess. opts . cg . profile_use . clone ( ) ;
367
- modules_config. sanitizer = sess. opts . debugging_opts . sanitizer . clone ( ) ;
368
- modules_config. sanitizer_recover = sess. opts . debugging_opts . sanitizer_recover . clone ( ) ;
369
- modules_config. sanitizer_memory_track_origins =
370
- sess. opts . debugging_opts . sanitizer_memory_track_origins ;
371
- modules_config. opt_level = Some ( sess. opts . optimize ) ;
372
- modules_config. opt_size = Some ( sess. opts . optimize ) ;
373
-
374
- // Save all versions of the bytecode if we're saving our temporaries.
375
- if sess. opts . cg . save_temps {
376
- modules_config. emit_no_opt_bc = true ;
377
- modules_config. emit_pre_lto_bc = true ;
378
- modules_config. emit_bc = true ;
379
- metadata_config. emit_bc = true ;
380
- allocator_config. emit_bc = true ;
381
- }
382
-
383
- // Emit compressed bitcode files for the crate if we're emitting an rlib.
384
- // Whenever an rlib is created, the bitcode is inserted into the archive in
385
- // order to allow LTO against it.
386
- if need_crate_bitcode_for_rlib ( sess) {
387
- modules_config. emit_bc_compressed = true ;
388
- allocator_config. emit_bc_compressed = true ;
389
- }
390
-
391
- let emit_obj =
392
- if sess. target . target . options . obj_is_bitcode || sess. opts . cg . linker_plugin_lto . enabled ( ) {
393
- EmitObj :: Bitcode
394
- } else if sess. opts . debugging_opts . embed_bitcode {
395
- match sess. opts . optimize {
396
- config:: OptLevel :: No | config:: OptLevel :: Less => {
397
- EmitObj :: ObjectCode ( BitcodeSection :: Marker )
398
- }
399
- _ => EmitObj :: ObjectCode ( BitcodeSection :: Full ) ,
400
- }
401
- } else {
402
- EmitObj :: ObjectCode ( BitcodeSection :: None )
403
- } ;
404
-
405
- modules_config. emit_pre_lto_bc = need_pre_lto_bitcode_for_incr_comp ( sess) ;
406
-
407
- for output_type in sess. opts . output_types . keys ( ) {
408
- match * output_type {
409
- OutputType :: Bitcode => {
410
- modules_config. emit_bc = true ;
411
- }
412
- OutputType :: LlvmAssembly => {
413
- modules_config. emit_ir = true ;
414
- }
415
- OutputType :: Assembly => {
416
- modules_config. emit_asm = true ;
417
- // If we're not using the LLVM assembler, this function
418
- // could be invoked specially with output_type_assembly, so
419
- // in this case we still want the metadata object file.
420
- if !sess. opts . output_types . contains_key ( & OutputType :: Assembly ) {
421
- metadata_config. emit_obj = emit_obj;
422
- allocator_config. emit_obj = emit_obj;
423
- }
424
- }
425
- OutputType :: Object => {
426
- modules_config. emit_obj = emit_obj;
427
- }
428
- OutputType :: Metadata => {
429
- metadata_config. emit_obj = emit_obj;
430
- }
431
- OutputType :: Exe => {
432
- modules_config. emit_obj = emit_obj;
433
- metadata_config. emit_obj = emit_obj;
434
- allocator_config. emit_obj = emit_obj;
435
- }
436
- OutputType :: Mir => { }
437
- OutputType :: DepInfo => { }
438
- }
439
- }
440
-
441
- modules_config. set_flags ( sess, no_builtins) ;
442
- metadata_config. set_flags ( sess, no_builtins) ;
443
- allocator_config. set_flags ( sess, no_builtins) ;
444
-
445
- // Exclude metadata and allocator modules from time_passes output, since
446
- // they throw off the "LLVM passes" measurement.
447
- metadata_config. time_module = false ;
448
- allocator_config. time_module = false ;
424
+ let regular_config = ModuleConfig :: new ( ModuleKind :: Regular , sess, no_builtins) ;
425
+ let metadata_config = ModuleConfig :: new ( ModuleKind :: Metadata , sess, no_builtins) ;
426
+ let allocator_config = ModuleConfig :: new ( ModuleKind :: Allocator , sess, no_builtins) ;
449
427
450
428
let ( shared_emitter, shared_emitter_main) = SharedEmitter :: new ( ) ;
451
429
let ( codegen_worker_send, codegen_worker_receive) = channel ( ) ;
@@ -459,7 +437,7 @@ pub fn start_async_codegen<B: ExtraBackendMethods>(
459
437
coordinator_receive,
460
438
total_cgus,
461
439
sess. jobserver . clone ( ) ,
462
- Arc :: new ( modules_config ) ,
440
+ Arc :: new ( regular_config ) ,
463
441
Arc :: new ( metadata_config) ,
464
442
Arc :: new ( allocator_config) ,
465
443
coordinator_send. clone ( ) ,
@@ -959,7 +937,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
959
937
coordinator_receive : Receiver < Box < dyn Any + Send > > ,
960
938
total_cgus : usize ,
961
939
jobserver : Client ,
962
- modules_config : Arc < ModuleConfig > ,
940
+ regular_config : Arc < ModuleConfig > ,
963
941
metadata_config : Arc < ModuleConfig > ,
964
942
allocator_config : Arc < ModuleConfig > ,
965
943
tx_to_llvm_workers : Sender < Box < dyn Any + Send > > ,
@@ -1042,7 +1020,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
1042
1020
coordinator_send,
1043
1021
diag_emitter : shared_emitter. clone ( ) ,
1044
1022
output_filenames : tcx. output_filenames ( LOCAL_CRATE ) ,
1045
- regular_module_config : modules_config ,
1023
+ regular_module_config : regular_config ,
1046
1024
metadata_module_config : metadata_config,
1047
1025
allocator_module_config : allocator_config,
1048
1026
tm_factory : TargetMachineFactory ( backend. target_machine_factory ( tcx. sess , ol, false ) ) ,
0 commit comments