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