@@ -16,6 +16,7 @@ extern crate rustc_hir_analysis;
1616extern crate rustc_interface;
1717extern crate rustc_log;
1818extern crate rustc_middle;
19+ extern crate rustc_query_system;
1920extern crate rustc_session;
2021extern crate rustc_span;
2122extern crate rustc_target;
@@ -36,6 +37,8 @@ extern crate tikv_jemalloc_sys as _;
3637
3738mod log;
3839
40+ use std:: any:: Any ;
41+ use std:: cell:: RefCell ;
3942use std:: env;
4043use std:: num:: { NonZero , NonZeroI32 } ;
4144use std:: ops:: Range ;
@@ -51,6 +54,8 @@ use miri::{
5154} ;
5255use rustc_abi:: ExternAbi ;
5356use rustc_codegen_ssa:: traits:: CodegenBackend ;
57+ use rustc_codegen_ssa:: { CodegenResults , TargetConfig } ;
58+ use rustc_data_structures:: fx:: FxIndexMap ;
5459use rustc_data_structures:: sync:: { self , DynSync } ;
5560use rustc_driver:: Compilation ;
5661use rustc_hir:: def_id:: LOCAL_CRATE ;
@@ -66,8 +71,9 @@ use rustc_middle::middle::exported_symbols::{
6671use rustc_middle:: query:: LocalCrate ;
6772use rustc_middle:: traits:: { ObligationCause , ObligationCauseCode } ;
6873use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
69- use rustc_session:: EarlyDiagCtxt ;
70- use rustc_session:: config:: { CrateType , ErrorOutputType , OptLevel , Options } ;
74+ use rustc_query_system:: dep_graph:: { WorkProduct , WorkProductId } ;
75+ use rustc_session:: config:: { CrateType , ErrorOutputType , OptLevel , Options , OutputFilenames } ;
76+ use rustc_session:: { EarlyDiagCtxt , Session } ;
7177use rustc_span:: def_id:: DefId ;
7278use rustc_target:: spec:: Target ;
7379
@@ -192,15 +198,64 @@ fn make_miri_codegen_backend(opts: &Options, target: &Target) -> Box<dyn Codegen
192198}
193199
194200impl rustc_driver:: Callbacks for MiriCompilerCalls {
195- fn config ( & mut self , config : & mut rustc_interface:: interface:: Config ) {
196- config. make_codegen_backend = Some ( Box :: new ( make_miri_codegen_backend) ) ;
201+ fn config ( & mut self , config : & mut Config ) {
202+ let mut miri_config = self . miri_config . take ( ) ;
203+ let mut many_seeds = self . many_seeds . take ( ) ;
204+
205+ config. make_codegen_backend = Some ( Box :: new ( move |opts, target| {
206+ let early_dcx = EarlyDiagCtxt :: new ( opts. error_format ) ;
207+
208+ // Use the target_config method of the default codegen backend (eg LLVM) to ensure the
209+ // calculated target features match said backend by respecting eg -Ctarget-cpu.
210+ let target_config_backend =
211+ rustc_interface:: util:: get_codegen_backend ( & early_dcx, & opts. sysroot , None , target) ;
212+ let target_config_backend_init = Once :: new ( ) ;
213+
214+ Box :: new ( MiriCodegenBackend {
215+ miri_config : RefCell :: new ( miri_config. take ( ) ) ,
216+ many_seeds : RefCell :: new ( many_seeds. take ( ) ) ,
217+ target_config_override : Box :: new ( move |sess| {
218+ target_config_backend_init. call_once ( || target_config_backend. init ( sess) ) ;
219+ target_config_backend. target_config ( sess)
220+ } ) ,
221+ } )
222+ } ) ) ;
197223 }
224+ }
198225
199- fn after_analysis < ' tcx > (
200- & mut self ,
201- _: & rustc_interface:: interface:: Compiler ,
202- tcx : TyCtxt < ' tcx > ,
203- ) -> Compilation {
226+ struct MiriCodegenBackend {
227+ miri_config : RefCell < Option < MiriConfig > > ,
228+ many_seeds : RefCell < Option < ManySeedsConfig > > ,
229+ target_config_override : Box < dyn Fn ( & Session ) -> TargetConfig > ,
230+ }
231+
232+ impl CodegenBackend for MiriCodegenBackend {
233+ fn name ( & self ) -> & ' static str {
234+ "miri"
235+ }
236+
237+ fn locale_resource ( & self ) -> & ' static str {
238+ ""
239+ }
240+
241+ fn target_config ( & self , sess : & Session ) -> TargetConfig {
242+ ( self . target_config_override ) ( sess)
243+ }
244+
245+ fn codegen_crate < ' tcx > ( & self , _tcx : TyCtxt < ' tcx > ) -> Box < dyn Any > {
246+ unreachable ! ( )
247+ }
248+
249+ fn join_codegen (
250+ & self ,
251+ _ongoing_codegen : Box < dyn Any > ,
252+ _sess : & Session ,
253+ _outputs : & OutputFilenames ,
254+ ) -> ( CodegenResults , FxIndexMap < WorkProductId , WorkProduct > ) {
255+ unreachable ! ( )
256+ }
257+
258+ fn jit_crate < ' tcx > ( & self , tcx : TyCtxt < ' tcx > , mut args : Vec < String > ) -> ExitCode {
204259 // Compilation is done, interpretation is starting. Deal with diagnostics from the
205260 // compilation part. We cannot call `sess.finish_diagnostics()` as then "aborting due to
206261 // previous errors" gets printed twice.
@@ -218,9 +273,10 @@ impl rustc_driver::Callbacks for MiriCompilerCalls {
218273 let ( entry_def_id, entry_type) = entry_fn ( tcx) ;
219274
220275 // Obtain and complete the Miri configuration.
221- let mut config = self . miri_config . take ( ) . expect ( "after_analysis must only be called once" ) ;
276+ let config = self . miri_config . take ( ) . expect ( "after_analysis must only be called once" ) ;
277+
222278 // Add filename to `miri` arguments.
223- config . args . insert ( 0 , tcx. sess . io . input . filestem ( ) . to_string ( ) ) ;
279+ args. insert ( 0 , tcx. sess . io . input . filestem ( ) . to_string ( ) ) ;
224280
225281 // Adjust working directory for interpretation.
226282 if let Some ( cwd) = env:: var_os ( "MIRI_CWD" ) {
@@ -244,20 +300,27 @@ impl rustc_driver::Callbacks for MiriCompilerCalls {
244300
245301 // Invoke the interpreter.
246302 let res = if config. genmc_config . is_some ( ) {
247- assert ! ( self . many_seeds. is_none( ) ) ;
303+ assert ! ( self . many_seeds. borrow ( ) . is_none( ) ) ;
248304 run_genmc_mode ( tcx, & config, |genmc_ctx : Rc < GenmcCtx > | {
249- miri:: eval_entry ( tcx, entry_def_id, entry_type, & config, Some ( genmc_ctx) )
305+ miri:: eval_entry ( tcx, entry_def_id, entry_type, & args , & config, Some ( genmc_ctx) )
250306 } )
251307 } else if let Some ( many_seeds) = self . many_seeds . take ( ) {
252308 assert ! ( config. seed. is_none( ) ) ;
253309 run_many_seeds ( many_seeds, |seed| {
254310 let mut config = config. clone ( ) ;
255311 config. seed = Some ( seed) ;
256312 eprintln ! ( "Trying seed: {seed}" ) ;
257- miri:: eval_entry ( tcx, entry_def_id, entry_type, & config, /* genmc_ctx */ None )
313+ miri:: eval_entry (
314+ tcx,
315+ entry_def_id,
316+ entry_type,
317+ & args,
318+ & config,
319+ /* genmc_ctx */ None ,
320+ )
258321 } )
259322 } else {
260- miri:: eval_entry ( tcx, entry_def_id, entry_type, & config, None )
323+ miri:: eval_entry ( tcx, entry_def_id, entry_type, & args , & config, None )
261324 } ;
262325 // Process interpreter result.
263326 if let Err ( return_code) = res {
@@ -487,6 +550,7 @@ fn main() -> ExitCode {
487550
488551 let mut rustc_args = vec ! [ ] ;
489552 let mut after_dashdash = false ;
553+ let mut guest_args = vec ! [ ] ;
490554
491555 // Note that we require values to be given with `=`, not with a space.
492556 // This matches how rustc parses `-Z`.
@@ -499,7 +563,7 @@ fn main() -> ExitCode {
499563 rustc_args. extend ( miri:: MIRI_DEFAULT_ARGS . iter ( ) . map ( ToString :: to_string) ) ;
500564 } else if after_dashdash {
501565 // Everything that comes after `--` is forwarded to the interpreted crate.
502- miri_config . args . push ( arg) ;
566+ guest_args . push ( arg) ;
503567 } else if arg == "--" {
504568 after_dashdash = true ;
505569 } else if arg == "-Zmiri-disable-validation" {
@@ -746,7 +810,6 @@ fn main() -> ExitCode {
746810 many_seeds. map ( |seeds| ManySeedsConfig { seeds, keep_going : many_seeds_keep_going } ) ;
747811
748812 debug ! ( "rustc arguments: {:?}" , rustc_args) ;
749- debug ! ( "crate arguments: {:?}" , miri_config. args) ;
750813 if !miri_config. native_lib . is_empty ( ) && miri_config. native_lib_enable_tracing {
751814 // SAFETY: No other threads are running
752815 #[ cfg( all( unix, feature = "native-lib" ) ) ]
@@ -757,5 +820,9 @@ fn main() -> ExitCode {
757820 ) ;
758821 }
759822 }
823+ rustc_args. push ( "-Zjit-mode" . to_owned ( ) ) ;
824+ rustc_args. push ( "--" . to_owned ( ) ) ;
825+ rustc_args. extend ( guest_args) ;
826+
760827 run_compiler_and_exit ( & rustc_args, & mut MiriCompilerCalls :: new ( miri_config, many_seeds) )
761828}
0 commit comments