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 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 Addr
.getPointer(), Cmp
, New
, Addr
.getAlignment().getAsAlign(),
136 SuccessOrdering
, FailureOrdering
, SSID
);
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
, Addr
.getPointer(), Val
,
144 Addr
.getAlignment().getAsAlign(),
148 using CGBuilderBaseTy::CreateAddrSpaceCast
;
149 Address
CreateAddrSpaceCast(Address Addr
, llvm::Type
*Ty
,
150 const llvm::Twine
&Name
= "") {
151 return Addr
.withPointer(CreateAddrSpaceCast(Addr
.getPointer(), Ty
, Name
),
152 Addr
.isKnownNonNull());
155 using CGBuilderBaseTy::CreatePointerBitCastOrAddrSpaceCast
;
156 Address
CreatePointerBitCastOrAddrSpaceCast(Address Addr
, llvm::Type
*Ty
,
157 llvm::Type
*ElementTy
,
158 const llvm::Twine
&Name
= "") {
160 CreatePointerBitCastOrAddrSpaceCast(Addr
.getPointer(), Ty
, Name
);
161 return Address(Ptr
, ElementTy
, Addr
.getAlignment(), Addr
.isKnownNonNull());
165 /// %addr = {T1, T2...}* ...
167 /// %name = getelementptr inbounds %addr, i32 0, i32 index
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
>(Addr
.getElementType());
175 const llvm::DataLayout
&DL
= BB
->getParent()->getParent()->getDataLayout();
176 const llvm::StructLayout
*Layout
= DL
.getStructLayout(ElTy
);
177 auto Offset
= CharUnits::fromQuantity(Layout
->getElementOffset(Index
));
180 CreateStructGEP(Addr
.getElementType(), Addr
.getPointer(), Index
, Name
),
181 ElTy
->getElementType(Index
),
182 Addr
.getAlignment().alignmentAtOffset(Offset
), Addr
.isKnownNonNull());
186 /// %addr = [n x T]* ...
188 /// %name = getelementptr inbounds %addr, i64 0, i64 index
189 /// where i64 is actually the target word size.
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
>(Addr
.getElementType());
196 const llvm::DataLayout
&DL
= BB
->getParent()->getParent()->getDataLayout();
198 CharUnits::fromQuantity(DL
.getTypeAllocSize(ElTy
->getElementType()));
201 CreateInBoundsGEP(Addr
.getElementType(), Addr
.getPointer(),
202 {getSize(CharUnits::Zero()), getSize(Index
)}, Name
),
203 ElTy
->getElementType(),
204 Addr
.getAlignment().alignmentAtOffset(Index
* EltSize
),
205 Addr
.isKnownNonNull());
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(DL
.getTypeAllocSize(ElTy
));
219 return Address(CreateInBoundsGEP(Addr
.getElementType(), Addr
.getPointer(),
220 getSize(Index
), Name
),
221 ElTy
, Addr
.getAlignment().alignmentAtOffset(Index
* EltSize
),
222 Addr
.isKnownNonNull());
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();
234 CharUnits::fromQuantity(DL
.getTypeAllocSize(Addr
.getElementType()));
236 return Address(CreateGEP(Addr
.getElementType(), Addr
.getPointer(),
237 getSize(Index
), Name
),
238 Addr
.getElementType(),
239 Addr
.getAlignment().alignmentAtOffset(Index
* EltSize
),
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();
250 CharUnits::fromQuantity(DL
.getTypeAllocSize(Addr
.getElementType()));
253 CreateGEP(Addr
.getElementType(), Addr
.getPointer(), Index
, Name
),
254 Addr
.getElementType(),
255 Addr
.getAlignment().alignmentOfArrayElement(EltSize
), NotKnownNonNull
);
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(Addr
.getElementType(), Addr
.getPointer(),
263 getSize(Offset
), Name
),
264 Addr
.getElementType(),
265 Addr
.getAlignment().alignmentAtOffset(Offset
),
266 Addr
.isKnownNonNull());
268 Address
CreateConstByteGEP(Address Addr
, CharUnits Offset
,
269 const llvm::Twine
&Name
= "") {
270 assert(Addr
.getElementType() == TypeCache
.Int8Ty
);
271 return Address(CreateGEP(Addr
.getElementType(), Addr
.getPointer(),
272 getSize(Offset
), Name
),
273 Addr
.getElementType(),
274 Addr
.getAlignment().alignmentAtOffset(Offset
),
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();
283 auto *GEP
= cast
<llvm::GetElementPtrInst
>(CreateConstInBoundsGEP2_32(
284 Addr
.getElementType(), Addr
.getPointer(), Idx0
, Idx1
, Name
));
286 DL
.getIndexSizeInBits(Addr
.getType()->getPointerAddressSpace()), 0,
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 CharUnits::fromQuantity(Offset
.getSExtValue())),
293 Addr
.isKnownNonNull());
296 using CGBuilderBaseTy::CreateMemCpy
;
297 llvm::CallInst
*CreateMemCpy(Address Dest
, Address Src
, llvm::Value
*Size
,
298 bool IsVolatile
= false) {
299 return CreateMemCpy(Dest
.getPointer(), Dest
.getAlignment().getAsAlign(),
300 Src
.getPointer(), Src
.getAlignment().getAsAlign(), Size
,
303 llvm::CallInst
*CreateMemCpy(Address Dest
, Address Src
, uint64_t Size
,
304 bool IsVolatile
= false) {
305 return CreateMemCpy(Dest
.getPointer(), Dest
.getAlignment().getAsAlign(),
306 Src
.getPointer(), Src
.getAlignment().getAsAlign(), Size
,
310 using CGBuilderBaseTy::CreateMemCpyInline
;
311 llvm::CallInst
*CreateMemCpyInline(Address Dest
, Address Src
, uint64_t Size
) {
312 return CreateMemCpyInline(
313 Dest
.getPointer(), Dest
.getAlignment().getAsAlign(), Src
.getPointer(),
314 Src
.getAlignment().getAsAlign(), getInt64(Size
));
317 using CGBuilderBaseTy::CreateMemMove
;
318 llvm::CallInst
*CreateMemMove(Address Dest
, Address Src
, llvm::Value
*Size
,
319 bool IsVolatile
= false) {
320 return CreateMemMove(Dest
.getPointer(), Dest
.getAlignment().getAsAlign(),
321 Src
.getPointer(), Src
.getAlignment().getAsAlign(),
325 using CGBuilderBaseTy::CreateMemSet
;
326 llvm::CallInst
*CreateMemSet(Address Dest
, llvm::Value
*Value
,
327 llvm::Value
*Size
, bool IsVolatile
= false) {
328 return CreateMemSet(Dest
.getPointer(), Value
, Size
,
329 Dest
.getAlignment().getAsAlign(), IsVolatile
);
332 using CGBuilderBaseTy::CreateMemSetInline
;
333 llvm::CallInst
*CreateMemSetInline(Address Dest
, llvm::Value
*Value
,
335 return CreateMemSetInline(Dest
.getPointer(),
336 Dest
.getAlignment().getAsAlign(), Value
,
340 using CGBuilderBaseTy::CreatePreserveStructAccessIndex
;
341 Address
CreatePreserveStructAccessIndex(Address Addr
, unsigned Index
,
343 llvm::MDNode
*DbgInfo
) {
344 llvm::StructType
*ElTy
= cast
<llvm::StructType
>(Addr
.getElementType());
345 const llvm::DataLayout
&DL
= BB
->getParent()->getParent()->getDataLayout();
346 const llvm::StructLayout
*Layout
= DL
.getStructLayout(ElTy
);
347 auto Offset
= CharUnits::fromQuantity(Layout
->getElementOffset(Index
));
349 return Address(CreatePreserveStructAccessIndex(ElTy
, Addr
.getPointer(),
350 Index
, FieldIndex
, DbgInfo
),
351 ElTy
->getElementType(Index
),
352 Addr
.getAlignment().alignmentAtOffset(Offset
));
355 using CGBuilderBaseTy::CreateLaunderInvariantGroup
;
356 Address
CreateLaunderInvariantGroup(Address Addr
) {
357 return Addr
.withPointer(CreateLaunderInvariantGroup(Addr
.getPointer()),
358 Addr
.isKnownNonNull());
362 } // end namespace CodeGen
363 } // end namespace clang