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