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 a common base class for llvm.coro.id instructions. 82 class LLVM_LIBRARY_VISIBILITY AnyCoroIdInst : public IntrinsicInst { 83 public: 84 CoroAllocInst *getCoroAlloc() { 85 for (User *U : users()) 86 if (auto *CA = dyn_cast<CoroAllocInst>(U)) 87 return CA; 88 return nullptr; 89 } 90 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: 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 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: 117 AllocaInst *getPromise() const { 118 Value *Arg = getArgOperand(PromiseArg); 119 return isa<ConstantPointerNull>(Arg) 120 ? nullptr 121 : cast<AllocaInst>(Arg->stripPointerCasts()); 122 } 123 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 158 bool hasOutlinedParts() const { return OutlinedParts != nullptr; } 159 bool isPostSplit() const { return Resumers != nullptr; } 160 bool isPreSplit() const { return !isPostSplit(); } 161 }; 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 } 176 Constant *getRawInfo() const { 177 return cast<Constant>(getArgOperand(InfoArg)->stripPointerCasts()); 178 } 179 180 void setInfo(Constant *C) { setArgOperand(InfoArg, C); } 181 182 Function *getCoroutine() const { 183 return cast<Function>(getArgOperand(CoroutineArg)->stripPointerCasts()); 184 } 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: 194 static bool classof(const IntrinsicInst *I) { 195 return I->getIntrinsicID() == Intrinsic::coro_id; 196 } 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 210 uint64_t getStorageSize() const { 211 return cast<ConstantInt>(getArgOperand(SizeArg))->getZExtValue(); 212 } 213 214 Align getStorageAlignment() const { 215 return cast<ConstantInt>(getArgOperand(AlignArg))->getAlignValue(); 216 } 217 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. 225 Function *getPrototype() const { 226 return cast<Function>(getArgOperand(PrototypeArg)->stripPointerCasts()); 227 } 228 229 /// Return the function to use for allocating memory. 230 Function *getAllocFunction() const { 231 return cast<Function>(getArgOperand(AllocArg)->stripPointerCasts()); 232 } 233 234 /// Return the function to use for deallocating memory. 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: 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 } 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: 255 static bool classof(const IntrinsicInst *I) { 256 return I->getIntrinsicID() == Intrinsic::coro_id_retcon; 257 } 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: 268 static bool classof(const IntrinsicInst *I) { 269 return I->getIntrinsicID() == Intrinsic::coro_id_retcon_once; 270 } 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. 286 uint64_t getStorageSize() const { 287 return cast<ConstantInt>(getArgOperand(SizeArg))->getZExtValue(); 288 } 289 290 /// The alignment of the initial async function context. 291 Align getStorageAlignment() const { 292 return cast<ConstantInt>(getArgOperand(AlignArg))->getAlignValue(); 293 } 294 295 /// The async context parameter. 296 Value *getStorage() const { 297 return getParent()->getParent()->getArg(getStorageArgumentIndex()); 298 } 299 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 /// }; 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: 317 static bool classof(const IntrinsicInst *I) { 318 auto ID = I->getIntrinsicID(); 319 return ID == Intrinsic::coro_id_async; 320 } 321 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: 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: 338 static bool classof(const IntrinsicInst *I) { 339 return I->getIntrinsicID() == Intrinsic::coro_async_context_alloc; 340 } 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: 352 Value *getAsyncContext() const { 353 return getArgOperand(AsyncContextArg)->stripPointerCasts(); 354 } 355 356 // Methods to support type inquiry through isa, cast, and dyn_cast: 357 static bool classof(const IntrinsicInst *I) { 358 return I->getIntrinsicID() == Intrinsic::coro_async_context_dealloc; 359 } 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: 371 static bool classof(const IntrinsicInst *I) { 372 return I->getIntrinsicID() == Intrinsic::coro_async_resume; 373 } 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: 383 static bool classof(const IntrinsicInst *I) { 384 return I->getIntrinsicID() == Intrinsic::coro_async_size_replace; 385 } 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: 395 static bool classof(const IntrinsicInst *I) { 396 return I->getIntrinsicID() == Intrinsic::coro_frame; 397 } 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: 408 Value *getFrame() const { return getArgOperand(FrameArg); } 409 410 // Methods to support type inquiry through isa, cast, and dyn_cast: 411 static bool classof(const IntrinsicInst *I) { 412 return I->getIntrinsicID() == Intrinsic::coro_free; 413 } 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: 424 AnyCoroIdInst *getId() const { 425 return cast<AnyCoroIdInst>(getArgOperand(IdArg)); 426 } 427 428 Value *getMem() const { return getArgOperand(MemArg); } 429 430 // Methods for support type inquiry through isa, cast, and dyn_cast: 431 static bool classof(const IntrinsicInst *I) { 432 return I->getIntrinsicID() == Intrinsic::coro_begin; 433 } 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: 443 static bool classof(const IntrinsicInst *I) { 444 return I->getIntrinsicID() == Intrinsic::coro_save; 445 } 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)? 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. 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: 469 static bool classof(const IntrinsicInst *I) { 470 return I->getIntrinsicID() == Intrinsic::coro_promise; 471 } 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: 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 } 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: 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 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: 510 static bool classof(const IntrinsicInst *I) { 511 return I->getIntrinsicID() == Intrinsic::coro_suspend; 512 } 513 static bool classof(const Value *V) { 514 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 515 } 516 }; 517 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 536 unsigned getStorageArgumentIndex() const { 537 auto *Arg = cast<ConstantInt>(getArgOperand(StorageArgNoArg)); 538 return Arg->getZExtValue(); 539 } 540 541 Function *getAsyncContextProjectionFunction() const { 542 return cast<Function>( 543 getArgOperand(AsyncContextProjectionArg)->stripPointerCasts()); 544 } 545 546 CoroAsyncResumeInst *getResumeFunction() const { 547 return cast<CoroAsyncResumeInst>( 548 getArgOperand(ResumeFunctionArg)->stripPointerCasts()); 549 } 550 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: 557 static bool classof(const IntrinsicInst *I) { 558 return I->getIntrinsicID() == Intrinsic::coro_suspend_async; 559 } 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: 568 op_iterator value_begin() { return arg_begin(); } 569 const_op_iterator value_begin() const { return arg_begin(); } 570 571 op_iterator value_end() { return arg_end(); } 572 const_op_iterator value_end() const { return arg_end(); } 573 574 iterator_range<op_iterator> value_operands() { 575 return make_range(value_begin(), value_end()); 576 } 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: 582 static bool classof(const IntrinsicInst *I) { 583 return I->getIntrinsicID() == Intrinsic::coro_suspend_retcon; 584 } 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: 594 static bool classof(const IntrinsicInst *I) { 595 return I->getIntrinsicID() == Intrinsic::coro_size; 596 } 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: 606 bool isFallthrough() const { return !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: 612 static bool classof(const IntrinsicInst *I) { 613 auto ID = I->getIntrinsicID(); 614 return ID == Intrinsic::coro_end || ID == Intrinsic::coro_end_async; 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.end instruction. 622 class LLVM_LIBRARY_VISIBILITY CoroEndInst : public AnyCoroEndInst { 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_end; 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.end instruction. 634 class LLVM_LIBRARY_VISIBILITY CoroAsyncEndInst : public AnyCoroEndInst { 635 enum { FrameArg, UnwindArg, MustTailCallFuncArg }; 636 637 public: 638 void checkWellFormed() const; 639 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: 649 static bool classof(const IntrinsicInst *I) { 650 return I->getIntrinsicID() == Intrinsic::coro_end_async; 651 } 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: 661 Value *getSize() const { 662 return getArgOperand(SizeArg); 663 } 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: 669 static bool classof(const IntrinsicInst *I) { 670 return I->getIntrinsicID() == Intrinsic::coro_alloca_alloc; 671 } 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: 681 CoroAllocaAllocInst *getAlloc() const { 682 return cast<CoroAllocaAllocInst>(getArgOperand(AllocArg)); 683 } 684 685 // Methods to support type inquiry through isa, cast, and dyn_cast: 686 static bool classof(const IntrinsicInst *I) { 687 return I->getIntrinsicID() == Intrinsic::coro_alloca_get; 688 } 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: 698 CoroAllocaAllocInst *getAlloc() const { 699 return cast<CoroAllocaAllocInst>(getArgOperand(AllocArg)); 700 } 701 702 // Methods to support type inquiry through isa, cast, and dyn_cast: 703 static bool classof(const IntrinsicInst *I) { 704 return I->getIntrinsicID() == Intrinsic::coro_alloca_free; 705 } 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