Coverage Report

Created: 2022-07-16 07:03

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/CodeGen/CGBuilder.h
Line
Count
Source (jump to first uncovered line)
1
//===-- CGBuilder.h - Choose IRBuilder implementation  ----------*- 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
#ifndef LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H
10
#define LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H
11
12
#include "Address.h"
13
#include "CodeGenTypeCache.h"
14
#include "llvm/IR/DataLayout.h"
15
#include "llvm/IR/IRBuilder.h"
16
#include "llvm/IR/Type.h"
17
18
namespace clang {
19
namespace CodeGen {
20
21
class CodeGenFunction;
22
23
/// This is an IRBuilder insertion helper that forwards to
24
/// CodeGenFunction::InsertHelper, which adds necessary metadata to
25
/// instructions.
26
class CGBuilderInserter final : public llvm::IRBuilderDefaultInserter {
27
public:
28
2.12k
  CGBuilderInserter() = default;
29
315k
  explicit CGBuilderInserter(CodeGenFunction *CGF) : CGF(CGF) {}
30
31
  /// This forwards to CodeGenFunction::InsertHelper.
32
  void InsertHelper(llvm::Instruction *I, const llvm::Twine &Name,
33
                    llvm::BasicBlock *BB,
34
                    llvm::BasicBlock::iterator InsertPt) const override;
35
36
private:
37
  CodeGenFunction *CGF = nullptr;
38
};
39
40
typedef CGBuilderInserter CGBuilderInserterTy;
41
42
typedef llvm::IRBuilder<llvm::ConstantFolder, CGBuilderInserterTy>
43
    CGBuilderBaseTy;
44
45
class CGBuilderTy : public CGBuilderBaseTy {
46
  /// Storing a reference to the type cache here makes it a lot easier
47
  /// to build natural-feeling, target-specific IR.
48
  const CodeGenTypeCache &TypeCache;
49
50
public:
51
  CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::LLVMContext &C)
52
338
      : CGBuilderBaseTy(C), TypeCache(TypeCache) {}
53
  CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::LLVMContext &C,
54
              const llvm::ConstantFolder &F,
55
              const CGBuilderInserterTy &Inserter)
56
315k
      : CGBuilderBaseTy(C, F, Inserter), TypeCache(TypeCache) {}
57
  CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::Instruction *I)
58
198
      : CGBuilderBaseTy(I), TypeCache(TypeCache) {}
59
  CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::BasicBlock *BB)
60
1.58k
      : CGBuilderBaseTy(BB), TypeCache(TypeCache) {}
61
62
111k
  llvm::ConstantInt *getSize(CharUnits N) {
63
111k
    return llvm::ConstantInt::get(TypeCache.SizeTy, N.getQuantity());
64
111k
  }
65
109k
  llvm::ConstantInt *getSize(uint64_t N) {
66
109k
    return llvm::ConstantInt::get(TypeCache.SizeTy, N);
67
109k
  }
68
69
  // Note that we intentionally hide the CreateLoad APIs that don't
70
  // take an alignment.
71
92.0k
  llvm::LoadInst *CreateLoad(Address Addr, const llvm::Twine &Name = "") {
72
92.0k
    return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(),
73
92.0k
                             Addr.getAlignment().getAsAlign(), Name);
74
92.0k
  }
75
118k
  llvm::LoadInst *CreateLoad(Address Addr, const char *Name) {
76
    // This overload is required to prevent string literals from
77
    // ending up in the IsVolatile overload.
78
118k
    return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(),
79
118k
                             Addr.getAlignment().getAsAlign(), Name);
80
118k
  }
81
  llvm::LoadInst *CreateLoad(Address Addr, bool IsVolatile,
82
1.30M
                             const llvm::Twine &Name = "") {
83
1.30M
    return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(),
84
1.30M
                             Addr.getAlignment().getAsAlign(), IsVolatile,
85
1.30M
                             Name);
86
1.30M
  }
