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

source code of clang/lib/CodeGen/CGBuilder.h