@@ -43,6 +43,7 @@ use rustc_session::config::{CrateType, OutputFilenames, OutputType};
4343use rustc_session:: cstore:: MetadataLoaderDyn ;
4444use rustc_session:: output:: out_filename;
4545use rustc_session:: Session ;
46+ use rustc_smir:: rustc_internal;
4647use rustc_target:: abi:: Endian ;
4748use rustc_target:: spec:: PanicStrategy ;
4849use std:: any:: Any ;
@@ -208,105 +209,115 @@ impl CodegenBackend for GotocCodegenBackend {
208209 rustc_metadata : EncodedMetadata ,
209210 _need_metadata_module : bool ,
210211 ) -> Box < dyn Any > {
211- super :: utils:: init ( ) ;
212-
213- // Queries shouldn't change today once codegen starts.
214- let queries = self . queries . lock ( ) . unwrap ( ) . clone ( ) ;
215- check_target ( tcx. sess ) ;
216- check_options ( tcx. sess ) ;
217-
218- // Codegen all items that need to be processed according to the selected reachability mode:
219- //
220- // - Harnesses: Generate one model per local harnesses (marked with `kani::proof` attribute).
221- // - Tests: Generate one model per test harnesses.
222- // - PubFns: Generate code for all reachable logic starting from the local public functions.
223- // - None: Don't generate code. This is used to compile dependencies.
224- let base_filename = tcx. output_filenames ( ( ) ) . output_path ( OutputType :: Object ) ;
225- let reachability = queries. args ( ) . reachability_analysis ;
226- let mut results = GotoCodegenResults :: new ( tcx, reachability) ;
227- match reachability {
228- ReachabilityType :: Harnesses => {
229- // Cross-crate collecting of all items that are reachable from the crate harnesses.
230- let harnesses = queries. target_harnesses ( ) ;
231- let mut items: HashSet < DefPathHash > = HashSet :: with_capacity ( harnesses. len ( ) ) ;
232- items. extend ( harnesses) ;
233- let harnesses =
234- filter_crate_items ( tcx, |_, def_id| items. contains ( & tcx. def_path_hash ( def_id) ) ) ;
235- for harness in harnesses {
236- let model_path =
237- queries. harness_model_path ( & tcx. def_path_hash ( harness. def_id ( ) ) ) . unwrap ( ) ;
212+ let ret_val = rustc_internal:: run ( tcx, || {
213+ super :: utils:: init ( ) ;
214+
215+ // Queries shouldn't change today once codegen starts.
216+ let queries = self . queries . lock ( ) . unwrap ( ) . clone ( ) ;
217+ check_target ( tcx. sess ) ;
218+ check_options ( tcx. sess ) ;
219+
220+ // Codegen all items that need to be processed according to the selected reachability mode:
221+ //
222+ // - Harnesses: Generate one model per local harnesses (marked with `kani::proof` attribute).
223+ // - Tests: Generate one model per test harnesses.
224+ // - PubFns: Generate code for all reachable logic starting from the local public functions.
225+ // - None: Don't generate code. This is used to compile dependencies.
226+ let base_filename = tcx. output_filenames ( ( ) ) . output_path ( OutputType :: Object ) ;
227+ let reachability = queries. args ( ) . reachability_analysis ;
228+ let mut results = GotoCodegenResults :: new ( tcx, reachability) ;
229+ match reachability {
230+ ReachabilityType :: Harnesses => {
231+ // Cross-crate collecting of all items that are reachable from the crate harnesses.
232+ let harnesses = queries. target_harnesses ( ) ;
233+ let mut items: HashSet < DefPathHash > = HashSet :: with_capacity ( harnesses. len ( ) ) ;
234+ items. extend ( harnesses) ;
235+ let harnesses = filter_crate_items ( tcx, |_, def_id| {
236+ items. contains ( & tcx. def_path_hash ( def_id) )
237+ } ) ;
238+ for harness in harnesses {
239+ let model_path = queries
240+ . harness_model_path ( & tcx. def_path_hash ( harness. def_id ( ) ) )
241+ . unwrap ( ) ;
242+ let ( gcx, items) =
243+ self . codegen_items ( tcx, & [ harness] , model_path, & results. machine_model ) ;
244+ results. extend ( gcx, items, None ) ;
245+ }
246+ }
247+ ReachabilityType :: Tests => {
248+ // We're iterating over crate items here, so what we have to codegen is the "test description" containing the
249+ // test closure that we want to execute
250+ // TODO: Refactor this code so we can guarantee that the pair (test_fn, test_desc) actually match.
251+ let mut descriptions = vec ! [ ] ;
252+ let harnesses = filter_const_crate_items ( tcx, |_, def_id| {
253+ if is_test_harness_description ( tcx, def_id) {
254+ descriptions. push ( def_id) ;
255+ true
256+ } else {
257+ false
258+ }
259+ } ) ;
260+ // Codegen still takes a considerable amount, thus, we only generate one model for
261+ // all harnesses and copy them for each harness.
262+ // We will be able to remove this once we optimize all calls to CBMC utilities.
263+ // https://github.com/model-checking/kani/issues/1971
264+ let model_path = base_filename. with_extension ( ArtifactType :: SymTabGoto ) ;
238265 let ( gcx, items) =
239- self . codegen_items ( tcx, & [ harness ] , model_path, & results. machine_model ) ;
266+ self . codegen_items ( tcx, & harnesses , & model_path, & results. machine_model ) ;
240267 results. extend ( gcx, items, None ) ;
241- }
242- }
243- ReachabilityType :: Tests => {
244- // We're iterating over crate items here, so what we have to codegen is the "test description" containing the
245- // test closure that we want to execute
246- // TODO: Refactor this code so we can guarantee that the pair (test_fn, test_desc) actually match.
247- let mut descriptions = vec ! [ ] ;
248- let harnesses = filter_const_crate_items ( tcx , |_ , def_id| {
249- if is_test_harness_description ( tcx , def_id ) {
250- descriptions . push ( def_id ) ;
251- true
252- } else {
253- false
268+
269+ for ( test_fn , test_desc ) in harnesses . iter ( ) . zip ( descriptions . iter ( ) ) {
270+ let instance =
271+ if let MonoItem :: Fn ( instance ) = test_fn { instance } else { continue } ;
272+ let metadata =
273+ gen_test_metadata ( tcx , * test_desc, * instance , & base_filename ) ;
274+ let test_model_path = & metadata . goto_file . as_ref ( ) . unwrap ( ) ;
275+ std :: fs :: copy ( & model_path , test_model_path ) . expect ( & format ! (
276+ "Failed to copy {} to {}" ,
277+ model_path . display ( ) ,
278+ test_model_path . display ( )
279+ ) ) ;
280+ results . harnesses . push ( metadata ) ;
254281 }
255- } ) ;
256- // Codegen still takes a considerable amount, thus, we only generate one model for
257- // all harnesses and copy them for each harness.
258- // We will be able to remove this once we optimize all calls to CBMC utilities.
259- // https://github.com/model-checking/kani/issues/1971
260- let model_path = base_filename. with_extension ( ArtifactType :: SymTabGoto ) ;
261- let ( gcx, items) =
262- self . codegen_items ( tcx, & harnesses, & model_path, & results. machine_model ) ;
263- results. extend ( gcx, items, None ) ;
264-
265- for ( test_fn, test_desc) in harnesses. iter ( ) . zip ( descriptions. iter ( ) ) {
266- let instance =
267- if let MonoItem :: Fn ( instance) = test_fn { instance } else { continue } ;
268- let metadata = gen_test_metadata ( tcx, * test_desc, * instance, & base_filename) ;
269- let test_model_path = & metadata. goto_file . as_ref ( ) . unwrap ( ) ;
270- std:: fs:: copy ( & model_path, test_model_path) . expect ( & format ! (
271- "Failed to copy {} to {}" ,
272- model_path. display( ) ,
273- test_model_path. display( )
274- ) ) ;
275- results. harnesses . push ( metadata) ;
282+ }
283+ ReachabilityType :: None => { }
284+ ReachabilityType :: PubFns => {
285+ let entry_fn = tcx. entry_fn ( ( ) ) . map ( |( id, _) | id) ;
286+ let local_reachable = filter_crate_items ( tcx, |_, def_id| {
287+ ( tcx. is_reachable_non_generic ( def_id) && tcx. def_kind ( def_id) . is_fn_like ( ) )
288+ || entry_fn == Some ( def_id)
289+ } ) ;
290+ let model_path = base_filename. with_extension ( ArtifactType :: SymTabGoto ) ;
291+ let ( gcx, items) = self . codegen_items (
292+ tcx,
293+ & local_reachable,
294+ & model_path,
295+ & results. machine_model ,
296+ ) ;
297+ results. extend ( gcx, items, None ) ;
276298 }
277299 }
278- ReachabilityType :: None => { }
279- ReachabilityType :: PubFns => {
280- let entry_fn = tcx. entry_fn ( ( ) ) . map ( |( id, _) | id) ;
281- let local_reachable = filter_crate_items ( tcx, |_, def_id| {
282- ( tcx. is_reachable_non_generic ( def_id) && tcx. def_kind ( def_id) . is_fn_like ( ) )
283- || entry_fn == Some ( def_id)
284- } ) ;
285- let model_path = base_filename. with_extension ( ArtifactType :: SymTabGoto ) ;
286- let ( gcx, items) =
287- self . codegen_items ( tcx, & local_reachable, & model_path, & results. machine_model ) ;
288- results. extend ( gcx, items, None ) ;
289- }
290- }
291300
292- if reachability != ReachabilityType :: None {
293- // Print compilation report.
294- results. print_report ( tcx) ;
295-
296- if reachability != ReachabilityType :: Harnesses {
297- // In a workspace, cargo seems to be using the same file prefix to build a crate that is
298- // a package lib and also a dependency of another package.
299- // To avoid overriding the metadata for its verification, we skip this step when
300- // reachability is None, even because there is nothing to record.
301- write_file (
302- & base_filename,
303- ArtifactType :: Metadata ,
304- & results. generate_metadata ( ) ,
305- queries. args ( ) . output_pretty_json ,
306- ) ;
301+ if reachability != ReachabilityType :: None {
302+ // Print compilation report.
303+ results. print_report ( tcx) ;
304+
305+ if reachability != ReachabilityType :: Harnesses {
306+ // In a workspace, cargo seems to be using the same file prefix to build a crate that is
307+ // a package lib and also a dependency of another package.
308+ // To avoid overriding the metadata for its verification, we skip this step when
309+ // reachability is None, even because there is nothing to record.
310+ write_file (
311+ & base_filename,
312+ ArtifactType :: Metadata ,
313+ & results. generate_metadata ( ) ,
314+ queries. args ( ) . output_pretty_json ,
315+ ) ;
316+ }
307317 }
308- }
309- codegen_results ( tcx, rustc_metadata, & results. machine_model )
318+ codegen_results ( tcx, rustc_metadata, & results. machine_model )
319+ } ) ;
320+ ret_val. unwrap ( )
310321 }
311322
312323 fn join_codegen (
0 commit comments