87
88
  using CGBuilderBaseTy::CreateAlignedLoad;
89
  llvm::LoadInst *CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr,
90
                                    CharUnits Align,
91
26.8k
                                    const llvm::Twine &Name = "") {
92
26.8k
    assert(llvm::cast<llvm::PointerType>(Addr->getType())
93
26.8k
               ->isOpaqueOrPointeeTypeMatches(Ty));
94
0
    return CreateAlignedLoad(Ty, Addr, Align.getAsAlign(), Name);
95
26.8k
  }
96
97
  // Note that we intentionally hide the CreateStore APIs that don't
98
  // take an alignment.
99
  llvm::StoreInst *CreateStore(llvm::Value *Val, Address Addr,
100
1.26M
                               bool IsVolatile = false) {
101
1.26M
    return CreateAlignedStore(Val, Addr.getPointer(),
102
1.26M
                              Addr.getAlignment().getAsAlign(), IsVolatile);
103
1.26M
  }
104
105
  using CGBuilderBaseTy::CreateAlignedStore;
106
  llvm::StoreInst *CreateAlignedStore(llvm::Value *Val, llvm::Value *Addr,
107
                                      CharUnits Align,
108
6.72k
                                      bool IsVolatile = false) {
109
6.72k
    return CreateAlignedStore(Val, Addr, Align.getAsAlign(), IsVolatile);
110
6.72k
  }
111
112
  // FIXME: these "default-aligned" APIs should be removed,
113
  // but I don't feel like fixing all the builtin code right now.
114
  llvm::StoreInst *CreateDefaultAlignedStore(llvm::Value *Val,
115
                                             llvm::Value *Addr,
116
981
                                             bool IsVolatile = false) {
117
981
    return CGBuilderBaseTy::CreateStore(Val, Addr, IsVolatile);
118
981
  }
119
120
  /// Emit a load from an i1 flag variable.
121
  llvm::LoadInst *CreateFlagLoad(llvm::Value *Addr,
122
239
                                 const llvm::Twine &Name = "") {
123
239
    assert(llvm::cast<llvm::PointerType>(Addr->getType())
124
239
               ->isOpaqueOrPointeeTypeMatches(getInt1Ty()));
125
0
    return CreateAlignedLoad(getInt1Ty(), Addr, CharUnits::One(), Name);
126
239
  }
127
128
  /// Emit a store to an i1 flag variable.
129
247
  llvm::StoreInst *CreateFlagStore(bool Value, llvm::Value *Addr) {
130
247
    assert(llvm::cast<llvm::PointerType>(Addr->getType())
131
247
               ->isOpaqueOrPointeeTypeMatches(getInt1Ty()));
132
0
    return CreateAlignedStore(getInt1(Value), Addr, CharUnits::One());
133
247
  }
134
135
  // Temporarily use old signature; clang will be updated to an Address overload
136
  // in a subsequent patch.
137
  llvm::AtomicCmpXchgInst *
138
  CreateAtomicCmpXchg(llvm::Value *Ptr, llvm::Value *Cmp, llvm::Value *New,
139
                      llvm::AtomicOrdering SuccessOrdering,
140
                      llvm::AtomicOrdering FailureOrdering,
141
550
                      llvm::SyncScope::ID SSID = llvm::SyncScope::System) {
142
550
    return CGBuilderBaseTy::CreateAtomicCmpXchg(
143
550
        Ptr, Cmp, New, llvm::MaybeAlign(), SuccessOrdering, FailureOrdering,
144
550
        SSID);
145
550
  }
146
147
  // Temporarily use old signature; clang will be updated to an Address overload
148
  // in a subsequent patch.
149
  llvm::AtomicRMWInst *
150
  CreateAtomicRMW(llvm::AtomicRMWInst::BinOp Op, llvm::Value *Ptr,
151
                  llvm::Value *Val, llvm::AtomicOrdering Ordering,
152
2.21k
                  llvm::SyncScope::ID SSID = llvm::SyncScope::System) {
153
2.21k
    return CGBuilderBaseTy::CreateAtomicRMW(Op, Ptr, Val, llvm::MaybeAlign(),
154
2.21k
                                            Ordering, SSID);
155
2.21k
  }
