20#define DEBUG_TYPE "coro-early"
36 : LowererBase(M), Builder(Context),
37 AnyResumeFnPtrTy(PointerType::getUnqual(Context)) {}
46void Lowerer::lowerResumeOrDestroy(
CallBase &CB,
69 DL.getStructLayout(SampleStruct)->getElementOffset(2), Alignment);
73 Builder.SetInsertPoint(Intrin);
75 Builder.CreateConstInBoundsGEP1_32(Int8Ty, Operand,
Offset);
86 Value *Operand =
II->getArgOperand(0);
90 "resume function not at offset zero");
91 auto *FrameTy = Int8Ptr;
93 Builder.SetInsertPoint(
II);
94 auto *
Load = Builder.CreateLoad(FrameTy, Operand);
95 auto *
Cond = Builder.CreateICmpEQ(Load, NullPtr);
97 II->replaceAllUsesWith(
Cond);
98 II->eraseFromParent();
103 if (M.debug_compile_units().empty())
108 std::array<Metadata *, 2> Params{
nullptr,
nullptr};
109 auto *SubroutineType =
110 DB.createSubroutineType(DB.getOrCreateTypeArray(Params));
112 auto *SP = DB.createFunction(
114 0, SubroutineType, 0, DINode::FlagArtificial,
115 DISubprogram::SPFlagDefinition);
128 auto *FnPtrTy = Builder.getPtrTy(0);
135 "__NoopCoro_ResumeDestroy", &M);
142 Constant* Values[] = {NoopFn, NoopFn};
145 GlobalVariable::PrivateLinkage, NoopCoroConst,
146 "NoopCoro.Frame.Const");
147 cast<GlobalVariable>(NoopCoro)->setNoSanitizeMetadata();
150 Builder.SetInsertPoint(
II);
151 auto *NoopCoroVoidPtr = Builder.CreateBitCast(NoopCoro, Int8Ptr);
152 II->replaceAllUsesWith(NoopCoroVoidPtr);
153 II->eraseFromParent();
162 if (
auto *CB = dyn_cast<CoroBeginInst>(U))
166void Lowerer::lowerEarlyIntrinsics(
Function &
F) {
169 bool HasCoroSuspend =
false;
171 auto *CB = dyn_cast<CallBase>(&
I);
178 case Intrinsic::coro_free:
181 case Intrinsic::coro_suspend:
184 if (cast<CoroSuspendInst>(&
I)->isFinal())
186 HasCoroSuspend =
true;
188 case Intrinsic::coro_end_async:
189 case Intrinsic::coro_end:
192 if (cast<AnyCoroEndInst>(&
I)->isFallthrough())
195 case Intrinsic::coro_noop:
196 lowerCoroNoop(cast<IntrinsicInst>(&
I));
198 case Intrinsic::coro_id:
199 if (
auto *CII = cast<CoroIdInst>(&
I)) {
200 if (CII->getInfo().isPreSplit()) {
201 assert(
F.isPresplitCoroutine() &&
202 "The frontend uses Switch-Resumed ABI should emit "
203 "\"presplitcoroutine\" attribute for the coroutine.");
205 CII->setCoroutineSelf();
206 CoroId = cast<CoroIdInst>(&
I);
210 case Intrinsic::coro_id_retcon:
211 case Intrinsic::coro_id_retcon_once:
212 case Intrinsic::coro_id_async:
213 F.setPresplitCoroutine();
215 case Intrinsic::coro_resume:
218 case Intrinsic::coro_destroy:
221 case Intrinsic::coro_promise:
222 lowerCoroPromise(cast<CoroPromiseInst>(&
I));
224 case Intrinsic::coro_done:
225 lowerCoroDone(cast<IntrinsicInst>(&
I));
235 CF->setArgOperand(0, CoroId);
242 if (
A.hasNoAliasAttr())
243 A.removeAttr(Attribute::NoAlias);
248 M, {
"llvm.coro.id",
"llvm.coro.id.retcon",
"llvm.coro.id.retcon.once",
249 "llvm.coro.id.async",
"llvm.coro.destroy",
"llvm.coro.done",
250 "llvm.coro.end",
"llvm.coro.end.async",
"llvm.coro.noop",
251 "llvm.coro.free",
"llvm.coro.promise",
"llvm.coro.resume",
252 "llvm.coro.suspend"});
261 L.lowerEarlyIntrinsics(
F);
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Expand Atomic instructions
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.
uint64_t IntrinsicInst * II
const SmallVectorImpl< MachineOperand > & Cond
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)
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...
InstListType::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, InsertPosition 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.
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.
static Type * getVoidTy(LLVMContext &C)
static IntegerType * getInt8Ty(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)