@@ -1508,6 +1508,7 @@ enum Message {
15081508 } ,
15091509 CodegenComplete ,
15101510 CodegenItem ,
1511+ CodegenAborted ,
15111512}
15121513
15131514struct Diagnostic {
@@ -1788,6 +1789,7 @@ fn start_executing_work(tcx: TyCtxt,
17881789 let mut needs_lto = Vec :: new ( ) ;
17891790 let mut lto_import_only_modules = Vec :: new ( ) ;
17901791 let mut started_lto = false ;
1792+ let mut codegen_aborted = false ;
17911793
17921794 // This flag tracks whether all items have gone through codegens
17931795 let mut codegen_done = false ;
@@ -1805,13 +1807,19 @@ fn start_executing_work(tcx: TyCtxt,
18051807 let mut llvm_start_time = None ;
18061808
18071809 // Run the message loop while there's still anything that needs message
1808- // processing:
1810+ // processing. Note that as soon as codegen is aborted we simply want to
1811+ // wait for all existing work to finish, so many of the conditions here
1812+ // only apply if codegen hasn't been aborted as they represent pending
1813+ // work to be done.
18091814 while !codegen_done ||
1810- work_items. len ( ) > 0 ||
18111815 running > 0 ||
1812- needs_lto. len ( ) > 0 ||
1813- lto_import_only_modules. len ( ) > 0 ||
1814- main_thread_worker_state != MainThreadWorkerState :: Idle {
1816+ ( !codegen_aborted && (
1817+ work_items. len ( ) > 0 ||
1818+ needs_lto. len ( ) > 0 ||
1819+ lto_import_only_modules. len ( ) > 0 ||
1820+ main_thread_worker_state != MainThreadWorkerState :: Idle
1821+ ) )
1822+ {
18151823
18161824 // While there are still CGUs to be codegened, the coordinator has
18171825 // to decide how to utilize the compiler processes implicit Token:
@@ -1840,6 +1848,9 @@ fn start_executing_work(tcx: TyCtxt,
18401848 spawn_work ( cgcx, item) ;
18411849 }
18421850 }
1851+ } else if codegen_aborted {
1852+ // don't queue up any more work if codegen was aborted, we're
1853+ // just waiting for our existing children to finish
18431854 } else {
18441855 // If we've finished everything related to normal codegen
18451856 // then it must be the case that we've got some LTO work to do.
@@ -1904,7 +1915,7 @@ fn start_executing_work(tcx: TyCtxt,
19041915
19051916 // Spin up what work we can, only doing this while we've got available
19061917 // parallelism slots and work left to spawn.
1907- while work_items. len ( ) > 0 && running < tokens. len ( ) {
1918+ while !codegen_aborted && work_items. len ( ) > 0 && running < tokens. len ( ) {
19081919 let ( item, _) = work_items. pop ( ) . unwrap ( ) ;
19091920
19101921 maybe_start_llvm_timer ( cgcx. config ( item. module_kind ( ) ) ,
@@ -1969,18 +1980,34 @@ fn start_executing_work(tcx: TyCtxt,
19691980 if !cgcx. opts . debugging_opts . no_parallel_llvm {
19701981 helper. request_token ( ) ;
19711982 }
1983+ assert ! ( !codegen_aborted) ;
19721984 assert_eq ! ( main_thread_worker_state,
19731985 MainThreadWorkerState :: Codegenning ) ;
19741986 main_thread_worker_state = MainThreadWorkerState :: Idle ;
19751987 }
19761988
19771989 Message :: CodegenComplete => {
19781990 codegen_done = true ;
1991+ assert ! ( !codegen_aborted) ;
19791992 assert_eq ! ( main_thread_worker_state,
19801993 MainThreadWorkerState :: Codegenning ) ;
19811994 main_thread_worker_state = MainThreadWorkerState :: Idle ;
19821995 }
19831996
1997+ // If codegen is aborted that means translation was aborted due
1998+ // to some normal-ish compiler error. In this situation we want
1999+ // to exit as soon as possible, but we want to make sure all
2000+ // existing work has finished. Flag codegen as being done, and
2001+ // then conditions above will ensure no more work is spawned but
2002+ // we'll keep executing this loop until `running` hits 0.
2003+ Message :: CodegenAborted => {
2004+ assert ! ( !codegen_aborted) ;
2005+ codegen_done = true ;
2006+ codegen_aborted = true ;
2007+ assert_eq ! ( main_thread_worker_state,
2008+ MainThreadWorkerState :: Codegenning ) ;
2009+ }
2010+
19842011 // If a thread exits successfully then we drop a token associated
19852012 // with that worker and update our `running` count. We may later
19862013 // re-acquire a token to continue running more work. We may also not
@@ -2446,6 +2473,19 @@ impl OngoingCodegen {
24462473 drop ( self . coordinator_send . send ( Box :: new ( Message :: CodegenComplete ) ) ) ;
24472474 }
24482475
2476+ /// Consume this context indicating that codegen was entirely aborted, and
2477+ /// we need to exit as quickly as possible.
2478+ ///
2479+ /// This method blocks the current thread until all worker threads have
2480+ /// finished, and all worker threads should have exited or be real close to
2481+ /// exiting at this point.
2482+ pub fn codegen_aborted ( self ) {
2483+ // Signal to the coordinator it should spawn no more work and start
2484+ // shutdown.
2485+ drop ( self . coordinator_send . send ( Box :: new ( Message :: CodegenAborted ) ) ) ;
2486+ drop ( self . future . join ( ) ) ;
2487+ }
2488+
24492489 pub fn check_for_errors ( & self , sess : & Session ) {
24502490 self . shared_emitter_main . check ( sess, false ) ;
24512491 }
@@ -2464,6 +2504,11 @@ impl OngoingCodegen {
24642504 }
24652505}
24662506
2507+ // impl Drop for OngoingCodegen {
2508+ // fn drop(&mut self) {
2509+ // }
2510+ // }
2511+
24672512pub ( crate ) fn submit_codegened_module_to_llvm ( tcx : TyCtxt ,
24682513 module : ModuleCodegen ,
24692514 cost : u64 ) {
0 commit comments