156
157
  using CGBuilderBaseTy::CreateAddrSpaceCast;
158
  Address CreateAddrSpaceCast(Address Addr, llvm::Type *Ty,
159
5
                              const llvm::Twine &Name = "") {
160
5
    assert(cast<llvm::PointerType>(Ty)->isOpaqueOrPointeeTypeMatches(
161
5
               Addr.getElementType()) &&
162
5
           "Should not change the element type");
163
0
    return Addr.withPointer(CreateAddrSpaceCast(Addr.getPointer(), Ty, Name));
164
5
  }
165
166
  /// Cast the element type of the given address to a different type,
167
  /// preserving information like the alignment and address space.
168
  Address CreateElementBitCast(Address Addr, llvm::Type *Ty,
169
568k
                               const llvm::Twine &Name = "") {
170
568k
    auto *PtrTy = Ty->getPointerTo(Addr.getAddressSpace());
171
568k
    return Address(CreateBitCast(Addr.getPointer(), PtrTy, Name), Ty,
172
568k
                   Addr.getAlignment());
173
568k
  }
174
175
  using CGBuilderBaseTy::CreatePointerBitCastOrAddrSpaceCast;
176
  Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty,
177
                                              llvm::Type *ElementTy,
178
2.10k
                                              const llvm::Twine &Name = "") {
179
2.10k
    llvm::Value *Ptr =
180
2.10k
        CreatePointerBitCastOrAddrSpaceCast(Addr.getPointer(), Ty, Name);
181
2.10k
    return Address(Ptr, ElementTy, Addr.getAlignment());
182
2.10k
  }
183
184
  /// Given
185
  ///   %addr = {T1, T2...}* ...
186
  /// produce
187
  ///   %name = getelementptr inbounds %addr, i32 0, i32 index
188
  ///
189
  /// This API assumes that drilling into a struct like this is always an
190
  /// inbounds operation.
191
  using CGBuilderBaseTy::CreateStructGEP;
192
  Address CreateStructGEP(Address Addr, unsigned Index,
193
277k
                          const llvm::Twine &Name = "") {
194
277k
    llvm::StructType *ElTy = cast<llvm::StructType>(Addr.getElementType());
195
277k
    const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
196
277k
    const llvm::StructLayout *Layout = DL.getStructLayout(ElTy);
197
277k
    auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index));
198
199
277k
    return Address(
200
277k
        CreateStructGEP(Addr.getElementType(), Addr.getPointer(), Index, Name),
201
277k
        ElTy->getElementType(Index),
202
277k
        Addr.getAlignment().alignmentAtOffset(Offset));
203
277k
  }
204
205
  /// Given
206
  ///   %addr = [n x T]* ...
207
  /// produce
208
  ///   %name = getelementptr inbounds %addr, i64 0, i64 index
209
  /// where i64 is actually the target word size.
210
  ///
211
  /// This API assumes that drilling into an array like this is always
212
  /// an inbounds operation.
213
  Address CreateConstArrayGEP(Address Addr, uint64_t Index,
214
107k
                              const llvm::Twine &Name = "") {
215
107k
    llvm::ArrayType *ElTy = cast<llvm::ArrayType>(Addr.getElementType());
216
107k
    const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
217
107k
    CharUnits EltSize =
218
107k
        CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy->getElementType()));
219
220
107k
    return Address(
221
107k
        CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(),
222
107k
                          {getSize(CharUnits::Zero()), getSize(Index)}, Name),
223
107k
        ElTy->getElementType(),
224
107k
        Addr.getAlignment().alignmentAtOffset(Index * EltSize));
225
107k
  }
226
227
  /// Given
228
  ///   %addr = T* ...
229
  /// produce
230
  ///   %name = getelementptr inbounds %addr, i64 index
