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