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 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:
getAwaiter()89 Value *getAwaiter() const { return getArgOperand(AwaiterArg); }
90
getFrame()91 Value *getFrame() const { return getArgOperand(FrameArg); }
92
getWrapperFunction()93 Function *getWrapperFunction() const {
94 return cast<Function>(getArgOperand(WrapperArg));
95 }
96
97 // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const CallBase * CB)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
classof(const Value * V)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:
getCoroAlloc()117 CoroAllocInst *getCoroAlloc() {
118 for (User *U : users())
119 if (auto *CA = dyn_cast<CoroAllocInst>(U))
120 return CA;
121 return nullptr;
122 }
123
getCoroBegin()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:
classof(const IntrinsicInst * I)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
classof(const Value * V)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:
getPromise()150 AllocaInst *getPromise() const {
151 Value *Arg = getArgOperand(PromiseArg);
152 return isa<ConstantPointerNull>(Arg)
153 ? nullptr
154 : cast<AllocaInst>(Arg->stripPointerCasts());
155 }
156
clearPromise()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
hasOutlinedPartsInfo191 bool hasOutlinedParts() const { return OutlinedParts != nullptr; }
isPostSplitInfo192 bool isPostSplit() const { return Resumers != nullptr; }
isPreSplitInfo193 bool isPreSplit() const { return !isPostSplit(); }
194 };
getInfo()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 }
getRawInfo()209 Constant *getRawInfo() const {
210 return cast<Constant>(getArgOperand(InfoArg)->stripPointerCasts());
211 }
212
setInfo(Constant * C)213 void setInfo(Constant *C) { setArgOperand(InfoArg, C); }
214
getCoroutine()215 Function *getCoroutine() const {
216 return cast<Function>(getArgOperand(CoroutineArg)->stripPointerCasts());
217 }
setCoroutineSelf()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:
classof(const IntrinsicInst * I)225 static bool classof(const IntrinsicInst *I) {
226 return I->getIntrinsicID() == Intrinsic::coro_id;
227 }
classof(const Value * V)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
getStorageSize()241 uint64_t getStorageSize() const {
242 return cast<ConstantInt>(getArgOperand(SizeArg))->getZExtValue();
243 }
244
getStorageAlignment()245 Align getStorageAlignment() const {
246 return cast<ConstantInt>(getArgOperand(AlignArg))->getAlignValue();
247 }
248
getStorage()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.
getPrototype()256 Function *getPrototype() const {
257 return cast<Function>(getArgOperand(PrototypeArg)->stripPointerCasts());
258 }
259
260 /// Return the function to use for allocating memory.
getAllocFunction()261 Function *getAllocFunction() const {
262 return cast<Function>(getArgOperand(AllocArg)->stripPointerCasts());
263 }
264
265 /// Return the function to use for deallocating memory.
getDeallocFunction()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:
classof(const IntrinsicInst * I)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 }
classof(const Value * V)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:
classof(const IntrinsicInst * I)286 static bool classof(const IntrinsicInst *I) {
287 return I->getIntrinsicID() == Intrinsic::coro_id_retcon;
288 }
classof(const Value * V)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:
classof(const IntrinsicInst * I)299 static bool classof(const IntrinsicInst *I) {
300 return I->getIntrinsicID() == Intrinsic::coro_id_retcon_once;
301 }
classof(const Value * V)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.
getStorageSize()317 uint64_t getStorageSize() const {
318 return cast<ConstantInt>(getArgOperand(SizeArg))->getZExtValue();
319 }
320
321 /// The alignment of the initial async function context.
getStorageAlignment()322 Align getStorageAlignment() const {
323 return cast<ConstantInt>(getArgOperand(AlignArg))->getAlignValue();
324 }
325
326 /// The async context parameter.
getStorage()327 Value *getStorage() const {
328 return getParent()->getParent()->getArg(getStorageArgumentIndex());
329 }
330
getStorageArgumentIndex()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 /// };
getAsyncFunctionPointer()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:
classof(const IntrinsicInst * I)348 static bool classof(const IntrinsicInst *I) {
349 auto ID = I->getIntrinsicID();
350 return ID == Intrinsic::coro_id_async;
351 }
352
classof(const Value * V)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:
getAsyncFunctionPointer()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:
classof(const IntrinsicInst * I)369 static bool classof(const IntrinsicInst *I) {
370 return I->getIntrinsicID() == Intrinsic::coro_async_context_alloc;
371 }
classof(const Value * V)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:
getAsyncContext()383 Value *getAsyncContext() const {
384 return getArgOperand(AsyncContextArg)->stripPointerCasts();
385 }
386
387 // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)388 static bool classof(const IntrinsicInst *I) {
389 return I->getIntrinsicID() == Intrinsic::coro_async_context_dealloc;
390 }
classof(const Value * V)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:
classof(const IntrinsicInst * I)402 static bool classof(const IntrinsicInst *I) {
403 return I->getIntrinsicID() == Intrinsic::coro_async_resume;
404 }
classof(const Value * V)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:
classof(const IntrinsicInst * I)414 static bool classof(const IntrinsicInst *I) {
415 return I->getIntrinsicID() == Intrinsic::coro_async_size_replace;
416 }
classof(const Value * V)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:
classof(const IntrinsicInst * I)426 static bool classof(const IntrinsicInst *I) {
427 return I->getIntrinsicID() == Intrinsic::coro_frame;
428 }
classof(const Value * V)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:
getFrame()439 Value *getFrame() const { return getArgOperand(FrameArg); }
440
441 // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)442 static bool classof(const IntrinsicInst *I) {
443 return I->getIntrinsicID() == Intrinsic::coro_free;
444 }
classof(const Value * V)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:
getId()455 AnyCoroIdInst *getId() const {
456 return cast<AnyCoroIdInst>(getArgOperand(IdArg));
457 }
458
getMem()459 Value *getMem() const { return getArgOperand(MemArg); }
460
461 // Methods for support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)462 static bool classof(const IntrinsicInst *I) {
463 return I->getIntrinsicID() == Intrinsic::coro_begin;
464 }
classof(const Value * V)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:
classof(const IntrinsicInst * I)474 static bool classof(const IntrinsicInst *I) {
475 return I->getIntrinsicID() == Intrinsic::coro_save;
476 }
classof(const Value * V)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)?
isFromPromise()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.
getAlignment()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:
classof(const IntrinsicInst * I)500 static bool classof(const IntrinsicInst *I) {
501 return I->getIntrinsicID() == Intrinsic::coro_promise;
502 }
classof(const Value * V)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:
classof(const IntrinsicInst * I)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 }
classof(const Value * V)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:
getCoroSave()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
isFinal()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:
classof(const IntrinsicInst * I)541 static bool classof(const IntrinsicInst *I) {
542 return I->getIntrinsicID() == Intrinsic::coro_suspend;
543 }
classof(const Value * V)544 static bool classof(const Value *V) {
545 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
546 }
547 };
548
getCoroSave()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
getStorageArgumentIndex()567 unsigned getStorageArgumentIndex() const {
568 auto *Arg = cast<ConstantInt>(getArgOperand(StorageArgNoArg));
569 return Arg->getZExtValue();
570 }
571
getAsyncContextProjectionFunction()572 Function *getAsyncContextProjectionFunction() const {
573 return cast<Function>(
574 getArgOperand(AsyncContextProjectionArg)->stripPointerCasts());
575 }
576
getResumeFunction()577 CoroAsyncResumeInst *getResumeFunction() const {
578 return cast<CoroAsyncResumeInst>(
579 getArgOperand(ResumeFunctionArg)->stripPointerCasts());
580 }
581
getMustTailCallFunction()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:
classof(const IntrinsicInst * I)588 static bool classof(const IntrinsicInst *I) {
589 return I->getIntrinsicID() == Intrinsic::coro_suspend_async;
590 }
classof(const Value * V)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:
value_begin()599 op_iterator value_begin() { return arg_begin(); }
value_begin()600 const_op_iterator value_begin() const { return arg_begin(); }
601
value_end()602 op_iterator value_end() { return arg_end(); }
value_end()603 const_op_iterator value_end() const { return arg_end(); }
604
value_operands()605 iterator_range<op_iterator> value_operands() {
606 return make_range(value_begin(), value_end());
607 }
value_operands()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:
classof(const IntrinsicInst * I)613 static bool classof(const IntrinsicInst *I) {
614 return I->getIntrinsicID() == Intrinsic::coro_suspend_retcon;
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.size instruction.
622 class LLVM_LIBRARY_VISIBILITY CoroSizeInst : public IntrinsicInst {
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_size;
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.align instruction.
634 class LLVM_LIBRARY_VISIBILITY CoroAlignInst : public IntrinsicInst {
635 public:
636 // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)637 static bool classof(const IntrinsicInst *I) {
638 return I->getIntrinsicID() == Intrinsic::coro_align;
639 }
classof(const Value * V)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:
retval_begin()648 op_iterator retval_begin() { return arg_begin(); }
retval_begin()649 const_op_iterator retval_begin() const { return arg_begin(); }
650
retval_end()651 op_iterator retval_end() { return arg_end(); }
retval_end()652 const_op_iterator retval_end() const { return arg_end(); }
653
return_values()654 iterator_range<op_iterator> return_values() {
655 return make_range(retval_begin(), retval_end());
656 }
return_values()657 iterator_range<const_op_iterator> return_values() const {
658 return make_range(retval_begin(), retval_end());
659 }
660
numReturns()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:
classof(const IntrinsicInst * I)666 static bool classof(const IntrinsicInst *I) {
667 return I->getIntrinsicID() == Intrinsic::coro_end_results;
668 }
classof(const Value * V)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:
isFallthrough()678 bool isFallthrough() const { return !isUnwind(); }
isUnwind()679 bool isUnwind() const {
680 return cast<Constant>(getArgOperand(UnwindArg))->isOneValue();
681 }
682
hasResults()683 bool hasResults() const {
684 return !isa<ConstantTokenNone>(getArgOperand(TokenArg));
685 }
686
getResults()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:
classof(const IntrinsicInst * I)693 static bool classof(const IntrinsicInst *I) {
694 auto ID = I->getIntrinsicID();
695 return ID == Intrinsic::coro_end || ID == Intrinsic::coro_end_async;
696 }
classof(const Value * V)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:
classof(const IntrinsicInst * I)706 static bool classof(const IntrinsicInst *I) {
707 return I->getIntrinsicID() == Intrinsic::coro_end;
708 }
classof(const Value * V)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
getMustTailCallFunction()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:
classof(const IntrinsicInst * I)730 static bool classof(const IntrinsicInst *I) {
731 return I->getIntrinsicID() == Intrinsic::coro_end_async;
732 }
classof(const Value * V)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:
getSize()742 Value *getSize() const {
743 return getArgOperand(SizeArg);
744 }
getAlignment()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:
classof(const IntrinsicInst * I)750 static bool classof(const IntrinsicInst *I) {
751 return I->getIntrinsicID() == Intrinsic::coro_alloca_alloc;
752 }
classof(const Value * V)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:
getAlloc()762 CoroAllocaAllocInst *getAlloc() const {
763 return cast<CoroAllocaAllocInst>(getArgOperand(AllocArg));
764 }
765
766 // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)767 static bool classof(const IntrinsicInst *I) {
768 return I->getIntrinsicID() == Intrinsic::coro_alloca_get;
769 }
classof(const Value * V)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:
getAlloc()779 CoroAllocaAllocInst *getAlloc() const {
780 return cast<CoroAllocaAllocInst>(getArgOperand(AllocArg));
781 }
782
783 // Methods to support type inquiry through isa, cast, and dyn_cast:
classof(const IntrinsicInst * I)784 static bool classof(const IntrinsicInst *I) {
785 return I->getIntrinsicID() == Intrinsic::coro_alloca_free;
786 }
classof(const Value * V)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