xref: /freebsd/contrib/llvm-project/clang/lib/CodeGen/CGBuilder.h (revision bc7512cc58af2e8bbe5bbf5ca0059b1daa1da897)
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 "llvm/IR/DataLayout.h"
13 #include "llvm/IR/IRBuilder.h"
14 #include "Address.h"
15 #include "CodeGenTypeCache.h"
16 
17 namespace clang {
18 namespace CodeGen {
19 
20 class CodeGenFunction;
21 
22 /// This is an IRBuilder insertion helper that forwards to
23 /// CodeGenFunction::InsertHelper, which adds necessary metadata to
24 /// instructions.
25 class CGBuilderInserter final : public llvm::IRBuilderDefaultInserter {
26 public:
27   CGBuilderInserter() = default;
28   explicit CGBuilderInserter(CodeGenFunction *CGF) : CGF(CGF) {}
29 
30   /// This forwards to CodeGenFunction::InsertHelper.
31   void InsertHelper(llvm::Instruction *I, const llvm::Twine &Name,
32                     llvm::BasicBlock *BB,
33                     llvm::BasicBlock::iterator InsertPt) const override;
34 private:
35   CodeGenFunction *CGF = nullptr;
36 };
37 
38 typedef CGBuilderInserter CGBuilderInserterTy;
39 
40 typedef llvm::IRBuilder<llvm::ConstantFolder, CGBuilderInserterTy>
41     CGBuilderBaseTy;
42 
43 class CGBuilderTy : public CGBuilderBaseTy {
44   /// Storing a reference to the type cache here makes it a lot easier
45   /// to build natural-feeling, target-specific IR.
46   const CodeGenTypeCache &TypeCache;
47 public:
48   CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::LLVMContext &C)
49     : CGBuilderBaseTy(C), TypeCache(TypeCache) {}
50   CGBuilderTy(const CodeGenTypeCache &TypeCache,
51               llvm::LLVMContext &C, const llvm::ConstantFolder &F,
52               const CGBuilderInserterTy &Inserter)
53     : CGBuilderBaseTy(C, F, Inserter), TypeCache(TypeCache) {}
54   CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::Instruction *I)
55     : CGBuilderBaseTy(I), TypeCache(TypeCache) {}
56   CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::BasicBlock *BB)
57     : CGBuilderBaseTy(BB), TypeCache(TypeCache) {}
58 
59   llvm::ConstantInt *getSize(CharUnits N) {
60     return llvm::ConstantInt::get(TypeCache.SizeTy, N.getQuantity());
61   }
62   llvm::ConstantInt *getSize(uint64_t N) {
63     return llvm::ConstantInt::get(TypeCache.SizeTy, N);
64   }
65 
66   // Note that we intentionally hide the CreateLoad APIs that don't
67   // take an alignment.
68   llvm::LoadInst *CreateLoad(Address Addr, const llvm::Twine &Name = "") {
69     return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(),
70                              Addr.getAlignment().getAsAlign(), Name);
71   }
72   llvm::LoadInst *CreateLoad(Address Addr, const char *Name) {
73     // This overload is required to prevent string literals from
74     // ending up in the IsVolatile overload.
75     return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(),
76                              Addr.getAlignment().getAsAlign(), Name);
77   }
78   llvm::LoadInst *CreateLoad(Address Addr, bool IsVolatile,
79                              const llvm::Twine &Name = "") {
80     return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(),
81                              Addr.getAlignment().getAsAlign(), IsVolatile,
82                              Name);
83   }
84 
85   using CGBuilderBaseTy::CreateAlignedLoad;
86   llvm::LoadInst *CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr,
87                                     CharUnits Align,
88                                     const llvm::Twine &Name = "") {
89     assert(llvm::cast<llvm::PointerType>(Addr->getType())
90                ->isOpaqueOrPointeeTypeMatches(Ty));
91     return CreateAlignedLoad(Ty, Addr, Align.getAsAlign(), Name);
92   }
93 
94   // Note that we intentionally hide the CreateStore APIs that don't
95   // take an alignment.
96   llvm::StoreInst *CreateStore(llvm::Value *Val, Address Addr,
97                                bool IsVolatile = false) {
98     return CreateAlignedStore(Val, Addr.getPointer(),
99                               Addr.getAlignment().getAsAlign(), IsVolatile);
100   }
101 
102   using CGBuilderBaseTy::CreateAlignedStore;
103   llvm::StoreInst *CreateAlignedStore(llvm::Value *Val, llvm::Value *Addr,
104                                       CharUnits Align, bool IsVolatile = false) {
105     return CreateAlignedStore(Val, Addr, Align.getAsAlign(), IsVolatile);
106   }
107 
108   // FIXME: these "default-aligned" APIs should be removed,
109   // but I don't feel like fixing all the builtin code right now.
110   llvm::StoreInst *CreateDefaultAlignedStore(llvm::Value *Val,
111                                              llvm::Value *Addr,
112                                              bool IsVolatile = false) {
113     return CGBuilderBaseTy::CreateStore(Val, Addr, IsVolatile);
114   }
115 
116   /// Emit a load from an i1 flag variable.
117   llvm::LoadInst *CreateFlagLoad(llvm::Value *Addr,
118                                  const llvm::Twine &Name = "") {
119     assert(llvm::cast<llvm::PointerType>(Addr->getType())
120                ->isOpaqueOrPointeeTypeMatches(getInt1Ty()));
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     assert(llvm::cast<llvm::PointerType>(Addr->getType())
127                ->isOpaqueOrPointeeTypeMatches(getInt1Ty()));
128     return CreateAlignedStore(getInt1(Value), Addr, CharUnits::One());
129   }
130 
131   // Temporarily use old signature; clang will be updated to an Address overload
132   // in a subsequent patch.
133   llvm::AtomicCmpXchgInst *
134   CreateAtomicCmpXchg(llvm::Value *Ptr, llvm::Value *Cmp, llvm::Value *New,
135                       llvm::AtomicOrdering SuccessOrdering,
136                       llvm::AtomicOrdering FailureOrdering,
137                       llvm::SyncScope::ID SSID = llvm::SyncScope::System) {
138     return CGBuilderBaseTy::CreateAtomicCmpXchg(
139         Ptr, Cmp, New, llvm::MaybeAlign(), SuccessOrdering, FailureOrdering,
140         SSID);
141   }
142 
143   // Temporarily use old signature; clang will be updated to an Address overload
144   // in a subsequent patch.
145   llvm::AtomicRMWInst *
146   CreateAtomicRMW(llvm::AtomicRMWInst::BinOp Op, llvm::Value *Ptr,
147                   llvm::Value *Val, llvm::AtomicOrdering Ordering,
148                   llvm::SyncScope::ID SSID = llvm::SyncScope::System) {
149     return CGBuilderBaseTy::CreateAtomicRMW(Op, Ptr, Val, llvm::MaybeAlign(),
150                                             Ordering, SSID);
151   }
152 
153   using CGBuilderBaseTy::CreateBitCast;
154   Address CreateBitCast(Address Addr, llvm::Type *Ty,
155                         const llvm::Twine &Name = "") {
156     return Address(CreateBitCast(Addr.getPointer(), Ty, Name),
157                    Addr.getAlignment());
158   }
159 
160   using CGBuilderBaseTy::CreateAddrSpaceCast;
161   Address CreateAddrSpaceCast(Address Addr, llvm::Type *Ty,
162                               const llvm::Twine &Name = "") {
163     return Address(CreateAddrSpaceCast(Addr.getPointer(), Ty, Name),
164                    Addr.getAlignment());
165   }
166 
167   /// Cast the element type of the given address to a different type,
168   /// preserving information like the alignment and address space.
169   Address CreateElementBitCast(Address Addr, llvm::Type *Ty,
170                                const llvm::Twine &Name = "") {
171     auto *PtrTy = Ty->getPointerTo(Addr.getAddressSpace());
172     return Address(CreateBitCast(Addr.getPointer(), PtrTy, Name),
173                    Ty, Addr.getAlignment());
174   }
175 
176   using CGBuilderBaseTy::CreatePointerBitCastOrAddrSpaceCast;
177   Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty,
178                                               const llvm::Twine &Name = "") {
179     llvm::Value *Ptr =
180       CreatePointerBitCastOrAddrSpaceCast(Addr.getPointer(), Ty, Name);
181     return Address(Ptr, 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(CreateStructGEP(Addr.getElementType(),
200                                    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(CreateGEP(Addr.getElementType(), Addr.getPointer(), Index,
271                              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::CreatePreserveStructAccessIndex;
348   Address CreatePreserveStructAccessIndex(Address Addr,
349                                           unsigned Index,
350                                           unsigned FieldIndex,
351                                           llvm::MDNode *DbgInfo) {
352     llvm::StructType *ElTy = cast<llvm::StructType>(Addr.getElementType());
353     const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
354     const llvm::StructLayout *Layout = DL.getStructLayout(ElTy);
355     auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index));
356 
357     return Address(CreatePreserveStructAccessIndex(ElTy, Addr.getPointer(),
358                                                    Index, FieldIndex, DbgInfo),
359                    ElTy->getElementType(Index),
360                    Addr.getAlignment().alignmentAtOffset(Offset));
361   }
362 
363   using CGBuilderBaseTy::CreateLaunderInvariantGroup;
364   Address CreateLaunderInvariantGroup(Address Addr) {
365     return Addr.withPointer(CreateLaunderInvariantGroup(Addr.getPointer()));
366   }
367 };
368 
369 }  // end namespace CodeGen
370 }  // end namespace clang
371 
372 #endif
373