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
20namespace clang {
21namespace CodeGen {
22
23class CGBuilderTy;
24class CodeGenFunction;
25
26/// This is an IRBuilder insertion helper that forwards to
27/// CodeGenFunction::InsertHelper, which adds necessary metadata to
28/// instructions.
29class CGBuilderInserter final : public llvm::IRBuilderDefaultInserter {
30 friend CGBuilderTy;
31
32public:
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
40private:
41 CodeGenFunction *CGF = nullptr;
42};
43
44typedef CGBuilderInserter CGBuilderInserterTy;
45
46typedef llvm::IRBuilder<llvm::ConstantFolder, CGBuilderInserterTy>
47 CGBuilderBaseTy;
48
49class 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>(Val: CreateConstInBoundsGEP2_32(
69 Ty: Addr.getElementType(), Ptr: emitRawPointerFromAddress(Addr), Idx0, Idx1,
70 Name));
71 else
72 GEP = cast<llvm::GetElementPtrInst>(Val: CreateConstGEP2_32(
73 Ty: Addr.getElementType(), Ptr: emitRawPointerFromAddress(Addr), Idx0, Idx1,
74 Name));
75 llvm::APInt Offset(
76 DL.getIndexSizeInBits(AS: 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 offset: CharUnits::fromQuantity(Quantity: Offset.getSExtValue())),
83 IsInBounds ? Addr.isKnownNonNull() : NotKnownNonNull);
84 }
85
86public:
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(Ty: TypeCache.SizeTy, V: N.getQuantity());
100 }
101 llvm::ConstantInt *getSize(uint64_t N) {
102 return llvm::ConstantInt::get(Ty: TypeCache.SizeTy, V: 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(Ty: Addr.getElementType(),
109 Ptr: emitRawPointerFromAddress(Addr),
110 Align: 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(Ty: Addr.getElementType(),
116 Ptr: emitRawPointerFromAddress(Addr),
117 Align: Addr.getAlignment().getAsAlign(), Name);
118 }
119 llvm::LoadInst *CreateLoad(Address Addr, bool IsVolatile,
120 const llvm::Twine &Name = "") {
121 return CreateAlignedLoad(
122 Ty: Addr.getElementType(), Ptr: emitRawPointerFromAddress(Addr),
123 Align: Addr.getAlignment().getAsAlign(), isVolatile: 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, Ptr: Addr, Align: 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, Ptr: emitRawPointerFromAddress(Addr),
138 Align: Addr.getAlignment().getAsAlign(), isVolatile: 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, Ptr: Addr, Align: Align.getAsAlign(), isVolatile: 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, Ptr: Addr, isVolatile: 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(Ty: getInt1Ty(), Addr, Align: 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(Val: getInt1(V: Value), Addr, Align: 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 Ptr: Addr.emitRawPointer(CGF&: *getCGF()), Cmp, New,
174 Align: 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, Ptr: Addr.emitRawPointer(CGF&: *getCGF()), Val,
184 Align: 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(V: Addr.getBasePointer(), DestTy: 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(V: Addr.emitRawPointer(CGF&: *getCGF()), DestTy: 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(ElemTy: 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>(Val: Addr.getElementType());
221 const llvm::DataLayout &DL = BB->getDataLayout();
222 const llvm::StructLayout *Layout = DL.getStructLayout(Ty: ElTy);
223 auto Offset = CharUnits::fromQuantity(Quantity: Layout->getElementOffset(Idx: Index));
224
225 return Address(CreateStructGEP(Ty: Addr.getElementType(), Ptr: Addr.getBasePointer(),
226 Idx: Index, Name),
227 ElTy->getElementType(N: Index),
228 Addr.getAlignment().alignmentAtOffset(offset: 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>(Val: Addr.getElementType());
243 const llvm::DataLayout &DL = BB->getDataLayout();
244 CharUnits EltSize =
245 CharUnits::fromQuantity(Quantity: DL.getTypeAllocSize(Ty: ElTy->getElementType()));
246
247 return Address(
248 CreateInBoundsGEP(Ty: Addr.getElementType(), Ptr: Addr.getBasePointer(),
249 IdxList: {getSize(N: CharUnits::Zero()), getSize(N: Index)}, Name),
250 ElTy->getElementType(),
251 Addr.getAlignment().alignmentAtOffset(offset: 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(Quantity: DL.getTypeAllocSize(Ty: ElTy));
265
266 return Address(
267 CreateInBoundsGEP(Ty: ElTy, Ptr: Addr.getBasePointer(), IdxList: getSize(N: Index), Name),
268 ElTy, Addr.getAlignment().alignmentAtOffset(offset: 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(Quantity: DL.getTypeAllocSize(Ty: ElTy));
282
283 return Address(CreateGEP(Ty: ElTy, Ptr: Addr.getBasePointer(), IdxList: getSize(N: Index), Name),
284 Addr.getElementType(),
285 Addr.getAlignment().alignmentAtOffset(offset: 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(Quantity: DL.getTypeAllocSize(Ty: Addr.getElementType()));
296
297 return Address(
298 CreateGEP(Ty: Addr.getElementType(), Ptr: Addr.emitRawPointer(CGF), IdxList: Index, Name),
299 Addr.getElementType(),
300 Addr.getAlignment().alignmentOfArrayElement(elementSize: 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(Ty: Addr.getElementType(), Ptr: Addr.getBasePointer(),
309 IdxList: getSize(N: Offset), Name),
310 Addr.getElementType(), Addr.getAlignment().alignmentAtOffset(offset: 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(Ty: Addr.getElementType(), Ptr: Addr.getBasePointer(),
318 IdxList: getSize(N: Offset), Name),
319 Addr.getElementType(),
320 Addr.getAlignment().alignmentAtOffset(offset: 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(Ty: 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(Ty: Addr.getElementType(),
348 Ptr: 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(Arg: 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(Addr: Dest);
366 llvm::Value *SrcPtr = emitRawPointerFromAddress(Addr: Src);
367 return CreateMemCpy(Dst: DestPtr, DstAlign: Dest.getAlignment().getAsAlign(), Src: SrcPtr,
368 SrcAlign: Src.getAlignment().getAsAlign(), Size, isVolatile: IsVolatile);
369 }
370 llvm::CallInst *CreateMemCpy(Address Dest, Address Src, uint64_t Size,
371 bool IsVolatile = false) {
372 llvm::Value *DestPtr = emitRawPointerFromAddress(Addr: Dest);
373 llvm::Value *SrcPtr = emitRawPointerFromAddress(Addr: Src);
374 return CreateMemCpy(Dst: DestPtr, DstAlign: Dest.getAlignment().getAsAlign(), Src: SrcPtr,
375 SrcAlign: Src.getAlignment().getAsAlign(), Size, isVolatile: IsVolatile);
376 }
377
378 using CGBuilderBaseTy::CreateMemCpyInline;
379 llvm::CallInst *CreateMemCpyInline(Address Dest, Address Src, uint64_t Size) {
380 llvm::Value *DestPtr = emitRawPointerFromAddress(Addr: Dest);
381 llvm::Value *SrcPtr = emitRawPointerFromAddress(Addr: Src);
382 return CreateMemCpyInline(Dst: DestPtr, DstAlign: Dest.getAlignment().getAsAlign(), Src: SrcPtr,
383 SrcAlign: Src.getAlignment().getAsAlign(), Size: getInt64(C: 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(Addr: Dest);
390 llvm::Value *SrcPtr = emitRawPointerFromAddress(Addr: Src);
391 return CreateMemMove(Dst: DestPtr, DstAlign: Dest.getAlignment().getAsAlign(), Src: SrcPtr,
392 SrcAlign: Src.getAlignment().getAsAlign(), Size, isVolatile: 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(Ptr: emitRawPointerFromAddress(Addr: Dest), Val: Value, Size,
399 Align: Dest.getAlignment().getAsAlign(), isVolatile: IsVolatile);
400 }
401
402 using CGBuilderBaseTy::CreateMemSetInline;
403 llvm::CallInst *CreateMemSetInline(Address Dest, llvm::Value *Value,
404 uint64_t Size) {
405 return CreateMemSetInline(Dst: emitRawPointerFromAddress(Addr: Dest),
406 DstAlign: Dest.getAlignment().getAsAlign(), Val: Value,
407 Size: getInt64(C: 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>(Val: Addr.getElementType());
415 const llvm::DataLayout &DL = BB->getDataLayout();
416 const llvm::StructLayout *Layout = DL.getStructLayout(Ty: ElTy);
417 auto Offset = CharUnits::fromQuantity(Quantity: Layout->getElementOffset(Idx: Index));
418
419 return Address(
420 CreatePreserveStructAccessIndex(ElTy, Base: emitRawPointerFromAddress(Addr),
421 Index, FieldIndex, DbgInfo),
422 ElTy->getElementType(N: Index),
423 Addr.getAlignment().alignmentAtOffset(offset: Offset));
424 }
425
426 using CGBuilderBaseTy::CreatePreserveUnionAccessIndex;
427 Address CreatePreserveUnionAccessIndex(Address Addr, unsigned FieldIndex,
428 llvm::MDNode *DbgInfo) {
429 Addr.replaceBasePointer(P: CreatePreserveUnionAccessIndex(
430 Base: Addr.getBasePointer(), FieldIndex, DbgInfo));
431 return Addr;
432 }
433
434 using CGBuilderBaseTy::CreateLaunderInvariantGroup;
435 Address CreateLaunderInvariantGroup(Address Addr) {
436 Addr.replaceBasePointer(P: CreateLaunderInvariantGroup(Ptr: Addr.getBasePointer()));
437 return Addr;
438 }
439
440 using CGBuilderBaseTy::CreateStripInvariantGroup;
441 Address CreateStripInvariantGroup(Address Addr) {
442 Addr.replaceBasePointer(P: CreateStripInvariantGroup(Ptr: Addr.getBasePointer()));
443 return Addr;
444 }
445};
446
447} // end namespace CodeGen
448} // end namespace clang
449
450#endif
451