From e207be653eaec0d1dddbf0209a33fe485ef34be6 Mon Sep 17 00:00:00 2001 From: Ryan Scott Date: Thu, 20 Apr 2023 14:24:57 -0400 Subject: [PATCH] Add EXPORT_ALL option for exporting more symbols in MIR JSON This will be needed for a `cargo saw-export` command (#39), which works over more symbols than just the ones with a `crux_test` configuration. --- doc/rustc.md | 3 +++ src/analyz/mod.rs | 12 +++++++++--- src/analyz/to_json.rs | 16 ++++++++++++++++ src/bin/mir-json-rustc-wrapper.rs | 11 ++++++++++- src/bin/mir-json.rs | 15 ++++++++++++--- 5 files changed, 50 insertions(+), 7 deletions(-) diff --git a/doc/rustc.md b/doc/rustc.md index 5047fb9..19356ae 100644 --- a/doc/rustc.md +++ b/doc/rustc.md @@ -50,6 +50,9 @@ variables: dependencies. * `CRUX_USE_OVERRIDE_CRATES`: The list of crates for which `crucible-mir` overrides should be used. +* `EXPORT_ALL`: If this environment variable is set, then the MIR JSON file + will export all top-level functions. Otherwise, it will only export those + functions with a `#[crux_test]` attribute. ## Other binaries diff --git a/src/analyz/mod.rs b/src/analyz/mod.rs index 6ff04fb..7766bd1 100644 --- a/src/analyz/mod.rs +++ b/src/analyz/mod.rs @@ -699,7 +699,7 @@ fn init_instances_from_mono_items(ms: &mut MirState) -> io::Result<()> { fn init_instances_from_tests(ms: &mut MirState, out: &mut impl JsonOutput) -> io::Result<()> { let tcx = ms.state.tcx; for &def_id in tcx.mir_keys(def_id::LOCAL_CRATE) { - if !has_test_attr(tcx, def_id) { + if ms.export_style == ExportStyle::ExportCruxTests && !has_test_attr(tcx, def_id) { continue; } @@ -884,6 +884,7 @@ fn emit_fn<'tcx>( state: ms.state, tys: ms.tys, match_span_map: ms.match_span_map, + export_style: ms.export_style, }; let ms = &mut ms; @@ -945,6 +946,7 @@ pub struct AnalysisData { fn analyze_inner<'tcx, O: JsonOutput, F: FnOnce(&Path) -> io::Result>( sess: &Session, queries: &'tcx Queries<'tcx>, + export_style: ExportStyle, mk_output: F, ) -> Result>, serde_cbor::Error> { let mut mir_path = None; @@ -993,6 +995,7 @@ fn analyze_inner<'tcx, O: JsonOutput, F: FnOnce(&Path) -> io::Result>( state: &state, tys: &mut tys, match_span_map: &get_match_spans(), + export_style: export_style, }; // Traits and top-level statics can be enumerated directly. @@ -1037,8 +1040,9 @@ fn analyze_inner<'tcx, O: JsonOutput, F: FnOnce(&Path) -> io::Result>( pub fn analyze_nonstreaming<'tcx>( sess: &Session, queries: &'tcx Queries<'tcx>, + export_style: ExportStyle, ) -> Result>, serde_cbor::Error> { - let opt_ad = analyze_inner(sess, queries, |_| { Ok(lib_util::Output::default()) })?; + let opt_ad = analyze_inner(sess, queries, export_style, |_| { Ok(lib_util::Output::default()) })?; let AnalysisData { mir_path, extern_mir_paths, output: out } = match opt_ad { Some(x) => x, None => return Ok(None), @@ -1067,8 +1071,9 @@ pub fn analyze_nonstreaming<'tcx>( pub fn analyze_streaming<'tcx>( sess: &Session, queries: &'tcx Queries<'tcx>, + export_style: ExportStyle, ) -> Result>, serde_cbor::Error> { - let opt_ad = analyze_inner(sess, queries, lib_util::start_streaming)?; + let opt_ad = analyze_inner(sess, queries, export_style, lib_util::start_streaming)?; let AnalysisData { mir_path, extern_mir_paths, output } = match opt_ad { Some(x) => x, None => return Ok(None), @@ -1078,6 +1083,7 @@ pub fn analyze_streaming<'tcx>( } pub use self::analyze_streaming as analyze; +pub use analyz::to_json::ExportStyle; fn make_attr(key: &str, value: &str) -> ast::Attribute { ast::Attribute { diff --git a/src/analyz/to_json.rs b/src/analyz/to_json.rs index e22d78e..56d21b4 100644 --- a/src/analyz/to_json.rs +++ b/src/analyz/to_json.rs @@ -247,6 +247,21 @@ impl<'tcx> TyIntern<'tcx> { } } +/// How many functions should be exported in the JSON output? +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +pub enum ExportStyle { + /// Only export functions annotated with the `#[crux_test]` attribute. + ExportCruxTests, + /// Export all functions. + ExportAll +} + +impl Default for ExportStyle { + fn default() -> Self { + ExportStyle::ExportCruxTests + } +} + pub struct MirState<'a, 'tcx : 'a> { pub mir: Option<&'tcx Body<'tcx>>, pub used: &'a mut Used<'tcx>, @@ -263,6 +278,7 @@ pub struct MirState<'a, 'tcx : 'a> { /// rewritten. This seems okay for now since the user is mostly interested in coverage in /// their own top-level crate anyway. pub match_span_map: &'a HashMap, + pub export_style: ExportStyle, } /// Trait for converting MIR elements to JSON. diff --git a/src/bin/mir-json-rustc-wrapper.rs b/src/bin/mir-json-rustc-wrapper.rs index cac9d64..660df0d 100644 --- a/src/bin/mir-json-rustc-wrapper.rs +++ b/src/bin/mir-json-rustc-wrapper.rs @@ -107,6 +107,7 @@ fn scrub_externs(externs: &mut Externs, use_override_crates: &HashSet) { struct MirJsonCallbacks { analysis_data: Option>, use_override_crates: HashSet, + export_style: analyz::ExportStyle, } impl rustc_driver::Callbacks for MirJsonCallbacks { @@ -137,7 +138,7 @@ impl rustc_driver::Callbacks for MirJsonCallbacks { compiler: &Compiler, queries: &'tcx Queries<'tcx>, ) -> Compilation { - self.analysis_data = analyz::analyze(compiler.session(), queries).unwrap(); + self.analysis_data = analyz::analyze(compiler.session(), queries, self.export_style).unwrap(); Compilation::Continue } } @@ -196,6 +197,12 @@ fn go() { } } + let export_style = if env::var("EXPORT_ALL").is_ok() { + analyz::ExportStyle::ExportAll + } else { + analyz::ExportStyle::ExportCruxTests + }; + let test_idx = match args.iter().position(|s| s == "--test") { None => { @@ -207,6 +214,7 @@ fn go() { &mut MirJsonCallbacks { analysis_data: None, use_override_crates: use_override_crates.clone(), + export_style, }, None, None, @@ -242,6 +250,7 @@ fn go() { let mut callbacks = MirJsonCallbacks { analysis_data: None, use_override_crates: use_override_crates.clone(), + export_style, }; rustc_driver::run_compiler( &args, diff --git a/src/bin/mir-json.rs b/src/bin/mir-json.rs index 3e23f4d..119b044 100644 --- a/src/bin/mir-json.rs +++ b/src/bin/mir-json.rs @@ -17,8 +17,11 @@ use mir_json::analyz; use rustc_driver::Compilation; use rustc_interface::interface::Compiler; use rustc_interface::Queries; +use std::env; -struct MirJsonCallbacks; +struct MirJsonCallbacks { + export_style: analyz::ExportStyle, +} impl rustc_driver::Callbacks for MirJsonCallbacks { fn after_parsing<'tcx>( @@ -46,7 +49,7 @@ impl rustc_driver::Callbacks for MirJsonCallbacks { compiler: &Compiler, queries: &'tcx Queries<'tcx>, ) -> Compilation { - analyz::analyze(compiler.session(), queries).unwrap(); + analyz::analyze(compiler.session(), queries, self.export_style).unwrap(); Compilation::Continue } } @@ -54,9 +57,15 @@ impl rustc_driver::Callbacks for MirJsonCallbacks { fn go() { let args: Vec = std::env::args().collect(); + let export_style = if env::var("EXPORT_ALL").is_ok() { + analyz::ExportStyle::ExportAll + } else { + analyz::ExportStyle::ExportCruxTests + }; + rustc_driver::run_compiler( &args, // args: &[String] - &mut MirJsonCallbacks, + &mut MirJsonCallbacks { export_style }, None, None, ).unwrap();