1311116Sdim//===-- CoroInstr.h - Coroutine Intrinsics Instruction Wrappers -*- C++ -*-===//
2311116Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6311116Sdim//
7311116Sdim//===----------------------------------------------------------------------===//
8311116Sdim// This file defines classes that make it really easy to deal with intrinsic
9311116Sdim// functions with the isa/dyncast family of functions.  In particular, this
10311116Sdim// allows you to do things like:
11311116Sdim//
12311116Sdim//     if (auto *SF = dyn_cast<CoroSubFnInst>(Inst))
13311116Sdim//        ... SF->getFrame() ...
14311116Sdim//
15311116Sdim// All intrinsic function calls are instances of the call instruction, so these
16311116Sdim// are all subclasses of the CallInst class.  Note that none of these classes
17311116Sdim// has state or virtual methods, which is an important part of this gross/neat
18311116Sdim// hack working.
19311116Sdim//
20311116Sdim// The helpful comment above is borrowed from llvm/IntrinsicInst.h, we keep
21311116Sdim// coroutine intrinsic wrappers here since they are only used by the passes in
22311116Sdim// the Coroutine library.
23311116Sdim//===----------------------------------------------------------------------===//
24311116Sdim
25321369Sdim#ifndef LLVM_LIB_TRANSFORMS_COROUTINES_COROINSTR_H
26321369Sdim#define LLVM_LIB_TRANSFORMS_COROUTINES_COROINSTR_H
27321369Sdim
28311116Sdim#include "llvm/IR/GlobalVariable.h"
29311116Sdim#include "llvm/IR/IntrinsicInst.h"
30360784Sdim#include "llvm/Support/raw_ostream.h"
31311116Sdim
32311116Sdimnamespace llvm {
33311116Sdim
34311116Sdim/// This class represents the llvm.coro.subfn.addr instruction.
35311116Sdimclass LLVM_LIBRARY_VISIBILITY CoroSubFnInst : public IntrinsicInst {
36311116Sdim  enum { FrameArg, IndexArg };
37311116Sdim
38311116Sdimpublic:
39311116Sdim  enum ResumeKind {
40311116Sdim    RestartTrigger = -1,
41311116Sdim    ResumeIndex,
42311116Sdim    DestroyIndex,
43311116Sdim    CleanupIndex,
44311116Sdim    IndexLast,
45311116Sdim    IndexFirst = RestartTrigger
46311116Sdim  };
47311116Sdim
48311116Sdim  Value *getFrame() const { return getArgOperand(FrameArg); }
49311116Sdim  ResumeKind getIndex() const {
50311116Sdim    int64_t Index = getRawIndex()->getValue().getSExtValue();
51311116Sdim    assert(Index >= IndexFirst && Index < IndexLast &&
52311116Sdim           "unexpected CoroSubFnInst index argument");
53311116Sdim    return static_cast<ResumeKind>(Index);
54311116Sdim  }
55311116Sdim
56311116Sdim  ConstantInt *getRawIndex() const {
57311116Sdim    return cast<ConstantInt>(getArgOperand(IndexArg));
58311116Sdim  }
59311116Sdim
60311116Sdim  // Methods to support type inquiry through isa, cast, and dyn_cast:
61321369Sdim  static bool classof(const IntrinsicInst *I) {
62311116Sdim    return I->getIntrinsicID() == Intrinsic::coro_subfn_addr;
63311116Sdim  }
64321369Sdim  static bool classof(const Value *V) {
65311116Sdim    return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
66311116Sdim  }
67311116Sdim};
68311116Sdim
69311116Sdim/// This represents the llvm.coro.alloc instruction.
70311116Sdimclass LLVM_LIBRARY_VISIBILITY CoroAllocInst : public IntrinsicInst {
71311116Sdimpublic:
72311116Sdim  // Methods to support type inquiry through isa, cast, and dyn_cast:
73321369Sdim  static bool classof(const IntrinsicInst *I) {
74311116Sdim    return I->getIntrinsicID() == Intrinsic::coro_alloc;
75311116Sdim  }
76321369Sdim  static bool classof(const Value *V) {
77311116Sdim    return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
78311116Sdim  }
79311116Sdim};
80311116Sdim
81360784Sdim/// This represents a common base class for llvm.coro.id instructions.
82360784Sdimclass LLVM_LIBRARY_VISIBILITY AnyCoroIdInst : public IntrinsicInst {
83311116Sdimpublic:
84311116Sdim  CoroAllocInst *getCoroAlloc() {
85311116Sdim    for (User *U : users())
86311116Sdim      if (auto *CA = dyn_cast<CoroAllocInst>(U))
87311116Sdim        return CA;
88311116Sdim    return nullptr;
89311116Sdim  }
90311116Sdim
91311116Sdim  IntrinsicInst *getCoroBegin() {
92311116Sdim    for (User *U : users())
93311116Sdim      if (auto *II = dyn_cast<IntrinsicInst>(U))
94311116Sdim        if (II->getIntrinsicID() == Intrinsic::coro_begin)
95311116Sdim          return II;
96311116Sdim    llvm_unreachable("no coro.begin associated with coro.id");
97311116Sdim  }
98311116Sdim
99360784Sdim  // Methods to support type inquiry through isa, cast, and dyn_cast:
100360784Sdim  static bool classof(const IntrinsicInst *I) {
101360784Sdim    auto ID = I->getIntrinsicID();
102360784Sdim    return ID == Intrinsic::coro_id ||
103360784Sdim           ID == Intrinsic::coro_id_retcon ||
104360784Sdim           ID == Intrinsic::coro_id_retcon_once;
105360784Sdim  }
106360784Sdim
107360784Sdim  static bool classof(const Value *V) {
108360784Sdim    return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
109360784Sdim  }
110360784Sdim};
111360784Sdim
112360784Sdim/// This represents the llvm.coro.id instruction.
113360784Sdimclass LLVM_LIBRARY_VISIBILITY CoroIdInst : public AnyCoroIdInst {
114360784Sdim  enum { AlignArg, PromiseArg, CoroutineArg, InfoArg };
115360784Sdim
116360784Sdimpublic:
117311116Sdim  AllocaInst *getPromise() const {
118311116Sdim    Value *Arg = getArgOperand(PromiseArg);
119311116Sdim    return isa<ConstantPointerNull>(Arg)
120311116Sdim               ? nullptr
121311116Sdim               : cast<AllocaInst>(Arg->stripPointerCasts());
122311116Sdim  }
123311116Sdim
124311116Sdim  void clearPromise() {
125311116Sdim    Value *Arg = getArgOperand(PromiseArg);
126311116Sdim    setArgOperand(PromiseArg,
127311116Sdim                  ConstantPointerNull::get(Type::getInt8PtrTy(getContext())));
128311116Sdim    if (isa<AllocaInst>(Arg))
129311116Sdim      return;
130311116Sdim    assert((isa<BitCastInst>(Arg) || isa<GetElementPtrInst>(Arg)) &&
131311116Sdim           "unexpected instruction designating the promise");
132311116Sdim    // TODO: Add a check that any remaining users of Inst are after coro.begin
133311116Sdim    // or add code to move the users after coro.begin.
134311116Sdim    auto *Inst = cast<Instruction>(Arg);
135311116Sdim    if (Inst->use_empty()) {
136311116Sdim      Inst->eraseFromParent();
137311116Sdim      return;
138311116Sdim    }
139311116Sdim    Inst->moveBefore(getCoroBegin()->getNextNode());
140311116Sdim  }
141311116Sdim
142311116Sdim  // Info argument of coro.id is
143311116Sdim  //   fresh out of the frontend: null ;
144311116Sdim  //   outlined                 : {Init, Return, Susp1, Susp2, ...} ;
145311116Sdim  //   postsplit                : [resume, destroy, cleanup] ;
146311116Sdim  //
147311116Sdim  // If parts of the coroutine were outlined to protect against undesirable
148311116Sdim  // code motion, these functions will be stored in a struct literal referred to
149311116Sdim  // by the Info parameter. Note: this is only needed before coroutine is split.
150311116Sdim  //
151311116Sdim  // After coroutine is split, resume functions are stored in an array
152311116Sdim  // referred to by this parameter.
153311116Sdim
154311116Sdim  struct Info {
155311116Sdim    ConstantStruct *OutlinedParts = nullptr;
156311116Sdim    ConstantArray *Resumers = nullptr;
157311116Sdim
158311116Sdim    bool hasOutlinedParts() const { return OutlinedParts != nullptr; }
159311116Sdim    bool isPostSplit() const { return Resumers != nullptr; }
160311116Sdim    bool isPreSplit() const { return !isPostSplit(); }
161311116Sdim  };
162311116Sdim  Info getInfo() const {
163311116Sdim    Info Result;
164311116Sdim    auto *GV = dyn_cast<GlobalVariable>(getRawInfo());
165311116Sdim    if (!GV)
166311116Sdim      return Result;
167311116Sdim
168311116Sdim    assert(GV->isConstant() && GV->hasDefinitiveInitializer());
169311116Sdim    Constant *Initializer = GV->getInitializer();
170311116Sdim    if ((Result.OutlinedParts = dyn_cast<ConstantStruct>(Initializer)))
171311116Sdim      return Result;
172311116Sdim
173311116Sdim    Result.Resumers = cast<ConstantArray>(Initializer);
174311116Sdim    return Result;
175311116Sdim  }
176311116Sdim  Constant *getRawInfo() const {
177311116Sdim    return cast<Constant>(getArgOperand(InfoArg)->stripPointerCasts());
178311116Sdim  }
179311116Sdim
180311116Sdim  void setInfo(Constant *C) { setArgOperand(InfoArg, C); }
181311116Sdim
182311116Sdim  Function *getCoroutine() const {
183311116Sdim    return cast<Function>(getArgOperand(CoroutineArg)->stripPointerCasts());
184311116Sdim  }
185311116Sdim  void setCoroutineSelf() {
186311116Sdim    assert(isa<ConstantPointerNull>(getArgOperand(CoroutineArg)) &&
187311116Sdim           "Coroutine argument is already assigned");
188311116Sdim    auto *const Int8PtrTy = Type::getInt8PtrTy(getContext());
189311116Sdim    setArgOperand(CoroutineArg,
190311116Sdim                  ConstantExpr::getBitCast(getFunction(), Int8PtrTy));
191311116Sdim  }
192311116Sdim
193311116Sdim  // Methods to support type inquiry through isa, cast, and dyn_cast:
194321369Sdim  static bool classof(const IntrinsicInst *I) {
195311116Sdim    return I->getIntrinsicID() == Intrinsic::coro_id;
196311116Sdim  }
197321369Sdim  static bool classof(const Value *V) {
198311116Sdim    return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
199311116Sdim  }
200311116Sdim};
201311116Sdim
202360784Sdim/// This represents either the llvm.coro.id.retcon or
203360784Sdim/// llvm.coro.id.retcon.once instruction.
204360784Sdimclass LLVM_LIBRARY_VISIBILITY AnyCoroIdRetconInst : public AnyCoroIdInst {
205360784Sdim  enum { SizeArg, AlignArg, StorageArg, PrototypeArg, AllocArg, DeallocArg };
206360784Sdim
207360784Sdimpublic:
208360784Sdim  void checkWellFormed() const;
209360784Sdim
210360784Sdim  uint64_t getStorageSize() const {
211360784Sdim    return cast<ConstantInt>(getArgOperand(SizeArg))->getZExtValue();
212360784Sdim  }
213360784Sdim
214360784Sdim  uint64_t getStorageAlignment() const {
215360784Sdim    return cast<ConstantInt>(getArgOperand(AlignArg))->getZExtValue();
216360784Sdim  }
217360784Sdim
218360784Sdim  Value *getStorage() const {
219360784Sdim    return getArgOperand(StorageArg);
220360784Sdim  }
221360784Sdim
222360784Sdim  /// Return the prototype for the continuation function.  The type,
223360784Sdim  /// attributes, and calling convention of the continuation function(s)
224360784Sdim  /// are taken from this declaration.
225360784Sdim  Function *getPrototype() const {
226360784Sdim    return cast<Function>(getArgOperand(PrototypeArg)->stripPointerCasts());
227360784Sdim  }
228360784Sdim
229360784Sdim  /// Return the function to use for allocating memory.
230360784Sdim  Function *getAllocFunction() const {
231360784Sdim    return cast<Function>(getArgOperand(AllocArg)->stripPointerCasts());
232360784Sdim  }
233360784Sdim
234360784Sdim  /// Return the function to use for deallocating memory.
235360784Sdim  Function *getDeallocFunction() const {
236360784Sdim    return cast<Function>(getArgOperand(DeallocArg)->stripPointerCasts());
237360784Sdim  }
238360784Sdim
239360784Sdim  // Methods to support type inquiry through isa, cast, and dyn_cast:
240360784Sdim  static bool classof(const IntrinsicInst *I) {
241360784Sdim    auto ID = I->getIntrinsicID();
242360784Sdim    return ID == Intrinsic::coro_id_retcon
243360784Sdim        || ID == Intrinsic::coro_id_retcon_once;
244360784Sdim  }
245360784Sdim  static bool classof(const Value *V) {
246360784Sdim    return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
247360784Sdim  }
248360784Sdim};
249360784Sdim
250360784Sdim/// This represents the llvm.coro.id.retcon instruction.
251360784Sdimclass LLVM_LIBRARY_VISIBILITY CoroIdRetconInst
252360784Sdim    : public AnyCoroIdRetconInst {
253360784Sdimpublic:
254360784Sdim  // Methods to support type inquiry through isa, cast, and dyn_cast:
255360784Sdim  static bool classof(const IntrinsicInst *I) {
256360784Sdim    return I->getIntrinsicID() == Intrinsic::coro_id_retcon;
257360784Sdim  }
258360784Sdim  static bool classof(const Value *V) {
259360784Sdim    return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
260360784Sdim  }
261360784Sdim};
262360784Sdim
263360784Sdim/// This represents the llvm.coro.id.retcon.once instruction.
264360784Sdimclass LLVM_LIBRARY_VISIBILITY CoroIdRetconOnceInst
265360784Sdim    : public AnyCoroIdRetconInst {
266360784Sdimpublic:
267360784Sdim  // Methods to support type inquiry through isa, cast, and dyn_cast:
268360784Sdim  static bool classof(const IntrinsicInst *I) {
269360784Sdim    return I->getIntrinsicID() == Intrinsic::coro_id_retcon_once;
270360784Sdim  }
271360784Sdim  static bool classof(const Value *V) {
272360784Sdim    return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
273360784Sdim  }
274360784Sdim};
275360784Sdim
276311116Sdim/// This represents the llvm.coro.frame instruction.
277311116Sdimclass LLVM_LIBRARY_VISIBILITY CoroFrameInst : public IntrinsicInst {
278311116Sdimpublic:
279311116Sdim  // Methods to support type inquiry through isa, cast, and dyn_cast:
280321369Sdim  static bool classof(const IntrinsicInst *I) {
281311116Sdim    return I->getIntrinsicID() == Intrinsic::coro_frame;
282311116Sdim  }
283321369Sdim  static bool classof(const Value *V) {
284311116Sdim    return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
285311116Sdim  }
286311116Sdim};
287311116Sdim
288311116Sdim/// This represents the llvm.coro.free instruction.
289311116Sdimclass LLVM_LIBRARY_VISIBILITY CoroFreeInst : public IntrinsicInst {
290311116Sdim  enum { IdArg, FrameArg };
291311116Sdim
292311116Sdimpublic:
293311116Sdim  Value *getFrame() const { return getArgOperand(FrameArg); }
294311116Sdim
295311116Sdim  // Methods to support type inquiry through isa, cast, and dyn_cast:
296321369Sdim  static bool classof(const IntrinsicInst *I) {
297311116Sdim    return I->getIntrinsicID() == Intrinsic::coro_free;
298311116Sdim  }
299321369Sdim  static bool classof(const Value *V) {
300311116Sdim    return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
301311116Sdim  }
302311116Sdim};
303311116Sdim
304311116Sdim/// This class represents the llvm.coro.begin instruction.
305311116Sdimclass LLVM_LIBRARY_VISIBILITY CoroBeginInst : public IntrinsicInst {
306311116Sdim  enum { IdArg, MemArg };
307311116Sdim
308311116Sdimpublic:
309360784Sdim  AnyCoroIdInst *getId() const {
310360784Sdim    return cast<AnyCoroIdInst>(getArgOperand(IdArg));
311360784Sdim  }
312311116Sdim
313311116Sdim  Value *getMem() const { return getArgOperand(MemArg); }
314311116Sdim
315311116Sdim  // Methods for support type inquiry through isa, cast, and dyn_cast:
316321369Sdim  static bool classof(const IntrinsicInst *I) {
317311116Sdim    return I->getIntrinsicID() == Intrinsic::coro_begin;
318311116Sdim  }
319321369Sdim  static bool classof(const Value *V) {
320311116Sdim    return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
321311116Sdim  }
322311116Sdim};
323311116Sdim
324311116Sdim/// This represents the llvm.coro.save instruction.
325311116Sdimclass LLVM_LIBRARY_VISIBILITY CoroSaveInst : public IntrinsicInst {
326311116Sdimpublic:
327311116Sdim  // Methods to support type inquiry through isa, cast, and dyn_cast:
328321369Sdim  static bool classof(const IntrinsicInst *I) {
329311116Sdim    return I->getIntrinsicID() == Intrinsic::coro_save;
330311116Sdim  }
331321369Sdim  static bool classof(const Value *V) {
332311116Sdim    return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
333311116Sdim  }
334311116Sdim};
335311116Sdim
336311116Sdim/// This represents the llvm.coro.promise instruction.
337311116Sdimclass LLVM_LIBRARY_VISIBILITY CoroPromiseInst : public IntrinsicInst {
338311116Sdim  enum { FrameArg, AlignArg, FromArg };
339311116Sdim
340311116Sdimpublic:
341311116Sdim  bool isFromPromise() const {
342311116Sdim    return cast<Constant>(getArgOperand(FromArg))->isOneValue();
343311116Sdim  }
344311116Sdim  unsigned getAlignment() const {
345311116Sdim    return cast<ConstantInt>(getArgOperand(AlignArg))->getZExtValue();
346311116Sdim  }
347311116Sdim
348311116Sdim  // Methods to support type inquiry through isa, cast, and dyn_cast:
349321369Sdim  static bool classof(const IntrinsicInst *I) {
350311116Sdim    return I->getIntrinsicID() == Intrinsic::coro_promise;
351311116Sdim  }
352321369Sdim  static bool classof(const Value *V) {
353311116Sdim    return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
354311116Sdim  }
355311116Sdim};
356311116Sdim
357360784Sdimclass LLVM_LIBRARY_VISIBILITY AnyCoroSuspendInst : public IntrinsicInst {
358360784Sdimpublic:
359360784Sdim  CoroSaveInst *getCoroSave() const;
360360784Sdim
361360784Sdim  // Methods to support type inquiry through isa, cast, and dyn_cast:
362360784Sdim  static bool classof(const IntrinsicInst *I) {
363360784Sdim    return I->getIntrinsicID() == Intrinsic::coro_suspend ||
364360784Sdim           I->getIntrinsicID() == Intrinsic::coro_suspend_retcon;
365360784Sdim  }
366360784Sdim  static bool classof(const Value *V) {
367360784Sdim    return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
368360784Sdim  }
369360784Sdim};
370360784Sdim
371311116Sdim/// This represents the llvm.coro.suspend instruction.
372360784Sdimclass LLVM_LIBRARY_VISIBILITY CoroSuspendInst : public AnyCoroSuspendInst {
373311116Sdim  enum { SaveArg, FinalArg };
374311116Sdim
375311116Sdimpublic:
376311116Sdim  CoroSaveInst *getCoroSave() const {
377311116Sdim    Value *Arg = getArgOperand(SaveArg);
378311116Sdim    if (auto *SI = dyn_cast<CoroSaveInst>(Arg))
379311116Sdim      return SI;
380311116Sdim    assert(isa<ConstantTokenNone>(Arg));
381311116Sdim    return nullptr;
382311116Sdim  }
383360784Sdim
384311116Sdim  bool isFinal() const {
385311116Sdim    return cast<Constant>(getArgOperand(FinalArg))->isOneValue();
386311116Sdim  }
387311116Sdim
388311116Sdim  // Methods to support type inquiry through isa, cast, and dyn_cast:
389321369Sdim  static bool classof(const IntrinsicInst *I) {
390311116Sdim    return I->getIntrinsicID() == Intrinsic::coro_suspend;
391311116Sdim  }
392321369Sdim  static bool classof(const Value *V) {
393311116Sdim    return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
394311116Sdim  }
395311116Sdim};
396311116Sdim
397360784Sdiminline CoroSaveInst *AnyCoroSuspendInst::getCoroSave() const {
398360784Sdim  if (auto Suspend = dyn_cast<CoroSuspendInst>(this))
399360784Sdim    return Suspend->getCoroSave();
400360784Sdim  return nullptr;
401360784Sdim}
402360784Sdim
403360784Sdim/// This represents the llvm.coro.suspend.retcon instruction.
404360784Sdimclass LLVM_LIBRARY_VISIBILITY CoroSuspendRetconInst : public AnyCoroSuspendInst {
405360784Sdimpublic:
406360784Sdim  op_iterator value_begin() { return arg_begin(); }
407360784Sdim  const_op_iterator value_begin() const { return arg_begin(); }
408360784Sdim
409360784Sdim  op_iterator value_end() { return arg_end(); }
410360784Sdim  const_op_iterator value_end() const { return arg_end(); }
411360784Sdim
412360784Sdim  iterator_range<op_iterator> value_operands() {
413360784Sdim    return make_range(value_begin(), value_end());
414360784Sdim  }
415360784Sdim  iterator_range<const_op_iterator> value_operands() const {
416360784Sdim    return make_range(value_begin(), value_end());
417360784Sdim  }
418360784Sdim
419360784Sdim  // Methods to support type inquiry through isa, cast, and dyn_cast:
420360784Sdim  static bool classof(const IntrinsicInst *I) {
421360784Sdim    return I->getIntrinsicID() == Intrinsic::coro_suspend_retcon;
422360784Sdim  }
423360784Sdim  static bool classof(const Value *V) {
424360784Sdim    return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
425360784Sdim  }
426360784Sdim};
427360784Sdim
428311116Sdim/// This represents the llvm.coro.size instruction.
429311116Sdimclass LLVM_LIBRARY_VISIBILITY CoroSizeInst : public IntrinsicInst {
430311116Sdimpublic:
431311116Sdim  // Methods to support type inquiry through isa, cast, and dyn_cast:
432321369Sdim  static bool classof(const IntrinsicInst *I) {
433311116Sdim    return I->getIntrinsicID() == Intrinsic::coro_size;
434311116Sdim  }
435321369Sdim  static bool classof(const Value *V) {
436311116Sdim    return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
437311116Sdim  }
438311116Sdim};
439311116Sdim
440311116Sdim/// This represents the llvm.coro.end instruction.
441311116Sdimclass LLVM_LIBRARY_VISIBILITY CoroEndInst : public IntrinsicInst {
442311116Sdim  enum { FrameArg, UnwindArg };
443311116Sdim
444311116Sdimpublic:
445311116Sdim  bool isFallthrough() const { return !isUnwind(); }
446311116Sdim  bool isUnwind() const {
447311116Sdim    return cast<Constant>(getArgOperand(UnwindArg))->isOneValue();
448311116Sdim  }
449311116Sdim
450311116Sdim  // Methods to support type inquiry through isa, cast, and dyn_cast:
451321369Sdim  static bool classof(const IntrinsicInst *I) {
452311116Sdim    return I->getIntrinsicID() == Intrinsic::coro_end;
453311116Sdim  }
454321369Sdim  static bool classof(const Value *V) {
455311116Sdim    return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
456311116Sdim  }
457311116Sdim};
458311116Sdim
459360784Sdim/// This represents the llvm.coro.alloca.alloc instruction.
460360784Sdimclass LLVM_LIBRARY_VISIBILITY CoroAllocaAllocInst : public IntrinsicInst {
461360784Sdim  enum { SizeArg, AlignArg };
462360784Sdimpublic:
463360784Sdim  Value *getSize() const {
464360784Sdim    return getArgOperand(SizeArg);
465360784Sdim  }
466360784Sdim  unsigned getAlignment() const {
467360784Sdim    return cast<ConstantInt>(getArgOperand(AlignArg))->getZExtValue();
468360784Sdim  }
469360784Sdim
470360784Sdim  // Methods to support type inquiry through isa, cast, and dyn_cast:
471360784Sdim  static bool classof(const IntrinsicInst *I) {
472360784Sdim    return I->getIntrinsicID() == Intrinsic::coro_alloca_alloc;
473360784Sdim  }
474360784Sdim  static bool classof(const Value *V) {
475360784Sdim    return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
476360784Sdim  }
477360784Sdim};
478360784Sdim
479360784Sdim/// This represents the llvm.coro.alloca.get instruction.
480360784Sdimclass LLVM_LIBRARY_VISIBILITY CoroAllocaGetInst : public IntrinsicInst {
481360784Sdim  enum { AllocArg };
482360784Sdimpublic:
483360784Sdim  CoroAllocaAllocInst *getAlloc() const {
484360784Sdim    return cast<CoroAllocaAllocInst>(getArgOperand(AllocArg));
485360784Sdim  }
486360784Sdim
487360784Sdim  // Methods to support type inquiry through isa, cast, and dyn_cast:
488360784Sdim  static bool classof(const IntrinsicInst *I) {
489360784Sdim    return I->getIntrinsicID() == Intrinsic::coro_alloca_get;
490360784Sdim  }
491360784Sdim  static bool classof(const Value *V) {
492360784Sdim    return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
493360784Sdim  }
494360784Sdim};
495360784Sdim
496360784Sdim/// This represents the llvm.coro.alloca.free instruction.
497360784Sdimclass LLVM_LIBRARY_VISIBILITY CoroAllocaFreeInst : public IntrinsicInst {
498360784Sdim  enum { AllocArg };
499360784Sdimpublic:
500360784Sdim  CoroAllocaAllocInst *getAlloc() const {
501360784Sdim    return cast<CoroAllocaAllocInst>(getArgOperand(AllocArg));
502360784Sdim  }
503360784Sdim
504360784Sdim  // Methods to support type inquiry through isa, cast, and dyn_cast:
505360784Sdim  static bool classof(const IntrinsicInst *I) {
506360784Sdim    return I->getIntrinsicID() == Intrinsic::coro_alloca_free;
507360784Sdim  }
508360784Sdim  static bool classof(const Value *V) {
509360784Sdim    return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
510360784Sdim  }
511360784Sdim};
512360784Sdim
513311116Sdim} // End namespace llvm.
514321369Sdim
515321369Sdim#endif
516