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 88 IntegerType *getIndexType() const { 89 assert(FrameTy && "frame type not assigned"); 90 return cast<IntegerType>(FrameTy->getElementType(IndexField)); 91 } 92 ConstantInt *getIndex(uint64_t Value) const { 93 return ConstantInt::get(getIndexType(), Value); 94 } 95 96 Shape() = default; 97 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