Thanks to visit codestin.com
Credit goes to llvm.org

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 {
62
63 // Values invalidated by replaceSwiftErrorOps()
65
66 void clear() {
67 CoroBegin = nullptr;
68 CoroEnds.clear();
69 CoroIsInRampInsts.clear();
70 CoroSizes.clear();
71 CoroAligns.clear();
72 CoroSuspends.clear();
73 CoroAwaitSuspends.clear();
74 SymmetricTransfers.clear();
75
76 SwiftErrorOps.clear();
77
78 FrameTy = nullptr;
79 FramePtr = nullptr;
80 AllocaSpillBlock = nullptr;
81 }
82
83 // Scan the function and collect the above intrinsics for later processing
86 SmallVectorImpl<CoroSaveInst *> &UnusedCoroSaves,
87 CoroPromiseInst *&CoroPromise);
88 // If for some reason, we were not able to find coro.begin, bailout.
89 LLVM_ABI void
92 // Perform ABI related initial transformation
94 // Remove orphaned and unnecessary intrinsics
96 SmallVectorImpl<CoroSaveInst *> &UnusedCoroSaves,
97 CoroPromiseInst *CoroPromise);
98
99 // Field indexes for special fields in the switch lowering.
101 enum {
104
105 // The promise field is always at a fixed offset from the start of
106 // frame given its type, but the index isn't a constant for all
107 // possible frames.
108
109 // The switch-index field isn't at a fixed offset or index, either;
110 // we just work it in where it fits best.
111 };
112 };
113
115
116 StructType *FrameTy = nullptr;
119 Value *FramePtr = nullptr;
121
132
140
153
154 union {
158 };
159
162 return cast<CoroIdInst>(CoroBegin->getId());
163 }
164
169
174
175 unsigned getSwitchIndexField() const {
177 assert(FrameTy && "frame type not assigned");
178 return SwitchLowering.IndexField;
179 }
182 assert(FrameTy && "frame type not assigned");
183 return cast<IntegerType>(FrameTy->getElementType(getSwitchIndexField()));
184 }
186 return ConstantInt::get(getIndexType(), Value);
187 }
188
191 assert(FrameTy && "frame type not assigned");
192 return cast<PointerType>(FrameTy->getElementType(SwitchFieldIndex::Resume));
193 }
194
196 switch (ABI) {
198 return FunctionType::get(Type::getVoidTy(FrameTy->getContext()),
199 PointerType::getUnqual(FrameTy->getContext()),
200 /*IsVarArg=*/false);
203 return RetconLowering.ResumePrototype->getFunctionType();
204 case coro::ABI::Async:
205 // Not used. The function type depends on the active suspend.
206 return nullptr;
207 }
208
209 llvm_unreachable("Unknown coro::ABI enum");
210 }
211
214 auto FTy = CoroBegin->getFunction()->getFunctionType();
215
216 // The safety of all this is checked by checkWFRetconPrototype.
217 if (auto STy = dyn_cast<StructType>(FTy->getReturnType())) {
218 return STy->elements().slice(1);
219 } else {
220 return ArrayRef<Type *>();
221 }
222 }
223
226
227 // The safety of all this is checked by checkWFRetconPrototype.
228 auto FTy = RetconLowering.ResumePrototype->getFunctionType();
229 return FTy->params().slice(1);
230 }
231
233 switch (ABI) {
235 return CallingConv::Fast;
236
239 return RetconLowering.ResumePrototype->getCallingConv();
240 case coro::ABI::Async:
241 return AsyncLowering.AsyncCC;
242 }
243 llvm_unreachable("Unknown coro::ABI enum");
244 }
245
247 if (ABI == coro::ABI::Switch)
248 return SwitchLowering.PromiseAlloca;
249 return nullptr;
250 }
251
253 if (auto *I = dyn_cast<Instruction>(FramePtr)) {
254 BasicBlock::iterator It = std::next(I->getIterator());
255 It.setHeadBit(true); // Copy pre-RemoveDIs behaviour.
256 return It;
257 }
258 return cast<Argument>(FramePtr)->getParent()->getEntryBlock().begin();
259 }
260
261 /// Allocate memory according to the rules of the active lowering.
262 ///
263 /// \param CG - if non-null, will be updated for the new call
265 CallGraph *CG) const;
266
267 /// Deallocate memory according to the rules of the active lowering.
268 ///
269 /// \param CG - if non-null, will be updated for the new call
270 LLVM_ABI void emitDealloc(IRBuilder<> &Builder, Value *Ptr,
271 CallGraph *CG) const;
272
273 Shape() = default;
274 explicit Shape(Function &F) {
276 SmallVector<CoroSaveInst *, 2> UnusedCoroSaves;
277 CoroPromiseInst *CoroPromise = nullptr;
278
279 analyze(F, CoroFrames, UnusedCoroSaves, CoroPromise);
280 if (!CoroBegin) {
281 invalidateCoroutine(F, CoroFrames);
282 return;
283 }
284 cleanCoroutine(CoroFrames, UnusedCoroSaves, CoroPromise);
285 }
286};
287
288} // end namespace coro
289
290} // end namespace llvm
291
292#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:461
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:502
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:61
SmallVector< CoroAwaitSuspendInst *, 4 > CoroAwaitSuspends
Definition CoroShape.h:60
AsyncLoweringStorage AsyncLowering
Definition CoroShape.h:157
FunctionType * getResumeFunctionType() const
Definition CoroShape.h:195
IntegerType * getIndexType() const
Definition CoroShape.h:180
StructType * FrameTy
Definition CoroShape.h:116
LLVM_ABI void cleanCoroutine(SmallVectorImpl< CoroFrameInst * > &CoroFrames, SmallVectorImpl< CoroSaveInst * > &UnusedCoroSaves, CoroPromiseInst *CoroPromise)
AnyCoroIdRetconInst * getRetconCoroId() const
Definition CoroShape.h:165
PointerType * getSwitchResumePointerType() const
Definition CoroShape.h:189
CoroIdInst * getSwitchCoroId() const
Definition CoroShape.h:160
LLVM_ABI void initABI()
SmallVector< CoroSizeInst *, 2 > CoroSizes
Definition CoroShape.h:57
LLVM_ABI void analyze(Function &F, SmallVectorImpl< CoroFrameInst * > &CoroFrames, SmallVectorImpl< CoroSaveInst * > &UnusedCoroSaves, CoroPromiseInst *&CoroPromise)
CallingConv::ID getResumeFunctionCC() const
Definition CoroShape.h:232
Shape(Function &F)
Definition CoroShape.h:274
ArrayRef< Type * > getRetconResumeTypes() const
Definition CoroShape.h:224
SmallVector< AnyCoroSuspendInst *, 4 > CoroSuspends
Definition CoroShape.h:59
uint64_t FrameSize
Definition CoroShape.h:118
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:185
AllocaInst * getPromiseAlloca() const
Definition CoroShape.h:246
SwitchLoweringStorage SwitchLowering
Definition CoroShape.h:155
CoroBeginInst * CoroBegin
Definition CoroShape.h:54
BasicBlock::iterator getInsertPtAfterFramePtr() const
Definition CoroShape.h:252
ArrayRef< Type * > getRetconResultTypes() const
Definition CoroShape.h:212
SmallVector< CoroIsInRampInst *, 2 > CoroIsInRampInsts
Definition CoroShape.h:56
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:156
SmallVector< CoroAlignInst *, 2 > CoroAligns
Definition CoroShape.h:58
CoroIdAsyncInst * getAsyncCoroId() const
Definition CoroShape.h:170
SmallVector< AnyCoroEndInst *, 4 > CoroEnds
Definition CoroShape.h:55
SmallVector< CallInst *, 2 > SwiftErrorOps
Definition CoroShape.h:64
LLVM_ABI void invalidateCoroutine(Function &F, SmallVectorImpl< CoroFrameInst * > &CoroFrames)
BasicBlock * AllocaSpillBlock
Definition CoroShape.h:120
unsigned getSwitchIndexField() const
Definition CoroShape.h:175