231
  /// where i64 is actually the target word size.
232
  Address CreateConstInBoundsGEP(Address Addr, uint64_t Index,
233
356
                                 const llvm::Twine &Name = "") {
234
356
    llvm::Type *ElTy = Addr.getElementType();
235
356
    const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
236
356
    CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy));
237
238
356
    return Address(CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(),
239
356
                                     getSize(Index), Name),
240
356
                   ElTy,
241
356
                   Addr.getAlignment().alignmentAtOffset(Index * EltSize));
242
356
  }
243
244
  /// Given
245
  ///   %addr = T* ...
246
  /// produce
247
  ///   %name = getelementptr inbounds %addr, i64 index
248
  /// where i64 is actually the target word size.
249
  Address CreateConstGEP(Address Addr, uint64_t Index,
250
1.19k
                         const llvm::Twine &Name = "") {
251
1.19k
    const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
252
1.19k
    CharUnits EltSize =
253
1.19k
        CharUnits::fromQuantity(DL.getTypeAllocSize(Addr.getElementType()));
254
255
1.19k
    return Address(CreateGEP(Addr.getElementType(), Addr.getPointer(),
256
1.19k
                             getSize(Index), Name),
257
1.19k
                   Addr.getElementType(),
258
1.19k
                   Addr.getAlignment().alignmentAtOffset(Index * EltSize));
259
1.19k
  }
260
261
  /// Create GEP with single dynamic index. The address alignment is reduced
262
  /// according to the element size.
263
  using CGBuilderBaseTy::CreateGEP;
264
  Address CreateGEP(Address Addr, llvm::Value *Index,
265
54
                    const llvm::Twine &Name = "") {
266
54
    const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
267
54
    CharUnits EltSize =
268
54
        CharUnits::fromQuantity(DL.getTypeAllocSize(Addr.getElementType()));
269
270
54
    return Address(
271
54
        CreateGEP(Addr.getElementType(), Addr.getPointer(), Index, Name),
272
54
        Addr.getElementType(),
273
54
        Addr.getAlignment().alignmentOfArrayElement(EltSize));
274
54
  }
275
276
  /// Given a pointer to i8, adjust it by a given constant offset.
277
  Address CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset,
278
3.50k
                                     const llvm::Twine &Name = "") {
279
3.50k
    assert(Addr.getElementType() == TypeCache.Int8Ty);
280
0
    return Address(CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(),
281
3.50k
                                     getSize(Offset), Name),
282
3.50k
                   Addr.getElementType(),
283
3.50k
                   Addr.getAlignment().alignmentAtOffset(Offset));
284
3.50k
  }
285
  Address CreateConstByteGEP(Address Addr, CharUnits Offset,
286
637
                             const llvm::Twine &Name = "") {
287
637
    assert(Addr.getElementType() == TypeCache.Int8Ty);
288
0
    return Address(CreateGEP(Addr.getElementType(), Addr.getPointer(),
289
637
                             getSize(Offset), Name),
290
637
                   Addr.getElementType(),
291
637
                   Addr.getAlignment().alignmentAtOffset(Offset));
292
637
  }
293
294
  using CGBuilderBaseTy::CreateConstInBoundsGEP2_32;
295
  Address CreateConstInBoundsGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1,
296
190
                                     const llvm::Twine &Name = "") {
297
190
    const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
298
299
190
    auto *GEP = cast<llvm::GetElementPtrInst>(CreateConstInBoundsGEP2_32(
300
190
        Addr.getElementType(), Addr.getPointer(), Idx0, Idx1, Name));
301
190
    llvm::APInt Offset(
302
190
        DL.getIndexSizeInBits(Addr.getType()->getPointerAddressSpace()), 0,
303
190
        /*isSigned=*/true);
304
190
    if (!GEP->accumulateConstantOffset(DL, Offset))
305
0
      llvm_unreachable("offset of GEP with constants is always computable");
306
190
    return Address(GEP, GEP->getResultElementType(),
307
190
                   Addr.getAlignment().alignmentAtOffset(
308
190
                       CharUnits::fromQuantity(Offset.getSExtValue())));
309
190
  }
