19#define DEBUG_TYPE "coro-early"
47void Lowerer::lowerResumeOrDestroy(
CallBase &CB,
70 DL.getStructLayout(SampleStruct)->getElementOffset(2), Alignment);
91 "resume function not at offset zero");
92 auto *FrameTy = Int8Ptr;
96 auto *BCI =
Builder.CreateBitCast(Operand, FramePtrTy);
106 if (M.debug_compile_units().empty())
111 std::array<Metadata *, 2> Params{
nullptr,
nullptr};
112 auto *SubroutineType =
113 DB.createSubroutineType(DB.getOrCreateTypeArray(Params));
115 auto *SP = DB.createFunction(
117 0, SubroutineType, 0, DINode::FlagArtificial,
118 DISubprogram::SPFlagDefinition);
133 auto *FnPtrTy = FnTy->getPointerTo();
134 FrameTy->
setBody({FnPtrTy, FnPtrTy});
139 "__NoopCoro_ResumeDestroy", &M);
146 Constant* Values[] = {NoopFn, NoopFn};
149 GlobalVariable::PrivateLinkage, NoopCoroConst,
150 "NoopCoro.Frame.Const");
154 auto *NoopCoroVoidPtr =
Builder.CreateBitCast(NoopCoro, Int8Ptr);
165 if (
auto *CB = dyn_cast<CoroBeginInst>(U))
169void Lowerer::lowerEarlyIntrinsics(
Function &
F) {
172 bool HasCoroSuspend =
false;
174 auto *CB = dyn_cast<CallBase>(&
I);
181 case Intrinsic::coro_free:
184 case Intrinsic::coro_suspend:
187 if (cast<CoroSuspendInst>(&
I)->isFinal())
189 HasCoroSuspend =
true;
191 case Intrinsic::coro_end_async:
192 case Intrinsic::coro_end:
195 if (cast<AnyCoroEndInst>(&
I)->isFallthrough())
198 case Intrinsic::coro_noop:
199 lowerCoroNoop(cast<IntrinsicInst>(&
I));
201 case Intrinsic::coro_id:
202 if (
auto *CII = cast<CoroIdInst>(&
I)) {
203 if (CII->getInfo().isPreSplit()) {
204 assert(
F.isPresplitCoroutine() &&
205 "The frontend uses Swtich-Resumed ABI should emit "
206 "\"coroutine.presplit\" attribute for the coroutine.");
208 CII->setCoroutineSelf();
209 CoroId = cast<CoroIdInst>(&
I);
213 case Intrinsic::coro_id_retcon:
214 case Intrinsic::coro_id_retcon_once:
215 case Intrinsic::coro_id_async:
216 F.setPresplitCoroutine();
218 case Intrinsic::coro_resume:
221 case Intrinsic::coro_destroy:
224 case Intrinsic::coro_promise:
225 lowerCoroPromise(cast<CoroPromiseInst>(&
I));
227 case Intrinsic::coro_done:
228 lowerCoroDone(cast<IntrinsicInst>(&
I));
238 CF->setArgOperand(0, CoroId);
245 if (
A.hasNoAliasAttr())
246 A.removeAttr(Attribute::NoAlias);
251 M, {
"llvm.coro.id",
"llvm.coro.id.retcon",
"llvm.coro.id.retcon.once",
252 "llvm.coro.id.async",
"llvm.coro.destroy",
"llvm.coro.done",
253 "llvm.coro.end",
"llvm.coro.end.async",
"llvm.coro.noop",
254 "llvm.coro.free",
"llvm.coro.promise",
"llvm.coro.resume",
255 "llvm.coro.suspend"});
264 L.lowerEarlyIntrinsics(
F);
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
SmallVector< MachineOperand, 4 > Cond
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static void setCannotDuplicate(CoroIdInst *CoroId)
static bool declaresCoroEarlyIntrinsics(const Module &M)
static void buildDebugInfoForNoopResumeDestroyFunc(Function *NoopFn)
Module.h This file contains the declarations for the Module class.
print must be executed print the must be executed context for all instructions
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A container for analyses that lazily runs them and caches their results.
This class represents an incoming formal argument to a Function.
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Represents analyses that only rely on functions' control flow.
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
void setCallingConv(CallingConv::ID CC)
Value * getArgOperand(unsigned i) const
void setCannotDuplicate()
Intrinsic::ID getIntrinsicID() const
Returns the intrinsic ID of the intrinsic called or Intrinsic::not_intrinsic if the called function i...
void setCalledOperand(Value *V)
static Constant * get(StructType *T, ArrayRef< Constant * > V)
This is an important base class in LLVM.
This represents the llvm.coro.free instruction.
This represents the llvm.coro.id instruction.
This represents the llvm.coro.promise instruction.
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)?
A parsed version of the target data layout string in and methods for querying it.
void setSubprogram(DISubprogram *SP)
Set the attached subprogram.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
void setCallingConv(CallingConv::ID CC)
Module * getParent()
Get the module that this global value is contained inside of...
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
const Module * getModule() const
Return the module owning the function this instruction belongs to or nullptr it the function does not...
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
A wrapper class for inspecting calls to intrinsic functions.
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.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
void preserveSet()
Mark an analysis set as preserved.
static ReturnInst * Create(LLVMContext &C, Value *retVal=nullptr, Instruction *InsertBefore=nullptr)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Class to represent struct types.
static StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
void setBody(ArrayRef< Type * > Elements, bool isPacked=false)
Specify a body for an opaque identified type.
static StructType * create(LLVMContext &Context, StringRef Name)
This creates an identified struct.
The instances of the Type class are immutable: once they are created, they are never changed.
PointerType * getPointerTo(unsigned AddrSpace=0) const
Return a pointer to the current type.
static Type * getVoidTy(LLVMContext &C)
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
iterator_range< user_iterator > users()
StringRef getName() const
Return a constant reference to the value's name.
@ Fast
Attempts to make calls as fast as possible (e.g.
@ C
The default llvm calling convention, compatible with C.
bool declaresIntrinsics(const Module &M, const std::initializer_list< StringRef >)
This is an optimization pass for GlobalISel generic memory operations.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
This struct is a compact representation of a valid (non-zero power of two) alignment.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)