Coverage Report

Created: 2022-05-17 06:19

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/CodeGen/CGBlocks.h
Line
Count
Source (jump to first uncovered line)
1
//===-- CGBlocks.h - state for LLVM CodeGen for blocks ----------*- 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
//
9
// This is the internal state used for llvm translation for block literals.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#ifndef LLVM_CLANG_LIB_CODEGEN_CGBLOCKS_H
14
#define LLVM_CLANG_LIB_CODEGEN_CGBLOCKS_H
15
16
#include "CGBuilder.h"
17
#include "CGCall.h"
18
#include "CGValue.h"
19
#include "CodeGenFunction.h"
20
#include "CodeGenTypes.h"
21
#include "clang/AST/CharUnits.h"
22
#include "clang/AST/Expr.h"
23
#include "clang/AST/ExprCXX.h"
24
#include "clang/AST/ExprObjC.h"
25
#include "clang/AST/Type.h"
26
#include "clang/Basic/TargetInfo.h"
27
28
namespace llvm {
29
class Value;
30
}
31
32
namespace clang {
33
namespace CodeGen {
34
35
class CGBlockInfo;
36
37
// Flags stored in __block variables.
38
enum BlockByrefFlags {
39
  BLOCK_BYREF_HAS_COPY_DISPOSE         = (1   << 25), // compiler
40
  BLOCK_BYREF_LAYOUT_MASK              = (0xF << 28), // compiler
41
  BLOCK_BYREF_LAYOUT_EXTENDED          = (1   << 28),
42
  BLOCK_BYREF_LAYOUT_NON_OBJECT        = (2   << 28),
43
  BLOCK_BYREF_LAYOUT_STRONG            = (3   << 28),
44
  BLOCK_BYREF_LAYOUT_WEAK              = (4   << 28),
45
  BLOCK_BYREF_LAYOUT_UNRETAINED        = (5   << 28)
46
};
47
48
enum BlockLiteralFlags {
49
  BLOCK_IS_NOESCAPE      =  (1 << 23),
50
  BLOCK_HAS_COPY_DISPOSE =  (1 << 25),
51
  BLOCK_HAS_CXX_OBJ =       (1 << 26),
52
  BLOCK_IS_GLOBAL =         (1 << 28),
53
  BLOCK_USE_STRET =         (1 << 29),
54
  BLOCK_HAS_SIGNATURE  =    (1 << 30),
55
  BLOCK_HAS_EXTENDED_LAYOUT = (1u << 31)
56
};
57
class BlockFlags {
58
  uint32_t flags;
59
60
public:
61
344
  BlockFlags(uint32_t flags) : flags(flags) {}
62
979
  BlockFlags() : flags(0) {}
63
2.33k
  BlockFlags(BlockLiteralFlags flag) : flags(flag) {}
64
313
  BlockFlags(BlockByrefFlags flag) : flags(flag) {}
65
66
1.29k
  uint32_t getBitMask() const { return flags; }
67
0
  bool empty() const { return flags == 0; }
68
69
324
  friend BlockFlags operator|(BlockFlags l, BlockFlags r) {
70
324
    return BlockFlags(l.flags | r.flags);
71
324
  }
72
1.14k
  friend BlockFlags &operator|=(BlockFlags &l, BlockFlags r) {
73
1.14k
    l.flags |= r.flags;
74
1.14k
    return l;
75
1.14k
  }
76
40
  friend bool operator&(BlockFlags l, BlockFlags r) {
77
40
    return (l.flags & r.flags);
78
40
  }
79
100
  bool operator==(BlockFlags r) {
80
100
    return (flags == r.flags);
81
100
  }
82
};
83
324
inline BlockFlags operator|(BlockLiteralFlags l, BlockLiteralFlags r) {
84
324
  return BlockFlags(l) | BlockFlags(r);
85
324
}
86
87
enum BlockFieldFlag_t {
88
  BLOCK_FIELD_IS_OBJECT   = 0x03,  /* id, NSObject, __attribute__((NSObject)),
89
                                    block, ... */
90
  BLOCK_FIELD_IS_BLOCK    = 0x07,  /* a block variable */
91
92
  BLOCK_FIELD_IS_BYREF    = 0x08,  /* the on stack structure holding the __block
93
                                    variable */
94
  BLOCK_FIELD_IS_WEAK     = 0x10,  /* declared __weak, only used in byref copy
95
                                    helpers */
96
  BLOCK_FIELD_IS_ARC      = 0x40,  /* field has ARC-specific semantics */
97
  BLOCK_BYREF_CALLER      = 128,   /* called from __block (byref) copy/dispose
98
                                      support routines */
99
  BLOCK_BYREF_CURRENT_MAX = 256
100
};
101
102
class BlockFieldFlags {
103
  uint32_t flags;
104
105
36
  BlockFieldFlags(uint32_t flags) : flags(flags) {}
106
public:
107
16.8k
  BlockFieldFlags() : flags(0) {}
108
3.28k
  BlockFieldFlags(BlockFieldFlag_t flag) : flags(flag) {}
109
110
1.92k
  uint32_t getBitMask() const { return flags; }
111
0
  bool empty() const { return flags == 0; }
112
113
  /// Answers whether the flags indicate that this field is an object
114
  /// or block pointer that requires _Block_object_assign/dispose.
115
0
  bool isSpecialPointer() const { return flags & BLOCK_FIELD_IS_OBJECT; }
116
117
36
  friend BlockFieldFlags operator|(BlockFieldFlags l, BlockFieldFlags r) {
118
36
    return BlockFieldFlags(l.flags | r.flags);
119
36
  }
120
52
  friend BlockFieldFlags &operator|=(BlockFieldFlags &l, BlockFieldFlags r) {
121
52
    l.flags |= r.flags;
122
52
    return l;
123
52
  }
124
0
  friend bool operator&(BlockFieldFlags l, BlockFieldFlags r) {
125
0
    return (l.flags & r.flags);
126
0
  }
127
502
  bool operator==(BlockFieldFlags Other) const {
128
502
    return flags == Other.flags;
129
502
  }
130
};
131
0
inline BlockFieldFlags operator|(BlockFieldFlag_t l, BlockFieldFlag_t r) {
132
0
  return BlockFieldFlags(l) | BlockFieldFlags(r);
133
0
}
134
135
/// Information about the layout of a __block variable.
136
class BlockByrefInfo {
137
public:
138
  llvm::StructType *Type;
139
  unsigned FieldIndex;
140
  CharUnits ByrefAlignment;
141
  CharUnits FieldOffset;
142
};
143
144
/// Represents a type of copy/destroy operation that should be performed for an
145
/// entity that's captured by a block.
146
enum class BlockCaptureEntityKind {
147
  None,
148
  CXXRecord, // Copy or destroy
149
  ARCWeak,
150
  ARCStrong,
151
  NonTrivialCStruct,
152
  BlockObject, // Assign or release
153
};
154
155
/// CGBlockInfo - Information to generate a block literal.
156
class CGBlockInfo {
157
public:
158
  /// Name - The name of the block, kindof.
159
  StringRef Name;
160
161
  /// The field index of 'this' within the block, if there is one.
162
  unsigned CXXThisIndex;
163
164
  class Capture {
165
    uintptr_t Data;
166
    EHScopeStack::stable_iterator Cleanup;
167
    CharUnits::QuantityType Offset;
168
169
    /// Type of the capture field. Normally, this is identical to the type of
170
    /// the capture's VarDecl, but can be different if there is an enclosing
171
    /// lambda.
172
    QualType FieldType;
173
174
  public:
175
27.6k
    bool isIndex() const { return (Data & 1) != 0; }
176
13.4k
    bool isConstant() const { return !isIndex(); }
177
178
12.2k
    unsigned getIndex() const {
179
12.2k
      assert(isIndex());
180
0
      return Data >> 1;
181
12.2k
    }
182
1.95k
    CharUnits getOffset() const {
183
1.95k
      assert(isIndex());
184
0
      return CharUnits::fromQuantity(Offset);
185
1.95k
    }
186
0
    EHScopeStack::stable_iterator getCleanup() const {
187
0
      assert(isIndex());
188
0
      return Cleanup;
189
0
    }
190
0
    void setCleanup(EHScopeStack::stable_iterator cleanup) {
191
0
      assert(isIndex());
192
0
      Cleanup = cleanup;
193
0
    }
194
195
5
    llvm::Value *getConstant() const {
196
5
      assert(isConstant());
197
0
      return reinterpret_cast<llvm::Value*>(Data);
198
5
    }
199
200
8.63k
    QualType fieldType() const {
201
8.63k
      return FieldType;
202
8.63k
    }
203
204
    static Capture
205
    makeIndex(unsigned index, CharUnits offset, QualType FieldType,
206
              BlockCaptureEntityKind CopyKind, BlockFieldFlags CopyFlags,
207
              BlockCaptureEntityKind DisposeKind, BlockFieldFlags DisposeFlags,
208
2.31k
              const BlockDecl::Capture *Cap) {
209
2.31k
      Capture v;
210
2.31k
      v.Data = (index << 1) | 1;
211
2.31k
      v.Offset = offset.getQuantity();
212
2.31k
      v.FieldType = FieldType;
213
2.31k
      v.CopyKind = CopyKind;
214
2.31k
      v.CopyFlags = CopyFlags;
215
2.31k
      v.DisposeKind = DisposeKind;
216
2.31k
      v.DisposeFlags = DisposeFlags;
217
2.31k
      v.Cap = Cap;
218
2.31k
      return v;
219
2.31k
    }
220
221
    static Capture makeConstant(llvm::Value *value,
222
5
                                const BlockDecl::Capture *Cap) {
223
5
      Capture v;
224
5
      v.Data = reinterpret_cast<uintptr_t>(value);
225
5
      v.Cap = Cap;
226
5
      return v;
227
5
    }
228
229
7.54k
    bool isConstantOrTrivial() const {
230
7.54k
      return CopyKind == BlockCaptureEntityKind::None &&
231
7.54k
             
DisposeKind == BlockCaptureEntityKind::None4.77k
;
232
7.54k
    }
233
234
    BlockCaptureEntityKind CopyKind = BlockCaptureEntityKind::None,
235
                           DisposeKind = BlockCaptureEntityKind::None;
236
    BlockFieldFlags CopyFlags, DisposeFlags;
237
    const BlockDecl::Capture *Cap;
238
  };
239
240
  /// CanBeGlobal - True if the block can be global, i.e. it has
241
  /// no non-constant captures.
242
  bool CanBeGlobal : 1;
243
244
  /// True if the block has captures that would necessitate custom copy or
245
  /// dispose helper functions if the block were escaping.
246
  bool NeedsCopyDispose : 1;
247
248
  /// Indicates whether the block is non-escaping.
249
  bool NoEscape : 1;
250
251
  /// HasCXXObject - True if the block's custom copy/dispose functions
252
  /// need to be run even in GC mode.
253
  bool HasCXXObject : 1;
254
255
  /// UsesStret : True if the block uses an stret return.  Mutable
256
  /// because it gets set later in the block-creation process.
257
  mutable bool UsesStret : 1;
258
259
  /// HasCapturedVariableLayout : True if block has captured variables
260
  /// and their layout meta-data has been generated.
261
  bool HasCapturedVariableLayout : 1;
262
263
  /// Indicates whether an object of a non-external C++ class is captured. This
264
  /// bit is used to determine the linkage of the block copy/destroy helper
265
  /// functions.
266
  bool CapturesNonExternalType : 1;
267
268
  /// Mapping from variables to pointers to captures in SortedCaptures.
269
  llvm::DenseMap<const VarDecl *, Capture *> Captures;
270
271
  /// The block's captures. Non-constant captures are sorted by their offsets.
272
  llvm::SmallVector<Capture, 4> SortedCaptures;
273
274
  Address LocalAddress;
275
  llvm::StructType *StructureType;
276
  const BlockDecl *Block;
277
  const BlockExpr *BlockExpression;
278
  CharUnits BlockSize;
279
  CharUnits BlockAlign;
280
  CharUnits CXXThisOffset;
281
282
  // Offset of the gap caused by block header having a smaller
283
  // alignment than the alignment of the block descriptor. This
284
  // is the gap offset before the first capturued field.
285
  CharUnits BlockHeaderForcedGapOffset;
286
  // Gap size caused by aligning first field after block header.
287
  // This could be zero if no forced alignment is required.
288
  CharUnits BlockHeaderForcedGapSize;
289
290
  /// The next block in the block-info chain.  Invalid if this block
291
  /// info is not part of the CGF's block-info chain, which is true
292
  /// if it corresponds to a global block or a block whose expression
293
  /// has been encountered.
294
  CGBlockInfo *NextBlockInfo;
295
296
768
  void buildCaptureMap() {
297
768
    for (auto &C : SortedCaptures)
298
2.32k
      Captures[C.Cap->getVariable()] = &C;
299
768
  }
300
301
14.6k
  const Capture &getCapture(const VarDecl *var) const {
302
14.6k
    return const_cast<CGBlockInfo*>(this)->getCapture(var);
303
14.6k
  }
304
14.6k
  Capture &getCapture(const VarDecl *var) {
305
14.6k
    auto it = Captures.find(var);
306
14.6k
    assert(it != Captures.end() && "no entry for variable!");
307
0
    return *it->second;
308
14.6k
  }
309
310
5.15k
  const BlockDecl *getBlockDecl() const { return Block; }
311
7.36k
  const BlockExpr *getBlockExpr() const {
312
7.36k
    assert(BlockExpression);
313
0
    assert(BlockExpression->getBlockDecl() == Block);
314
0
    return BlockExpression;
315
7.36k
  }
316
317
  CGBlockInfo(const BlockDecl *blockDecl, StringRef Name);
318
};
319
320
}  // end namespace CodeGen
321
}  // end namespace clang
322
323
#endif