xref: /freebsd/contrib/llvm-project/clang/lib/CodeGen/CGBuilder.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H
10 #define LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H
11 
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"
20 
21 namespace clang {
22 namespace CodeGen {
23 
24 class CGBuilderTy;
25 class CodeGenFunction;
26 
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;
32 
33 public:
34   CGBuilderInserter() = default;
CGBuilderInserter(CodeGenFunction * CGF)35   explicit CGBuilderInserter(CodeGenFunction *CGF) : CGF(CGF) {}
36 
37   /// This forwards to CodeGenFunction::InsertHelper.
38   void InsertHelper(llvm::Instruction *I, const llvm::Twine &Name,
39                     llvm::BasicBlock::iterator InsertPt) const override;
40 
41 private:
42   CodeGenFunction *CGF = nullptr;
43 };
44 
45 typedef CGBuilderInserter CGBuilderInserterTy;
46 
47 typedef llvm::IRBuilder<llvm::ConstantFolder, CGBuilderInserterTy>
48     CGBuilderBaseTy;
49 
50 class CGBuilderTy : public CGBuilderBaseTy {
51   friend class Address;
52 
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;
56 
getCGF()57   CodeGenFunction *getCGF() const { return getInserter().CGF; }
58 
emitRawPointerFromAddress(Address Addr)59   llvm::Value *emitRawPointerFromAddress(Address Addr) const {
60     return Addr.getBasePointer();
61   }
62 
63   template <bool IsInBounds>
createConstGEP2_32(Address Addr,unsigned Idx0,unsigned Idx1,const llvm::Twine & Name)64   Address createConstGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1,
65                              const llvm::Twine &Name) {
66     const llvm::DataLayout &DL = BB->getDataLayout();
67     llvm::Value *V;
68     if (IsInBounds)
69       V = CreateConstInBoundsGEP2_32(Addr.getElementType(),
70                                      emitRawPointerFromAddress(Addr), Idx0,
71                                      Idx1, Name);
72     else
73       V = CreateConstGEP2_32(Addr.getElementType(),
74                              emitRawPointerFromAddress(Addr), Idx0, Idx1, Name);
75     llvm::APInt Offset(
76         DL.getIndexSizeInBits(Addr.getType()->getPointerAddressSpace()), 0,
77         /*isSigned=*/true);
78     if (!llvm::GEPOperator::accumulateConstantOffset(
79             Addr.getElementType(), {getInt32(Idx0), getInt32(Idx1)}, DL,
80             Offset))
81       llvm_unreachable(
82           "accumulateConstantOffset with constant indices should not fail.");
83     llvm::Type *ElementTy = llvm::GetElementPtrInst::getIndexedType(
84         Addr.getElementType(), {Idx0, Idx1});
85     return Address(V, ElementTy,
86                    Addr.getAlignment().alignmentAtOffset(
87                        CharUnits::fromQuantity(Offset.getSExtValue())),
88                    IsInBounds ? Addr.isKnownNonNull() : NotKnownNonNull);
89   }
90 
91 public:
CGBuilderTy(const CodeGenTypeCache & TypeCache,llvm::LLVMContext & C)92   CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::LLVMContext &C)
93       : CGBuilderBaseTy(C), TypeCache(TypeCache) {}
CGBuilderTy(const CodeGenTypeCache & TypeCache,llvm::LLVMContext & C,const llvm::ConstantFolder & F,const CGBuilderInserterTy & Inserter)94   CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::LLVMContext &C,
95               const llvm::ConstantFolder &F,
96               const CGBuilderInserterTy &Inserter)
97       : CGBuilderBaseTy(C, F, Inserter), TypeCache(TypeCache) {}
CGBuilderTy(const CodeGenTypeCache & TypeCache,llvm::Instruction * I)98   CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::Instruction *I)
99       : CGBuilderBaseTy(I), TypeCache(TypeCache) {}
CGBuilderTy(const CodeGenTypeCache & TypeCache,llvm::BasicBlock * BB)100   CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::BasicBlock *BB)
101       : CGBuilderBaseTy(BB), TypeCache(TypeCache) {}
102 
getSize(CharUnits N)103   llvm::ConstantInt *getSize(CharUnits N) {
104     return llvm::ConstantInt::get(TypeCache.SizeTy, N.getQuantity());
105   }
getSize(uint64_t N)106   llvm::ConstantInt *getSize(uint64_t N) {
107     return llvm::ConstantInt::get(TypeCache.SizeTy, N);
108   }
109 
110   // Note that we intentionally hide the CreateLoad APIs that don't
111   // take an alignment.
112   llvm::LoadInst *CreateLoad(Address Addr, const llvm::Twine &Name = "") {
113     return CreateAlignedLoad(Addr.getElementType(),
114                              emitRawPointerFromAddress(Addr),
115                              Addr.getAlignment().getAsAlign(), Name);
116   }
CreateLoad(Address Addr,const char * Name)117   llvm::LoadInst *CreateLoad(Address Addr, const char *Name) {
118     // This overload is required to prevent string literals from
119     // ending up in the IsVolatile overload.
120     return CreateAlignedLoad(Addr.getElementType(),
121                              emitRawPointerFromAddress(Addr),
122                              Addr.getAlignment().getAsAlign(), Name);
123   }
124   llvm::LoadInst *CreateLoad(Address Addr, bool IsVolatile,
125                              const llvm::Twine &Name = "") {
126     return CreateAlignedLoad(
127         Addr.getElementType(), emitRawPointerFromAddress(Addr),
128         Addr.getAlignment().getAsAlign(), IsVolatile, Name);
129   }
130 
131   using CGBuilderBaseTy::CreateAlignedLoad;
132   llvm::LoadInst *CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr,
133                                     CharUnits Align,
134                                     const llvm::Twine &Name = "") {
135     return CreateAlignedLoad(Ty, Addr, Align.getAsAlign(), Name);
136   }
137 
138   // Note that we intentionally hide the CreateStore APIs that don't
139   // take an alignment.
140   llvm::StoreInst *CreateStore(llvm::Value *Val, Address Addr,
141                                bool IsVolatile = false) {
142     return CreateAlignedStore(Val, emitRawPointerFromAddress(Addr),
143                               Addr.getAlignment().getAsAlign(), IsVolatile);
144   }
145 
146   using CGBuilderBaseTy::CreateAlignedStore;
147   llvm::StoreInst *CreateAlignedStore(llvm::Value *Val, llvm::Value *Addr,
148                                       CharUnits Align,
149                                       bool IsVolatile = false) {
150     return CreateAlignedStore(Val, Addr, Align.getAsAlign(), IsVolatile);
151   }
152 
153   // FIXME: these "default-aligned" APIs should be removed,
154   // but I don't feel like fixing all the builtin code right now.
155   llvm::StoreInst *CreateDefaultAlignedStore(llvm::Value *Val,
156                                              llvm::Value *Addr,
157                                              bool IsVolatile = false) {
158     return CGBuilderBaseTy::CreateStore(Val, Addr, IsVolatile);
159   }
160 
161   /// Emit a load from an i1 flag variable.
162   llvm::LoadInst *CreateFlagLoad(llvm::Value *Addr,
163                                  const llvm::Twine &Name = "") {
164     return CreateAlignedLoad(getInt1Ty(), Addr, CharUnits::One(), Name);
165   }
166 
167   /// Emit a store to an i1 flag variable.
CreateFlagStore(bool Value,llvm::Value * Addr)168   llvm::StoreInst *CreateFlagStore(bool Value, llvm::Value *Addr) {
169     return CreateAlignedStore(getInt1(Value), Addr, CharUnits::One());
170   }
171 
172   llvm::AtomicCmpXchgInst *
173   CreateAtomicCmpXchg(Address Addr, llvm::Value *Cmp, llvm::Value *New,
174                       llvm::AtomicOrdering SuccessOrdering,
175                       llvm::AtomicOrdering FailureOrdering,
176                       llvm::SyncScope::ID SSID = llvm::SyncScope::System) {
177     return CGBuilderBaseTy::CreateAtomicCmpXchg(
178         Addr.emitRawPointer(*getCGF()), Cmp, New,
179         Addr.getAlignment().getAsAlign(), SuccessOrdering, FailureOrdering,
180         SSID);
181   }
182 
183   llvm::AtomicRMWInst *
184   CreateAtomicRMW(llvm::AtomicRMWInst::BinOp Op, Address Addr, llvm::Value *Val,
185                   llvm::AtomicOrdering Ordering,
186                   llvm::SyncScope::ID SSID = llvm::SyncScope::System) {
187     return CGBuilderBaseTy::CreateAtomicRMW(
188         Op, Addr.emitRawPointer(*getCGF()), Val,
189         Addr.getAlignment().getAsAlign(), Ordering, SSID);
190   }
191 
192   using CGBuilderBaseTy::CreateAddrSpaceCast;
193   Address CreateAddrSpaceCast(Address Addr, llvm::Type *Ty,
194                               llvm::Type *ElementTy,
195                               const llvm::Twine &Name = "") {
196     if (!Addr.hasOffset())
197       return Address(CreateAddrSpaceCast(Addr.getBasePointer(), Ty, Name),
198                      ElementTy, Addr.getAlignment(), Addr.getPointerAuthInfo(),
199                      /*Offset=*/nullptr, Addr.isKnownNonNull());
200     // Eagerly force a raw address if these is an offset.
201     return RawAddress(
202         CreateAddrSpaceCast(Addr.emitRawPointer(*getCGF()), Ty, Name),
203         ElementTy, Addr.getAlignment(), Addr.isKnownNonNull());
204   }
205 
206   using CGBuilderBaseTy::CreatePointerBitCastOrAddrSpaceCast;
207   Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty,
208                                               llvm::Type *ElementTy,
209                                               const llvm::Twine &Name = "") {
210     if (Addr.getType()->getAddressSpace() == Ty->getPointerAddressSpace())
211       return Addr.withElementType(ElementTy);
212     return CreateAddrSpaceCast(Addr, Ty, ElementTy, Name);
213   }
214 
215   /// Given
216   ///   %addr = {T1, T2...}* ...
217   /// produce
218   ///   %name = getelementptr inbounds nuw %addr, i32 0, i32 index
219   ///
220   /// This API assumes that drilling into a struct like this is always an
221   /// inbounds and nuw operation.
222   using CGBuilderBaseTy::CreateStructGEP;
223   Address CreateStructGEP(Address Addr, unsigned Index,
224                           const llvm::Twine &Name = "") {
225     llvm::StructType *ElTy = cast<llvm::StructType>(Addr.getElementType());
226     const llvm::DataLayout &DL = BB->getDataLayout();
227     const llvm::StructLayout *Layout = DL.getStructLayout(ElTy);
228     auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index));
229 
230     return Address(CreateStructGEP(Addr.getElementType(), Addr.getBasePointer(),
231                                    Index, Name),
232                    ElTy->getElementType(Index),
233                    Addr.getAlignment().alignmentAtOffset(Offset),
234                    Addr.isKnownNonNull());
235   }
236 
237   /// Given
238   ///   %addr = [n x T]* ...
239   /// produce
240   ///   %name = getelementptr inbounds %addr, i64 0, i64 index
241   /// where i64 is actually the target word size.
242   ///
243   /// This API assumes that drilling into an array like this is always
244   /// an inbounds operation.
245   Address CreateConstArrayGEP(Address Addr, uint64_t Index,
246                               const llvm::Twine &Name = "") {
247     llvm::ArrayType *ElTy = cast<llvm::ArrayType>(Addr.getElementType());
248     const llvm::DataLayout &DL = BB->getDataLayout();
249     CharUnits EltSize =
250         CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy->getElementType()));
251 
252     return Address(
253         CreateInBoundsGEP(Addr.getElementType(), Addr.getBasePointer(),
254                           {getSize(CharUnits::Zero()), getSize(Index)}, Name),
255         ElTy->getElementType(),
256         Addr.getAlignment().alignmentAtOffset(Index * EltSize),
257         Addr.isKnownNonNull());
258   }
259 
260   /// Given
261   ///   %addr = T* ...
262   /// produce
263   ///   %name = getelementptr inbounds %addr, i64 index
264   /// where i64 is actually the target word size.
265   Address CreateConstInBoundsGEP(Address Addr, uint64_t Index,
266                                  const llvm::Twine &Name = "") {
267     llvm::Type *ElTy = Addr.getElementType();
268     const llvm::DataLayout &DL = BB->getDataLayout();
269     CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy));
270 
271     return Address(
272         CreateInBoundsGEP(ElTy, Addr.getBasePointer(), getSize(Index), Name),
273         ElTy, Addr.getAlignment().alignmentAtOffset(Index * EltSize),
274         Addr.isKnownNonNull());
275   }
276 
277   /// Given
278   ///   %addr = T* ...
279   /// produce
280   ///   %name = getelementptr inbounds %addr, i64 index
281   /// where i64 is actually the target word size.
282   Address CreateConstGEP(Address Addr, uint64_t Index,
283                          const llvm::Twine &Name = "") {
284     llvm::Type *ElTy = Addr.getElementType();
285     const llvm::DataLayout &DL = BB->getDataLayout();
286     CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy));
287 
288     return Address(CreateGEP(ElTy, Addr.getBasePointer(), getSize(Index), Name),
289                    Addr.getElementType(),
290                    Addr.getAlignment().alignmentAtOffset(Index * EltSize));
291   }
292 
293   /// Create GEP with single dynamic index. The address alignment is reduced
294   /// according to the element size.
295   using CGBuilderBaseTy::CreateGEP;
296   Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index,
297                     const llvm::Twine &Name = "") {
298     const llvm::DataLayout &DL = BB->getDataLayout();
299     CharUnits EltSize =
300         CharUnits::fromQuantity(DL.getTypeAllocSize(Addr.getElementType()));
301 
302     return Address(
303         CreateGEP(Addr.getElementType(), Addr.emitRawPointer(CGF), Index, Name),
304         Addr.getElementType(),
305         Addr.getAlignment().alignmentOfArrayElement(EltSize));
306   }
307 
308   /// Given a pointer to i8, adjust it by a given constant offset.
309   Address CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset,
310                                      const llvm::Twine &Name = "") {
311     assert(Addr.getElementType() == TypeCache.Int8Ty);
312     return Address(
313         CreateInBoundsGEP(Addr.getElementType(), Addr.getBasePointer(),
314                           getSize(Offset), Name),
315         Addr.getElementType(), Addr.getAlignment().alignmentAtOffset(Offset),
316         Addr.isKnownNonNull());
317   }
318 
319   Address CreateConstByteGEP(Address Addr, CharUnits Offset,
320                              const llvm::Twine &Name = "") {
321     assert(Addr.getElementType() == TypeCache.Int8Ty);
322     return Address(CreateGEP(Addr.getElementType(), Addr.getBasePointer(),
323                              getSize(Offset), Name),
324                    Addr.getElementType(),
325                    Addr.getAlignment().alignmentAtOffset(Offset));
326   }
327 
328   using CGBuilderBaseTy::CreateConstInBoundsGEP2_32;
329   Address CreateConstInBoundsGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1,
330                                      const llvm::Twine &Name = "") {
331     return createConstGEP2_32<true>(Addr, Idx0, Idx1, Name);
332   }
333 
334   using CGBuilderBaseTy::CreateConstGEP2_32;
335   Address CreateConstGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1,
336                              const llvm::Twine &Name = "") {
337     return createConstGEP2_32<false>(Addr, Idx0, Idx1, Name);
338   }
339 
340   Address CreateGEP(Address Addr, ArrayRef<llvm::Value *> IdxList,
341                     llvm::Type *ElementType, CharUnits Align,
342                     const Twine &Name = "",
343                     llvm::GEPNoWrapFlags NW = llvm::GEPNoWrapFlags::none()) {
344     llvm::Value *Ptr = emitRawPointerFromAddress(Addr);
345     return RawAddress(CreateGEP(Addr.getElementType(), Ptr, IdxList, Name, NW),
346                       ElementType, Align);
347   }
348 
349   using CGBuilderBaseTy::CreateInBoundsGEP;
350   Address CreateInBoundsGEP(Address Addr, ArrayRef<llvm::Value *> IdxList,
351                             llvm::Type *ElementType, CharUnits Align,
352                             const Twine &Name = "") {
353     return RawAddress(CreateInBoundsGEP(Addr.getElementType(),
354                                         emitRawPointerFromAddress(Addr),
355                                         IdxList, Name),
356                       ElementType, Align, Addr.isKnownNonNull());
357   }
358 
359   using CGBuilderBaseTy::CreateIsNull;
360   llvm::Value *CreateIsNull(Address Addr, const Twine &Name = "") {
361     if (!Addr.hasOffset())
362       return CreateIsNull(Addr.getBasePointer(), Name);
363     // The pointer isn't null if Addr has an offset since offsets can always
364     // be applied inbound.
365     return llvm::ConstantInt::getFalse(Context);
366   }
367 
368   using CGBuilderBaseTy::CreateMemCpy;
369   llvm::CallInst *CreateMemCpy(Address Dest, Address Src, llvm::Value *Size,
370                                bool IsVolatile = false) {
371     llvm::Value *DestPtr = emitRawPointerFromAddress(Dest);
372     llvm::Value *SrcPtr = emitRawPointerFromAddress(Src);
373     return CreateMemCpy(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr,
374                         Src.getAlignment().getAsAlign(), Size, IsVolatile);
375   }
376   llvm::CallInst *CreateMemCpy(Address Dest, Address Src, uint64_t Size,
377                                bool IsVolatile = false) {
378     llvm::Value *DestPtr = emitRawPointerFromAddress(Dest);
379     llvm::Value *SrcPtr = emitRawPointerFromAddress(Src);
380     return CreateMemCpy(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr,
381                         Src.getAlignment().getAsAlign(), Size, IsVolatile);
382   }
383 
384   using CGBuilderBaseTy::CreateMemCpyInline;
CreateMemCpyInline(Address Dest,Address Src,uint64_t Size)385   llvm::CallInst *CreateMemCpyInline(Address Dest, Address Src, uint64_t Size) {
386     llvm::Value *DestPtr = emitRawPointerFromAddress(Dest);
387     llvm::Value *SrcPtr = emitRawPointerFromAddress(Src);
388     return CreateMemCpyInline(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr,
389                               Src.getAlignment().getAsAlign(), getInt64(Size));
390   }
391 
392   using CGBuilderBaseTy::CreateMemMove;
393   llvm::CallInst *CreateMemMove(Address Dest, Address Src, llvm::Value *Size,
394                                 bool IsVolatile = false) {
395     llvm::Value *DestPtr = emitRawPointerFromAddress(Dest);
396     llvm::Value *SrcPtr = emitRawPointerFromAddress(Src);
397     return CreateMemMove(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr,
398                          Src.getAlignment().getAsAlign(), Size, IsVolatile);
399   }
400 
401   using CGBuilderBaseTy::CreateMemSet;
402   llvm::CallInst *CreateMemSet(Address Dest, llvm::Value *Value,
403                                llvm::Value *Size, bool IsVolatile = false) {
404     return CreateMemSet(emitRawPointerFromAddress(Dest), Value, Size,
405                         Dest.getAlignment().getAsAlign(), IsVolatile);
406   }
407 
408   using CGBuilderBaseTy::CreateMemSetInline;
CreateMemSetInline(Address Dest,llvm::Value * Value,uint64_t Size)409   llvm::CallInst *CreateMemSetInline(Address Dest, llvm::Value *Value,
410                                      uint64_t Size) {
411     return CreateMemSetInline(emitRawPointerFromAddress(Dest),
412                               Dest.getAlignment().getAsAlign(), Value,
413                               getInt64(Size));
414   }
415 
416   using CGBuilderBaseTy::CreatePreserveStructAccessIndex;
CreatePreserveStructAccessIndex(Address Addr,unsigned Index,unsigned FieldIndex,llvm::MDNode * DbgInfo)417   Address CreatePreserveStructAccessIndex(Address Addr, unsigned Index,
418                                           unsigned FieldIndex,
419                                           llvm::MDNode *DbgInfo) {
420     llvm::StructType *ElTy = cast<llvm::StructType>(Addr.getElementType());
421     const llvm::DataLayout &DL = BB->getDataLayout();
422     const llvm::StructLayout *Layout = DL.getStructLayout(ElTy);
423     auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index));
424 
425     return Address(
426         CreatePreserveStructAccessIndex(ElTy, emitRawPointerFromAddress(Addr),
427                                         Index, FieldIndex, DbgInfo),
428         ElTy->getElementType(Index),
429         Addr.getAlignment().alignmentAtOffset(Offset));
430   }
431 
432   using CGBuilderBaseTy::CreatePreserveUnionAccessIndex;
CreatePreserveUnionAccessIndex(Address Addr,unsigned FieldIndex,llvm::MDNode * DbgInfo)433   Address CreatePreserveUnionAccessIndex(Address Addr, unsigned FieldIndex,
434                                          llvm::MDNode *DbgInfo) {
435     Addr.replaceBasePointer(CreatePreserveUnionAccessIndex(
436         Addr.getBasePointer(), FieldIndex, DbgInfo));
437     return Addr;
438   }
439 
440   using CGBuilderBaseTy::CreateLaunderInvariantGroup;
CreateLaunderInvariantGroup(Address Addr)441   Address CreateLaunderInvariantGroup(Address Addr) {
442     Addr.replaceBasePointer(CreateLaunderInvariantGroup(Addr.getBasePointer()));
443     return Addr;
444   }
445 
446   using CGBuilderBaseTy::CreateStripInvariantGroup;
CreateStripInvariantGroup(Address Addr)447   Address CreateStripInvariantGroup(Address Addr) {
448     Addr.replaceBasePointer(CreateStripInvariantGroup(Addr.getBasePointer()));
449     return Addr;
450   }
451 };
452 
453 } // end namespace CodeGen
454 } // end namespace clang
455 
456 #endif
457