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
14 #include "CodeGenTypeCache.h"
15 #include "llvm/Analysis/Utils/Local.h"
16 #include "llvm/IR/DataLayout.h"
17 #include "llvm/IR/IRBuilder.h"
18 #include "llvm/IR/Type.h"
24 class CodeGenFunction
;
26 /// This is an IRBuilder insertion helper that forwards to
27 /// CodeGenFunction::InsertHelper, which adds necessary metadata to
29 class CGBuilderInserter final
: public llvm::IRBuilderDefaultInserter
{
33 CGBuilderInserter() = default;
34 explicit CGBuilderInserter(CodeGenFunction
*CGF
) : CGF(CGF
) {}
36 /// This forwards to CodeGenFunction::InsertHelper.
37 void InsertHelper(llvm::Instruction
*I
, const llvm::Twine
&Name
,
38 llvm::BasicBlock::iterator InsertPt
) const override
;
41 CodeGenFunction
*CGF
= nullptr;
44 typedef CGBuilderInserter CGBuilderInserterTy
;
46 typedef llvm::IRBuilder
<llvm::ConstantFolder
, CGBuilderInserterTy
>
49 class CGBuilderTy
: public CGBuilderBaseTy
{
52 /// Storing a reference to the type cache here makes it a lot easier
53 /// to build natural-feeling, target-specific IR.
54 const CodeGenTypeCache
&TypeCache
;
56 CodeGenFunction
*getCGF() const { return getInserter().CGF
; }
58 llvm::Value
*emitRawPointerFromAddress(Address Addr
) const {
59 return Addr
.getBasePointer();
62 template <bool IsInBounds
>
63 Address
createConstGEP2_32(Address Addr
, unsigned Idx0
, unsigned Idx1
,
64 const llvm::Twine
&Name
) {
65 const llvm::DataLayout
&DL
= BB
->getDataLayout();
66 llvm::GetElementPtrInst
*GEP
;
68 GEP
= cast
<llvm::GetElementPtrInst
>(CreateConstInBoundsGEP2_32(
69 Addr
.getElementType(), emitRawPointerFromAddress(Addr
), Idx0
, Idx1
,
72 GEP
= cast
<llvm::GetElementPtrInst
>(CreateConstGEP2_32(
73 Addr
.getElementType(), emitRawPointerFromAddress(Addr
), Idx0
, Idx1
,
76 DL
.getIndexSizeInBits(Addr
.getType()->getPointerAddressSpace()), 0,
78 if (!GEP
->accumulateConstantOffset(DL
, Offset
))
79 llvm_unreachable("offset of GEP with constants is always computable");
80 return Address(GEP
, GEP
->getResultElementType(),
81 Addr
.getAlignment().alignmentAtOffset(
82 CharUnits::fromQuantity(Offset
.getSExtValue())),
83 IsInBounds
? Addr
.isKnownNonNull() : NotKnownNonNull
);
87 CGBuilderTy(const CodeGenTypeCache
&TypeCache
, llvm::LLVMContext
&C
)
88 : CGBuilderBaseTy(C
), TypeCache(TypeCache
) {}
89 CGBuilderTy(const CodeGenTypeCache
&TypeCache
, llvm::LLVMContext
&C
,
90 const llvm::ConstantFolder
&F
,
91 const CGBuilderInserterTy
&Inserter
)
92 : CGBuilderBaseTy(C
, F
, Inserter
), TypeCache(TypeCache
) {}
93 CGBuilderTy(const CodeGenTypeCache
&TypeCache
, llvm::Instruction
*I
)
94 : CGBuilderBaseTy(I
), TypeCache(TypeCache
) {}
95 CGBuilderTy(const CodeGenTypeCache
&TypeCache
, llvm::BasicBlock
*BB
)
96 : CGBuilderBaseTy(BB
), TypeCache(TypeCache
) {}
98 llvm::ConstantInt
*getSize(CharUnits N
) {
99 return llvm::ConstantInt::get(TypeCache
.SizeTy
, N
.getQuantity());
101 llvm::ConstantInt
*getSize(uint64_t N
) {
102 return llvm::ConstantInt::get(TypeCache
.SizeTy
, N
);
105 // Note that we intentionally hide the CreateLoad APIs that don't
106 // take an alignment.
107 llvm::LoadInst
*CreateLoad(Address Addr
, const llvm::Twine
&Name
= "") {
108 return CreateAlignedLoad(Addr
.getElementType(),
109 emitRawPointerFromAddress(Addr
),
110 Addr
.getAlignment().getAsAlign(), Name
);
112 llvm::LoadInst
*CreateLoad(Address Addr
, const char *Name
) {
113 // This overload is required to prevent string literals from
114 // ending up in the IsVolatile overload.
115 return CreateAlignedLoad(Addr
.getElementType(),
116 emitRawPointerFromAddress(Addr
),
117 Addr
.getAlignment().getAsAlign(), Name
);
119 llvm::LoadInst
*CreateLoad(Address Addr
, bool IsVolatile
,
120 const llvm::Twine
&Name
= "") {
121 return CreateAlignedLoad(
122 Addr
.getElementType(), emitRawPointerFromAddress(Addr
),
123 Addr
.getAlignment().getAsAlign(), IsVolatile
, Name
);
126 using CGBuilderBaseTy::CreateAlignedLoad
;
127 llvm::LoadInst
*CreateAlignedLoad(llvm::Type
*Ty
, llvm::Value
*Addr
,
129 const llvm::Twine
&Name
= "") {
130 return CreateAlignedLoad(Ty
, Addr
, Align
.getAsAlign(), Name
);
133 // Note that we intentionally hide the CreateStore APIs that don't
134 // take an alignment.
135 llvm::StoreInst
*CreateStore(llvm::Value
*Val
, Address Addr
,
136 bool IsVolatile
= false) {
137 return CreateAlignedStore(Val
, emitRawPointerFromAddress(Addr
),
138 Addr
.getAlignment().getAsAlign(), IsVolatile
);
141 using CGBuilderBaseTy::CreateAlignedStore
;
142 llvm::StoreInst
*CreateAlignedStore(llvm::Value
*Val
, llvm::Value
*Addr
,
144 bool IsVolatile
= false) {
145 return CreateAlignedStore(Val
, Addr
, Align
.getAsAlign(), IsVolatile
);
148 // FIXME: these "default-aligned" APIs should be removed,
149 // but I don't feel like fixing all the builtin code right now.
150 llvm::StoreInst
*CreateDefaultAlignedStore(llvm::Value
*Val
,
152 bool IsVolatile
= false) {
153 return CGBuilderBaseTy::CreateStore(Val
, Addr
, IsVolatile
);
156 /// Emit a load from an i1 flag variable.
157 llvm::LoadInst
*CreateFlagLoad(llvm::Value
*Addr
,
158 const llvm::Twine
&Name
= "") {
159 return CreateAlignedLoad(getInt1Ty(), Addr
, CharUnits::One(), Name
);
162 /// Emit a store to an i1 flag variable.
163 llvm::StoreInst
*CreateFlagStore(bool Value
, llvm::Value
*Addr
) {
164 return CreateAlignedStore(getInt1(Value
), Addr
, CharUnits::One());
167 llvm::AtomicCmpXchgInst
*
168 CreateAtomicCmpXchg(Address Addr
, llvm::Value
*Cmp
, llvm::Value
*New
,
169 llvm::AtomicOrdering SuccessOrdering
,
170 llvm::AtomicOrdering FailureOrdering
,
171 llvm::SyncScope::ID SSID
= llvm::SyncScope::System
) {
172 return CGBuilderBaseTy::CreateAtomicCmpXchg(
173 Addr
.emitRawPointer(*getCGF()), Cmp
, New
,
174 Addr
.getAlignment().getAsAlign(), SuccessOrdering
, FailureOrdering
,
178 llvm::AtomicRMWInst
*
179 CreateAtomicRMW(llvm::AtomicRMWInst::BinOp Op
, Address Addr
, llvm::Value
*Val
,
180 llvm::AtomicOrdering Ordering
,
181 llvm::SyncScope::ID SSID
= llvm::SyncScope::System
) {
182 return CGBuilderBaseTy::CreateAtomicRMW(
183 Op
, Addr
.emitRawPointer(*getCGF()), Val
,
184 Addr
.getAlignment().getAsAlign(), Ordering
, SSID
);
187 using CGBuilderBaseTy::CreateAddrSpaceCast
;
188 Address
CreateAddrSpaceCast(Address Addr
, llvm::Type
*Ty
,
189 llvm::Type
*ElementTy
,
190 const llvm::Twine
&Name
= "") {
191 if (!Addr
.hasOffset())
192 return Address(CreateAddrSpaceCast(Addr
.getBasePointer(), Ty
, Name
),
193 ElementTy
, Addr
.getAlignment(), Addr
.getPointerAuthInfo(),
194 /*Offset=*/nullptr, Addr
.isKnownNonNull());
195 // Eagerly force a raw address if these is an offset.
197 CreateAddrSpaceCast(Addr
.emitRawPointer(*getCGF()), Ty
, Name
),
198 ElementTy
, Addr
.getAlignment(), Addr
.isKnownNonNull());
201 using CGBuilderBaseTy::CreatePointerBitCastOrAddrSpaceCast
;
202 Address
CreatePointerBitCastOrAddrSpaceCast(Address Addr
, llvm::Type
*Ty
,
203 llvm::Type
*ElementTy
,
204 const llvm::Twine
&Name
= "") {
205 if (Addr
.getType()->getAddressSpace() == Ty
->getPointerAddressSpace())
206 return Addr
.withElementType(ElementTy
);
207 return CreateAddrSpaceCast(Addr
, Ty
, ElementTy
, Name
);
211 /// %addr = {T1, T2...}* ...
213 /// %name = getelementptr inbounds %addr, i32 0, i32 index
215 /// This API assumes that drilling into a struct like this is always an
216 /// inbounds operation.
217 using CGBuilderBaseTy::CreateStructGEP
;
218 Address
CreateStructGEP(Address Addr
, unsigned Index
,
219 const llvm::Twine
&Name
= "") {
220 llvm::StructType
*ElTy
= cast
<llvm::StructType
>(Addr
.getElementType());
221 const llvm::DataLayout
&DL
= BB
->getDataLayout();
222 const llvm::StructLayout
*Layout
= DL
.getStructLayout(ElTy
);
223 auto Offset
= CharUnits::fromQuantity(Layout
->getElementOffset(Index
));
225 return Address(CreateStructGEP(Addr
.getElementType(), Addr
.getBasePointer(),
227 ElTy
->getElementType(Index
),
228 Addr
.getAlignment().alignmentAtOffset(Offset
),
229 Addr
.isKnownNonNull());
233 /// %addr = [n x T]* ...
235 /// %name = getelementptr inbounds %addr, i64 0, i64 index
236 /// where i64 is actually the target word size.
238 /// This API assumes that drilling into an array like this is always
239 /// an inbounds operation.
240 Address
CreateConstArrayGEP(Address Addr
, uint64_t Index
,
241 const llvm::Twine
&Name
= "") {
242 llvm::ArrayType
*ElTy
= cast
<llvm::ArrayType
>(Addr
.getElementType());
243 const llvm::DataLayout
&DL
= BB
->getDataLayout();
245 CharUnits::fromQuantity(DL
.getTypeAllocSize(ElTy
->getElementType()));
248 CreateInBoundsGEP(Addr
.getElementType(), Addr
.getBasePointer(),
249 {getSize(CharUnits::Zero()), getSize(Index
)}, Name
),
250 ElTy
->getElementType(),
251 Addr
.getAlignment().alignmentAtOffset(Index
* EltSize
),
252 Addr
.isKnownNonNull());
258 /// %name = getelementptr inbounds %addr, i64 index
259 /// where i64 is actually the target word size.
260 Address
CreateConstInBoundsGEP(Address Addr
, uint64_t Index
,
261 const llvm::Twine
&Name
= "") {
262 llvm::Type
*ElTy
= Addr
.getElementType();
263 const llvm::DataLayout
&DL
= BB
->getDataLayout();
264 CharUnits EltSize
= CharUnits::fromQuantity(DL
.getTypeAllocSize(ElTy
));
267 CreateInBoundsGEP(ElTy
, Addr
.getBasePointer(), getSize(Index
), Name
),
268 ElTy
, Addr
.getAlignment().alignmentAtOffset(Index
* EltSize
),
269 Addr
.isKnownNonNull());
275 /// %name = getelementptr inbounds %addr, i64 index
276 /// where i64 is actually the target word size.
277 Address
CreateConstGEP(Address Addr
, uint64_t Index
,
278 const llvm::Twine
&Name
= "") {
279 llvm::Type
*ElTy
= Addr
.getElementType();
280 const llvm::DataLayout
&DL
= BB
->getDataLayout();
281 CharUnits EltSize
= CharUnits::fromQuantity(DL
.getTypeAllocSize(ElTy
));
283 return Address(CreateGEP(ElTy
, Addr
.getBasePointer(), getSize(Index
), Name
),
284 Addr
.getElementType(),
285 Addr
.getAlignment().alignmentAtOffset(Index
* EltSize
));
288 /// Create GEP with single dynamic index. The address alignment is reduced
289 /// according to the element size.
290 using CGBuilderBaseTy::CreateGEP
;
291 Address
CreateGEP(CodeGenFunction
&CGF
, Address Addr
, llvm::Value
*Index
,
292 const llvm::Twine
&Name
= "") {
293 const llvm::DataLayout
&DL
= BB
->getDataLayout();
295 CharUnits::fromQuantity(DL
.getTypeAllocSize(Addr
.getElementType()));
298 CreateGEP(Addr
.getElementType(), Addr
.emitRawPointer(CGF
), Index
, Name
),
299 Addr
.getElementType(),
300 Addr
.getAlignment().alignmentOfArrayElement(EltSize
));
303 /// Given a pointer to i8, adjust it by a given constant offset.
304 Address
CreateConstInBoundsByteGEP(Address Addr
, CharUnits Offset
,
305 const llvm::Twine
&Name
= "") {
306 assert(Addr
.getElementType() == TypeCache
.Int8Ty
);
308 CreateInBoundsGEP(Addr
.getElementType(), Addr
.getBasePointer(),
309 getSize(Offset
), Name
),
310 Addr
.getElementType(), Addr
.getAlignment().alignmentAtOffset(Offset
),
311 Addr
.isKnownNonNull());
314 Address
CreateConstByteGEP(Address Addr
, CharUnits Offset
,
315 const llvm::Twine
&Name
= "") {
316 assert(Addr
.getElementType() == TypeCache
.Int8Ty
);
317 return Address(CreateGEP(Addr
.getElementType(), Addr
.getBasePointer(),
318 getSize(Offset
), Name
),
319 Addr
.getElementType(),
320 Addr
.getAlignment().alignmentAtOffset(Offset
));
323 using CGBuilderBaseTy::CreateConstInBoundsGEP2_32
;
324 Address
CreateConstInBoundsGEP2_32(Address Addr
, unsigned Idx0
, unsigned Idx1
,
325 const llvm::Twine
&Name
= "") {
326 return createConstGEP2_32
<true>(Addr
, Idx0
, Idx1
, Name
);
329 using CGBuilderBaseTy::CreateConstGEP2_32
;
330 Address
CreateConstGEP2_32(Address Addr
, unsigned Idx0
, unsigned Idx1
,
331 const llvm::Twine
&Name
= "") {
332 return createConstGEP2_32
<false>(Addr
, Idx0
, Idx1
, Name
);
335 Address
CreateGEP(Address Addr
, ArrayRef
<llvm::Value
*> IdxList
,
336 llvm::Type
*ElementType
, CharUnits Align
,
337 const Twine
&Name
= "") {
338 llvm::Value
*Ptr
= emitRawPointerFromAddress(Addr
);
339 return RawAddress(CreateGEP(Addr
.getElementType(), Ptr
, IdxList
, Name
),
343 using CGBuilderBaseTy::CreateInBoundsGEP
;
344 Address
CreateInBoundsGEP(Address Addr
, ArrayRef
<llvm::Value
*> IdxList
,
345 llvm::Type
*ElementType
, CharUnits Align
,
346 const Twine
&Name
= "") {
347 return RawAddress(CreateInBoundsGEP(Addr
.getElementType(),
348 emitRawPointerFromAddress(Addr
),
350 ElementType
, Align
, Addr
.isKnownNonNull());
353 using CGBuilderBaseTy::CreateIsNull
;
354 llvm::Value
*CreateIsNull(Address Addr
, const Twine
&Name
= "") {
355 if (!Addr
.hasOffset())
356 return CreateIsNull(Addr
.getBasePointer(), Name
);
357 // The pointer isn't null if Addr has an offset since offsets can always
358 // be applied inbound.
359 return llvm::ConstantInt::getFalse(Context
);
362 using CGBuilderBaseTy::CreateMemCpy
;
363 llvm::CallInst
*CreateMemCpy(Address Dest
, Address Src
, llvm::Value
*Size
,
364 bool IsVolatile
= false) {
365 llvm::Value
*DestPtr
= emitRawPointerFromAddress(Dest
);
366 llvm::Value
*SrcPtr
= emitRawPointerFromAddress(Src
);
367 return CreateMemCpy(DestPtr
, Dest
.getAlignment().getAsAlign(), SrcPtr
,
368 Src
.getAlignment().getAsAlign(), Size
, IsVolatile
);
370 llvm::CallInst
*CreateMemCpy(Address Dest
, Address Src
, uint64_t Size
,
371 bool IsVolatile
= false) {
372 llvm::Value
*DestPtr
= emitRawPointerFromAddress(Dest
);
373 llvm::Value
*SrcPtr
= emitRawPointerFromAddress(Src
);
374 return CreateMemCpy(DestPtr
, Dest
.getAlignment().getAsAlign(), SrcPtr
,
375 Src
.getAlignment().getAsAlign(), Size
, IsVolatile
);
378 using CGBuilderBaseTy::CreateMemCpyInline
;
379 llvm::CallInst
*CreateMemCpyInline(Address Dest
, Address Src
, uint64_t Size
) {
380 llvm::Value
*DestPtr
= emitRawPointerFromAddress(Dest
);
381 llvm::Value
*SrcPtr
= emitRawPointerFromAddress(Src
);
382 return CreateMemCpyInline(DestPtr
, Dest
.getAlignment().getAsAlign(), SrcPtr
,
383 Src
.getAlignment().getAsAlign(), getInt64(Size
));
386 using CGBuilderBaseTy::CreateMemMove
;
387 llvm::CallInst
*CreateMemMove(Address Dest
, Address Src
, llvm::Value
*Size
,
388 bool IsVolatile
= false) {
389 llvm::Value
*DestPtr
= emitRawPointerFromAddress(Dest
);
390 llvm::Value
*SrcPtr
= emitRawPointerFromAddress(Src
);
391 return CreateMemMove(DestPtr
, Dest
.getAlignment().getAsAlign(), SrcPtr
,
392 Src
.getAlignment().getAsAlign(), Size
, IsVolatile
);
395 using CGBuilderBaseTy::CreateMemSet
;
396 llvm::CallInst
*CreateMemSet(Address Dest
, llvm::Value
*Value
,
397 llvm::Value
*Size
, bool IsVolatile
= false) {
398 return CreateMemSet(emitRawPointerFromAddress(Dest
), Value
, Size
,
399 Dest
.getAlignment().getAsAlign(), IsVolatile
);
402 using CGBuilderBaseTy::CreateMemSetInline
;
403 llvm::CallInst
*CreateMemSetInline(Address Dest
, llvm::Value
*Value
,
405 return CreateMemSetInline(emitRawPointerFromAddress(Dest
),
406 Dest
.getAlignment().getAsAlign(), Value
,
410 using CGBuilderBaseTy::CreatePreserveStructAccessIndex
;
411 Address
CreatePreserveStructAccessIndex(Address Addr
, unsigned Index
,
413 llvm::MDNode
*DbgInfo
) {
414 llvm::StructType
*ElTy
= cast
<llvm::StructType
>(Addr
.getElementType());
415 const llvm::DataLayout
&DL
= BB
->getDataLayout();
416 const llvm::StructLayout
*Layout
= DL
.getStructLayout(ElTy
);
417 auto Offset
= CharUnits::fromQuantity(Layout
->getElementOffset(Index
));
420 CreatePreserveStructAccessIndex(ElTy
, emitRawPointerFromAddress(Addr
),
421 Index
, FieldIndex
, DbgInfo
),
422 ElTy
->getElementType(Index
),
423 Addr
.getAlignment().alignmentAtOffset(Offset
));
426 using CGBuilderBaseTy::CreatePreserveUnionAccessIndex
;
427 Address
CreatePreserveUnionAccessIndex(Address Addr
, unsigned FieldIndex
,
428 llvm::MDNode
*DbgInfo
) {
429 Addr
.replaceBasePointer(CreatePreserveUnionAccessIndex(
430 Addr
.getBasePointer(), FieldIndex
, DbgInfo
));
434 using CGBuilderBaseTy::CreateLaunderInvariantGroup
;
435 Address
CreateLaunderInvariantGroup(Address Addr
) {
436 Addr
.replaceBasePointer(CreateLaunderInvariantGroup(Addr
.getBasePointer()));
440 using CGBuilderBaseTy::CreateStripInvariantGroup
;
441 Address
CreateStripInvariantGroup(Address Addr
) {
442 Addr
.replaceBasePointer(CreateStripInvariantGroup(Addr
.getBasePointer()));
447 } // end namespace CodeGen
448 } // end namespace clang