[AMDGPU][AsmParser][NFC] Get rid of custom default operand handlers.
[llvm-project.git] / clang / lib / CodeGen / CGBuilder.h
blob902fd945708375ab1fe100ec82d63c4f1e18186a
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 "CodeGenTypeCache.h"
14 #include "llvm/IR/DataLayout.h"
15 #include "llvm/IR/IRBuilder.h"
16 #include "llvm/IR/Type.h"
18 namespace clang {
19 namespace CodeGen {
21 class CodeGenFunction;
23 /// This is an IRBuilder insertion helper that forwards to
24 /// CodeGenFunction::InsertHelper, which adds necessary metadata to
25 /// instructions.
26 class CGBuilderInserter final : public llvm::IRBuilderDefaultInserter {
27 public:
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,
33 llvm::BasicBlock *BB,
34 llvm::BasicBlock::iterator InsertPt) const override;
36 private:
37 CodeGenFunction *CGF = nullptr;
40 typedef CGBuilderInserter CGBuilderInserterTy;
42 typedef llvm::IRBuilder<llvm::ConstantFolder, CGBuilderInserterTy>
43 CGBuilderBaseTy;
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;
50 public:
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
70 // take an alignment.
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,
85 Name);
88 using CGBuilderBaseTy::CreateAlignedLoad;
89 llvm::LoadInst *CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr,
90 CharUnits Align,
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
96 // take an alignment.
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,
105 CharUnits Align,
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,
113 llvm::Value *Addr,
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,
138 SSID);
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(),
148 Ordering, SSID);
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 = "") {
171 llvm::Value *Ptr =
172 CreatePointerBitCastOrAddrSpaceCast(Addr.getPointer(), Ty, Name);
173 return Address(Ptr, ElementTy, Addr.getAlignment(), Addr.isKnownNonNull());
176 /// Given
177 /// %addr = {T1, T2...}* ...
178 /// produce
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));
191 return Address(
192 CreateStructGEP(Addr.getElementType(), Addr.getPointer(), Index, Name),
193 ElTy->getElementType(Index),
194 Addr.getAlignment().alignmentAtOffset(Offset), Addr.isKnownNonNull());
197 /// Given
198 /// %addr = [n x T]* ...
199 /// produce
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();
209 CharUnits EltSize =
210 CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy->getElementType()));
212 return Address(
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());
220 /// Given
221 /// %addr = T* ...
222 /// produce
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());
237 /// Given
238 /// %addr = T* ...
239 /// produce
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();
245 CharUnits EltSize =
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),
252 NotKnownNonNull);
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();
261 CharUnits EltSize =
262 CharUnits::fromQuantity(DL.getTypeAllocSize(Addr.getElementType()));
264 return Address(
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),
287 NotKnownNonNull);
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));
297 llvm::APInt Offset(
298 DL.getIndexSizeInBits(Addr.getType()->getPointerAddressSpace()), 0,
299 /*isSigned=*/true);
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,
313 IsVolatile);
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,
319 IsVolatile);
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(),
334 Size, IsVolatile);
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,
346 uint64_t Size) {
347 return CreateMemSetInline(Dest.getPointer(),
348 Dest.getAlignment().getAsAlign(), Value,
349 getInt64(Size));
352 using CGBuilderBaseTy::CreatePreserveStructAccessIndex;
353 Address CreatePreserveStructAccessIndex(Address Addr, unsigned Index,
354 unsigned FieldIndex,
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
377 #endif