LLVM  10.0.0svn
CoroInternal.h
Go to the documentation of this file.
1 //===- CoroInternal.h - Internal Coroutine interfaces ---------*- 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 // Common definitions/declarations used internally by coroutine lowering passes.
9 //===----------------------------------------------------------------------===//
10 
11 #ifndef LLVM_LIB_TRANSFORMS_COROUTINES_COROINTERNAL_H
12 #define LLVM_LIB_TRANSFORMS_COROUTINES_COROINTERNAL_H
13 
14 #include "CoroInstr.h"
15 #include "llvm/IR/IRBuilder.h"
17 
18 namespace llvm {
19 
20 class CallGraph;
21 class CallGraphSCC;
22 class PassRegistry;
23 
24 void initializeCoroEarlyPass(PassRegistry &);
25 void initializeCoroSplitPass(PassRegistry &);
26 void initializeCoroElidePass(PassRegistry &);
27 void initializeCoroCleanupPass(PassRegistry &);
28 
29 // CoroEarly pass marks every function that has coro.begin with a string
30 // attribute "coroutine.presplit"="0". CoroSplit pass processes the coroutine
31 // twice. First, it lets it go through complete IPO optimization pipeline as a
32 // single function. It forces restart of the pipeline by inserting an indirect
33 // call to an empty function "coro.devirt.trigger" which is devirtualized by
34 // CoroElide pass that triggers a restart of the pipeline by CGPassManager.
35 // When CoroSplit pass sees the same coroutine the second time, it splits it up,
36 // adds coroutine subfunctions to the SCC to be processed by IPO pipeline.
37 
38 #define CORO_PRESPLIT_ATTR "coroutine.presplit"
39 #define UNPREPARED_FOR_SPLIT "0"
40 #define PREPARED_FOR_SPLIT "1"
41 
42 #define CORO_DEVIRT_TRIGGER_FN "coro.devirt.trigger"
43 
44 namespace coro {
45 
46 bool declaresIntrinsics(Module &M, std::initializer_list<StringRef>);
47 void replaceAllCoroAllocs(CoroBeginInst *CB, bool Replacement);
48 void replaceAllCoroFrees(CoroBeginInst *CB, Value *Replacement);
49 void replaceCoroFree(CoroIdInst *CoroId, bool Elide);
51  CallGraph &CG, CallGraphSCC &SCC);
52 
53 // Keeps data and helper functions for lowering coroutine intrinsics.
54 struct LowererBase {
60 
61  LowererBase(Module &M);
62  Value *makeSubFnCall(Value *Arg, int Index, Instruction *InsertPt);
63 };
64 
65 enum class ABI {
66  /// The "resume-switch" lowering, where there are separate resume and
67  /// destroy functions that are shared between all suspend points. The
68  /// coroutine frame implicitly stores the resume and destroy functions,
69  /// the current index, and any promise value.
70  Switch,
71 
72  /// The "returned-continuation" lowering, where each suspend point creates a
73  /// single continuation function that is used for both resuming and
74  /// destroying. Does not support promises.
75  Retcon,
76 
77  /// The "unique returned-continuation" lowering, where each suspend point
78  /// creates a single continuation function that is used for both resuming
79  /// and destroying. Does not support promises. The function is known to
80  /// suspend at most once during its execution, and the return value of
81  /// the continuation is void.
82  RetconOnce,
83 };
84 
85 // Holds structural Coroutine Intrinsics for a particular function and other
86 // values used during CoroSplit pass.
93 
94  // Field indexes for special fields in the switch lowering.
96  enum {
101  /// The index of the first spill field.
102  FirstSpill
103  };
104  };
105 
107 
111 
117  };
118 
125  };
126 
127  union {
130  };
131 
133  assert(ABI == coro::ABI::Switch);
134  return cast<CoroIdInst>(CoroBegin->getId());
135  }
136 
138  assert(ABI == coro::ABI::Retcon ||
139  ABI == coro::ABI::RetconOnce);
140  return cast<AnyCoroIdRetconInst>(CoroBegin->getId());
141  }
142 
144  assert(ABI == coro::ABI::Switch);
145  assert(FrameTy && "frame type not assigned");
146  return cast<IntegerType>(FrameTy->getElementType(SwitchFieldIndex::Index));
147  }
148  ConstantInt *getIndex(uint64_t Value) const {
149  return ConstantInt::get(getIndexType(), Value);
150  }
151 
153  assert(ABI == coro::ABI::Switch);
154  assert(FrameTy && "frame type not assigned");
155  return cast<PointerType>(FrameTy->getElementType(SwitchFieldIndex::Resume));
156  }
157 
159  switch (ABI) {
160  case coro::ABI::Switch: {
161  auto *FnPtrTy = getSwitchResumePointerType();
162  return cast<FunctionType>(FnPtrTy->getPointerElementType());
163  }
164  case coro::ABI::Retcon:
166  return RetconLowering.ResumePrototype->getFunctionType();
167  }
168  llvm_unreachable("Unknown coro::ABI enum");
169  }
170 
172  assert(ABI == coro::ABI::Retcon ||
173  ABI == coro::ABI::RetconOnce);
174  auto FTy = CoroBegin->getFunction()->getFunctionType();
175 
176  // The safety of all this is checked by checkWFRetconPrototype.
177  if (auto STy = dyn_cast<StructType>(FTy->getReturnType())) {
178  return STy->elements().slice(1);
179  } else {
180  return ArrayRef<Type*>();
181  }
182  }
183 
185  assert(ABI == coro::ABI::Retcon ||
186  ABI == coro::ABI::RetconOnce);
187 
188  // The safety of all this is checked by checkWFRetconPrototype.
189  auto FTy = RetconLowering.ResumePrototype->getFunctionType();
190  return FTy->params().slice(1);
191  }
192 
194  switch (ABI) {
195  case coro::ABI::Switch:
196  return CallingConv::Fast;
197 
198  case coro::ABI::Retcon:
200  return RetconLowering.ResumePrototype->getCallingConv();
201  }
202  llvm_unreachable("Unknown coro::ABI enum");
203  }
204 
205  unsigned getFirstSpillFieldIndex() const {
206  switch (ABI) {
207  case coro::ABI::Switch:
208  return SwitchFieldIndex::FirstSpill;
209 
210  case coro::ABI::Retcon:
212  return 0;
213  }
214  llvm_unreachable("Unknown coro::ABI enum");
215  }
216 
218  if (ABI == coro::ABI::Switch)
219  return SwitchLowering.PromiseAlloca;
220  return nullptr;
221  }
222 
223  /// Allocate memory according to the rules of the active lowering.
224  ///
225  /// \param CG - if non-null, will be updated for the new call
226  Value *emitAlloc(IRBuilder<> &Builder, Value *Size, CallGraph *CG) const;
227 
228  /// Deallocate memory according to the rules of the active lowering.
229  ///
230  /// \param CG - if non-null, will be updated for the new call
231  void emitDealloc(IRBuilder<> &Builder, Value *Ptr, CallGraph *CG) const;
232 
233  Shape() = default;
234  explicit Shape(Function &F) { buildFrom(F); }
235  void buildFrom(Function &F);
236 };
237 
239 
240 } // End namespace coro.
241 } // End namespace llvm
242 
243 #endif
The "returned-continuation" lowering, where each suspend point creates a single continuation function...
Instruction * FramePtr
Definition: CoroInternal.h:109
The "resume-switch" lowering, where there are separate resume and destroy functions that are shared b...
The "unique returned-continuation" lowering, where each suspend point creates a single continuation f...
CoroBeginInst * CoroBegin
Definition: CoroInternal.h:88
This represents the llvm.coro.id instruction.
Definition: CoroInstr.h:113
This class represents lattice values for constants.
Definition: AllocatorList.h:23
Type * getElementType(unsigned N) const
Definition: DerivedTypes.h:346
void initializeCoroEarlyPass(PassRegistry &)
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:65
void initializeCoroElidePass(PassRegistry &)
PointerType * getSwitchResumePointerType() const
Definition: CoroInternal.h:152
Shape(Function &F)
Definition: CoroInternal.h:234
IntegerType * getIndexType() const
Definition: CoroInternal.h:143
SmallVector< CallInst *, 2 > SwiftErrorOps
Definition: CoroInternal.h:92
RetconLoweringStorage RetconLowering
Definition: CoroInternal.h:129
F(f)
FunctionType * getResumeFunctionType() const
Definition: CoroInternal.h:158
PointerType *const Int8Ptr
Definition: CoroInternal.h:57
Class to represent struct types.
Definition: DerivedTypes.h:233
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
Definition: IRBuilder.h:779
ConstantInt * getIndex(uint64_t Value) const
Definition: CoroInternal.h:148
Class to represent function types.
Definition: DerivedTypes.h:103
void initializeCoroSplitPass(PassRegistry &)
FunctionType *const ResumeFnType
Definition: CoroInternal.h:58
CoroIdInst * getSwitchCoroId() const
Definition: CoroInternal.h:132
SmallVector< CoroSizeInst *, 2 > CoroSizes
Definition: CoroInternal.h:90
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: APInt.h:32
AnyCoroIdRetconInst * getRetconCoroId() const
Definition: CoroInternal.h:137
This represents either the llvm.coro.id.retcon or llvm.coro.id.retcon.once instruction.
Definition: CoroInstr.h:204
Class to represent pointers.
Definition: DerivedTypes.h:570
void replaceAllCoroFrees(CoroBeginInst *CB, Value *Replacement)
LLVM Basic Block Representation.
Definition: BasicBlock.h:57
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:64
Fast - This calling convention attempts to make calls as fast as possible (e.g.
Definition: CallingConv.h:42
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
#define LLVM_LIBRARY_VISIBILITY
LLVM_LIBRARY_VISIBILITY - If a class marked with this attribute is linked into a shared library...
Definition: Compiler.h:124
unsigned getFirstSpillFieldIndex() const
Definition: CoroInternal.h:205
Class to represent integer types.
Definition: DerivedTypes.h:40
const Function * getFunction() const
Return the function this instruction belongs to.
Definition: Instruction.cpp:59
AllocaInst * getPromiseAlloca() const
Definition: CoroInternal.h:217
LLVMContext & Context
Definition: CoroInternal.h:56
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
SwitchLoweringStorage SwitchLowering
Definition: CoroInternal.h:128
AnyCoroIdInst * getId() const
Definition: CoroInstr.h:309
StructType * FrameTy
Definition: CoroInternal.h:108
void replaceAllCoroAllocs(CoroBeginInst *CB, bool Replacement)
This is the shared class of boolean and integer constants.
Definition: Constants.h:83
ArrayRef< Type * > getRetconResumeTypes() const
Definition: CoroInternal.h:184
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:837
A constant pointer value that points to null.
Definition: Constants.h:538
ConstantPointerNull *const NullPtr
Definition: CoroInternal.h:59
void buildCoroutineFrame(Function &F, Shape &Shape)
Definition: CoroFrame.cpp:1325
static Constant * get(Type *Ty, uint64_t V, bool isSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
Definition: Constants.cpp:653
CallingConv::ID getResumeFunctionCC() const
Definition: CoroInternal.h:193
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Definition: Function.h:163
This class represents the llvm.coro.begin instruction.
Definition: CoroInstr.h:305
Value * makeSubFnCall(Value *Arg, int Index, Instruction *InsertPt)
Definition: Coroutines.cpp:107
SmallVector< AnyCoroSuspendInst *, 4 > CoroSuspends
Definition: CoroInternal.h:91
void initializeCoroCleanupPass(PassRegistry &)
The basic data container for the call graph of a Module of IR.
Definition: CallGraph.h:73
uint32_t Size
Definition: Profile.cpp:46
void replaceCoroFree(CoroIdInst *CoroId, bool Elide)
Definition: Coroutines.cpp:166
Multiway switch.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
SmallVector< CoroEndInst *, 4 > CoroEnds
Definition: CoroInternal.h:89
LLVM Value Representation.
Definition: Value.h:73
CallGraphSCC - This is a single SCC that a CallGraphSCCPass is run on.
bool declaresIntrinsics(Module &M, std::initializer_list< StringRef >)
Definition: Coroutines.cpp:153
BasicBlock * AllocaSpillBlock
Definition: CoroInternal.h:110
void updateCallGraph(Function &Caller, ArrayRef< Function *> Funcs, CallGraph &CG, CallGraphSCC &SCC)
Definition: Coroutines.cpp:207
an instruction to allocate memory on the stack
Definition: Instructions.h:59
ArrayRef< Type * > getRetconResultTypes() const
Definition: CoroInternal.h:171