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