Coverage Report

Created: 2020-09-22 08:39

/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
1.89k
  CGBuilderInserter() = default;
28
288k
  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
250
    : CGBuilderBaseTy(C), TypeCache(TypeCache) {}
50
  CGBuilderTy(const CodeGenTypeCache &TypeCache,
51
              llvm::LLVMContext &C, const llvm::ConstantFolder &F,
52
              const CGBuilderInserterTy &Inserter)
53
288k
    : CGBuilderBaseTy(C, F, Inserter), TypeCache(TypeCache) {}
54
  CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::Instruction *I)
55
144
    : CGBuilderBaseTy(I), TypeCache(TypeCache) {}
56
  CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::BasicBlock *BB)
57
1.50k
    : CGBuilderBaseTy(BB), TypeCache(TypeCache) {}
58
59
74.5k
  llvm::ConstantInt *getSize(CharUnits N) {
60
74.5k
    return llvm::ConstantInt::get(TypeCache.SizeTy, N.getQuantity());
61
74.5k
  }
62
72.2k
  llvm::ConstantInt *getSize(uint64_t N) {
63
72.2k
    return llvm::ConstantInt::get(TypeCache.SizeTy, N);
64
72.2k
  }
65
66
  // Note that we intentionally hide the CreateLoad APIs that don't
67
  // take an alignment.
68
83.1k
  llvm::LoadInst *CreateLoad(Address Addr, const llvm::Twine &Name = "") {
69
83.1k
    return CreateAlignedLoad(Addr.getPointer(),
70
83.1k
                             Addr.getAlignment().getAsAlign(), Name);
71
83.1k
  }
72
109k
  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
109k
    return CreateAlignedLoad(Addr.getPointer(),
76
109k
                             Addr.getAlignment().getAsAlign(), Name);
77
109k
  }
78
  llvm::LoadInst *CreateLoad(Address Addr, bool IsVolatile,
79
995k
                             const llvm::Twine &Name = "") {
80
995k
    return CreateAlignedLoad(
81
995k
        Addr.getPointer(), Addr.getAlignment().getAsAlign(), IsVolatile, Name);
82
995k
  }
83
84
  using CGBuilderBaseTy::CreateAlignedLoad;
85
  llvm::LoadInst *CreateAlignedLoad(llvm::Value *Addr, CharUnits Align,
86
20.1k
                                    const llvm::Twine &Name = "") {
87
20.1k
    return CreateAlignedLoad(Addr, Align.getAsAlign(), Name);
88
20.1k
  }
89
  llvm::LoadInst *CreateAlignedLoad(llvm::Value *Addr, CharUnits Align,
90
3.20k
                                    const char *Name) {
91
3.20k
    return CreateAlignedLoad(Addr, Align.getAsAlign(), Name);
92
3.20k
  }
93
  llvm::LoadInst *CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr,
94
                                    CharUnits Align,
95
490
                                    const llvm::Twine &Name = "") {
96
490
    assert(Addr->getType()->getPointerElementType() == Ty);
97
490
    return CreateAlignedLoad(Addr, Align.getAsAlign(), Name);
98
490
  }
99
100
  // Note that we intentionally hide the CreateStore APIs that don't
101
  // take an alignment.
102
  llvm::StoreInst *CreateStore(llvm::Value *Val, Address Addr,
103
1.10M
                               bool IsVolatile = false) {
104
1.10M
    return CreateAlignedStore(Val, Addr.getPointer(),
105
1.10M
                              Addr.getAlignment().getAsAlign(), IsVolatile);
106
1.10M
  }
107
108
  using CGBuilderBaseTy::CreateAlignedStore;
109
  llvm::StoreInst *CreateAlignedStore(llvm::Value *Val, llvm::Value *Addr,
110
5.45k
                                      CharUnits Align, bool IsVolatile = false) {
111
5.45k
    return CreateAlignedStore(Val, Addr, Align.getAsAlign(), IsVolatile);
112
5.45k
  }
113
114
  // FIXME: these "default-aligned" APIs should be removed,
115
  // but I don't feel like fixing all the builtin code right now.
116
  llvm::StoreInst *CreateDefaultAlignedStore(llvm::Value *Val,
117
                                             llvm::Value *Addr,
118
1.28k
                                             bool IsVolatile = false) {
119
1.28k
    return CGBuilderBaseTy::CreateStore(Val, Addr, IsVolatile);
120
1.28k
  }
121
122
  /// Emit a load from an i1 flag variable.
123
  llvm::LoadInst *CreateFlagLoad(llvm::Value *Addr,
124
207
                                 const llvm::Twine &Name = "") {
125
207
    assert(Addr->getType()->getPointerElementType() == getInt1Ty());
126
207
    return CreateAlignedLoad(getInt1Ty(), Addr, CharUnits::One(), Name);
127
207
  }
128
129
  /// Emit a store to an i1 flag variable.
