]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/llvm/lib/Transforms/Coroutines/CoroInternal.h
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm-project / llvm / lib / Transforms / Coroutines / CoroInternal.h
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/Transforms/Coroutines.h"
16
17 namespace llvm {
18
19 class CallGraph;
20 class CallGraphSCC;
21 class PassRegistry;
22
23 void initializeCoroEarlyPass(PassRegistry &);
24 void initializeCoroSplitPass(PassRegistry &);
25 void initializeCoroElidePass(PassRegistry &);
26 void initializeCoroCleanupPass(PassRegistry &);
27
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.
36
37 #define CORO_PRESPLIT_ATTR "coroutine.presplit"
38 #define UNPREPARED_FOR_SPLIT "0"
39 #define PREPARED_FOR_SPLIT "1"
40
41 #define CORO_DEVIRT_TRIGGER_FN "coro.devirt.trigger"
42
43 namespace coro {
44
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);
51
52 // Keeps data and helper functions for lowering coroutine intrinsics.
53 struct LowererBase {
54   Module &TheModule;
55   LLVMContext &Context;
56   PointerType *const Int8Ptr;
57   FunctionType *const ResumeFnType;
58   ConstantPointerNull *const NullPtr;
59
60   LowererBase(Module &M);
61   Value *makeSubFnCall(Value *Arg, int Index, Instruction *InsertPt);
62 };
63
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;
71
72   // Field Indexes for known coroutine frame fields.
73   enum {
74     ResumeField,
75     DestroyField,
76     PromiseField,
77     IndexField,
78   };
79
80   StructType *FrameTy;
81   Instruction *FramePtr;
82   BasicBlock *AllocaSpillBlock;
83   SwitchInst *ResumeSwitch;
84   AllocaInst *PromiseAlloca;
85   bool HasFinalSuspend;
86
87   IntegerType *getIndexType() const {
88     assert(FrameTy && "frame type not assigned");
89     return cast<IntegerType>(FrameTy->getElementType(IndexField));
90   }
91   ConstantInt *getIndex(uint64_t Value) const {
92     return ConstantInt::get(getIndexType(), Value);
93   }
94
95   Shape() = default;
96   explicit Shape(Function &F) { buildFrom(F); }
97   void buildFrom(Function &F);
98 };
99
100 void buildCoroutineFrame(Function &F, Shape &Shape);
101
102 } // End namespace coro.
103 } // End namespace llvm
104
105 #endif