@@ -11,7 +11,7 @@ use syntax::source_map::DUMMY_SP;
1111use crate :: {
1212 EnvVars , Evaluator , FnVal , HelpersEvalContextExt , InterpCx , InterpError ,
1313 InterpResult , MemoryExtra , MiriMemoryKind , Pointer , Scalar , StackPopCleanup , Tag ,
14- TlsEvalContextExt ,
14+ TlsEvalContextExt , MPlaceTy
1515} ;
1616
1717/// Configuration needed to spawn a Miri instance.
@@ -29,12 +29,15 @@ pub struct MiriConfig {
2929 pub seed : Option < u64 > ,
3030}
3131
32- // Used by priroda.
32+ /// Returns a freshly created `InterpCx`, along with an `MPlaceTy` representing
33+ /// the location where the return value of the `start` lang item will be
34+ /// written to.
35+ /// Public because this is also used by `priroda`.
3336pub fn create_ecx < ' mir , ' tcx : ' mir > (
3437 tcx : TyCtxt < ' tcx > ,
3538 main_id : DefId ,
3639 config : MiriConfig ,
37- ) -> InterpResult < ' tcx , InterpCx < ' mir , ' tcx , Evaluator < ' tcx > > > {
40+ ) -> InterpResult < ' tcx , ( InterpCx < ' mir , ' tcx , Evaluator < ' tcx > > , MPlaceTy < ' tcx , Tag > ) > {
3841 let mut ecx = InterpCx :: new (
3942 tcx. at ( syntax:: source_map:: DUMMY_SP ) ,
4043 ty:: ParamEnv :: reveal_all ( ) ,
@@ -170,40 +173,51 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
170173 ecx. write_scalar ( Scalar :: from_u32 ( 0 ) , errno_place. into ( ) ) ?;
171174 ecx. machine . last_error = Some ( errno_place) ;
172175
173- Ok ( ecx)
176+ Ok ( ( ecx, ret_ptr ) )
174177}
175178
176- pub fn eval_main < ' tcx > ( tcx : TyCtxt < ' tcx > , main_id : DefId , config : MiriConfig ) {
177- let mut ecx = match create_ecx ( tcx, main_id, config) {
178- Ok ( ecx) => ecx,
179+ /// Evaluates the main function specified by `main_id`.
180+ /// Returns `Some(return_code)` if program executed completed.
181+ /// Returns `None` if an evaluation error occured.
182+ pub fn eval_main < ' tcx > ( tcx : TyCtxt < ' tcx > , main_id : DefId , config : MiriConfig ) -> Option < i64 > {
183+ let ( mut ecx, ret_ptr) = match create_ecx ( tcx, main_id, config) {
184+ Ok ( v) => v,
179185 Err ( mut err) => {
180186 err. print_backtrace ( ) ;
181187 panic ! ( "Miri initialziation error: {}" , err. kind)
182188 }
183189 } ;
184190
185191 // Perform the main execution.
186- let res: InterpResult < ' _ > = ( || {
192+ let res: InterpResult < ' _ , i64 > = ( || {
187193 ecx. run ( ) ?;
188- ecx. run_tls_dtors ( )
194+ // Read the return code pointer *before* we run TLS destructors, to assert
195+ // that it was written to by the time that `start` lang item returned.
196+ let return_code = ecx. read_scalar ( ret_ptr. into ( ) ) ?. not_undef ( ) ?. to_machine_isize ( & ecx) ?;
197+ ecx. run_tls_dtors ( ) ?;
198+ Ok ( return_code)
189199 } ) ( ) ;
190200
191201 // Process the result.
192202 match res {
193- Ok ( ( ) ) => {
203+ Ok ( return_code ) => {
194204 let leaks = ecx. memory . leak_report ( ) ;
195205 // Disable the leak test on some platforms where we do not
196206 // correctly implement TLS destructors.
197207 let target_os = ecx. tcx . tcx . sess . target . target . target_os . to_lowercase ( ) ;
198208 let ignore_leaks = target_os == "windows" || target_os == "macos" ;
199209 if !ignore_leaks && leaks != 0 {
200210 tcx. sess . err ( "the evaluated program leaked memory" ) ;
211+ // Ignore the provided return code - let the reported error
212+ // determine the return code.
213+ return None ;
201214 }
215+ return Some ( return_code)
202216 }
203217 Err ( mut e) => {
204218 // Special treatment for some error kinds
205219 let msg = match e. kind {
206- InterpError :: Exit ( code) => std :: process :: exit ( code) ,
220+ InterpError :: Exit ( code) => return Some ( code. into ( ) ) ,
207221 err_unsup ! ( NoMirFor ( ..) ) =>
208222 format ! ( "{}. Did you set `MIRI_SYSROOT` to a Miri-enabled sysroot? You can prepare one with `cargo miri setup`." , e) ,
209223 _ => e. to_string ( )
@@ -246,6 +260,8 @@ pub fn eval_main<'tcx>(tcx: TyCtxt<'tcx>, main_id: DefId, config: MiriConfig) {
246260 trace ! ( " local {}: {:?}" , i, local. value) ;
247261 }
248262 }
263+ // Let the reported error determine the return code.
264+ return None ;
249265 }
250266 }
251267}
0 commit comments