]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Transforms/Coroutines/CoroInstr.h
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / Transforms / Coroutines / CoroInstr.h
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
31 namespace llvm {
32
33 /// This class represents the llvm.coro.subfn.addr instruction.
34 class LLVM_LIBRARY_VISIBILITY CoroSubFnInst : public IntrinsicInst {
35   enum { FrameArg, IndexArg };
36
37 public:
38   enum ResumeKind {
39     RestartTrigger = -1,
40     ResumeIndex,
41     DestroyIndex,
42     CleanupIndex,
43     IndexLast,
44     IndexFirst = RestartTrigger
45   };
46
47   Value *getFrame() const { return getArgOperand(FrameArg); }
48   ResumeKind getIndex() const {
49     int64_t Index = getRawIndex()->getValue().getSExtValue();
50     assert(Index >= IndexFirst && Index < IndexLast &&
51            "unexpected CoroSubFnInst index argument");
52     return static_cast<ResumeKind>(Index);
53   }
54
55   ConstantInt *getRawIndex() const {
56     return cast<ConstantInt>(getArgOperand(IndexArg));
57   }
58
59   // Methods to support type inquiry through isa, cast, and dyn_cast:
60   static bool classof(const IntrinsicInst *I) {
61     return I->getIntrinsicID() == Intrinsic::coro_subfn_addr;
62   }
63   static bool classof(const Value *V) {
64     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
65   }
66 };
67
68 /// This represents the llvm.coro.alloc instruction.
69 class LLVM_LIBRARY_VISIBILITY CoroAllocInst : public IntrinsicInst {
70 public:
71   // Methods to support type inquiry through isa, cast, and dyn_cast:
72   static bool classof(const IntrinsicInst *I) {
73     return I->getIntrinsicID() == Intrinsic::coro_alloc;
74   }
75   static bool classof(const Value *V) {
76     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
77   }
78 };
79
80 /// This represents the llvm.coro.alloc instruction.
81 class LLVM_LIBRARY_VISIBILITY CoroIdInst : public IntrinsicInst {
82   enum { AlignArg, PromiseArg, CoroutineArg, InfoArg };
83
84 public:
85   CoroAllocInst *getCoroAlloc() {
86     for (User *U : users())
87       if (auto *CA = dyn_cast<CoroAllocInst>(U))
88         return CA;
89     return nullptr;
90   }
91
92   IntrinsicInst *getCoroBegin() {
93     for (User *U : users())
94       if (auto *II = dyn_cast<IntrinsicInst>(U))
95         if (II->getIntrinsicID() == Intrinsic::coro_begin)
96           return II;
97     llvm_unreachable("no coro.begin associated with coro.id");
98   }
99
100   AllocaInst *getPromise() const {
101     Value *Arg = getArgOperand(PromiseArg);
102     return isa<ConstantPointerNull>(Arg)
103                ? nullptr
104                : cast<AllocaInst>(Arg->stripPointerCasts());
105   }
106
107   void clearPromise() {
108     Value *Arg = getArgOperand(PromiseArg);
109     setArgOperand(PromiseArg,
110                   ConstantPointerNull::get(Type::getInt8PtrTy(getContext())));
111     if (isa<AllocaInst>(Arg))
112       return;
113     assert((isa<BitCastInst>(Arg) || isa<GetElementPtrInst>(Arg)) &&
114            "unexpected instruction designating the promise");
115     // TODO: Add a check that any remaining users of Inst are after coro.begin
116     // or add code to move the users after coro.begin.
117     auto *Inst = cast<Instruction>(Arg);
118     if (Inst->use_empty()) {
119       Inst->eraseFromParent();
120       return;
121     }
122     Inst->moveBefore(getCoroBegin()->getNextNode());
123   }
124
125   // Info argument of coro.id is
126   //   fresh out of the frontend: null ;
127   //   outlined                 : {Init, Return, Susp1, Susp2, ...} ;
128   //   postsplit                : [resume, destroy, cleanup] ;
129   //
130   // If parts of the coroutine were outlined to protect against undesirable
131   // code motion, these functions will be stored in a struct literal referred to
132   // by the Info parameter. Note: this is only needed before coroutine is split.
133   //
134   // After coroutine is split, resume functions are stored in an array
135   // referred to by this parameter.
136
137   struct Info {
138     ConstantStruct *OutlinedParts = nullptr;
139     ConstantArray *Resumers = nullptr;
140
141     bool hasOutlinedParts() const { return OutlinedParts != nullptr; }
142     bool isPostSplit() const { return Resumers != nullptr; }
143     bool isPreSplit() const { return !isPostSplit(); }
144   };
145   Info getInfo() const {
146     Info Result;
147     auto *GV = dyn_cast<GlobalVariable>(getRawInfo());
148     if (!GV)
149       return Result;
150
151     assert(GV->isConstant() && GV->hasDefinitiveInitializer());
152     Constant *Initializer = GV->getInitializer();
153     if ((Result.OutlinedParts = dyn_cast<ConstantStruct>(Initializer)))
154       return Result;
155
156     Result.Resumers = cast<ConstantArray>(Initializer);
157     return Result;
158   }
159   Constant *getRawInfo() const {
160     return cast<Constant>(getArgOperand(InfoArg)->stripPointerCasts());
161   }
162
163   void setInfo(Constant *C) { setArgOperand(InfoArg, C); }
164
165   Function *getCoroutine() const {
166     return cast<Function>(getArgOperand(CoroutineArg)->stripPointerCasts());
167   }
168   void setCoroutineSelf() {
169     assert(isa<ConstantPointerNull>(getArgOperand(CoroutineArg)) &&
170            "Coroutine argument is already assigned");
171     auto *const Int8PtrTy = Type::getInt8PtrTy(getContext());
172     setArgOperand(CoroutineArg,
173                   ConstantExpr::getBitCast(getFunction(), Int8PtrTy));
174   }
175
176   // Methods to support type inquiry through isa, cast, and dyn_cast:
177   static bool classof(const IntrinsicInst *I) {
178     return I->getIntrinsicID() == Intrinsic::coro_id;
179   }
180   static bool classof(const Value *V) {
181     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
182   }
183 };
184
185 /// This represents the llvm.coro.frame instruction.
186 class LLVM_LIBRARY_VISIBILITY CoroFrameInst : public IntrinsicInst {
187 public:
188   // Methods to support type inquiry through isa, cast, and dyn_cast:
189   static bool classof(const IntrinsicInst *I) {
190     return I->getIntrinsicID() == Intrinsic::coro_frame;
191   }
192   static bool classof(const Value *V) {
193     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
194   }
195 };
196
197 /// This represents the llvm.coro.free instruction.
198 class LLVM_LIBRARY_VISIBILITY CoroFreeInst : public IntrinsicInst {
199   enum { IdArg, FrameArg };
200
201 public:
202   Value *getFrame() const { return getArgOperand(FrameArg); }
203
204   // Methods to support type inquiry through isa, cast, and dyn_cast:
205   static bool classof(const IntrinsicInst *I) {
206     return I->getIntrinsicID() == Intrinsic::coro_free;
207   }
208   static bool classof(const Value *V) {
209     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
210   }
211 };
212
213 /// This class represents the llvm.coro.begin instruction.
214 class LLVM_LIBRARY_VISIBILITY CoroBeginInst : public IntrinsicInst {
215   enum { IdArg, MemArg };
216
217 public:
218   CoroIdInst *getId() const { return cast<CoroIdInst>(getArgOperand(IdArg)); }
219
220   Value *getMem() const { return getArgOperand(MemArg); }
221
222   // Methods for support type inquiry through isa, cast, and dyn_cast:
223   static bool classof(const IntrinsicInst *I) {
224     return I->getIntrinsicID() == Intrinsic::coro_begin;
225   }
226   static bool classof(const Value *V) {
227     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
228   }
229 };
230
231 /// This represents the llvm.coro.save instruction.
232 class LLVM_LIBRARY_VISIBILITY CoroSaveInst : public IntrinsicInst {
233 public:
234   // Methods to support type inquiry through isa, cast, and dyn_cast:
235   static bool classof(const IntrinsicInst *I) {
236     return I->getIntrinsicID() == Intrinsic::coro_save;
237   }
238   static bool classof(const Value *V) {
239     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
240   }
241 };
242
243 /// This represents the llvm.coro.promise instruction.
244 class LLVM_LIBRARY_VISIBILITY CoroPromiseInst : public IntrinsicInst {
245   enum { FrameArg, AlignArg, FromArg };
246
247 public:
248   bool isFromPromise() const {
249     return cast<Constant>(getArgOperand(FromArg))->isOneValue();
250   }
251   unsigned getAlignment() const {
252     return cast<ConstantInt>(getArgOperand(AlignArg))->getZExtValue();
253   }
254
255   // Methods to support type inquiry through isa, cast, and dyn_cast:
256   static bool classof(const IntrinsicInst *I) {
257     return I->getIntrinsicID() == Intrinsic::coro_promise;
258   }
259   static bool classof(const Value *V) {
260     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
261   }
262 };
263
264 /// This represents the llvm.coro.suspend instruction.
265 class LLVM_LIBRARY_VISIBILITY CoroSuspendInst : public IntrinsicInst {
266   enum { SaveArg, FinalArg };
267
268 public:
269   CoroSaveInst *getCoroSave() const {
270     Value *Arg = getArgOperand(SaveArg);
271     if (auto *SI = dyn_cast<CoroSaveInst>(Arg))
272       return SI;
273     assert(isa<ConstantTokenNone>(Arg));
274     return nullptr;
275   }
276   bool isFinal() const {
277     return cast<Constant>(getArgOperand(FinalArg))->isOneValue();
278   }
279
280   // Methods to support type inquiry through isa, cast, and dyn_cast:
281   static bool classof(const IntrinsicInst *I) {
282     return I->getIntrinsicID() == Intrinsic::coro_suspend;
283   }
284   static bool classof(const Value *V) {
285     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
286   }
287 };
288
289 /// This represents the llvm.coro.size instruction.
290 class LLVM_LIBRARY_VISIBILITY CoroSizeInst : public IntrinsicInst {
291 public:
292   // Methods to support type inquiry through isa, cast, and dyn_cast:
293   static bool classof(const IntrinsicInst *I) {
294     return I->getIntrinsicID() == Intrinsic::coro_size;
295   }
296   static bool classof(const Value *V) {
297     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
298   }
299 };
300
301 /// This represents the llvm.coro.end instruction.
302 class LLVM_LIBRARY_VISIBILITY CoroEndInst : public IntrinsicInst {
303   enum { FrameArg, UnwindArg };
304
305 public:
306   bool isFallthrough() const { return !isUnwind(); }
307   bool isUnwind() const {
308     return cast<Constant>(getArgOperand(UnwindArg))->isOneValue();
309   }
310
311   // Methods to support type inquiry through isa, cast, and dyn_cast:
312   static bool classof(const IntrinsicInst *I) {
313     return I->getIntrinsicID() == Intrinsic::coro_end;
314   }
315   static bool classof(const Value *V) {
316     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
317   }
318 };
319
320 } // End namespace llvm.
321
322 #endif