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