@@ -177,17 +177,6 @@ void coro::suppressCoroAllocs(LLVMContext &Context,
177
177
}
178
178
}
179
179
180
- static void clear (coro::Shape &Shape) {
181
- Shape.CoroBegin = nullptr ;
182
- Shape.CoroEnds .clear ();
183
- Shape.CoroSizes .clear ();
184
- Shape.CoroSuspends .clear ();
185
-
186
- Shape.FrameTy = nullptr ;
187
- Shape.FramePtr = nullptr ;
188
- Shape.AllocaSpillBlock = nullptr ;
189
- }
190
-
191
180
static CoroSaveInst *createCoroSave (CoroBeginInst *CoroBegin,
192
181
CoroSuspendInst *SuspendInst) {
193
182
Module *M = SuspendInst->getModule ();
@@ -200,13 +189,14 @@ static CoroSaveInst *createCoroSave(CoroBeginInst *CoroBegin,
200
189
}
201
190
202
191
// Collect "interesting" coroutine intrinsics.
203
- void coro::Shape::buildFrom (Function &F) {
192
+ void coro::Shape::analyze (Function &F,
193
+ SmallVectorImpl<CoroFrameInst *> &CoroFrames,
194
+ SmallVectorImpl<CoroSaveInst *> &UnusedCoroSaves) {
195
+ clear ();
196
+
204
197
bool HasFinalSuspend = false ;
205
198
bool HasUnwindCoroEnd = false ;
206
199
size_t FinalSuspendIndex = 0 ;
207
- clear (*this );
208
- SmallVector<CoroFrameInst *, 8 > CoroFrames;
209
- SmallVector<CoroSaveInst *, 2 > UnusedCoroSaves;
210
200
211
201
for (Instruction &I : instructions (F)) {
212
202
// FIXME: coro_await_suspend_* are not proper `IntrinisicInst`s
@@ -298,15 +288,73 @@ void coro::Shape::buildFrom(Function &F) {
298
288
}
299
289
}
300
290
301
- // If for some reason, we were not able to find coro.begin, bailout.
302
- if (!CoroBegin) {
291
+ // If there is no CoroBegin then this is not a coroutine.
292
+ if (!CoroBegin)
293
+ return ;
294
+
295
+ // Determination of ABI and initializing lowering info
296
+ auto Id = CoroBegin->getId ();
297
+ switch (auto IntrID = Id->getIntrinsicID ()) {
298
+ case Intrinsic::coro_id: {
299
+ ABI = coro::ABI::Switch;
300
+ SwitchLowering.HasFinalSuspend = HasFinalSuspend;
301
+ SwitchLowering.HasUnwindCoroEnd = HasUnwindCoroEnd;
302
+
303
+ auto SwitchId = getSwitchCoroId ();
304
+ SwitchLowering.ResumeSwitch = nullptr ;
305
+ SwitchLowering.PromiseAlloca = SwitchId->getPromise ();
306
+ SwitchLowering.ResumeEntryBlock = nullptr ;
307
+
308
+ // Move final suspend to the last element in the CoroSuspends vector.
309
+ if (SwitchLowering.HasFinalSuspend &&
310
+ FinalSuspendIndex != CoroSuspends.size () - 1 )
311
+ std::swap (CoroSuspends[FinalSuspendIndex], CoroSuspends.back ());
312
+ break ;
313
+ }
314
+ case Intrinsic::coro_id_async: {
315
+ ABI = coro::ABI::Async;
316
+ auto *AsyncId = getAsyncCoroId ();
317
+ AsyncId->checkWellFormed ();
318
+ AsyncLowering.Context = AsyncId->getStorage ();
319
+ AsyncLowering.ContextArgNo = AsyncId->getStorageArgumentIndex ();
320
+ AsyncLowering.ContextHeaderSize = AsyncId->getStorageSize ();
321
+ AsyncLowering.ContextAlignment = AsyncId->getStorageAlignment ().value ();
322
+ AsyncLowering.AsyncFuncPointer = AsyncId->getAsyncFunctionPointer ();
323
+ AsyncLowering.AsyncCC = F.getCallingConv ();
324
+ break ;
325
+ }
326
+ case Intrinsic::coro_id_retcon:
327
+ case Intrinsic::coro_id_retcon_once: {
328
+ ABI = IntrID == Intrinsic::coro_id_retcon ? coro::ABI::Retcon
329
+ : coro::ABI::RetconOnce;
330
+ auto ContinuationId = getRetconCoroId ();
331
+ ContinuationId->checkWellFormed ();
332
+ auto Prototype = ContinuationId->getPrototype ();
333
+ RetconLowering.ResumePrototype = Prototype;
334
+ RetconLowering.Alloc = ContinuationId->getAllocFunction ();
335
+ RetconLowering.Dealloc = ContinuationId->getDeallocFunction ();
336
+ RetconLowering.ReturnBlock = nullptr ;
337
+ RetconLowering.IsFrameInlineInStorage = false ;
338
+ break ;
339
+ }
340
+ default :
341
+ llvm_unreachable (" coro.begin is not dependent on a coro.id call" );
342
+ }
343
+ }
344
+
345
+ // If for some reason, we were not able to find coro.begin, bailout.
346
+ void coro::Shape::invalidateCoroutine (
347
+ Function &F, SmallVectorImpl<CoroFrameInst *> &CoroFrames) {
348
+ assert (!CoroBegin);
349
+ {
303
350
// Replace coro.frame which are supposed to be lowered to the result of
304
351
// coro.begin with undef.
305
352
auto *Undef = UndefValue::get (PointerType::get (F.getContext (), 0 ));
306
353
for (CoroFrameInst *CF : CoroFrames) {
307
354
CF->replaceAllUsesWith (Undef);
308
355
CF->eraseFromParent ();
309
356
}
357
+ CoroFrames.clear ();
310
358
311
359
// Replace all coro.suspend with undef and remove related coro.saves if
312
360
// present.
@@ -316,25 +364,18 @@ void coro::Shape::buildFrom(Function &F) {
316
364
if (auto *CoroSave = CS->getCoroSave ())
317
365
CoroSave->eraseFromParent ();
318
366
}
367
+ CoroSuspends.clear ();
319
368
320
369
// Replace all coro.ends with unreachable instruction.
321
370
for (AnyCoroEndInst *CE : CoroEnds)
322
371
changeToUnreachable (CE);
323
-
324
- return ;
325
372
}
373
+ }
326
374
327
- auto Id = CoroBegin->getId ();
328
- switch (auto IdIntrinsic = Id->getIntrinsicID ()) {
329
- case Intrinsic::coro_id: {
330
- auto SwitchId = cast<CoroIdInst>(Id);
331
- this ->ABI = coro::ABI::Switch;
332
- this ->SwitchLowering .HasFinalSuspend = HasFinalSuspend;
333
- this ->SwitchLowering .HasUnwindCoroEnd = HasUnwindCoroEnd;
334
- this ->SwitchLowering .ResumeSwitch = nullptr ;
335
- this ->SwitchLowering .PromiseAlloca = SwitchId->getPromise ();
336
- this ->SwitchLowering .ResumeEntryBlock = nullptr ;
337
-
375
+ // Perform semantic checking and initialization of the ABI
376
+ void coro::Shape::initABI () {
377
+ switch (ABI) {
378
+ case coro::ABI::Switch: {
338
379
for (auto *AnySuspend : CoroSuspends) {
339
380
auto Suspend = dyn_cast<CoroSuspendInst>(AnySuspend);
340
381
if (!Suspend) {
@@ -349,33 +390,11 @@ void coro::Shape::buildFrom(Function &F) {
349
390
}
350
391
break ;
351
392
}
352
- case Intrinsic::coro_id_async: {
353
- auto *AsyncId = cast<CoroIdAsyncInst>(Id);
354
- AsyncId->checkWellFormed ();
355
- this ->ABI = coro::ABI::Async;
356
- this ->AsyncLowering .Context = AsyncId->getStorage ();
357
- this ->AsyncLowering .ContextArgNo = AsyncId->getStorageArgumentIndex ();
358
- this ->AsyncLowering .ContextHeaderSize = AsyncId->getStorageSize ();
359
- this ->AsyncLowering .ContextAlignment =
360
- AsyncId->getStorageAlignment ().value ();
361
- this ->AsyncLowering .AsyncFuncPointer = AsyncId->getAsyncFunctionPointer ();
362
- this ->AsyncLowering .AsyncCC = F.getCallingConv ();
393
+ case coro::ABI::Async: {
363
394
break ;
364
395
};
365
- case Intrinsic::coro_id_retcon:
366
- case Intrinsic::coro_id_retcon_once: {
367
- auto ContinuationId = cast<AnyCoroIdRetconInst>(Id);
368
- ContinuationId->checkWellFormed ();
369
- this ->ABI = (IdIntrinsic == Intrinsic::coro_id_retcon
370
- ? coro::ABI::Retcon
371
- : coro::ABI::RetconOnce);
372
- auto Prototype = ContinuationId->getPrototype ();
373
- this ->RetconLowering .ResumePrototype = Prototype;
374
- this ->RetconLowering .Alloc = ContinuationId->getAllocFunction ();
375
- this ->RetconLowering .Dealloc = ContinuationId->getDeallocFunction ();
376
- this ->RetconLowering .ReturnBlock = nullptr ;
377
- this ->RetconLowering .IsFrameInlineInStorage = false ;
378
-
396
+ case coro::ABI::Retcon:
397
+ case coro::ABI::RetconOnce: {
379
398
// Determine the result value types, and make sure they match up with
380
399
// the values passed to the suspends.
381
400
auto ResultTys = getRetconResultTypes ();
@@ -408,7 +427,7 @@ void coro::Shape::buildFrom(Function &F) {
408
427
409
428
#ifndef NDEBUG
410
429
Suspend->dump ();
411
- Prototype ->getFunctionType ()->dump ();
430
+ RetconLowering. ResumePrototype ->getFunctionType ()->dump ();
412
431
#endif
413
432
report_fatal_error (" argument to coro.suspend.retcon does not "
414
433
" match corresponding prototype function result" );
@@ -417,14 +436,14 @@ void coro::Shape::buildFrom(Function &F) {
417
436
if (SI != SE || RI != RE) {
418
437
#ifndef NDEBUG
419
438
Suspend->dump ();
420
- Prototype ->getFunctionType ()->dump ();
439
+ RetconLowering. ResumePrototype ->getFunctionType ()->dump ();
421
440
#endif
422
441
report_fatal_error (" wrong number of arguments to coro.suspend.retcon" );
423
442
}
424
443
425
444
// Check that the result type of the suspend matches the resume types.
426
445
Type *SResultTy = Suspend->getType ();
427
- ArrayRef<Type*> SuspendResultTys;
446
+ ArrayRef<Type *> SuspendResultTys;
428
447
if (SResultTy->isVoidTy ()) {
429
448
// leave as empty array
430
449
} else if (auto SResultStructTy = dyn_cast<StructType>(SResultTy)) {
@@ -436,15 +455,15 @@ void coro::Shape::buildFrom(Function &F) {
436
455
if (SuspendResultTys.size () != ResumeTys.size ()) {
437
456
#ifndef NDEBUG
438
457
Suspend->dump ();
439
- Prototype ->getFunctionType ()->dump ();
458
+ RetconLowering. ResumePrototype ->getFunctionType ()->dump ();
440
459
#endif
441
460
report_fatal_error (" wrong number of results from coro.suspend.retcon" );
442
461
}
443
462
for (size_t I = 0 , E = ResumeTys.size (); I != E; ++I) {
444
463
if (SuspendResultTys[I] != ResumeTys[I]) {
445
464
#ifndef NDEBUG
446
465
Suspend->dump ();
447
- Prototype ->getFunctionType ()->dump ();
466
+ RetconLowering. ResumePrototype ->getFunctionType ()->dump ();
448
467
#endif
449
468
report_fatal_error (" result from coro.suspend.retcon does not "
450
469
" match corresponding prototype function param" );
@@ -453,26 +472,25 @@ void coro::Shape::buildFrom(Function &F) {
453
472
}
454
473
break ;
455
474
}
456
-
457
475
default :
458
476
llvm_unreachable (" coro.begin is not dependent on a coro.id call" );
459
477
}
478
+ }
460
479
461
- // The coro.free intrinsic is always lowered to the result of coro.begin.
480
+ void coro::Shape::cleanCoroutine (
481
+ SmallVectorImpl<CoroFrameInst *> &CoroFrames,
482
+ SmallVectorImpl<CoroSaveInst *> &UnusedCoroSaves) {
483
+ // The coro.frame intrinsic is always lowered to the result of coro.begin.
462
484
for (CoroFrameInst *CF : CoroFrames) {
463
485
CF->replaceAllUsesWith (CoroBegin);
464
486
CF->eraseFromParent ();
465
487
}
466
-
467
- // Move final suspend to be the last element in the CoroSuspends vector.
468
- if (ABI == coro::ABI::Switch &&
469
- SwitchLowering.HasFinalSuspend &&
470
- FinalSuspendIndex != CoroSuspends.size () - 1 )
471
- std::swap (CoroSuspends[FinalSuspendIndex], CoroSuspends.back ());
488
+ CoroFrames.clear ();
472
489
473
490
// Remove orphaned coro.saves.
474
491
for (CoroSaveInst *CoroSave : UnusedCoroSaves)
475
492
CoroSave->eraseFromParent ();
493
+ UnusedCoroSaves.clear ();
476
494
}
477
495
478
496
static void propagateCallAttrsFromCallee (CallInst *Call, Function *Callee) {
0 commit comments