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