xref: /freebsd-src/contrib/llvm-project/clang/lib/CodeGen/CGBuilder.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-- CGBuilder.h - Choose IRBuilder implementation  ----------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #ifndef LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H
100b57cec5SDimitry Andric #define LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H
110b57cec5SDimitry Andric 
120b57cec5SDimitry Andric #include "Address.h"
13*0fca6ea1SDimitry Andric #include "CGValue.h"
140b57cec5SDimitry Andric #include "CodeGenTypeCache.h"
15*0fca6ea1SDimitry Andric #include "llvm/Analysis/Utils/Local.h"
166a5eebc1SDimitry Andric #include "llvm/IR/DataLayout.h"
176a5eebc1SDimitry Andric #include "llvm/IR/IRBuilder.h"
186a5eebc1SDimitry Andric #include "llvm/IR/Type.h"
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric namespace clang {
210b57cec5SDimitry Andric namespace CodeGen {
220b57cec5SDimitry Andric 
23*0fca6ea1SDimitry Andric class CGBuilderTy;
240b57cec5SDimitry Andric class CodeGenFunction;
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric /// This is an IRBuilder insertion helper that forwards to
270b57cec5SDimitry Andric /// CodeGenFunction::InsertHelper, which adds necessary metadata to
280b57cec5SDimitry Andric /// instructions.
295ffd83dbSDimitry Andric class CGBuilderInserter final : public llvm::IRBuilderDefaultInserter {
30*0fca6ea1SDimitry Andric   friend CGBuilderTy;
31*0fca6ea1SDimitry Andric 
320b57cec5SDimitry Andric public:
330b57cec5SDimitry Andric   CGBuilderInserter() = default;
340b57cec5SDimitry Andric   explicit CGBuilderInserter(CodeGenFunction *CGF) : CGF(CGF) {}
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric   /// This forwards to CodeGenFunction::InsertHelper.
370b57cec5SDimitry Andric   void InsertHelper(llvm::Instruction *I, const llvm::Twine &Name,
385ffd83dbSDimitry Andric                     llvm::BasicBlock::iterator InsertPt) const override;
3981ad6265SDimitry Andric 
400b57cec5SDimitry Andric private:
410b57cec5SDimitry Andric   CodeGenFunction *CGF = nullptr;
420b57cec5SDimitry Andric };
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric typedef CGBuilderInserter CGBuilderInserterTy;
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric typedef llvm::IRBuilder<llvm::ConstantFolder, CGBuilderInserterTy>
470b57cec5SDimitry Andric     CGBuilderBaseTy;
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric class CGBuilderTy : public CGBuilderBaseTy {
50*0fca6ea1SDimitry Andric   friend class Address;
51*0fca6ea1SDimitry Andric 
520b57cec5SDimitry Andric   /// Storing a reference to the type cache here makes it a lot easier
530b57cec5SDimitry Andric   /// to build natural-feeling, target-specific IR.
540b57cec5SDimitry Andric   const CodeGenTypeCache &TypeCache;
5581ad6265SDimitry Andric 
56*0fca6ea1SDimitry Andric   CodeGenFunction *getCGF() const { return getInserter().CGF; }
57*0fca6ea1SDimitry Andric 
58*0fca6ea1SDimitry Andric   llvm::Value *emitRawPointerFromAddress(Address Addr) const {
59*0fca6ea1SDimitry Andric     return Addr.getBasePointer();
60*0fca6ea1SDimitry Andric   }
61*0fca6ea1SDimitry Andric 
62*0fca6ea1SDimitry Andric   template <bool IsInBounds>
63*0fca6ea1SDimitry Andric   Address createConstGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1,
64*0fca6ea1SDimitry Andric                              const llvm::Twine &Name) {
65*0fca6ea1SDimitry Andric     const llvm::DataLayout &DL = BB->getDataLayout();
66*0fca6ea1SDimitry Andric     llvm::GetElementPtrInst *GEP;
67*0fca6ea1SDimitry Andric     if (IsInBounds)
68*0fca6ea1SDimitry Andric       GEP = cast<llvm::GetElementPtrInst>(CreateConstInBoundsGEP2_32(
69*0fca6ea1SDimitry Andric           Addr.getElementType(), emitRawPointerFromAddress(Addr), Idx0, Idx1,
70*0fca6ea1SDimitry Andric           Name));
71*0fca6ea1SDimitry Andric     else
72*0fca6ea1SDimitry Andric       GEP = cast<llvm::GetElementPtrInst>(CreateConstGEP2_32(
73*0fca6ea1SDimitry Andric           Addr.getElementType(), emitRawPointerFromAddress(Addr), Idx0, Idx1,
74*0fca6ea1SDimitry Andric           Name));
75*0fca6ea1SDimitry Andric     llvm::APInt Offset(
76*0fca6ea1SDimitry Andric         DL.getIndexSizeInBits(Addr.getType()->getPointerAddressSpace()), 0,
77*0fca6ea1SDimitry Andric         /*isSigned=*/true);
78*0fca6ea1SDimitry Andric     if (!GEP->accumulateConstantOffset(DL, Offset))
79*0fca6ea1SDimitry Andric       llvm_unreachable("offset of GEP with constants is always computable");
80*0fca6ea1SDimitry Andric     return Address(GEP, GEP->getResultElementType(),
81*0fca6ea1SDimitry Andric                    Addr.getAlignment().alignmentAtOffset(
82*0fca6ea1SDimitry Andric                        CharUnits::fromQuantity(Offset.getSExtValue())),
83*0fca6ea1SDimitry Andric                    IsInBounds ? Addr.isKnownNonNull() : NotKnownNonNull);
84*0fca6ea1SDimitry Andric   }
85*0fca6ea1SDimitry Andric 
860b57cec5SDimitry Andric public:
870b57cec5SDimitry Andric   CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::LLVMContext &C)
880b57cec5SDimitry Andric       : CGBuilderBaseTy(C), TypeCache(TypeCache) {}
8981ad6265SDimitry Andric   CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::LLVMContext &C,
9081ad6265SDimitry Andric               const llvm::ConstantFolder &F,
910b57cec5SDimitry Andric               const CGBuilderInserterTy &Inserter)
920b57cec5SDimitry Andric       : CGBuilderBaseTy(C, F, Inserter), TypeCache(TypeCache) {}
930b57cec5SDimitry Andric   CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::Instruction *I)
940b57cec5SDimitry Andric       : CGBuilderBaseTy(I), TypeCache(TypeCache) {}
950b57cec5SDimitry Andric   CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::BasicBlock *BB)
960b57cec5SDimitry Andric       : CGBuilderBaseTy(BB), TypeCache(TypeCache) {}
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric   llvm::ConstantInt *getSize(CharUnits N) {
990b57cec5SDimitry Andric     return llvm::ConstantInt::get(TypeCache.SizeTy, N.getQuantity());
1000b57cec5SDimitry Andric   }
1010b57cec5SDimitry Andric   llvm::ConstantInt *getSize(uint64_t N) {
1020b57cec5SDimitry Andric     return llvm::ConstantInt::get(TypeCache.SizeTy, N);
1030b57cec5SDimitry Andric   }
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric   // Note that we intentionally hide the CreateLoad APIs that don't
1060b57cec5SDimitry Andric   // take an alignment.
1070b57cec5SDimitry Andric   llvm::LoadInst *CreateLoad(Address Addr, const llvm::Twine &Name = "") {
108*0fca6ea1SDimitry Andric     return CreateAlignedLoad(Addr.getElementType(),
109*0fca6ea1SDimitry Andric                              emitRawPointerFromAddress(Addr),
1105ffd83dbSDimitry Andric                              Addr.getAlignment().getAsAlign(), Name);
1110b57cec5SDimitry Andric   }
1120b57cec5SDimitry Andric   llvm::LoadInst *CreateLoad(Address Addr, const char *Name) {
1130b57cec5SDimitry Andric     // This overload is required to prevent string literals from
1140b57cec5SDimitry Andric     // ending up in the IsVolatile overload.
115*0fca6ea1SDimitry Andric     return CreateAlignedLoad(Addr.getElementType(),
116*0fca6ea1SDimitry Andric                              emitRawPointerFromAddress(Addr),
1175ffd83dbSDimitry Andric                              Addr.getAlignment().getAsAlign(), Name);
1180b57cec5SDimitry Andric   }
1190b57cec5SDimitry Andric   llvm::LoadInst *CreateLoad(Address Addr, bool IsVolatile,
1200b57cec5SDimitry Andric                              const llvm::Twine &Name = "") {
121*0fca6ea1SDimitry Andric     return CreateAlignedLoad(
122*0fca6ea1SDimitry Andric         Addr.getElementType(), emitRawPointerFromAddress(Addr),
123*0fca6ea1SDimitry Andric         Addr.getAlignment().getAsAlign(), IsVolatile, Name);
1240b57cec5SDimitry Andric   }
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric   using CGBuilderBaseTy::CreateAlignedLoad;
1270b57cec5SDimitry Andric   llvm::LoadInst *CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr,
1280b57cec5SDimitry Andric                                     CharUnits Align,
1290b57cec5SDimitry Andric                                     const llvm::Twine &Name = "") {
130fe6060f1SDimitry Andric     return CreateAlignedLoad(Ty, Addr, Align.getAsAlign(), Name);
1310b57cec5SDimitry Andric   }
1320b57cec5SDimitry Andric 
1330b57cec5SDimitry Andric   // Note that we intentionally hide the CreateStore APIs that don't
1340b57cec5SDimitry Andric   // take an alignment.
1350b57cec5SDimitry Andric   llvm::StoreInst *CreateStore(llvm::Value *Val, Address Addr,
1360b57cec5SDimitry Andric                                bool IsVolatile = false) {
137*0fca6ea1SDimitry Andric     return CreateAlignedStore(Val, emitRawPointerFromAddress(Addr),
138480093f4SDimitry Andric                               Addr.getAlignment().getAsAlign(), IsVolatile);
1390b57cec5SDimitry Andric   }
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric   using CGBuilderBaseTy::CreateAlignedStore;
1420b57cec5SDimitry Andric   llvm::StoreInst *CreateAlignedStore(llvm::Value *Val, llvm::Value *Addr,
14381ad6265SDimitry Andric                                       CharUnits Align,
14481ad6265SDimitry Andric                                       bool IsVolatile = false) {
1455ffd83dbSDimitry Andric     return CreateAlignedStore(Val, Addr, Align.getAsAlign(), IsVolatile);
1460b57cec5SDimitry Andric   }
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric   // FIXME: these "default-aligned" APIs should be removed,
1490b57cec5SDimitry Andric   // but I don't feel like fixing all the builtin code right now.
1500b57cec5SDimitry Andric   llvm::StoreInst *CreateDefaultAlignedStore(llvm::Value *Val,
1510b57cec5SDimitry Andric                                              llvm::Value *Addr,
1520b57cec5SDimitry Andric                                              bool IsVolatile = false) {
1530b57cec5SDimitry Andric     return CGBuilderBaseTy::CreateStore(Val, Addr, IsVolatile);
1540b57cec5SDimitry Andric   }
1550b57cec5SDimitry Andric 
1560b57cec5SDimitry Andric   /// Emit a load from an i1 flag variable.
1570b57cec5SDimitry Andric   llvm::LoadInst *CreateFlagLoad(llvm::Value *Addr,
1580b57cec5SDimitry Andric                                  const llvm::Twine &Name = "") {
1590b57cec5SDimitry Andric     return CreateAlignedLoad(getInt1Ty(), Addr, CharUnits::One(), Name);
1600b57cec5SDimitry Andric   }
1610b57cec5SDimitry Andric 
1620b57cec5SDimitry Andric   /// Emit a store to an i1 flag variable.
1630b57cec5SDimitry Andric   llvm::StoreInst *CreateFlagStore(bool Value, llvm::Value *Addr) {
1640b57cec5SDimitry Andric     return CreateAlignedStore(getInt1(Value), Addr, CharUnits::One());
1650b57cec5SDimitry Andric   }
1660b57cec5SDimitry Andric 
167fe6060f1SDimitry Andric   llvm::AtomicCmpXchgInst *
1685f757f3fSDimitry Andric   CreateAtomicCmpXchg(Address Addr, llvm::Value *Cmp, llvm::Value *New,
169fe6060f1SDimitry Andric                       llvm::AtomicOrdering SuccessOrdering,
170fe6060f1SDimitry Andric                       llvm::AtomicOrdering FailureOrdering,
171fe6060f1SDimitry Andric                       llvm::SyncScope::ID SSID = llvm::SyncScope::System) {
172fe6060f1SDimitry Andric     return CGBuilderBaseTy::CreateAtomicCmpXchg(
173*0fca6ea1SDimitry Andric         Addr.emitRawPointer(*getCGF()), Cmp, New,
174*0fca6ea1SDimitry Andric         Addr.getAlignment().getAsAlign(), SuccessOrdering, FailureOrdering,
175*0fca6ea1SDimitry Andric         SSID);
176fe6060f1SDimitry Andric   }
177fe6060f1SDimitry Andric 
178fe6060f1SDimitry Andric   llvm::AtomicRMWInst *
1795f757f3fSDimitry Andric   CreateAtomicRMW(llvm::AtomicRMWInst::BinOp Op, Address Addr, llvm::Value *Val,
1805f757f3fSDimitry Andric                   llvm::AtomicOrdering Ordering,
181fe6060f1SDimitry Andric                   llvm::SyncScope::ID SSID = llvm::SyncScope::System) {
182*0fca6ea1SDimitry Andric     return CGBuilderBaseTy::CreateAtomicRMW(
183*0fca6ea1SDimitry Andric         Op, Addr.emitRawPointer(*getCGF()), Val,
184*0fca6ea1SDimitry Andric         Addr.getAlignment().getAsAlign(), Ordering, SSID);
185fe6060f1SDimitry Andric   }
186fe6060f1SDimitry Andric 
1870b57cec5SDimitry Andric   using CGBuilderBaseTy::CreateAddrSpaceCast;
1880b57cec5SDimitry Andric   Address CreateAddrSpaceCast(Address Addr, llvm::Type *Ty,
189*0fca6ea1SDimitry Andric                               llvm::Type *ElementTy,
1900b57cec5SDimitry Andric                               const llvm::Twine &Name = "") {
191*0fca6ea1SDimitry Andric     if (!Addr.hasOffset())
192*0fca6ea1SDimitry Andric       return Address(CreateAddrSpaceCast(Addr.getBasePointer(), Ty, Name),
193*0fca6ea1SDimitry Andric                      ElementTy, Addr.getAlignment(), Addr.getPointerAuthInfo(),
194*0fca6ea1SDimitry Andric                      /*Offset=*/nullptr, Addr.isKnownNonNull());
195*0fca6ea1SDimitry Andric     // Eagerly force a raw address if these is an offset.
196*0fca6ea1SDimitry Andric     return RawAddress(
197*0fca6ea1SDimitry Andric         CreateAddrSpaceCast(Addr.emitRawPointer(*getCGF()), Ty, Name),
198*0fca6ea1SDimitry Andric         ElementTy, Addr.getAlignment(), Addr.isKnownNonNull());
1990b57cec5SDimitry Andric   }
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric   using CGBuilderBaseTy::CreatePointerBitCastOrAddrSpaceCast;
2020b57cec5SDimitry Andric   Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty,
20381ad6265SDimitry Andric                                               llvm::Type *ElementTy,
2040b57cec5SDimitry Andric                                               const llvm::Twine &Name = "") {
205*0fca6ea1SDimitry Andric     if (Addr.getType()->getAddressSpace() == Ty->getPointerAddressSpace())
206*0fca6ea1SDimitry Andric       return Addr.withElementType(ElementTy);
207*0fca6ea1SDimitry Andric     return CreateAddrSpaceCast(Addr, Ty, ElementTy, Name);
2080b57cec5SDimitry Andric   }
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric   /// Given
2110b57cec5SDimitry Andric   ///   %addr = {T1, T2...}* ...
2120b57cec5SDimitry Andric   /// produce
2130b57cec5SDimitry Andric   ///   %name = getelementptr inbounds %addr, i32 0, i32 index
2140b57cec5SDimitry Andric   ///
2150b57cec5SDimitry Andric   /// This API assumes that drilling into a struct like this is always an
2160b57cec5SDimitry Andric   /// inbounds operation.
2170b57cec5SDimitry Andric   using CGBuilderBaseTy::CreateStructGEP;
2180b57cec5SDimitry Andric   Address CreateStructGEP(Address Addr, unsigned Index,
2190b57cec5SDimitry Andric                           const llvm::Twine &Name = "") {
2200b57cec5SDimitry Andric     llvm::StructType *ElTy = cast<llvm::StructType>(Addr.getElementType());
221*0fca6ea1SDimitry Andric     const llvm::DataLayout &DL = BB->getDataLayout();
2220b57cec5SDimitry Andric     const llvm::StructLayout *Layout = DL.getStructLayout(ElTy);
2230b57cec5SDimitry Andric     auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index));
2240b57cec5SDimitry Andric 
225*0fca6ea1SDimitry Andric     return Address(CreateStructGEP(Addr.getElementType(), Addr.getBasePointer(),
226*0fca6ea1SDimitry Andric                                    Index, Name),
2270eae32dcSDimitry Andric                    ElTy->getElementType(Index),
228*0fca6ea1SDimitry Andric                    Addr.getAlignment().alignmentAtOffset(Offset),
229*0fca6ea1SDimitry Andric                    Addr.isKnownNonNull());
2300b57cec5SDimitry Andric   }
2310b57cec5SDimitry Andric 
2320b57cec5SDimitry Andric   /// Given
2330b57cec5SDimitry Andric   ///   %addr = [n x T]* ...
2340b57cec5SDimitry Andric   /// produce
2350b57cec5SDimitry Andric   ///   %name = getelementptr inbounds %addr, i64 0, i64 index
2360b57cec5SDimitry Andric   /// where i64 is actually the target word size.
2370b57cec5SDimitry Andric   ///
2380b57cec5SDimitry Andric   /// This API assumes that drilling into an array like this is always
2390b57cec5SDimitry Andric   /// an inbounds operation.
2400b57cec5SDimitry Andric   Address CreateConstArrayGEP(Address Addr, uint64_t Index,
2410b57cec5SDimitry Andric                               const llvm::Twine &Name = "") {
2420b57cec5SDimitry Andric     llvm::ArrayType *ElTy = cast<llvm::ArrayType>(Addr.getElementType());
243*0fca6ea1SDimitry Andric     const llvm::DataLayout &DL = BB->getDataLayout();
2440b57cec5SDimitry Andric     CharUnits EltSize =
2450b57cec5SDimitry Andric         CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy->getElementType()));
2460b57cec5SDimitry Andric 
2470b57cec5SDimitry Andric     return Address(
248*0fca6ea1SDimitry Andric         CreateInBoundsGEP(Addr.getElementType(), Addr.getBasePointer(),
2490b57cec5SDimitry Andric                           {getSize(CharUnits::Zero()), getSize(Index)}, Name),
2500eae32dcSDimitry Andric         ElTy->getElementType(),
25106c3fb27SDimitry Andric         Addr.getAlignment().alignmentAtOffset(Index * EltSize),
25206c3fb27SDimitry Andric         Addr.isKnownNonNull());
2530b57cec5SDimitry Andric   }
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric   /// Given
2560b57cec5SDimitry Andric   ///   %addr = T* ...
2570b57cec5SDimitry Andric   /// produce
2580b57cec5SDimitry Andric   ///   %name = getelementptr inbounds %addr, i64 index
2590b57cec5SDimitry Andric   /// where i64 is actually the target word size.
2600b57cec5SDimitry Andric   Address CreateConstInBoundsGEP(Address Addr, uint64_t Index,
2610b57cec5SDimitry Andric                                  const llvm::Twine &Name = "") {
2620b57cec5SDimitry Andric     llvm::Type *ElTy = Addr.getElementType();
263*0fca6ea1SDimitry Andric     const llvm::DataLayout &DL = BB->getDataLayout();
2640b57cec5SDimitry Andric     CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy));
2650b57cec5SDimitry Andric 
266*0fca6ea1SDimitry Andric     return Address(
267*0fca6ea1SDimitry Andric         CreateInBoundsGEP(ElTy, Addr.getBasePointer(), getSize(Index), Name),
26806c3fb27SDimitry Andric         ElTy, Addr.getAlignment().alignmentAtOffset(Index * EltSize),
26906c3fb27SDimitry Andric         Addr.isKnownNonNull());
2700b57cec5SDimitry Andric   }
2710b57cec5SDimitry Andric 
2720b57cec5SDimitry Andric   /// Given
2730b57cec5SDimitry Andric   ///   %addr = T* ...
2740b57cec5SDimitry Andric   /// produce
2750b57cec5SDimitry Andric   ///   %name = getelementptr inbounds %addr, i64 index
2760b57cec5SDimitry Andric   /// where i64 is actually the target word size.
2770b57cec5SDimitry Andric   Address CreateConstGEP(Address Addr, uint64_t Index,
2780b57cec5SDimitry Andric                          const llvm::Twine &Name = "") {
279*0fca6ea1SDimitry Andric     llvm::Type *ElTy = Addr.getElementType();
280*0fca6ea1SDimitry Andric     const llvm::DataLayout &DL = BB->getDataLayout();
281*0fca6ea1SDimitry Andric     CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy));
2820b57cec5SDimitry Andric 
283*0fca6ea1SDimitry Andric     return Address(CreateGEP(ElTy, Addr.getBasePointer(), getSize(Index), Name),
2840eae32dcSDimitry Andric                    Addr.getElementType(),
285*0fca6ea1SDimitry Andric                    Addr.getAlignment().alignmentAtOffset(Index * EltSize));
2860b57cec5SDimitry Andric   }
2870b57cec5SDimitry Andric 
2880eae32dcSDimitry Andric   /// Create GEP with single dynamic index. The address alignment is reduced
2890eae32dcSDimitry Andric   /// according to the element size.
2900eae32dcSDimitry Andric   using CGBuilderBaseTy::CreateGEP;
291*0fca6ea1SDimitry Andric   Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index,
2920eae32dcSDimitry Andric                     const llvm::Twine &Name = "") {
293*0fca6ea1SDimitry Andric     const llvm::DataLayout &DL = BB->getDataLayout();
2940eae32dcSDimitry Andric     CharUnits EltSize =
2950eae32dcSDimitry Andric         CharUnits::fromQuantity(DL.getTypeAllocSize(Addr.getElementType()));
2960eae32dcSDimitry Andric 
29781ad6265SDimitry Andric     return Address(
298*0fca6ea1SDimitry Andric         CreateGEP(Addr.getElementType(), Addr.emitRawPointer(CGF), Index, Name),
2990eae32dcSDimitry Andric         Addr.getElementType(),
300*0fca6ea1SDimitry Andric         Addr.getAlignment().alignmentOfArrayElement(EltSize));
3010eae32dcSDimitry Andric   }
3020eae32dcSDimitry Andric 
3030b57cec5SDimitry Andric   /// Given a pointer to i8, adjust it by a given constant offset.
3040b57cec5SDimitry Andric   Address CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset,
3050b57cec5SDimitry Andric                                      const llvm::Twine &Name = "") {
3060b57cec5SDimitry Andric     assert(Addr.getElementType() == TypeCache.Int8Ty);
307*0fca6ea1SDimitry Andric     return Address(
308*0fca6ea1SDimitry Andric         CreateInBoundsGEP(Addr.getElementType(), Addr.getBasePointer(),
309fe6060f1SDimitry Andric                           getSize(Offset), Name),
310*0fca6ea1SDimitry Andric         Addr.getElementType(), Addr.getAlignment().alignmentAtOffset(Offset),
31106c3fb27SDimitry Andric         Addr.isKnownNonNull());
3120b57cec5SDimitry Andric   }
313*0fca6ea1SDimitry Andric 
3140b57cec5SDimitry Andric   Address CreateConstByteGEP(Address Addr, CharUnits Offset,
3150b57cec5SDimitry Andric                              const llvm::Twine &Name = "") {
3160b57cec5SDimitry Andric     assert(Addr.getElementType() == TypeCache.Int8Ty);
317*0fca6ea1SDimitry Andric     return Address(CreateGEP(Addr.getElementType(), Addr.getBasePointer(),
318fe6060f1SDimitry Andric                              getSize(Offset), Name),
3190eae32dcSDimitry Andric                    Addr.getElementType(),
320*0fca6ea1SDimitry Andric                    Addr.getAlignment().alignmentAtOffset(Offset));
3210b57cec5SDimitry Andric   }
3220b57cec5SDimitry Andric 
3230b57cec5SDimitry Andric   using CGBuilderBaseTy::CreateConstInBoundsGEP2_32;
3240b57cec5SDimitry Andric   Address CreateConstInBoundsGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1,
3250b57cec5SDimitry Andric                                      const llvm::Twine &Name = "") {
326*0fca6ea1SDimitry Andric     return createConstGEP2_32<true>(Addr, Idx0, Idx1, Name);
327*0fca6ea1SDimitry Andric   }
3280b57cec5SDimitry Andric 
329*0fca6ea1SDimitry Andric   using CGBuilderBaseTy::CreateConstGEP2_32;
330*0fca6ea1SDimitry Andric   Address CreateConstGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1,
331*0fca6ea1SDimitry Andric                              const llvm::Twine &Name = "") {
332*0fca6ea1SDimitry Andric     return createConstGEP2_32<false>(Addr, Idx0, Idx1, Name);
333*0fca6ea1SDimitry Andric   }
334*0fca6ea1SDimitry Andric 
335*0fca6ea1SDimitry Andric   Address CreateGEP(Address Addr, ArrayRef<llvm::Value *> IdxList,
336*0fca6ea1SDimitry Andric                     llvm::Type *ElementType, CharUnits Align,
337*0fca6ea1SDimitry Andric                     const Twine &Name = "") {
338*0fca6ea1SDimitry Andric     llvm::Value *Ptr = emitRawPointerFromAddress(Addr);
339*0fca6ea1SDimitry Andric     return RawAddress(CreateGEP(Addr.getElementType(), Ptr, IdxList, Name),
340*0fca6ea1SDimitry Andric                       ElementType, Align);
341*0fca6ea1SDimitry Andric   }
342*0fca6ea1SDimitry Andric 
343*0fca6ea1SDimitry Andric   using CGBuilderBaseTy::CreateInBoundsGEP;
344*0fca6ea1SDimitry Andric   Address CreateInBoundsGEP(Address Addr, ArrayRef<llvm::Value *> IdxList,
345*0fca6ea1SDimitry Andric                             llvm::Type *ElementType, CharUnits Align,
346*0fca6ea1SDimitry Andric                             const Twine &Name = "") {
347*0fca6ea1SDimitry Andric     return RawAddress(CreateInBoundsGEP(Addr.getElementType(),
348*0fca6ea1SDimitry Andric                                         emitRawPointerFromAddress(Addr),
349*0fca6ea1SDimitry Andric                                         IdxList, Name),
350*0fca6ea1SDimitry Andric                       ElementType, Align, Addr.isKnownNonNull());
351*0fca6ea1SDimitry Andric   }
352*0fca6ea1SDimitry Andric 
353*0fca6ea1SDimitry Andric   using CGBuilderBaseTy::CreateIsNull;
354*0fca6ea1SDimitry Andric   llvm::Value *CreateIsNull(Address Addr, const Twine &Name = "") {
355*0fca6ea1SDimitry Andric     if (!Addr.hasOffset())
356*0fca6ea1SDimitry Andric       return CreateIsNull(Addr.getBasePointer(), Name);
357*0fca6ea1SDimitry Andric     // The pointer isn't null if Addr has an offset since offsets can always
358*0fca6ea1SDimitry Andric     // be applied inbound.
359*0fca6ea1SDimitry Andric     return llvm::ConstantInt::getFalse(Context);
3600b57cec5SDimitry Andric   }
3610b57cec5SDimitry Andric 
3620b57cec5SDimitry Andric   using CGBuilderBaseTy::CreateMemCpy;
3630b57cec5SDimitry Andric   llvm::CallInst *CreateMemCpy(Address Dest, Address Src, llvm::Value *Size,
3640b57cec5SDimitry Andric                                bool IsVolatile = false) {
365*0fca6ea1SDimitry Andric     llvm::Value *DestPtr = emitRawPointerFromAddress(Dest);
366*0fca6ea1SDimitry Andric     llvm::Value *SrcPtr = emitRawPointerFromAddress(Src);
367*0fca6ea1SDimitry Andric     return CreateMemCpy(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr,
368*0fca6ea1SDimitry Andric                         Src.getAlignment().getAsAlign(), Size, IsVolatile);
3690b57cec5SDimitry Andric   }
3700b57cec5SDimitry Andric   llvm::CallInst *CreateMemCpy(Address Dest, Address Src, uint64_t Size,
3710b57cec5SDimitry Andric                                bool IsVolatile = false) {
372*0fca6ea1SDimitry Andric     llvm::Value *DestPtr = emitRawPointerFromAddress(Dest);
373*0fca6ea1SDimitry Andric     llvm::Value *SrcPtr = emitRawPointerFromAddress(Src);
374*0fca6ea1SDimitry Andric     return CreateMemCpy(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr,
375*0fca6ea1SDimitry Andric                         Src.getAlignment().getAsAlign(), Size, IsVolatile);
3760b57cec5SDimitry Andric   }
3770b57cec5SDimitry Andric 
3785ffd83dbSDimitry Andric   using CGBuilderBaseTy::CreateMemCpyInline;
3795ffd83dbSDimitry Andric   llvm::CallInst *CreateMemCpyInline(Address Dest, Address Src, uint64_t Size) {
380*0fca6ea1SDimitry Andric     llvm::Value *DestPtr = emitRawPointerFromAddress(Dest);
381*0fca6ea1SDimitry Andric     llvm::Value *SrcPtr = emitRawPointerFromAddress(Src);
382*0fca6ea1SDimitry Andric     return CreateMemCpyInline(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr,
3835ffd83dbSDimitry Andric                               Src.getAlignment().getAsAlign(), getInt64(Size));
3845ffd83dbSDimitry Andric   }
3855ffd83dbSDimitry Andric 
3860b57cec5SDimitry Andric   using CGBuilderBaseTy::CreateMemMove;
3870b57cec5SDimitry Andric   llvm::CallInst *CreateMemMove(Address Dest, Address Src, llvm::Value *Size,
3880b57cec5SDimitry Andric                                 bool IsVolatile = false) {
389*0fca6ea1SDimitry Andric     llvm::Value *DestPtr = emitRawPointerFromAddress(Dest);
390*0fca6ea1SDimitry Andric     llvm::Value *SrcPtr = emitRawPointerFromAddress(Src);
391*0fca6ea1SDimitry Andric     return CreateMemMove(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr,
392*0fca6ea1SDimitry Andric                          Src.getAlignment().getAsAlign(), Size, IsVolatile);
3930b57cec5SDimitry Andric   }
3940b57cec5SDimitry Andric 
3950b57cec5SDimitry Andric   using CGBuilderBaseTy::CreateMemSet;
3960b57cec5SDimitry Andric   llvm::CallInst *CreateMemSet(Address Dest, llvm::Value *Value,
3970b57cec5SDimitry Andric                                llvm::Value *Size, bool IsVolatile = false) {
398*0fca6ea1SDimitry Andric     return CreateMemSet(emitRawPointerFromAddress(Dest), Value, Size,
399480093f4SDimitry Andric                         Dest.getAlignment().getAsAlign(), IsVolatile);
4000b57cec5SDimitry Andric   }
4010b57cec5SDimitry Andric 
40281ad6265SDimitry Andric   using CGBuilderBaseTy::CreateMemSetInline;
40381ad6265SDimitry Andric   llvm::CallInst *CreateMemSetInline(Address Dest, llvm::Value *Value,
40481ad6265SDimitry Andric                                      uint64_t Size) {
405*0fca6ea1SDimitry Andric     return CreateMemSetInline(emitRawPointerFromAddress(Dest),
40681ad6265SDimitry Andric                               Dest.getAlignment().getAsAlign(), Value,
40781ad6265SDimitry Andric                               getInt64(Size));
40881ad6265SDimitry Andric   }
40981ad6265SDimitry Andric 
4100b57cec5SDimitry Andric   using CGBuilderBaseTy::CreatePreserveStructAccessIndex;
41181ad6265SDimitry Andric   Address CreatePreserveStructAccessIndex(Address Addr, unsigned Index,
4120b57cec5SDimitry Andric                                           unsigned FieldIndex,
4130b57cec5SDimitry Andric                                           llvm::MDNode *DbgInfo) {
4140b57cec5SDimitry Andric     llvm::StructType *ElTy = cast<llvm::StructType>(Addr.getElementType());
415*0fca6ea1SDimitry Andric     const llvm::DataLayout &DL = BB->getDataLayout();
4160b57cec5SDimitry Andric     const llvm::StructLayout *Layout = DL.getStructLayout(ElTy);
4170b57cec5SDimitry Andric     auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index));
4180b57cec5SDimitry Andric 
419*0fca6ea1SDimitry Andric     return Address(
420*0fca6ea1SDimitry Andric         CreatePreserveStructAccessIndex(ElTy, emitRawPointerFromAddress(Addr),
4210b57cec5SDimitry Andric                                         Index, FieldIndex, DbgInfo),
4220eae32dcSDimitry Andric         ElTy->getElementType(Index),
4230b57cec5SDimitry Andric         Addr.getAlignment().alignmentAtOffset(Offset));
4240b57cec5SDimitry Andric   }
4250eae32dcSDimitry Andric 
426*0fca6ea1SDimitry Andric   using CGBuilderBaseTy::CreatePreserveUnionAccessIndex;
427*0fca6ea1SDimitry Andric   Address CreatePreserveUnionAccessIndex(Address Addr, unsigned FieldIndex,
428*0fca6ea1SDimitry Andric                                          llvm::MDNode *DbgInfo) {
429*0fca6ea1SDimitry Andric     Addr.replaceBasePointer(CreatePreserveUnionAccessIndex(
430*0fca6ea1SDimitry Andric         Addr.getBasePointer(), FieldIndex, DbgInfo));
431*0fca6ea1SDimitry Andric     return Addr;
432*0fca6ea1SDimitry Andric   }
433*0fca6ea1SDimitry Andric 
4340eae32dcSDimitry Andric   using CGBuilderBaseTy::CreateLaunderInvariantGroup;
4350eae32dcSDimitry Andric   Address CreateLaunderInvariantGroup(Address Addr) {
436*0fca6ea1SDimitry Andric     Addr.replaceBasePointer(CreateLaunderInvariantGroup(Addr.getBasePointer()));
437*0fca6ea1SDimitry Andric     return Addr;
438*0fca6ea1SDimitry Andric   }
439*0fca6ea1SDimitry Andric 
440*0fca6ea1SDimitry Andric   using CGBuilderBaseTy::CreateStripInvariantGroup;
441*0fca6ea1SDimitry Andric   Address CreateStripInvariantGroup(Address Addr) {
442*0fca6ea1SDimitry Andric     Addr.replaceBasePointer(CreateStripInvariantGroup(Addr.getBasePointer()));
443*0fca6ea1SDimitry Andric     return Addr;
4440eae32dcSDimitry Andric   }
4450b57cec5SDimitry Andric };
4460b57cec5SDimitry Andric 
4470b57cec5SDimitry Andric } // end namespace CodeGen
4480b57cec5SDimitry Andric } // end namespace clang
4490b57cec5SDimitry Andric 
4500b57cec5SDimitry Andric #endif
451