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 assert(llvm::cast
<llvm::PointerType
>(Addr
->getType())
93 ->isOpaqueOrPointeeTypeMatches(Ty
));
94 return CreateAlignedLoad(Ty
, Addr
, Align
.getAsAlign(), Name
);
97 // Note that we intentionally hide the CreateStore APIs that don't
99 llvm::StoreInst
*CreateStore(llvm::Value
*Val
, Address Addr
,
100 bool IsVolatile
= false) {
101 return CreateAlignedStore(Val
, Addr
.getPointer(),
102 Addr
.getAlignment().getAsAlign(), IsVolatile
);
105 using CGBuilderBaseTy::CreateAlignedStore
;
106 llvm::StoreInst
*CreateAlignedStore(llvm::Value
*Val
, llvm::Value
*Addr
,
108 bool IsVolatile
= false) {
109 return CreateAlignedStore(Val
, Addr
, Align
.getAsAlign(), IsVolatile
);
112 // FIXME: these "default-aligned" APIs should be removed,
113 // but I don't feel like fixing all the builtin code right now.
114 llvm::StoreInst
*CreateDefaultAlignedStore(llvm::Value
*Val
,
116 bool IsVolatile
= false) {
117 return CGBuilderBaseTy::CreateStore(Val
, Addr
, IsVolatile
);
120 /// Emit a load from an i1 flag variable.
121 llvm::LoadInst
*CreateFlagLoad(llvm::Value
*Addr
,
122 const llvm::Twine
&Name
= "") {
123 assert(llvm::cast
<llvm::PointerType
>(Addr
->getType())
124 ->isOpaqueOrPointeeTypeMatches(getInt1Ty()));
125 return CreateAlignedLoad(getInt1Ty(), Addr
, CharUnits::One(), Name
);
128 /// Emit a store to an i1 flag variable.
129 llvm::StoreInst
*CreateFlagStore(bool Value
, llvm::Value
*Addr
) {
130 assert(llvm::cast
<llvm::PointerType
>(Addr
->getType())
131 ->isOpaqueOrPointeeTypeMatches(getInt1Ty()));
132 return CreateAlignedStore(getInt1(Value
), Addr
, CharUnits::One());
135 // Temporarily use old signature; clang will be updated to an Address overload
136 // in a subsequent patch.
137 llvm::AtomicCmpXchgInst
*
138 CreateAtomicCmpXchg(llvm::Value
*Ptr
, llvm::Value
*Cmp
, llvm::Value
*New
,
139 llvm::AtomicOrdering SuccessOrdering
,
140 llvm::AtomicOrdering FailureOrdering
,
141 llvm::SyncScope::ID SSID
= llvm::SyncScope::System
) {
142 return CGBuilderBaseTy::CreateAtomicCmpXchg(
143 Ptr
, Cmp
, New
, llvm::MaybeAlign(), SuccessOrdering
, FailureOrdering
,
147 // Temporarily use old signature; clang will be updated to an Address overload
148 // in a subsequent patch.
149 llvm::AtomicRMWInst
*
150 CreateAtomicRMW(llvm::AtomicRMWInst::BinOp Op
, llvm::Value
*Ptr
,
151 llvm::Value
*Val
, llvm::AtomicOrdering Ordering
,
152 llvm::SyncScope::ID SSID
= llvm::SyncScope::System
) {
153 return CGBuilderBaseTy::CreateAtomicRMW(Op
, Ptr
, Val
, llvm::MaybeAlign(),
157 using CGBuilderBaseTy::CreateAddrSpaceCast
;
158 Address
CreateAddrSpaceCast(Address Addr
, llvm::Type
*Ty
,
159 const llvm::Twine
&Name
= "") {
160 assert(cast
<llvm::PointerType
>(Ty
)->isOpaqueOrPointeeTypeMatches(
161 Addr
.getElementType()) &&
162 "Should not change the element type");
163 return Addr
.withPointer(CreateAddrSpaceCast(Addr
.getPointer(), Ty
, Name
));
166 /// Cast the element type of the given address to a different type,
167 /// preserving information like the alignment and address space.
168 Address
CreateElementBitCast(Address Addr
, llvm::Type
*Ty
,
169 const llvm::Twine
&Name
= "") {
170 auto *PtrTy
= Ty
->getPointerTo(Addr
.getAddressSpace());
171 return Address(CreateBitCast(Addr
.getPointer(), PtrTy
, Name
), Ty
,
172 Addr
.getAlignment());
175 using CGBuilderBaseTy::CreatePointerBitCastOrAddrSpaceCast
;
176 Address
CreatePointerBitCastOrAddrSpaceCast(Address Addr
, llvm::Type
*Ty
,
177 llvm::Type
*ElementTy
,
178 const llvm::Twine
&Name
= "") {
180 CreatePointerBitCastOrAddrSpaceCast(Addr
.getPointer(), Ty
, Name
);
181 return Address(Ptr
, ElementTy
, Addr
.getAlignment());
185 /// %addr = {T1, T2...}* ...
187 /// %name = getelementptr inbounds %addr, i32 0, i32 index
189 /// This API assumes that drilling into a struct like this is always an
190 /// inbounds operation.
191 using CGBuilderBaseTy::CreateStructGEP
;
192 Address
CreateStructGEP(Address Addr
, unsigned Index
,
193 const llvm::Twine
&Name
= "") {
194 llvm::StructType
*ElTy
= cast
<llvm::StructType
>(Addr
.getElementType());
195 const llvm::DataLayout
&DL
= BB
->getParent()->getParent()->getDataLayout();
196 const llvm::StructLayout
*Layout
= DL
.getStructLayout(ElTy
);
197 auto Offset
= CharUnits::fromQuantity(Layout
->getElementOffset(Index
));
200 CreateStructGEP(Addr
.getElementType(), Addr
.getPointer(), Index
, Name
),
201 ElTy
->getElementType(Index
),
202 Addr
.getAlignment().alignmentAtOffset(Offset
));
206 /// %addr = [n x T]* ...
208 /// %name = getelementptr inbounds %addr, i64 0, i64 index
209 /// where i64 is actually the target word size.
211 /// This API assumes that drilling into an array like this is always
212 /// an inbounds operation.
213 Address
CreateConstArrayGEP(Address Addr
, uint64_t Index
,
214 const llvm::Twine
&Name
= "") {
215 llvm::ArrayType
*ElTy
= cast
<llvm::ArrayType
>(Addr
.getElementType());
216 const llvm::DataLayout
&DL
= BB
->getParent()->getParent()->getDataLayout();
218 CharUnits::fromQuantity(DL
.getTypeAllocSize(ElTy
->getElementType()));
221 CreateInBoundsGEP(Addr
.getElementType(), Addr
.getPointer(),
222 {getSize(CharUnits::Zero()), getSize(Index
)}, Name
),
223 ElTy
->getElementType(),
224 Addr
.getAlignment().alignmentAtOffset(Index
* EltSize
));
230 /// %name = getelementptr inbounds %addr, i64 index
231 /// where i64 is actually the target word size.
232 Address
CreateConstInBoundsGEP(Address Addr
, uint64_t Index
,
233 const llvm::Twine
&Name
= "") {
234 llvm::Type
*ElTy
= Addr
.getElementType();
235 const llvm::DataLayout
&DL
= BB
->getParent()->getParent()->getDataLayout();
236 CharUnits EltSize
= CharUnits::fromQuantity(DL
.getTypeAllocSize(ElTy
));
238 return Address(CreateInBoundsGEP(Addr
.getElementType(), Addr
.getPointer(),
239 getSize(Index
), Name
),
241 Addr
.getAlignment().alignmentAtOffset(Index
* EltSize
));
247 /// %name = getelementptr inbounds %addr, i64 index
248 /// where i64 is actually the target word size.
249 Address
CreateConstGEP(Address Addr
, uint64_t Index
,
250 const llvm::Twine
&Name
= "") {
251 const llvm::DataLayout
&DL
= BB
->getParent()->getParent()->getDataLayout();
253 CharUnits::fromQuantity(DL
.getTypeAllocSize(Addr
.getElementType()));
255 return Address(CreateGEP(Addr
.getElementType(), Addr
.getPointer(),
256 getSize(Index
), Name
),
257 Addr
.getElementType(),
258 Addr
.getAlignment().alignmentAtOffset(Index
* EltSize
));
261 /// Create GEP with single dynamic index. The address alignment is reduced
262 /// according to the element size.
263 using CGBuilderBaseTy::CreateGEP
;
264 Address
CreateGEP(Address Addr
, llvm::Value
*Index
,
265 const llvm::Twine
&Name
= "") {
266 const llvm::DataLayout
&DL
= BB
->getParent()->getParent()->getDataLayout();
268 CharUnits::fromQuantity(DL
.getTypeAllocSize(Addr
.getElementType()));
271 CreateGEP(Addr
.getElementType(), Addr
.getPointer(), Index
, Name
),
272 Addr
.getElementType(),
273 Addr
.getAlignment().alignmentOfArrayElement(EltSize
));
276 /// Given a pointer to i8, adjust it by a given constant offset.
277 Address
CreateConstInBoundsByteGEP(Address Addr
, CharUnits Offset
,
278 const llvm::Twine
&Name
= "") {
279 assert(Addr
.getElementType() == TypeCache
.Int8Ty
);
280 return Address(CreateInBoundsGEP(Addr
.getElementType(), Addr
.getPointer(),
281 getSize(Offset
), Name
),
282 Addr
.getElementType(),
283 Addr
.getAlignment().alignmentAtOffset(Offset
));
285 Address
CreateConstByteGEP(Address Addr
, CharUnits Offset
,
286 const llvm::Twine
&Name
= "") {
287 assert(Addr
.getElementType() == TypeCache
.Int8Ty
);
288 return Address(CreateGEP(Addr
.getElementType(), Addr
.getPointer(),
289 getSize(Offset
), Name
),
290 Addr
.getElementType(),
291 Addr
.getAlignment().alignmentAtOffset(Offset
));
294 using CGBuilderBaseTy::CreateConstInBoundsGEP2_32
;
295 Address
CreateConstInBoundsGEP2_32(Address Addr
, unsigned Idx0
, unsigned Idx1
,
296 const llvm::Twine
&Name
= "") {
297 const llvm::DataLayout
&DL
= BB
->getParent()->getParent()->getDataLayout();
299 auto *GEP
= cast
<llvm::GetElementPtrInst
>(CreateConstInBoundsGEP2_32(
300 Addr
.getElementType(), Addr
.getPointer(), Idx0
, Idx1
, Name
));
302 DL
.getIndexSizeInBits(Addr
.getType()->getPointerAddressSpace()), 0,
304 if (!GEP
->accumulateConstantOffset(DL
, Offset
))
305 llvm_unreachable("offset of GEP with constants is always computable");
306 return Address(GEP
, GEP
->getResultElementType(),
307 Addr
.getAlignment().alignmentAtOffset(
308 CharUnits::fromQuantity(Offset
.getSExtValue())));
311 using CGBuilderBaseTy::CreateMemCpy
;
312 llvm::CallInst
*CreateMemCpy(Address Dest
, Address Src
, llvm::Value
*Size
,
313 bool IsVolatile
= false) {
314 return CreateMemCpy(Dest
.getPointer(), Dest
.getAlignment().getAsAlign(),
315 Src
.getPointer(), Src
.getAlignment().getAsAlign(), Size
,
318 llvm::CallInst
*CreateMemCpy(Address Dest
, Address Src
, uint64_t Size
,
319 bool IsVolatile
= false) {
320 return CreateMemCpy(Dest
.getPointer(), Dest
.getAlignment().getAsAlign(),
321 Src
.getPointer(), Src
.getAlignment().getAsAlign(), Size
,
325 using CGBuilderBaseTy::CreateMemCpyInline
;
326 llvm::CallInst
*CreateMemCpyInline(Address Dest
, Address Src
, uint64_t Size
) {
327 return CreateMemCpyInline(
328 Dest
.getPointer(), Dest
.getAlignment().getAsAlign(), Src
.getPointer(),
329 Src
.getAlignment().getAsAlign(), getInt64(Size
));
332 using CGBuilderBaseTy::CreateMemMove
;
333 llvm::CallInst
*CreateMemMove(Address Dest
, Address Src
, llvm::Value
*Size
,
334 bool IsVolatile
= false) {
335 return CreateMemMove(Dest
.getPointer(), Dest
.getAlignment().getAsAlign(),
336 Src
.getPointer(), Src
.getAlignment().getAsAlign(),
340 using CGBuilderBaseTy::CreateMemSet
;
341 llvm::CallInst
*CreateMemSet(Address Dest
, llvm::Value
*Value
,
342 llvm::Value
*Size
, bool IsVolatile
= false) {
343 return CreateMemSet(Dest
.getPointer(), Value
, Size
,
344 Dest
.getAlignment().getAsAlign(), IsVolatile
);
347 using CGBuilderBaseTy::CreateMemSetInline
;
348 llvm::CallInst
*CreateMemSetInline(Address Dest
, llvm::Value
*Value
,
350 return CreateMemSetInline(Dest
.getPointer(),
351 Dest
.getAlignment().getAsAlign(), Value
,
355 using CGBuilderBaseTy::CreatePreserveStructAccessIndex
;
356 Address
CreatePreserveStructAccessIndex(Address Addr
, unsigned Index
,
358 llvm::MDNode
*DbgInfo
) {
359 llvm::StructType
*ElTy
= cast
<llvm::StructType
>(Addr
.getElementType());
360 const llvm::DataLayout
&DL
= BB
->getParent()->getParent()->getDataLayout();
361 const llvm::StructLayout
*Layout
= DL
.getStructLayout(ElTy
);
362 auto Offset
= CharUnits::fromQuantity(Layout
->getElementOffset(Index
));
364 return Address(CreatePreserveStructAccessIndex(ElTy
, Addr
.getPointer(),
365 Index
, FieldIndex
, DbgInfo
),
366 ElTy
->getElementType(Index
),
367 Addr
.getAlignment().alignmentAtOffset(Offset
));
370 using CGBuilderBaseTy::CreateLaunderInvariantGroup
;
371 Address
CreateLaunderInvariantGroup(Address Addr
) {
372 return Addr
.withPointer(CreateLaunderInvariantGroup(Addr
.getPointer()));
376 } // end namespace CodeGen
377 } // end namespace clang