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.
31 Switch,
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.
36 Retcon,
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.
48 Async,
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 {
101 Destroy
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
124 unsigned IndexField;
125 unsigned IndexAlign;
126 unsigned IndexOffset;
129 };
130
137 };
138
142 unsigned ContextArgNo;
145 uint64_t FrameOffset; // Start of the frame.
146 uint64_t ContextSize; // Includes frame size.
148
150 };
151
152 union {
156 };
157
160 return cast<CoroIdInst>(CoroBegin->getId());
161 }
162
165 return cast<AnyCoroIdRetconInst>(CoroBegin->getId());
166 }
167
170 return cast<CoroIdAsyncInst>(CoroBegin->getId());
171 }
172
173 unsigned getSwitchIndexField() const {
175 assert(FrameTy && "frame type not assigned");
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) {
198 /*IsVarArg=*/false);
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.
227 return FTy->params().slice(1);
228 }
229
231 switch (ABI) {
233 return CallingConv::Fast;
234
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)
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
uint64_t Size
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
Definition: Instructions.h:64
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
AnyCoroIdInst * getId() const
Definition: CoroInstr.h:453
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.
Definition: DerivedTypes.h:105
ArrayRef< Type * > params() const
Definition: DerivedTypes.h:132
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Definition: Function.h:209
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
Definition: Function.h:270
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition: IRBuilder.h:2780
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
Definition: Instruction.cpp:82
Class to represent integer types.
Definition: DerivedTypes.h:42
Class to represent pointers.
Definition: DerivedTypes.h:700
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the default address space (address sp...
Definition: DerivedTypes.h:720
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:574
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1197
Class to represent struct types.
Definition: DerivedTypes.h:218
Type * getElementType(unsigned N) const
Definition: DerivedTypes.h:369
Multiway switch.
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
LLVMContext & getContext() const
Return the LLVMContext in which this type was uniqued.
Definition: Type.h:128
LLVM Value Representation.
Definition: Value.h:75
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ 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.
@ 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...
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
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)
Definition: Coroutines.cpp:472
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)
Definition: Coroutines.cpp:181
CallingConv::ID getResumeFunctionCC() const
Definition: CoroShape.h:230
coro::ABI ABI
Definition: CoroShape.h:112
Shape(Function &F)
Definition: CoroShape.h:272
ArrayRef< Type * > getRetconResumeTypes() const
Definition: CoroShape.h:222
Value * FramePtr
Definition: CoroShape.h:117
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.
Definition: Coroutines.cpp:505
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.
Definition: Coroutines.cpp:528
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)
Definition: Coroutines.cpp:342
BasicBlock * AllocaSpillBlock
Definition: CoroShape.h:118
unsigned getSwitchIndexField() const
Definition: CoroShape.h:173