1 //===-- CGBuilder.h - Choose IRBuilder implementation ----------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H
10 #define LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H
13 #include "CodeGenTypeCache.h"
14 #include "llvm/IR/DataLayout.h"
15 #include "llvm/IR/IRBuilder.h"
16 #include "llvm/IR/Type.h"
21 class CodeGenFunction
;
23 /// This is an IRBuilder insertion helper that forwards to
24 /// CodeGenFunction::InsertHelper, which adds necessary metadata to
26 class CGBuilderInserter final
: public llvm::IRBuilderDefaultInserter
{
28 CGBuilderInserter() = default;
29 explicit CGBuilderInserter(CodeGenFunction
*CGF
) : CGF(CGF
) {}
31 /// This forwards to CodeGenFunction::InsertHelper.
32 void InsertHelper(llvm::Instruction
*I
, const llvm::Twine
&Name
,
34 llvm::BasicBlock::iterator InsertPt
) const override
;
37 CodeGenFunction
*CGF
= nullptr;
40 typedef CGBuilderInserter CGBuilderInserterTy
;
42 typedef llvm::IRBuilder
<llvm::ConstantFolder
, CGBuilderInserterTy
>
45 class 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
;
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
) {}
62 llvm::ConstantInt
*getSize(CharUnits N
) {
63 return llvm::ConstantInt::get(TypeCache
.SizeTy
, N
.getQuantity());
65 llvm::ConstantInt
*getSize(uint64_t N
) {
66 return llvm::ConstantInt::get(TypeCache
.SizeTy
, N
);
69 // Note that we intentionally hide the CreateLoad APIs that don't
71 llvm::LoadInst
*CreateLoad(Address Addr
, const llvm::Twine
&Name
= "") {
72 return CreateAlignedLoad(Addr
.getElementType(), Addr
.getPointer(),
73 Addr
.getAlignment().getAsAlign(), Name
);
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(Addr
.getElementType(), Addr
.getPointer(),
79 Addr
.getAlignment().getAsAlign(), Name
);
81 llvm::LoadInst
*CreateLoad(Address Addr
, bool IsVolatile
,
82 const llvm::Twine
&Name
= "") {
83 return CreateAlignedLoad(Addr
.getElementType(), Addr
.getPointer(),
84 Addr
.getAlignment().getAsAlign(), IsVolatile
,
88 using CGBuilderBaseTy::CreateAlignedLoad
;
89 llvm::LoadInst
*CreateAlignedLoad(llvm::Type
*Ty
, llvm::Value
*Addr
,
91 const llvm::Twine
&Name
= "") {
92 return CreateAlignedLoad(Ty
, Addr
, Align
.getAsAlign(), Name
);
95 // Note that we intentionally hide the CreateStore APIs that don't
97 llvm::StoreInst
*CreateStore(llvm::Value
*Val
, Address Addr
,
98 bool IsVolatile
= false) {
99 return CreateAlignedStore(Val
, Addr
.getPointer(),
100 Addr
.getAlignment().getAsAlign(), IsVolatile
);
103 using CGBuilderBaseTy::CreateAlignedStore
;
104 llvm::StoreInst
*CreateAlignedStore(llvm::Value
*Val
, llvm::Value
*Addr
,
106 bool IsVolatile
= false) {
107 return CreateAlignedStore(Val
, Addr
, Align
.getAsAlign(), IsVolatile
);
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
,
114 bool IsVolatile
= false) {
115 return CGBuilderBaseTy::CreateStore(Val
, Addr
, IsVolatile
);
118 /// Emit a load from an i1 flag variable.
119 llvm::LoadInst
*CreateFlagLoad(llvm::Value
*Addr
,
120 const llvm::Twine
&Name
= "") {
121 return CreateAlignedLoad(getInt1Ty(), Addr
, CharUnits::One(), Name
);
124 /// Emit a store to an i1 flag variable.
125 llvm::StoreInst
*CreateFlagStore(bool Value
, llvm::Value
*Addr
) {
126 return CreateAlignedStore(getInt1(Value
), Addr
, CharUnits::One());
129 // Temporarily use old signature; clang will be updated to an Address overload
130 // in a subsequent patch.
131 llvm::AtomicCmpXchgInst
*
132 CreateAtomicCmpXchg(llvm::Value
*Ptr
, llvm::Value
*Cmp
, llvm::Value
*New
,
133 llvm::AtomicOrdering SuccessOrdering
,
134 llvm::AtomicOrdering FailureOrdering
,
135 llvm::SyncScope::ID SSID
= llvm::SyncScope::System
) {
136 return CGBuilderBaseTy::CreateAtomicCmpXchg(
137 Ptr
, Cmp
, New
, llvm::MaybeAlign(), SuccessOrdering
, FailureOrdering
,
141 // Temporarily use old signature; clang will be updated to an Address overload
142 // in a subsequent patch.
143 llvm::AtomicRMWInst
*
144 CreateAtomicRMW(llvm::AtomicRMWInst::BinOp Op
, llvm::Value
*Ptr
,
145 llvm::Value
*Val
, llvm::AtomicOrdering Ordering
,
146 llvm::SyncScope::ID SSID
= llvm::SyncScope::System
) {
147 return CGBuilderBaseTy::CreateAtomicRMW(Op
, Ptr
, Val
, llvm::MaybeAlign(),
151 using CGBuilderBaseTy::CreateAddrSpaceCast
;
152 Address
CreateAddrSpaceCast(Address Addr
, llvm::Type
*Ty
,
153 const llvm::Twine
&Name
= "") {
154 return Addr
.withPointer(CreateAddrSpaceCast(Addr
.getPointer(), Ty
, Name
),
155 Addr
.isKnownNonNull());
158 using CGBuilderBaseTy::CreatePointerBitCastOrAddrSpaceCast
;
159 Address
CreatePointerBitCastOrAddrSpaceCast(Address Addr
, llvm::Type
*Ty
,
160 llvm::Type
*ElementTy
,
161 const llvm::Twine
&Name
= "") {
163 CreatePointerBitCastOrAddrSpaceCast(Addr
.getPointer(), Ty
, Name
);
164 return Address(Ptr
, ElementTy
, Addr
.getAlignment(), Addr
.isKnownNonNull());
168 /// %addr = {T1, T2...}* ...
170 /// %name = getelementptr inbounds %addr, i32 0, i32 index
172 /// This API assumes that drilling into a struct like this is always an
173 /// inbounds operation.
174 using CGBuilderBaseTy::CreateStructGEP
;
175 Address
CreateStructGEP(Address Addr
, unsigned Index
,
176 const llvm::Twine
&Name
= "") {
177 llvm::StructType
*ElTy
= cast
<llvm::StructType
>(Addr
.getElementType());
178 const llvm::DataLayout
&DL
= BB
->getParent()->getParent()->getDataLayout();
179 const llvm::StructLayout
*Layout
= DL
.getStructLayout(ElTy
);
180 auto Offset
= CharUnits::fromQuantity(Layout
->getElementOffset(Index
));
183 CreateStructGEP(Addr
.getElementType(), Addr
.getPointer(), Index
, Name
),
184 ElTy
->getElementType(Index
),
185 Addr
.getAlignment().alignmentAtOffset(Offset
), Addr
.isKnownNonNull());
189 /// %addr = [n x T]* ...
191 /// %name = getelementptr inbounds %addr, i64 0, i64 index
192 /// where i64 is actually the target word size.
194 /// This API assumes that drilling into an array like this is always
195 /// an inbounds operation.
196 Address
CreateConstArrayGEP(Address Addr
, uint64_t Index
,
197 const llvm::Twine
&Name
= "") {
198 llvm::ArrayType
*ElTy
= cast
<llvm::ArrayType
>(Addr
.getElementType());
199 const llvm::DataLayout
&DL
= BB
->getParent()->getParent()->getDataLayout();
201 CharUnits::fromQuantity(DL
.getTypeAllocSize(ElTy
->getElementType()));
204 CreateInBoundsGEP(Addr
.getElementType(), Addr
.getPointer(),
205 {getSize(CharUnits::Zero()), getSize(Index
)}, Name
),
206 ElTy
->getElementType(),
207 Addr
.getAlignment().alignmentAtOffset(Index
* EltSize
),
208 Addr
.isKnownNonNull());
214 /// %name = getelementptr inbounds %addr, i64 index
215 /// where i64 is actually the target word size.
216 Address
CreateConstInBoundsGEP(Address Addr
, uint64_t Index
,
217 const llvm::Twine
&Name
= "") {
218 llvm::Type
*ElTy
= Addr
.getElementType();
219 const llvm::DataLayout
&DL
= BB
->getParent()->getParent()->getDataLayout();
220 CharUnits EltSize
= CharUnits::fromQuantity(DL
.getTypeAllocSize(ElTy
));
222 return Address(CreateInBoundsGEP(Addr
.getElementType(), Addr
.getPointer(),
223 getSize(Index
), Name
),
224 ElTy
, Addr
.getAlignment().alignmentAtOffset(Index
* EltSize
),
225 Addr
.isKnownNonNull());
231 /// %name = getelementptr inbounds %addr, i64 index
232 /// where i64 is actually the target word size.
233 Address
CreateConstGEP(Address Addr
, uint64_t Index
,
234 const llvm::Twine
&Name
= "") {
235 const llvm::DataLayout
&DL
= BB
->getParent()->getParent()->getDataLayout();
237 CharUnits::fromQuantity(DL
.getTypeAllocSize(Addr
.getElementType()));
239 return Address(CreateGEP(Addr
.getElementType(), Addr
.getPointer(),
240 getSize(Index
), Name
),
241 Addr
.getElementType(),
242 Addr
.getAlignment().alignmentAtOffset(Index
* EltSize
),
246 /// Create GEP with single dynamic index. The address alignment is reduced
247 /// according to the element size.
248 using CGBuilderBaseTy::CreateGEP
;
249 Address
CreateGEP(Address Addr
, llvm::Value
*Index
,
250 const llvm::Twine
&Name
= "") {
251 const llvm::DataLayout
&DL
= BB
->getParent()->getParent()->getDataLayout();
253 CharUnits::fromQuantity(DL
.getTypeAllocSize(Addr
.getElementType()));
256 CreateGEP(Addr
.getElementType(), Addr
.getPointer(), Index
, Name
),
257 Addr
.getElementType(),
258 Addr
.getAlignment().alignmentOfArrayElement(EltSize
), NotKnownNonNull
);
261 /// Given a pointer to i8, adjust it by a given constant offset.
262 Address
CreateConstInBoundsByteGEP(Address Addr
, CharUnits Offset
,
263 const llvm::Twine
&Name
= "") {
264 assert(Addr
.getElementType() == TypeCache
.Int8Ty
);
265 return Address(CreateInBoundsGEP(Addr
.getElementType(), Addr
.getPointer(),
266 getSize(Offset
), Name
),
267 Addr
.getElementType(),
268 Addr
.getAlignment().alignmentAtOffset(Offset
),
269 Addr
.isKnownNonNull());
271 Address
CreateConstByteGEP(Address Addr
, CharUnits Offset
,
272 const llvm::Twine
&Name
= "") {
273 assert(Addr
.getElementType() == TypeCache
.Int8Ty
);
274 return Address(CreateGEP(Addr
.getElementType(), Addr
.getPointer(),
275 getSize(Offset
), Name
),
276 Addr
.getElementType(),
277 Addr
.getAlignment().alignmentAtOffset(Offset
),
281 using CGBuilderBaseTy::CreateConstInBoundsGEP2_32
;
282 Address
CreateConstInBoundsGEP2_32(Address Addr
, unsigned Idx0
, unsigned Idx1
,
283 const llvm::Twine
&Name
= "") {
284 const llvm::DataLayout
&DL
= BB
->getParent()->getParent()->getDataLayout();
286 auto *GEP
= cast
<llvm::GetElementPtrInst
>(CreateConstInBoundsGEP2_32(
287 Addr
.getElementType(), Addr
.getPointer(), Idx0
, Idx1
, Name
));
289 DL
.getIndexSizeInBits(Addr
.getType()->getPointerAddressSpace()), 0,
291 if (!GEP
->accumulateConstantOffset(DL
, Offset
))
292 llvm_unreachable("offset of GEP with constants is always computable");
293 return Address(GEP
, GEP
->getResultElementType(),
294 Addr
.getAlignment().alignmentAtOffset(
295 CharUnits::fromQuantity(Offset
.getSExtValue())),
296 Addr
.isKnownNonNull());
299 using CGBuilderBaseTy::CreateMemCpy
;
300 llvm::CallInst
*CreateMemCpy(Address Dest
, Address Src
, llvm::Value
*Size
,
301 bool IsVolatile
= false) {
302 return CreateMemCpy(Dest
.getPointer(), Dest
.getAlignment().getAsAlign(),
303 Src
.getPointer(), Src
.getAlignment().getAsAlign(), Size
,
306 llvm::CallInst
*CreateMemCpy(Address Dest
, Address Src
, uint64_t Size
,
307 bool IsVolatile
= false) {
308 return CreateMemCpy(Dest
.getPointer(), Dest
.getAlignment().getAsAlign(),
309 Src
.getPointer(), Src
.getAlignment().getAsAlign(), Size
,
313 using CGBuilderBaseTy::CreateMemCpyInline
;
314 llvm::CallInst
*CreateMemCpyInline(Address Dest
, Address Src
, uint64_t Size
) {
315 return CreateMemCpyInline(
316 Dest
.getPointer(), Dest
.getAlignment().getAsAlign(), Src
.getPointer(),
317 Src
.getAlignment().getAsAlign(), getInt64(Size
));
320 using CGBuilderBaseTy::CreateMemMove
;
321 llvm::CallInst
*CreateMemMove(Address Dest
, Address Src
, llvm::Value
*Size
,
322 bool IsVolatile
= false) {
323 return CreateMemMove(Dest
.getPointer(), Dest
.getAlignment().getAsAlign(),
324 Src
.getPointer(), Src
.getAlignment().getAsAlign(),
328 using CGBuilderBaseTy::CreateMemSet
;
329 llvm::CallInst
*CreateMemSet(Address Dest
, llvm::Value
*Value
,
330 llvm::Value
*Size
, bool IsVolatile
= false) {
331 return CreateMemSet(Dest
.getPointer(), Value
, Size
,
332 Dest
.getAlignment().getAsAlign(), IsVolatile
);
335 using CGBuilderBaseTy::CreateMemSetInline
;
336 llvm::CallInst
*CreateMemSetInline(Address Dest
, llvm::Value
*Value
,
338 return CreateMemSetInline(Dest
.getPointer(),
339 Dest
.getAlignment().getAsAlign(), Value
,
343 using CGBuilderBaseTy::CreatePreserveStructAccessIndex
;
344 Address
CreatePreserveStructAccessIndex(Address Addr
, unsigned Index
,
346 llvm::MDNode
*DbgInfo
) {
347 llvm::StructType
*ElTy
= cast
<llvm::StructType
>(Addr
.getElementType());
348 const llvm::DataLayout
&DL
= BB
->getParent()->getParent()->getDataLayout();
349 const llvm::StructLayout
*Layout
= DL
.getStructLayout(ElTy
);
350 auto Offset
= CharUnits::fromQuantity(Layout
->getElementOffset(Index
));
352 return Address(CreatePreserveStructAccessIndex(ElTy
, Addr
.getPointer(),
353 Index
, FieldIndex
, DbgInfo
),
354 ElTy
->getElementType(Index
),
355 Addr
.getAlignment().alignmentAtOffset(Offset
));
358 using CGBuilderBaseTy::CreateLaunderInvariantGroup
;
359 Address
CreateLaunderInvariantGroup(Address Addr
) {
360 return Addr
.withPointer(CreateLaunderInvariantGroup(Addr
.getPointer()),
361 Addr
.isKnownNonNull());
365 } // end namespace CodeGen
366 } // end namespace clang