Coverage Report

Created: 2022-01-25 06:29

/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 "llvm/IR/DataLayout.h"
13
#include "llvm/IR/IRBuilder.h"
14
#include "Address.h"
15
#include "CodeGenTypeCache.h"
16
17
namespace clang {
18
namespace CodeGen {
19
20
class CodeGenFunction;
21
22
/// This is an IRBuilder insertion helper that forwards to
23
/// CodeGenFunction::InsertHelper, which adds necessary metadata to
24
/// instructions.
25
class CGBuilderInserter final : public llvm::IRBuilderDefaultInserter {
26
public:
27
2.05k
  CGBuilderInserter() = default;
28
314k
  explicit CGBuilderInserter(CodeGenFunction *CGF) : CGF(CGF) {}
29
30
  /// This forwards to CodeGenFunction::InsertHelper.
31
  void InsertHelper(llvm::Instruction *I, const llvm::Twine &Name,
32
                    llvm::BasicBlock *BB,
33
                    llvm::BasicBlock::iterator InsertPt) const override;
34
private:
35
  CodeGenFunction *CGF = nullptr;
36
};
37
38
typedef CGBuilderInserter CGBuilderInserterTy;
39
40
typedef llvm::IRBuilder<llvm::ConstantFolder, CGBuilderInserterTy>
41
    CGBuilderBaseTy;
42
43
class CGBuilderTy : public CGBuilderBaseTy {
44
  /// Storing a reference to the type cache here makes it a lot easier
45
  /// to build natural-feeling, target-specific IR.
46
  const CodeGenTypeCache &TypeCache;
47
public:
48
  CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::LLVMContext &C)
49
284
    : CGBuilderBaseTy(C), TypeCache(TypeCache) {}
50
  CGBuilderTy(const CodeGenTypeCache &TypeCache,
51
              llvm::LLVMContext &C, const llvm::ConstantFolder &F,
52
              const CGBuilderInserterTy &Inserter)
53
314k
    : CGBuilderBaseTy(C, F, Inserter), TypeCache(TypeCache) {}
54
  CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::Instruction *I)
55
214
    : CGBuilderBaseTy(I), TypeCache(TypeCache) {}
56
  CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::BasicBlock *BB)
57
1.56k
    : CGBuilderBaseTy(BB), TypeCache(TypeCache) {}
58
59
109k
  llvm::ConstantInt *getSize(CharUnits N) {
60
109k
    return llvm::ConstantInt::get(TypeCache.SizeTy, N.getQuantity());
61
109k
  }
62
107k
  llvm::ConstantInt *getSize(uint64_t N) {
63
107k
    return llvm::ConstantInt::get(TypeCache.SizeTy, N);
64
107k
  }
65
66
  // Note that we intentionally hide the CreateLoad APIs that don't
67
  // take an alignment.
68
88.9k
  llvm::LoadInst *CreateLoad(Address Addr, const llvm::Twine &Name = "") {
69
88.9k
    return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(),
70
88.9k
                             Addr.getAlignment().getAsAlign(), Name);
71
88.9k
  }
72
120k
  llvm::LoadInst *CreateLoad(Address Addr, const char *Name) {
73
    // This overload is required to prevent string literals from
74
    // ending up in the IsVolatile overload.
75
120k
    return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(),
76
120k
                             Addr.getAlignment().getAsAlign(), Name);
77
120k
  }
78
  llvm::LoadInst *CreateLoad(Address Addr, bool IsVolatile,
79
1.26M
                             const llvm::Twine &Name = "") {
80
1.26M
    return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(),
81
1.26M
                             Addr.getAlignment().getAsAlign(), IsVolatile,
82
1.26M
                             Name);
83
1.26M
  }
84
85
  using CGBuilderBaseTy::CreateAlignedLoad;
86
  llvm::LoadInst *CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr,
87
                                    CharUnits Align,
