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

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