@@ -1239,10 +1239,19 @@ fn start_executing_work<B: ExtraBackendMethods>(
1239
1239
let mut needs_thin_lto = Vec :: new ( ) ;
1240
1240
let mut lto_import_only_modules = Vec :: new ( ) ;
1241
1241
let mut started_lto = false ;
1242
- let mut codegen_aborted = false ;
1243
1242
1244
- // This flag tracks whether all items have gone through codegens
1245
- let mut codegen_done = false ;
1243
+ /// Possible state transitions:
1244
+ /// - Ongoing -> Completed
1245
+ /// - Ongoing -> Aborted
1246
+ /// - Completed -> Aborted
1247
+ #[ derive( Debug , PartialEq ) ]
1248
+ enum CodegenState {
1249
+ Ongoing ,
1250
+ Completed ,
1251
+ Aborted ,
1252
+ }
1253
+ use CodegenState :: * ;
1254
+ let mut codegen_state = Ongoing ;
1246
1255
1247
1256
// This is the queue of LLVM work items that still need processing.
1248
1257
let mut work_items = Vec :: < ( WorkItem < B > , u64 ) > :: new ( ) ;
@@ -1262,10 +1271,10 @@ fn start_executing_work<B: ExtraBackendMethods>(
1262
1271
// wait for all existing work to finish, so many of the conditions here
1263
1272
// only apply if codegen hasn't been aborted as they represent pending
1264
1273
// work to be done.
1265
- while !codegen_done
1274
+ while codegen_state == Ongoing
1266
1275
|| running > 0
1267
1276
|| main_thread_worker_state == MainThreadWorkerState :: LLVMing
1268
- || ( !codegen_aborted
1277
+ || ( codegen_state == Completed
1269
1278
&& !( work_items. is_empty ( )
1270
1279
&& needs_fat_lto. is_empty ( )
1271
1280
&& needs_thin_lto. is_empty ( )
@@ -1275,7 +1284,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
1275
1284
// While there are still CGUs to be codegened, the coordinator has
1276
1285
// to decide how to utilize the compiler processes implicit Token:
1277
1286
// For codegenning more CGU or for running them through LLVM.
1278
- if !codegen_done {
1287
+ if codegen_state == Ongoing {
1279
1288
if main_thread_worker_state == MainThreadWorkerState :: Idle {
1280
1289
// Compute the number of workers that will be running once we've taken as many
1281
1290
// items from the work queue as we can, plus one for the main thread. It's not
@@ -1312,10 +1321,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
1312
1321
spawn_work ( cgcx, item) ;
1313
1322
}
1314
1323
}
1315
- } else if codegen_aborted {
1316
- // don't queue up any more work if codegen was aborted, we're
1317
- // just waiting for our existing children to finish
1318
- } else {
1324
+ } else if codegen_state == Completed {
1319
1325
// If we've finished everything related to normal codegen
1320
1326
// then it must be the case that we've got some LTO work to do.
1321
1327
// Perform the serial work here of figuring out what we're
@@ -1382,11 +1388,15 @@ fn start_executing_work<B: ExtraBackendMethods>(
1382
1388
// Already making good use of that token
1383
1389
}
1384
1390
}
1391
+ } else {
1392
+ // Don't queue up any more work if codegen was aborted, we're
1393
+ // just waiting for our existing children to finish.
1394
+ assert ! ( codegen_state == Aborted ) ;
1385
1395
}
1386
1396
1387
1397
// Spin up what work we can, only doing this while we've got available
1388
1398
// parallelism slots and work left to spawn.
1389
- while !codegen_aborted && !work_items. is_empty ( ) && running < tokens. len ( ) {
1399
+ while codegen_state != Aborted && !work_items. is_empty ( ) && running < tokens. len ( ) {
1390
1400
let ( item, _) = work_items. pop ( ) . unwrap ( ) ;
1391
1401
1392
1402
maybe_start_llvm_timer ( prof, cgcx. config ( item. module_kind ( ) ) , & mut llvm_start_time) ;
@@ -1438,8 +1448,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
1438
1448
Err ( e) => {
1439
1449
let msg = & format ! ( "failed to acquire jobserver token: {}" , e) ;
1440
1450
shared_emitter. fatal ( msg) ;
1441
- codegen_done = true ;
1442
- codegen_aborted = true ;
1451
+ codegen_state = Aborted ;
1443
1452
}
1444
1453
}
1445
1454
}
@@ -1467,7 +1476,9 @@ fn start_executing_work<B: ExtraBackendMethods>(
1467
1476
}
1468
1477
1469
1478
Message :: CodegenComplete => {
1470
- codegen_done = true ;
1479
+ if codegen_state != Aborted {
1480
+ codegen_state = Completed ;
1481
+ }
1471
1482
assert_eq ! ( main_thread_worker_state, MainThreadWorkerState :: Codegenning ) ;
1472
1483
main_thread_worker_state = MainThreadWorkerState :: Idle ;
1473
1484
}
@@ -1479,8 +1490,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
1479
1490
// then conditions above will ensure no more work is spawned but
1480
1491
// we'll keep executing this loop until `running` hits 0.
1481
1492
Message :: CodegenAborted => {
1482
- codegen_done = true ;
1483
- codegen_aborted = true ;
1493
+ codegen_state = Aborted ;
1484
1494
}
1485
1495
1486
1496
Message :: WorkItem { result, worker_id } => {
@@ -1512,8 +1522,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
1512
1522
}
1513
1523
Err ( Some ( WorkerFatalError ) ) => {
1514
1524
// Like `CodegenAborted`, wait for remaining work to finish.
1515
- codegen_done = true ;
1516
- codegen_aborted = true ;
1525
+ codegen_state = Aborted ;
1517
1526
}
1518
1527
Err ( None ) => {
1519
1528
// If the thread failed that means it panicked, so
@@ -1525,15 +1534,15 @@ fn start_executing_work<B: ExtraBackendMethods>(
1525
1534
1526
1535
Message :: AddImportOnlyModule { module_data, work_product } => {
1527
1536
assert ! ( !started_lto) ;
1528
- assert ! ( !codegen_done ) ;
1537
+ assert_eq ! ( codegen_state , Ongoing ) ;
1529
1538
assert_eq ! ( main_thread_worker_state, MainThreadWorkerState :: Codegenning ) ;
1530
1539
lto_import_only_modules. push ( ( module_data, work_product) ) ;
1531
1540
main_thread_worker_state = MainThreadWorkerState :: Idle ;
1532
1541
}
1533
1542
}
1534
1543
}
1535
1544
1536
- if codegen_aborted {
1545
+ if codegen_state == Aborted {
1537
1546
return Err ( ( ) ) ;
1538
1547
}
1539
1548
0 commit comments