88
26.8k
                                    const llvm::Twine &Name = "") {
89
26.8k
    assert(llvm::cast<llvm::PointerType>(Addr->getType())
90
26.8k
               ->isOpaqueOrPointeeTypeMatches(Ty));
91
0
    return CreateAlignedLoad(Ty, Addr, Align.getAsAlign(), Name);
92
26.8k
  }
93
94
  // Note that we intentionally hide the CreateStore APIs that don't
95
  // take an alignment.
96
  llvm::StoreInst *CreateStore(llvm::Value *Val, Address Addr,
97
1.24M
                               bool IsVolatile = false) {
98
1.24M
    return CreateAlignedStore(Val, Addr.getPointer(),
99
1.24M
                              Addr.getAlignment().getAsAlign(), IsVolatile);
100
1.24M
  }
101
102
  using CGBuilderBaseTy::CreateAlignedStore;
103
  llvm::StoreInst *CreateAlignedStore(llvm::Value *Val, llvm::Value *Addr,
104
6.64k
                                      CharUnits Align, bool IsVolatile = false) {
105
6.64k
    return CreateAlignedStore(Val, Addr, Align.getAsAlign(), IsVolatile);
106
6.64k
  }
107
108
  // FIXME: these "default-aligned" APIs should be removed,
109
  // but I don't feel like fixing all the builtin code right now.
110
  llvm::StoreInst *CreateDefaultAlignedStore(llvm::Value *Val,
111
                                             llvm::Value *Addr,
112
971
                                             bool IsVolatile = false) {
113
971
    return CGBuilderBaseTy::CreateStore(Val, Addr, IsVolatile);
114
971
  }
115
116
  /// Emit a load from an i1 flag variable.
117
  llvm::LoadInst *CreateFlagLoad(llvm::Value *Addr,
118
238
                                 const llvm::Twine &Name = "") {
119
238
    assert(llvm::cast<llvm::PointerType>(Addr->getType())
120
238
               ->isOpaqueOrPointeeTypeMatches(getInt1Ty()));
121
0
    return CreateAlignedLoad(getInt1Ty(), Addr, CharUnits::One(), Name);
122
238
  }
123
124
  /// Emit a store to an i1 flag variable.
125
243
  llvm::StoreInst *CreateFlagStore(bool Value, llvm::Value *Addr) {
126
243
    assert(llvm::cast<llvm::PointerType>(Addr->getType())
127
243
               ->isOpaqueOrPointeeTypeMatches(getInt1Ty()));
128
0
    return CreateAlignedStore(getInt1(Value), Addr, CharUnits::One());
129
243
  }
130
131
  // Temporarily use old signature; clang will be updated to an Address overload
132
  // in a subsequent patch.
133
  llvm::AtomicCmpXchgInst *
134
  CreateAtomicCmpXchg(llvm::Value *Ptr, llvm::Value *Cmp, llvm::Value *New,
135
                      llvm::AtomicOrdering SuccessOrdering,
136
                      llvm::AtomicOrdering FailureOrdering,
137
575
                      llvm::SyncScope::ID SSID = llvm::SyncScope::System) {
138
575
    return CGBuilderBaseTy::CreateAtomicCmpXchg(
139
575
        Ptr, Cmp, New, llvm::MaybeAlign(), SuccessOrdering, FailureOrdering,
140
575
        SSID);
141
575
  }
142
143
  // Temporarily use old signature; clang will be updated to an Address overload
144
  // in a subsequent patch.
145
  llvm::AtomicRMWInst *
146
  CreateAtomicRMW(llvm::AtomicRMWInst::BinOp Op, llvm::Value *Ptr,
147
                  llvm::Value *Val, llvm::AtomicOrdering Ordering,
148
2.18k
                  llvm::SyncScope::ID SSID = llvm::SyncScope::System) {
149
2.18k
    return CGBuilderBaseTy::CreateAtomicRMW(Op, Ptr, Val, llvm::MaybeAlign(),
150
2.18k
                                            Ordering, SSID);
151
2.18k
  }
152
153
  using CGBuilderBaseTy::CreateBitCast;