130
211
  llvm::StoreInst *CreateFlagStore(bool Value, llvm::Value *Addr) {
131
211
    assert(Addr->getType()->getPointerElementType() == getInt1Ty());
132
211
    return CreateAlignedStore(getInt1(Value), Addr, CharUnits::One());
133
211
  }
134
135
  using CGBuilderBaseTy::CreateBitCast;
136
  Address CreateBitCast(Address Addr, llvm::Type *Ty,
137
397k
                        const llvm::Twine &Name = "") {
138
397k
    return Address(CreateBitCast(Addr.getPointer(), Ty, Name),
139
397k
                   Addr.getAlignment());
140
397k
  }
141
142
  using CGBuilderBaseTy::CreateAddrSpaceCast;
143
  Address CreateAddrSpaceCast(Address Addr, llvm::Type *Ty,
144
5
                              const llvm::Twine &Name = "") {
145
5
    return Address(CreateAddrSpaceCast(Addr.getPointer(), Ty, Name),
146
5
                   Addr.getAlignment());
147
5
  }
148
149
  /// Cast the element type of the given address to a different type,
150
  /// preserving information like the alignment and address space.
151
  Address CreateElementBitCast(Address Addr, llvm::Type *Ty,
152
342k
                               const llvm::Twine &Name = "") {
153
342k
    auto PtrTy = Ty->getPointerTo(Addr.getAddressSpace());
154
342k
    return CreateBitCast(Addr, PtrTy, Name);
155
342k
  }
156
157
  using CGBuilderBaseTy::CreatePointerBitCastOrAddrSpaceCast;
158
  Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty,
159
1.76k
                                              const llvm::Twine &Name = "") {
160
1.76k
    llvm::Value *Ptr =
161
1.76k
      CreatePointerBitCastOrAddrSpaceCast(Addr.getPointer(), Ty, Name);
162
1.76k
    return Address(Ptr, Addr.getAlignment());
163
1.76k
  }
164
165
  /// Given
166
  ///   %addr = {T1, T2...}* ...
167
  /// produce
168
  ///   %name = getelementptr inbounds %addr, i32 0, i32 index
169
  ///
170
  /// This API assumes that drilling into a struct like this is always an
171
  /// inbounds operation.
172
  using CGBuilderBaseTy::CreateStructGEP;
173
  Address CreateStructGEP(Address Addr, unsigned Index,
174
210k
                          const llvm::Twine &Name = "") {
175
210k
    llvm::StructType *ElTy = cast<llvm::StructType>(Addr.getElementType());
176
210k
    const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
177
210k
    const llvm::StructLayout *Layout = DL.getStructLayout(ElTy);
178
210k
    auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index));
179
180
210k
    return Address(CreateStructGEP(Addr.getElementType(),
181
210k
                                   Addr.getPointer(), Index, Name),
182
210k
                   Addr.getAlignment().alignmentAtOffset(Offset));
183
210k
  }
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
70.5k
                              const llvm::Twine &Name = "") {
195
70.5k
    llvm::ArrayType *ElTy = cast<llvm::ArrayType>(Addr.getElementType());
196
70.5k
    const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
197
70.5k
    CharUnits EltSize =
198
70.5k
        CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy->getElementType()));
199
200
70.5k
    return Address(
201
70.5k
        CreateInBoundsGEP(Addr.getPointer(),
202
70.5k
                          {getSize(CharUnits::Zero()), getSize(Index)}, Name),
203
70.5k
        Addr.getAlignment().alignmentAtOffset(Index * EltSize));
204
70.5k
  }
205
206
  /// Given
207
  ///   %addr = T* ...
208
  /// produce
209
  ///   %name = getelementptr inbounds %addr, i64 index
210
  /// where i64 is actually the target word size.
211
  Address CreateConstInBoundsGEP(Address Addr, uint64_t Index,
212
423
                                 const llvm::Twine &Name = "") {
213
423
    llvm::Type *ElTy = Addr.getElementType();
214
423
    const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
215
423
    CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy));
216
217
423
    return Address(CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(),
218
423
                                     getSize(Index), Name),
219
423
                   Addr.getAlignment().alignmentAtOffset(Index * EltSize));
220
423
  }
221
222
  /// Given
223
  ///   %addr = T* ...
224
  /// produce
225
  ///   %name = getelementptr inbounds %addr, i64 index
226
  /// where i64 is actually the target word size.
227
  Address CreateConstGEP(Address Addr, uint64_t Index,
228
1.19k
                         const llvm::Twine &Name = "") {
229
1.19k
    const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
230
1.19k
    CharUnits EltSize =
231
1.19k
        CharUnits::fromQuantity(DL.getTypeAllocSize(Addr.getElementType()));
232
233
1.19k
    return Address(CreateGEP(Addr.getElementType(), Addr.getPointer(),
234
1.19k
                             getSize(Index), Name),
235
1.19k
                   Addr.getAlignment().alignmentAtOffset(Index * EltSize));
236
1.19k
  }