310
311
  using CGBuilderBaseTy::CreateMemCpy;
312
  llvm::CallInst *CreateMemCpy(Address Dest, Address Src, llvm::Value *Size,
313
16.1k
                               bool IsVolatile = false) {
314
16.1k
    return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getAsAlign(),
315
16.1k
                        Src.getPointer(), Src.getAlignment().getAsAlign(), Size,
316
16.1k
                        IsVolatile);
317
16.1k
  }
318
  llvm::CallInst *CreateMemCpy(Address Dest, Address Src, uint64_t Size,
319
381
                               bool IsVolatile = false) {
320
381
    return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getAsAlign(),
321
381
                        Src.getPointer(), Src.getAlignment().getAsAlign(), Size,
322
381
                        IsVolatile);
323
381
  }
324
325
  using CGBuilderBaseTy::CreateMemCpyInline;
326
4
  llvm::CallInst *CreateMemCpyInline(Address Dest, Address Src, uint64_t Size) {
327
4
    return CreateMemCpyInline(
328
4
        Dest.getPointer(), Dest.getAlignment().getAsAlign(), Src.getPointer(),
329
4
        Src.getAlignment().getAsAlign(), getInt64(Size));
330
4
  }
331
332
  using CGBuilderBaseTy::CreateMemMove;
333
  llvm::CallInst *CreateMemMove(Address Dest, Address Src, llvm::Value *Size,
334
128
                                bool IsVolatile = false) {
335
128
    return CreateMemMove(Dest.getPointer(), Dest.getAlignment().getAsAlign(),
336
128
                         Src.getPointer(), Src.getAlignment().getAsAlign(),
337
128
                         Size, IsVolatile);
338
128
  }
339
340
  using CGBuilderBaseTy::CreateMemSet;
341
  llvm::CallInst *CreateMemSet(Address Dest, llvm::Value *Value,
342
2.54k
                               llvm::Value *Size, bool IsVolatile = false) {
343
2.54k
    return CreateMemSet(Dest.getPointer(), Value, Size,
344
2.54k
                        Dest.getAlignment().getAsAlign(), IsVolatile);
345
2.54k
  }
346
347
  using CGBuilderBaseTy::CreateMemSetInline;
348
  llvm::CallInst *CreateMemSetInline(Address Dest, llvm::Value *Value,
349
3
                                     uint64_t Size) {
350
3
    return CreateMemSetInline(Dest.getPointer(),
351
3
                              Dest.getAlignment().getAsAlign(), Value,
352
3
                              getInt64(Size));
353
3
  }
354
355
  using CGBuilderBaseTy::CreatePreserveStructAccessIndex;
356
  Address CreatePreserveStructAccessIndex(Address Addr, unsigned Index,
357
                                          unsigned FieldIndex,
358
11
                                          llvm::MDNode *DbgInfo) {
359
11
    llvm::StructType *ElTy = cast<llvm::StructType>(Addr.getElementType());
360
11
    const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
361
11
    const llvm::StructLayout *Layout = DL.getStructLayout(ElTy);
362
11
    auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index));
363
364
11
    return Address(CreatePreserveStructAccessIndex(ElTy, Addr.getPointer(),
365
11
                                                   Index, FieldIndex, DbgInfo),
366
11
                   ElTy->getElementType(Index),
367
11
                   Addr.getAlignment().alignmentAtOffset(Offset));
368
11
  }
369
370
  using CGBuilderBaseTy::CreateLaunderInvariantGroup;
371
11
  Address CreateLaunderInvariantGroup(Address Addr) {
372
11
    return Addr.withPointer(CreateLaunderInvariantGroup(Addr.getPointer()));
373
11
  }
374
};
375
376
} // end namespace CodeGen
377
} // end namespace clang
378
379
#endif