154
  Address CreateBitCast(Address Addr, llvm::Type *Ty,
155
11.6k
                        const llvm::Twine &Name = "") {
156
11.6k
    return Address(CreateBitCast(Addr.getPointer(), Ty, Name),
157
11.6k
                   Addr.getAlignment());
158
11.6k
  }
159
160
  using CGBuilderBaseTy::CreateAddrSpaceCast;
161
  Address CreateAddrSpaceCast(Address Addr, llvm::Type *Ty,
162
5
                              const llvm::Twine &Name = "") {
163
5
    return Address(CreateAddrSpaceCast(Addr.getPointer(), Ty, Name),
164
5
                   Addr.getAlignment());
165
5
  }
166
167
  /// Cast the element type of the given address to a different type,
168
  /// preserving information like the alignment and address space.
169
  Address CreateElementBitCast(Address Addr, llvm::Type *Ty,
170
537k
                               const llvm::Twine &Name = "") {
171
537k
    auto *PtrTy = Ty->getPointerTo(Addr.getAddressSpace());
172
537k
    return Address(CreateBitCast(Addr.getPointer(), PtrTy, Name),
173
537k
                   Ty, Addr.getAlignment());
174
537k
  }
175
176
  using CGBuilderBaseTy::CreatePointerBitCastOrAddrSpaceCast;
177
  Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty,
178
2.04k
                                              const llvm::Twine &Name = "") {
179
2.04k
    llvm::Value *Ptr =
180
2.04k
      CreatePointerBitCastOrAddrSpaceCast(Addr.getPointer(), Ty, Name);
181
2.04k
    return Address(Ptr, Addr.getAlignment());
182
2.04k
  }
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
272k
                          const llvm::Twine &Name = "") {
194
272k
    llvm::StructType *ElTy = cast<llvm::StructType>(Addr.getElementType());
195
272k
    const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
196
272k
    const llvm::StructLayout *Layout = DL.getStructLayout(ElTy);
197
272k
    auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index));
198
199
272k
    return Address(CreateStructGEP(Addr.getElementType(),
200
272k
                                   Addr.getPointer(), Index, Name),
201
272k
                   ElTy->getElementType(Index),
202
272k
                   Addr.getAlignment().alignmentAtOffset(Offset));
203
272k
  }
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
105k
                              const llvm::Twine &Name = "") {
215
105k
    llvm::ArrayType *ElTy = cast<llvm::ArrayType>(Addr.getElementType());
216
105k
    const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
217
105k
    CharUnits EltSize =
218
105k
        CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy->getElementType()));
219
220
105k
    return Address(
221
105k
        CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(),
222
105k
                          {getSize(CharUnits::Zero()), getSize(Index)}, Name),
223
105k
        ElTy->getElementType(),
224
105k
        Addr.getAlignment().alignmentAtOffset(Index * EltSize));
225
105k
  }
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.13k
                         const llvm::Twine &Name = "") {
251
1.13k
    const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
252
1.13k
    CharUnits EltSize =
253
1.13k
        CharUnits::fromQuantity(DL.getTypeAllocSize(Addr.getElementType()));
254
255
1.13k
    return Address(CreateGEP(Addr.getElementType(), Addr.getPointer(),
256
1.13k
                             getSize(Index), Name),
257
1.13k
                   Addr.getElementType(),
258
1.13k
                   Addr.getAlignment().alignmentAtOffset(Index * EltSize));
259
1.13k
  }
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(CreateGEP(Addr.getElementType(), Addr.getPointer(), Index,
271
54
                             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.45k
                                     const llvm::Twine &Name = "") {
279
3.45k
    assert(Addr.getElementType() == TypeCache.Int8Ty);
280
0
    return Address(CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(),
281
3.45k
                                     getSize(Offset), Name),
282
3.45k
                   Addr.getElementType(),
283
3.45k
                   Addr.getAlignment().alignmentAtOffset(Offset));
284
3.45k
  }
