Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Transforms/Coroutines/CoroInstr.h
Line
Count
Source (jump to first uncovered line)
1
//===-- CoroInstr.h - Coroutine Intrinsics Instruction Wrappers -*- 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
// This file defines classes that make it really easy to deal with intrinsic
9
// functions with the isa/dyncast family of functions.  In particular, this
10
// allows you to do things like:
11
//
12
//     if (auto *SF = dyn_cast<CoroSubFnInst>(Inst))
13
//        ... SF->getFrame() ...
14
//
15
// All intrinsic function calls are instances of the call instruction, so these
16
// are all subclasses of the CallInst class.  Note that none of these classes
17
// has state or virtual methods, which is an important part of this gross/neat
18
// hack working.
19
//
20
// The helpful comment above is borrowed from llvm/IntrinsicInst.h, we keep
21
// coroutine intrinsic wrappers here since they are only used by the passes in
22
// the Coroutine library.
23
//===----------------------------------------------------------------------===//
24
25
#ifndef LLVM_LIB_TRANSFORMS_COROUTINES_COROINSTR_H
26
#define LLVM_LIB_TRANSFORMS_COROUTINES_COROINSTR_H
27
28
#include "llvm/IR/GlobalVariable.h"
29
#include "llvm/IR/IntrinsicInst.h"
30
31
namespace llvm {
32
33
/// This class represents the llvm.coro.subfn.addr instruction.
34
class LLVM_LIBRARY_VISIBILITY CoroSubFnInst : public IntrinsicInst {
35
  enum { FrameArg, IndexArg };
36
37
public:
38
  enum ResumeKind {
39
    RestartTrigger = -1,
40
    ResumeIndex,
41
    DestroyIndex,
42
    CleanupIndex,
43
    IndexLast,
44
    IndexFirst = RestartTrigger
45
  };
46
47
12
  Value *getFrame() const { return getArgOperand(FrameArg); }
48
43
  ResumeKind getIndex() const {
49
43
    int64_t Index = getRawIndex()->getValue().getSExtValue();
50
43
    assert(Index >= IndexFirst && Index < IndexLast &&
51
43
           "unexpected CoroSubFnInst index argument");
52
43
    return static_cast<ResumeKind>(Index);
53
43
  }
54
55
46
  ConstantInt *getRawIndex() const {
56
46
    return cast<ConstantInt>(getArgOperand(IndexArg));
57
46
  }
58
59
  // Methods to support type inquiry through isa, cast, and dyn_cast:
60
125
  static bool classof(const IntrinsicInst *I) {
61
125
    return I->getIntrinsicID() == Intrinsic::coro_subfn_addr;
62
125
  }
63
548
  static bool classof(const Value *V) {
64
548
    return isa<IntrinsicInst>(V) && 
classof(cast<IntrinsicInst>(V))125
;
65
548
  }
66
};
67
68
/// This represents the llvm.coro.alloc instruction.
69
class LLVM_LIBRARY_VISIBILITY CoroAllocInst : public IntrinsicInst {
70
public:
71
  // Methods to support type inquiry through isa, cast, and dyn_cast:
72
64
  static bool classof(const IntrinsicInst *I) {
73
64
    return I->getIntrinsicID() == Intrinsic::coro_alloc;
74
64
  }
75
64
  static bool classof(const Value *V) {
76
64
    return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
77
64
  }
78
};
79
80
/// This represents the llvm.coro.alloc instruction.
81
class LLVM_LIBRARY_VISIBILITY CoroIdInst : public IntrinsicInst {
82
  enum { AlignArg, PromiseArg, CoroutineArg, InfoArg };
83
84
public:
85
37
  CoroAllocInst *getCoroAlloc() {
86
37
    for (User *U : users())
87
56
      if (auto *CA = dyn_cast<CoroAllocInst>(U))
88
14
        return CA;
89
37
    
return nullptr23
;
90
37
  }
91
92
0
  IntrinsicInst *getCoroBegin() {
93
0
    for (User *U : users())
94
0
      if (auto *II = dyn_cast<IntrinsicInst>(U))
95
0
        if (II->getIntrinsicID() == Intrinsic::coro_begin)
96
0
          return II;
97
0
    llvm_unreachable("no coro.begin associated with coro.id");
98
0
  }
99
100
37
  AllocaInst *getPromise() const {
101
37
    Value *Arg = getArgOperand(PromiseArg);
102
37
    return isa<ConstantPointerNull>(Arg)
103
37
               ? 
nullptr35
104
37
               : 
cast<AllocaInst>(Arg->stripPointerCasts())2
;
105
37
  }
106
107
2
  void clearPromise() {
108
2
    Value *Arg = getArgOperand(PromiseArg);
109
2
    setArgOperand(PromiseArg,
110
2
                  ConstantPointerNull::get(Type::getInt8PtrTy(getContext())));
111
2
    if (isa<AllocaInst>(Arg))
112
0
      return;
113
2
    assert((isa<BitCastInst>(Arg) || isa<GetElementPtrInst>(Arg)) &&
114
2
           "unexpected instruction designating the promise");
115
2
    // TODO: Add a check that any remaining users of Inst are after coro.begin
116
2
    // or add code to move the users after coro.begin.
117
2
    auto *Inst = cast<Instruction>(Arg);
118
2
    if (Inst->use_empty()) {
119
2
      Inst->eraseFromParent();
120
2
      return;
121
2
    }
122
0
    Inst->moveBefore(getCoroBegin()->getNextNode());
123
0
  }
124
125
  // Info argument of coro.id is
126
  //   fresh out of the frontend: null ;
127
  //   outlined                 : {Init, Return, Susp1, Susp2, ...} ;
128
  //   postsplit                : [resume, destroy, cleanup] ;
129
  //
130
  // If parts of the coroutine were outlined to protect against undesirable
131
  // code motion, these functions will be stored in a struct literal referred to
132
  // by the Info parameter. Note: this is only needed before coroutine is split.
133
  //
134
  // After coroutine is split, resume functions are stored in an array
135
  // referred to by this parameter.
136
137
  struct Info {
138
    ConstantStruct *OutlinedParts = nullptr;
139
    ConstantArray *Resumers = nullptr;
140
141
0
    bool hasOutlinedParts() const { return OutlinedParts != nullptr; }
142
95
    bool isPostSplit() const { return Resumers != nullptr; }
143
48
    bool isPreSplit() const { return !isPostSplit(); }
144
  };
145
118
  Info getInfo() const {
146
118
    Info Result;
147
118
    auto *GV = dyn_cast<GlobalVariable>(getRawInfo());
148
118
    if (!GV)
149
58
      return Result;
150
60
151
60
    assert(GV->isConstant() && GV->hasDefinitiveInitializer());
152
60
    Constant *Initializer = GV->getInitializer();
153
60
    if ((Result.OutlinedParts = dyn_cast<ConstantStruct>(Initializer)))
154
0
      return Result;
155
60
156
60
    Result.Resumers = cast<ConstantArray>(Initializer);
157
60
    return Result;
158
60
  }
159
118
  Constant *getRawInfo() const {
160
118
    return cast<Constant>(getArgOperand(InfoArg)->stripPointerCasts());
161
118
  }
162
163
33
  void setInfo(Constant *C) { setArgOperand(InfoArg, C); }
164
165
36
  Function *getCoroutine() const {
166
36
    return cast<Function>(getArgOperand(CoroutineArg)->stripPointerCasts());
167
36
  }
168
10
  void setCoroutineSelf() {
169
10
    assert(isa<ConstantPointerNull>(getArgOperand(CoroutineArg)) &&
170
10
           "Coroutine argument is already assigned");
171
10
    auto *const Int8PtrTy = Type::getInt8PtrTy(getContext());
172
10
    setArgOperand(CoroutineArg,
173
10
                  ConstantExpr::getBitCast(getFunction(), Int8PtrTy));
174
10
  }
175
176
  // Methods to support type inquiry through isa, cast, and dyn_cast:
177
496
  static bool classof(const IntrinsicInst *I) {
178
496
    return I->getIntrinsicID() == Intrinsic::coro_id;
179
496
  }
180
2.80k
  static bool classof(const Value *V) {
181
2.80k
    return isa<IntrinsicInst>(V) && 
classof(cast<IntrinsicInst>(V))496
;
182
2.80k
  }
183
};
184
185
/// This represents the llvm.coro.frame instruction.
186
class LLVM_LIBRARY_VISIBILITY CoroFrameInst : public IntrinsicInst {
187
public:
188
  // Methods to support type inquiry through isa, cast, and dyn_cast:
189
0
  static bool classof(const IntrinsicInst *I) {
190
0
    return I->getIntrinsicID() == Intrinsic::coro_frame;
191
0
  }
192
0
  static bool classof(const Value *V) {
193
0
    return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
194
0
  }
195
};
196
197
/// This represents the llvm.coro.free instruction.
198
class LLVM_LIBRARY_VISIBILITY CoroFreeInst : public IntrinsicInst {
199
  enum { IdArg, FrameArg };
200
201
public:
202
56
  Value *getFrame() const { return getArgOperand(FrameArg); }
203
204
  // Methods to support type inquiry through isa, cast, and dyn_cast:
205
228
  static bool classof(const IntrinsicInst *I) {
206
228
    return I->getIntrinsicID() == Intrinsic::coro_free;
207
228
  }
208
228
  static bool classof(const Value *V) {
209
228
    return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
210
228
  }
211
};
212
213
/// This class represents the llvm.coro.begin instruction.
214
class LLVM_LIBRARY_VISIBILITY CoroBeginInst : public IntrinsicInst {
215
  enum { IdArg, MemArg };
216
217
public:
218
246
  CoroIdInst *getId() const { return cast<CoroIdInst>(getArgOperand(IdArg)); }
219
220
0
  Value *getMem() const { return getArgOperand(MemArg); }
221
222
  // Methods for support type inquiry through isa, cast, and dyn_cast:
223
58
  static bool classof(const IntrinsicInst *I) {
224
58
    return I->getIntrinsicID() == Intrinsic::coro_begin;
225
58
  }
226
58
  static bool classof(const Value *V) {
227
58
    return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
228
58
  }
229
};
230
231
/// This represents the llvm.coro.save instruction.
232
class LLVM_LIBRARY_VISIBILITY CoroSaveInst : public IntrinsicInst {
233
public:
234
  // Methods to support type inquiry through isa, cast, and dyn_cast:
235
390
  static bool classof(const IntrinsicInst *I) {
236
390
    return I->getIntrinsicID() == Intrinsic::coro_save;
237
390
  }
238
1.29k
  static bool classof(const Value *V) {
239
1.29k
    return isa<IntrinsicInst>(V) && 
classof(cast<IntrinsicInst>(V))390
;
240
1.29k
  }
241
};
242
243
/// This represents the llvm.coro.promise instruction.
244
class LLVM_LIBRARY_VISIBILITY CoroPromiseInst : public IntrinsicInst {
245
  enum { FrameArg, AlignArg, FromArg };
246
247
public:
248
1
  bool isFromPromise() const {
249
1
    return cast<Constant>(getArgOperand(FromArg))->isOneValue();
250
1
  }
251
1
  unsigned getAlignment() const {
252
1
    return cast<ConstantInt>(getArgOperand(AlignArg))->getZExtValue();
253
1
  }
254
255
  // Methods to support type inquiry through isa, cast, and dyn_cast:
256
0
  static bool classof(const IntrinsicInst *I) {
257
0
    return I->getIntrinsicID() == Intrinsic::coro_promise;
258
0
  }
259
0
  static bool classof(const Value *V) {
260
0
    return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
261
0
  }
262
};
263
264
/// This represents the llvm.coro.suspend instruction.
265
class LLVM_LIBRARY_VISIBILITY CoroSuspendInst : public IntrinsicInst {
266
  enum { SaveArg, FinalArg };
267
268
public:
269
164
  CoroSaveInst *getCoroSave() const {
270
164
    Value *Arg = getArgOperand(SaveArg);
271
164
    if (auto *SI = dyn_cast<CoroSaveInst>(Arg))
272
135
      return SI;
273
29
    assert(isa<ConstantTokenNone>(Arg));
274
29
    return nullptr;
275
29
  }
276
95
  bool isFinal() const {
277
95
    return cast<Constant>(getArgOperand(FinalArg))->isOneValue();
278
95
  }
279
280
  // Methods to support type inquiry through isa, cast, and dyn_cast:
281
216
  static bool classof(const IntrinsicInst *I) {
282
216
    return I->getIntrinsicID() == Intrinsic::coro_suspend;
283
216
  }
284
1.09k
  static bool classof(const Value *V) {
285
1.09k
    return isa<IntrinsicInst>(V) && 
classof(cast<IntrinsicInst>(V))216
;
286
1.09k
  }
287
};
288
289
/// This represents the llvm.coro.size instruction.
290
class LLVM_LIBRARY_VISIBILITY CoroSizeInst : public IntrinsicInst {
291
public:
292
  // Methods to support type inquiry through isa, cast, and dyn_cast:
293
0
  static bool classof(const IntrinsicInst *I) {
294
0
    return I->getIntrinsicID() == Intrinsic::coro_size;
295
0
  }
296
0
  static bool classof(const Value *V) {
297
0
    return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
298
0
  }
299
};
300
301
/// This represents the llvm.coro.end instruction.
302
class LLVM_LIBRARY_VISIBILITY CoroEndInst : public IntrinsicInst {
303
  enum { FrameArg, UnwindArg };
304
305
public:
306
49
  bool isFallthrough() const { return !isUnwind(); }
307
154
  bool isUnwind() const {
308
154
    return cast<Constant>(getArgOperand(UnwindArg))->isOneValue();
309
154
  }
310
311
  // Methods to support type inquiry through isa, cast, and dyn_cast:
312
0
  static bool classof(const IntrinsicInst *I) {
313
0
    return I->getIntrinsicID() == Intrinsic::coro_end;
314
0
  }
315
0
  static bool classof(const Value *V) {
316
0
    return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
317
0
  }
318
};
319
320
} // End namespace llvm.
321
322
#endif