@@ -18,6 +18,7 @@ extern crate rustc_hir_analysis;
1818extern crate rustc_interface;
1919extern crate rustc_log;
2020extern crate rustc_middle;
21+ extern crate rustc_query_system;
2122extern crate rustc_session;
2223extern crate rustc_span;
2324extern crate rustc_target;
@@ -38,9 +39,12 @@ extern crate tikv_jemalloc_sys as _;
3839
3940mod log;
4041
42+ use std:: any:: Any ;
43+ use std:: cell:: RefCell ;
4144use std:: env;
4245use std:: num:: { NonZero , NonZeroI32 } ;
4346use std:: ops:: Range ;
47+ use std:: process:: ExitCode ;
4448use std:: rc:: Rc ;
4549use std:: str:: FromStr ;
4650use std:: sync:: Once ;
@@ -52,6 +56,8 @@ use miri::{
5256} ;
5357use rustc_abi:: ExternAbi ;
5458use rustc_codegen_ssa:: traits:: CodegenBackend ;
59+ use rustc_codegen_ssa:: { CodegenResults , TargetConfig } ;
60+ use rustc_data_structures:: fx:: FxIndexMap ;
5561use rustc_data_structures:: sync:: { self , DynSync } ;
5662use rustc_driver:: Compilation ;
5763use rustc_hir:: def_id:: LOCAL_CRATE ;
@@ -67,8 +73,9 @@ use rustc_middle::middle::exported_symbols::{
6773use rustc_middle:: query:: LocalCrate ;
6874use rustc_middle:: traits:: { ObligationCause , ObligationCauseCode } ;
6975use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
70- use rustc_session:: EarlyDiagCtxt ;
71- use rustc_session:: config:: { CrateType , ErrorOutputType , OptLevel , Options } ;
76+ use rustc_query_system:: dep_graph:: { WorkProduct , WorkProductId } ;
77+ use rustc_session:: config:: { CrateType , ErrorOutputType , OptLevel , Options , OutputFilenames } ;
78+ use rustc_session:: { EarlyDiagCtxt , Session } ;
7279use rustc_span:: def_id:: DefId ;
7380use rustc_target:: spec:: Target ;
7481
@@ -193,15 +200,64 @@ fn make_miri_codegen_backend(opts: &Options, target: &Target) -> Box<dyn Codegen
193200}
194201
195202impl rustc_driver:: Callbacks for MiriCompilerCalls {
196- fn config ( & mut self , config : & mut rustc_interface:: interface:: Config ) {
197- config. make_codegen_backend = Some ( Box :: new ( make_miri_codegen_backend) ) ;
203+ fn config ( & mut self , config : & mut Config ) {
204+ let mut miri_config = self . miri_config . take ( ) ;
205+ let mut many_seeds = self . many_seeds . take ( ) ;
206+
207+ config. make_codegen_backend = Some ( Box :: new ( move |opts, target| {
208+ let early_dcx = EarlyDiagCtxt :: new ( opts. error_format ) ;
209+
210+ // Use the target_config method of the default codegen backend (eg LLVM) to ensure the
211+ // calculated target features match said backend by respecting eg -Ctarget-cpu.
212+ let target_config_backend =
213+ rustc_interface:: util:: get_codegen_backend ( & early_dcx, & opts. sysroot , None , target) ;
214+ let target_config_backend_init = Once :: new ( ) ;
215+
216+ Box :: new ( MiriCodegenBackend {
217+ miri_config : RefCell :: new ( miri_config. take ( ) ) ,
218+ many_seeds : RefCell :: new ( many_seeds. take ( ) ) ,
219+ target_config_override : Box :: new ( move |sess| {
220+ target_config_backend_init. call_once ( || target_config_backend. init ( sess) ) ;
221+ target_config_backend. target_config ( sess)
222+ } ) ,
223+ } )
224+ } ) ) ;
198225 }
226+ }
199227
200- fn after_analysis < ' tcx > (
201- & mut self ,
202- _: & rustc_interface:: interface:: Compiler ,
203- tcx : TyCtxt < ' tcx > ,
204- ) -> Compilation {
228+ struct MiriCodegenBackend {
229+ miri_config : RefCell < Option < MiriConfig > > ,
230+ many_seeds : RefCell < Option < ManySeedsConfig > > ,
231+ target_config_override : Box < dyn Fn ( & Session ) -> TargetConfig > ,
232+ }
233+
234+ impl CodegenBackend for MiriCodegenBackend {
235+ fn name ( & self ) -> & ' static str {
236+ "miri"
237+ }
238+
239+ fn locale_resource ( & self ) -> & ' static str {
240+ ""
241+ }
242+
243+ fn target_config ( & self , sess : & Session ) -> TargetConfig {
244+ ( self . target_config_override ) ( sess)
245+ }
246+
247+ fn codegen_crate < ' tcx > ( & self , _tcx : TyCtxt < ' tcx > ) -> Box < dyn Any > {
248+ unreachable ! ( )
249+ }
250+
251+ fn join_codegen (
252+ & self ,
253+ _ongoing_codegen : Box < dyn Any > ,
254+ _sess : & Session ,
255+ _outputs : & OutputFilenames ,
256+ ) -> ( CodegenResults , FxIndexMap < WorkProductId , WorkProduct > ) {
257+ unreachable ! ( )
258+ }
259+
260+ fn jit_crate < ' tcx > ( & self , tcx : TyCtxt < ' tcx > , mut args : Vec < String > ) -> ExitCode {
205261 // Compilation is done, interpretation is starting. Deal with diagnostics from the
206262 // compilation part. We cannot call `sess.finish_diagnostics()` as then "aborting due to
207263 // previous errors" gets printed twice.
@@ -219,9 +275,10 @@ impl rustc_driver::Callbacks for MiriCompilerCalls {
219275 let ( entry_def_id, entry_type) = entry_fn ( tcx) ;
220276
221277 // Obtain and complete the Miri configuration.
222- let mut config = self . miri_config . take ( ) . expect ( "after_analysis must only be called once" ) ;
278+ let config = self . miri_config . take ( ) . expect ( "after_analysis must only be called once" ) ;
279+
223280 // Add filename to `miri` arguments.
224- config . args . insert ( 0 , tcx. sess . io . input . filestem ( ) . to_string ( ) ) ;
281+ args. insert ( 0 , tcx. sess . io . input . filestem ( ) . to_string ( ) ) ;
225282
226283 // Adjust working directory for interpretation.
227284 if let Some ( cwd) = env:: var_os ( "MIRI_CWD" ) {
@@ -245,20 +302,27 @@ impl rustc_driver::Callbacks for MiriCompilerCalls {
245302
246303 // Invoke the interpreter.
247304 let res = if config. genmc_config . is_some ( ) {
248- assert ! ( self . many_seeds. is_none( ) ) ;
305+ assert ! ( self . many_seeds. borrow ( ) . is_none( ) ) ;
249306 run_genmc_mode ( tcx, & config, |genmc_ctx : Rc < GenmcCtx > | {
250- miri:: eval_entry ( tcx, entry_def_id, entry_type, & config, Some ( genmc_ctx) )
307+ miri:: eval_entry ( tcx, entry_def_id, entry_type, & args , & config, Some ( genmc_ctx) )
251308 } )
252309 } else if let Some ( many_seeds) = self . many_seeds . take ( ) {
253310 assert ! ( config. seed. is_none( ) ) ;
254311 run_many_seeds ( many_seeds, |seed| {
255312 let mut config = config. clone ( ) ;
256313 config. seed = Some ( seed) ;
257314 eprintln ! ( "Trying seed: {seed}" ) ;
258- miri:: eval_entry ( tcx, entry_def_id, entry_type, & config, /* genmc_ctx */ None )
315+ miri:: eval_entry (
316+ tcx,
317+ entry_def_id,
318+ entry_type,
319+ & args,
320+ & config,
321+ /* genmc_ctx */ None ,
322+ )
259323 } )
260324 } else {
261- miri:: eval_entry ( tcx, entry_def_id, entry_type, & config, None )
325+ miri:: eval_entry ( tcx, entry_def_id, entry_type, & args , & config, None )
262326 } ;
263327 // Process interpreter result.
264328 if let Err ( return_code) = res {
@@ -486,6 +550,7 @@ fn main() {
486550
487551 let mut rustc_args = vec ! [ ] ;
488552 let mut after_dashdash = false ;
553+ let mut guest_args = vec ! [ ] ;
489554
490555 // Note that we require values to be given with `=`, not with a space.
491556 // This matches how rustc parses `-Z`.
@@ -498,7 +563,7 @@ fn main() {
498563 rustc_args. extend ( miri:: MIRI_DEFAULT_ARGS . iter ( ) . map ( ToString :: to_string) ) ;
499564 } else if after_dashdash {
500565 // Everything that comes after `--` is forwarded to the interpreted crate.
501- miri_config . args . push ( arg) ;
566+ guest_args . push ( arg) ;
502567 } else if arg == "--" {
503568 after_dashdash = true ;
504569 } else if arg == "-Zmiri-disable-validation" {
@@ -745,7 +810,6 @@ fn main() {
745810 many_seeds. map ( |seeds| ManySeedsConfig { seeds, keep_going : many_seeds_keep_going } ) ;
746811
747812 debug ! ( "rustc arguments: {:?}" , rustc_args) ;
748- debug ! ( "crate arguments: {:?}" , miri_config. args) ;
749813 if !miri_config. native_lib . is_empty ( ) && miri_config. native_lib_enable_tracing {
750814 // SAFETY: No other threads are running
751815 #[ cfg( all( unix, feature = "native-lib" ) ) ]
@@ -756,5 +820,9 @@ fn main() {
756820 ) ;
757821 }
758822 }
823+ rustc_args. push ( "-Zjit-mode" . to_owned ( ) ) ;
824+ rustc_args. push ( "--" . to_owned ( ) ) ;
825+ rustc_args. extend ( guest_args) ;
826+
759827 run_compiler_and_exit ( & rustc_args, & mut MiriCompilerCalls :: new ( miri_config, many_seeds) )
760828}
0 commit comments