[RISCV] Add shrinkwrap test cases showing gaps in current impl
[llvm-project.git] / clang / lib / CodeGen / CGBuilder.h
blobb8036cf6e6a30607d4c28e436df71ac5ee6d5fc9
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/GEPNoWrapFlags.h"
18 #include "llvm/IR/IRBuilder.h"
19 #include "llvm/IR/Type.h"
21 namespace clang {
22 namespace CodeGen {
24 class CGBuilderTy;
25 class CodeGenFunction;
27 /// This is an IRBuilder insertion helper that forwards to
28 /// CodeGenFunction::InsertHelper, which adds necessary metadata to
29 /// instructions.
30 class CGBuilderInserter final : public llvm::IRBuilderDefaultInserter {
31 friend CGBuilderTy;
33 public:
34 CGBuilderInserter() = default;
35 explicit CGBuilderInserter(CodeGenFunction *CGF) : CGF(CGF) {}
37 /// This forwards to CodeGenFunction::InsertHelper.
38 void InsertHelper(llvm::Instruction *I, const llvm::Twine &Name,
39 llvm::BasicBlock::iterator InsertPt) const override;
41 private:
42 CodeGenFunction *CGF = nullptr;
45 typedef CGBuilderInserter CGBuilderInserterTy;
47 typedef llvm::IRBuilder<llvm::ConstantFolder, CGBuilderInserterTy>
48 CGBuilderBaseTy;
50 class CGBuilderTy : public CGBuilderBaseTy {
51 friend class Address;
53 /// Storing a reference to the type cache here makes it a lot easier
54 /// to build natural-feeling, target-specific IR.
55 const CodeGenTypeCache &TypeCache;
57 CodeGenFunction *getCGF() const { return getInserter().CGF; }
59 llvm::Value *emitRawPointerFromAddress(Address Addr) const {
60 return Addr.getBasePointer();
63 template <bool IsInBounds>
64 Address createConstGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1,
65 const llvm::Twine &Name) {
66 const llvm::DataLayout &DL = BB->getDataLayout();
67 llvm::GetElementPtrInst *GEP;
68 if (IsInBounds)
69 GEP = cast<llvm::GetElementPtrInst>(CreateConstInBoundsGEP2_32(
70 Addr.getElementType(), emitRawPointerFromAddress(Addr), Idx0, Idx1,
71 Name));
72 else
73 GEP = cast<llvm::GetElementPtrInst>(CreateConstGEP2_32(
74 Addr.getElementType(), emitRawPointerFromAddress(Addr), Idx0, Idx1,
75 Name));
76 llvm::APInt Offset(
77 DL.getIndexSizeInBits(Addr.getType()->getPointerAddressSpace()), 0,
78 /*isSigned=*/true);
79 if (!GEP->accumulateConstantOffset(DL, Offset))
80 llvm_unreachable("offset of GEP with constants is always computable");
81 return Address(GEP, GEP->getResultElementType(),
82 Addr.getAlignment().alignmentAtOffset(
83 CharUnits::fromQuantity(Offset.getSExtValue())),
84 IsInBounds ? Addr.isKnownNonNull() : NotKnownNonNull);
87 public:
88 CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::LLVMContext &C)
89 : CGBuilderBaseTy(C), TypeCache(TypeCache) {}
90 CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::LLVMContext &C,
91 const llvm::ConstantFolder &F,
92 const CGBuilderInserterTy &Inserter)
93 : CGBuilderBaseTy(C, F, Inserter), TypeCache(TypeCache) {}
94 CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::Instruction *I)
95 : CGBuilderBaseTy(I), TypeCache(TypeCache) {}
96 CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::BasicBlock *BB)
97 : CGBuilderBaseTy(BB), TypeCache(TypeCache) {}
99 llvm::ConstantInt *getSize(CharUnits N) {
100 return llvm::ConstantInt::get(TypeCache.SizeTy, N.getQuantity());
102 llvm::ConstantInt *getSize(uint64_t N) {
103 return llvm::ConstantInt::get(TypeCache.SizeTy, N);
106 // Note that we intentionally hide the CreateLoad APIs that don't
107 // take an alignment.
108 llvm::LoadInst *CreateLoad(Address Addr, const llvm::Twine &Name = "") {
109 return CreateAlignedLoad(Addr.getElementType(),
110 emitRawPointerFromAddress(Addr),
111 Addr.getAlignment().getAsAlign(), Name);
113 llvm::LoadInst *CreateLoad(Address Addr, const char *Name) {
114 // This overload is required to prevent string literals from
115 // ending up in the IsVolatile overload.
116 return CreateAlignedLoad(Addr.getElementType(),
117 emitRawPointerFromAddress(Addr),
118 Addr.getAlignment().getAsAlign(), Name);
120 llvm::LoadInst *CreateLoad(Address Addr, bool IsVolatile,
121 const llvm::Twine &Name = "") {
122 return CreateAlignedLoad(
123 Addr.getElementType(), emitRawPointerFromAddress(Addr),
124 Addr.getAlignment().getAsAlign(), IsVolatile, Name);
127 using CGBuilderBaseTy::CreateAlignedLoad;
128 llvm::LoadInst *CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr,
129 CharUnits Align,
130 const llvm::Twine &Name = "") {
131 return CreateAlignedLoad(Ty, Addr, Align.getAsAlign(), Name);
134 // Note that we intentionally hide the CreateStore APIs that don't
135 // take an alignment.
136 llvm::StoreInst *CreateStore(llvm::Value *Val, Address Addr,
137 bool IsVolatile = false) {
138 return CreateAlignedStore(Val, emitRawPointerFromAddress(Addr),
139 Addr.getAlignment().getAsAlign(), IsVolatile);
142 using CGBuilderBaseTy::CreateAlignedStore;
143 llvm::StoreInst *CreateAlignedStore(llvm::Value *Val, llvm::Value *Addr,
144 CharUnits Align,
145 bool IsVolatile = false) {
146 return CreateAlignedStore(Val, Addr, Align.getAsAlign(), IsVolatile);
149 // FIXME: these "default-aligned" APIs should be removed,
150 // but I don't feel like fixing all the builtin code right now.
151 llvm::StoreInst *CreateDefaultAlignedStore(llvm::Value *Val,
152 llvm::Value *Addr,
153 bool IsVolatile = false) {
154 return CGBuilderBaseTy::CreateStore(Val, Addr, IsVolatile);
157 /// Emit a load from an i1 flag variable.
158 llvm::LoadInst *CreateFlagLoad(llvm::Value *Addr,
159 const llvm::Twine &Name = "") {
160 return CreateAlignedLoad(getInt1Ty(), Addr, CharUnits::One(), Name);
163 /// Emit a store to an i1 flag variable.
164 llvm::StoreInst *CreateFlagStore(bool Value, llvm::Value *Addr) {
165 return CreateAlignedStore(getInt1(Value), Addr, CharUnits::One());
168 llvm::AtomicCmpXchgInst *
169 CreateAtomicCmpXchg(Address Addr, llvm::Value *Cmp, llvm::Value *New,
170 llvm::AtomicOrdering SuccessOrdering,
171 llvm::AtomicOrdering FailureOrdering,
172 llvm::SyncScope::ID SSID = llvm::SyncScope::System) {
173 return CGBuilderBaseTy::CreateAtomicCmpXchg(
174 Addr.emitRawPointer(*getCGF()), Cmp, New,
175 Addr.getAlignment().getAsAlign(), SuccessOrdering, FailureOrdering,
176 SSID);
179 llvm::AtomicRMWInst *
180 CreateAtomicRMW(llvm::AtomicRMWInst::BinOp Op, Address Addr, llvm::Value *Val,
181 llvm::AtomicOrdering Ordering,
182 llvm::SyncScope::ID SSID = llvm::SyncScope::System) {
183 return CGBuilderBaseTy::CreateAtomicRMW(
184 Op, Addr.emitRawPointer(*getCGF()), Val,
185 Addr.getAlignment().getAsAlign(), Ordering, SSID);
188 using CGBuilderBaseTy::CreateAddrSpaceCast;
189 Address CreateAddrSpaceCast(Address Addr, llvm::Type *Ty,
190 llvm::Type *ElementTy,
191 const llvm::Twine &Name = "") {
192 if (!Addr.hasOffset())
193 return Address(CreateAddrSpaceCast(Addr.getBasePointer(), Ty, Name),
194 ElementTy, Addr.getAlignment(), Addr.getPointerAuthInfo(),
195 /*Offset=*/nullptr, Addr.isKnownNonNull());
196 // Eagerly force a raw address if these is an offset.
197 return RawAddress(
198 CreateAddrSpaceCast(Addr.emitRawPointer(*getCGF()), Ty, Name),
199 ElementTy, Addr.getAlignment(), Addr.isKnownNonNull());
202 using CGBuilderBaseTy::CreatePointerBitCastOrAddrSpaceCast;
203 Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty,
204 llvm::Type *ElementTy,
205 const llvm::Twine &Name = "") {
206 if (Addr.getType()->getAddressSpace() == Ty->getPointerAddressSpace())
207 return Addr.withElementType(ElementTy);
208 return CreateAddrSpaceCast(Addr, Ty, ElementTy, Name);
211 /// Given
212 /// %addr = {T1, T2...}* ...
213 /// produce
214 /// %name = getelementptr inbounds nuw %addr, i32 0, i32 index
216 /// This API assumes that drilling into a struct like this is always an
217 /// inbounds and nuw operation.
218 using CGBuilderBaseTy::CreateStructGEP;
219 Address CreateStructGEP(Address Addr, unsigned Index,
220 const llvm::Twine &Name = "") {
221 llvm::StructType *ElTy = cast<llvm::StructType>(Addr.getElementType());
222 const llvm::DataLayout &DL = BB->getDataLayout();
223 const llvm::StructLayout *Layout = DL.getStructLayout(ElTy);
224 auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index));
226 return Address(CreateStructGEP(Addr.getElementType(), Addr.getBasePointer(),
227 Index, Name),
228 ElTy->getElementType(Index),
229 Addr.getAlignment().alignmentAtOffset(Offset),
230 Addr.isKnownNonNull());
233 /// Given
234 /// %addr = [n x T]* ...
235 /// produce
236 /// %name = getelementptr inbounds %addr, i64 0, i64 index
237 /// where i64 is actually the target word size.
239 /// This API assumes that drilling into an array like this is always
240 /// an inbounds operation.
241 Address CreateConstArrayGEP(Address Addr, uint64_t Index,
242 const llvm::Twine &Name = "") {
243 llvm::ArrayType *ElTy = cast<llvm::ArrayType>(Addr.getElementType());
244 const llvm::DataLayout &DL = BB->getDataLayout();
245 CharUnits EltSize =
246 CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy->getElementType()));
248 return Address(
249 CreateInBoundsGEP(Addr.getElementType(), Addr.getBasePointer(),
250 {getSize(CharUnits::Zero()), getSize(Index)}, Name),
251 ElTy->getElementType(),
252 Addr.getAlignment().alignmentAtOffset(Index * EltSize),
253 Addr.isKnownNonNull());
256 /// Given
257 /// %addr = T* ...
258 /// produce
259 /// %name = getelementptr inbounds %addr, i64 index
260 /// where i64 is actually the target word size.
261 Address CreateConstInBoundsGEP(Address Addr, uint64_t Index,
262 const llvm::Twine &Name = "") {
263 llvm::Type *ElTy = Addr.getElementType();
264 const llvm::DataLayout &DL = BB->getDataLayout();
265 CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy));
267 return Address(
268 CreateInBoundsGEP(ElTy, Addr.getBasePointer(), getSize(Index), Name),
269 ElTy, Addr.getAlignment().alignmentAtOffset(Index * EltSize),
270 Addr.isKnownNonNull());
273 /// Given
274 /// %addr = T* ...
275 /// produce
276 /// %name = getelementptr inbounds %addr, i64 index
277 /// where i64 is actually the target word size.
278 Address CreateConstGEP(Address Addr, uint64_t Index,
279 const llvm::Twine &Name = "") {
280 llvm::Type *ElTy = Addr.getElementType();
281 const llvm::DataLayout &DL = BB->getDataLayout();
282 CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy));
284 return Address(CreateGEP(ElTy, Addr.getBasePointer(), getSize(Index), Name),
285 Addr.getElementType(),
286 Addr.getAlignment().alignmentAtOffset(Index * EltSize));
289 /// Create GEP with single dynamic index. The address alignment is reduced
290 /// according to the element size.
291 using CGBuilderBaseTy::CreateGEP;
292 Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index,
293 const llvm::Twine &Name = "") {
294 const llvm::DataLayout &DL = BB->getDataLayout();
295 CharUnits EltSize =
296 CharUnits::fromQuantity(DL.getTypeAllocSize(Addr.getElementType()));
298 return Address(
299 CreateGEP(Addr.getElementType(), Addr.emitRawPointer(CGF), Index, Name),
300 Addr.getElementType(),
301 Addr.getAlignment().alignmentOfArrayElement(EltSize));
304 /// Given a pointer to i8, adjust it by a given constant offset.
305 Address CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset,
306 const llvm::Twine &Name = "") {
307 assert(Addr.getElementType() == TypeCache.Int8Ty);
308 return Address(
309 CreateInBoundsGEP(Addr.getElementType(), Addr.getBasePointer(),
310 getSize(Offset), Name),
311 Addr.getElementType(), Addr.getAlignment().alignmentAtOffset(Offset),
312 Addr.isKnownNonNull());
315 Address CreateConstByteGEP(Address Addr, CharUnits Offset,
316 const llvm::Twine &Name = "") {
317 assert(Addr.getElementType() == TypeCache.Int8Ty);
318 return Address(CreateGEP(Addr.getElementType(), Addr.getBasePointer(),
319 getSize(Offset), Name),
320 Addr.getElementType(),
321 Addr.getAlignment().alignmentAtOffset(Offset));
324 using CGBuilderBaseTy::CreateConstInBoundsGEP2_32;
325 Address CreateConstInBoundsGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1,
326 const llvm::Twine &Name = "") {
327 return createConstGEP2_32<true>(Addr, Idx0, Idx1, Name);
330 using CGBuilderBaseTy::CreateConstGEP2_32;
331 Address CreateConstGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1,
332 const llvm::Twine &Name = "") {
333 return createConstGEP2_32<false>(Addr, Idx0, Idx1, Name);
336 Address CreateGEP(Address Addr, ArrayRef<llvm::Value *> IdxList,
337 llvm::Type *ElementType, CharUnits Align,
338 const Twine &Name = "",
339 llvm::GEPNoWrapFlags NW = llvm::GEPNoWrapFlags::none()) {
340 llvm::Value *Ptr = emitRawPointerFromAddress(Addr);
341 return RawAddress(CreateGEP(Addr.getElementType(), Ptr, IdxList, Name, NW),
342 ElementType, Align);
345 using CGBuilderBaseTy::CreateInBoundsGEP;
346 Address CreateInBoundsGEP(Address Addr, ArrayRef<llvm::Value *> IdxList,
347 llvm::Type *ElementType, CharUnits Align,
348 const Twine &Name = "") {
349 return RawAddress(CreateInBoundsGEP(Addr.getElementType(),
350 emitRawPointerFromAddress(Addr),
351 IdxList, Name),
352 ElementType, Align, Addr.isKnownNonNull());
355 using CGBuilderBaseTy::CreateIsNull;
356 llvm::Value *CreateIsNull(Address Addr, const Twine &Name = "") {
357 if (!Addr.hasOffset())
358 return CreateIsNull(Addr.getBasePointer(), Name);
359 // The pointer isn't null if Addr has an offset since offsets can always
360 // be applied inbound.
361 return llvm::ConstantInt::getFalse(Context);
364 using CGBuilderBaseTy::CreateMemCpy;
365 llvm::CallInst *CreateMemCpy(Address Dest, Address Src, llvm::Value *Size,
366 bool IsVolatile = false) {
367 llvm::Value *DestPtr = emitRawPointerFromAddress(Dest);
368 llvm::Value *SrcPtr = emitRawPointerFromAddress(Src);
369 return CreateMemCpy(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr,
370 Src.getAlignment().getAsAlign(), Size, IsVolatile);
372 llvm::CallInst *CreateMemCpy(Address Dest, Address Src, uint64_t Size,
373 bool IsVolatile = false) {
374 llvm::Value *DestPtr = emitRawPointerFromAddress(Dest);
375 llvm::Value *SrcPtr = emitRawPointerFromAddress(Src);
376 return CreateMemCpy(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr,
377 Src.getAlignment().getAsAlign(), Size, IsVolatile);
380 using CGBuilderBaseTy::CreateMemCpyInline;
381 llvm::CallInst *CreateMemCpyInline(Address Dest, Address Src, uint64_t Size) {
382 llvm::Value *DestPtr = emitRawPointerFromAddress(Dest);
383 llvm::Value *SrcPtr = emitRawPointerFromAddress(Src);
384 return CreateMemCpyInline(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr,
385 Src.getAlignment().getAsAlign(), getInt64(Size));
388 using CGBuilderBaseTy::CreateMemMove;
389 llvm::CallInst *CreateMemMove(Address Dest, Address Src, llvm::Value *Size,
390 bool IsVolatile = false) {
391 llvm::Value *DestPtr = emitRawPointerFromAddress(Dest);
392 llvm::Value *SrcPtr = emitRawPointerFromAddress(Src);
393 return CreateMemMove(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr,
394 Src.getAlignment().getAsAlign(), Size, IsVolatile);
397 using CGBuilderBaseTy::CreateMemSet;
398 llvm::CallInst *CreateMemSet(Address Dest, llvm::Value *Value,
399 llvm::Value *Size, bool IsVolatile = false) {
400 return CreateMemSet(emitRawPointerFromAddress(Dest), Value, Size,
401 Dest.getAlignment().getAsAlign(), IsVolatile);
404 using CGBuilderBaseTy::CreateMemSetInline;
405 llvm::CallInst *CreateMemSetInline(Address Dest, llvm::Value *Value,
406 uint64_t Size) {
407 return CreateMemSetInline(emitRawPointerFromAddress(Dest),
408 Dest.getAlignment().getAsAlign(), Value,
409 getInt64(Size));
412 using CGBuilderBaseTy::CreatePreserveStructAccessIndex;
413 Address CreatePreserveStructAccessIndex(Address Addr, unsigned Index,
414 unsigned FieldIndex,
415 llvm::MDNode *DbgInfo) {
416 llvm::StructType *ElTy = cast<llvm::StructType>(Addr.getElementType());
417 const llvm::DataLayout &DL = BB->getDataLayout();
418 const llvm::StructLayout *Layout = DL.getStructLayout(ElTy);
419 auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index));
421 return Address(
422 CreatePreserveStructAccessIndex(ElTy, emitRawPointerFromAddress(Addr),
423 Index, FieldIndex, DbgInfo),
424 ElTy->getElementType(Index),
425 Addr.getAlignment().alignmentAtOffset(Offset));
428 using CGBuilderBaseTy::CreatePreserveUnionAccessIndex;
429 Address CreatePreserveUnionAccessIndex(Address Addr, unsigned FieldIndex,
430 llvm::MDNode *DbgInfo) {
431 Addr.replaceBasePointer(CreatePreserveUnionAccessIndex(
432 Addr.getBasePointer(), FieldIndex, DbgInfo));
433 return Addr;
436 using CGBuilderBaseTy::CreateLaunderInvariantGroup;
437 Address CreateLaunderInvariantGroup(Address Addr) {
438 Addr.replaceBasePointer(CreateLaunderInvariantGroup(Addr.getBasePointer()));
439 return Addr;
442 using CGBuilderBaseTy::CreateStripInvariantGroup;
443 Address CreateStripInvariantGroup(Address Addr) {
444 Addr.replaceBasePointer(CreateStripInvariantGroup(Addr.getBasePointer()));
445 return Addr;
449 } // end namespace CodeGen
450 } // end namespace clang
452 #endif