@@ -1508,6 +1508,7 @@ enum Message {
1508
1508
} ,
1509
1509
CodegenComplete ,
1510
1510
CodegenItem ,
1511
+ CodegenAborted ,
1511
1512
}
1512
1513
1513
1514
struct Diagnostic {
@@ -1788,6 +1789,7 @@ fn start_executing_work(tcx: TyCtxt,
1788
1789
let mut needs_lto = Vec :: new ( ) ;
1789
1790
let mut lto_import_only_modules = Vec :: new ( ) ;
1790
1791
let mut started_lto = false ;
1792
+ let mut codegen_aborted = false ;
1791
1793
1792
1794
// This flag tracks whether all items have gone through codegens
1793
1795
let mut codegen_done = false ;
@@ -1805,13 +1807,19 @@ fn start_executing_work(tcx: TyCtxt,
1805
1807
let mut llvm_start_time = None ;
1806
1808
1807
1809
// 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.
1809
1814
while !codegen_done ||
1810
- work_items. len ( ) > 0 ||
1811
1815
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
+ {
1815
1823
1816
1824
// While there are still CGUs to be codegened, the coordinator has
1817
1825
// to decide how to utilize the compiler processes implicit Token:
@@ -1840,6 +1848,9 @@ fn start_executing_work(tcx: TyCtxt,
1840
1848
spawn_work ( cgcx, item) ;
1841
1849
}
1842
1850
}
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
1843
1854
} else {
1844
1855
// If we've finished everything related to normal codegen
1845
1856
// 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,
1904
1915
1905
1916
// Spin up what work we can, only doing this while we've got available
1906
1917
// 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 ( ) {
1908
1919
let ( item, _) = work_items. pop ( ) . unwrap ( ) ;
1909
1920
1910
1921
maybe_start_llvm_timer ( cgcx. config ( item. module_kind ( ) ) ,
@@ -1969,18 +1980,34 @@ fn start_executing_work(tcx: TyCtxt,
1969
1980
if !cgcx. opts . debugging_opts . no_parallel_llvm {
1970
1981
helper. request_token ( ) ;
1971
1982
}
1983
+ assert ! ( !codegen_aborted) ;
1972
1984
assert_eq ! ( main_thread_worker_state,
1973
1985
MainThreadWorkerState :: Codegenning ) ;
1974
1986
main_thread_worker_state = MainThreadWorkerState :: Idle ;
1975
1987
}
1976
1988
1977
1989
Message :: CodegenComplete => {
1978
1990
codegen_done = true ;
1991
+ assert ! ( !codegen_aborted) ;
1979
1992
assert_eq ! ( main_thread_worker_state,
1980
1993
MainThreadWorkerState :: Codegenning ) ;
1981
1994
main_thread_worker_state = MainThreadWorkerState :: Idle ;
1982
1995
}
1983
1996
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
+
1984
2011
// If a thread exits successfully then we drop a token associated
1985
2012
// with that worker and update our `running` count. We may later
1986
2013
// re-acquire a token to continue running more work. We may also not
@@ -2446,6 +2473,19 @@ impl OngoingCodegen {
2446
2473
drop ( self . coordinator_send . send ( Box :: new ( Message :: CodegenComplete ) ) ) ;
2447
2474
}
2448
2475
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
+
2449
2489
pub fn check_for_errors ( & self , sess : & Session ) {
2450
2490
self . shared_emitter_main . check ( sess, false ) ;
2451
2491
}
@@ -2464,6 +2504,11 @@ impl OngoingCodegen {
2464
2504
}
2465
2505
}
2466
2506
2507
+ // impl Drop for OngoingCodegen {
2508
+ // fn drop(&mut self) {
2509
+ // }
2510
+ // }
2511
+
2467
2512
pub ( crate ) fn submit_codegened_module_to_llvm ( tcx : TyCtxt ,
2468
2513
module : ModuleCodegen ,
2469
2514
cost : u64 ) {
0 commit comments