Clang Project

clang_source_code/lib/CodeGen/CGBuilder.h
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
17namespace clang {
18namespace CodeGen {
19
20class CodeGenFunction;
21
22/// This is an IRBuilder insertion helper that forwards to
23/// CodeGenFunction::InsertHelper, which adds necessary metadata to
24/// instructions.
25class CGBuilderInserter : protected llvm::IRBuilderDefaultInserter {
26public:
27  CGBuilderInserter() = default;
28  explicit CGBuilderInserter(CodeGenFunction *CGF) : CGF(CGF) {}
29
30protected:
31  /// This forwards to CodeGenFunction::InsertHelper.
32  void InsertHelper(llvm::Instruction *Iconst llvm::Twine &Name,
33                    llvm::BasicBlock *BB,
34                    llvm::BasicBlock::iterator InsertPtconst;
35private:
36  CodeGenFunction *CGF = nullptr;
37};
38
39typedef CGBuilderInserter CGBuilderInserterTy;
40
41typedef llvm::IRBuilder<llvm::ConstantFolder, CGBuilderInserterTy>
42    CGBuilderBaseTy;
43
44class CGBuilderTy : public CGBuilderBaseTy {
45  /// Storing a reference to the type cache here makes it a lot easier
46  /// to build natural-feeling, target-specific IR.
47  const CodeGenTypeCache &TypeCache;
48public:
49  CGBuilderTy(const CodeGenTypeCache &TypeCachellvm::LLVMContext &C)
50    : CGBuilderBaseTy(C), TypeCache(TypeCache) {}
51  CGBuilderTy(const CodeGenTypeCache &TypeCache,
52              llvm::LLVMContext &Cconst llvm::ConstantFolder &F,
53              const CGBuilderInserterTy &Inserter)
54    : CGBuilderBaseTy(C, F, Inserter), TypeCache(TypeCache) {}
55  CGBuilderTy(const CodeGenTypeCache &TypeCachellvm::Instruction *I)
56    : CGBuilderBaseTy(I), TypeCache(TypeCache) {}
57  CGBuilderTy(const CodeGenTypeCache &TypeCachellvm::BasicBlock *BB)
58    : CGBuilderBaseTy(BB), TypeCache(TypeCache) {}
59
60  llvm::ConstantInt *getSize(CharUnits N) {
61    return llvm::ConstantInt::get(TypeCache.SizeTy, N.getQuantity());
62  }
63  llvm::ConstantInt *getSize(uint64_t N) {
64    return llvm::ConstantInt::get(TypeCache.SizeTy, N);
65  }
66
67  // Note that we intentionally hide the CreateLoad APIs that don't
68  // take an alignment.
69  llvm::LoadInst *CreateLoad(Address Addr, const llvm::Twine &Name = "") {
70    return CreateAlignedLoad(Addr.getPointer(),
71                             Addr.getAlignment().getQuantity(),
72                             Name);
73  }
74  llvm::LoadInst *CreateLoad(Address Addr, const char *Name) {
75    // This overload is required to prevent string literals from
76    // ending up in the IsVolatile overload.
77    return CreateAlignedLoad(Addr.getPointer(),
78                             Addr.getAlignment().getQuantity(),
79                             Name);
80  }
81  llvm::LoadInst *CreateLoad(Address Addr, bool IsVolatile,
82                             const llvm::Twine &Name = "") {
83    return CreateAlignedLoad(Addr.getPointer(),
84                             Addr.getAlignment().getQuantity(),
85                             IsVolatile,
86                             Name);
87  }
88
89  using CGBuilderBaseTy::CreateAlignedLoad;
90  llvm::LoadInst *CreateAlignedLoad(llvm::Value *Addr, CharUnits Align,
91                                    const llvm::Twine &Name = "") {
92    return CreateAlignedLoad(Addr, Align.getQuantity(), Name);
93  }
94  llvm::LoadInst *CreateAlignedLoad(llvm::Value *Addr, CharUnits Align,
95                                    const char *Name) {
96    return CreateAlignedLoad(Addr, Align.getQuantity(), Name);
97  }
98  llvm::LoadInst *CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr,
99                                    CharUnits Align,
100                                    const llvm::Twine &Name = "") {
101    getType()->getPointerElementType() == Ty", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGBuilder.h", 101, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Addr->getType()->getPointerElementType() == Ty);
102    return CreateAlignedLoad(Addr, Align.getQuantity(), Name);
103  }
104
105  // Note that we intentionally hide the CreateStore APIs that don't
106  // take an alignment.
107  llvm::StoreInst *CreateStore(llvm::Value *Val, Address Addr,
108                               bool IsVolatile = false) {
109    return CreateAlignedStore(Val, Addr.getPointer(),
110                              Addr.getAlignment().getQuantity(), IsVolatile);
111  }
112
113  using CGBuilderBaseTy::CreateAlignedStore;
114  llvm::StoreInst *CreateAlignedStore(llvm::Value *Val, llvm::Value *Addr,
115                                      CharUnits Align, bool IsVolatile = false) {
116    return CreateAlignedStore(Val, Addr, Align.getQuantity(), IsVolatile);
117  }
118
119  // FIXME: these "default-aligned" APIs should be removed,
120  // but I don't feel like fixing all the builtin code right now.
121  llvm::StoreInst *CreateDefaultAlignedStore(llvm::Value *Val,
122                                             llvm::Value *Addr,
123                                             bool IsVolatile = false) {
124    return CGBuilderBaseTy::CreateStore(Val, Addr, IsVolatile);
125  }
126
127  /// Emit a load from an i1 flag variable.
128  llvm::LoadInst *CreateFlagLoad(llvm::Value *Addr,
129                                 const llvm::Twine &Name = "") {
130    getType()->getPointerElementType() == getInt1Ty()", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGBuilder.h", 130, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Addr->getType()->getPointerElementType() == getInt1Ty());
131    return CreateAlignedLoad(getInt1Ty(), Addr, CharUnits::One(), Name);
132  }
133
134  /// Emit a store to an i1 flag variable.
135  llvm::StoreInst *CreateFlagStore(bool Value, llvm::Value *Addr) {
136    getType()->getPointerElementType() == getInt1Ty()", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CGBuilder.h", 136, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Addr->getType()->getPointerElementType() == getInt1Ty());
137    return CreateAlignedStore(getInt1(Value), Addr, CharUnits::One());
138  }
139
140  using CGBuilderBaseTy::CreateBitCast;
141  Address CreateBitCast(Address Addrllvm::Type *Ty,
142                        const llvm::Twine &Name = "") {
143    return Address(CreateBitCast(Addr.getPointer(), Ty, Name),
144                   Addr.getAlignment());
145  }
146
147  using CGBuilderBaseTy::CreateAddrSpaceCast;
148  Address CreateAddrSpaceCast(Address Addrllvm::Type *Ty,
149                              const llvm::Twine &Name = "") {
150    return Address(CreateAddrSpaceCast(Addr.getPointer(), Ty, Name),
151                   Addr.getAlignment());
152  }
153
154  /// Cast the element type of the given address to a different type,
155  /// preserving information like the alignment and address space.
156  Address CreateElementBitCast(Address Addrllvm::Type *Ty,
157                               const llvm::Twine &Name = "") {
158    auto PtrTy = Ty->getPointerTo(Addr.getAddressSpace());
159    return CreateBitCast(Addr, PtrTy, Name);
160  }
161
162  using CGBuilderBaseTy::CreatePointerBitCastOrAddrSpaceCast;
163  Address CreatePointerBitCastOrAddrSpaceCast(Address Addrllvm::Type *Ty,
164                                              const llvm::Twine &Name = "") {
165    llvm::Value *Ptr =
166      CreatePointerBitCastOrAddrSpaceCast(Addr.getPointer(), Ty, Name);
167    return Address(PtrAddr.getAlignment());
168  }
169
170  /// Given
171  ///   %addr = {T1, T2...}* ...
172  /// produce
173  ///   %name = getelementptr inbounds %addr, i32 0, i32 index
174  ///
175  /// This API assumes that drilling into a struct like this is always an
176  /// inbounds operation.
177  using CGBuilderBaseTy::CreateStructGEP;
178  Address CreateStructGEP(Address Addrunsigned Index,
179                          const llvm::Twine &Name = "") {
180    llvm::StructType *ElTy = cast<llvm::StructType>(Addr.getElementType());
181    const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
182    const llvm::StructLayout *Layout = DL.getStructLayout(ElTy);
183    auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index));
184
185    return Address(CreateStructGEP(Addr.getElementType(),
186                                   Addr.getPointer(), Index, Name),
187                   Addr.getAlignment().alignmentAtOffset(Offset));
188  }
189
190  /// Given
191  ///   %addr = [n x T]* ...
192  /// produce
193  ///   %name = getelementptr inbounds %addr, i64 0, i64 index
194  /// where i64 is actually the target word size.
195  ///
196  /// This API assumes that drilling into an array like this is always
197  /// an inbounds operation.
198  Address CreateConstArrayGEP(Address Addruint64_t Index,
199                              const llvm::Twine &Name = "") {
200    llvm::ArrayType *ElTy = cast<llvm::ArrayType>(Addr.getElementType());
201    const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
202    CharUnits EltSize =
203        CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy->getElementType()));
204
205    return Address(
206        CreateInBoundsGEP(Addr.getPointer(),
207                          {getSize(CharUnits::Zero()), getSize(Index)}, Name),
208        Addr.getAlignment().alignmentAtOffset(Index * EltSize));
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 Addruint64_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                   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 CreateConstGEP(Address Addruint64_t Index,
233                         const llvm::Twine &Name = "") {
234    const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
235    CharUnits EltSize =
236        CharUnits::fromQuantity(DL.getTypeAllocSize(Addr.getElementType()));
237
238    return Address(CreateGEP(Addr.getElementType(), Addr.getPointer(),
239                             getSize(Index), Name),
240                   Addr.getAlignment().alignmentAtOffset(Index * EltSize));
241  }
242
243  /// Given a pointer to i8, adjust it by a given constant offset.
244  Address CreateConstInBoundsByteGEP(Address AddrCharUnits Offset,
245                                     const llvm::Twine &Name = "") {
246    assert(Addr.getElementType() == TypeCache.Int8Ty);
247    return Address(CreateInBoundsGEP(Addr.getPointer(), getSize(Offset), Name),
248                   Addr.getAlignment().alignmentAtOffset(Offset));
249  }
250  Address CreateConstByteGEP(Address AddrCharUnits Offset,
251                             const llvm::Twine &Name = "") {
252    assert(Addr.getElementType() == TypeCache.Int8Ty);
253    return Address(CreateGEP(Addr.getPointer(), getSize(Offset), Name),
254                   Addr.getAlignment().alignmentAtOffset(Offset));
255  }
256
257  using CGBuilderBaseTy::CreateConstInBoundsGEP2_32;
258  Address CreateConstInBoundsGEP2_32(Address Addrunsigned Idx0unsigned Idx1,
259                                     const llvm::Twine &Name = "") {
260    const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout();
261
262    auto *GEP = cast<llvm::GetElementPtrInst>(CreateConstInBoundsGEP2_32(
263        Addr.getElementType(), Addr.getPointer(), Idx0, Idx1, Name));
264    llvm::APInt Offset(
265        DL.getIndexSizeInBits(Addr.getType()->getPointerAddressSpace()), 0,
266        /*IsSigned=*/true);
267    if (!GEP->accumulateConstantOffset(DL, Offset))
268      llvm_unreachable("offset of GEP with constants is always computable");
269    return Address(GEP, Addr.getAlignment().alignmentAtOffset(
270                            CharUnits::fromQuantity(Offset.getSExtValue())));
271  }
272
273  using CGBuilderBaseTy::CreateMemCpy;
274  llvm::CallInst *CreateMemCpy(Address Dest, Address Src, llvm::Value *Size,
275                               bool IsVolatile = false) {
276    return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getQuantity(),
277                        Src.getPointer(), Src.getAlignment().getQuantity(),
278                        Size,IsVolatile);
279  }
280  llvm::CallInst *CreateMemCpy(Address Dest, Address Src, uint64_t Size,
281                               bool IsVolatile = false) {
282    return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getQuantity(),
283                        Src.getPointer(), Src.getAlignment().getQuantity(),
284                        Size, IsVolatile);
285  }
286
287  using CGBuilderBaseTy::CreateMemMove;
288  llvm::CallInst *CreateMemMove(Address Dest, Address Src, llvm::Value *Size,
289                                bool IsVolatile = false) {
290    return CreateMemMove(Dest.getPointer(), Dest.getAlignment().getQuantity(),
291                         Src.getPointer(), Src.getAlignment().getQuantity(),
292                         Size, IsVolatile);
293  }
294
295  using CGBuilderBaseTy::CreateMemSet;
296  llvm::CallInst *CreateMemSet(Address Dest, llvm::Value *Value,
297                               llvm::Value *Size, bool IsVolatile = false) {
298    return CreateMemSet(Dest.getPointer(), Value, Size,
299                        Dest.getAlignment().getQuantity(), IsVolatile);
300  }
301};
302
303}  // end namespace CodeGen
304}  // end namespace clang
305
306#endif
307
clang::CodeGen::CGBuilderInserter::InsertHelper
clang::CodeGen::CGBuilderInserter::CGF
clang::CodeGen::CGBuilderTy::TypeCache
clang::CodeGen::CGBuilderTy::getSize
clang::CodeGen::CGBuilderTy::getSize
clang::CodeGen::CGBuilderTy::CreateLoad
clang::CodeGen::CGBuilderTy::CreateLoad
clang::CodeGen::CGBuilderTy::CreateLoad
clang::CodeGen::CGBuilderTy::CreateAlignedLoad
clang::CodeGen::CGBuilderTy::CreateAlignedLoad
clang::CodeGen::CGBuilderTy::CreateAlignedLoad
clang::CodeGen::CGBuilderTy::CreateStore
clang::CodeGen::CGBuilderTy::CreateAlignedStore
clang::CodeGen::CGBuilderTy::CreateDefaultAlignedStore
clang::CodeGen::CGBuilderTy::CreateFlagLoad
clang::CodeGen::CGBuilderTy::CreateFlagStore
clang::CodeGen::CGBuilderTy::CreateBitCast
clang::CodeGen::CGBuilderTy::CreateAddrSpaceCast
clang::CodeGen::CGBuilderTy::CreateElementBitCast
clang::CodeGen::CGBuilderTy::CreatePointerBitCastOrAddrSpaceCast
clang::CodeGen::CGBuilderTy::CreateStructGEP
clang::CodeGen::CGBuilderTy::CreateConstArrayGEP
clang::CodeGen::CGBuilderTy::CreateConstInBoundsGEP
clang::CodeGen::CGBuilderTy::CreateConstGEP
clang::CodeGen::CGBuilderTy::CreateConstInBoundsByteGEP
clang::CodeGen::CGBuilderTy::CreateConstByteGEP
clang::CodeGen::CGBuilderTy::CreateConstInBoundsGEP2_32
clang::CodeGen::CGBuilderTy::CreateMemCpy
clang::CodeGen::CGBuilderTy::CreateMemCpy
clang::CodeGen::CGBuilderTy::CreateMemMove
clang::CodeGen::CGBuilderTy::CreateMemSet
clang::CodeGen::CGBuilderInserter::InsertHelper
clang::CodeGen::CGBuilderTy::getSize
clang::CodeGen::CGBuilderTy::CreateLoad
clang::CodeGen::CGBuilderTy::CreateLoad
clang::CodeGen::CGBuilderTy::CreateAlignedLoad
clang::CodeGen::CGBuilderTy::CreateAlignedLoad
clang::CodeGen::CGBuilderTy::CreateAlignedLoad
clang::CodeGen::CGBuilderTy::CreateStore
clang::CodeGen::CGBuilderTy::CreateAlignedStore
clang::CodeGen::CGBuilderTy::CreateDefaultAlignedStore
clang::CodeGen::CGBuilderTy::CreateFlagLoad
clang::CodeGen::CGBuilderTy::CreateFlagStore
clang::CodeGen::CGBuilderTy::CreateBitCast
clang::CodeGen::CGBuilderTy::CreateAddrSpaceCast
clang::CodeGen::CGBuilderTy::CreateElementBitCast
clang::CodeGen::CGBuilderTy::CreatePointerBitCastOrAddrSpaceCast
clang::CodeGen::CGBuilderTy::CreateStructGEP
clang::CodeGen::CGBuilderTy::CreateConstArrayGEP
clang::CodeGen::CGBuilderTy::CreateConstInBoundsGEP
clang::CodeGen::CGBuilderTy::CreateConstGEP
clang::CodeGen::CGBuilderTy::CreateConstInBoundsByteGEP
clang::CodeGen::CGBuilderTy::CreateConstByteGEP
clang::CodeGen::CGBuilderTy::CreateConstInBoundsGEP2_32
clang::CodeGen::CGBuilderTy::CreateMemCpy
clang::CodeGen::CGBuilderTy::CreateMemCpy
clang::CodeGen::CGBuilderTy::CreateMemMove
clang::CodeGen::CGBuilderTy::CreateMemSet
clang::CodeGen::CGBuilderInserter::InsertHelper
clang::CodeGen::CGBuilderInserter::InsertHelper
clang::CodeGen::CGBuilderTy::CreateConstArrayGEP
clang::CodeGen::CGBuilderTy::CreateConstInBoundsGEP
clang::CodeGen::CGBuilderTy::CreateConstGEP
clang::CodeGen::CGBuilderTy::CreateAlignedLoad
clang::CodeGen::CGBuilderTy::CreateAlignedLoad
clang::CodeGen::CGBuilderTy::CreateFlagLoad