xref: /aosp_15_r20/external/clang/lib/CodeGen/CGBuilder.h (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li //===-- CGBuilder.h - Choose IRBuilder implementation  ----------*- C++ -*-===//
2*67e74705SXin Li //
3*67e74705SXin Li //                     The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li 
10*67e74705SXin Li #ifndef LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H
11*67e74705SXin Li #define LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H
12*67e74705SXin Li 
13*67e74705SXin Li #include "llvm/IR/DataLayout.h"
14*67e74705SXin Li #include "llvm/IR/IRBuilder.h"
15*67e74705SXin Li #include "Address.h"
16*67e74705SXin Li #include "CodeGenTypeCache.h"
17*67e74705SXin Li 
18*67e74705SXin Li namespace clang {
19*67e74705SXin Li namespace CodeGen {
20*67e74705SXin Li 
21*67e74705SXin Li class CodeGenFunction;
22*67e74705SXin Li 
23*67e74705SXin Li /// \brief This is an IRBuilder insertion helper that forwards to
24*67e74705SXin Li /// CodeGenFunction::InsertHelper, which adds necessary metadata to
25*67e74705SXin Li /// instructions.
26*67e74705SXin Li class CGBuilderInserter : protected llvm::IRBuilderDefaultInserter {
27*67e74705SXin Li public:
28*67e74705SXin Li   CGBuilderInserter() = default;
CGBuilderInserter(CodeGenFunction * CGF)29*67e74705SXin Li   explicit CGBuilderInserter(CodeGenFunction *CGF) : CGF(CGF) {}
30*67e74705SXin Li 
31*67e74705SXin Li protected:
32*67e74705SXin Li   /// \brief This forwards to CodeGenFunction::InsertHelper.
33*67e74705SXin Li   void InsertHelper(llvm::Instruction *I, const llvm::Twine &Name,
34*67e74705SXin Li                     llvm::BasicBlock *BB,
35*67e74705SXin Li                     llvm::BasicBlock::iterator InsertPt) const;
36*67e74705SXin Li private:
37*67e74705SXin Li   CodeGenFunction *CGF = nullptr;
38*67e74705SXin Li };
39*67e74705SXin Li 
40*67e74705SXin Li typedef CGBuilderInserter CGBuilderInserterTy;
41*67e74705SXin Li 
42*67e74705SXin Li typedef llvm::IRBuilder<llvm::ConstantFolder, CGBuilderInserterTy>
43*67e74705SXin Li     CGBuilderBaseTy;
44*67e74705SXin Li 
45*67e74705SXin Li class CGBuilderTy : public CGBuilderBaseTy {
46*67e74705SXin Li   /// Storing a reference to the type cache here makes it a lot easier
47*67e74705SXin Li   /// to build natural-feeling, target-specific IR.
48*67e74705SXin Li   const CodeGenTypeCache &TypeCache;
49*67e74705SXin Li public:
CGBuilderTy(const CodeGenTypeCache & TypeCache,llvm::LLVMContext & C)50*67e74705SXin Li   CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::LLVMContext &C)
51*67e74705SXin Li     : CGBuilderBaseTy(C), TypeCache(TypeCache) {}
CGBuilderTy(const CodeGenTypeCache & TypeCache,llvm::LLVMContext & C,const llvm::ConstantFolder & F,const CGBuilderInserterTy & Inserter)52*67e74705SXin Li   CGBuilderTy(const CodeGenTypeCache &TypeCache,
53*67e74705SXin Li               llvm::LLVMContext &C, const llvm::ConstantFolder &F,
54*67e74705SXin Li               const CGBuilderInserterTy &Inserter)
55*67e74705SXin Li     : CGBuilderBaseTy(C, F, Inserter), TypeCache(TypeCache) {}
CGBuilderTy(const CodeGenTypeCache & TypeCache,llvm::Instruction * I)56*67e74705SXin Li   CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::Instruction *I)
57*67e74705SXin Li     : CGBuilderBaseTy(I), TypeCache(TypeCache) {}
CGBuilderTy(const CodeGenTypeCache & TypeCache,llvm::BasicBlock * BB)58*67e74705SXin Li   CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::BasicBlock *BB)
59*67e74705SXin Li     : CGBuilderBaseTy(BB), TypeCache(TypeCache) {}
60*67e74705SXin Li 
getSize(CharUnits N)61*67e74705SXin Li   llvm::ConstantInt *getSize(CharUnits N) {
62*67e74705SXin Li     return llvm::ConstantInt::get(TypeCache.SizeTy, N.getQuantity());
63*67e74705SXin Li   }
getSize(uint64_t N)64*67e74705SXin Li   llvm::ConstantInt *getSize(uint64_t N) {
65*67e74705SXin Li     return llvm::ConstantInt::get(TypeCache.SizeTy, N);
66*67e74705SXin Li   }
67*67e74705SXin Li 
68*67e74705SXin Li   // Note that we intentionally hide the CreateLoad APIs that don't
69*67e74705SXin Li   // take an alignment.
70*67e74705SXin Li   llvm::LoadInst *CreateLoad(Address Addr, const llvm::Twine &Name = "") {
71*67e74705SXin Li     return CreateAlignedLoad(Addr.getPointer(),
72*67e74705SXin Li                              Addr.getAlignment().getQuantity(),
73*67e74705SXin Li                              Name);
74*67e74705SXin Li   }
CreateLoad(Address Addr,const char * Name)75*67e74705SXin Li   llvm::LoadInst *CreateLoad(Address Addr, const char *Name) {
76*67e74705SXin Li     // This overload is required to prevent string literals from
77*67e74705SXin Li     // ending up in the IsVolatile overload.
78*67e74705SXin Li     return CreateAlignedLoad(Addr.getPointer(),
79*67e74705SXin Li                              Addr.getAlignment().getQuantity(),
80*67e74705SXin Li                              Name);
81*67e74705SXin Li   }
82*67e74705SXin Li   llvm::LoadInst *CreateLoad(Address Addr, bool IsVolatile,
83*67e74705SXin Li                              const llvm::Twine &Name = "") {
84*67e74705SXin Li     return CreateAlignedLoad(Addr.getPointer(),
85*67e74705SXin Li                              Addr.getAlignment().getQuantity(),
86*67e74705SXin Li                              IsVolatile,
87*67e74705SXin Li                              Name);
88*67e74705SXin Li   }
89*67e74705SXin Li 
90*67e74705SXin Li   using CGBuilderBaseTy::CreateAlignedLoad;
91*67e74705SXin Li   llvm::LoadInst *CreateAlignedLoad(llvm::Value *Addr, CharUnits Align,
92*67e74705SXin Li                                     const llvm::Twine &Name = "") {
93*67e74705SXin Li     return CreateAlignedLoad(Addr, Align.getQuantity(), Name);
94*67e74705SXin Li   }
CreateAlignedLoad(llvm::Value * Addr,CharUnits Align,const char * Name)95*67e74705SXin Li   llvm::LoadInst *CreateAlignedLoad(llvm::Value *Addr, CharUnits Align,
96*67e74705SXin Li                                     const char *Name) {
97*67e74705SXin Li     return CreateAlignedLoad(Addr, Align.getQuantity(), Name);
98*67e74705SXin Li   }
99*67e74705SXin Li   llvm::LoadInst *CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr,
100*67e74705SXin Li                                     CharUnits Align,
101*67e74705SXin Li                                     const llvm::Twine &Name = "") {
102*67e74705SXin Li     assert(Addr->getType()->getPointerElementType() == Ty);
103*67e74705SXin Li     return CreateAlignedLoad(Addr, Align.getQuantity(), Name);
104*67e74705SXin Li   }
105*67e74705SXin Li   llvm::LoadInst *CreateAlignedLoad(llvm::Value *Addr, CharUnits Align,
106*67e74705SXin Li                                     bool IsVolatile,
107*67e74705SXin Li                                     const llvm::Twine &Name = "") {
108*67e74705SXin Li     return CreateAlignedLoad(Addr, Align.getQuantity(), IsVolatile, Name);
109*67e74705SXin Li   }
110*67e74705SXin Li 
111*67e74705SXin Li   // Note that we intentionally hide the CreateStore APIs that don't
112*67e74705SXin Li   // take an alignment.
113*67e74705SXin Li   llvm::StoreInst *CreateStore(llvm::Value *Val, Address Addr,
114*67e74705SXin Li                                bool IsVolatile = false) {
115*67e74705SXin Li     return CreateAlignedStore(Val, Addr.getPointer(),
116*67e74705SXin Li                               Addr.getAlignment().getQuantity(), IsVolatile);
117*67e74705SXin Li   }
118*67e74705SXin Li 
119*67e74705SXin Li   using CGBuilderBaseTy::CreateAlignedStore;
120*67e74705SXin Li   llvm::StoreInst *CreateAlignedStore(llvm::Value *Val, llvm::Value *Addr,
121*67e74705SXin Li                                       CharUnits Align, bool IsVolatile = false) {
122*67e74705SXin Li     return CreateAlignedStore(Val, Addr, Align.getQuantity(), IsVolatile);
123*67e74705SXin Li   }
124*67e74705SXin Li 
125*67e74705SXin Li   // FIXME: these "default-aligned" APIs should be removed,
126*67e74705SXin Li   // but I don't feel like fixing all the builtin code right now.
127*67e74705SXin Li   llvm::LoadInst *CreateDefaultAlignedLoad(llvm::Value *Addr,
128*67e74705SXin Li                                            const llvm::Twine &Name = "") {
129*67e74705SXin Li     return CGBuilderBaseTy::CreateLoad(Addr, false, Name);
130*67e74705SXin Li   }
CreateDefaultAlignedLoad(llvm::Value * Addr,const char * Name)131*67e74705SXin Li   llvm::LoadInst *CreateDefaultAlignedLoad(llvm::Value *Addr,
132*67e74705SXin Li                                            const char *Name) {
133*67e74705SXin Li     return CGBuilderBaseTy::CreateLoad(Addr, false, Name);
134*67e74705SXin Li   }
135*67e74705SXin Li   llvm::LoadInst *CreateDefaultAlignedLoad(llvm::Value *Addr, bool IsVolatile,
136*67e74705SXin Li                                            const llvm::Twine &Name = "") {
137*67e74705SXin Li     return CGBuilderBaseTy::CreateLoad(Addr, IsVolatile, Name);
138*67e74705SXin Li   }
139*67e74705SXin Li 
140*67e74705SXin Li   llvm::StoreInst *CreateDefaultAlignedStore(llvm::Value *Val,
141*67e74705SXin Li                                              llvm::Value *Addr,
142*67e74705SXin Li                                              bool IsVolatile = false) {
143*67e74705SXin Li     return CGBuilderBaseTy::CreateStore(Val, Addr, IsVolatile);
144*67e74705SXin Li   }
145*67e74705SXin Li 
146*67e74705SXin Li   /// Emit a load from an i1 flag variable.
147*67e74705SXin Li   llvm::LoadInst *CreateFlagLoad(llvm::Value *Addr,
148*67e74705SXin Li                                  const llvm::Twine &Name = "") {
149*67e74705SXin Li     assert(Addr->getType()->getPointerElementType() == getInt1Ty());
150*67e74705SXin Li     return CreateAlignedLoad(getInt1Ty(), Addr, CharUnits::One(), Name);
151*67e74705SXin Li   }
152*67e74705SXin Li 
153*67e74705SXin Li   /// Emit a store to an i1 flag variable.
CreateFlagStore(bool Value,llvm::Value * Addr)154*67e74705SXin Li   llvm::StoreInst *CreateFlagStore(bool Value, llvm::Value *Addr) {
155*67e74705SXin Li     assert(Addr->getType()->getPointerElementType() == getInt1Ty());
156*67e74705SXin Li     return CreateAlignedStore(getInt1(Value), Addr, CharUnits::One());
157*67e74705SXin Li   }
158*67e74705SXin Li 
159*67e74705SXin Li   using CGBuilderBaseTy::CreateBitCast;
160*67e74705SXin Li   Address CreateBitCast(Address Addr, llvm::Type *Ty,
161*67e74705SXin Li                         const llvm::Twine &Name = "") {
162*67e74705SXin Li     return Address(CreateBitCast(Addr.getPointer(), Ty, Name),
163*67e74705SXin Li                    Addr.getAlignment());
164*67e74705SXin Li   }
165*67e74705SXin Li 
166*67e74705SXin Li   /// Cast the element type of the given address to a different type,
167*67e74705SXin Li   /// preserving information like the alignment and address space.
168*67e74705SXin Li   Address CreateElementBitCast(Address Addr, llvm::Type *Ty,
169*67e74705SXin Li                                const llvm::Twine &Name = "") {
170*67e74705SXin Li     auto PtrTy = Ty->getPointerTo(Addr.getAddressSpace());
171*67e74705SXin Li     return CreateBitCast(Addr, PtrTy, Name);
172*67e74705SXin Li   }
173*67e74705SXin Li 
174*67e74705SXin Li   using CGBuilderBaseTy::CreatePointerBitCastOrAddrSpaceCast;
175*67e74705SXin Li   Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty,
176*67e74705SXin Li                                               const llvm::Twine &Name = "") {
177*67e74705SXin Li     llvm::Value *Ptr =
178*67e74705SXin Li       CreatePointerBitCastOrAddrSpaceCast(Addr.getPointer(), Ty, Name);
179*67e74705SXin Li     return Address(Ptr, Addr.getAlignment());
180*67e74705SXin Li   }
181*67e74705SXin Li 
182*67e74705SXin Li   using CGBuilderBaseTy::CreateStructGEP;
183*67e74705SXin Li   Address CreateStructGEP(Address Addr, unsigned Index, CharUnits Offset,
184*67e74705SXin Li                           const llvm::Twine &Name = "") {
185*67e74705SXin Li     return Address(CreateStructGEP(Addr.getElementType(),
186*67e74705SXin Li                                    Addr.getPointer(), Index, Name),
187*67e74705SXin Li                    Addr.getAlignment().alignmentAtOffset(Offset));
188*67e74705SXin Li   }
189*67e74705SXin Li   Address CreateStructGEP(Address Addr, unsigned Index,
190*67e74705SXin Li                           const llvm::StructLayout *Layout,
191*67e74705SXin Li                           const llvm::Twine &Name = "") {
192*67e74705SXin Li     auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index));
193*67e74705SXin Li     return CreateStructGEP(Addr, Index, Offset, Name);
194*67e74705SXin Li   }
195*67e74705SXin Li 
196*67e74705SXin Li   /// Given
197*67e74705SXin Li   ///   %addr = [n x T]* ...
198*67e74705SXin Li   /// produce
199*67e74705SXin Li   ///   %name = getelementptr inbounds %addr, i64 0, i64 index
200*67e74705SXin Li   /// where i64 is actually the target word size.
201*67e74705SXin Li   ///
202*67e74705SXin Li   /// This API assumes that drilling into an array like this is always
203*67e74705SXin Li   /// an inbounds operation.
204*67e74705SXin Li   ///
205*67e74705SXin Li   /// \param EltSize - the size of the type T in bytes
206*67e74705SXin Li   Address CreateConstArrayGEP(Address Addr, uint64_t Index, CharUnits EltSize,
207*67e74705SXin Li                               const llvm::Twine &Name = "") {
208*67e74705SXin Li     return Address(CreateInBoundsGEP(Addr.getPointer(),
209*67e74705SXin Li                                      {getSize(CharUnits::Zero()),
210*67e74705SXin Li                                       getSize(Index)},
211*67e74705SXin Li                                      Name),
212*67e74705SXin Li                    Addr.getAlignment().alignmentAtOffset(Index * EltSize));
213*67e74705SXin Li   }
214*67e74705SXin Li 
215*67e74705SXin Li   /// Given
216*67e74705SXin Li   ///   %addr = T* ...
217*67e74705SXin Li   /// produce
218*67e74705SXin Li   ///   %name = getelementptr inbounds %addr, i64 index
219*67e74705SXin Li   /// where i64 is actually the target word size.
220*67e74705SXin Li   ///
221*67e74705SXin Li   /// \param EltSize - the size of the type T in bytes
222*67e74705SXin Li   Address CreateConstInBoundsGEP(Address Addr, uint64_t Index,
223*67e74705SXin Li                                  CharUnits EltSize,
224*67e74705SXin Li                                  const llvm::Twine &Name = "") {
225*67e74705SXin Li     return Address(CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(),
226*67e74705SXin Li                                      getSize(Index), Name),
227*67e74705SXin Li                    Addr.getAlignment().alignmentAtOffset(Index * EltSize));
228*67e74705SXin Li   }
229*67e74705SXin Li 
230*67e74705SXin Li   /// Given
231*67e74705SXin Li   ///   %addr = T* ...
232*67e74705SXin Li   /// produce
233*67e74705SXin Li   ///   %name = getelementptr inbounds %addr, i64 index
234*67e74705SXin Li   /// where i64 is actually the target word size.
235*67e74705SXin Li   ///
236*67e74705SXin Li   /// \param EltSize - the size of the type T in bytes
237*67e74705SXin Li   Address CreateConstGEP(Address Addr, uint64_t Index, CharUnits EltSize,
238*67e74705SXin Li                          const llvm::Twine &Name = "") {
239*67e74705SXin Li     return Address(CreateGEP(Addr.getElementType(), Addr.getPointer(),
240*67e74705SXin Li                              getSize(Index), Name),
241*67e74705SXin Li                    Addr.getAlignment().alignmentAtOffset(Index * EltSize));
242*67e74705SXin Li   }
243*67e74705SXin Li 
244*67e74705SXin Li   /// Given a pointer to i8, adjust it by a given constant offset.
245*67e74705SXin Li   Address CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset,
246*67e74705SXin Li                                      const llvm::Twine &Name = "") {
247*67e74705SXin Li     assert(Addr.getElementType() == TypeCache.Int8Ty);
248*67e74705SXin Li     return Address(CreateInBoundsGEP(Addr.getPointer(), getSize(Offset), Name),
249*67e74705SXin Li                    Addr.getAlignment().alignmentAtOffset(Offset));
250*67e74705SXin Li   }
251*67e74705SXin Li   Address CreateConstByteGEP(Address Addr, CharUnits Offset,
252*67e74705SXin Li                              const llvm::Twine &Name = "") {
253*67e74705SXin Li     assert(Addr.getElementType() == TypeCache.Int8Ty);
254*67e74705SXin Li     return Address(CreateGEP(Addr.getPointer(), getSize(Offset), Name),
255*67e74705SXin Li                    Addr.getAlignment().alignmentAtOffset(Offset));
256*67e74705SXin Li   }
257*67e74705SXin Li 
258*67e74705SXin Li   llvm::Value *CreateConstInBoundsByteGEP(llvm::Value *Ptr, CharUnits Offset,
259*67e74705SXin Li                                           const llvm::Twine &Name = "") {
260*67e74705SXin Li     assert(Ptr->getType()->getPointerElementType() == TypeCache.Int8Ty);
261*67e74705SXin Li     return CreateInBoundsGEP(Ptr, getSize(Offset), Name);
262*67e74705SXin Li   }
263*67e74705SXin Li   llvm::Value *CreateConstByteGEP(llvm::Value *Ptr, CharUnits Offset,
264*67e74705SXin Li                                   const llvm::Twine &Name = "") {
265*67e74705SXin Li     assert(Ptr->getType()->getPointerElementType() == TypeCache.Int8Ty);
266*67e74705SXin Li     return CreateGEP(Ptr, getSize(Offset), Name);
267*67e74705SXin Li   }
268*67e74705SXin Li 
269*67e74705SXin Li   using CGBuilderBaseTy::CreateMemCpy;
270*67e74705SXin Li   llvm::CallInst *CreateMemCpy(Address Dest, Address Src, llvm::Value *Size,
271*67e74705SXin Li                                bool IsVolatile = false) {
272*67e74705SXin Li     auto Align = std::min(Dest.getAlignment(), Src.getAlignment());
273*67e74705SXin Li     return CreateMemCpy(Dest.getPointer(), Src.getPointer(), Size,
274*67e74705SXin Li                         Align.getQuantity(), IsVolatile);
275*67e74705SXin Li   }
276*67e74705SXin Li   llvm::CallInst *CreateMemCpy(Address Dest, Address Src, uint64_t Size,
277*67e74705SXin Li                                bool IsVolatile = false) {
278*67e74705SXin Li     auto Align = std::min(Dest.getAlignment(), Src.getAlignment());
279*67e74705SXin Li     return CreateMemCpy(Dest.getPointer(), Src.getPointer(), Size,
280*67e74705SXin Li                         Align.getQuantity(), IsVolatile);
281*67e74705SXin Li   }
282*67e74705SXin Li 
283*67e74705SXin Li   using CGBuilderBaseTy::CreateMemMove;
284*67e74705SXin Li   llvm::CallInst *CreateMemMove(Address Dest, Address Src, llvm::Value *Size,
285*67e74705SXin Li                                 bool IsVolatile = false) {
286*67e74705SXin Li     auto Align = std::min(Dest.getAlignment(), Src.getAlignment());
287*67e74705SXin Li     return CreateMemMove(Dest.getPointer(), Src.getPointer(), Size,
288*67e74705SXin Li                          Align.getQuantity(), IsVolatile);
289*67e74705SXin Li   }
290*67e74705SXin Li 
291*67e74705SXin Li   using CGBuilderBaseTy::CreateMemSet;
292*67e74705SXin Li   llvm::CallInst *CreateMemSet(Address Dest, llvm::Value *Value,
293*67e74705SXin Li                                llvm::Value *Size, bool IsVolatile = false) {
294*67e74705SXin Li     return CreateMemSet(Dest.getPointer(), Value, Size,
295*67e74705SXin Li                         Dest.getAlignment().getQuantity(), IsVolatile);
296*67e74705SXin Li   }
297*67e74705SXin Li };
298*67e74705SXin Li 
299*67e74705SXin Li }  // end namespace CodeGen
300*67e74705SXin Li }  // end namespace clang
301*67e74705SXin Li 
302*67e74705SXin Li #endif
303