[Clang][CodeGen] Fix type for atomic float incdec operators (#107075)
[llvm-project.git] / clang / lib / CodeGen / CGBuilder.h
blob5d59d5a4ae2c14c0e342b68fc2e8fe1151db87a4
1 //===-- CGBuilder.h - Choose IRBuilder implementation ----------*- C++ -*-===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
9 #ifndef LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H
10 #define LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H
12 #include "Address.h"
13 #include "CGValue.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"
20 namespace clang {
21 namespace CodeGen {
23 class CGBuilderTy;
24 class CodeGenFunction;
26 /// This is an IRBuilder insertion helper that forwards to
27 /// CodeGenFunction::InsertHelper, which adds necessary metadata to
28 /// instructions.
29 class CGBuilderInserter final : public llvm::IRBuilderDefaultInserter {
30 friend CGBuilderTy;
32 public:
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;
40 private:
41 CodeGenFunction *CGF = nullptr;
44 typedef CGBuilderInserter CGBuilderInserterTy;
46 typedef llvm::IRBuilder<llvm::ConstantFolder, CGBuilderInserterTy>
47 CGBuilderBaseTy;
49 class CGBuilderTy : public CGBuilderBaseTy {
50 friend class Address;
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;
67 if (IsInBounds)
68 GEP = cast<llvm::GetElementPtrInst>(CreateConstInBoundsGEP2_32(
69 Addr.getElementType(), emitRawPointerFromAddress(Addr), Idx0, Idx1,
70 Name));
71 else
72 GEP = cast<llvm::GetElementPtrInst>(CreateConstGEP2_32(
73 Addr.getElementType(), emitRawPointerFromAddress(Addr), Idx0, Idx1,
74 Name));
75 llvm::APInt Offset(
76 DL.getIndexSizeInBits(Addr.getType()->getPointerAddressSpace()), 0,
77 /*isSigned=*/true);
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);
86 public:
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,
128 CharUnits Align,
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,
143 CharUnits Align,
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,
151 llvm::Value *Addr,
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,
175 SSID);
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.
196 return RawAddress(
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);
210 /// Given
211 /// %addr = {T1, T2...}* ...
212 /// produce
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(),
226 Index, Name),
227 ElTy->getElementType(Index),
228 Addr.getAlignment().alignmentAtOffset(Offset),
229 Addr.isKnownNonNull());
232 /// Given
233 /// %addr = [n x T]* ...
234 /// produce
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();
244 CharUnits EltSize =
245 CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy->getElementType()));
247 return Address(
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());
255 /// Given
256 /// %addr = T* ...
257 /// produce
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));
266 return Address(
267 CreateInBoundsGEP(ElTy, Addr.getBasePointer(), getSize(Index), Name),
268 ElTy, Addr.getAlignment().alignmentAtOffset(Index * EltSize),
269 Addr.isKnownNonNull());
272 /// Given
273 /// %addr = T* ...
274 /// produce
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();
294 CharUnits EltSize =
295 CharUnits::fromQuantity(DL.getTypeAllocSize(Addr.getElementType()));
297 return Address(
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);
307 return Address(
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),
340 ElementType, Align);
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),
349 IdxList, Name),
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,
404 uint64_t Size) {
405 return CreateMemSetInline(emitRawPointerFromAddress(Dest),
406 Dest.getAlignment().getAsAlign(), Value,
407 getInt64(Size));
410 using CGBuilderBaseTy::CreatePreserveStructAccessIndex;
411 Address CreatePreserveStructAccessIndex(Address Addr, unsigned Index,
412 unsigned FieldIndex,
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));
419 return Address(
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));
431 return Addr;
434 using CGBuilderBaseTy::CreateLaunderInvariantGroup;
435 Address CreateLaunderInvariantGroup(Address Addr) {
436 Addr.replaceBasePointer(CreateLaunderInvariantGroup(Addr.getBasePointer()));
437 return Addr;
440 using CGBuilderBaseTy::CreateStripInvariantGroup;
441 Address CreateStripInvariantGroup(Address Addr) {
442 Addr.replaceBasePointer(CreateStripInvariantGroup(Addr.getBasePointer()));
443 return Addr;
447 } // end namespace CodeGen
448 } // end namespace clang
450 #endif