237
238
  /// Given a pointer to i8, adjust it by a given constant offset.
239
  Address CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset,
240
3.36k
                                     const llvm::Twine &Name = "") {
241
3.36k
    assert(Addr.getElementType() == TypeCache.Int8Ty);
242
3.36k
    return Address(CreateInBoundsGEP(Addr.getPointer(), getSize(Offset), Name),
243
3.36k
                   Addr.getAlignment().alignmentAtOffset(Offset));
244
3.36k
  }
245
  Address CreateConstByteGEP(Address Addr, CharUnits Offset,
246
576
                             const llvm::Twine &Name = "") {
247
576
    assert(Addr.getElementType() == TypeCache.Int8Ty);
248
576
    return Address(CreateGEP(Addr.getPointer(), getSize(Offset), Name),
249
576
                   Addr.getAlignment().alignmentAtOffset(Offset));
250
576
  }
251
252
  using CGBuilderBaseTy::CreateConstInBoundsGEP2_32;
253
  Address CreateConstInBoundsGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1,
254
191
                                     const llvm::Twine &Name = "") {
255
191
    const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
256
257
191
    auto *GEP = cast<llvm::GetElementPtrInst>(CreateConstInBoundsGEP2_32(
258
191
        Addr.getElementType(), Addr.getPointer(), Idx0, Idx1, Name));
259
191
    llvm::APInt Offset(
260
191
        DL.getIndexSizeInBits(Addr.getType()->getPointerAddressSpace()), 0,
261
191
        /*isSigned=*/true);
262
191
    if (!GEP->accumulateConstantOffset(DL, Offset))
263
0
      llvm_unreachable("offset of GEP with constants is always computable");
264
191
    return Address(GEP, Addr.getAlignment().alignmentAtOffset(
265
191
                            CharUnits::fromQuantity(Offset.getSExtValue())));
266
191
  }
267
268
  using CGBuilderBaseTy::CreateMemCpy;
269
  llvm::CallInst *CreateMemCpy(Address Dest, Address Src, llvm::Value *Size,
270
13.6k
                               bool IsVolatile = false) {
271
13.6k
    return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getAsAlign(),
272
13.6k
                        Src.getPointer(), Src.getAlignment().getAsAlign(), Size,
273
13.6k
                        IsVolatile);
274
13.6k
  }
275
  llvm::CallInst *CreateMemCpy(Address Dest, Address Src, uint64_t Size,
276
333
                               bool IsVolatile = false) {
277
333
    return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getAsAlign(),
278
333
                        Src.getPointer(), Src.getAlignment().getAsAlign(), Size,
279
333
                        IsVolatile);
280
333
  }
281
282
  using CGBuilderBaseTy::CreateMemCpyInline;
283
4
  llvm::CallInst *CreateMemCpyInline(Address Dest, Address Src, uint64_t Size) {
284
4
    return CreateMemCpyInline(
285
4
        Dest.getPointer(), Dest.getAlignment().getAsAlign(), Src.getPointer(),
286
4
        Src.getAlignment().getAsAlign(), getInt64(Size));
287
4
  }
288
289
  using CGBuilderBaseTy::CreateMemMove;
290
  llvm::CallInst *CreateMemMove(Address Dest, Address Src, llvm::Value *Size,
291
13
                                bool IsVolatile = false) {
292
13
    return CreateMemMove(Dest.getPointer(), Dest.getAlignment().getAsAlign(),
293
13
                         Src.getPointer(), Src.getAlignment().getAsAlign(),
294
13
                         Size, IsVolatile);
295
13
  }
296
297
  using CGBuilderBaseTy::CreateMemSet;
298
  llvm::CallInst *CreateMemSet(Address Dest, llvm::Value *Value,
299
2.42k
                               llvm::Value *Size, bool IsVolatile = false) {
300
2.42k
    return CreateMemSet(Dest.getPointer(), Value, Size,
301
2.42k
                        Dest.getAlignment().getAsAlign(), IsVolatile);
302
2.42k
  }
303
304
  using CGBuilderBaseTy::CreatePreserveStructAccessIndex;
305
  Address CreatePreserveStructAccessIndex(Address Addr,
306
                                          unsigned Index,
307
                                          unsigned FieldIndex,
308
38
                                          llvm::MDNode *DbgInfo) {
309
38
    llvm::StructType *ElTy = cast<llvm::StructType>(Addr.getElementType());
310
38
    const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
311
38
    const llvm::StructLayout *Layout = DL.getStructLayout(ElTy);
312
38
    auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index));
313
314
38
    return Address(CreatePreserveStructAccessIndex(ElTy, Addr.getPointer(),
315
38
                                                   Index, FieldIndex, DbgInfo),
316
38
                   Addr.getAlignment().alignmentAtOffset(Offset));
317
38
  }
318
};
319
320
}  // end namespace CodeGen
321
}  // end namespace clang
322
323
#endif