LLVM 22.0.0git
CoroShape.h
Go to the documentation of this file.
1//===- CoroShape.h - Coroutine info for lowering --------------*- 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 declares the shape info struct that is required by many coroutine
9// utility methods.
10//===----------------------------------------------------------------------===//
11
12#ifndef LLVM_TRANSFORMS_COROUTINES_COROSHAPE_H
13#define LLVM_TRANSFORMS_COROUTINES_COROSHAPE_H
14
15#include "llvm/IR/IRBuilder.h"
16#include "llvm/IR/PassManager.h"
19
20namespace llvm {
21
22class CallGraph;
23
24namespace coro {
25
26enum class ABI {
27 /// The "resume-switch" lowering, where there are separate resume and
28 /// destroy functions that are shared between all suspend points. The
29 /// coroutine frame implicitly stores the resume and destroy functions,
30 /// the current index, and any promise value.
32
33 /// The "returned-continuation" lowering, where each suspend point creates a
34 /// single continuation function that is used for both resuming and
35 /// destroying. Does not support promises.
37
38 /// The "unique returned-continuation" lowering, where each suspend point
39 /// creates a single continuation function that is used for both resuming
40 /// and destroying. Does not support promises. The function is known to
41 /// suspend at most once during its execution, and the return value of
42 /// the continuation is void.
44
45 /// The "async continuation" lowering, where each suspend point creates a
46 /// single continuation function. The continuation function is available as an
47 /// intrinsic.
49};
50
51// Holds structural Coroutine Intrinsics for a particular function and other
52// values used during CoroSplit pass.
53struct Shape {
61
62 // Values invalidated by replaceSwiftErrorOps()
64
65 void clear() {
66 CoroBegin = nullptr;
67 CoroEnds.clear();
68 CoroSizes.clear();
69 CoroAligns.clear();
70 CoroSuspends.clear();
71 CoroAwaitSuspends.clear();
72 SymmetricTransfers.clear();
73
74 SwiftErrorOps.clear();
75
76 FrameTy = nullptr;
77 FramePtr = nullptr;
78 AllocaSpillBlock = nullptr;
79 }
80
81 // Scan the function and collect the above intrinsics for later processing
84 SmallVectorImpl<CoroSaveInst *> &UnusedCoroSaves,
85 CoroPromiseInst *&CoroPromise);
86 // If for some reason, we were not able to find coro.begin, bailout.
87 LLVM_ABI void
90 // Perform ABI related initial transformation
92 // Remove orphaned and unnecessary intrinsics
94 SmallVectorImpl<CoroSaveInst *> &UnusedCoroSaves,
95 CoroPromiseInst *CoroPromise);
96
97 // Field indexes for special fields in the switch lowering.
99 enum {
102
103 // The promise field is always at a fixed offset from the start of
104 // frame given its type, but the index isn't a constant for all
105 // possible frames.
106
107 // The switch-index field isn't at a fixed offset or index, either;
108 // we just work it in where it fits best.
109 };
110 };
111
113
114 StructType *FrameTy = nullptr;
117 Value *FramePtr = nullptr;
119
130
138
151
152 union {
156 };
157
160 return cast<CoroIdInst>(CoroBegin->getId());
161 }
162
167
172
173 unsigned getSwitchIndexField() const {
175 assert(FrameTy && "frame type not assigned");
176 return SwitchLowering.IndexField;
177 }
180 assert(FrameTy && "frame type not assigned");
181 return cast<IntegerType>(FrameTy->getElementType(getSwitchIndexField()));
182 }
184 return ConstantInt::get(getIndexType(), Value);
185 }
186
189 assert(FrameTy && "frame type not assigned");
190 return cast<PointerType>(FrameTy->getElementType(SwitchFieldIndex::Resume));
191 }
192
194 switch (ABI) {
196 return FunctionType::get(Type::getVoidTy(FrameTy->getContext()),
197 PointerType::getUnqual(FrameTy->getContext()),
198 /*IsVarArg=*/false);
201 return RetconLowering.ResumePrototype->getFunctionType();
202 case coro::ABI::Async:
203 // Not used. The function type depends on the active suspend.
204 return nullptr;
205 }
206
207 llvm_unreachable("Unknown coro::ABI enum");
208 }
209
212 auto FTy = CoroBegin->getFunction()->getFunctionType();
213
214 // The safety of all this is checked by checkWFRetconPrototype.
215 if (auto STy = dyn_cast<StructType>(FTy->getReturnType())) {
216 return STy->elements().slice(1);
217 } else {
218 return ArrayRef<Type *>();
219 }
220 }
221
224
225 // The safety of all this is checked by checkWFRetconPrototype.
226 auto FTy = RetconLowering.ResumePrototype->getFunctionType();
227 return FTy->params().slice(1);
228 }
229
231 switch (ABI) {
233 return CallingConv::Fast;
234
237 return RetconLowering.ResumePrototype->getCallingConv();
238 case coro::ABI::Async:
239 return AsyncLowering.AsyncCC;
240 }
241 llvm_unreachable("Unknown coro::ABI enum");
242 }
243
245 if (ABI == coro::ABI::Switch)
246 return SwitchLowering.PromiseAlloca;
247 return nullptr;
248 }
249
251 if (auto *I = dyn_cast<Instruction>(FramePtr)) {
252 BasicBlock::iterator It = std::next(I->getIterator());
253 It.setHeadBit(true); // Copy pre-RemoveDIs behaviour.
254 return It;
255 }
256 return cast<Argument>(FramePtr)->getParent()->getEntryBlock().begin();
257 }
258
259 /// Allocate memory according to the rules of the active lowering.
260 ///
261 /// \param CG - if non-null, will be updated for the new call
263 CallGraph *CG) const;
264
265 /// Deallocate memory according to the rules of the active lowering.
266 ///
267 /// \param CG - if non-null, will be updated for the new call
268 LLVM_ABI void emitDealloc(IRBuilder<> &Builder, Value *Ptr,
269 CallGraph *CG) const;
270
271 Shape() = default;
272 explicit Shape(Function &F) {
274 SmallVector<CoroSaveInst *, 2> UnusedCoroSaves;
275 CoroPromiseInst *CoroPromise = nullptr;
276
277 analyze(F, CoroFrames, UnusedCoroSaves, CoroPromise);
278 if (!CoroBegin) {
279 invalidateCoroutine(F, CoroFrames);
280 return;
281 }
282 cleanCoroutine(CoroFrames, UnusedCoroSaves, CoroPromise);
283 }
284};
285
286} // end namespace coro
287
288} // end namespace llvm
289
290#endif // LLVM_TRANSFORMS_COROUTINES_COROSHAPE_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define LLVM_ABI
Definition Compiler.h:213
This header defines various interfaces for pass management in LLVM.
#define F(x, y, z)
Definition MD5.cpp:55
#define I(x, y, z)
Definition MD5.cpp:58
an instruction to allocate memory on the stack
This represents either the llvm.coro.id.retcon or llvm.coro.id.retcon.once instruction.
Definition CoroInstr.h:237
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:41
LLVM Basic Block Representation.
Definition BasicBlock.h:62
InstListType::iterator iterator
Instruction iterators...
Definition BasicBlock.h:170
The basic data container for the call graph of a Module of IR.
Definition CallGraph.h:72
This is the shared class of boolean and integer constants.
Definition Constants.h:87
This class represents the llvm.coro.begin or llvm.coro.begin.custom.abi instructions.
Definition CoroInstr.h:449
This represents the llvm.coro.id.async instruction.
Definition CoroInstr.h:306
This represents the llvm.coro.id instruction.
Definition CoroInstr.h:148
This represents the llvm.coro.promise instruction.
Definition CoroInstr.h:490
Class to represent function types.
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition IRBuilder.h:2780
Class to represent integer types.
Class to represent pointers.
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the default address space (address sp...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Class to represent struct types.
Multiway switch.
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
Definition Type.cpp:281
LLVM Value Representation.
Definition Value.h:75
#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.
Definition CallingConv.h:24
@ Fast
Attempts to make calls as fast as possible (e.g.
Definition CallingConv.h:41
@ Async
The "async continuation" lowering, where each suspend point creates a single continuation function.
Definition CoroShape.h:48
@ RetconOnce
The "unique returned-continuation" lowering, where each suspend point creates a single continuation f...
Definition CoroShape.h:43
@ Retcon
The "returned-continuation" lowering, where each suspend point creates a single continuation function...
Definition CoroShape.h:36
@ Switch
The "resume-switch" lowering, where there are separate resume and destroy functions that are shared b...
Definition CoroShape.h:31
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.
Definition Casting.h:649
ArrayRef(const T &OneElt) -> ArrayRef< T >
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:565
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
SmallVector< CallInst *, 2 > SymmetricTransfers
Definition CoroShape.h:60
SmallVector< CoroAwaitSuspendInst *, 4 > CoroAwaitSuspends
Definition CoroShape.h:59
AsyncLoweringStorage AsyncLowering
Definition CoroShape.h:155
FunctionType * getResumeFunctionType() const
Definition CoroShape.h:193
IntegerType * getIndexType() const
Definition CoroShape.h:178
StructType * FrameTy
Definition CoroShape.h:114
LLVM_ABI void cleanCoroutine(SmallVectorImpl< CoroFrameInst * > &CoroFrames, SmallVectorImpl< CoroSaveInst * > &UnusedCoroSaves, CoroPromiseInst *CoroPromise)
AnyCoroIdRetconInst * getRetconCoroId() const
Definition CoroShape.h:163
PointerType * getSwitchResumePointerType() const
Definition CoroShape.h:187
CoroIdInst * getSwitchCoroId() const
Definition CoroShape.h:158
LLVM_ABI void initABI()
SmallVector< CoroSizeInst *, 2 > CoroSizes
Definition CoroShape.h:56
LLVM_ABI void analyze(Function &F, SmallVectorImpl< CoroFrameInst * > &CoroFrames, SmallVectorImpl< CoroSaveInst * > &UnusedCoroSaves, CoroPromiseInst *&CoroPromise)
CallingConv::ID getResumeFunctionCC() const
Definition CoroShape.h:230
Shape(Function &F)
Definition CoroShape.h:272
ArrayRef< Type * > getRetconResumeTypes() const
Definition CoroShape.h:222
SmallVector< AnyCoroSuspendInst *, 4 > CoroSuspends
Definition CoroShape.h:58
uint64_t FrameSize
Definition CoroShape.h:116
LLVM_ABI Value * emitAlloc(IRBuilder<> &Builder, Value *Size, CallGraph *CG) const
Allocate memory according to the rules of the active lowering.
ConstantInt * getIndex(uint64_t Value) const
Definition CoroShape.h:183
AllocaInst * getPromiseAlloca() const
Definition CoroShape.h:244
SwitchLoweringStorage SwitchLowering
Definition CoroShape.h:153
CoroBeginInst * CoroBegin
Definition CoroShape.h:54
BasicBlock::iterator getInsertPtAfterFramePtr() const
Definition CoroShape.h:250
ArrayRef< Type * > getRetconResultTypes() const
Definition CoroShape.h:210
LLVM_ABI void emitDealloc(IRBuilder<> &Builder, Value *Ptr, CallGraph *CG) const
Deallocate memory according to the rules of the active lowering.
RetconLoweringStorage RetconLowering
Definition CoroShape.h:154
SmallVector< CoroAlignInst *, 2 > CoroAligns
Definition CoroShape.h:57
CoroIdAsyncInst * getAsyncCoroId() const
Definition CoroShape.h:168
SmallVector< AnyCoroEndInst *, 4 > CoroEnds
Definition CoroShape.h:55
SmallVector< CallInst *, 2 > SwiftErrorOps
Definition CoroShape.h:63
LLVM_ABI void invalidateCoroutine(Function &F, SmallVectorImpl< CoroFrameInst * > &CoroFrames)
BasicBlock * AllocaSpillBlock
Definition CoroShape.h:118
unsigned getSwitchIndexField() const
Definition CoroShape.h:173