1 //===- CoroInternal.h - Internal Coroutine interfaces ---------*- C++ -*---===//
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
7 //===----------------------------------------------------------------------===//
8 // Common definitions/declarations used internally by coroutine lowering passes.
9 //===----------------------------------------------------------------------===//
11 #ifndef LLVM_LIB_TRANSFORMS_COROUTINES_COROINTERNAL_H
12 #define LLVM_LIB_TRANSFORMS_COROUTINES_COROINTERNAL_H
14 #include "CoroInstr.h"
15 #include "llvm/Transforms/Coroutines.h"
23 void initializeCoroEarlyPass(PassRegistry
&);
24 void initializeCoroSplitPass(PassRegistry
&);
25 void initializeCoroElidePass(PassRegistry
&);
26 void initializeCoroCleanupPass(PassRegistry
&);
28 // CoroEarly pass marks every function that has coro.begin with a string
29 // attribute "coroutine.presplit"="0". CoroSplit pass processes the coroutine
30 // twice. First, it lets it go through complete IPO optimization pipeline as a
31 // single function. It forces restart of the pipeline by inserting an indirect
32 // call to an empty function "coro.devirt.trigger" which is devirtualized by
33 // CoroElide pass that triggers a restart of the pipeline by CGPassManager.
34 // When CoroSplit pass sees the same coroutine the second time, it splits it up,
35 // adds coroutine subfunctions to the SCC to be processed by IPO pipeline.
37 #define CORO_PRESPLIT_ATTR "coroutine.presplit"
38 #define UNPREPARED_FOR_SPLIT "0"
39 #define PREPARED_FOR_SPLIT "1"
41 #define CORO_DEVIRT_TRIGGER_FN "coro.devirt.trigger"
45 bool declaresIntrinsics(Module
&M
, std::initializer_list
<StringRef
>);
46 void replaceAllCoroAllocs(CoroBeginInst
*CB
, bool Replacement
);
47 void replaceAllCoroFrees(CoroBeginInst
*CB
, Value
*Replacement
);
48 void replaceCoroFree(CoroIdInst
*CoroId
, bool Elide
);
49 void updateCallGraph(Function
&Caller
, ArrayRef
<Function
*> Funcs
,
50 CallGraph
&CG
, CallGraphSCC
&SCC
);
52 // Keeps data and helper functions for lowering coroutine intrinsics.
56 PointerType
*const Int8Ptr
;
57 FunctionType
*const ResumeFnType
;
58 ConstantPointerNull
*const NullPtr
;
60 LowererBase(Module
&M
);
61 Value
*makeSubFnCall(Value
*Arg
, int Index
, Instruction
*InsertPt
);
64 // Holds structural Coroutine Intrinsics for a particular function and other
65 // values used during CoroSplit pass.
66 struct LLVM_LIBRARY_VISIBILITY Shape
{
67 CoroBeginInst
*CoroBegin
;
68 SmallVector
<CoroEndInst
*, 4> CoroEnds
;
69 SmallVector
<CoroSizeInst
*, 2> CoroSizes
;
70 SmallVector
<CoroSuspendInst
*, 4> CoroSuspends
;
72 // Field Indexes for known coroutine frame fields.
81 Instruction
*FramePtr
;
82 BasicBlock
*AllocaSpillBlock
;
83 SwitchInst
*ResumeSwitch
;
84 AllocaInst
*PromiseAlloca
;
87 IntegerType
*getIndexType() const {
88 assert(FrameTy
&& "frame type not assigned");
89 return cast
<IntegerType
>(FrameTy
->getElementType(IndexField
));
91 ConstantInt
*getIndex(uint64_t Value
) const {
92 return ConstantInt::get(getIndexType(), Value
);
96 explicit Shape(Function
&F
) { buildFrom(F
); }
97 void buildFrom(Function
&F
);
100 void buildCoroutineFrame(Function
&F
, Shape
&Shape
);
102 } // End namespace coro.
103 } // End namespace llvm