285
  Address CreateConstByteGEP(Address Addr, CharUnits Offset,
286
616
                             const llvm::Twine &Name = "") {
287
616
    assert(Addr.getElementType() == TypeCache.Int8Ty);
288
0
    return Address(CreateGEP(Addr.getElementType(), Addr.getPointer(),
289
616
                             getSize(Offset), Name),
290
616
                   Addr.getElementType(),
291
616
                   Addr.getAlignment().alignmentAtOffset(Offset));
292
616
  }
293
294
  using CGBuilderBaseTy::CreateConstInBoundsGEP2_32;
295
  Address CreateConstInBoundsGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1,
296
193
                                     const llvm::Twine &Name = "") {
297
193
    const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
298
299
193
    auto *GEP = cast<llvm::GetElementPtrInst>(CreateConstInBoundsGEP2_32(
300
193
        Addr.getElementType(), Addr.getPointer(), Idx0, Idx1, Name));
301
193
    llvm::APInt Offset(
302
193
        DL.getIndexSizeInBits(Addr.getType()->getPointerAddressSpace()), 0,
303
193
        /*isSigned=*/true);
304
193
    if (!GEP->accumulateConstantOffset(DL, Offset))
305
0
      llvm_unreachable("offset of GEP with constants is always computable");
306
193
    return Address(GEP, GEP->getResultElementType(),
307
193
                   Addr.getAlignment().alignmentAtOffset(
308
193
                       CharUnits::fromQuantity(Offset.getSExtValue())));
309
193
  }
310
311
  using CGBuilderBaseTy::CreateMemCpy;
312
  llvm::CallInst *CreateMemCpy(Address Dest, Address Src, llvm::Value *Size,
313
14.4k
                               bool IsVolatile = false) {
314
14.4k
    return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getAsAlign(),
315
14.4k
                        Src.getPointer(), Src.getAlignment().getAsAlign(), Size,
316
14.4k
                        IsVolatile);
317
14.4k
  }
318
  llvm::CallInst *CreateMemCpy(Address Dest, Address Src, uint64_t Size,
319
361
                               bool IsVolatile = false) {
320
361
    return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getAsAlign(),
321
361
                        Src.getPointer(), Src.getAlignment().getAsAlign(), Size,
322
361
                        IsVolatile);
323
361
  }
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
6
                                bool IsVolatile = false) {
335
6
    return CreateMemMove(Dest.getPointer(), Dest.getAlignment().getAsAlign(),
336
6
                         Src.getPointer(), Src.getAlignment().getAsAlign(),
337
6
                         Size, IsVolatile);
338
6
  }
339
340
  using CGBuilderBaseTy::CreateMemSet;
341
  llvm::CallInst *CreateMemSet(Address Dest, llvm::Value *Value,
342
2.47k
                               llvm::Value *Size, bool IsVolatile = false) {
343
2.47k
    return CreateMemSet(Dest.getPointer(), Value, Size,
344
2.47k
                        Dest.getAlignment().getAsAlign(), IsVolatile);
345
2.47k
  }
346
347
  using CGBuilderBaseTy::CreatePreserveStructAccessIndex;
348
  Address CreatePreserveStructAccessIndex(Address Addr,
349
                                          unsigned Index,
350
                                          unsigned FieldIndex,
351
11
                                          llvm::MDNode *DbgInfo) {
352
11
    llvm::StructType *ElTy = cast<llvm::StructType>(Addr.getElementType());
353
11
    const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
354
11
    const llvm::StructLayout *Layout = DL.getStructLayout(ElTy);
355
11
    auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index));
356
357
11
    return Address(CreatePreserveStructAccessIndex(ElTy, Addr.getPointer(),
358
11
                                                   Index, FieldIndex, DbgInfo),
359
11
                   ElTy->getElementType(Index),
360
11
                   Addr.getAlignment().alignmentAtOffset(Offset));
361
11
  }
362
363
  using CGBuilderBaseTy::CreateLaunderInvariantGroup;
364
11
  Address CreateLaunderInvariantGroup(Address Addr) {
365
11
    return Addr.withPointer(CreateLaunderInvariantGroup(Addr.getPointer()));
366
11
  }
367
};
368
369
}  // end namespace CodeGen
370
}  // end namespace clang
371
372
#endif