xref: /freebsd-src/contrib/llvm-project/llvm/lib/Transforms/Coroutines/CoroInstr.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1 //===-- CoroInstr.h - Coroutine Intrinsics Instruction Wrappers -*- C++ -*-===//
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 // This file defines classes that make it really easy to deal with intrinsic
9 // functions with the isa/dyncast family of functions.  In particular, this
10 // allows you to do things like:
11 //
12 //     if (auto *SF = dyn_cast<CoroSubFnInst>(Inst))
13 //        ... SF->getFrame() ...
14 //
15 // All intrinsic function calls are instances of the call instruction, so these
16 // are all subclasses of the CallInst class.  Note that none of these classes
17 // has state or virtual methods, which is an important part of this gross/neat
18 // hack working.
19 //
20 // The helpful comment above is borrowed from llvm/IntrinsicInst.h, we keep
21 // coroutine intrinsic wrappers here since they are only used by the passes in
22 // the Coroutine library.
23 //===----------------------------------------------------------------------===//
24 
25 #ifndef LLVM_LIB_TRANSFORMS_COROUTINES_COROINSTR_H
26 #define LLVM_LIB_TRANSFORMS_COROUTINES_COROINSTR_H
27 
28 #include "llvm/IR/GlobalVariable.h"
29 #include "llvm/IR/IntrinsicInst.h"
30 #include "llvm/Support/raw_ostream.h"
31 
32 namespace llvm {
33 
34 /// This class represents the llvm.coro.subfn.addr instruction.
35 class LLVM_LIBRARY_VISIBILITY CoroSubFnInst : public IntrinsicInst {
36   enum { FrameArg, IndexArg };
37 
38 public:
39   enum ResumeKind {
40     RestartTrigger = -1,
41     ResumeIndex,
42     DestroyIndex,
43     CleanupIndex,
44     IndexLast,
45     IndexFirst = RestartTrigger
46   };
47 
48   Value *getFrame() const { return getArgOperand(FrameArg); }
49   ResumeKind getIndex() const {
50     int64_t Index = getRawIndex()->getValue().getSExtValue();
51     assert(Index >= IndexFirst && Index < IndexLast &&
52            "unexpected CoroSubFnInst index argument");
53     return static_cast<ResumeKind>(Index);
54   }
55 
56   ConstantInt *getRawIndex() const {
57     return cast<ConstantInt>(getArgOperand(IndexArg));
58   }
59 
60   // Methods to support type inquiry through isa, cast, and dyn_cast:
61   static bool classof(const IntrinsicInst *I) {
62     return I->getIntrinsicID() == Intrinsic::coro_subfn_addr;
63   }
64   static bool classof(const Value *V) {
65     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
66   }
67 };
68 
69 /// This represents the llvm.coro.alloc instruction.
70 class LLVM_LIBRARY_VISIBILITY CoroAllocInst : public IntrinsicInst {
71 public:
72   // Methods to support type inquiry through isa, cast, and dyn_cast:
73   static bool classof(const IntrinsicInst *I) {
74     return I->getIntrinsicID() == Intrinsic::coro_alloc;
75   }
76   static bool classof(const Value *V) {
77     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
78   }
79 };
80 
81 /// This represents the llvm.coro.await.suspend.{void,bool,handle} instructions.
82 // FIXME: add callback metadata
83 // FIXME: make a proper IntrinisicInst. Currently this is not possible,
84 // because llvm.coro.await.suspend.* can be invoked.
85 class LLVM_LIBRARY_VISIBILITY CoroAwaitSuspendInst : public CallBase {
86   enum { AwaiterArg, FrameArg, WrapperArg };
87 
88 public:
89   Value *getAwaiter() const { return getArgOperand(AwaiterArg); }
90 
91   Value *getFrame() const { return getArgOperand(FrameArg); }
92 
93   Function *getWrapperFunction() const {
94     return cast<Function>(getArgOperand(WrapperArg));
95   }
96 
97   // Methods to support type inquiry through isa, cast, and dyn_cast:
98   static bool classof(const CallBase *CB) {
99     if (const Function *CF = CB->getCalledFunction()) {
100       auto IID = CF->getIntrinsicID();
101       return IID == Intrinsic::coro_await_suspend_void ||
102              IID == Intrinsic::coro_await_suspend_bool ||
103              IID == Intrinsic::coro_await_suspend_handle;
104     }
105 
106     return false;
107   }
108 
109   static bool classof(const Value *V) {
110     return isa<CallBase>(V) && classof(cast<CallBase>(V));
111   }
112 };
113 
114 /// This represents a common base class for llvm.coro.id instructions.
115 class LLVM_LIBRARY_VISIBILITY AnyCoroIdInst : public IntrinsicInst {
116 public:
117   CoroAllocInst *getCoroAlloc() {
118     for (User *U : users())
119       if (auto *CA = dyn_cast<CoroAllocInst>(U))
120         return CA;
121     return nullptr;
122   }
123 
124   IntrinsicInst *getCoroBegin() {
125     for (User *U : users())
126       if (auto *II = dyn_cast<IntrinsicInst>(U))
127         if (II->getIntrinsicID() == Intrinsic::coro_begin)
128           return II;
129     llvm_unreachable("no coro.begin associated with coro.id");
130   }
131 
132   // Methods to support type inquiry through isa, cast, and dyn_cast:
133   static bool classof(const IntrinsicInst *I) {
134     auto ID = I->getIntrinsicID();
135     return ID == Intrinsic::coro_id || ID == Intrinsic::coro_id_retcon ||
136            ID == Intrinsic::coro_id_retcon_once ||
137            ID == Intrinsic::coro_id_async;
138   }
139 
140   static bool classof(const Value *V) {
141     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
142   }
143 };
144 
145 /// This represents the llvm.coro.id instruction.
146 class LLVM_LIBRARY_VISIBILITY CoroIdInst : public AnyCoroIdInst {
147   enum { AlignArg, PromiseArg, CoroutineArg, InfoArg };
148 
149 public:
150   AllocaInst *getPromise() const {
151     Value *Arg = getArgOperand(PromiseArg);
152     return isa<ConstantPointerNull>(Arg)
153                ? nullptr
154                : cast<AllocaInst>(Arg->stripPointerCasts());
155   }
156 
157   void clearPromise() {
158     Value *Arg = getArgOperand(PromiseArg);
159     setArgOperand(PromiseArg, ConstantPointerNull::get(
160                                   PointerType::getUnqual(getContext())));
161     if (isa<AllocaInst>(Arg))
162       return;
163     assert((isa<BitCastInst>(Arg) || isa<GetElementPtrInst>(Arg)) &&
164            "unexpected instruction designating the promise");
165     // TODO: Add a check that any remaining users of Inst are after coro.begin
166     // or add code to move the users after coro.begin.
167     auto *Inst = cast<Instruction>(Arg);
168     if (Inst->use_empty()) {
169       Inst->eraseFromParent();
170       return;
171     }
172     Inst->moveBefore(getCoroBegin()->getNextNode());
173   }
174 
175   // Info argument of coro.id is
176   //   fresh out of the frontend: null ;
177   //   outlined                 : {Init, Return, Susp1, Susp2, ...} ;
178   //   postsplit                : [resume, destroy, cleanup] ;
179   //
180   // If parts of the coroutine were outlined to protect against undesirable
181   // code motion, these functions will be stored in a struct literal referred to
182   // by the Info parameter. Note: this is only needed before coroutine is split.
183   //
184   // After coroutine is split, resume functions are stored in an array
185   // referred to by this parameter.
186 
187   struct Info {
188     ConstantStruct *OutlinedParts = nullptr;
189     ConstantArray *Resumers = nullptr;
190 
191     bool hasOutlinedParts() const { return OutlinedParts != nullptr; }
192     bool isPostSplit() const { return Resumers != nullptr; }
193     bool isPreSplit() const { return !isPostSplit(); }
194   };
195   Info getInfo() const {
196     Info Result;
197     auto *GV = dyn_cast<GlobalVariable>(getRawInfo());
198     if (!GV)
199       return Result;
200 
201     assert(GV->isConstant() && GV->hasDefinitiveInitializer());
202     Constant *Initializer = GV->getInitializer();
203     if ((Result.OutlinedParts = dyn_cast<ConstantStruct>(Initializer)))
204       return Result;
205 
206     Result.Resumers = cast<ConstantArray>(Initializer);
207     return Result;
208   }
209   Constant *getRawInfo() const {
210     return cast<Constant>(getArgOperand(InfoArg)->stripPointerCasts());
211   }
212 
213   void setInfo(Constant *C) { setArgOperand(InfoArg, C); }
214 
215   Function *getCoroutine() const {
216     return cast<Function>(getArgOperand(CoroutineArg)->stripPointerCasts());
217   }
218   void setCoroutineSelf() {
219     assert(isa<ConstantPointerNull>(getArgOperand(CoroutineArg)) &&
220            "Coroutine argument is already assigned");
221     setArgOperand(CoroutineArg, getFunction());
222   }
223 
224   // Methods to support type inquiry through isa, cast, and dyn_cast:
225   static bool classof(const IntrinsicInst *I) {
226     return I->getIntrinsicID() == Intrinsic::coro_id;
227   }
228   static bool classof(const Value *V) {
229     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
230   }
231 };
232 
233 /// This represents either the llvm.coro.id.retcon or
234 /// llvm.coro.id.retcon.once instruction.
235 class LLVM_LIBRARY_VISIBILITY AnyCoroIdRetconInst : public AnyCoroIdInst {
236   enum { SizeArg, AlignArg, StorageArg, PrototypeArg, AllocArg, DeallocArg };
237 
238 public:
239   void checkWellFormed() const;
240 
241   uint64_t getStorageSize() const {
242     return cast<ConstantInt>(getArgOperand(SizeArg))->getZExtValue();
243   }
244 
245   Align getStorageAlignment() const {
246     return cast<ConstantInt>(getArgOperand(AlignArg))->getAlignValue();
247   }
248 
249   Value *getStorage() const {
250     return getArgOperand(StorageArg);
251   }
252 
253   /// Return the prototype for the continuation function.  The type,
254   /// attributes, and calling convention of the continuation function(s)
255   /// are taken from this declaration.
256   Function *getPrototype() const {
257     return cast<Function>(getArgOperand(PrototypeArg)->stripPointerCasts());
258   }
259 
260   /// Return the function to use for allocating memory.
261   Function *getAllocFunction() const {
262     return cast<Function>(getArgOperand(AllocArg)->stripPointerCasts());
263   }
264 
265   /// Return the function to use for deallocating memory.
266   Function *getDeallocFunction() const {
267     return cast<Function>(getArgOperand(DeallocArg)->stripPointerCasts());
268   }
269 
270   // Methods to support type inquiry through isa, cast, and dyn_cast:
271   static bool classof(const IntrinsicInst *I) {
272     auto ID = I->getIntrinsicID();
273     return ID == Intrinsic::coro_id_retcon
274         || ID == Intrinsic::coro_id_retcon_once;
275   }
276   static bool classof(const Value *V) {
277     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
278   }
279 };
280 
281 /// This represents the llvm.coro.id.retcon instruction.
282 class LLVM_LIBRARY_VISIBILITY CoroIdRetconInst
283     : public AnyCoroIdRetconInst {
284 public:
285   // Methods to support type inquiry through isa, cast, and dyn_cast:
286   static bool classof(const IntrinsicInst *I) {
287     return I->getIntrinsicID() == Intrinsic::coro_id_retcon;
288   }
289   static bool classof(const Value *V) {
290     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
291   }
292 };
293 
294 /// This represents the llvm.coro.id.retcon.once instruction.
295 class LLVM_LIBRARY_VISIBILITY CoroIdRetconOnceInst
296     : public AnyCoroIdRetconInst {
297 public:
298   // Methods to support type inquiry through isa, cast, and dyn_cast:
299   static bool classof(const IntrinsicInst *I) {
300     return I->getIntrinsicID() == Intrinsic::coro_id_retcon_once;
301   }
302   static bool classof(const Value *V) {
303     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
304   }
305 };
306 
307 /// This represents the llvm.coro.id.async instruction.
308 class LLVM_LIBRARY_VISIBILITY CoroIdAsyncInst : public AnyCoroIdInst {
309   enum { SizeArg, AlignArg, StorageArg, AsyncFuncPtrArg };
310 
311 public:
312   void checkWellFormed() const;
313 
314   /// The initial async function context size. The fields of which are reserved
315   /// for use by the frontend. The frame will be allocated as a tail of this
316   /// context.
317   uint64_t getStorageSize() const {
318     return cast<ConstantInt>(getArgOperand(SizeArg))->getZExtValue();
319   }
320 
321   /// The alignment of the initial async function context.
322   Align getStorageAlignment() const {
323     return cast<ConstantInt>(getArgOperand(AlignArg))->getAlignValue();
324   }
325 
326   /// The async context parameter.
327   Value *getStorage() const {
328     return getParent()->getParent()->getArg(getStorageArgumentIndex());
329   }
330 
331   unsigned getStorageArgumentIndex() const {
332     auto *Arg = cast<ConstantInt>(getArgOperand(StorageArg));
333     return Arg->getZExtValue();
334   }
335 
336   /// Return the async function pointer address. This should be the address of
337   /// a async function pointer struct for the current async function.
338   /// struct async_function_pointer {
339   ///   uint32_t context_size;
340   ///   uint32_t relative_async_function_pointer;
341   ///  };
342   GlobalVariable *getAsyncFunctionPointer() const {
343     return cast<GlobalVariable>(
344         getArgOperand(AsyncFuncPtrArg)->stripPointerCasts());
345   }
346 
347   // Methods to support type inquiry through isa, cast, and dyn_cast:
348   static bool classof(const IntrinsicInst *I) {
349     auto ID = I->getIntrinsicID();
350     return ID == Intrinsic::coro_id_async;
351   }
352 
353   static bool classof(const Value *V) {
354     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
355   }
356 };
357 
358 /// This represents the llvm.coro.context.alloc instruction.
359 class LLVM_LIBRARY_VISIBILITY CoroAsyncContextAllocInst : public IntrinsicInst {
360   enum { AsyncFuncPtrArg };
361 
362 public:
363   GlobalVariable *getAsyncFunctionPointer() const {
364     return cast<GlobalVariable>(
365         getArgOperand(AsyncFuncPtrArg)->stripPointerCasts());
366   }
367 
368   // Methods to support type inquiry through isa, cast, and dyn_cast:
369   static bool classof(const IntrinsicInst *I) {
370     return I->getIntrinsicID() == Intrinsic::coro_async_context_alloc;
371   }
372   static bool classof(const Value *V) {
373     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
374   }
375 };
376 
377 /// This represents the llvm.coro.context.dealloc instruction.
378 class LLVM_LIBRARY_VISIBILITY CoroAsyncContextDeallocInst
379     : public IntrinsicInst {
380   enum { AsyncContextArg };
381 
382 public:
383   Value *getAsyncContext() const {
384     return getArgOperand(AsyncContextArg)->stripPointerCasts();
385   }
386 
387   // Methods to support type inquiry through isa, cast, and dyn_cast:
388   static bool classof(const IntrinsicInst *I) {
389     return I->getIntrinsicID() == Intrinsic::coro_async_context_dealloc;
390   }
391   static bool classof(const Value *V) {
392     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
393   }
394 };
395 
396 /// This represents the llvm.coro.async.resume instruction.
397 /// During lowering this is replaced by the resume function of a suspend point
398 /// (the continuation function).
399 class LLVM_LIBRARY_VISIBILITY CoroAsyncResumeInst : public IntrinsicInst {
400 public:
401   // Methods to support type inquiry through isa, cast, and dyn_cast:
402   static bool classof(const IntrinsicInst *I) {
403     return I->getIntrinsicID() == Intrinsic::coro_async_resume;
404   }
405   static bool classof(const Value *V) {
406     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
407   }
408 };
409 
410 /// This represents the llvm.coro.async.size.replace instruction.
411 class LLVM_LIBRARY_VISIBILITY CoroAsyncSizeReplace : public IntrinsicInst {
412 public:
413   // Methods to support type inquiry through isa, cast, and dyn_cast:
414   static bool classof(const IntrinsicInst *I) {
415     return I->getIntrinsicID() == Intrinsic::coro_async_size_replace;
416   }
417   static bool classof(const Value *V) {
418     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
419   }
420 };
421 
422 /// This represents the llvm.coro.frame instruction.
423 class LLVM_LIBRARY_VISIBILITY CoroFrameInst : public IntrinsicInst {
424 public:
425   // Methods to support type inquiry through isa, cast, and dyn_cast:
426   static bool classof(const IntrinsicInst *I) {
427     return I->getIntrinsicID() == Intrinsic::coro_frame;
428   }
429   static bool classof(const Value *V) {
430     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
431   }
432 };
433 
434 /// This represents the llvm.coro.free instruction.
435 class LLVM_LIBRARY_VISIBILITY CoroFreeInst : public IntrinsicInst {
436   enum { IdArg, FrameArg };
437 
438 public:
439   Value *getFrame() const { return getArgOperand(FrameArg); }
440 
441   // Methods to support type inquiry through isa, cast, and dyn_cast:
442   static bool classof(const IntrinsicInst *I) {
443     return I->getIntrinsicID() == Intrinsic::coro_free;
444   }
445   static bool classof(const Value *V) {
446     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
447   }
448 };
449 
450 /// This class represents the llvm.coro.begin instruction.
451 class LLVM_LIBRARY_VISIBILITY CoroBeginInst : public IntrinsicInst {
452   enum { IdArg, MemArg };
453 
454 public:
455   AnyCoroIdInst *getId() const {
456     return cast<AnyCoroIdInst>(getArgOperand(IdArg));
457   }
458 
459   Value *getMem() const { return getArgOperand(MemArg); }
460 
461   // Methods for support type inquiry through isa, cast, and dyn_cast:
462   static bool classof(const IntrinsicInst *I) {
463     return I->getIntrinsicID() == Intrinsic::coro_begin;
464   }
465   static bool classof(const Value *V) {
466     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
467   }
468 };
469 
470 /// This represents the llvm.coro.save instruction.
471 class LLVM_LIBRARY_VISIBILITY CoroSaveInst : public IntrinsicInst {
472 public:
473   // Methods to support type inquiry through isa, cast, and dyn_cast:
474   static bool classof(const IntrinsicInst *I) {
475     return I->getIntrinsicID() == Intrinsic::coro_save;
476   }
477   static bool classof(const Value *V) {
478     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
479   }
480 };
481 
482 /// This represents the llvm.coro.promise instruction.
483 class LLVM_LIBRARY_VISIBILITY CoroPromiseInst : public IntrinsicInst {
484   enum { FrameArg, AlignArg, FromArg };
485 
486 public:
487   /// Are we translating from the frame to the promise (false) or from
488   /// the promise to the frame (true)?
489   bool isFromPromise() const {
490     return cast<Constant>(getArgOperand(FromArg))->isOneValue();
491   }
492 
493   /// The required alignment of the promise.  This must match the
494   /// alignment of the promise alloca in the coroutine.
495   Align getAlignment() const {
496     return cast<ConstantInt>(getArgOperand(AlignArg))->getAlignValue();
497   }
498 
499   // Methods to support type inquiry through isa, cast, and dyn_cast:
500   static bool classof(const IntrinsicInst *I) {
501     return I->getIntrinsicID() == Intrinsic::coro_promise;
502   }
503   static bool classof(const Value *V) {
504     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
505   }
506 };
507 
508 class LLVM_LIBRARY_VISIBILITY AnyCoroSuspendInst : public IntrinsicInst {
509 public:
510   CoroSaveInst *getCoroSave() const;
511 
512   // Methods to support type inquiry through isa, cast, and dyn_cast:
513   static bool classof(const IntrinsicInst *I) {
514     return I->getIntrinsicID() == Intrinsic::coro_suspend ||
515            I->getIntrinsicID() == Intrinsic::coro_suspend_async ||
516            I->getIntrinsicID() == Intrinsic::coro_suspend_retcon;
517   }
518   static bool classof(const Value *V) {
519     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
520   }
521 };
522 
523 /// This represents the llvm.coro.suspend instruction.
524 class LLVM_LIBRARY_VISIBILITY CoroSuspendInst : public AnyCoroSuspendInst {
525   enum { SaveArg, FinalArg };
526 
527 public:
528   CoroSaveInst *getCoroSave() const {
529     Value *Arg = getArgOperand(SaveArg);
530     if (auto *SI = dyn_cast<CoroSaveInst>(Arg))
531       return SI;
532     assert(isa<ConstantTokenNone>(Arg));
533     return nullptr;
534   }
535 
536   bool isFinal() const {
537     return cast<Constant>(getArgOperand(FinalArg))->isOneValue();
538   }
539 
540   // Methods to support type inquiry through isa, cast, and dyn_cast:
541   static bool classof(const IntrinsicInst *I) {
542     return I->getIntrinsicID() == Intrinsic::coro_suspend;
543   }
544   static bool classof(const Value *V) {
545     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
546   }
547 };
548 
549 inline CoroSaveInst *AnyCoroSuspendInst::getCoroSave() const {
550   if (auto Suspend = dyn_cast<CoroSuspendInst>(this))
551     return Suspend->getCoroSave();
552   return nullptr;
553 }
554 
555 /// This represents the llvm.coro.suspend.async instruction.
556 class LLVM_LIBRARY_VISIBILITY CoroSuspendAsyncInst : public AnyCoroSuspendInst {
557 public:
558   enum {
559     StorageArgNoArg,
560     ResumeFunctionArg,
561     AsyncContextProjectionArg,
562     MustTailCallFuncArg
563   };
564 
565   void checkWellFormed() const;
566 
567   unsigned getStorageArgumentIndex() const {
568     auto *Arg = cast<ConstantInt>(getArgOperand(StorageArgNoArg));
569     return Arg->getZExtValue();
570   }
571 
572   Function *getAsyncContextProjectionFunction() const {
573     return cast<Function>(
574         getArgOperand(AsyncContextProjectionArg)->stripPointerCasts());
575   }
576 
577   CoroAsyncResumeInst *getResumeFunction() const {
578     return cast<CoroAsyncResumeInst>(
579         getArgOperand(ResumeFunctionArg)->stripPointerCasts());
580   }
581 
582   Function *getMustTailCallFunction() const {
583     return cast<Function>(
584         getArgOperand(MustTailCallFuncArg)->stripPointerCasts());
585   }
586 
587   // Methods to support type inquiry through isa, cast, and dyn_cast:
588   static bool classof(const IntrinsicInst *I) {
589     return I->getIntrinsicID() == Intrinsic::coro_suspend_async;
590   }
591   static bool classof(const Value *V) {
592     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
593   }
594 };
595 
596 /// This represents the llvm.coro.suspend.retcon instruction.
597 class LLVM_LIBRARY_VISIBILITY CoroSuspendRetconInst : public AnyCoroSuspendInst {
598 public:
599   op_iterator value_begin() { return arg_begin(); }
600   const_op_iterator value_begin() const { return arg_begin(); }
601 
602   op_iterator value_end() { return arg_end(); }
603   const_op_iterator value_end() const { return arg_end(); }
604 
605   iterator_range<op_iterator> value_operands() {
606     return make_range(value_begin(), value_end());
607   }
608   iterator_range<const_op_iterator> value_operands() const {
609     return make_range(value_begin(), value_end());
610   }
611 
612   // Methods to support type inquiry through isa, cast, and dyn_cast:
613   static bool classof(const IntrinsicInst *I) {
614     return I->getIntrinsicID() == Intrinsic::coro_suspend_retcon;
615   }
616   static bool classof(const Value *V) {
617     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
618   }
619 };
620 
621 /// This represents the llvm.coro.size instruction.
622 class LLVM_LIBRARY_VISIBILITY CoroSizeInst : public IntrinsicInst {
623 public:
624   // Methods to support type inquiry through isa, cast, and dyn_cast:
625   static bool classof(const IntrinsicInst *I) {
626     return I->getIntrinsicID() == Intrinsic::coro_size;
627   }
628   static bool classof(const Value *V) {
629     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
630   }
631 };
632 
633 /// This represents the llvm.coro.align instruction.
634 class LLVM_LIBRARY_VISIBILITY CoroAlignInst : public IntrinsicInst {
635 public:
636   // Methods to support type inquiry through isa, cast, and dyn_cast:
637   static bool classof(const IntrinsicInst *I) {
638     return I->getIntrinsicID() == Intrinsic::coro_align;
639   }
640   static bool classof(const Value *V) {
641     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
642   }
643 };
644 
645 /// This represents the llvm.end.results instruction.
646 class LLVM_LIBRARY_VISIBILITY CoroEndResults : public IntrinsicInst {
647 public:
648   op_iterator retval_begin() { return arg_begin(); }
649   const_op_iterator retval_begin() const { return arg_begin(); }
650 
651   op_iterator retval_end() { return arg_end(); }
652   const_op_iterator retval_end() const { return arg_end(); }
653 
654   iterator_range<op_iterator> return_values() {
655     return make_range(retval_begin(), retval_end());
656   }
657   iterator_range<const_op_iterator> return_values() const {
658     return make_range(retval_begin(), retval_end());
659   }
660 
661   unsigned numReturns() const {
662     return std::distance(retval_begin(), retval_end());
663   }
664 
665   // Methods to support type inquiry through isa, cast, and dyn_cast:
666   static bool classof(const IntrinsicInst *I) {
667     return I->getIntrinsicID() == Intrinsic::coro_end_results;
668   }
669   static bool classof(const Value *V) {
670     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
671   }
672 };
673 
674 class LLVM_LIBRARY_VISIBILITY AnyCoroEndInst : public IntrinsicInst {
675   enum { FrameArg, UnwindArg, TokenArg };
676 
677 public:
678   bool isFallthrough() const { return !isUnwind(); }
679   bool isUnwind() const {
680     return cast<Constant>(getArgOperand(UnwindArg))->isOneValue();
681   }
682 
683   bool hasResults() const {
684     return !isa<ConstantTokenNone>(getArgOperand(TokenArg));
685   }
686 
687   CoroEndResults *getResults() const {
688     assert(hasResults());
689     return cast<CoroEndResults>(getArgOperand(TokenArg));
690   }
691 
692   // Methods to support type inquiry through isa, cast, and dyn_cast:
693   static bool classof(const IntrinsicInst *I) {
694     auto ID = I->getIntrinsicID();
695     return ID == Intrinsic::coro_end || ID == Intrinsic::coro_end_async;
696   }
697   static bool classof(const Value *V) {
698     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
699   }
700 };
701 
702 /// This represents the llvm.coro.end instruction.
703 class LLVM_LIBRARY_VISIBILITY CoroEndInst : public AnyCoroEndInst {
704 public:
705   // Methods to support type inquiry through isa, cast, and dyn_cast:
706   static bool classof(const IntrinsicInst *I) {
707     return I->getIntrinsicID() == Intrinsic::coro_end;
708   }
709   static bool classof(const Value *V) {
710     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
711   }
712 };
713 
714 /// This represents the llvm.coro.end instruction.
715 class LLVM_LIBRARY_VISIBILITY CoroAsyncEndInst : public AnyCoroEndInst {
716   enum { FrameArg, UnwindArg, MustTailCallFuncArg };
717 
718 public:
719   void checkWellFormed() const;
720 
721   Function *getMustTailCallFunction() const {
722     if (arg_size() < 3)
723       return nullptr;
724 
725     return cast<Function>(
726         getArgOperand(MustTailCallFuncArg)->stripPointerCasts());
727   }
728 
729   // Methods to support type inquiry through isa, cast, and dyn_cast:
730   static bool classof(const IntrinsicInst *I) {
731     return I->getIntrinsicID() == Intrinsic::coro_end_async;
732   }
733   static bool classof(const Value *V) {
734     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
735   }
736 };
737 
738 /// This represents the llvm.coro.alloca.alloc instruction.
739 class LLVM_LIBRARY_VISIBILITY CoroAllocaAllocInst : public IntrinsicInst {
740   enum { SizeArg, AlignArg };
741 public:
742   Value *getSize() const {
743     return getArgOperand(SizeArg);
744   }
745   Align getAlignment() const {
746     return cast<ConstantInt>(getArgOperand(AlignArg))->getAlignValue();
747   }
748 
749   // Methods to support type inquiry through isa, cast, and dyn_cast:
750   static bool classof(const IntrinsicInst *I) {
751     return I->getIntrinsicID() == Intrinsic::coro_alloca_alloc;
752   }
753   static bool classof(const Value *V) {
754     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
755   }
756 };
757 
758 /// This represents the llvm.coro.alloca.get instruction.
759 class LLVM_LIBRARY_VISIBILITY CoroAllocaGetInst : public IntrinsicInst {
760   enum { AllocArg };
761 public:
762   CoroAllocaAllocInst *getAlloc() const {
763     return cast<CoroAllocaAllocInst>(getArgOperand(AllocArg));
764   }
765 
766   // Methods to support type inquiry through isa, cast, and dyn_cast:
767   static bool classof(const IntrinsicInst *I) {
768     return I->getIntrinsicID() == Intrinsic::coro_alloca_get;
769   }
770   static bool classof(const Value *V) {
771     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
772   }
773 };
774 
775 /// This represents the llvm.coro.alloca.free instruction.
776 class LLVM_LIBRARY_VISIBILITY CoroAllocaFreeInst : public IntrinsicInst {
777   enum { AllocArg };
778 public:
779   CoroAllocaAllocInst *getAlloc() const {
780     return cast<CoroAllocaAllocInst>(getArgOperand(AllocArg));
781   }
782 
783   // Methods to support type inquiry through isa, cast, and dyn_cast:
784   static bool classof(const IntrinsicInst *I) {
785     return I->getIntrinsicID() == Intrinsic::coro_alloca_free;
786   }
787   static bool classof(const Value *V) {
788     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
789   }
790 };
791 
792 } // End namespace llvm.
793 
794 #endif
795