]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/llvm/lib/Transforms/Coroutines/CoroInstr.h
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm-project / 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 #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 ||
103            ID == Intrinsic::coro_id_retcon ||
104            ID == Intrinsic::coro_id_retcon_once;
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   uint64_t getStorageAlignment() const {
215     return cast<ConstantInt>(getArgOperand(AlignArg))->getZExtValue();
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.frame instruction.
277 class LLVM_LIBRARY_VISIBILITY CoroFrameInst : public IntrinsicInst {
278 public:
279   // Methods to support type inquiry through isa, cast, and dyn_cast:
280   static bool classof(const IntrinsicInst *I) {
281     return I->getIntrinsicID() == Intrinsic::coro_frame;
282   }
283   static bool classof(const Value *V) {
284     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
285   }
286 };
287
288 /// This represents the llvm.coro.free instruction.
289 class LLVM_LIBRARY_VISIBILITY CoroFreeInst : public IntrinsicInst {
290   enum { IdArg, FrameArg };
291
292 public:
293   Value *getFrame() const { return getArgOperand(FrameArg); }
294
295   // Methods to support type inquiry through isa, cast, and dyn_cast:
296   static bool classof(const IntrinsicInst *I) {
297     return I->getIntrinsicID() == Intrinsic::coro_free;
298   }
299   static bool classof(const Value *V) {
300     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
301   }
302 };
303
304 /// This class represents the llvm.coro.begin instruction.
305 class LLVM_LIBRARY_VISIBILITY CoroBeginInst : public IntrinsicInst {
306   enum { IdArg, MemArg };
307
308 public:
309   AnyCoroIdInst *getId() const {
310     return cast<AnyCoroIdInst>(getArgOperand(IdArg));
311   }
312
313   Value *getMem() const { return getArgOperand(MemArg); }
314
315   // Methods for support type inquiry through isa, cast, and dyn_cast:
316   static bool classof(const IntrinsicInst *I) {
317     return I->getIntrinsicID() == Intrinsic::coro_begin;
318   }
319   static bool classof(const Value *V) {
320     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
321   }
322 };
323
324 /// This represents the llvm.coro.save instruction.
325 class LLVM_LIBRARY_VISIBILITY CoroSaveInst : public IntrinsicInst {
326 public:
327   // Methods to support type inquiry through isa, cast, and dyn_cast:
328   static bool classof(const IntrinsicInst *I) {
329     return I->getIntrinsicID() == Intrinsic::coro_save;
330   }
331   static bool classof(const Value *V) {
332     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
333   }
334 };
335
336 /// This represents the llvm.coro.promise instruction.
337 class LLVM_LIBRARY_VISIBILITY CoroPromiseInst : public IntrinsicInst {
338   enum { FrameArg, AlignArg, FromArg };
339
340 public:
341   bool isFromPromise() const {
342     return cast<Constant>(getArgOperand(FromArg))->isOneValue();
343   }
344   unsigned getAlignment() const {
345     return cast<ConstantInt>(getArgOperand(AlignArg))->getZExtValue();
346   }
347
348   // Methods to support type inquiry through isa, cast, and dyn_cast:
349   static bool classof(const IntrinsicInst *I) {
350     return I->getIntrinsicID() == Intrinsic::coro_promise;
351   }
352   static bool classof(const Value *V) {
353     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
354   }
355 };
356
357 class LLVM_LIBRARY_VISIBILITY AnyCoroSuspendInst : public IntrinsicInst {
358 public:
359   CoroSaveInst *getCoroSave() const;
360
361   // Methods to support type inquiry through isa, cast, and dyn_cast:
362   static bool classof(const IntrinsicInst *I) {
363     return I->getIntrinsicID() == Intrinsic::coro_suspend ||
364            I->getIntrinsicID() == Intrinsic::coro_suspend_retcon;
365   }
366   static bool classof(const Value *V) {
367     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
368   }
369 };
370
371 /// This represents the llvm.coro.suspend instruction.
372 class LLVM_LIBRARY_VISIBILITY CoroSuspendInst : public AnyCoroSuspendInst {
373   enum { SaveArg, FinalArg };
374
375 public:
376   CoroSaveInst *getCoroSave() const {
377     Value *Arg = getArgOperand(SaveArg);
378     if (auto *SI = dyn_cast<CoroSaveInst>(Arg))
379       return SI;
380     assert(isa<ConstantTokenNone>(Arg));
381     return nullptr;
382   }
383
384   bool isFinal() const {
385     return cast<Constant>(getArgOperand(FinalArg))->isOneValue();
386   }
387
388   // Methods to support type inquiry through isa, cast, and dyn_cast:
389   static bool classof(const IntrinsicInst *I) {
390     return I->getIntrinsicID() == Intrinsic::coro_suspend;
391   }
392   static bool classof(const Value *V) {
393     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
394   }
395 };
396
397 inline CoroSaveInst *AnyCoroSuspendInst::getCoroSave() const {
398   if (auto Suspend = dyn_cast<CoroSuspendInst>(this))
399     return Suspend->getCoroSave();
400   return nullptr;
401 }
402
403 /// This represents the llvm.coro.suspend.retcon instruction.
404 class LLVM_LIBRARY_VISIBILITY CoroSuspendRetconInst : public AnyCoroSuspendInst {
405 public:
406   op_iterator value_begin() { return arg_begin(); }
407   const_op_iterator value_begin() const { return arg_begin(); }
408
409   op_iterator value_end() { return arg_end(); }
410   const_op_iterator value_end() const { return arg_end(); }
411
412   iterator_range<op_iterator> value_operands() {
413     return make_range(value_begin(), value_end());
414   }
415   iterator_range<const_op_iterator> value_operands() const {
416     return make_range(value_begin(), value_end());
417   }
418
419   // Methods to support type inquiry through isa, cast, and dyn_cast:
420   static bool classof(const IntrinsicInst *I) {
421     return I->getIntrinsicID() == Intrinsic::coro_suspend_retcon;
422   }
423   static bool classof(const Value *V) {
424     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
425   }
426 };
427
428 /// This represents the llvm.coro.size instruction.
429 class LLVM_LIBRARY_VISIBILITY CoroSizeInst : public IntrinsicInst {
430 public:
431   // Methods to support type inquiry through isa, cast, and dyn_cast:
432   static bool classof(const IntrinsicInst *I) {
433     return I->getIntrinsicID() == Intrinsic::coro_size;
434   }
435   static bool classof(const Value *V) {
436     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
437   }
438 };
439
440 /// This represents the llvm.coro.end instruction.
441 class LLVM_LIBRARY_VISIBILITY CoroEndInst : public IntrinsicInst {
442   enum { FrameArg, UnwindArg };
443
444 public:
445   bool isFallthrough() const { return !isUnwind(); }
446   bool isUnwind() const {
447     return cast<Constant>(getArgOperand(UnwindArg))->isOneValue();
448   }
449
450   // Methods to support type inquiry through isa, cast, and dyn_cast:
451   static bool classof(const IntrinsicInst *I) {
452     return I->getIntrinsicID() == Intrinsic::coro_end;
453   }
454   static bool classof(const Value *V) {
455     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
456   }
457 };
458
459 /// This represents the llvm.coro.alloca.alloc instruction.
460 class LLVM_LIBRARY_VISIBILITY CoroAllocaAllocInst : public IntrinsicInst {
461   enum { SizeArg, AlignArg };
462 public:
463   Value *getSize() const {
464     return getArgOperand(SizeArg);
465   }
466   unsigned getAlignment() const {
467     return cast<ConstantInt>(getArgOperand(AlignArg))->getZExtValue();
468   }
469
470   // Methods to support type inquiry through isa, cast, and dyn_cast:
471   static bool classof(const IntrinsicInst *I) {
472     return I->getIntrinsicID() == Intrinsic::coro_alloca_alloc;
473   }
474   static bool classof(const Value *V) {
475     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
476   }
477 };
478
479 /// This represents the llvm.coro.alloca.get instruction.
480 class LLVM_LIBRARY_VISIBILITY CoroAllocaGetInst : public IntrinsicInst {
481   enum { AllocArg };
482 public:
483   CoroAllocaAllocInst *getAlloc() const {
484     return cast<CoroAllocaAllocInst>(getArgOperand(AllocArg));
485   }
486
487   // Methods to support type inquiry through isa, cast, and dyn_cast:
488   static bool classof(const IntrinsicInst *I) {
489     return I->getIntrinsicID() == Intrinsic::coro_alloca_get;
490   }
491   static bool classof(const Value *V) {
492     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
493   }
494 };
495
496 /// This represents the llvm.coro.alloca.free instruction.
497 class LLVM_LIBRARY_VISIBILITY CoroAllocaFreeInst : public IntrinsicInst {
498   enum { AllocArg };
499 public:
500   CoroAllocaAllocInst *getAlloc() const {
501     return cast<CoroAllocaAllocInst>(getArgOperand(AllocArg));
502   }
503
504   // Methods to support type inquiry through isa, cast, and dyn_cast:
505   static bool classof(const IntrinsicInst *I) {
506     return I->getIntrinsicID() == Intrinsic::coro_alloca_free;
507   }
508   static bool classof(const Value *V) {
509     return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
510   }
511 };
512
513 } // End namespace llvm.
514
515 #endif