Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Transforms/Coroutines/CoroInternal.h
Line
Count
Source
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
638
#define CORO_PRESPLIT_ATTR "coroutine.presplit"
38
57
#define UNPREPARED_FOR_SPLIT "0"
39
10
#define PREPARED_FOR_SPLIT "1"
40
41
84
#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
72
  IntegerType *getIndexType() const {
88
72
    assert(FrameTy && "frame type not assigned");
89
72
    return cast<IntegerType>(FrameTy->getElementType(IndexField));
90
72
  }
91
39
  ConstantInt *getIndex(uint64_t Value) const {
92
39
    return ConstantInt::get(getIndexType(), Value);
93
39
  }
94
95
  Shape() = default;
96
37
  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