• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- CoroInternal.h - Internal Coroutine interfaces ---------*- C++ -*---===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 // Common definitions/declarations used internally by coroutine lowering passes.
10 //===----------------------------------------------------------------------===//
11 
12 #ifndef LLVM_LIB_TRANSFORMS_COROUTINES_COROINTERNAL_H
13 #define LLVM_LIB_TRANSFORMS_COROUTINES_COROINTERNAL_H
14 
15 #include "CoroInstr.h"
16 #include "llvm/Transforms/Coroutines.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);
50 void updateCallGraph(Function &Caller, ArrayRef<Function *> Funcs,
51                      CallGraph &CG, CallGraphSCC &SCC);
52 
53 // Keeps data and helper functions for lowering coroutine intrinsics.
54 struct LowererBase {
55   Module &TheModule;
56   LLVMContext &Context;
57   PointerType *const Int8Ptr;
58   FunctionType *const ResumeFnType;
59   ConstantPointerNull *const NullPtr;
60 
61   LowererBase(Module &M);
62   Value *makeSubFnCall(Value *Arg, int Index, Instruction *InsertPt);
63 };
64 
65 // Holds structural Coroutine Intrinsics for a particular function and other
66 // values used during CoroSplit pass.
67 struct LLVM_LIBRARY_VISIBILITY Shape {
68   CoroBeginInst *CoroBegin;
69   SmallVector<CoroEndInst *, 4> CoroEnds;
70   SmallVector<CoroSizeInst *, 2> CoroSizes;
71   SmallVector<CoroSuspendInst *, 4> CoroSuspends;
72 
73   // Field Indexes for known coroutine frame fields.
74   enum {
75     ResumeField,
76     DestroyField,
77     PromiseField,
78     IndexField,
79   };
80 
81   StructType *FrameTy;
82   Instruction *FramePtr;
83   BasicBlock *AllocaSpillBlock;
84   SwitchInst *ResumeSwitch;
85   AllocaInst *PromiseAlloca;
86   bool HasFinalSuspend;
87 
getIndexTypeShape88   IntegerType *getIndexType() const {
89     assert(FrameTy && "frame type not assigned");
90     return cast<IntegerType>(FrameTy->getElementType(IndexField));
91   }
getIndexShape92   ConstantInt *getIndex(uint64_t Value) const {
93     return ConstantInt::get(getIndexType(), Value);
94   }
95 
96   Shape() = default;
ShapeShape97   explicit Shape(Function &F) { buildFrom(F); }
98   void buildFrom(Function &F);
99 };
100 
101 void buildCoroutineFrame(Function &F, Shape &Shape);
102 
103 } // End namespace coro.
104 } // End namespace llvm
105 
106 #endif
107