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     assert(llvm::cast<llvm::PointerType>(Addr->getType())
93                ->isOpaqueOrPointeeTypeMatches(Ty));
94     return CreateAlignedLoad(Ty, Addr, Align.getAsAlign(), Name);
95   }
96 
97   // Note that we intentionally hide the CreateStore APIs that don't
98   // take an alignment.
99   llvm::StoreInst *CreateStore(llvm::Value *Val, Address Addr,
100                                bool IsVolatile = false) {
101     return CreateAlignedStore(Val, Addr.getPointer(),
102                               Addr.getAlignment().getAsAlign(), IsVolatile);
103   }
104 
105   using CGBuilderBaseTy::CreateAlignedStore;
106   llvm::StoreInst *CreateAlignedStore(llvm::Value *Val, llvm::Value *Addr,
107                                       CharUnits Align,
108                                       bool IsVolatile = false) {
109     return CreateAlignedStore(Val, Addr, Align.getAsAlign(), IsVolatile);
110   }
111 
112   // FIXME: these "default-aligned" APIs should be removed,
113   // but I don't feel like fixing all the builtin code right now.
114   llvm::StoreInst *CreateDefaultAlignedStore(llvm::Value *Val,
115                                              llvm::Value *Addr,
116                                              bool IsVolatile = false) {
117     return CGBuilderBaseTy::CreateStore(Val, Addr, IsVolatile);
118   }
119 
120   /// Emit a load from an i1 flag variable.
121   llvm::LoadInst *CreateFlagLoad(llvm::Value *Addr,
122                                  const llvm::Twine &Name = "") {
123     assert(llvm::cast<llvm::PointerType>(Addr->getType())
124                ->isOpaqueOrPointeeTypeMatches(getInt1Ty()));
125     return CreateAlignedLoad(getInt1Ty(), Addr, CharUnits::One(), Name);
126   }
127 
128   /// Emit a store to an i1 flag variable.
129   llvm::StoreInst *CreateFlagStore(bool Value, llvm::Value *Addr) {
130     assert(llvm::cast<llvm::PointerType>(Addr->getType())
131                ->isOpaqueOrPointeeTypeMatches(getInt1Ty()));
132     return CreateAlignedStore(getInt1(Value), Addr, CharUnits::One());
133   }
134 
135   // Temporarily use old signature; clang will be updated to an Address overload
136   // in a subsequent patch.
137   llvm::AtomicCmpXchgInst *
138   CreateAtomicCmpXchg(llvm::Value *Ptr, llvm::Value *Cmp, llvm::Value *New,
139                       llvm::AtomicOrdering SuccessOrdering,
140                       llvm::AtomicOrdering FailureOrdering,
141                       llvm::SyncScope::ID SSID = llvm::SyncScope::System) {
142     return CGBuilderBaseTy::CreateAtomicCmpXchg(
143         Ptr, Cmp, New, llvm::MaybeAlign(), SuccessOrdering, FailureOrdering,
144         SSID);
145   }
146 
147   // Temporarily use old signature; clang will be updated to an Address overload
148   // in a subsequent patch.
149   llvm::AtomicRMWInst *
150   CreateAtomicRMW(llvm::AtomicRMWInst::BinOp Op, llvm::Value *Ptr,
151                   llvm::Value *Val, llvm::AtomicOrdering Ordering,
152                   llvm::SyncScope::ID SSID = llvm::SyncScope::System) {
153     return CGBuilderBaseTy::CreateAtomicRMW(Op, Ptr, Val, llvm::MaybeAlign(),
154                                             Ordering, SSID);
155   }
156 
157   using CGBuilderBaseTy::CreateAddrSpaceCast;
158   Address CreateAddrSpaceCast(Address Addr, llvm::Type *Ty,
159                               const llvm::Twine &Name = "") {
160     assert(cast<llvm::PointerType>(Ty)->isOpaqueOrPointeeTypeMatches(
161                Addr.getElementType()) &&
162            "Should not change the element type");
163     return Addr.withPointer(CreateAddrSpaceCast(Addr.getPointer(), Ty, Name));
164   }
165 
166   /// Cast the element type of the given address to a different type,
167   /// preserving information like the alignment and address space.
168   Address CreateElementBitCast(Address Addr, llvm::Type *Ty,
169                                const llvm::Twine &Name = "") {
170     auto *PtrTy = Ty->getPointerTo(Addr.getAddressSpace());
171     return Address(CreateBitCast(Addr.getPointer(), PtrTy, Name), Ty,
172                    Addr.getAlignment());
173   }
174 
175   using CGBuilderBaseTy::CreatePointerBitCastOrAddrSpaceCast;
176   Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty,
177                                               llvm::Type *ElementTy,
178                                               const llvm::Twine &Name = "") {
179     llvm::Value *Ptr =
180         CreatePointerBitCastOrAddrSpaceCast(Addr.getPointer(), Ty, Name);
181     return Address(Ptr, ElementTy, Addr.getAlignment());
182   }
183 
184   /// Given
185   ///   %addr = {T1, T2...}* ...
186   /// produce
187   ///   %name = getelementptr inbounds %addr, i32 0, i32 index
188   ///
189   /// This API assumes that drilling into a struct like this is always an
190   /// inbounds operation.
191   using CGBuilderBaseTy::CreateStructGEP;
192   Address CreateStructGEP(Address Addr, unsigned Index,
193                           const llvm::Twine &Name = "") {
194     llvm::StructType *ElTy = cast<llvm::StructType>(Addr.getElementType());
195     const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
196     const llvm::StructLayout *Layout = DL.getStructLayout(ElTy);
197     auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index));
198 
199     return Address(
200         CreateStructGEP(Addr.getElementType(), Addr.getPointer(), Index, Name),
201         ElTy->getElementType(Index),
202         Addr.getAlignment().alignmentAtOffset(Offset));
203   }
204 
205   /// Given
206   ///   %addr = [n x T]* ...
207   /// produce
208   ///   %name = getelementptr inbounds %addr, i64 0, i64 index
209   /// where i64 is actually the target word size.
210   ///
211   /// This API assumes that drilling into an array like this is always
212   /// an inbounds operation.
213   Address CreateConstArrayGEP(Address Addr, uint64_t Index,
214                               const llvm::Twine &Name = "") {
215     llvm::ArrayType *ElTy = cast<llvm::ArrayType>(Addr.getElementType());
216     const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
217     CharUnits EltSize =
218         CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy->getElementType()));
219 
220     return Address(
221         CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(),
222                           {getSize(CharUnits::Zero()), getSize(Index)}, Name),
223         ElTy->getElementType(),
224         Addr.getAlignment().alignmentAtOffset(Index * EltSize));
225   }
226 
227   /// Given
228   ///   %addr = T* ...
229   /// produce
230   ///   %name = getelementptr inbounds %addr, i64 index
231   /// where i64 is actually the target word size.
232   Address CreateConstInBoundsGEP(Address Addr, uint64_t Index,
233                                  const llvm::Twine &Name = "") {
234     llvm::Type *ElTy = Addr.getElementType();
235     const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
236     CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy));
237 
238     return Address(CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(),
239                                      getSize(Index), Name),
240                    ElTy,
241                    Addr.getAlignment().alignmentAtOffset(Index * EltSize));
242   }
243 
244   /// Given
245   ///   %addr = T* ...
246   /// produce
247   ///   %name = getelementptr inbounds %addr, i64 index
248   /// where i64 is actually the target word size.
249   Address CreateConstGEP(Address Addr, uint64_t 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(CreateGEP(Addr.getElementType(), Addr.getPointer(),
256                              getSize(Index), Name),
257                    Addr.getElementType(),
258                    Addr.getAlignment().alignmentAtOffset(Index * EltSize));
259   }
260 
261   /// Create GEP with single dynamic index. The address alignment is reduced
262   /// according to the element size.
263   using CGBuilderBaseTy::CreateGEP;
264   Address CreateGEP(Address Addr, llvm::Value *Index,
265                     const llvm::Twine &Name = "") {
266     const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
267     CharUnits EltSize =
268         CharUnits::fromQuantity(DL.getTypeAllocSize(Addr.getElementType()));
269 
270     return Address(
271         CreateGEP(Addr.getElementType(), Addr.getPointer(), Index, Name),
272         Addr.getElementType(),
273         Addr.getAlignment().alignmentOfArrayElement(EltSize));
274   }
275 
276   /// Given a pointer to i8, adjust it by a given constant offset.
277   Address CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset,
278                                      const llvm::Twine &Name = "") {
279     assert(Addr.getElementType() == TypeCache.Int8Ty);
280     return Address(CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(),
281                                      getSize(Offset), Name),
282                    Addr.getElementType(),
283                    Addr.getAlignment().alignmentAtOffset(Offset));
284   }
285   Address CreateConstByteGEP(Address Addr, CharUnits Offset,
286                              const llvm::Twine &Name = "") {
287     assert(Addr.getElementType() == TypeCache.Int8Ty);
288     return Address(CreateGEP(Addr.getElementType(), Addr.getPointer(),
289                              getSize(Offset), Name),
290                    Addr.getElementType(),
291                    Addr.getAlignment().alignmentAtOffset(Offset));
292   }
293 
294   using CGBuilderBaseTy::CreateConstInBoundsGEP2_32;
295   Address CreateConstInBoundsGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1,
296                                      const llvm::Twine &Name = "") {
297     const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
298 
299     auto *GEP = cast<llvm::GetElementPtrInst>(CreateConstInBoundsGEP2_32(
300         Addr.getElementType(), Addr.getPointer(), Idx0, Idx1, Name));
301     llvm::APInt Offset(
302         DL.getIndexSizeInBits(Addr.getType()->getPointerAddressSpace()), 0,
303         /*isSigned=*/true);
304     if (!GEP->accumulateConstantOffset(DL, Offset))
305       llvm_unreachable("offset of GEP with constants is always computable");
306     return Address(GEP, GEP->getResultElementType(),
307                    Addr.getAlignment().alignmentAtOffset(
308                        CharUnits::fromQuantity(Offset.getSExtValue())));
309   }
310 
311   using CGBuilderBaseTy::CreateMemCpy;
312   llvm::CallInst *CreateMemCpy(Address Dest, Address Src, llvm::Value *Size,
313                                bool IsVolatile = false) {
314     return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getAsAlign(),
315                         Src.getPointer(), Src.getAlignment().getAsAlign(), Size,
316                         IsVolatile);
317   }
318   llvm::CallInst *CreateMemCpy(Address Dest, Address Src, uint64_t Size,
319                                bool IsVolatile = false) {
320     return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getAsAlign(),
321                         Src.getPointer(), Src.getAlignment().getAsAlign(), Size,
322                         IsVolatile);
323   }
324 
325   using CGBuilderBaseTy::CreateMemCpyInline;
326   llvm::CallInst *CreateMemCpyInline(Address Dest, Address Src, uint64_t Size) {
327     return CreateMemCpyInline(
328         Dest.getPointer(), Dest.getAlignment().getAsAlign(), Src.getPointer(),
329         Src.getAlignment().getAsAlign(), getInt64(Size));
330   }
331 
332   using CGBuilderBaseTy::CreateMemMove;
333   llvm::CallInst *CreateMemMove(Address Dest, Address Src, llvm::Value *Size,
334                                 bool IsVolatile = false) {
335     return CreateMemMove(Dest.getPointer(), Dest.getAlignment().getAsAlign(),
336                          Src.getPointer(), Src.getAlignment().getAsAlign(),
337                          Size, IsVolatile);
338   }
339 
340   using CGBuilderBaseTy::CreateMemSet;
341   llvm::CallInst *CreateMemSet(Address Dest, llvm::Value *Value,
342                                llvm::Value *Size, bool IsVolatile = false) {
343     return CreateMemSet(Dest.getPointer(), Value, Size,
344                         Dest.getAlignment().getAsAlign(), IsVolatile);
345   }
346 
347   using CGBuilderBaseTy::CreateMemSetInline;
348   llvm::CallInst *CreateMemSetInline(Address Dest, llvm::Value *Value,
349                                      uint64_t Size) {
350     return CreateMemSetInline(Dest.getPointer(),
351                               Dest.getAlignment().getAsAlign(), Value,
352                               getInt64(Size));
353   }
354 
355   using CGBuilderBaseTy::CreatePreserveStructAccessIndex;
356   Address CreatePreserveStructAccessIndex(Address Addr, unsigned Index,
357                                           unsigned FieldIndex,
358                                           llvm::MDNode *DbgInfo) {
359     llvm::StructType *ElTy = cast<llvm::StructType>(Addr.getElementType());
360     const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
361     const llvm::StructLayout *Layout = DL.getStructLayout(ElTy);
362     auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index));
363 
364     return Address(CreatePreserveStructAccessIndex(ElTy, Addr.getPointer(),
365                                                    Index, FieldIndex, DbgInfo),
366                    ElTy->getElementType(Index),
367                    Addr.getAlignment().alignmentAtOffset(Offset));
368   }
369 
370   using CGBuilderBaseTy::CreateLaunderInvariantGroup;
371   Address CreateLaunderInvariantGroup(Address Addr) {
372     return Addr.withPointer(CreateLaunderInvariantGroup(Addr.getPointer()));
373   }
374 };
375 
376 } // end namespace CodeGen
377 } // end namespace clang
378 
379 #endif
380