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 /// Cast the element type of the given address to a different type,
159 /// preserving information like the alignment and address space.
160 Address
CreateElementBitCast(Address Addr
, llvm::Type
*Ty
,
161 const llvm::Twine
&Name
= "") {
162 auto *PtrTy
= Ty
->getPointerTo(Addr
.getAddressSpace());
163 return Address(CreateBitCast(Addr
.getPointer(), PtrTy
, Name
), Ty
,
164 Addr
.getAlignment(), Addr
.isKnownNonNull());
167 using CGBuilderBaseTy::CreatePointerBitCastOrAddrSpaceCast
;
168 Address
CreatePointerBitCastOrAddrSpaceCast(Address Addr
, llvm::Type
*Ty
,
169 llvm::Type
*ElementTy
,
170 const llvm::Twine
&Name
= "") {
172 CreatePointerBitCastOrAddrSpaceCast(Addr
.getPointer(), Ty
, Name
);
173 return Address(Ptr
, ElementTy
, Addr
.getAlignment(), Addr
.isKnownNonNull());
177 /// %addr = {T1, T2...}* ...
179 /// %name = getelementptr inbounds %addr, i32 0, i32 index
181 /// This API assumes that drilling into a struct like this is always an
182 /// inbounds operation.
183 using CGBuilderBaseTy::CreateStructGEP
;
184 Address
CreateStructGEP(Address Addr
, unsigned Index
,
185 const llvm::Twine
&Name
= "") {
186 llvm::StructType
*ElTy
= cast
<llvm::StructType
>(Addr
.getElementType());
187 const llvm::DataLayout
&DL
= BB
->getParent()->getParent()->getDataLayout();
188 const llvm::StructLayout
*Layout
= DL
.getStructLayout(ElTy
);
189 auto Offset
= CharUnits::fromQuantity(Layout
->getElementOffset(Index
));
192 CreateStructGEP(Addr
.getElementType(), Addr
.getPointer(), Index
, Name
),
193 ElTy
->getElementType(Index
),
194 Addr
.getAlignment().alignmentAtOffset(Offset
), Addr
.isKnownNonNull());
198 /// %addr = [n x T]* ...
200 /// %name = getelementptr inbounds %addr, i64 0, i64 index
201 /// where i64 is actually the target word size.
203 /// This API assumes that drilling into an array like this is always
204 /// an inbounds operation.
205 Address
CreateConstArrayGEP(Address Addr
, uint64_t Index
,
206 const llvm::Twine
&Name
= "") {
207 llvm::ArrayType
*ElTy
= cast
<llvm::ArrayType
>(Addr
.getElementType());
208 const llvm::DataLayout
&DL
= BB
->getParent()->getParent()->getDataLayout();
210 CharUnits::fromQuantity(DL
.getTypeAllocSize(ElTy
->getElementType()));
213 CreateInBoundsGEP(Addr
.getElementType(), Addr
.getPointer(),
214 {getSize(CharUnits::Zero()), getSize(Index
)}, Name
),
215 ElTy
->getElementType(),
216 Addr
.getAlignment().alignmentAtOffset(Index
* EltSize
),
217 Addr
.isKnownNonNull());
223 /// %name = getelementptr inbounds %addr, i64 index
224 /// where i64 is actually the target word size.
225 Address
CreateConstInBoundsGEP(Address Addr
, uint64_t Index
,
226 const llvm::Twine
&Name
= "") {
227 llvm::Type
*ElTy
= Addr
.getElementType();
228 const llvm::DataLayout
&DL
= BB
->getParent()->getParent()->getDataLayout();
229 CharUnits EltSize
= CharUnits::fromQuantity(DL
.getTypeAllocSize(ElTy
));
231 return Address(CreateInBoundsGEP(Addr
.getElementType(), Addr
.getPointer(),
232 getSize(Index
), Name
),
233 ElTy
, Addr
.getAlignment().alignmentAtOffset(Index
* EltSize
),
234 Addr
.isKnownNonNull());
240 /// %name = getelementptr inbounds %addr, i64 index
241 /// where i64 is actually the target word size.
242 Address
CreateConstGEP(Address Addr
, uint64_t Index
,
243 const llvm::Twine
&Name
= "") {
244 const llvm::DataLayout
&DL
= BB
->getParent()->getParent()->getDataLayout();
246 CharUnits::fromQuantity(DL
.getTypeAllocSize(Addr
.getElementType()));
248 return Address(CreateGEP(Addr
.getElementType(), Addr
.getPointer(),
249 getSize(Index
), Name
),
250 Addr
.getElementType(),
251 Addr
.getAlignment().alignmentAtOffset(Index
* EltSize
),
255 /// Create GEP with single dynamic index. The address alignment is reduced
256 /// according to the element size.
257 using CGBuilderBaseTy::CreateGEP
;
258 Address
CreateGEP(Address Addr
, llvm::Value
*Index
,
259 const llvm::Twine
&Name
= "") {
260 const llvm::DataLayout
&DL
= BB
->getParent()->getParent()->getDataLayout();
262 CharUnits::fromQuantity(DL
.getTypeAllocSize(Addr
.getElementType()));
265 CreateGEP(Addr
.getElementType(), Addr
.getPointer(), Index
, Name
),
266 Addr
.getElementType(),
267 Addr
.getAlignment().alignmentOfArrayElement(EltSize
), NotKnownNonNull
);
270 /// Given a pointer to i8, adjust it by a given constant offset.
271 Address
CreateConstInBoundsByteGEP(Address Addr
, CharUnits Offset
,
272 const llvm::Twine
&Name
= "") {
273 assert(Addr
.getElementType() == TypeCache
.Int8Ty
);
274 return Address(CreateInBoundsGEP(Addr
.getElementType(), Addr
.getPointer(),
275 getSize(Offset
), Name
),
276 Addr
.getElementType(),
277 Addr
.getAlignment().alignmentAtOffset(Offset
),
278 Addr
.isKnownNonNull());
280 Address
CreateConstByteGEP(Address Addr
, CharUnits Offset
,
281 const llvm::Twine
&Name
= "") {
282 assert(Addr
.getElementType() == TypeCache
.Int8Ty
);
283 return Address(CreateGEP(Addr
.getElementType(), Addr
.getPointer(),
284 getSize(Offset
), Name
),
285 Addr
.getElementType(),
286 Addr
.getAlignment().alignmentAtOffset(Offset
),
290 using CGBuilderBaseTy::CreateConstInBoundsGEP2_32
;
291 Address
CreateConstInBoundsGEP2_32(Address Addr
, unsigned Idx0
, unsigned Idx1
,
292 const llvm::Twine
&Name
= "") {
293 const llvm::DataLayout
&DL
= BB
->getParent()->getParent()->getDataLayout();
295 auto *GEP
= cast
<llvm::GetElementPtrInst
>(CreateConstInBoundsGEP2_32(
296 Addr
.getElementType(), Addr
.getPointer(), Idx0
, Idx1
, Name
));
298 DL
.getIndexSizeInBits(Addr
.getType()->getPointerAddressSpace()), 0,
300 if (!GEP
->accumulateConstantOffset(DL
, Offset
))
301 llvm_unreachable("offset of GEP with constants is always computable");
302 return Address(GEP
, GEP
->getResultElementType(),
303 Addr
.getAlignment().alignmentAtOffset(
304 CharUnits::fromQuantity(Offset
.getSExtValue())),
305 Addr
.isKnownNonNull());
308 using CGBuilderBaseTy::CreateMemCpy
;
309 llvm::CallInst
*CreateMemCpy(Address Dest
, Address Src
, llvm::Value
*Size
,
310 bool IsVolatile
= false) {
311 return CreateMemCpy(Dest
.getPointer(), Dest
.getAlignment().getAsAlign(),
312 Src
.getPointer(), Src
.getAlignment().getAsAlign(), Size
,
315 llvm::CallInst
*CreateMemCpy(Address Dest
, Address Src
, uint64_t Size
,
316 bool IsVolatile
= false) {
317 return CreateMemCpy(Dest
.getPointer(), Dest
.getAlignment().getAsAlign(),
318 Src
.getPointer(), Src
.getAlignment().getAsAlign(), Size
,
322 using CGBuilderBaseTy::CreateMemCpyInline
;
323 llvm::CallInst
*CreateMemCpyInline(Address Dest
, Address Src
, uint64_t Size
) {
324 return CreateMemCpyInline(
325 Dest
.getPointer(), Dest
.getAlignment().getAsAlign(), Src
.getPointer(),
326 Src
.getAlignment().getAsAlign(), getInt64(Size
));
329 using CGBuilderBaseTy::CreateMemMove
;
330 llvm::CallInst
*CreateMemMove(Address Dest
, Address Src
, llvm::Value
*Size
,
331 bool IsVolatile
= false) {
332 return CreateMemMove(Dest
.getPointer(), Dest
.getAlignment().getAsAlign(),
333 Src
.getPointer(), Src
.getAlignment().getAsAlign(),
337 using CGBuilderBaseTy::CreateMemSet
;
338 llvm::CallInst
*CreateMemSet(Address Dest
, llvm::Value
*Value
,
339 llvm::Value
*Size
, bool IsVolatile
= false) {
340 return CreateMemSet(Dest
.getPointer(), Value
, Size
,
341 Dest
.getAlignment().getAsAlign(), IsVolatile
);
344 using CGBuilderBaseTy::CreateMemSetInline
;
345 llvm::CallInst
*CreateMemSetInline(Address Dest
, llvm::Value
*Value
,
347 return CreateMemSetInline(Dest
.getPointer(),
348 Dest
.getAlignment().getAsAlign(), Value
,
352 using CGBuilderBaseTy::CreatePreserveStructAccessIndex
;
353 Address
CreatePreserveStructAccessIndex(Address Addr
, unsigned Index
,
355 llvm::MDNode
*DbgInfo
) {
356 llvm::StructType
*ElTy
= cast
<llvm::StructType
>(Addr
.getElementType());
357 const llvm::DataLayout
&DL
= BB
->getParent()->getParent()->getDataLayout();
358 const llvm::StructLayout
*Layout
= DL
.getStructLayout(ElTy
);
359 auto Offset
= CharUnits::fromQuantity(Layout
->getElementOffset(Index
));
361 return Address(CreatePreserveStructAccessIndex(ElTy
, Addr
.getPointer(),
362 Index
, FieldIndex
, DbgInfo
),
363 ElTy
->getElementType(Index
),
364 Addr
.getAlignment().alignmentAtOffset(Offset
));
367 using CGBuilderBaseTy::CreateLaunderInvariantGroup
;
368 Address
CreateLaunderInvariantGroup(Address Addr
) {
369 return Addr
.withPointer(CreateLaunderInvariantGroup(Addr
.getPointer()),
370 Addr
.isKnownNonNull());
374 } // end namespace CodeGen
375 } // end namespace clang