60 "makeSubFnCall: Index value out of range");
68 Intrinsic::coro_alloc,
69 Intrinsic::coro_async_context_alloc,
70 Intrinsic::coro_async_context_dealloc,
71 Intrinsic::coro_async_resume,
72 Intrinsic::coro_async_size_replace,
73 Intrinsic::coro_await_suspend_bool,
74 Intrinsic::coro_await_suspend_handle,
75 Intrinsic::coro_await_suspend_void,
76 Intrinsic::coro_begin,
77 Intrinsic::coro_begin_custom_abi,
78 Intrinsic::coro_destroy,
81 Intrinsic::coro_end_async,
82 Intrinsic::coro_frame,
85 Intrinsic::coro_id_async,
86 Intrinsic::coro_id_retcon,
87 Intrinsic::coro_id_retcon_once,
89 Intrinsic::coro_prepare_async,
90 Intrinsic::coro_prepare_retcon,
91 Intrinsic::coro_promise,
92 Intrinsic::coro_resume,
94 Intrinsic::coro_subfn_addr,
95 Intrinsic::coro_suspend,
96 Intrinsic::coro_is_in_ramp,
112 "Only non-overloaded intrinsics supported");
136 CF->replaceAllUsesWith(Replacement);
137 CF->eraseFromParent();
140 for (
auto *CD : CoroDeads)
141 CD->eraseFromParent();
150 if (CoroAllocs.
empty())
165 for (
auto *CA : CoroAllocs) {
166 CA->replaceAllUsesWith(False);
167 CA->eraseFromParent();
189 bool HasFinalSuspend =
false;
190 bool HasUnwindCoroEnd =
false;
191 size_t FinalSuspendIndex = 0;
199 switch (
II->getIntrinsicID()) {
202 case Intrinsic::coro_size:
205 case Intrinsic::coro_align:
208 case Intrinsic::coro_frame:
211 case Intrinsic::coro_save:
217 case Intrinsic::coro_suspend_async: {
219 Suspend->checkWellFormed();
223 case Intrinsic::coro_suspend_retcon: {
228 case Intrinsic::coro_suspend: {
231 if (Suspend->isFinal()) {
234 "Only one suspend point can be marked as final");
235 HasFinalSuspend =
true;
240 case Intrinsic::coro_begin:
241 case Intrinsic::coro_begin_custom_abi: {
246 if (Id && !Id->getInfo().isPreSplit())
251 "coroutine should have exactly one defining @llvm.coro.begin");
252 CB->addRetAttr(Attribute::NonNull);
253 CB->addRetAttr(Attribute::NoAlias);
254 CB->removeFnAttr(Attribute::NoDuplicate);
258 case Intrinsic::coro_end_async:
259 case Intrinsic::coro_end:
262 AsyncEnd->checkWellFormed();
266 HasUnwindCoroEnd =
true;
273 if (
CoroEnds.front()->isFallthrough())
275 "Only one coro.end can be marked as fallthrough");
280 case Intrinsic::coro_is_in_ramp:
283 case Intrinsic::coro_promise:
284 assert(CoroPromise ==
nullptr &&
285 "CoroEarly must ensure coro.promise unique");
298 switch (
auto IntrID = Id->getIntrinsicID()) {
299 case Intrinsic::coro_id: {
315 case Intrinsic::coro_id_async: {
318 AsyncId->checkWellFormed();
320 AsyncLowering.ContextArgNo = AsyncId->getStorageArgumentIndex();
322 AsyncLowering.ContextAlignment = AsyncId->getStorageAlignment().value();
323 AsyncLowering.AsyncFuncPointer = AsyncId->getAsyncFunctionPointer();
327 case Intrinsic::coro_id_retcon:
328 case Intrinsic::coro_id_retcon_once: {
332 ContinuationId->checkWellFormed();
333 auto Prototype = ContinuationId->getPrototype();
355 CF->replaceAllUsesWith(
Poison);
356 CF->eraseFromParent();
364 if (
auto *CoroSave = CS->getCoroSave())
365 CoroSave->eraseFromParent();
366 CS->eraseFromParent();
379 for (
auto *AnySuspend :
Shape.CoroSuspends) {
388 if (!Suspend->getCoroSave())
401 auto ResultTys =
Shape.getRetconResultTypes();
402 auto ResumeTys =
Shape.getRetconResumeTypes();
404 for (
auto *AnySuspend :
Shape.CoroSuspends) {
411 "coro.suspend.retcon");
415 auto SI = Suspend->value_begin(), SE = Suspend->value_end();
416 auto RI = ResultTys.begin(), RE = ResultTys.end();
417 for (;
SI != SE && RI != RE; ++
SI, ++RI) {
418 auto SrcTy = (*SI)->getType();
424 auto BCI =
new BitCastInst(*
SI, *RI,
"", Suspend->getIterator());
431 Shape.RetconLowering.ResumePrototype->getFunctionType()->dump();
434 "match corresponding prototype function result");
437 if (
SI != SE || RI != RE) {
440 Shape.RetconLowering.ResumePrototype->getFunctionType()->dump();
446 Type *SResultTy = Suspend->getType();
451 SuspendResultTys = SResultStructTy->elements();
454 SuspendResultTys = SResultTy;
456 if (SuspendResultTys.
size() != ResumeTys.size()) {
459 Shape.RetconLowering.ResumePrototype->getFunctionType()->dump();
463 for (
size_t I = 0, E = ResumeTys.size();
I != E; ++
I) {
464 if (SuspendResultTys[
I] != ResumeTys[
I]) {
467 Shape.RetconLowering.ResumePrototype->getFunctionType()->dump();
470 "match corresponding prototype function param");
483 CF->eraseFromParent();
489 CoroSave->eraseFromParent();
490 UnusedCoroSaves.
clear();
501 Call->setCallingConv(Callee->getCallingConv());
507 (*CG)[
Call->getFunction()]->addCalledFunction(
Call, (*CG)[Callee]);
520 Alloc->getFunctionType()->getParamType(0),
542 Ptr = Builder.CreateBitCast(Ptr,
543 Dealloc->getFunctionType()->getParamType(0));
544 auto *
Call = Builder.CreateCall(Dealloc, Ptr);
560 errs() <<
" Value: ";
573 fail(
I,
"llvm.coro.id.retcon.* prototype not a Function", V);
575 auto FT =
F->getFunctionType();
579 if (FT->getReturnType()->isPointerTy()) {
582 ResultOkay = (!SRetTy->isOpaque() &&
583 SRetTy->getNumElements() > 0 &&
584 SRetTy->getElementType(0)->isPointerTy());
589 fail(
I,
"llvm.coro.id.retcon prototype must return pointer as first "
592 if (FT->getReturnType() !=
593 I->getFunction()->getFunctionType()->getReturnType())
594 fail(
I,
"llvm.coro.id.retcon prototype return type must be same as"
595 "current function return type",
F);
600 if (FT->getNumParams() == 0 || !FT->getParamType(0)->isPointerTy())
601 fail(
I,
"llvm.coro.id.retcon.* prototype must take pointer as "
602 "its first parameter",
F);
609 fail(
I,
"llvm.coro.* allocator not a Function", V);
611 auto FT =
F->getFunctionType();
612 if (!FT->getReturnType()->isPointerTy())
613 fail(
I,
"llvm.coro.* allocator must return a pointer",
F);
615 if (FT->getNumParams() != 1 ||
616 !FT->getParamType(0)->isIntegerTy())
617 fail(
I,
"llvm.coro.* allocator must take integer as only param",
F);
624 fail(
I,
"llvm.coro.* deallocator not a Function", V);
626 auto FT =
F->getFunctionType();
627 if (!FT->getReturnType()->isVoidTy())
628 fail(
I,
"llvm.coro.* deallocator must return void",
F);
630 if (FT->getNumParams() != 1 ||
631 !FT->getParamType(0)->isPointerTy())
632 fail(
I,
"llvm.coro.* deallocator must take pointer as only param",
F);
636 const char *Reason) {
644 "size argument to coro.id.retcon.* must be constant");
646 "alignment argument to coro.id.retcon.* must be constant");
654 if (!AsyncFuncPtrAddr)
655 fail(
I,
"llvm.coro.id.async async function pointer not a global", V);
660 "size argument to coro.id.async must be constant");
662 "alignment argument to coro.id.async must be constant");
664 "storage argument offset to coro.id.async must be constant");
670 auto *FunTy =
F->getFunctionType();
671 if (!FunTy->getReturnType()->isPointerTy())
673 "llvm.coro.suspend.async resume function projection function must "
676 if (FunTy->getNumParams() != 1 || !FunTy->getParamType(0)->isPointerTy())
678 "llvm.coro.suspend.async resume function projection function must "
679 "take one ptr type as parameter",
689 if (!MustTailCallFunc)
691 auto *FnTy = MustTailCallFunc->getFunctionType();
692 if (FnTy->getNumParams() != (
arg_size() - 3))
694 "llvm.coro.end.async must tail call function argument type must "
695 "match the tail arguments",
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Expand Atomic instructions
This file contains the simple types necessary to represent the attributes associated with functions a...
static void fail(const SDLoc &DL, SelectionDAG &DAG, const Twine &Msg, SDValue Val={})
This file provides interfaces used to build and manipulate a call graph, which is a very useful tool ...
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static Intrinsic::ID NonOverloadedCoroIntrinsics[]
static void checkWFDealloc(const Instruction *I, Value *V)
Check that the given value is a well-formed deallocator.
static void checkConstantInt(const Instruction *I, Value *V, const char *Reason)
static void checkWFRetconPrototype(const AnyCoroIdRetconInst *I, Value *V)
Check that the given value is a well-formed prototype for the llvm.coro.id.retcon.
static void propagateCallAttrsFromCallee(CallInst *Call, Function *Callee)
static void checkAsyncContextProjectFunction(const Instruction *I, Function *F)
static CoroSaveInst * createCoroSave(CoroBeginInst *CoroBegin, CoroSuspendInst *SuspendInst)
static void checkWFAlloc(const Instruction *I, Value *V)
Check that the given value is a well-formed allocator.
static void addCallToCallGraph(CallGraph *CG, CallInst *Call, Function *Callee)
static void checkAsyncFuncPointer(const Instruction *I, Value *V)
Module.h This file contains the declarations for the Module class.
uint64_t IntrinsicInst * II
This file defines the SmallVector class.
static const unsigned FramePtr
This represents either the llvm.coro.id.retcon or llvm.coro.id.retcon.once instruction.
LLVM_ABI void checkWellFormed() const
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
LLVM Basic Block Representation.
const Instruction & front() const
This class represents a no-op cast from one type to another.
Value * getArgOperand(unsigned i) const
void setArgOperand(unsigned i, Value *v)
unsigned arg_size() const
The basic data container for the call graph of a Module of IR.
This class represents a function call, abstracting a target machine's calling convention.
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
static LLVM_ABI bool isBitCastable(Type *SrcTy, Type *DestTy)
Check whether a bitcast between these types is valid.
static LLVM_ABI ConstantInt * getFalse(LLVMContext &Context)
A constant pointer value that points to null.
static LLVM_ABI ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
Function * getMustTailCallFunction() const
LLVM_ABI void checkWellFormed() const
This class represents the llvm.coro.begin or llvm.coro.begin.custom.abi instructions.
This represents the llvm.coro.frame instruction.
This represents the llvm.coro.free instruction.
LLVM_ABI void checkWellFormed() const
This represents the llvm.coro.id instruction.
This represents the llvm.coro.promise instruction.
bool isFromPromise() const
Are we translating from the frame to the promise (false) or from the promise to the frame (true)?
This represents the llvm.coro.save instruction.
Function * getAsyncContextProjectionFunction() const
LLVM_ABI void checkWellFormed() const
This represents the llvm.coro.suspend instruction.
CoroSaveInst * getCoroSave() const
Class to represent function types.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
LLVM_ABI const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
This is an important class for using LLVM in a threaded context.
A Module instance is used to store all the information related to an LLVM module.
Class to represent pointers.
static LLVM_ABI PointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space.
static LLVM_ABI PoisonValue * get(Type *T)
Static factory methods - Return an 'poison' object of the specified type.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
bool isVoidTy() const
Return true if this is 'void'.
LLVM Value Representation.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVMContext & getContext() const
All values hold a context through their type.
iterator_range< user_iterator > users()
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > Tys={})
Look up the Function declaration of the intrinsic id in the Module M.
LLVM_ABI Function * getDeclarationIfExists(const Module *M, ID id)
Look up the Function declaration of the intrinsic id in the Module M and return it if it exists.
LLVM_ABI bool isOverloaded(ID id)
Returns true if the intrinsic can be overloaded.
@ Async
The "async continuation" lowering, where each suspend point creates a single continuation function.
@ RetconOnce
The "unique returned-continuation" lowering, where each suspend point creates a single continuation f...
@ Retcon
The "returned-continuation" lowering, where each suspend point creates a single continuation function...
@ Switch
The "resume-switch" lowering, where there are separate resume and destroy functions that are shared b...
bool declaresAnyIntrinsic(const Module &M)
bool isSuspendBlock(BasicBlock *BB)
void suppressCoroAllocs(CoroIdInst *CoroId)
Replaces all @llvm.coro.alloc intrinsics calls associated with a given call @llvm....
void elideCoroFree(Value *FramePtr)
bool declaresIntrinsics(const Module &M, ArrayRef< Intrinsic::ID > List)
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
LLVM_ABI unsigned changeToUnreachable(Instruction *I, bool PreserveLCSSA=false, DomTreeUpdater *DTU=nullptr, MemorySSAUpdater *MSSAU=nullptr)
Insert an unreachable instruction before the specified instruction, making it and the rest of the cod...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
PointerType *const Int8Ptr
ConstantPointerNull *const NullPtr
CallInst * makeSubFnCall(Value *Arg, int Index, Instruction *InsertPt)
FunctionType *const ResumeFnType
SmallVector< CoroAwaitSuspendInst *, 4 > CoroAwaitSuspends
AsyncLoweringStorage AsyncLowering
LLVM_ABI void cleanCoroutine(SmallVectorImpl< CoroFrameInst * > &CoroFrames, SmallVectorImpl< CoroSaveInst * > &UnusedCoroSaves, CoroPromiseInst *CoroPromise)
AnyCoroIdRetconInst * getRetconCoroId() const
CoroIdInst * getSwitchCoroId() const
SmallVector< CoroSizeInst *, 2 > CoroSizes
LLVM_ABI void analyze(Function &F, SmallVectorImpl< CoroFrameInst * > &CoroFrames, SmallVectorImpl< CoroSaveInst * > &UnusedCoroSaves, CoroPromiseInst *&CoroPromise)
SmallVector< AnyCoroSuspendInst *, 4 > CoroSuspends
LLVM_ABI Value * emitAlloc(IRBuilder<> &Builder, Value *Size, CallGraph *CG) const
Allocate memory according to the rules of the active lowering.
AllocaInst * getPromiseAlloca() const
SwitchLoweringStorage SwitchLowering
CoroBeginInst * CoroBegin
SmallVector< CoroIsInRampInst *, 2 > CoroIsInRampInsts
LLVM_ABI void emitDealloc(IRBuilder<> &Builder, Value *Ptr, CallGraph *CG) const
Deallocate memory according to the rules of the active lowering.
RetconLoweringStorage RetconLowering
SmallVector< CoroAlignInst *, 2 > CoroAligns
CoroIdAsyncInst * getAsyncCoroId() const
SmallVector< AnyCoroEndInst *, 4 > CoroEnds
LLVM_ABI void invalidateCoroutine(Function &F, SmallVectorImpl< CoroFrameInst * > &CoroFrames)