diff --git a/dynamic_instrumentation/src/callbacks.rs b/dynamic_instrumentation/src/callbacks.rs new file mode 100644 index 0000000000..75ebb73333 --- /dev/null +++ b/dynamic_instrumentation/src/callbacks.rs @@ -0,0 +1,86 @@ +use crate::instrument::Instrumenter; + +use rustc_ast::ast::{Item, ItemKind, Visibility, VisibilityKind}; +use rustc_ast::node_id::NodeId; +use rustc_ast::ptr::P; +use rustc_const_eval::transform::validate; +use rustc_driver::Compilation; +use rustc_interface::interface::Compiler; +use rustc_interface::Queries; +use rustc_middle::mir::MirPass; +use rustc_middle::ty::query::{ExternProviders, Providers}; +use rustc_middle::ty::WithOptConstParam; +use rustc_session::Session; +use rustc_span::def_id::LocalDefId; +use rustc_span::symbol::Ident; +use rustc_span::DUMMY_SP; + +use lazy_static::lazy_static; + +lazy_static! { + /// TODO(kkysen) can be made non-lazy when `Mutex::new` is `const` in rust 1.63 + pub static ref INSTRUMENTER: Instrumenter = Instrumenter::new(); +} + +pub struct NullCallbacks; + +impl rustc_driver::Callbacks for NullCallbacks {} + +pub struct MirTransformCallbacks; + +impl rustc_driver::Callbacks for MirTransformCallbacks { + fn config(&mut self, config: &mut rustc_interface::Config) { + config.override_queries = Some(override_queries); + } + + fn after_parsing<'tcx>( + &mut self, + _compiler: &Compiler, + queries: &'tcx Queries<'tcx>, + ) -> Compilation { + let parse = queries.parse().unwrap(); + let mut parse = parse.peek_mut(); + parse.items.push(P(Item { + attrs: Vec::new(), + id: NodeId::from_u32(0), + span: DUMMY_SP, + vis: Visibility { + kind: VisibilityKind::Inherited, + span: DUMMY_SP, + tokens: None, + }, + ident: Ident::from_str("c2rust_analysis_rt"), + kind: ItemKind::ExternCrate(None), + tokens: None, + })); + Compilation::Continue + } +} + +fn override_queries( + _sess: &Session, + providers: &mut Providers, + _extern_providers: &mut ExternProviders, +) { + providers.mir_built = |tcx, def: WithOptConstParam| { + let mut providers = Providers::default(); + rustc_mir_build::provide(&mut providers); + + let steal_mir = (providers.mir_built)(tcx, def); + let mut mir = steal_mir.steal(); + + let body_did = def.did.to_def_id(); + let fn_ty = tcx.type_of(body_did); + if fn_ty.is_fn() && !tcx.is_const_fn(body_did) && !tcx.is_static(body_did) { + INSTRUMENTER.instrument_fn(tcx, &mut mir, body_did); + + validate::Validator { + when: "After dynamic instrumentation".to_string(), + mir_phase: mir.phase, + } + .run_pass(tcx, &mut mir); + } + + tcx.alloc_steal_mir(mir) + }; +} diff --git a/dynamic_instrumentation/src/lib.rs b/dynamic_instrumentation/src/lib.rs index e1e8134b7b..8b7af26476 100644 --- a/dynamic_instrumentation/src/lib.rs +++ b/dynamic_instrumentation/src/lib.rs @@ -13,6 +13,7 @@ extern crate rustc_span; extern crate rustc_target; mod arg; +mod callbacks; mod hooks; mod instrument; mod into_operand; @@ -21,7 +22,7 @@ mod point; mod runtime_conversions; mod util; -use instrument::Instrumenter; +use callbacks::{MirTransformCallbacks, NullCallbacks, INSTRUMENTER}; use cargo::core::compiler::{CompileMode, Context, DefaultExecutor, Executor, Unit}; use cargo::core::{PackageId, Target, Verbosity, Workspace}; @@ -32,97 +33,13 @@ use cargo::util::CargoResult; use cargo::Config; use cargo_util::ProcessBuilder; -use rustc_ast::ast::{Item, ItemKind, Visibility, VisibilityKind}; -use rustc_ast::node_id::NodeId; -use rustc_ast::ptr::P; -use rustc_const_eval::transform::validate; -use rustc_driver::Compilation; -use rustc_interface::interface::Compiler; -use rustc_interface::Queries; -use rustc_middle::mir::MirPass; -use rustc_middle::ty::query::{ExternProviders, Providers}; -use rustc_middle::ty::WithOptConstParam; -use rustc_session::Session; -use rustc_span::def_id::LocalDefId; -use rustc_span::symbol::Ident; -use rustc_span::DUMMY_SP; - use anyhow::anyhow; -use lazy_static::lazy_static; use std::env; use std::ffi::OsString; use std::path::Path; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, Mutex}; -lazy_static! { - /// TODO(kkysen) can be made non-lazy when `Mutex::new` is `const` in rust 1.63 - static ref INSTRUMENTER: Instrumenter = Instrumenter::new(); -} - -struct NullCallbacks; - -impl rustc_driver::Callbacks for NullCallbacks {} - -struct MirTransformCallbacks; - -impl rustc_driver::Callbacks for MirTransformCallbacks { - fn config(&mut self, config: &mut rustc_interface::Config) { - config.override_queries = Some(override_queries); - } - - fn after_parsing<'tcx>( - &mut self, - _compiler: &Compiler, - queries: &'tcx Queries<'tcx>, - ) -> Compilation { - let parse = queries.parse().unwrap(); - let mut parse = parse.peek_mut(); - parse.items.push(P(Item { - attrs: Vec::new(), - id: NodeId::from_u32(0), - span: DUMMY_SP, - vis: Visibility { - kind: VisibilityKind::Inherited, - span: DUMMY_SP, - tokens: None, - }, - ident: Ident::from_str("c2rust_analysis_rt"), - kind: ItemKind::ExternCrate(None), - tokens: None, - })); - Compilation::Continue - } -} - -fn override_queries( - _sess: &Session, - providers: &mut Providers, - _extern_providers: &mut ExternProviders, -) { - providers.mir_built = |tcx, def: WithOptConstParam| { - let mut providers = Providers::default(); - rustc_mir_build::provide(&mut providers); - - let steal_mir = (providers.mir_built)(tcx, def); - let mut mir = steal_mir.steal(); - - let body_did = def.did.to_def_id(); - let fn_ty = tcx.type_of(body_did); - if fn_ty.is_fn() && !tcx.is_const_fn(body_did) && !tcx.is_static(body_did) { - INSTRUMENTER.instrument_fn(tcx, &mut mir, body_did); - - validate::Validator { - when: "After dynamic instrumentation".to_string(), - mir_phase: mir.phase, - } - .run_pass(tcx, &mut mir); - } - - tcx.alloc_steal_mir(mir) - }; -} - pub fn instrument( metadata_file_path: &Path, rt_path: &Path,