Coverage Report

Created: 2024-01-17 10:31

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