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
getFrame()48 Value *getFrame() const { return getArgOperand(FrameArg); }
getIndex()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
getRawIndex()56 ConstantInt *getRawIndex() const {
57 return cast<ConstantInt>(getArgOperand(IndexArg));
58 }
59
60 // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)61 static bool classof(const IntrinsicInst *I) {
62 return I->getIntrinsicID() == Intrinsic::coro_subfn_addr;
63 }
classof(const Value * V)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:
classof(const IntrinsicInst * I)73 static bool classof(const IntrinsicInst *I) {
74 return I->getIntrinsicID() == Intrinsic::coro_alloc;
75 }
classof(const Value * V)76 static bool classof(const Value *V) {
77 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
78 }
79 };
80
81 /// This represents a common base class for llvm.coro.id instructions.
82 class LLVM_LIBRARY_VISIBILITY AnyCoroIdInst : public IntrinsicInst {
83 public:
getCoroAlloc()84 CoroAllocInst *getCoroAlloc() {
85 for (User *U : users())
86 if (auto *CA = dyn_cast<CoroAllocInst>(U))
87 return CA;
88 return nullptr;
89 }
90
getCoroBegin()91 IntrinsicInst *getCoroBegin() {
92 for (User *U : users())
93 if (auto *II = dyn_cast<IntrinsicInst>(U))
94 if (II->getIntrinsicID() == Intrinsic::coro_begin)
95 return II;
96 llvm_unreachable("no coro.begin associated with coro.id");
97 }
98
99 // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)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;
105 }
106
classof(const Value * V)107 static bool classof(const Value *V) {
108 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
109 }
110 };
111
112 /// This represents the llvm.coro.id instruction.
113 class LLVM_LIBRARY_VISIBILITY CoroIdInst : public AnyCoroIdInst {
114 enum { AlignArg, PromiseArg, CoroutineArg, InfoArg };
115
116 public:
getPromise()117 AllocaInst *getPromise() const {
118 Value *Arg = getArgOperand(PromiseArg);
119 return isa<ConstantPointerNull>(Arg)
120 ? nullptr
121 : cast<AllocaInst>(Arg->stripPointerCasts());
122 }
123
clearPromise()124 void clearPromise() {
125 Value *Arg = getArgOperand(PromiseArg);
126 setArgOperand(PromiseArg,
127 ConstantPointerNull::get(Type::getInt8PtrTy(getContext())));
128 if (isa<AllocaInst>(Arg))
129 return;
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();
137 return;
138 }
139 Inst->moveBefore(getCoroBegin()->getNextNode());
140 }
141
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] ;
146 //
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.
150 //
151 // After coroutine is split, resume functions are stored in an array
152 // referred to by this parameter.
153
154 struct Info {
155 ConstantStruct *OutlinedParts = nullptr;
156 ConstantArray *Resumers = nullptr;
157
hasOutlinedPartsInfo158 bool hasOutlinedParts() const { return OutlinedParts != nullptr; }
isPostSplitInfo159 bool isPostSplit() const { return Resumers != nullptr; }
isPreSplitInfo160 bool isPreSplit() const { return !isPostSplit(); }
161 };
getInfo()162 Info getInfo() const {
163 Info Result;
164 auto *GV = dyn_cast<GlobalVariable>(getRawInfo());
165 if (!GV)
166 return Result;
167
168 assert(GV->isConstant() && GV->hasDefinitiveInitializer());
169 Constant *Initializer = GV->getInitializer();
170 if ((Result.OutlinedParts = dyn_cast<ConstantStruct>(Initializer)))
171 return Result;
172
173 Result.Resumers = cast<ConstantArray>(Initializer);
174 return Result;
175 }
getRawInfo()176 Constant *getRawInfo() const {
177 return cast<Constant>(getArgOperand(InfoArg)->stripPointerCasts());
178 }
179
setInfo(Constant * C)180 void setInfo(Constant *C) { setArgOperand(InfoArg, C); }
181
getCoroutine()182 Function *getCoroutine() const {
183 return cast<Function>(getArgOperand(CoroutineArg)->stripPointerCasts());
184 }
setCoroutineSelf()185 void setCoroutineSelf() {
186 assert(isa<ConstantPointerNull>(getArgOperand(CoroutineArg)) &&
187 "Coroutine argument is already assigned");
188 auto *const Int8PtrTy = Type::getInt8PtrTy(getContext());
189 setArgOperand(CoroutineArg,
190 ConstantExpr::getBitCast(getFunction(), Int8PtrTy));
191 }
192
193 // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)194 static bool classof(const IntrinsicInst *I) {
195 return I->getIntrinsicID() == Intrinsic::coro_id;
196 }
classof(const Value * V)197 static bool classof(const Value *V) {
198 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
199 }
200 };
201
202 /// This represents either the llvm.coro.id.retcon or
203 /// llvm.coro.id.retcon.once instruction.
204 class LLVM_LIBRARY_VISIBILITY AnyCoroIdRetconInst : public AnyCoroIdInst {
205 enum { SizeArg, AlignArg, StorageArg, PrototypeArg, AllocArg, DeallocArg };
206
207 public:
208 void checkWellFormed() const;
209
getStorageSize()210 uint64_t getStorageSize() const {
211 return cast<ConstantInt>(getArgOperand(SizeArg))->getZExtValue();
212 }
213
getStorageAlignment()214 Align getStorageAlignment() const {
215 return cast<ConstantInt>(getArgOperand(AlignArg))->getAlignValue();
216 }
217
getStorage()218 Value *getStorage() const {
219 return getArgOperand(StorageArg);
220 }
221
222 /// Return the prototype for the continuation function. The type,
223 /// attributes, and calling convention of the continuation function(s)
224 /// are taken from this declaration.
getPrototype()225 Function *getPrototype() const {
226 return cast<Function>(getArgOperand(PrototypeArg)->stripPointerCasts());
227 }
228
229 /// Return the function to use for allocating memory.
getAllocFunction()230 Function *getAllocFunction() const {
231 return cast<Function>(getArgOperand(AllocArg)->stripPointerCasts());
232 }
233
234 /// Return the function to use for deallocating memory.
getDeallocFunction()235 Function *getDeallocFunction() const {
236 return cast<Function>(getArgOperand(DeallocArg)->stripPointerCasts());
237 }
238
239 // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)240 static bool classof(const IntrinsicInst *I) {
241 auto ID = I->getIntrinsicID();
242 return ID == Intrinsic::coro_id_retcon
243 || ID == Intrinsic::coro_id_retcon_once;
244 }
classof(const Value * V)245 static bool classof(const Value *V) {
246 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
247 }
248 };
249
250 /// This represents the llvm.coro.id.retcon instruction.
251 class LLVM_LIBRARY_VISIBILITY CoroIdRetconInst
252 : public AnyCoroIdRetconInst {
253 public:
254 // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)255 static bool classof(const IntrinsicInst *I) {
256 return I->getIntrinsicID() == Intrinsic::coro_id_retcon;
257 }
classof(const Value * V)258 static bool classof(const Value *V) {
259 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
260 }
261 };
262
263 /// This represents the llvm.coro.id.retcon.once instruction.
264 class LLVM_LIBRARY_VISIBILITY CoroIdRetconOnceInst
265 : public AnyCoroIdRetconInst {
266 public:
267 // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)268 static bool classof(const IntrinsicInst *I) {
269 return I->getIntrinsicID() == Intrinsic::coro_id_retcon_once;
270 }
classof(const Value * V)271 static bool classof(const Value *V) {
272 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
273 }
274 };
275
276 /// This represents the llvm.coro.id.async instruction.
277 class LLVM_LIBRARY_VISIBILITY CoroIdAsyncInst : public AnyCoroIdInst {
278 enum { SizeArg, AlignArg, StorageArg, AsyncFuncPtrArg };
279
280 public:
281 void checkWellFormed() const;
282
283 /// The initial async function context size. The fields of which are reserved
284 /// for use by the frontend. The frame will be allocated as a tail of this
285 /// context.
getStorageSize()286 uint64_t getStorageSize() const {
287 return cast<ConstantInt>(getArgOperand(SizeArg))->getZExtValue();
288 }
289
290 /// The alignment of the initial async function context.
getStorageAlignment()291 Align getStorageAlignment() const {
292 return cast<ConstantInt>(getArgOperand(AlignArg))->getAlignValue();
293 }
294
295 /// The async context parameter.
getStorage()296 Value *getStorage() const {
297 return getParent()->getParent()->getArg(getStorageArgumentIndex());
298 }
299
getStorageArgumentIndex()300 unsigned getStorageArgumentIndex() const {
301 auto *Arg = cast<ConstantInt>(getArgOperand(StorageArg));
302 return Arg->getZExtValue();
303 }
304
305 /// Return the async function pointer address. This should be the address of
306 /// a async function pointer struct for the current async function.
307 /// struct async_function_pointer {
308 /// uint32_t context_size;
309 /// uint32_t relative_async_function_pointer;
310 /// };
getAsyncFunctionPointer()311 GlobalVariable *getAsyncFunctionPointer() const {
312 return cast<GlobalVariable>(
313 getArgOperand(AsyncFuncPtrArg)->stripPointerCasts());
314 }
315
316 // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)317 static bool classof(const IntrinsicInst *I) {
318 auto ID = I->getIntrinsicID();
319 return ID == Intrinsic::coro_id_async;
320 }
321
classof(const Value * V)322 static bool classof(const Value *V) {
323 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
324 }
325 };
326
327 /// This represents the llvm.coro.context.alloc instruction.
328 class LLVM_LIBRARY_VISIBILITY CoroAsyncContextAllocInst : public IntrinsicInst {
329 enum { AsyncFuncPtrArg };
330
331 public:
getAsyncFunctionPointer()332 GlobalVariable *getAsyncFunctionPointer() const {
333 return cast<GlobalVariable>(
334 getArgOperand(AsyncFuncPtrArg)->stripPointerCasts());
335 }
336
337 // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)338 static bool classof(const IntrinsicInst *I) {
339 return I->getIntrinsicID() == Intrinsic::coro_async_context_alloc;
340 }
classof(const Value * V)341 static bool classof(const Value *V) {
342 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
343 }
344 };
345
346 /// This represents the llvm.coro.context.dealloc instruction.
347 class LLVM_LIBRARY_VISIBILITY CoroAsyncContextDeallocInst
348 : public IntrinsicInst {
349 enum { AsyncContextArg };
350
351 public:
getAsyncContext()352 Value *getAsyncContext() const {
353 return getArgOperand(AsyncContextArg)->stripPointerCasts();
354 }
355
356 // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)357 static bool classof(const IntrinsicInst *I) {
358 return I->getIntrinsicID() == Intrinsic::coro_async_context_dealloc;
359 }
classof(const Value * V)360 static bool classof(const Value *V) {
361 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
362 }
363 };
364
365 /// This represents the llvm.coro.async.resume instruction.
366 /// During lowering this is replaced by the resume function of a suspend point
367 /// (the continuation function).
368 class LLVM_LIBRARY_VISIBILITY CoroAsyncResumeInst : public IntrinsicInst {
369 public:
370 // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)371 static bool classof(const IntrinsicInst *I) {
372 return I->getIntrinsicID() == Intrinsic::coro_async_resume;
373 }
classof(const Value * V)374 static bool classof(const Value *V) {
375 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
376 }
377 };
378
379 /// This represents the llvm.coro.async.size.replace instruction.
380 class LLVM_LIBRARY_VISIBILITY CoroAsyncSizeReplace : public IntrinsicInst {
381 public:
382 // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)383 static bool classof(const IntrinsicInst *I) {
384 return I->getIntrinsicID() == Intrinsic::coro_async_size_replace;
385 }
classof(const Value * V)386 static bool classof(const Value *V) {
387 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
388 }
389 };
390
391 /// This represents the llvm.coro.frame instruction.
392 class LLVM_LIBRARY_VISIBILITY CoroFrameInst : public IntrinsicInst {
393 public:
394 // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)395 static bool classof(const IntrinsicInst *I) {
396 return I->getIntrinsicID() == Intrinsic::coro_frame;
397 }
classof(const Value * V)398 static bool classof(const Value *V) {
399 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
400 }
401 };
402
403 /// This represents the llvm.coro.free instruction.
404 class LLVM_LIBRARY_VISIBILITY CoroFreeInst : public IntrinsicInst {
405 enum { IdArg, FrameArg };
406
407 public:
getFrame()408 Value *getFrame() const { return getArgOperand(FrameArg); }
409
410 // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)411 static bool classof(const IntrinsicInst *I) {
412 return I->getIntrinsicID() == Intrinsic::coro_free;
413 }
classof(const Value * V)414 static bool classof(const Value *V) {
415 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
416 }
417 };
418
419 /// This class represents the llvm.coro.begin instruction.
420 class LLVM_LIBRARY_VISIBILITY CoroBeginInst : public IntrinsicInst {
421 enum { IdArg, MemArg };
422
423 public:
getId()424 AnyCoroIdInst *getId() const {
425 return cast<AnyCoroIdInst>(getArgOperand(IdArg));
426 }
427
getMem()428 Value *getMem() const { return getArgOperand(MemArg); }
429
430 // Methods for support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)431 static bool classof(const IntrinsicInst *I) {
432 return I->getIntrinsicID() == Intrinsic::coro_begin;
433 }
classof(const Value * V)434 static bool classof(const Value *V) {
435 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
436 }
437 };
438
439 /// This represents the llvm.coro.save instruction.
440 class LLVM_LIBRARY_VISIBILITY CoroSaveInst : public IntrinsicInst {
441 public:
442 // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)443 static bool classof(const IntrinsicInst *I) {
444 return I->getIntrinsicID() == Intrinsic::coro_save;
445 }
classof(const Value * V)446 static bool classof(const Value *V) {
447 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
448 }
449 };
450
451 /// This represents the llvm.coro.promise instruction.
452 class LLVM_LIBRARY_VISIBILITY CoroPromiseInst : public IntrinsicInst {
453 enum { FrameArg, AlignArg, FromArg };
454
455 public:
456 /// Are we translating from the frame to the promise (false) or from
457 /// the promise to the frame (true)?
isFromPromise()458 bool isFromPromise() const {
459 return cast<Constant>(getArgOperand(FromArg))->isOneValue();
460 }
461
462 /// The required alignment of the promise. This must match the
463 /// alignment of the promise alloca in the coroutine.
getAlignment()464 Align getAlignment() const {
465 return cast<ConstantInt>(getArgOperand(AlignArg))->getAlignValue();
466 }
467
468 // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)469 static bool classof(const IntrinsicInst *I) {
470 return I->getIntrinsicID() == Intrinsic::coro_promise;
471 }
classof(const Value * V)472 static bool classof(const Value *V) {
473 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
474 }
475 };
476
477 class LLVM_LIBRARY_VISIBILITY AnyCoroSuspendInst : public IntrinsicInst {
478 public:
479 CoroSaveInst *getCoroSave() const;
480
481 // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)482 static bool classof(const IntrinsicInst *I) {
483 return I->getIntrinsicID() == Intrinsic::coro_suspend ||
484 I->getIntrinsicID() == Intrinsic::coro_suspend_async ||
485 I->getIntrinsicID() == Intrinsic::coro_suspend_retcon;
486 }
classof(const Value * V)487 static bool classof(const Value *V) {
488 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
489 }
490 };
491
492 /// This represents the llvm.coro.suspend instruction.
493 class LLVM_LIBRARY_VISIBILITY CoroSuspendInst : public AnyCoroSuspendInst {
494 enum { SaveArg, FinalArg };
495
496 public:
getCoroSave()497 CoroSaveInst *getCoroSave() const {
498 Value *Arg = getArgOperand(SaveArg);
499 if (auto *SI = dyn_cast<CoroSaveInst>(Arg))
500 return SI;
501 assert(isa<ConstantTokenNone>(Arg));
502 return nullptr;
503 }
504
isFinal()505 bool isFinal() const {
506 return cast<Constant>(getArgOperand(FinalArg))->isOneValue();
507 }
508
509 // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)510 static bool classof(const IntrinsicInst *I) {
511 return I->getIntrinsicID() == Intrinsic::coro_suspend;
512 }
classof(const Value * V)513 static bool classof(const Value *V) {
514 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
515 }
516 };
517
getCoroSave()518 inline CoroSaveInst *AnyCoroSuspendInst::getCoroSave() const {
519 if (auto Suspend = dyn_cast<CoroSuspendInst>(this))
520 return Suspend->getCoroSave();
521 return nullptr;
522 }
523
524 /// This represents the llvm.coro.suspend.async instruction.
525 class LLVM_LIBRARY_VISIBILITY CoroSuspendAsyncInst : public AnyCoroSuspendInst {
526 public:
527 enum {
528 StorageArgNoArg,
529 ResumeFunctionArg,
530 AsyncContextProjectionArg,
531 MustTailCallFuncArg
532 };
533
534 void checkWellFormed() const;
535
getStorageArgumentIndex()536 unsigned getStorageArgumentIndex() const {
537 auto *Arg = cast<ConstantInt>(getArgOperand(StorageArgNoArg));
538 return Arg->getZExtValue();
539 }
540
getAsyncContextProjectionFunction()541 Function *getAsyncContextProjectionFunction() const {
542 return cast<Function>(
543 getArgOperand(AsyncContextProjectionArg)->stripPointerCasts());
544 }
545
getResumeFunction()546 CoroAsyncResumeInst *getResumeFunction() const {
547 return cast<CoroAsyncResumeInst>(
548 getArgOperand(ResumeFunctionArg)->stripPointerCasts());
549 }
550
getMustTailCallFunction()551 Function *getMustTailCallFunction() const {
552 return cast<Function>(
553 getArgOperand(MustTailCallFuncArg)->stripPointerCasts());
554 }
555
556 // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)557 static bool classof(const IntrinsicInst *I) {
558 return I->getIntrinsicID() == Intrinsic::coro_suspend_async;
559 }
classof(const Value * V)560 static bool classof(const Value *V) {
561 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
562 }
563 };
564
565 /// This represents the llvm.coro.suspend.retcon instruction.
566 class LLVM_LIBRARY_VISIBILITY CoroSuspendRetconInst : public AnyCoroSuspendInst {
567 public:
value_begin()568 op_iterator value_begin() { return arg_begin(); }
value_begin()569 const_op_iterator value_begin() const { return arg_begin(); }
570
value_end()571 op_iterator value_end() { return arg_end(); }
value_end()572 const_op_iterator value_end() const { return arg_end(); }
573
value_operands()574 iterator_range<op_iterator> value_operands() {
575 return make_range(value_begin(), value_end());
576 }
value_operands()577 iterator_range<const_op_iterator> value_operands() const {
578 return make_range(value_begin(), value_end());
579 }
580
581 // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)582 static bool classof(const IntrinsicInst *I) {
583 return I->getIntrinsicID() == Intrinsic::coro_suspend_retcon;
584 }
classof(const Value * V)585 static bool classof(const Value *V) {
586 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
587 }
588 };
589
590 /// This represents the llvm.coro.size instruction.
591 class LLVM_LIBRARY_VISIBILITY CoroSizeInst : public IntrinsicInst {
592 public:
593 // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)594 static bool classof(const IntrinsicInst *I) {
595 return I->getIntrinsicID() == Intrinsic::coro_size;
596 }
classof(const Value * V)597 static bool classof(const Value *V) {
598 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
599 }
600 };
601
602 class LLVM_LIBRARY_VISIBILITY AnyCoroEndInst : public IntrinsicInst {
603 enum { FrameArg, UnwindArg };
604
605 public:
isFallthrough()606 bool isFallthrough() const { return !isUnwind(); }
isUnwind()607 bool isUnwind() const {
608 return cast<Constant>(getArgOperand(UnwindArg))->isOneValue();
609 }
610
611 // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)612 static bool classof(const IntrinsicInst *I) {
613 auto ID = I->getIntrinsicID();
614 return ID == Intrinsic::coro_end || ID == Intrinsic::coro_end_async;
615 }
classof(const Value * V)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.end instruction.
622 class LLVM_LIBRARY_VISIBILITY CoroEndInst : public AnyCoroEndInst {
623 public:
624 // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)625 static bool classof(const IntrinsicInst *I) {
626 return I->getIntrinsicID() == Intrinsic::coro_end;
627 }
classof(const Value * V)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.end instruction.
634 class LLVM_LIBRARY_VISIBILITY CoroAsyncEndInst : public AnyCoroEndInst {
635 enum { FrameArg, UnwindArg, MustTailCallFuncArg };
636
637 public:
638 void checkWellFormed() const;
639
getMustTailCallFunction()640 Function *getMustTailCallFunction() const {
641 if (getNumArgOperands() < 3)
642 return nullptr;
643
644 return cast<Function>(
645 getArgOperand(MustTailCallFuncArg)->stripPointerCasts());
646 }
647
648 // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)649 static bool classof(const IntrinsicInst *I) {
650 return I->getIntrinsicID() == Intrinsic::coro_end_async;
651 }
classof(const Value * V)652 static bool classof(const Value *V) {
653 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
654 }
655 };
656
657 /// This represents the llvm.coro.alloca.alloc instruction.
658 class LLVM_LIBRARY_VISIBILITY CoroAllocaAllocInst : public IntrinsicInst {
659 enum { SizeArg, AlignArg };
660 public:
getSize()661 Value *getSize() const {
662 return getArgOperand(SizeArg);
663 }
getAlignment()664 Align getAlignment() const {
665 return cast<ConstantInt>(getArgOperand(AlignArg))->getAlignValue();
666 }
667
668 // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)669 static bool classof(const IntrinsicInst *I) {
670 return I->getIntrinsicID() == Intrinsic::coro_alloca_alloc;
671 }
classof(const Value * V)672 static bool classof(const Value *V) {
673 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
674 }
675 };
676
677 /// This represents the llvm.coro.alloca.get instruction.
678 class LLVM_LIBRARY_VISIBILITY CoroAllocaGetInst : public IntrinsicInst {
679 enum { AllocArg };
680 public:
getAlloc()681 CoroAllocaAllocInst *getAlloc() const {
682 return cast<CoroAllocaAllocInst>(getArgOperand(AllocArg));
683 }
684
685 // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)686 static bool classof(const IntrinsicInst *I) {
687 return I->getIntrinsicID() == Intrinsic::coro_alloca_get;
688 }
classof(const Value * V)689 static bool classof(const Value *V) {
690 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
691 }
692 };
693
694 /// This represents the llvm.coro.alloca.free instruction.
695 class LLVM_LIBRARY_VISIBILITY CoroAllocaFreeInst : public IntrinsicInst {
696 enum { AllocArg };
697 public:
getAlloc()698 CoroAllocaAllocInst *getAlloc() const {
699 return cast<CoroAllocaAllocInst>(getArgOperand(AllocArg));
700 }
701
702 // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)703 static bool classof(const IntrinsicInst *I) {
704 return I->getIntrinsicID() == Intrinsic::coro_alloca_free;
705 }
classof(const Value * V)706 static bool classof(const Value *V) {
707 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
708 }
709 };
710
711 } // End namespace llvm.
712
713 #endif
714