LLVM 20.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"
18
19namespace llvm {
20
21class CallGraph;
22
23namespace coro {
24
25enum class ABI {
26 /// The "resume-switch" lowering, where there are separate resume and
27 /// destroy functions that are shared between all suspend points. The
28 /// coroutine frame implicitly stores the resume and destroy functions,
29 /// the current index, and any promise value.
30 Switch,
31
32 /// The "returned-continuation" lowering, where each suspend point creates a
33 /// single continuation function that is used for both resuming and
34 /// destroying. Does not support promises.
35 Retcon,
36
37 /// The "unique returned-continuation" lowering, where each suspend point
38 /// creates a single continuation function that is used for both resuming
39 /// and destroying. Does not support promises. The function is known to
40 /// suspend at most once during its execution, and the return value of
41 /// the continuation is void.
43
44 /// The "async continuation" lowering, where each suspend point creates a
45 /// single continuation function. The continuation function is available as an
46 /// intrinsic.
47 Async,
48};
49
50// Holds structural Coroutine Intrinsics for a particular function and other
51// values used during CoroSplit pass.
52struct Shape {
60
61 // Values invalidated by replaceSwiftErrorOps()
63
64 void clear() {
65 CoroBegin = nullptr;
66 CoroEnds.clear();
67 CoroSizes.clear();
68 CoroAligns.clear();
69 CoroSuspends.clear();
70 CoroAwaitSuspends.clear();
71 SymmetricTransfers.clear();
72
73 SwiftErrorOps.clear();
74
75 FrameTy = nullptr;
76 FramePtr = nullptr;
77 AllocaSpillBlock = nullptr;
78 }
79
80 // Scan the function and collect the above intrinsics for later processing
82 SmallVectorImpl<CoroSaveInst *> &UnusedCoroSaves);
83 // If for some reason, we were not able to find coro.begin, bailout.
86 // Perform ABI related initial transformation
87 void initABI();
88 // Remove orphaned and unnecessary intrinsics
90 SmallVectorImpl<CoroSaveInst *> &UnusedCoroSaves);
91
92 // Field indexes for special fields in the switch lowering.
94 enum {
97
98 // The promise field is always at a fixed offset from the start of
99 // frame given its type, but the index isn't a constant for all
100 // possible frames.
101
102 // The switch-index field isn't at a fixed offset or index, either;
103 // we just work it in where it fits best.
104 };
105 };
106
108
109 StructType *FrameTy = nullptr;
112 Value *FramePtr = nullptr;
114
119 unsigned IndexField;
120 unsigned IndexAlign;
121 unsigned IndexOffset;
124 };
125
132 };
133
137 unsigned ContextArgNo;
140 uint64_t FrameOffset; // Start of the frame.
141 uint64_t ContextSize; // Includes frame size.
143
145 };
146
147 union {
151 };
152
155 return cast<CoroIdInst>(CoroBegin->getId());
156 }
157
160 return cast<AnyCoroIdRetconInst>(CoroBegin->getId());
161 }
162
165 return cast<CoroIdAsyncInst>(CoroBegin->getId());
166 }
167
168 unsigned getSwitchIndexField() const {
170 assert(FrameTy && "frame type not assigned");
172 }
175 assert(FrameTy && "frame type not assigned");
176 return cast<IntegerType>(FrameTy->getElementType(getSwitchIndexField()));
177 }
179 return ConstantInt::get(getIndexType(), Value);
180 }
181
184 assert(FrameTy && "frame type not assigned");
185 return cast<PointerType>(FrameTy->getElementType(SwitchFieldIndex::Resume));
186 }
187
189 switch (ABI) {
193 /*IsVarArg=*/false);
197 case coro::ABI::Async:
198 // Not used. The function type depends on the active suspend.
199 return nullptr;
200 }
201
202 llvm_unreachable("Unknown coro::ABI enum");
203 }
204
207 auto FTy = CoroBegin->getFunction()->getFunctionType();
208
209 // The safety of all this is checked by checkWFRetconPrototype.
210 if (auto STy = dyn_cast<StructType>(FTy->getReturnType())) {
211 return STy->elements().slice(1);
212 } else {
213 return ArrayRef<Type *>();
214 }
215 }
216
219
220 // The safety of all this is checked by checkWFRetconPrototype.
222 return FTy->params().slice(1);
223 }
224
226 switch (ABI) {
228 return CallingConv::Fast;
229
233 case coro::ABI::Async:
234 return AsyncLowering.AsyncCC;
235 }
236 llvm_unreachable("Unknown coro::ABI enum");
237 }
238
240 if (ABI == coro::ABI::Switch)
242 return nullptr;
243 }
244
246 if (auto *I = dyn_cast<Instruction>(FramePtr)) {
247 BasicBlock::iterator It = std::next(I->getIterator());
248 It.setHeadBit(true); // Copy pre-RemoveDIs behaviour.
249 return It;
250 }
251 return cast<Argument>(FramePtr)->getParent()->getEntryBlock().begin();
252 }
253
254 /// Allocate memory according to the rules of the active lowering.
255 ///
256 /// \param CG - if non-null, will be updated for the new call
257 Value *emitAlloc(IRBuilder<> &Builder, Value *Size, CallGraph *CG) const;
258
259 /// Deallocate memory according to the rules of the active lowering.
260 ///
261 /// \param CG - if non-null, will be updated for the new call
262 void emitDealloc(IRBuilder<> &Builder, Value *Ptr, CallGraph *CG) const;
263
264 Shape() = default;
265 explicit Shape(Function &F) {
267 SmallVector<CoroSaveInst *, 2> UnusedCoroSaves;
268
269 analyze(F, CoroFrames, UnusedCoroSaves);
270 if (!CoroBegin) {
271 invalidateCoroutine(F, CoroFrames);
272 return;
273 }
274 cleanCoroutine(CoroFrames, UnusedCoroSaves);
275 }
276};
277
278} // end namespace coro
279
280} // end namespace llvm
281
282#endif // LLVM_TRANSFORMS_COROUTINES_COROSHAPE_H
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
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
an instruction to allocate memory on the stack
Definition: Instructions.h:63
This represents either the llvm.coro.id.retcon or llvm.coro.id.retcon.once instruction.
Definition: CoroInstr.h:236
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:61
InstListType::iterator iterator
Instruction iterators...
Definition: BasicBlock.h:177
The basic data container for the call graph of a Module of IR.
Definition: CallGraph.h:71
This is the shared class of boolean and integer constants.
Definition: Constants.h:83
This class represents the llvm.coro.begin or llvm.coro.begin.custom.abi instructions.
Definition: CoroInstr.h:448
AnyCoroIdInst * getId() const
Definition: CoroInstr.h:452
This represents the llvm.coro.id.async instruction.
Definition: CoroInstr.h:305
This represents the llvm.coro.id instruction.
Definition: CoroInstr.h:147
Class to represent function types.
Definition: DerivedTypes.h:105
ArrayRef< Type * > params() const
Definition: DerivedTypes.h:132
static 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:216
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
Definition: Function.h:277
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition: IRBuilder.h:2697
const Function * getFunction() const
Return the function this instruction belongs to.
Definition: Instruction.cpp:70
Class to represent integer types.
Definition: DerivedTypes.h:42
Class to represent pointers.
Definition: DerivedTypes.h:670
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:686
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:573
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
Class to represent struct types.
Definition: DerivedTypes.h:218
Type * getElementType(unsigned N) const
Definition: DerivedTypes.h:366
Multiway switch.
static 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:74
#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:59
SmallVector< CoroAwaitSuspendInst *, 4 > CoroAwaitSuspends
Definition: CoroShape.h:58
AsyncLoweringStorage AsyncLowering
Definition: CoroShape.h:150
FunctionType * getResumeFunctionType() const
Definition: CoroShape.h:188
IntegerType * getIndexType() const
Definition: CoroShape.h:173
StructType * FrameTy
Definition: CoroShape.h:109
AnyCoroIdRetconInst * getRetconCoroId() const
Definition: CoroShape.h:158
PointerType * getSwitchResumePointerType() const
Definition: CoroShape.h:182
CoroIdInst * getSwitchCoroId() const
Definition: CoroShape.h:153
SmallVector< CoroSizeInst *, 2 > CoroSizes
Definition: CoroShape.h:55
CallingConv::ID getResumeFunctionCC() const
Definition: CoroShape.h:225
coro::ABI ABI
Definition: CoroShape.h:107
Shape(Function &F)
Definition: CoroShape.h:265
ArrayRef< Type * > getRetconResumeTypes() const
Definition: CoroShape.h:217
Value * FramePtr
Definition: CoroShape.h:112
SmallVector< AnyCoroSuspendInst *, 4 > CoroSuspends
Definition: CoroShape.h:57
uint64_t FrameSize
Definition: CoroShape.h:111
Value * emitAlloc(IRBuilder<> &Builder, Value *Size, CallGraph *CG) const
Allocate memory according to the rules of the active lowering.
Definition: Coroutines.cpp:505
void cleanCoroutine(SmallVectorImpl< CoroFrameInst * > &CoroFrames, SmallVectorImpl< CoroSaveInst * > &UnusedCoroSaves)
Definition: Coroutines.cpp:479
ConstantInt * getIndex(uint64_t Value) const
Definition: CoroShape.h:178
AllocaInst * getPromiseAlloca() const
Definition: CoroShape.h:239
SwitchLoweringStorage SwitchLowering
Definition: CoroShape.h:148
CoroBeginInst * CoroBegin
Definition: CoroShape.h:53
BasicBlock::iterator getInsertPtAfterFramePtr() const
Definition: CoroShape.h:245
ArrayRef< Type * > getRetconResultTypes() const
Definition: CoroShape.h:205
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:149
SmallVector< CoroAlignInst *, 2 > CoroAligns
Definition: CoroShape.h:56
CoroIdAsyncInst * getAsyncCoroId() const
Definition: CoroShape.h:163
SmallVector< AnyCoroEndInst *, 4 > CoroEnds
Definition: CoroShape.h:54
SmallVector< CallInst *, 2 > SwiftErrorOps
Definition: CoroShape.h:62
void invalidateCoroutine(Function &F, SmallVectorImpl< CoroFrameInst * > &CoroFrames)
Definition: Coroutines.cpp:349
BasicBlock * AllocaSpillBlock
Definition: CoroShape.h:113
unsigned getSwitchIndexField() const
Definition: CoroShape.h:168
void analyze(Function &F, SmallVectorImpl< CoroFrameInst * > &CoroFrames, SmallVectorImpl< CoroSaveInst * > &UnusedCoroSaves)
Definition: Coroutines.cpp:194