25#ifndef LLVM_LIB_TRANSFORMS_COROUTINES_COROINSTR_H
26#define LLVM_LIB_TRANSFORMS_COROUTINES_COROINSTR_H
36 enum { FrameArg, IndexArg };
45 IndexFirst = RestartTrigger
50 int64_t
Index = getRawIndex()->getValue().getSExtValue();
52 "unexpected CoroSubFnInst index argument");
57 return cast<ConstantInt>(getArgOperand(IndexArg));
62 return I->getIntrinsicID() == Intrinsic::coro_subfn_addr;
65 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
74 return I->getIntrinsicID() == Intrinsic::coro_alloc;
77 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
86 if (
auto *CA = dyn_cast<CoroAllocInst>(U))
93 if (
auto *II = dyn_cast<IntrinsicInst>(U))
94 if (II->getIntrinsicID() == Intrinsic::coro_begin)
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;
108 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
114 enum { AlignArg, PromiseArg, CoroutineArg, InfoArg };
118 Value *Arg = getArgOperand(PromiseArg);
119 return isa<ConstantPointerNull>(Arg)
125 Value *Arg = getArgOperand(PromiseArg);
126 setArgOperand(PromiseArg, ConstantPointerNull::get(
127 PointerType::getUnqual(getContext())));
128 if (isa<AllocaInst>(Arg))
130 assert((isa<BitCastInst>(Arg) || isa<GetElementPtrInst>(Arg)) &&
131 "unexpected instruction designating the promise");
134 auto *Inst = cast<Instruction>(Arg);
135 if (Inst->use_empty()) {
136 Inst->eraseFromParent();
139 Inst->moveBefore(getCoroBegin()->getNextNode());
164 auto *GV = dyn_cast<GlobalVariable>(getRawInfo());
168 assert(GV->isConstant() && GV->hasDefinitiveInitializer());
169 Constant *Initializer = GV->getInitializer();
170 if ((Result.OutlinedParts = dyn_cast<ConstantStruct>(Initializer)))
173 Result.Resumers = cast<ConstantArray>(Initializer);
177 return cast<Constant>(getArgOperand(InfoArg)->stripPointerCasts());
183 return cast<Function>(getArgOperand(CoroutineArg)->stripPointerCasts());
186 assert(isa<ConstantPointerNull>(getArgOperand(CoroutineArg)) &&
187 "Coroutine argument is already assigned");
193 return I->getIntrinsicID() == Intrinsic::coro_id;
196 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
203 enum { SizeArg, AlignArg, StorageArg, PrototypeArg, AllocArg, DeallocArg };
206 void checkWellFormed()
const;
209 return cast<ConstantInt>(getArgOperand(SizeArg))->getZExtValue();
213 return cast<ConstantInt>(getArgOperand(AlignArg))->getAlignValue();
217 return getArgOperand(StorageArg);
224 return cast<Function>(getArgOperand(PrototypeArg)->stripPointerCasts());
229 return cast<Function>(getArgOperand(AllocArg)->stripPointerCasts());
234 return cast<Function>(getArgOperand(DeallocArg)->stripPointerCasts());
239 auto ID =
I->getIntrinsicID();
240 return ID == Intrinsic::coro_id_retcon
241 ||
ID == Intrinsic::coro_id_retcon_once;
244 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
254 return I->getIntrinsicID() == Intrinsic::coro_id_retcon;
257 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
267 return I->getIntrinsicID() == Intrinsic::coro_id_retcon_once;
270 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
276 enum { SizeArg, AlignArg, StorageArg, AsyncFuncPtrArg };
279 void checkWellFormed()
const;
285 return cast<ConstantInt>(getArgOperand(SizeArg))->getZExtValue();
290 return cast<ConstantInt>(getArgOperand(AlignArg))->getAlignValue();
295 return getParent()->getParent()->getArg(getStorageArgumentIndex());
299 auto *Arg = cast<ConstantInt>(getArgOperand(StorageArg));
300 return Arg->getZExtValue();
310 return cast<GlobalVariable>(
311 getArgOperand(AsyncFuncPtrArg)->stripPointerCasts());
316 auto ID =
I->getIntrinsicID();
317 return ID == Intrinsic::coro_id_async;
321 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
327 enum { AsyncFuncPtrArg };
331 return cast<GlobalVariable>(
332 getArgOperand(AsyncFuncPtrArg)->stripPointerCasts());
337 return I->getIntrinsicID() == Intrinsic::coro_async_context_alloc;
340 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
347 enum { AsyncContextArg };
356 return I->getIntrinsicID() == Intrinsic::coro_async_context_dealloc;
359 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
370 return I->getIntrinsicID() == Intrinsic::coro_async_resume;
373 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
382 return I->getIntrinsicID() == Intrinsic::coro_async_size_replace;
385 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
394 return I->getIntrinsicID() == Intrinsic::coro_frame;
397 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
403 enum { IdArg, FrameArg };
410 return I->getIntrinsicID() == Intrinsic::coro_free;
413 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
419 enum { IdArg, MemArg };
423 return cast<AnyCoroIdInst>(getArgOperand(IdArg));
430 return I->getIntrinsicID() == Intrinsic::coro_begin;
433 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
442 return I->getIntrinsicID() == Intrinsic::coro_save;
445 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
451 enum { FrameArg, AlignArg, FromArg };
457 return cast<Constant>(getArgOperand(FromArg))->isOneValue();
463 return cast<ConstantInt>(getArgOperand(AlignArg))->getAlignValue();
468 return I->getIntrinsicID() == Intrinsic::coro_promise;
471 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
481 return I->getIntrinsicID() == Intrinsic::coro_suspend ||
482 I->getIntrinsicID() == Intrinsic::coro_suspend_async ||
483 I->getIntrinsicID() == Intrinsic::coro_suspend_retcon;
486 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
492 enum { SaveArg, FinalArg };
496 Value *Arg = getArgOperand(SaveArg);
497 if (
auto *
SI = dyn_cast<CoroSaveInst>(Arg))
499 assert(isa<ConstantTokenNone>(Arg));
504 return cast<Constant>(getArgOperand(FinalArg))->isOneValue();
509 return I->getIntrinsicID() == Intrinsic::coro_suspend;
512 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
517 if (
auto Suspend = dyn_cast<CoroSuspendInst>(
this))
518 return Suspend->getCoroSave();
532 void checkWellFormed()
const;
535 auto *Arg = cast<ConstantInt>(getArgOperand(StorageArgNoArg));
536 return Arg->getZExtValue();
540 return cast<Function>(
541 getArgOperand(AsyncContextProjectionArg)->stripPointerCasts());
545 return cast<CoroAsyncResumeInst>(
546 getArgOperand(ResumeFunctionArg)->stripPointerCasts());
550 return cast<Function>(
551 getArgOperand(MustTailCallFuncArg)->stripPointerCasts());
556 return I->getIntrinsicID() == Intrinsic::coro_suspend_async;
559 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
573 return make_range(value_begin(), value_end());
576 return make_range(value_begin(), value_end());
581 return I->getIntrinsicID() == Intrinsic::coro_suspend_retcon;
584 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
593 return I->getIntrinsicID() == Intrinsic::coro_size;
596 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
605 return I->getIntrinsicID() == Intrinsic::coro_align;
608 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
622 return make_range(retval_begin(), retval_end());
625 return make_range(retval_begin(), retval_end());
629 return std::distance(retval_begin(), retval_end());
634 return I->getIntrinsicID() == Intrinsic::coro_end_results;
637 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
642 enum { FrameArg, UnwindArg, TokenArg };
647 return cast<Constant>(getArgOperand(UnwindArg))->isOneValue();
651 return !isa<ConstantTokenNone>(getArgOperand(TokenArg));
656 return cast<CoroEndResults>(getArgOperand(TokenArg));
661 auto ID =
I->getIntrinsicID();
662 return ID == Intrinsic::coro_end ||
ID == Intrinsic::coro_end_async;
665 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
674 return I->getIntrinsicID() == Intrinsic::coro_end;
677 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
683 enum { FrameArg, UnwindArg, MustTailCallFuncArg };
686 void checkWellFormed()
const;
692 return cast<Function>(
693 getArgOperand(MustTailCallFuncArg)->stripPointerCasts());
698 return I->getIntrinsicID() == Intrinsic::coro_end_async;
701 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
707 enum { SizeArg, AlignArg };
710 return getArgOperand(SizeArg);
713 return cast<ConstantInt>(getArgOperand(AlignArg))->getAlignValue();
718 return I->getIntrinsicID() == Intrinsic::coro_alloca_alloc;
721 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
730 return cast<CoroAllocaAllocInst>(getArgOperand(AllocArg));
735 return I->getIntrinsicID() == Intrinsic::coro_alloca_get;
738 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
747 return cast<CoroAllocaAllocInst>(getArgOperand(AllocArg));
752 return I->getIntrinsicID() == Intrinsic::coro_alloca_free;
755 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
static const Function * getParent(const Value *V)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
#define LLVM_LIBRARY_VISIBILITY
static Function * getFunction(Constant *C)
StandardInstrumentations SI(Mod->getContext(), Debug, VerifyEach)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
an instruction to allocate memory on the stack
bool isFallthrough() const
static bool classof(const Value *V)
static bool classof(const IntrinsicInst *I)
CoroEndResults * getResults() const
This represents a common base class for llvm.coro.id instructions.
IntrinsicInst * getCoroBegin()
static bool classof(const IntrinsicInst *I)
static bool classof(const Value *V)
CoroAllocInst * getCoroAlloc()
This represents either the llvm.coro.id.retcon or llvm.coro.id.retcon.once instruction.
static bool classof(const IntrinsicInst *I)
Value * getStorage() const
Align getStorageAlignment() const
Function * getPrototype() const
Return the prototype for the continuation function.
uint64_t getStorageSize() const
Function * getAllocFunction() const
Return the function to use for allocating memory.
static bool classof(const Value *V)
Function * getDeallocFunction() const
Return the function to use for deallocating memory.
static bool classof(const Value *V)
static bool classof(const IntrinsicInst *I)
CoroSaveInst * getCoroSave() const
ConstantArray - Constant Array Declarations.
This is the shared class of boolean and integer constants.
This is an important base class in LLVM.
This represents the llvm.coro.align instruction.
static bool classof(const Value *V)
static bool classof(const IntrinsicInst *I)
This represents the llvm.coro.alloc instruction.
static bool classof(const IntrinsicInst *I)
static bool classof(const Value *V)
This represents the llvm.coro.alloca.alloc instruction.
static bool classof(const IntrinsicInst *I)
Align getAlignment() const
static bool classof(const Value *V)
This represents the llvm.coro.alloca.free instruction.
static bool classof(const Value *V)
static bool classof(const IntrinsicInst *I)
CoroAllocaAllocInst * getAlloc() const
This represents the llvm.coro.alloca.get instruction.
static bool classof(const Value *V)
CoroAllocaAllocInst * getAlloc() const
static bool classof(const IntrinsicInst *I)
This represents the llvm.coro.context.alloc instruction.
static bool classof(const IntrinsicInst *I)
static bool classof(const Value *V)
GlobalVariable * getAsyncFunctionPointer() const
This represents the llvm.coro.context.dealloc instruction.
Value * getAsyncContext() const
static bool classof(const IntrinsicInst *I)
static bool classof(const Value *V)
This represents the llvm.coro.end instruction.
Function * getMustTailCallFunction() const
static bool classof(const Value *V)
static bool classof(const IntrinsicInst *I)
This represents the llvm.coro.async.resume instruction.
static bool classof(const Value *V)
static bool classof(const IntrinsicInst *I)
This represents the llvm.coro.async.size.replace instruction.
static bool classof(const IntrinsicInst *I)
static bool classof(const Value *V)
This class represents the llvm.coro.begin instruction.
AnyCoroIdInst * getId() const
static bool classof(const IntrinsicInst *I)
static bool classof(const Value *V)
This represents the llvm.coro.end instruction.
static bool classof(const Value *V)
static bool classof(const IntrinsicInst *I)
This represents the llvm.end.results instruction.
op_iterator retval_begin()
const_op_iterator retval_begin() const
iterator_range< const_op_iterator > return_values() const
iterator_range< op_iterator > return_values()
static bool classof(const IntrinsicInst *I)
const_op_iterator retval_end() const
static bool classof(const Value *V)
unsigned numReturns() const
This represents the llvm.coro.frame instruction.
static bool classof(const Value *V)
static bool classof(const IntrinsicInst *I)
This represents the llvm.coro.free instruction.
static bool classof(const Value *V)
static bool classof(const IntrinsicInst *I)
This represents the llvm.coro.id.async instruction.
Align getStorageAlignment() const
The alignment of the initial async function context.
uint64_t getStorageSize() const
The initial async function context size.
GlobalVariable * getAsyncFunctionPointer() const
Return the async function pointer address.
static bool classof(const IntrinsicInst *I)
Value * getStorage() const
The async context parameter.
unsigned getStorageArgumentIndex() const
static bool classof(const Value *V)
This represents the llvm.coro.id instruction.
static bool classof(const Value *V)
void setInfo(Constant *C)
static bool classof(const IntrinsicInst *I)
Function * getCoroutine() const
Constant * getRawInfo() const
AllocaInst * getPromise() const
This represents the llvm.coro.id.retcon instruction.
static bool classof(const IntrinsicInst *I)
static bool classof(const Value *V)
This represents the llvm.coro.id.retcon.once instruction.
static bool classof(const Value *V)
static bool classof(const IntrinsicInst *I)
This represents the llvm.coro.promise instruction.
static bool classof(const Value *V)
Align getAlignment() const
The required alignment of the promise.
bool isFromPromise() const
Are we translating from the frame to the promise (false) or from the promise to the frame (true)?
static bool classof(const IntrinsicInst *I)
This represents the llvm.coro.save instruction.
static bool classof(const Value *V)
static bool classof(const IntrinsicInst *I)
This represents the llvm.coro.size instruction.
static bool classof(const Value *V)
static bool classof(const IntrinsicInst *I)
This class represents the llvm.coro.subfn.addr instruction.
static bool classof(const Value *V)
ResumeKind getIndex() const
ConstantInt * getRawIndex() const
static bool classof(const IntrinsicInst *I)
This represents the llvm.coro.suspend.async instruction.
Function * getAsyncContextProjectionFunction() const
@ AsyncContextProjectionArg
static bool classof(const Value *V)
unsigned getStorageArgumentIndex() const
CoroAsyncResumeInst * getResumeFunction() const
static bool classof(const IntrinsicInst *I)
Function * getMustTailCallFunction() const
This represents the llvm.coro.suspend instruction.
CoroSaveInst * getCoroSave() const
static bool classof(const Value *V)
static bool classof(const IntrinsicInst *I)
This represents the llvm.coro.suspend.retcon instruction.
op_iterator value_begin()
static bool classof(const Value *V)
const_op_iterator value_begin() const
const_op_iterator value_end() const
iterator_range< const_op_iterator > value_operands() const
iterator_range< op_iterator > value_operands()
static bool classof(const IntrinsicInst *I)
A wrapper class for inspecting calls to intrinsic functions.
A Use represents the edge between a Value definition and its users.
LLVM Value Representation.
const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
A range adaptor for a pair of iterators.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
This struct is a compact representation of a valid (non-zero power of two) alignment.
bool hasOutlinedParts() const