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.alloc",
127       "llvm.coro.async.context.alloc",
128       "llvm.coro.async.context.dealloc",
129       "llvm.coro.async.resume",
130       "llvm.coro.async.size.replace",
131       "llvm.coro.async.store_resume",
132       "llvm.coro.begin",
133       "llvm.coro.destroy",
134       "llvm.coro.done",
135       "llvm.coro.end",
136       "llvm.coro.end.async",
137       "llvm.coro.frame",
138       "llvm.coro.free",
139       "llvm.coro.id",
140       "llvm.coro.id.async",
141       "llvm.coro.id.retcon",
142       "llvm.coro.id.retcon.once",
143       "llvm.coro.noop",
144       "llvm.coro.param",
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_frame:
273         CoroFrames.push_back(cast<CoroFrameInst>(II));
274         break;
275       case Intrinsic::coro_save:
276         // After optimizations, coro_suspends using this coro_save might have
277         // been removed, remember orphaned coro_saves to remove them later.
278         if (II->use_empty())
279           UnusedCoroSaves.push_back(cast<CoroSaveInst>(II));
280         break;
281       case Intrinsic::coro_suspend_async: {
282         auto *Suspend = cast<CoroSuspendAsyncInst>(II);
283         Suspend->checkWellFormed();
284         CoroSuspends.push_back(Suspend);
285         break;
286       }
287       case Intrinsic::coro_suspend_retcon: {
288         auto Suspend = cast<CoroSuspendRetconInst>(II);
289         CoroSuspends.push_back(Suspend);
290         break;
291       }
292       case Intrinsic::coro_suspend: {
293         auto Suspend = cast<CoroSuspendInst>(II);
294         CoroSuspends.push_back(Suspend);
295         if (Suspend->isFinal()) {
296           if (HasFinalSuspend)
297             report_fatal_error(
298               "Only one suspend point can be marked as final");
299           HasFinalSuspend = true;
300           FinalSuspendIndex = CoroSuspends.size() - 1;
301         }
302         break;
303       }
304       case Intrinsic::coro_begin: {
305         auto CB = cast<CoroBeginInst>(II);
306 
307         // Ignore coro id's that aren't pre-split.
308         auto Id = dyn_cast<CoroIdInst>(CB->getId());
309         if (Id && !Id->getInfo().isPreSplit())
310           break;
311 
312         if (CoroBegin)
313           report_fatal_error(
314                 "coroutine should have exactly one defining @llvm.coro.begin");
315         CB->addRetAttr(Attribute::NonNull);
316         CB->addRetAttr(Attribute::NoAlias);
317         CB->removeFnAttr(Attribute::NoDuplicate);
318         CoroBegin = CB;
319         break;
320       }
321       case Intrinsic::coro_end_async:
322       case Intrinsic::coro_end:
323         CoroEnds.push_back(cast<AnyCoroEndInst>(II));
324         if (auto *AsyncEnd = dyn_cast<CoroAsyncEndInst>(II)) {
325           AsyncEnd->checkWellFormed();
326         }
327         if (CoroEnds.back()->isFallthrough() && isa<CoroEndInst>(II)) {
328           // Make sure that the fallthrough coro.end is the first element in the
329           // CoroEnds vector.
330           // Note: I don't think this is neccessary anymore.
331           if (CoroEnds.size() > 1) {
332             if (CoroEnds.front()->isFallthrough())
333               report_fatal_error(
334                   "Only one coro.end can be marked as fallthrough");
335             std::swap(CoroEnds.front(), CoroEnds.back());
336           }
337         }
338         break;
339       }
340     }
341   }
342 
343   // If for some reason, we were not able to find coro.begin, bailout.
344   if (!CoroBegin) {
345     // Replace coro.frame which are supposed to be lowered to the result of
346     // coro.begin with undef.
347     auto *Undef = UndefValue::get(Type::getInt8PtrTy(F.getContext()));
348     for (CoroFrameInst *CF : CoroFrames) {
349       CF->replaceAllUsesWith(Undef);
350       CF->eraseFromParent();
351     }
352 
353     // Replace all coro.suspend with undef and remove related coro.saves if
354     // present.
355     for (AnyCoroSuspendInst *CS : CoroSuspends) {
356       CS->replaceAllUsesWith(UndefValue::get(CS->getType()));
357       CS->eraseFromParent();
358       if (auto *CoroSave = CS->getCoroSave())
359         CoroSave->eraseFromParent();
360     }
361 
362     // Replace all coro.ends with unreachable instruction.
363     for (AnyCoroEndInst *CE : CoroEnds)
364       changeToUnreachable(CE);
365 
366     return;
367   }
368 
369   auto Id = CoroBegin->getId();
370   switch (auto IdIntrinsic = Id->getIntrinsicID()) {
371   case Intrinsic::coro_id: {
372     auto SwitchId = cast<CoroIdInst>(Id);
373     this->ABI = coro::ABI::Switch;
374     this->SwitchLowering.HasFinalSuspend = HasFinalSuspend;
375     this->SwitchLowering.ResumeSwitch = nullptr;
376     this->SwitchLowering.PromiseAlloca = SwitchId->getPromise();
377     this->SwitchLowering.ResumeEntryBlock = nullptr;
378 
379     for (auto AnySuspend : CoroSuspends) {
380       auto Suspend = dyn_cast<CoroSuspendInst>(AnySuspend);
381       if (!Suspend) {
382 #ifndef NDEBUG
383         AnySuspend->dump();
384 #endif
385         report_fatal_error("coro.id must be paired with coro.suspend");
386       }
387 
388       if (!Suspend->getCoroSave())
389         createCoroSave(CoroBegin, Suspend);
390     }
391     break;
392   }
393   case Intrinsic::coro_id_async: {
394     auto *AsyncId = cast<CoroIdAsyncInst>(Id);
395     AsyncId->checkWellFormed();
396     this->ABI = coro::ABI::Async;
397     this->AsyncLowering.Context = AsyncId->getStorage();
398     this->AsyncLowering.ContextArgNo = AsyncId->getStorageArgumentIndex();
399     this->AsyncLowering.ContextHeaderSize = AsyncId->getStorageSize();
400     this->AsyncLowering.ContextAlignment =
401         AsyncId->getStorageAlignment().value();
402     this->AsyncLowering.AsyncFuncPointer = AsyncId->getAsyncFunctionPointer();
403     this->AsyncLowering.AsyncCC = F.getCallingConv();
404     break;
405   };
406   case Intrinsic::coro_id_retcon:
407   case Intrinsic::coro_id_retcon_once: {
408     auto ContinuationId = cast<AnyCoroIdRetconInst>(Id);
409     ContinuationId->checkWellFormed();
410     this->ABI = (IdIntrinsic == Intrinsic::coro_id_retcon
411                   ? coro::ABI::Retcon
412                   : coro::ABI::RetconOnce);
413     auto Prototype = ContinuationId->getPrototype();
414     this->RetconLowering.ResumePrototype = Prototype;
415     this->RetconLowering.Alloc = ContinuationId->getAllocFunction();
416     this->RetconLowering.Dealloc = ContinuationId->getDeallocFunction();
417     this->RetconLowering.ReturnBlock = nullptr;
418     this->RetconLowering.IsFrameInlineInStorage = false;
419 
420     // Determine the result value types, and make sure they match up with
421     // the values passed to the suspends.
422     auto ResultTys = getRetconResultTypes();
423     auto ResumeTys = getRetconResumeTypes();
424 
425     for (auto AnySuspend : CoroSuspends) {
426       auto Suspend = dyn_cast<CoroSuspendRetconInst>(AnySuspend);
427       if (!Suspend) {
428 #ifndef NDEBUG
429         AnySuspend->dump();
430 #endif
431         report_fatal_error("coro.id.retcon.* must be paired with "
432                            "coro.suspend.retcon");
433       }
434 
435       // Check that the argument types of the suspend match the results.
436       auto SI = Suspend->value_begin(), SE = Suspend->value_end();
437       auto RI = ResultTys.begin(), RE = ResultTys.end();
438       for (; SI != SE && RI != RE; ++SI, ++RI) {
439         auto SrcTy = (*SI)->getType();
440         if (SrcTy != *RI) {
441           // The optimizer likes to eliminate bitcasts leading into variadic
442           // calls, but that messes with our invariants.  Re-insert the
443           // bitcast and ignore this type mismatch.
444           if (CastInst::isBitCastable(SrcTy, *RI)) {
445             auto BCI = new BitCastInst(*SI, *RI, "", Suspend);
446             SI->set(BCI);
447             continue;
448           }
449 
450 #ifndef NDEBUG
451           Suspend->dump();
452           Prototype->getFunctionType()->dump();
453 #endif
454           report_fatal_error("argument to coro.suspend.retcon does not "
455                              "match corresponding prototype function result");
456         }
457       }
458       if (SI != SE || RI != RE) {
459 #ifndef NDEBUG
460         Suspend->dump();
461         Prototype->getFunctionType()->dump();
462 #endif
463         report_fatal_error("wrong number of arguments to coro.suspend.retcon");
464       }
465 
466       // Check that the result type of the suspend matches the resume types.
467       Type *SResultTy = Suspend->getType();
468       ArrayRef<Type*> SuspendResultTys;
469       if (SResultTy->isVoidTy()) {
470         // leave as empty array
471       } else if (auto SResultStructTy = dyn_cast<StructType>(SResultTy)) {
472         SuspendResultTys = SResultStructTy->elements();
473       } else {
474         // forms an ArrayRef using SResultTy, be careful
475         SuspendResultTys = SResultTy;
476       }
477       if (SuspendResultTys.size() != ResumeTys.size()) {
478 #ifndef NDEBUG
479         Suspend->dump();
480         Prototype->getFunctionType()->dump();
481 #endif
482         report_fatal_error("wrong number of results from coro.suspend.retcon");
483       }
484       for (size_t I = 0, E = ResumeTys.size(); I != E; ++I) {
485         if (SuspendResultTys[I] != ResumeTys[I]) {
486 #ifndef NDEBUG
487           Suspend->dump();
488           Prototype->getFunctionType()->dump();
489 #endif
490           report_fatal_error("result from coro.suspend.retcon does not "
491                              "match corresponding prototype function param");
492         }
493       }
494     }
495     break;
496   }
497 
498   default:
499     llvm_unreachable("coro.begin is not dependent on a coro.id call");
500   }
501 
502   // The coro.free intrinsic is always lowered to the result of coro.begin.
503   for (CoroFrameInst *CF : CoroFrames) {
504     CF->replaceAllUsesWith(CoroBegin);
505     CF->eraseFromParent();
506   }
507 
508   // Move final suspend to be the last element in the CoroSuspends vector.
509   if (ABI == coro::ABI::Switch &&
510       SwitchLowering.HasFinalSuspend &&
511       FinalSuspendIndex != CoroSuspends.size() - 1)
512     std::swap(CoroSuspends[FinalSuspendIndex], CoroSuspends.back());
513 
514   // Remove orphaned coro.saves.
515   for (CoroSaveInst *CoroSave : UnusedCoroSaves)
516     CoroSave->eraseFromParent();
517 }
518 
519 static void propagateCallAttrsFromCallee(CallInst *Call, Function *Callee) {
520   Call->setCallingConv(Callee->getCallingConv());
521   // TODO: attributes?
522 }
523 
524 static void addCallToCallGraph(CallGraph *CG, CallInst *Call, Function *Callee){
525   if (CG)
526     (*CG)[Call->getFunction()]->addCalledFunction(Call, (*CG)[Callee]);
527 }
528 
529 Value *coro::Shape::emitAlloc(IRBuilder<> &Builder, Value *Size,
530                               CallGraph *CG) const {
531   switch (ABI) {
532   case coro::ABI::Switch:
533     llvm_unreachable("can't allocate memory in coro switch-lowering");
534 
535   case coro::ABI::Retcon:
536   case coro::ABI::RetconOnce: {
537     auto Alloc = RetconLowering.Alloc;
538     Size = Builder.CreateIntCast(Size,
539                                  Alloc->getFunctionType()->getParamType(0),
540                                  /*is signed*/ false);
541     auto *Call = Builder.CreateCall(Alloc, Size);
542     propagateCallAttrsFromCallee(Call, Alloc);
543     addCallToCallGraph(CG, Call, Alloc);
544     return Call;
545   }
546   case coro::ABI::Async:
547     llvm_unreachable("can't allocate memory in coro async-lowering");
548   }
549   llvm_unreachable("Unknown coro::ABI enum");
550 }
551 
552 void coro::Shape::emitDealloc(IRBuilder<> &Builder, Value *Ptr,
553                               CallGraph *CG) const {
554   switch (ABI) {
555   case coro::ABI::Switch:
556     llvm_unreachable("can't allocate memory in coro switch-lowering");
557 
558   case coro::ABI::Retcon:
559   case coro::ABI::RetconOnce: {
560     auto Dealloc = RetconLowering.Dealloc;
561     Ptr = Builder.CreateBitCast(Ptr,
562                                 Dealloc->getFunctionType()->getParamType(0));
563     auto *Call = Builder.CreateCall(Dealloc, Ptr);
564     propagateCallAttrsFromCallee(Call, Dealloc);
565     addCallToCallGraph(CG, Call, Dealloc);
566     return;
567   }
568   case coro::ABI::Async:
569     llvm_unreachable("can't allocate memory in coro async-lowering");
570   }
571   llvm_unreachable("Unknown coro::ABI enum");
572 }
573 
574 [[noreturn]] static void fail(const Instruction *I, const char *Reason,
575                               Value *V) {
576 #ifndef NDEBUG
577   I->dump();
578   if (V) {
579     errs() << "  Value: ";
580     V->printAsOperand(llvm::errs());
581     errs() << '\n';
582   }
583 #endif
584   report_fatal_error(Reason);
585 }
586 
587 /// Check that the given value is a well-formed prototype for the
588 /// llvm.coro.id.retcon.* intrinsics.
589 static void checkWFRetconPrototype(const AnyCoroIdRetconInst *I, Value *V) {
590   auto F = dyn_cast<Function>(V->stripPointerCasts());
591   if (!F)
592     fail(I, "llvm.coro.id.retcon.* prototype not a Function", V);
593 
594   auto FT = F->getFunctionType();
595 
596   if (isa<CoroIdRetconInst>(I)) {
597     bool ResultOkay;
598     if (FT->getReturnType()->isPointerTy()) {
599       ResultOkay = true;
600     } else if (auto SRetTy = dyn_cast<StructType>(FT->getReturnType())) {
601       ResultOkay = (!SRetTy->isOpaque() &&
602                     SRetTy->getNumElements() > 0 &&
603                     SRetTy->getElementType(0)->isPointerTy());
604     } else {
605       ResultOkay = false;
606     }
607     if (!ResultOkay)
608       fail(I, "llvm.coro.id.retcon prototype must return pointer as first "
609               "result", F);
610 
611     if (FT->getReturnType() !=
612           I->getFunction()->getFunctionType()->getReturnType())
613       fail(I, "llvm.coro.id.retcon prototype return type must be same as"
614               "current function return type", F);
615   } else {
616     // No meaningful validation to do here for llvm.coro.id.unique.once.
617   }
618 
619   if (FT->getNumParams() == 0 || !FT->getParamType(0)->isPointerTy())
620     fail(I, "llvm.coro.id.retcon.* prototype must take pointer as "
621             "its first parameter", F);
622 }
623 
624 /// Check that the given value is a well-formed allocator.
625 static void checkWFAlloc(const Instruction *I, Value *V) {
626   auto F = dyn_cast<Function>(V->stripPointerCasts());
627   if (!F)
628     fail(I, "llvm.coro.* allocator not a Function", V);
629 
630   auto FT = F->getFunctionType();
631   if (!FT->getReturnType()->isPointerTy())
632     fail(I, "llvm.coro.* allocator must return a pointer", F);
633 
634   if (FT->getNumParams() != 1 ||
635       !FT->getParamType(0)->isIntegerTy())
636     fail(I, "llvm.coro.* allocator must take integer as only param", F);
637 }
638 
639 /// Check that the given value is a well-formed deallocator.
640 static void checkWFDealloc(const Instruction *I, Value *V) {
641   auto F = dyn_cast<Function>(V->stripPointerCasts());
642   if (!F)
643     fail(I, "llvm.coro.* deallocator not a Function", V);
644 
645   auto FT = F->getFunctionType();
646   if (!FT->getReturnType()->isVoidTy())
647     fail(I, "llvm.coro.* deallocator must return void", F);
648 
649   if (FT->getNumParams() != 1 ||
650       !FT->getParamType(0)->isPointerTy())
651     fail(I, "llvm.coro.* deallocator must take pointer as only param", F);
652 }
653 
654 static void checkConstantInt(const Instruction *I, Value *V,
655                              const char *Reason) {
656   if (!isa<ConstantInt>(V)) {
657     fail(I, Reason, V);
658   }
659 }
660 
661 void AnyCoroIdRetconInst::checkWellFormed() const {
662   checkConstantInt(this, getArgOperand(SizeArg),
663                    "size argument to coro.id.retcon.* must be constant");
664   checkConstantInt(this, getArgOperand(AlignArg),
665                    "alignment argument to coro.id.retcon.* must be constant");
666   checkWFRetconPrototype(this, getArgOperand(PrototypeArg));
667   checkWFAlloc(this, getArgOperand(AllocArg));
668   checkWFDealloc(this, getArgOperand(DeallocArg));
669 }
670 
671 static void checkAsyncFuncPointer(const Instruction *I, Value *V) {
672   auto *AsyncFuncPtrAddr = dyn_cast<GlobalVariable>(V->stripPointerCasts());
673   if (!AsyncFuncPtrAddr)
674     fail(I, "llvm.coro.id.async async function pointer not a global", V);
675 
676   auto *StructTy =
677       cast<StructType>(AsyncFuncPtrAddr->getType()->getPointerElementType());
678   if (StructTy->isOpaque() || !StructTy->isPacked() ||
679       StructTy->getNumElements() != 2 ||
680       !StructTy->getElementType(0)->isIntegerTy(32) ||
681       !StructTy->getElementType(1)->isIntegerTy(32))
682     fail(I,
683          "llvm.coro.id.async async function pointer argument's type is not "
684          "<{i32, i32}>",
685          V);
686 }
687 
688 void CoroIdAsyncInst::checkWellFormed() const {
689   checkConstantInt(this, getArgOperand(SizeArg),
690                    "size argument to coro.id.async must be constant");
691   checkConstantInt(this, getArgOperand(AlignArg),
692                    "alignment argument to coro.id.async must be constant");
693   checkConstantInt(this, getArgOperand(StorageArg),
694                    "storage argument offset to coro.id.async must be constant");
695   checkAsyncFuncPointer(this, getArgOperand(AsyncFuncPtrArg));
696 }
697 
698 static void checkAsyncContextProjectFunction(const Instruction *I,
699                                              Function *F) {
700   auto *FunTy = cast<FunctionType>(F->getValueType());
701   if (!FunTy->getReturnType()->isPointerTy() ||
702       !FunTy->getReturnType()->getPointerElementType()->isIntegerTy(8))
703     fail(I,
704          "llvm.coro.suspend.async resume function projection function must "
705          "return an i8* type",
706          F);
707   if (FunTy->getNumParams() != 1 || !FunTy->getParamType(0)->isPointerTy() ||
708       !FunTy->getParamType(0)->getPointerElementType()->isIntegerTy(8))
709     fail(I,
710          "llvm.coro.suspend.async resume function projection function must "
711          "take one i8* type as parameter",
712          F);
713 }
714 
715 void CoroSuspendAsyncInst::checkWellFormed() const {
716   checkAsyncContextProjectFunction(this, getAsyncContextProjectionFunction());
717 }
718 
719 void CoroAsyncEndInst::checkWellFormed() const {
720   auto *MustTailCallFunc = getMustTailCallFunction();
721   if (!MustTailCallFunc)
722     return;
723   auto *FnTy =
724       cast<FunctionType>(MustTailCallFunc->getType()->getPointerElementType());
725   if (FnTy->getNumParams() != (arg_size() - 3))
726     fail(this,
727          "llvm.coro.end.async must tail call function argument type must "
728          "match the tail arguments",
729          MustTailCallFunc);
730 }
731 
732 void LLVMAddCoroEarlyPass(LLVMPassManagerRef PM) {
733   unwrap(PM)->add(createCoroEarlyLegacyPass());
734 }
735 
736 void LLVMAddCoroSplitPass(LLVMPassManagerRef PM) {
737   unwrap(PM)->add(createCoroSplitLegacyPass());
738 }
739 
740 void LLVMAddCoroElidePass(LLVMPassManagerRef PM) {
741   unwrap(PM)->add(createCoroElideLegacyPass());
742 }
743 
744 void LLVMAddCoroCleanupPass(LLVMPassManagerRef PM) {
745   unwrap(PM)->add(createCoroCleanupLegacyPass());
746 }
747 
748 void
749 LLVMPassManagerBuilderAddCoroutinePassesToExtensionPoints(LLVMPassManagerBuilderRef PMB) {
750   PassManagerBuilder *Builder = unwrap(PMB);
751   addCoroutinePassesToExtensionPoints(*Builder);
752 }
753