@@ -221,7 +221,7 @@ enum TlsDtorsStatePriv<'tcx> {
221221 PthreadDtors ( RunningDtorState ) ,
222222 /// For Windows Dtors, we store the list of functions that we still have to call.
223223 /// These are functions from the magic `.CRT$XLB` linker section.
224- WindowsDtors ( Vec < ImmTy < ' tcx > > ) ,
224+ WindowsDtors ( RunningDtorState , Vec < ImmTy < ' tcx > > ) ,
225225 Done ,
226226}
227227
@@ -249,7 +249,7 @@ impl<'tcx> TlsDtorsState<'tcx> {
249249 // Determine which destructors to run.
250250 let dtors = this. lookup_windows_tls_dtors ( ) ?;
251251 // And move to the next state, that runs them.
252- break ' new_state WindowsDtors ( dtors) ;
252+ break ' new_state WindowsDtors ( Default :: default ( ) , dtors) ;
253253 }
254254 _ => {
255255 // No TLS dtor support.
@@ -271,7 +271,13 @@ impl<'tcx> TlsDtorsState<'tcx> {
271271 Poll :: Ready ( ( ) ) => break ' new_state Done ,
272272 }
273273 }
274- WindowsDtors ( dtors) => {
274+ WindowsDtors ( state, dtors) => {
275+ // Fls destructors are scheduled before the tls callback, similar to pthread dtors.
276+ match this. schedule_next_windows_fls_dtor ( state) ? {
277+ Poll :: Pending => return interp_ok ( Poll :: Pending ) , // just keep going
278+ Poll :: Ready ( ( ) ) => { }
279+ }
280+
275281 if let Some ( dtor) = dtors. pop ( ) {
276282 this. schedule_windows_tls_dtor ( dtor) ?;
277283 return interp_ok ( Poll :: Pending ) ; // we stay in this state (but `dtors` got shorter)
@@ -359,6 +365,16 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
359365 fn schedule_next_pthread_tls_dtor (
360366 & mut self ,
361367 state : & mut RunningDtorState ,
368+ ) -> InterpResult < ' tcx , Poll < ( ) > > {
369+ self . schedule_next_tls_dtor_callback ( state, ExternAbi :: C { unwind : false } )
370+ }
371+
372+ /// Schedule a TLS destructor. Returns `true` if found
373+ /// a destructor to schedule, and `false` otherwise.
374+ fn schedule_next_tls_dtor_callback (
375+ & mut self ,
376+ state : & mut RunningDtorState ,
377+ caller_abi : ExternAbi ,
362378 ) -> InterpResult < ' tcx , Poll < ( ) > > {
363379 let this = self . eval_context_mut ( ) ;
364380 let active_thread = this. active_thread ( ) ;
@@ -379,7 +395,7 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
379395
380396 this. call_function (
381397 instance,
382- ExternAbi :: C { unwind : false } ,
398+ caller_abi ,
383399 & [ ImmTy :: from_scalar ( ptr, this. machine . layouts . mut_raw_ptr ) ] ,
384400 None ,
385401 ReturnContinuation :: Stop { cleanup : true } ,
@@ -390,4 +406,13 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
390406
391407 interp_ok ( Poll :: Ready ( ( ) ) )
392408 }
409+
410+ /// Schedule a Windows FLS destructor. Returns `true` if found
411+ /// a destructor to schedule, and `false` otherwise.
412+ fn schedule_next_windows_fls_dtor (
413+ & mut self ,
414+ state : & mut RunningDtorState ,
415+ ) -> InterpResult < ' tcx , Poll < ( ) > > {
416+ self . schedule_next_tls_dtor_callback ( state, ExternAbi :: System { unwind : false } )
417+ }
393418}
0 commit comments