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