1 //===-- CoroInstr.h - Coroutine Intrinsics Instruction Wrappers -*- C++ -*-===//
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
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:
12 // if (auto *SF = dyn_cast<CoroSubFnInst>(Inst))
13 // ... SF->getFrame() ...
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
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 //===----------------------------------------------------------------------===//
25 #ifndef LLVM_LIB_TRANSFORMS_COROUTINES_COROINSTR_H
26 #define LLVM_LIB_TRANSFORMS_COROUTINES_COROINSTR_H
28 #include "llvm/IR/GlobalVariable.h"
29 #include "llvm/IR/IntrinsicInst.h"
30 #include "llvm/Support/raw_ostream.h"
34 /// This class represents the llvm.coro.subfn.addr instruction.
35 class LLVM_LIBRARY_VISIBILITY CoroSubFnInst
: public IntrinsicInst
{
36 enum { FrameArg
, IndexArg
};
45 IndexFirst
= RestartTrigger
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
);
56 ConstantInt
*getRawIndex() const {
57 return cast
<ConstantInt
>(getArgOperand(IndexArg
));
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
;
64 static bool classof(const Value
*V
) {
65 return isa
<IntrinsicInst
>(V
) && classof(cast
<IntrinsicInst
>(V
));
69 /// This represents the llvm.coro.alloc instruction.
70 class LLVM_LIBRARY_VISIBILITY CoroAllocInst
: public IntrinsicInst
{
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
;
76 static bool classof(const Value
*V
) {
77 return isa
<IntrinsicInst
>(V
) && classof(cast
<IntrinsicInst
>(V
));
81 /// This represents a common base class for llvm.coro.id instructions.
82 class LLVM_LIBRARY_VISIBILITY AnyCoroIdInst
: public IntrinsicInst
{
84 CoroAllocInst
*getCoroAlloc() {
85 for (User
*U
: users())
86 if (auto *CA
= dyn_cast
<CoroAllocInst
>(U
))
91 IntrinsicInst
*getCoroBegin() {
92 for (User
*U
: users())
93 if (auto *II
= dyn_cast
<IntrinsicInst
>(U
))
94 if (II
->getIntrinsicID() == Intrinsic::coro_begin
)
96 llvm_unreachable("no coro.begin associated with coro.id");
99 // Methods to support type inquiry through isa, cast, and dyn_cast:
100 static bool classof(const IntrinsicInst
*I
) {
101 auto ID
= I
->getIntrinsicID();
102 return ID
== Intrinsic::coro_id
|| ID
== Intrinsic::coro_id_retcon
||
103 ID
== Intrinsic::coro_id_retcon_once
||
104 ID
== Intrinsic::coro_id_async
;
107 static bool classof(const Value
*V
) {
108 return isa
<IntrinsicInst
>(V
) && classof(cast
<IntrinsicInst
>(V
));
112 /// This represents the llvm.coro.id instruction.
113 class LLVM_LIBRARY_VISIBILITY CoroIdInst
: public AnyCoroIdInst
{
114 enum { AlignArg
, PromiseArg
, CoroutineArg
, InfoArg
};
117 AllocaInst
*getPromise() const {
118 Value
*Arg
= getArgOperand(PromiseArg
);
119 return isa
<ConstantPointerNull
>(Arg
)
121 : cast
<AllocaInst
>(Arg
->stripPointerCasts());
124 void clearPromise() {
125 Value
*Arg
= getArgOperand(PromiseArg
);
126 setArgOperand(PromiseArg
, ConstantPointerNull::get(
127 PointerType::getUnqual(getContext())));
128 if (isa
<AllocaInst
>(Arg
))
130 assert((isa
<BitCastInst
>(Arg
) || isa
<GetElementPtrInst
>(Arg
)) &&
131 "unexpected instruction designating the promise");
132 // TODO: Add a check that any remaining users of Inst are after coro.begin
133 // or add code to move the users after coro.begin.
134 auto *Inst
= cast
<Instruction
>(Arg
);
135 if (Inst
->use_empty()) {
136 Inst
->eraseFromParent();
139 Inst
->moveBefore(getCoroBegin()->getNextNode());
142 // Info argument of coro.id is
143 // fresh out of the frontend: null ;
144 // outlined : {Init, Return, Susp1, Susp2, ...} ;
145 // postsplit : [resume, destroy, cleanup] ;
147 // If parts of the coroutine were outlined to protect against undesirable
148 // code motion, these functions will be stored in a struct literal referred to
149 // by the Info parameter. Note: this is only needed before coroutine is split.
151 // After coroutine is split, resume functions are stored in an array
152 // referred to by this parameter.
155 ConstantStruct
*OutlinedParts
= nullptr;
156 ConstantArray
*Resumers
= nullptr;
158 bool hasOutlinedParts() const { return OutlinedParts
!= nullptr; }
159 bool isPostSplit() const { return Resumers
!= nullptr; }
160 bool isPreSplit() const { return !isPostSplit(); }
162 Info
getInfo() const {
164 auto *GV
= dyn_cast
<GlobalVariable
>(getRawInfo());
168 assert(GV
->isConstant() && GV
->hasDefinitiveInitializer());
169 Constant
*Initializer
= GV
->getInitializer();
170 if ((Result
.OutlinedParts
= dyn_cast
<ConstantStruct
>(Initializer
)))
173 Result
.Resumers
= cast
<ConstantArray
>(Initializer
);
176 Constant
*getRawInfo() const {
177 return cast
<Constant
>(getArgOperand(InfoArg
)->stripPointerCasts());
180 void setInfo(Constant
*C
) { setArgOperand(InfoArg
, C
); }
182 Function
*getCoroutine() const {
183 return cast
<Function
>(getArgOperand(CoroutineArg
)->stripPointerCasts());
185 void setCoroutineSelf() {
186 assert(isa
<ConstantPointerNull
>(getArgOperand(CoroutineArg
)) &&
187 "Coroutine argument is already assigned");
188 setArgOperand(CoroutineArg
, getFunction());
191 // Methods to support type inquiry through isa, cast, and dyn_cast:
192 static bool classof(const IntrinsicInst
*I
) {
193 return I
->getIntrinsicID() == Intrinsic::coro_id
;
195 static bool classof(const Value
*V
) {
196 return isa
<IntrinsicInst
>(V
) && classof(cast
<IntrinsicInst
>(V
));
200 /// This represents either the llvm.coro.id.retcon or
201 /// llvm.coro.id.retcon.once instruction.
202 class LLVM_LIBRARY_VISIBILITY AnyCoroIdRetconInst
: public AnyCoroIdInst
{
203 enum { SizeArg
, AlignArg
, StorageArg
, PrototypeArg
, AllocArg
, DeallocArg
};
206 void checkWellFormed() const;
208 uint64_t getStorageSize() const {
209 return cast
<ConstantInt
>(getArgOperand(SizeArg
))->getZExtValue();
212 Align
getStorageAlignment() const {
213 return cast
<ConstantInt
>(getArgOperand(AlignArg
))->getAlignValue();
216 Value
*getStorage() const {
217 return getArgOperand(StorageArg
);
220 /// Return the prototype for the continuation function. The type,
221 /// attributes, and calling convention of the continuation function(s)
222 /// are taken from this declaration.
223 Function
*getPrototype() const {
224 return cast
<Function
>(getArgOperand(PrototypeArg
)->stripPointerCasts());
227 /// Return the function to use for allocating memory.
228 Function
*getAllocFunction() const {
229 return cast
<Function
>(getArgOperand(AllocArg
)->stripPointerCasts());
232 /// Return the function to use for deallocating memory.
233 Function
*getDeallocFunction() const {
234 return cast
<Function
>(getArgOperand(DeallocArg
)->stripPointerCasts());
237 // Methods to support type inquiry through isa, cast, and dyn_cast:
238 static bool classof(const IntrinsicInst
*I
) {
239 auto ID
= I
->getIntrinsicID();
240 return ID
== Intrinsic::coro_id_retcon
241 || ID
== Intrinsic::coro_id_retcon_once
;
243 static bool classof(const Value
*V
) {
244 return isa
<IntrinsicInst
>(V
) && classof(cast
<IntrinsicInst
>(V
));
248 /// This represents the llvm.coro.id.retcon instruction.
249 class LLVM_LIBRARY_VISIBILITY CoroIdRetconInst
250 : public AnyCoroIdRetconInst
{
252 // Methods to support type inquiry through isa, cast, and dyn_cast:
253 static bool classof(const IntrinsicInst
*I
) {
254 return I
->getIntrinsicID() == Intrinsic::coro_id_retcon
;
256 static bool classof(const Value
*V
) {
257 return isa
<IntrinsicInst
>(V
) && classof(cast
<IntrinsicInst
>(V
));
261 /// This represents the llvm.coro.id.retcon.once instruction.
262 class LLVM_LIBRARY_VISIBILITY CoroIdRetconOnceInst
263 : public AnyCoroIdRetconInst
{
265 // Methods to support type inquiry through isa, cast, and dyn_cast:
266 static bool classof(const IntrinsicInst
*I
) {
267 return I
->getIntrinsicID() == Intrinsic::coro_id_retcon_once
;
269 static bool classof(const Value
*V
) {
270 return isa
<IntrinsicInst
>(V
) && classof(cast
<IntrinsicInst
>(V
));
274 /// This represents the llvm.coro.id.async instruction.
275 class LLVM_LIBRARY_VISIBILITY CoroIdAsyncInst
: public AnyCoroIdInst
{
276 enum { SizeArg
, AlignArg
, StorageArg
, AsyncFuncPtrArg
};
279 void checkWellFormed() const;
281 /// The initial async function context size. The fields of which are reserved
282 /// for use by the frontend. The frame will be allocated as a tail of this
284 uint64_t getStorageSize() const {
285 return cast
<ConstantInt
>(getArgOperand(SizeArg
))->getZExtValue();
288 /// The alignment of the initial async function context.
289 Align
getStorageAlignment() const {
290 return cast
<ConstantInt
>(getArgOperand(AlignArg
))->getAlignValue();
293 /// The async context parameter.
294 Value
*getStorage() const {
295 return getParent()->getParent()->getArg(getStorageArgumentIndex());
298 unsigned getStorageArgumentIndex() const {
299 auto *Arg
= cast
<ConstantInt
>(getArgOperand(StorageArg
));
300 return Arg
->getZExtValue();
303 /// Return the async function pointer address. This should be the address of
304 /// a async function pointer struct for the current async function.
305 /// struct async_function_pointer {
306 /// uint32_t context_size;
307 /// uint32_t relative_async_function_pointer;
309 GlobalVariable
*getAsyncFunctionPointer() const {
310 return cast
<GlobalVariable
>(
311 getArgOperand(AsyncFuncPtrArg
)->stripPointerCasts());
314 // Methods to support type inquiry through isa, cast, and dyn_cast:
315 static bool classof(const IntrinsicInst
*I
) {
316 auto ID
= I
->getIntrinsicID();
317 return ID
== Intrinsic::coro_id_async
;
320 static bool classof(const Value
*V
) {
321 return isa
<IntrinsicInst
>(V
) && classof(cast
<IntrinsicInst
>(V
));
325 /// This represents the llvm.coro.context.alloc instruction.
326 class LLVM_LIBRARY_VISIBILITY CoroAsyncContextAllocInst
: public IntrinsicInst
{
327 enum { AsyncFuncPtrArg
};
330 GlobalVariable
*getAsyncFunctionPointer() const {
331 return cast
<GlobalVariable
>(
332 getArgOperand(AsyncFuncPtrArg
)->stripPointerCasts());
335 // Methods to support type inquiry through isa, cast, and dyn_cast:
336 static bool classof(const IntrinsicInst
*I
) {
337 return I
->getIntrinsicID() == Intrinsic::coro_async_context_alloc
;
339 static bool classof(const Value
*V
) {
340 return isa
<IntrinsicInst
>(V
) && classof(cast
<IntrinsicInst
>(V
));
344 /// This represents the llvm.coro.context.dealloc instruction.
345 class LLVM_LIBRARY_VISIBILITY CoroAsyncContextDeallocInst
346 : public IntrinsicInst
{
347 enum { AsyncContextArg
};
350 Value
*getAsyncContext() const {
351 return getArgOperand(AsyncContextArg
)->stripPointerCasts();
354 // Methods to support type inquiry through isa, cast, and dyn_cast:
355 static bool classof(const IntrinsicInst
*I
) {
356 return I
->getIntrinsicID() == Intrinsic::coro_async_context_dealloc
;
358 static bool classof(const Value
*V
) {
359 return isa
<IntrinsicInst
>(V
) && classof(cast
<IntrinsicInst
>(V
));
363 /// This represents the llvm.coro.async.resume instruction.
364 /// During lowering this is replaced by the resume function of a suspend point
365 /// (the continuation function).
366 class LLVM_LIBRARY_VISIBILITY CoroAsyncResumeInst
: public IntrinsicInst
{
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_resume
;
372 static bool classof(const Value
*V
) {
373 return isa
<IntrinsicInst
>(V
) && classof(cast
<IntrinsicInst
>(V
));
377 /// This represents the llvm.coro.async.size.replace instruction.
378 class LLVM_LIBRARY_VISIBILITY CoroAsyncSizeReplace
: public IntrinsicInst
{
380 // Methods to support type inquiry through isa, cast, and dyn_cast:
381 static bool classof(const IntrinsicInst
*I
) {
382 return I
->getIntrinsicID() == Intrinsic::coro_async_size_replace
;
384 static bool classof(const Value
*V
) {
385 return isa
<IntrinsicInst
>(V
) && classof(cast
<IntrinsicInst
>(V
));
389 /// This represents the llvm.coro.frame instruction.
390 class LLVM_LIBRARY_VISIBILITY CoroFrameInst
: public IntrinsicInst
{
392 // Methods to support type inquiry through isa, cast, and dyn_cast:
393 static bool classof(const IntrinsicInst
*I
) {
394 return I
->getIntrinsicID() == Intrinsic::coro_frame
;
396 static bool classof(const Value
*V
) {
397 return isa
<IntrinsicInst
>(V
) && classof(cast
<IntrinsicInst
>(V
));
401 /// This represents the llvm.coro.free instruction.
402 class LLVM_LIBRARY_VISIBILITY CoroFreeInst
: public IntrinsicInst
{
403 enum { IdArg
, FrameArg
};
406 Value
*getFrame() const { return getArgOperand(FrameArg
); }
408 // Methods to support type inquiry through isa, cast, and dyn_cast:
409 static bool classof(const IntrinsicInst
*I
) {
410 return I
->getIntrinsicID() == Intrinsic::coro_free
;
412 static bool classof(const Value
*V
) {
413 return isa
<IntrinsicInst
>(V
) && classof(cast
<IntrinsicInst
>(V
));
417 /// This class represents the llvm.coro.begin instruction.
418 class LLVM_LIBRARY_VISIBILITY CoroBeginInst
: public IntrinsicInst
{
419 enum { IdArg
, MemArg
};
422 AnyCoroIdInst
*getId() const {
423 return cast
<AnyCoroIdInst
>(getArgOperand(IdArg
));
426 Value
*getMem() const { return getArgOperand(MemArg
); }
428 // Methods for support type inquiry through isa, cast, and dyn_cast:
429 static bool classof(const IntrinsicInst
*I
) {
430 return I
->getIntrinsicID() == Intrinsic::coro_begin
;
432 static bool classof(const Value
*V
) {
433 return isa
<IntrinsicInst
>(V
) && classof(cast
<IntrinsicInst
>(V
));
437 /// This represents the llvm.coro.save instruction.
438 class LLVM_LIBRARY_VISIBILITY CoroSaveInst
: public IntrinsicInst
{
440 // Methods to support type inquiry through isa, cast, and dyn_cast:
441 static bool classof(const IntrinsicInst
*I
) {
442 return I
->getIntrinsicID() == Intrinsic::coro_save
;
444 static bool classof(const Value
*V
) {
445 return isa
<IntrinsicInst
>(V
) && classof(cast
<IntrinsicInst
>(V
));
449 /// This represents the llvm.coro.promise instruction.
450 class LLVM_LIBRARY_VISIBILITY CoroPromiseInst
: public IntrinsicInst
{
451 enum { FrameArg
, AlignArg
, FromArg
};
454 /// Are we translating from the frame to the promise (false) or from
455 /// the promise to the frame (true)?
456 bool isFromPromise() const {
457 return cast
<Constant
>(getArgOperand(FromArg
))->isOneValue();
460 /// The required alignment of the promise. This must match the
461 /// alignment of the promise alloca in the coroutine.
462 Align
getAlignment() const {
463 return cast
<ConstantInt
>(getArgOperand(AlignArg
))->getAlignValue();
466 // Methods to support type inquiry through isa, cast, and dyn_cast:
467 static bool classof(const IntrinsicInst
*I
) {
468 return I
->getIntrinsicID() == Intrinsic::coro_promise
;
470 static bool classof(const Value
*V
) {
471 return isa
<IntrinsicInst
>(V
) && classof(cast
<IntrinsicInst
>(V
));
475 class LLVM_LIBRARY_VISIBILITY AnyCoroSuspendInst
: public IntrinsicInst
{
477 CoroSaveInst
*getCoroSave() const;
479 // Methods to support type inquiry through isa, cast, and dyn_cast:
480 static bool classof(const IntrinsicInst
*I
) {
481 return I
->getIntrinsicID() == Intrinsic::coro_suspend
||
482 I
->getIntrinsicID() == Intrinsic::coro_suspend_async
||
483 I
->getIntrinsicID() == Intrinsic::coro_suspend_retcon
;
485 static bool classof(const Value
*V
) {
486 return isa
<IntrinsicInst
>(V
) && classof(cast
<IntrinsicInst
>(V
));
490 /// This represents the llvm.coro.suspend instruction.
491 class LLVM_LIBRARY_VISIBILITY CoroSuspendInst
: public AnyCoroSuspendInst
{
492 enum { SaveArg
, FinalArg
};
495 CoroSaveInst
*getCoroSave() const {
496 Value
*Arg
= getArgOperand(SaveArg
);
497 if (auto *SI
= dyn_cast
<CoroSaveInst
>(Arg
))
499 assert(isa
<ConstantTokenNone
>(Arg
));
503 bool isFinal() const {
504 return cast
<Constant
>(getArgOperand(FinalArg
))->isOneValue();
507 // Methods to support type inquiry through isa, cast, and dyn_cast:
508 static bool classof(const IntrinsicInst
*I
) {
509 return I
->getIntrinsicID() == Intrinsic::coro_suspend
;
511 static bool classof(const Value
*V
) {
512 return isa
<IntrinsicInst
>(V
) && classof(cast
<IntrinsicInst
>(V
));
516 inline CoroSaveInst
*AnyCoroSuspendInst::getCoroSave() const {
517 if (auto Suspend
= dyn_cast
<CoroSuspendInst
>(this))
518 return Suspend
->getCoroSave();
522 /// This represents the llvm.coro.suspend.async instruction.
523 class LLVM_LIBRARY_VISIBILITY CoroSuspendAsyncInst
: public AnyCoroSuspendInst
{
528 AsyncContextProjectionArg
,
532 void checkWellFormed() const;
534 unsigned getStorageArgumentIndex() const {
535 auto *Arg
= cast
<ConstantInt
>(getArgOperand(StorageArgNoArg
));
536 return Arg
->getZExtValue();
539 Function
*getAsyncContextProjectionFunction() const {
540 return cast
<Function
>(
541 getArgOperand(AsyncContextProjectionArg
)->stripPointerCasts());
544 CoroAsyncResumeInst
*getResumeFunction() const {
545 return cast
<CoroAsyncResumeInst
>(
546 getArgOperand(ResumeFunctionArg
)->stripPointerCasts());
549 Function
*getMustTailCallFunction() const {
550 return cast
<Function
>(
551 getArgOperand(MustTailCallFuncArg
)->stripPointerCasts());
554 // Methods to support type inquiry through isa, cast, and dyn_cast:
555 static bool classof(const IntrinsicInst
*I
) {
556 return I
->getIntrinsicID() == Intrinsic::coro_suspend_async
;
558 static bool classof(const Value
*V
) {
559 return isa
<IntrinsicInst
>(V
) && classof(cast
<IntrinsicInst
>(V
));
563 /// This represents the llvm.coro.suspend.retcon instruction.
564 class LLVM_LIBRARY_VISIBILITY CoroSuspendRetconInst
: public AnyCoroSuspendInst
{
566 op_iterator
value_begin() { return arg_begin(); }
567 const_op_iterator
value_begin() const { return arg_begin(); }
569 op_iterator
value_end() { return arg_end(); }
570 const_op_iterator
value_end() const { return arg_end(); }
572 iterator_range
<op_iterator
> value_operands() {
573 return make_range(value_begin(), value_end());
575 iterator_range
<const_op_iterator
> value_operands() const {
576 return make_range(value_begin(), value_end());
579 // Methods to support type inquiry through isa, cast, and dyn_cast:
580 static bool classof(const IntrinsicInst
*I
) {
581 return I
->getIntrinsicID() == Intrinsic::coro_suspend_retcon
;
583 static bool classof(const Value
*V
) {
584 return isa
<IntrinsicInst
>(V
) && classof(cast
<IntrinsicInst
>(V
));
588 /// This represents the llvm.coro.size instruction.
589 class LLVM_LIBRARY_VISIBILITY CoroSizeInst
: public IntrinsicInst
{
591 // Methods to support type inquiry through isa, cast, and dyn_cast:
592 static bool classof(const IntrinsicInst
*I
) {
593 return I
->getIntrinsicID() == Intrinsic::coro_size
;
595 static bool classof(const Value
*V
) {
596 return isa
<IntrinsicInst
>(V
) && classof(cast
<IntrinsicInst
>(V
));
600 /// This represents the llvm.coro.align instruction.
601 class LLVM_LIBRARY_VISIBILITY CoroAlignInst
: public IntrinsicInst
{
603 // Methods to support type inquiry through isa, cast, and dyn_cast:
604 static bool classof(const IntrinsicInst
*I
) {
605 return I
->getIntrinsicID() == Intrinsic::coro_align
;
607 static bool classof(const Value
*V
) {
608 return isa
<IntrinsicInst
>(V
) && classof(cast
<IntrinsicInst
>(V
));
612 /// This represents the llvm.end.results instruction.
613 class LLVM_LIBRARY_VISIBILITY CoroEndResults
: public IntrinsicInst
{
615 op_iterator
retval_begin() { return arg_begin(); }
616 const_op_iterator
retval_begin() const { return arg_begin(); }
618 op_iterator
retval_end() { return arg_end(); }
619 const_op_iterator
retval_end() const { return arg_end(); }
621 iterator_range
<op_iterator
> return_values() {
622 return make_range(retval_begin(), retval_end());
624 iterator_range
<const_op_iterator
> return_values() const {
625 return make_range(retval_begin(), retval_end());
628 unsigned numReturns() const {
629 return std::distance(retval_begin(), retval_end());
632 // Methods to support type inquiry through isa, cast, and dyn_cast:
633 static bool classof(const IntrinsicInst
*I
) {
634 return I
->getIntrinsicID() == Intrinsic::coro_end_results
;
636 static bool classof(const Value
*V
) {
637 return isa
<IntrinsicInst
>(V
) && classof(cast
<IntrinsicInst
>(V
));
641 class LLVM_LIBRARY_VISIBILITY AnyCoroEndInst
: public IntrinsicInst
{
642 enum { FrameArg
, UnwindArg
, TokenArg
};
645 bool isFallthrough() const { return !isUnwind(); }
646 bool isUnwind() const {
647 return cast
<Constant
>(getArgOperand(UnwindArg
))->isOneValue();
650 bool hasResults() const {
651 return !isa
<ConstantTokenNone
>(getArgOperand(TokenArg
));
654 CoroEndResults
*getResults() const {
655 assert(hasResults());
656 return cast
<CoroEndResults
>(getArgOperand(TokenArg
));
659 // Methods to support type inquiry through isa, cast, and dyn_cast:
660 static bool classof(const IntrinsicInst
*I
) {
661 auto ID
= I
->getIntrinsicID();
662 return ID
== Intrinsic::coro_end
|| ID
== Intrinsic::coro_end_async
;
664 static bool classof(const Value
*V
) {
665 return isa
<IntrinsicInst
>(V
) && classof(cast
<IntrinsicInst
>(V
));
669 /// This represents the llvm.coro.end instruction.
670 class LLVM_LIBRARY_VISIBILITY CoroEndInst
: public AnyCoroEndInst
{
672 // Methods to support type inquiry through isa, cast, and dyn_cast:
673 static bool classof(const IntrinsicInst
*I
) {
674 return I
->getIntrinsicID() == Intrinsic::coro_end
;
676 static bool classof(const Value
*V
) {
677 return isa
<IntrinsicInst
>(V
) && classof(cast
<IntrinsicInst
>(V
));
681 /// This represents the llvm.coro.end instruction.
682 class LLVM_LIBRARY_VISIBILITY CoroAsyncEndInst
: public AnyCoroEndInst
{
683 enum { FrameArg
, UnwindArg
, MustTailCallFuncArg
};
686 void checkWellFormed() const;
688 Function
*getMustTailCallFunction() const {
692 return cast
<Function
>(
693 getArgOperand(MustTailCallFuncArg
)->stripPointerCasts());
696 // Methods to support type inquiry through isa, cast, and dyn_cast:
697 static bool classof(const IntrinsicInst
*I
) {
698 return I
->getIntrinsicID() == Intrinsic::coro_end_async
;
700 static bool classof(const Value
*V
) {
701 return isa
<IntrinsicInst
>(V
) && classof(cast
<IntrinsicInst
>(V
));
705 /// This represents the llvm.coro.alloca.alloc instruction.
706 class LLVM_LIBRARY_VISIBILITY CoroAllocaAllocInst
: public IntrinsicInst
{
707 enum { SizeArg
, AlignArg
};
709 Value
*getSize() const {
710 return getArgOperand(SizeArg
);
712 Align
getAlignment() const {
713 return cast
<ConstantInt
>(getArgOperand(AlignArg
))->getAlignValue();
716 // Methods to support type inquiry through isa, cast, and dyn_cast:
717 static bool classof(const IntrinsicInst
*I
) {
718 return I
->getIntrinsicID() == Intrinsic::coro_alloca_alloc
;
720 static bool classof(const Value
*V
) {
721 return isa
<IntrinsicInst
>(V
) && classof(cast
<IntrinsicInst
>(V
));
725 /// This represents the llvm.coro.alloca.get instruction.
726 class LLVM_LIBRARY_VISIBILITY CoroAllocaGetInst
: public IntrinsicInst
{
729 CoroAllocaAllocInst
*getAlloc() const {
730 return cast
<CoroAllocaAllocInst
>(getArgOperand(AllocArg
));
733 // Methods to support type inquiry through isa, cast, and dyn_cast:
734 static bool classof(const IntrinsicInst
*I
) {
735 return I
->getIntrinsicID() == Intrinsic::coro_alloca_get
;
737 static bool classof(const Value
*V
) {
738 return isa
<IntrinsicInst
>(V
) && classof(cast
<IntrinsicInst
>(V
));
742 /// This represents the llvm.coro.alloca.free instruction.
743 class LLVM_LIBRARY_VISIBILITY CoroAllocaFreeInst
: public IntrinsicInst
{
746 CoroAllocaAllocInst
*getAlloc() const {
747 return cast
<CoroAllocaAllocInst
>(getArgOperand(AllocArg
));
750 // Methods to support type inquiry through isa, cast, and dyn_cast:
751 static bool classof(const IntrinsicInst
*I
) {
752 return I
->getIntrinsicID() == Intrinsic::coro_alloca_free
;
754 static bool classof(const Value
*V
) {
755 return isa
<IntrinsicInst
>(V
) && classof(cast
<IntrinsicInst
>(V
));
759 } // End namespace llvm.