Home | History | Annotate | Download | only in Coroutines
      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