Coverage Report

Created: 2022-05-17 06:19

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