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