1 //===- Coroutines.cpp -----------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the common infrastructure for Coroutine Passes.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "llvm/Transforms/Coroutines.h"
14 #include "CoroInstr.h"
15 #include "CoroInternal.h"
16 #include "llvm-c/Transforms/Coroutines.h"
17 #include "llvm/ADT/SmallVector.h"
18 #include "llvm/ADT/StringRef.h"
19 #include "llvm/Analysis/CallGraph.h"
20 #include "llvm/Analysis/CallGraphSCCPass.h"
21 #include "llvm/IR/Attributes.h"
22 #include "llvm/IR/Constants.h"
23 #include "llvm/IR/DerivedTypes.h"
24 #include "llvm/IR/Function.h"
25 #include "llvm/IR/InstIterator.h"
26 #include "llvm/IR/Instructions.h"
27 #include "llvm/IR/IntrinsicInst.h"
28 #include "llvm/IR/Intrinsics.h"
29 #include "llvm/IR/LegacyPassManager.h"
30 #include "llvm/IR/Module.h"
31 #include "llvm/IR/Type.h"
32 #include "llvm/InitializePasses.h"
33 #include "llvm/Support/Casting.h"
34 #include "llvm/Support/ErrorHandling.h"
35 #include "llvm/Transforms/IPO.h"
36 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
37 #include "llvm/Transforms/Utils/Local.h"
38 #include <cassert>
39 #include <cstddef>
40 #include <utility>
41 
42 using namespace llvm;
43 
44 void llvm::initializeCoroutines(PassRegistry &Registry) {
45   initializeCoroEarlyLegacyPass(Registry);
46   initializeCoroSplitLegacyPass(Registry);
47   initializeCoroElideLegacyPass(Registry);
48   initializeCoroCleanupLegacyPass(Registry);
49 }
50 
51 static void addCoroutineOpt0Passes(const PassManagerBuilder &Builder,
52                                    legacy::PassManagerBase &PM) {
53   PM.add(createCoroSplitLegacyPass());
54   PM.add(createCoroElideLegacyPass());
55 
56   PM.add(createBarrierNoopPass());
57   PM.add(createCoroCleanupLegacyPass());
58 }
59 
60 static void addCoroutineEarlyPasses(const PassManagerBuilder &Builder,
61                                     legacy::PassManagerBase &PM) {
62   PM.add(createCoroEarlyLegacyPass());
63 }
64 
65 static void addCoroutineScalarOptimizerPasses(const PassManagerBuilder &Builder,
66                                               legacy::PassManagerBase &PM) {
67   PM.add(createCoroElideLegacyPass());
68 }
69 
70 static void addCoroutineSCCPasses(const PassManagerBuilder &Builder,
71                                   legacy::PassManagerBase &PM) {
72   PM.add(createCoroSplitLegacyPass(Builder.OptLevel != 0));
73 }
74 
75 static void addCoroutineOptimizerLastPasses(const PassManagerBuilder &Builder,
76                                             legacy::PassManagerBase &PM) {
77   PM.add(createCoroCleanupLegacyPass());
78 }
79 
80 void llvm::addCoroutinePassesToExtensionPoints(PassManagerBuilder &Builder) {
81   Builder.addExtension(PassManagerBuilder::EP_EarlyAsPossible,
82                        addCoroutineEarlyPasses);
83   Builder.addExtension(PassManagerBuilder::EP_EnabledOnOptLevel0,
84                        addCoroutineOpt0Passes);
85   Builder.addExtension(PassManagerBuilder::EP_CGSCCOptimizerLate,
86                        addCoroutineSCCPasses);
87   Builder.addExtension(PassManagerBuilder::EP_ScalarOptimizerLate,
88                        addCoroutineScalarOptimizerPasses);
89   Builder.addExtension(PassManagerBuilder::EP_OptimizerLast,
90                        addCoroutineOptimizerLastPasses);
91 }
92 
93 // Construct the lowerer base class and initialize its members.
94 coro::LowererBase::LowererBase(Module &M)
95     : TheModule(M), Context(M.getContext()),
96       Int8Ptr(Type::getInt8PtrTy(Context)),
97       ResumeFnType(FunctionType::get(Type::getVoidTy(Context), Int8Ptr,
98                                      /*isVarArg=*/false)),
99       NullPtr(ConstantPointerNull::get(Int8Ptr)) {}
100 
101 // Creates a sequence of instructions to obtain a resume function address using
102 // llvm.coro.subfn.addr. It generates the following sequence:
103 //
104 //    call i8* @llvm.coro.subfn.addr(i8* %Arg, i8 %index)
105 //    bitcast i8* %2 to void(i8*)*
106 
107 Value *coro::LowererBase::makeSubFnCall(Value *Arg, int Index,
108                                         Instruction *InsertPt) {
109   auto *IndexVal = ConstantInt::get(Type::getInt8Ty(Context), Index);
110   auto *Fn = Intrinsic::getDeclaration(&TheModule, Intrinsic::coro_subfn_addr);
111 
112   assert(Index >= CoroSubFnInst::IndexFirst &&
113          Index < CoroSubFnInst::IndexLast &&
114          "makeSubFnCall: Index value out of range");
115   auto *Call = CallInst::Create(Fn, {Arg, IndexVal}, "", InsertPt);
116 
117   auto *Bitcast =
118       new BitCastInst(Call, ResumeFnType->getPointerTo(), "", InsertPt);
119   return Bitcast;
120 }
121 
122 // NOTE: Must be sorted!
123 static const char *const CoroIntrinsics[] = {
124     "llvm.coro.align",
125     "llvm.coro.alloc",
126     "llvm.coro.async.context.alloc",
127     "llvm.coro.async.context.dealloc",
128     "llvm.coro.async.resume",
129     "llvm.coro.async.size.replace",
130     "llvm.coro.async.store_resume",
131     "llvm.coro.begin",
132     "llvm.coro.destroy",
133     "llvm.coro.done",
134     "llvm.coro.end",
135     "llvm.coro.end.async",
136     "llvm.coro.frame",
137     "llvm.coro.free",
138     "llvm.coro.id",
139     "llvm.coro.id.async",
140     "llvm.coro.id.retcon",
141     "llvm.coro.id.retcon.once",
142     "llvm.coro.noop",
143     "llvm.coro.prepare.async",
144     "llvm.coro.prepare.retcon",
145     "llvm.coro.promise",
146     "llvm.coro.resume",
147     "llvm.coro.save",
148     "llvm.coro.size",
149     "llvm.coro.subfn.addr",
150     "llvm.coro.suspend",
151     "llvm.coro.suspend.async",
152     "llvm.coro.suspend.retcon",
153 };
154 
155 #ifndef NDEBUG
156 static bool isCoroutineIntrinsicName(StringRef Name) {
157   return Intrinsic::lookupLLVMIntrinsicByName(CoroIntrinsics, Name) != -1;
158 }
159 #endif
160 
161 bool coro::declaresAnyIntrinsic(const Module &M) {
162   for (StringRef Name : CoroIntrinsics) {
163     assert(isCoroutineIntrinsicName(Name) && "not a coroutine intrinsic");
164     if (M.getNamedValue(Name))
165       return true;
166   }
167 
168   return false;
169 }
170 
171 // Verifies if a module has named values listed. Also, in debug mode verifies
172 // that names are intrinsic names.
173 bool coro::declaresIntrinsics(const Module &M,
174                               const std::initializer_list<StringRef> List) {
175   for (StringRef Name : List) {
176     assert(isCoroutineIntrinsicName(Name) && "not a coroutine intrinsic");
177     if (M.getNamedValue(Name))
178       return true;
179   }
180 
181   return false;
182 }
183 
184 // Replace all coro.frees associated with the provided CoroId either with 'null'
185 // if Elide is true and with its frame parameter otherwise.
186 void coro::replaceCoroFree(CoroIdInst *CoroId, bool Elide) {
187   SmallVector<CoroFreeInst *, 4> CoroFrees;
188   for (User *U : CoroId->users())
189     if (auto CF = dyn_cast<CoroFreeInst>(U))
190       CoroFrees.push_back(CF);
191 
192   if (CoroFrees.empty())
193     return;
194 
195   Value *Replacement =
196       Elide ? ConstantPointerNull::get(Type::getInt8PtrTy(CoroId->getContext()))
197             : CoroFrees.front()->getFrame();
198 
199   for (CoroFreeInst *CF : CoroFrees) {
200     CF->replaceAllUsesWith(Replacement);
201     CF->eraseFromParent();
202   }
203 }
204 
205 // FIXME: This code is stolen from CallGraph::addToCallGraph(Function *F), which
206 // happens to be private. It is better for this functionality exposed by the
207 // CallGraph.
208 static void buildCGN(CallGraph &CG, CallGraphNode *Node) {
209   Function *F = Node->getFunction();
210 
211   // Look for calls by this function.
212   for (Instruction &I : instructions(F))
213     if (auto *Call = dyn_cast<CallBase>(&I)) {
214       const Function *Callee = Call->getCalledFunction();
215       if (!Callee || !Intrinsic::isLeaf(Callee->getIntrinsicID()))
216         // Indirect calls of intrinsics are not allowed so no need to check.
217         // We can be more precise here by using TargetArg returned by
218         // Intrinsic::isLeaf.
219         Node->addCalledFunction(Call, CG.getCallsExternalNode());
220       else if (!Callee->isIntrinsic())
221         Node->addCalledFunction(Call, CG.getOrInsertFunction(Callee));
222     }
223 }
224 
225 // Rebuild CGN after we extracted parts of the code from ParentFunc into
226 // NewFuncs. Builds CGNs for the NewFuncs and adds them to the current SCC.
227 void coro::updateCallGraph(Function &ParentFunc, ArrayRef<Function *> NewFuncs,
228                            CallGraph &CG, CallGraphSCC &SCC) {
229   // Rebuild CGN from scratch for the ParentFunc
230   auto *ParentNode = CG[&ParentFunc];
231   ParentNode->removeAllCalledFunctions();
232   buildCGN(CG, ParentNode);
233 
234   SmallVector<CallGraphNode *, 8> Nodes(SCC.begin(), SCC.end());
235 
236   for (Function *F : NewFuncs) {
237     CallGraphNode *Callee = CG.getOrInsertFunction(F);
238     Nodes.push_back(Callee);
239     buildCGN(CG, Callee);
240   }
241 
242   SCC.initialize(Nodes);
243 }
244 
245 static void clear(coro::Shape &Shape) {
246   Shape.CoroBegin = nullptr;
247   Shape.CoroEnds.clear();
248   Shape.CoroSizes.clear();
249   Shape.CoroSuspends.clear();
250 
251   Shape.FrameTy = nullptr;
252   Shape.FramePtr = nullptr;
253   Shape.AllocaSpillBlock = nullptr;
254 }
255 
256 static CoroSaveInst *createCoroSave(CoroBeginInst *CoroBegin,
257                                     CoroSuspendInst *SuspendInst) {
258   Module *M = SuspendInst->getModule();
259   auto *Fn = Intrinsic::getDeclaration(M, Intrinsic::coro_save);
260   auto *SaveInst =
261       cast<CoroSaveInst>(CallInst::Create(Fn, CoroBegin, "", SuspendInst));
262   assert(!SuspendInst->getCoroSave());
263   SuspendInst->setArgOperand(0, SaveInst);
264   return SaveInst;
265 }
266 
267 // Collect "interesting" coroutine intrinsics.
268 void coro::Shape::buildFrom(Function &F) {
269   bool HasFinalSuspend = false;
270   size_t FinalSuspendIndex = 0;
271   clear(*this);
272   SmallVector<CoroFrameInst *, 8> CoroFrames;
273   SmallVector<CoroSaveInst *, 2> UnusedCoroSaves;
274 
275   for (Instruction &I : instructions(F)) {
276     if (auto II = dyn_cast<IntrinsicInst>(&I)) {
277       switch (II->getIntrinsicID()) {
278       default:
279         continue;
280       case Intrinsic::coro_size:
281         CoroSizes.push_back(cast<CoroSizeInst>(II));
282         break;
283       case Intrinsic::coro_align:
284         CoroAligns.push_back(cast<CoroAlignInst>(II));
285         break;
286       case Intrinsic::coro_frame:
287         CoroFrames.push_back(cast<CoroFrameInst>(II));
288         break;
289       case Intrinsic::coro_save:
290         // After optimizations, coro_suspends using this coro_save might have
291         // been removed, remember orphaned coro_saves to remove them later.
292         if (II->use_empty())
293           UnusedCoroSaves.push_back(cast<CoroSaveInst>(II));
294         break;
295       case Intrinsic::coro_suspend_async: {
296         auto *Suspend = cast<CoroSuspendAsyncInst>(II);
297         Suspend->checkWellFormed();
298         CoroSuspends.push_back(Suspend);
299         break;
300       }
301       case Intrinsic::coro_suspend_retcon: {
302         auto Suspend = cast<CoroSuspendRetconInst>(II);
303         CoroSuspends.push_back(Suspend);
304         break;
305       }
306       case Intrinsic::coro_suspend: {
307         auto Suspend = cast<CoroSuspendInst>(II);
308         CoroSuspends.push_back(Suspend);
309         if (Suspend->isFinal()) {
310           if (HasFinalSuspend)
311             report_fatal_error(
312               "Only one suspend point can be marked as final");
313           HasFinalSuspend = true;
314           FinalSuspendIndex = CoroSuspends.size() - 1;
315         }
316         break;
317       }
318       case Intrinsic::coro_begin: {
319         auto CB = cast<CoroBeginInst>(II);
320 
321         // Ignore coro id's that aren't pre-split.
322         auto Id = dyn_cast<CoroIdInst>(CB->getId());
323         if (Id && !Id->getInfo().isPreSplit())
324           break;
325 
326         if (CoroBegin)
327           report_fatal_error(
328                 "coroutine should have exactly one defining @llvm.coro.begin");
329         CB->addRetAttr(Attribute::NonNull);
330         CB->addRetAttr(Attribute::NoAlias);
331         CB->removeFnAttr(Attribute::NoDuplicate);
332         CoroBegin = CB;
333         break;
334       }
335       case Intrinsic::coro_end_async:
336       case Intrinsic::coro_end:
337         CoroEnds.push_back(cast<AnyCoroEndInst>(II));
338         if (auto *AsyncEnd = dyn_cast<CoroAsyncEndInst>(II)) {
339           AsyncEnd->checkWellFormed();
340         }
341         if (CoroEnds.back()->isFallthrough() && isa<CoroEndInst>(II)) {
342           // Make sure that the fallthrough coro.end is the first element in the
343           // CoroEnds vector.
344           // Note: I don't think this is neccessary anymore.
345           if (CoroEnds.size() > 1) {
346             if (CoroEnds.front()->isFallthrough())
347               report_fatal_error(
348                   "Only one coro.end can be marked as fallthrough");
349             std::swap(CoroEnds.front(), CoroEnds.back());
350           }
351         }
352         break;
353       }
354     }
355   }
356 
357   // If for some reason, we were not able to find coro.begin, bailout.
358   if (!CoroBegin) {
359     // Replace coro.frame which are supposed to be lowered to the result of
360     // coro.begin with undef.
361     auto *Undef = UndefValue::get(Type::getInt8PtrTy(F.getContext()));
362     for (CoroFrameInst *CF : CoroFrames) {
363       CF->replaceAllUsesWith(Undef);
364       CF->eraseFromParent();
365     }
366 
367     // Replace all coro.suspend with undef and remove related coro.saves if
368     // present.
369     for (AnyCoroSuspendInst *CS : CoroSuspends) {
370       CS->replaceAllUsesWith(UndefValue::get(CS->getType()));
371       CS->eraseFromParent();
372       if (auto *CoroSave = CS->getCoroSave())
373         CoroSave->eraseFromParent();
374     }
375 
376     // Replace all coro.ends with unreachable instruction.
377     for (AnyCoroEndInst *CE : CoroEnds)
378       changeToUnreachable(CE);
379 
380     return;
381   }
382 
383   auto Id = CoroBegin->getId();
384   switch (auto IdIntrinsic = Id->getIntrinsicID()) {
385   case Intrinsic::coro_id: {
386     auto SwitchId = cast<CoroIdInst>(Id);
387     this->ABI = coro::ABI::Switch;
388     this->SwitchLowering.HasFinalSuspend = HasFinalSuspend;
389     this->SwitchLowering.ResumeSwitch = nullptr;
390     this->SwitchLowering.PromiseAlloca = SwitchId->getPromise();
391     this->SwitchLowering.ResumeEntryBlock = nullptr;
392 
393     for (auto AnySuspend : CoroSuspends) {
394       auto Suspend = dyn_cast<CoroSuspendInst>(AnySuspend);
395       if (!Suspend) {
396 #ifndef NDEBUG
397         AnySuspend->dump();
398 #endif
399         report_fatal_error("coro.id must be paired with coro.suspend");
400       }
401 
402       if (!Suspend->getCoroSave())
403         createCoroSave(CoroBegin, Suspend);
404     }
405     break;
406   }
407   case Intrinsic::coro_id_async: {
408     auto *AsyncId = cast<CoroIdAsyncInst>(Id);
409     AsyncId->checkWellFormed();
410     this->ABI = coro::ABI::Async;
411     this->AsyncLowering.Context = AsyncId->getStorage();
412     this->AsyncLowering.ContextArgNo = AsyncId->getStorageArgumentIndex();
413     this->AsyncLowering.ContextHeaderSize = AsyncId->getStorageSize();
414     this->AsyncLowering.ContextAlignment =
415         AsyncId->getStorageAlignment().value();
416     this->AsyncLowering.AsyncFuncPointer = AsyncId->getAsyncFunctionPointer();
417     this->AsyncLowering.AsyncCC = F.getCallingConv();
418     break;
419   };
420   case Intrinsic::coro_id_retcon:
421   case Intrinsic::coro_id_retcon_once: {
422     auto ContinuationId = cast<AnyCoroIdRetconInst>(Id);
423     ContinuationId->checkWellFormed();
424     this->ABI = (IdIntrinsic == Intrinsic::coro_id_retcon
425                   ? coro::ABI::Retcon
426                   : coro::ABI::RetconOnce);
427     auto Prototype = ContinuationId->getPrototype();
428     this->RetconLowering.ResumePrototype = Prototype;
429     this->RetconLowering.Alloc = ContinuationId->getAllocFunction();
430     this->RetconLowering.Dealloc = ContinuationId->getDeallocFunction();
431     this->RetconLowering.ReturnBlock = nullptr;
432     this->RetconLowering.IsFrameInlineInStorage = false;
433 
434     // Determine the result value types, and make sure they match up with
435     // the values passed to the suspends.
436     auto ResultTys = getRetconResultTypes();
437     auto ResumeTys = getRetconResumeTypes();
438 
439     for (auto AnySuspend : CoroSuspends) {
440       auto Suspend = dyn_cast<CoroSuspendRetconInst>(AnySuspend);
441       if (!Suspend) {
442 #ifndef NDEBUG
443         AnySuspend->dump();
444 #endif
445         report_fatal_error("coro.id.retcon.* must be paired with "
446                            "coro.suspend.retcon");
447       }
448 
449       // Check that the argument types of the suspend match the results.
450       auto SI = Suspend->value_begin(), SE = Suspend->value_end();
451       auto RI = ResultTys.begin(), RE = ResultTys.end();
452       for (; SI != SE && RI != RE; ++SI, ++RI) {
453         auto SrcTy = (*SI)->getType();
454         if (SrcTy != *RI) {
455           // The optimizer likes to eliminate bitcasts leading into variadic
456           // calls, but that messes with our invariants.  Re-insert the
457           // bitcast and ignore this type mismatch.
458           if (CastInst::isBitCastable(SrcTy, *RI)) {
459             auto BCI = new BitCastInst(*SI, *RI, "", Suspend);
460             SI->set(BCI);
461             continue;
462           }
463 
464 #ifndef NDEBUG
465           Suspend->dump();
466           Prototype->getFunctionType()->dump();
467 #endif
468           report_fatal_error("argument to coro.suspend.retcon does not "
469                              "match corresponding prototype function result");
470         }
471       }
472       if (SI != SE || RI != RE) {
473 #ifndef NDEBUG
474         Suspend->dump();
475         Prototype->getFunctionType()->dump();
476 #endif
477         report_fatal_error("wrong number of arguments to coro.suspend.retcon");
478       }
479 
480       // Check that the result type of the suspend matches the resume types.
481       Type *SResultTy = Suspend->getType();
482       ArrayRef<Type*> SuspendResultTys;
483       if (SResultTy->isVoidTy()) {
484         // leave as empty array
485       } else if (auto SResultStructTy = dyn_cast<StructType>(SResultTy)) {
486         SuspendResultTys = SResultStructTy->elements();
487       } else {
488         // forms an ArrayRef using SResultTy, be careful
489         SuspendResultTys = SResultTy;
490       }
491       if (SuspendResultTys.size() != ResumeTys.size()) {
492 #ifndef NDEBUG
493         Suspend->dump();
494         Prototype->getFunctionType()->dump();
495 #endif
496         report_fatal_error("wrong number of results from coro.suspend.retcon");
497       }
498       for (size_t I = 0, E = ResumeTys.size(); I != E; ++I) {
499         if (SuspendResultTys[I] != ResumeTys[I]) {
500 #ifndef NDEBUG
501           Suspend->dump();
502           Prototype->getFunctionType()->dump();
503 #endif
504           report_fatal_error("result from coro.suspend.retcon does not "
505                              "match corresponding prototype function param");
506         }
507       }
508     }
509     break;
510   }
511 
512   default:
513     llvm_unreachable("coro.begin is not dependent on a coro.id call");
514   }
515 
516   // The coro.free intrinsic is always lowered to the result of coro.begin.
517   for (CoroFrameInst *CF : CoroFrames) {
518     CF->replaceAllUsesWith(CoroBegin);
519     CF->eraseFromParent();
520   }
521 
522   // Move final suspend to be the last element in the CoroSuspends vector.
523   if (ABI == coro::ABI::Switch &&
524       SwitchLowering.HasFinalSuspend &&
525       FinalSuspendIndex != CoroSuspends.size() - 1)
526     std::swap(CoroSuspends[FinalSuspendIndex], CoroSuspends.back());
527 
528   // Remove orphaned coro.saves.
529   for (CoroSaveInst *CoroSave : UnusedCoroSaves)
530     CoroSave->eraseFromParent();
531 }
532 
533 static void propagateCallAttrsFromCallee(CallInst *Call, Function *Callee) {
534   Call->setCallingConv(Callee->getCallingConv());
535   // TODO: attributes?
536 }
537 
538 static void addCallToCallGraph(CallGraph *CG, CallInst *Call, Function *Callee){
539   if (CG)
540     (*CG)[Call->getFunction()]->addCalledFunction(Call, (*CG)[Callee]);
541 }
542 
543 Value *coro::Shape::emitAlloc(IRBuilder<> &Builder, Value *Size,
544                               CallGraph *CG) const {
545   switch (ABI) {
546   case coro::ABI::Switch:
547     llvm_unreachable("can't allocate memory in coro switch-lowering");
548 
549   case coro::ABI::Retcon:
550   case coro::ABI::RetconOnce: {
551     auto Alloc = RetconLowering.Alloc;
552     Size = Builder.CreateIntCast(Size,
553                                  Alloc->getFunctionType()->getParamType(0),
554                                  /*is signed*/ false);
555     auto *Call = Builder.CreateCall(Alloc, Size);
556     propagateCallAttrsFromCallee(Call, Alloc);
557     addCallToCallGraph(CG, Call, Alloc);
558     return Call;
559   }
560   case coro::ABI::Async:
561     llvm_unreachable("can't allocate memory in coro async-lowering");
562   }
563   llvm_unreachable("Unknown coro::ABI enum");
564 }
565 
566 void coro::Shape::emitDealloc(IRBuilder<> &Builder, Value *Ptr,
567                               CallGraph *CG) const {
568   switch (ABI) {
569   case coro::ABI::Switch:
570     llvm_unreachable("can't allocate memory in coro switch-lowering");
571 
572   case coro::ABI::Retcon:
573   case coro::ABI::RetconOnce: {
574     auto Dealloc = RetconLowering.Dealloc;
575     Ptr = Builder.CreateBitCast(Ptr,
576                                 Dealloc->getFunctionType()->getParamType(0));
577     auto *Call = Builder.CreateCall(Dealloc, Ptr);
578     propagateCallAttrsFromCallee(Call, Dealloc);
579     addCallToCallGraph(CG, Call, Dealloc);
580     return;
581   }
582   case coro::ABI::Async:
583     llvm_unreachable("can't allocate memory in coro async-lowering");
584   }
585   llvm_unreachable("Unknown coro::ABI enum");
586 }
587 
588 [[noreturn]] static void fail(const Instruction *I, const char *Reason,
589                               Value *V) {
590 #ifndef NDEBUG
591   I->dump();
592   if (V) {
593     errs() << "  Value: ";
594     V->printAsOperand(llvm::errs());
595     errs() << '\n';
596   }
597 #endif
598   report_fatal_error(Reason);
599 }
600 
601 /// Check that the given value is a well-formed prototype for the
602 /// llvm.coro.id.retcon.* intrinsics.
603 static void checkWFRetconPrototype(const AnyCoroIdRetconInst *I, Value *V) {
604   auto F = dyn_cast<Function>(V->stripPointerCasts());
605   if (!F)
606     fail(I, "llvm.coro.id.retcon.* prototype not a Function", V);
607 
608   auto FT = F->getFunctionType();
609 
610   if (isa<CoroIdRetconInst>(I)) {
611     bool ResultOkay;
612     if (FT->getReturnType()->isPointerTy()) {
613       ResultOkay = true;
614     } else if (auto SRetTy = dyn_cast<StructType>(FT->getReturnType())) {
615       ResultOkay = (!SRetTy->isOpaque() &&
616                     SRetTy->getNumElements() > 0 &&
617                     SRetTy->getElementType(0)->isPointerTy());
618     } else {
619       ResultOkay = false;
620     }
621     if (!ResultOkay)
622       fail(I, "llvm.coro.id.retcon prototype must return pointer as first "
623               "result", F);
624 
625     if (FT->getReturnType() !=
626           I->getFunction()->getFunctionType()->getReturnType())
627       fail(I, "llvm.coro.id.retcon prototype return type must be same as"
628               "current function return type", F);
629   } else {
630     // No meaningful validation to do here for llvm.coro.id.unique.once.
631   }
632 
633   if (FT->getNumParams() == 0 || !FT->getParamType(0)->isPointerTy())
634     fail(I, "llvm.coro.id.retcon.* prototype must take pointer as "
635             "its first parameter", F);
636 }
637 
638 /// Check that the given value is a well-formed allocator.
639 static void checkWFAlloc(const Instruction *I, Value *V) {
640   auto F = dyn_cast<Function>(V->stripPointerCasts());
641   if (!F)
642     fail(I, "llvm.coro.* allocator not a Function", V);
643 
644   auto FT = F->getFunctionType();
645   if (!FT->getReturnType()->isPointerTy())
646     fail(I, "llvm.coro.* allocator must return a pointer", F);
647 
648   if (FT->getNumParams() != 1 ||
649       !FT->getParamType(0)->isIntegerTy())
650     fail(I, "llvm.coro.* allocator must take integer as only param", F);
651 }
652 
653 /// Check that the given value is a well-formed deallocator.
654 static void checkWFDealloc(const Instruction *I, Value *V) {
655   auto F = dyn_cast<Function>(V->stripPointerCasts());
656   if (!F)
657     fail(I, "llvm.coro.* deallocator not a Function", V);
658 
659   auto FT = F->getFunctionType();
660   if (!FT->getReturnType()->isVoidTy())
661     fail(I, "llvm.coro.* deallocator must return void", F);
662 
663   if (FT->getNumParams() != 1 ||
664       !FT->getParamType(0)->isPointerTy())
665     fail(I, "llvm.coro.* deallocator must take pointer as only param", F);
666 }
667 
668 static void checkConstantInt(const Instruction *I, Value *V,
669                              const char *Reason) {
670   if (!isa<ConstantInt>(V)) {
671     fail(I, Reason, V);
672   }
673 }
674 
675 void AnyCoroIdRetconInst::checkWellFormed() const {
676   checkConstantInt(this, getArgOperand(SizeArg),
677                    "size argument to coro.id.retcon.* must be constant");
678   checkConstantInt(this, getArgOperand(AlignArg),
679                    "alignment argument to coro.id.retcon.* must be constant");
680   checkWFRetconPrototype(this, getArgOperand(PrototypeArg));
681   checkWFAlloc(this, getArgOperand(AllocArg));
682   checkWFDealloc(this, getArgOperand(DeallocArg));
683 }
684 
685 static void checkAsyncFuncPointer(const Instruction *I, Value *V) {
686   auto *AsyncFuncPtrAddr = dyn_cast<GlobalVariable>(V->stripPointerCasts());
687   if (!AsyncFuncPtrAddr)
688     fail(I, "llvm.coro.id.async async function pointer not a global", V);
689 
690   if (AsyncFuncPtrAddr->getType()->isOpaquePointerTy())
691     return;
692 
693   auto *StructTy = cast<StructType>(
694       AsyncFuncPtrAddr->getType()->getNonOpaquePointerElementType());
695   if (StructTy->isOpaque() || !StructTy->isPacked() ||
696       StructTy->getNumElements() != 2 ||
697       !StructTy->getElementType(0)->isIntegerTy(32) ||
698       !StructTy->getElementType(1)->isIntegerTy(32))
699     fail(I,
700          "llvm.coro.id.async async function pointer argument's type is not "
701          "<{i32, i32}>",
702          V);
703 }
704 
705 void CoroIdAsyncInst::checkWellFormed() const {
706   checkConstantInt(this, getArgOperand(SizeArg),
707                    "size argument to coro.id.async must be constant");
708   checkConstantInt(this, getArgOperand(AlignArg),
709                    "alignment argument to coro.id.async must be constant");
710   checkConstantInt(this, getArgOperand(StorageArg),
711                    "storage argument offset to coro.id.async must be constant");
712   checkAsyncFuncPointer(this, getArgOperand(AsyncFuncPtrArg));
713 }
714 
715 static void checkAsyncContextProjectFunction(const Instruction *I,
716                                              Function *F) {
717   auto *FunTy = cast<FunctionType>(F->getValueType());
718   Type *Int8Ty = Type::getInt8Ty(F->getContext());
719   auto *RetPtrTy = dyn_cast<PointerType>(FunTy->getReturnType());
720   if (!RetPtrTy || !RetPtrTy->isOpaqueOrPointeeTypeMatches(Int8Ty))
721     fail(I,
722          "llvm.coro.suspend.async resume function projection function must "
723          "return an i8* type",
724          F);
725   if (FunTy->getNumParams() != 1 || !FunTy->getParamType(0)->isPointerTy() ||
726       !cast<PointerType>(FunTy->getParamType(0))
727            ->isOpaqueOrPointeeTypeMatches(Int8Ty))
728     fail(I,
729          "llvm.coro.suspend.async resume function projection function must "
730          "take one i8* type as parameter",
731          F);
732 }
733 
734 void CoroSuspendAsyncInst::checkWellFormed() const {
735   checkAsyncContextProjectFunction(this, getAsyncContextProjectionFunction());
736 }
737 
738 void CoroAsyncEndInst::checkWellFormed() const {
739   auto *MustTailCallFunc = getMustTailCallFunction();
740   if (!MustTailCallFunc)
741     return;
742   auto *FnTy = MustTailCallFunc->getFunctionType();
743   if (FnTy->getNumParams() != (arg_size() - 3))
744     fail(this,
745          "llvm.coro.end.async must tail call function argument type must "
746          "match the tail arguments",
747          MustTailCallFunc);
748 }
749 
750 void LLVMAddCoroEarlyPass(LLVMPassManagerRef PM) {
751   unwrap(PM)->add(createCoroEarlyLegacyPass());
752 }
753 
754 void LLVMAddCoroSplitPass(LLVMPassManagerRef PM) {
755   unwrap(PM)->add(createCoroSplitLegacyPass());
756 }
757 
758 void LLVMAddCoroElidePass(LLVMPassManagerRef PM) {
759   unwrap(PM)->add(createCoroElideLegacyPass());
760 }
761 
762 void LLVMAddCoroCleanupPass(LLVMPassManagerRef PM) {
763   unwrap(PM)->add(createCoroCleanupLegacyPass());
764 }
765 
766 void
767 LLVMPassManagerBuilderAddCoroutinePassesToExtensionPoints(LLVMPassManagerBuilderRef PMB) {
768   PassManagerBuilder *Builder = unwrap(PMB);
769   addCoroutinePassesToExtensionPoints(*Builder);
770 }
771