Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/CodeGen/CGBuilder.h
35233 views
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 "CGValue.h"
14
#include "CodeGenTypeCache.h"
15
#include "llvm/Analysis/Utils/Local.h"
16
#include "llvm/IR/DataLayout.h"
17
#include "llvm/IR/IRBuilder.h"
18
#include "llvm/IR/Type.h"
19
20
namespace clang {
21
namespace CodeGen {
22
23
class CGBuilderTy;
24
class CodeGenFunction;
25
26
/// This is an IRBuilder insertion helper that forwards to
27
/// CodeGenFunction::InsertHelper, which adds necessary metadata to
28
/// instructions.
29
class CGBuilderInserter final : public llvm::IRBuilderDefaultInserter {
30
friend CGBuilderTy;
31
32
public:
33
CGBuilderInserter() = default;
34
explicit CGBuilderInserter(CodeGenFunction *CGF) : CGF(CGF) {}
35
36
/// This forwards to CodeGenFunction::InsertHelper.
37
void InsertHelper(llvm::Instruction *I, const llvm::Twine &Name,
38
llvm::BasicBlock::iterator InsertPt) const override;
39
40
private:
41
CodeGenFunction *CGF = nullptr;
42
};
43
44
typedef CGBuilderInserter CGBuilderInserterTy;
45
46
typedef llvm::IRBuilder<llvm::ConstantFolder, CGBuilderInserterTy>
47
CGBuilderBaseTy;
48
49
class CGBuilderTy : public CGBuilderBaseTy {
50
friend class Address;
51
52
/// Storing a reference to the type cache here makes it a lot easier
53
/// to build natural-feeling, target-specific IR.
54
const CodeGenTypeCache &TypeCache;
55
56
CodeGenFunction *getCGF() const { return getInserter().CGF; }
57
58
llvm::Value *emitRawPointerFromAddress(Address Addr) const {
59
return Addr.getBasePointer();
60
}
61
62
template <bool IsInBounds>
63
Address createConstGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1,
64
const llvm::Twine &Name) {
65
const llvm::DataLayout &DL = BB->getDataLayout();
66
llvm::GetElementPtrInst *GEP;
67
if (IsInBounds)
68
GEP = cast<llvm::GetElementPtrInst>(CreateConstInBoundsGEP2_32(
69
Addr.getElementType(), emitRawPointerFromAddress(Addr), Idx0, Idx1,
70
Name));
71
else
72
GEP = cast<llvm::GetElementPtrInst>(CreateConstGEP2_32(
73
Addr.getElementType(), emitRawPointerFromAddress(Addr), Idx0, Idx1,
74
Name));
75
llvm::APInt Offset(
76
DL.getIndexSizeInBits(Addr.getType()->getPointerAddressSpace()), 0,
77
/*isSigned=*/true);
78
if (!GEP->accumulateConstantOffset(DL, Offset))
79
llvm_unreachable("offset of GEP with constants is always computable");
80
return Address(GEP, GEP->getResultElementType(),
81
Addr.getAlignment().alignmentAtOffset(
82
CharUnits::fromQuantity(Offset.getSExtValue())),
83
IsInBounds ? Addr.isKnownNonNull() : NotKnownNonNull);
84
}
85
86
public:
87
CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::LLVMContext &C)
88
: CGBuilderBaseTy(C), TypeCache(TypeCache) {}
89
CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::LLVMContext &C,
90
const llvm::ConstantFolder &F,
91
const CGBuilderInserterTy &Inserter)
92
: CGBuilderBaseTy(C, F, Inserter), TypeCache(TypeCache) {}
93
CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::Instruction *I)
94
: CGBuilderBaseTy(I), TypeCache(TypeCache) {}
95
CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::BasicBlock *BB)
96
: CGBuilderBaseTy(BB), TypeCache(TypeCache) {}
97
98
llvm::ConstantInt *getSize(CharUnits N) {
99
return llvm::ConstantInt::get(TypeCache.SizeTy, N.getQuantity());
100
}
101
llvm::ConstantInt *getSize(uint64_t N) {
102
return llvm::ConstantInt::get(TypeCache.SizeTy, N);
103
}
104
105
// Note that we intentionally hide the CreateLoad APIs that don't
106
// take an alignment.
107
llvm::LoadInst *CreateLoad(Address Addr, const llvm::Twine &Name = "") {
108
return CreateAlignedLoad(Addr.getElementType(),
109
emitRawPointerFromAddress(Addr),
110
Addr.getAlignment().getAsAlign(), Name);
111
}
112
llvm::LoadInst *CreateLoad(Address Addr, const char *Name) {
113
// This overload is required to prevent string literals from
114
// ending up in the IsVolatile overload.
115
return CreateAlignedLoad(Addr.getElementType(),
116
emitRawPointerFromAddress(Addr),
117
Addr.getAlignment().getAsAlign(), Name);
118
}
119
llvm::LoadInst *CreateLoad(Address Addr, bool IsVolatile,
120
const llvm::Twine &Name = "") {
121
return CreateAlignedLoad(
122
Addr.getElementType(), emitRawPointerFromAddress(Addr),
123
Addr.getAlignment().getAsAlign(), IsVolatile, Name);
124
}
125
126
using CGBuilderBaseTy::CreateAlignedLoad;
127
llvm::LoadInst *CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr,
128
CharUnits Align,
129
const llvm::Twine &Name = "") {
130
return CreateAlignedLoad(Ty, Addr, Align.getAsAlign(), Name);
131
}
132
133
// Note that we intentionally hide the CreateStore APIs that don't
134
// take an alignment.
135
llvm::StoreInst *CreateStore(llvm::Value *Val, Address Addr,
136
bool IsVolatile = false) {
137
return CreateAlignedStore(Val, emitRawPointerFromAddress(Addr),
138
Addr.getAlignment().getAsAlign(), IsVolatile);
139
}
140
141
using CGBuilderBaseTy::CreateAlignedStore;
142
llvm::StoreInst *CreateAlignedStore(llvm::Value *Val, llvm::Value *Addr,
143
CharUnits Align,
144
bool IsVolatile = false) {
145
return CreateAlignedStore(Val, Addr, Align.getAsAlign(), IsVolatile);
146
}
147
148
// FIXME: these "default-aligned" APIs should be removed,
149
// but I don't feel like fixing all the builtin code right now.
150
llvm::StoreInst *CreateDefaultAlignedStore(llvm::Value *Val,
151
llvm::Value *Addr,
152
bool IsVolatile = false) {
153
return CGBuilderBaseTy::CreateStore(Val, Addr, IsVolatile);
154
}
155
156
/// Emit a load from an i1 flag variable.
157
llvm::LoadInst *CreateFlagLoad(llvm::Value *Addr,
158
const llvm::Twine &Name = "") {
159
return CreateAlignedLoad(getInt1Ty(), Addr, CharUnits::One(), Name);
160
}
161
162
/// Emit a store to an i1 flag variable.
163
llvm::StoreInst *CreateFlagStore(bool Value, llvm::Value *Addr) {
164
return CreateAlignedStore(getInt1(Value), Addr, CharUnits::One());
165
}
166
167
llvm::AtomicCmpXchgInst *
168
CreateAtomicCmpXchg(Address Addr, llvm::Value *Cmp, llvm::Value *New,
169
llvm::AtomicOrdering SuccessOrdering,
170
llvm::AtomicOrdering FailureOrdering,
171
llvm::SyncScope::ID SSID = llvm::SyncScope::System) {
172
return CGBuilderBaseTy::CreateAtomicCmpXchg(
173
Addr.emitRawPointer(*getCGF()), Cmp, New,
174
Addr.getAlignment().getAsAlign(), SuccessOrdering, FailureOrdering,
175
SSID);
176
}
177
178
llvm::AtomicRMWInst *
179
CreateAtomicRMW(llvm::AtomicRMWInst::BinOp Op, Address Addr, llvm::Value *Val,
180
llvm::AtomicOrdering Ordering,
181
llvm::SyncScope::ID SSID = llvm::SyncScope::System) {
182
return CGBuilderBaseTy::CreateAtomicRMW(
183
Op, Addr.emitRawPointer(*getCGF()), Val,
184
Addr.getAlignment().getAsAlign(), Ordering, SSID);
185
}
186
187
using CGBuilderBaseTy::CreateAddrSpaceCast;
188
Address CreateAddrSpaceCast(Address Addr, llvm::Type *Ty,
189
llvm::Type *ElementTy,
190
const llvm::Twine &Name = "") {
191
if (!Addr.hasOffset())
192
return Address(CreateAddrSpaceCast(Addr.getBasePointer(), Ty, Name),
193
ElementTy, Addr.getAlignment(), Addr.getPointerAuthInfo(),
194
/*Offset=*/nullptr, Addr.isKnownNonNull());
195
// Eagerly force a raw address if these is an offset.
196
return RawAddress(
197
CreateAddrSpaceCast(Addr.emitRawPointer(*getCGF()), Ty, Name),
198
ElementTy, Addr.getAlignment(), Addr.isKnownNonNull());
199
}
200
201
using CGBuilderBaseTy::CreatePointerBitCastOrAddrSpaceCast;
202
Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty,
203
llvm::Type *ElementTy,
204
const llvm::Twine &Name = "") {
205
if (Addr.getType()->getAddressSpace() == Ty->getPointerAddressSpace())
206
return Addr.withElementType(ElementTy);
207
return CreateAddrSpaceCast(Addr, Ty, ElementTy, Name);
208
}
209
210
/// Given
211
/// %addr = {T1, T2...}* ...
212
/// produce
213
/// %name = getelementptr inbounds %addr, i32 0, i32 index
214
///
215
/// This API assumes that drilling into a struct like this is always an
216
/// inbounds operation.
217
using CGBuilderBaseTy::CreateStructGEP;
218
Address CreateStructGEP(Address Addr, unsigned Index,
219
const llvm::Twine &Name = "") {
220
llvm::StructType *ElTy = cast<llvm::StructType>(Addr.getElementType());
221
const llvm::DataLayout &DL = BB->getDataLayout();
222
const llvm::StructLayout *Layout = DL.getStructLayout(ElTy);
223
auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index));
224
225
return Address(CreateStructGEP(Addr.getElementType(), Addr.getBasePointer(),
226
Index, Name),
227
ElTy->getElementType(Index),
228
Addr.getAlignment().alignmentAtOffset(Offset),
229
Addr.isKnownNonNull());
230
}
231
232
/// Given
233
/// %addr = [n x T]* ...
234
/// produce
235
/// %name = getelementptr inbounds %addr, i64 0, i64 index
236
/// where i64 is actually the target word size.
237
///
238
/// This API assumes that drilling into an array like this is always
239
/// an inbounds operation.
240
Address CreateConstArrayGEP(Address Addr, uint64_t Index,
241
const llvm::Twine &Name = "") {
242
llvm::ArrayType *ElTy = cast<llvm::ArrayType>(Addr.getElementType());
243
const llvm::DataLayout &DL = BB->getDataLayout();
244
CharUnits EltSize =
245
CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy->getElementType()));
246
247
return Address(
248
CreateInBoundsGEP(Addr.getElementType(), Addr.getBasePointer(),
249
{getSize(CharUnits::Zero()), getSize(Index)}, Name),
250
ElTy->getElementType(),
251
Addr.getAlignment().alignmentAtOffset(Index * EltSize),
252
Addr.isKnownNonNull());
253
}
254
255
/// Given
256
/// %addr = T* ...
257
/// produce
258
/// %name = getelementptr inbounds %addr, i64 index
259
/// where i64 is actually the target word size.
260
Address CreateConstInBoundsGEP(Address Addr, uint64_t Index,
261
const llvm::Twine &Name = "") {
262
llvm::Type *ElTy = Addr.getElementType();
263
const llvm::DataLayout &DL = BB->getDataLayout();
264
CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy));
265
266
return Address(
267
CreateInBoundsGEP(ElTy, Addr.getBasePointer(), getSize(Index), Name),
268
ElTy, Addr.getAlignment().alignmentAtOffset(Index * EltSize),
269
Addr.isKnownNonNull());
270
}
271
272
/// Given
273
/// %addr = T* ...
274
/// produce
275
/// %name = getelementptr inbounds %addr, i64 index
276
/// where i64 is actually the target word size.
277
Address CreateConstGEP(Address Addr, uint64_t Index,
278
const llvm::Twine &Name = "") {
279
llvm::Type *ElTy = Addr.getElementType();
280
const llvm::DataLayout &DL = BB->getDataLayout();
281
CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy));
282
283
return Address(CreateGEP(ElTy, Addr.getBasePointer(), getSize(Index), Name),
284
Addr.getElementType(),
285
Addr.getAlignment().alignmentAtOffset(Index * EltSize));
286
}
287
288
/// Create GEP with single dynamic index. The address alignment is reduced
289
/// according to the element size.
290
using CGBuilderBaseTy::CreateGEP;
291
Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index,
292
const llvm::Twine &Name = "") {
293
const llvm::DataLayout &DL = BB->getDataLayout();
294
CharUnits EltSize =
295
CharUnits::fromQuantity(DL.getTypeAllocSize(Addr.getElementType()));
296
297
return Address(
298
CreateGEP(Addr.getElementType(), Addr.emitRawPointer(CGF), Index, Name),
299
Addr.getElementType(),
300
Addr.getAlignment().alignmentOfArrayElement(EltSize));
301
}
302
303
/// Given a pointer to i8, adjust it by a given constant offset.
304
Address CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset,
305
const llvm::Twine &Name = "") {
306
assert(Addr.getElementType() == TypeCache.Int8Ty);
307
return Address(
308
CreateInBoundsGEP(Addr.getElementType(), Addr.getBasePointer(),
309
getSize(Offset), Name),
310
Addr.getElementType(), Addr.getAlignment().alignmentAtOffset(Offset),
311
Addr.isKnownNonNull());
312
}
313
314
Address CreateConstByteGEP(Address Addr, CharUnits Offset,
315
const llvm::Twine &Name = "") {
316
assert(Addr.getElementType() == TypeCache.Int8Ty);
317
return Address(CreateGEP(Addr.getElementType(), Addr.getBasePointer(),
318
getSize(Offset), Name),
319
Addr.getElementType(),
320
Addr.getAlignment().alignmentAtOffset(Offset));
321
}
322
323
using CGBuilderBaseTy::CreateConstInBoundsGEP2_32;
324
Address CreateConstInBoundsGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1,
325
const llvm::Twine &Name = "") {
326
return createConstGEP2_32<true>(Addr, Idx0, Idx1, Name);
327
}
328
329
using CGBuilderBaseTy::CreateConstGEP2_32;
330
Address CreateConstGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1,
331
const llvm::Twine &Name = "") {
332
return createConstGEP2_32<false>(Addr, Idx0, Idx1, Name);
333
}
334
335
Address CreateGEP(Address Addr, ArrayRef<llvm::Value *> IdxList,
336
llvm::Type *ElementType, CharUnits Align,
337
const Twine &Name = "") {
338
llvm::Value *Ptr = emitRawPointerFromAddress(Addr);
339
return RawAddress(CreateGEP(Addr.getElementType(), Ptr, IdxList, Name),
340
ElementType, Align);
341
}
342
343
using CGBuilderBaseTy::CreateInBoundsGEP;
344
Address CreateInBoundsGEP(Address Addr, ArrayRef<llvm::Value *> IdxList,
345
llvm::Type *ElementType, CharUnits Align,
346
const Twine &Name = "") {
347
return RawAddress(CreateInBoundsGEP(Addr.getElementType(),
348
emitRawPointerFromAddress(Addr),
349
IdxList, Name),
350
ElementType, Align, Addr.isKnownNonNull());
351
}
352
353
using CGBuilderBaseTy::CreateIsNull;
354
llvm::Value *CreateIsNull(Address Addr, const Twine &Name = "") {
355
if (!Addr.hasOffset())
356
return CreateIsNull(Addr.getBasePointer(), Name);
357
// The pointer isn't null if Addr has an offset since offsets can always
358
// be applied inbound.
359
return llvm::ConstantInt::getFalse(Context);
360
}
361
362
using CGBuilderBaseTy::CreateMemCpy;
363
llvm::CallInst *CreateMemCpy(Address Dest, Address Src, llvm::Value *Size,
364
bool IsVolatile = false) {
365
llvm::Value *DestPtr = emitRawPointerFromAddress(Dest);
366
llvm::Value *SrcPtr = emitRawPointerFromAddress(Src);
367
return CreateMemCpy(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr,
368
Src.getAlignment().getAsAlign(), Size, IsVolatile);
369
}
370
llvm::CallInst *CreateMemCpy(Address Dest, Address Src, uint64_t Size,
371
bool IsVolatile = false) {
372
llvm::Value *DestPtr = emitRawPointerFromAddress(Dest);
373
llvm::Value *SrcPtr = emitRawPointerFromAddress(Src);
374
return CreateMemCpy(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr,
375
Src.getAlignment().getAsAlign(), Size, IsVolatile);
376
}
377
378
using CGBuilderBaseTy::CreateMemCpyInline;
379
llvm::CallInst *CreateMemCpyInline(Address Dest, Address Src, uint64_t Size) {
380
llvm::Value *DestPtr = emitRawPointerFromAddress(Dest);
381
llvm::Value *SrcPtr = emitRawPointerFromAddress(Src);
382
return CreateMemCpyInline(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr,
383
Src.getAlignment().getAsAlign(), getInt64(Size));
384
}
385
386
using CGBuilderBaseTy::CreateMemMove;
387
llvm::CallInst *CreateMemMove(Address Dest, Address Src, llvm::Value *Size,
388
bool IsVolatile = false) {
389
llvm::Value *DestPtr = emitRawPointerFromAddress(Dest);
390
llvm::Value *SrcPtr = emitRawPointerFromAddress(Src);
391
return CreateMemMove(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr,
392
Src.getAlignment().getAsAlign(), Size, IsVolatile);
393
}
394
395
using CGBuilderBaseTy::CreateMemSet;
396
llvm::CallInst *CreateMemSet(Address Dest, llvm::Value *Value,
397
llvm::Value *Size, bool IsVolatile = false) {
398
return CreateMemSet(emitRawPointerFromAddress(Dest), Value, Size,
399
Dest.getAlignment().getAsAlign(), IsVolatile);
400
}
401
402
using CGBuilderBaseTy::CreateMemSetInline;
403
llvm::CallInst *CreateMemSetInline(Address Dest, llvm::Value *Value,
404
uint64_t Size) {
405
return CreateMemSetInline(emitRawPointerFromAddress(Dest),
406
Dest.getAlignment().getAsAlign(), Value,
407
getInt64(Size));
408
}
409
410
using CGBuilderBaseTy::CreatePreserveStructAccessIndex;
411
Address CreatePreserveStructAccessIndex(Address Addr, unsigned Index,
412
unsigned FieldIndex,
413
llvm::MDNode *DbgInfo) {
414
llvm::StructType *ElTy = cast<llvm::StructType>(Addr.getElementType());
415
const llvm::DataLayout &DL = BB->getDataLayout();
416
const llvm::StructLayout *Layout = DL.getStructLayout(ElTy);
417
auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index));
418
419
return Address(
420
CreatePreserveStructAccessIndex(ElTy, emitRawPointerFromAddress(Addr),
421
Index, FieldIndex, DbgInfo),
422
ElTy->getElementType(Index),
423
Addr.getAlignment().alignmentAtOffset(Offset));
424
}
425
426
using CGBuilderBaseTy::CreatePreserveUnionAccessIndex;
427
Address CreatePreserveUnionAccessIndex(Address Addr, unsigned FieldIndex,
428
llvm::MDNode *DbgInfo) {
429
Addr.replaceBasePointer(CreatePreserveUnionAccessIndex(
430
Addr.getBasePointer(), FieldIndex, DbgInfo));
431
return Addr;
432
}
433
434
using CGBuilderBaseTy::CreateLaunderInvariantGroup;
435
Address CreateLaunderInvariantGroup(Address Addr) {
436
Addr.replaceBasePointer(CreateLaunderInvariantGroup(Addr.getBasePointer()));
437
return Addr;
438
}
439
440
using CGBuilderBaseTy::CreateStripInvariantGroup;
441
Address CreateStripInvariantGroup(Address Addr) {
442
Addr.replaceBasePointer(CreateStripInvariantGroup(Addr.getBasePointer()));
443
return Addr;
444
}
445
};
446
447
} // end namespace CodeGen
448
} // end namespace clang
449
450
#endif
451
452