/src/llvm-project/clang/lib/CodeGen/CGBuilder.h
Line | Count | Source (jump to first uncovered line) |
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 | 0 | CGBuilderInserter() = default; |
29 | 0 | 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 | 0 | : CGBuilderBaseTy(C), TypeCache(TypeCache) {} |
53 | | CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::LLVMContext &C, |
54 | | const llvm::ConstantFolder &F, |
55 | | const CGBuilderInserterTy &Inserter) |
56 | 0 | : CGBuilderBaseTy(C, F, Inserter), TypeCache(TypeCache) {} |
57 | | CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::Instruction *I) |
58 | 0 | : CGBuilderBaseTy(I), TypeCache(TypeCache) {} |
59 | | CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::BasicBlock *BB) |
60 | 0 | : CGBuilderBaseTy(BB), TypeCache(TypeCache) {} |
61 | | |
62 | 0 | llvm::ConstantInt *getSize(CharUnits N) { |
63 | 0 | return llvm::ConstantInt::get(TypeCache.SizeTy, N.getQuantity()); |
64 | 0 | } |
65 | 0 | llvm::ConstantInt *getSize(uint64_t N) { |
66 | 0 | return llvm::ConstantInt::get(TypeCache.SizeTy, N); |
67 | 0 | } |
68 | | |
69 | | // Note that we intentionally hide the CreateLoad APIs that don't |
70 | | // take an alignment. |
71 | 0 | llvm::LoadInst *CreateLoad(Address Addr, const llvm::Twine &Name = "") { |
72 | 0 | return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(), |
73 | 0 | Addr.getAlignment().getAsAlign(), Name); |
74 | 0 | } |
75 | 0 | 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 | 0 | return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(), |
79 | 0 | Addr.getAlignment().getAsAlign(), Name); |
80 | 0 | } |
81 | | llvm::LoadInst *CreateLoad(Address Addr, bool IsVolatile, |
82 | 0 | const llvm::Twine &Name = "") { |
83 | 0 | return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(), |
84 | 0 | Addr.getAlignment().getAsAlign(), IsVolatile, |
85 | 0 | Name); |
86 | 0 | } |
87 | | |
88 | | using CGBuilderBaseTy::CreateAlignedLoad; |
89 | | llvm::LoadInst *CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr, |
90 | | CharUnits Align, |
91 | 0 | const llvm::Twine &Name = "") { |
92 | 0 | return CreateAlignedLoad(Ty, Addr, Align.getAsAlign(), Name); |
93 | 0 | } |
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 | 0 | bool IsVolatile = false) { |
99 | 0 | return CreateAlignedStore(Val, Addr.getPointer(), |
100 | 0 | Addr.getAlignment().getAsAlign(), IsVolatile); |
101 | 0 | } |
102 | | |
103 | | using CGBuilderBaseTy::CreateAlignedStore; |
104 | | llvm::StoreInst *CreateAlignedStore(llvm::Value *Val, llvm::Value *Addr, |
105 | | CharUnits Align, |
106 | 0 | bool IsVolatile = false) { |
107 | 0 | return CreateAlignedStore(Val, Addr, Align.getAsAlign(), IsVolatile); |
108 | 0 | } |
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 | 0 | bool IsVolatile = false) { |
115 | 0 | return CGBuilderBaseTy::CreateStore(Val, Addr, IsVolatile); |
116 | 0 | } |
117 | | |
118 | | /// Emit a load from an i1 flag variable. |
119 | | llvm::LoadInst *CreateFlagLoad(llvm::Value *Addr, |
120 | 0 | const llvm::Twine &Name = "") { |
121 | 0 | return CreateAlignedLoad(getInt1Ty(), Addr, CharUnits::One(), Name); |
122 | 0 | } |
123 | | |
124 | | /// Emit a store to an i1 flag variable. |
125 | 0 | llvm::StoreInst *CreateFlagStore(bool Value, llvm::Value *Addr) { |
126 | 0 | return CreateAlignedStore(getInt1(Value), Addr, CharUnits::One()); |
127 | 0 | } |
128 | | |
129 | | llvm::AtomicCmpXchgInst * |
130 | | CreateAtomicCmpXchg(Address Addr, llvm::Value *Cmp, llvm::Value *New, |
131 | | llvm::AtomicOrdering SuccessOrdering, |
132 | | llvm::AtomicOrdering FailureOrdering, |
133 | 0 | llvm::SyncScope::ID SSID = llvm::SyncScope::System) { |
134 | 0 | return CGBuilderBaseTy::CreateAtomicCmpXchg( |
135 | 0 | Addr.getPointer(), Cmp, New, Addr.getAlignment().getAsAlign(), |
136 | 0 | SuccessOrdering, FailureOrdering, SSID); |
137 | 0 | } |
138 | | |
139 | | llvm::AtomicRMWInst * |
140 | | CreateAtomicRMW(llvm::AtomicRMWInst::BinOp Op, Address Addr, llvm::Value *Val, |
141 | | llvm::AtomicOrdering Ordering, |
142 | 0 | llvm::SyncScope::ID SSID = llvm::SyncScope::System) { |
143 | 0 | return CGBuilderBaseTy::CreateAtomicRMW(Op, Addr.getPointer(), Val, |
144 | 0 | Addr.getAlignment().getAsAlign(), |
145 | 0 | Ordering, SSID); |
146 | 0 | } |
147 | | |
148 | | using CGBuilderBaseTy::CreateAddrSpaceCast; |
149 | | Address CreateAddrSpaceCast(Address Addr, llvm::Type *Ty, |
150 | 0 | const llvm::Twine &Name = "") { |
151 | 0 | return Addr.withPointer(CreateAddrSpaceCast(Addr.getPointer(), Ty, Name), |
152 | 0 | Addr.isKnownNonNull()); |
153 | 0 | } |
154 | | |
155 | | using CGBuilderBaseTy::CreatePointerBitCastOrAddrSpaceCast; |
156 | | Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty, |
157 | | llvm::Type *ElementTy, |
158 | 0 | const llvm::Twine &Name = "") { |
159 | 0 | llvm::Value *Ptr = |
160 | 0 | CreatePointerBitCastOrAddrSpaceCast(Addr.getPointer(), Ty, Name); |
161 | 0 | return Address(Ptr, ElementTy, Addr.getAlignment(), Addr.isKnownNonNull()); |
162 | 0 | } |
163 | | |
164 | | /// Given |
165 | | /// %addr = {T1, T2...}* ... |
166 | | /// produce |
167 | | /// %name = getelementptr inbounds %addr, i32 0, i32 index |
168 | | /// |
169 | | /// This API assumes that drilling into a struct like this is always an |
170 | | /// inbounds operation. |
171 | | using CGBuilderBaseTy::CreateStructGEP; |
172 | | Address CreateStructGEP(Address Addr, unsigned Index, |
173 | 0 | const llvm::Twine &Name = "") { |
174 | 0 | llvm::StructType *ElTy = cast<llvm::StructType>(Addr.getElementType()); |
175 | 0 | const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); |
176 | 0 | const llvm::StructLayout *Layout = DL.getStructLayout(ElTy); |
177 | 0 | auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index)); |
178 | |
|
179 | 0 | return Address( |
180 | 0 | CreateStructGEP(Addr.getElementType(), Addr.getPointer(), Index, Name), |
181 | 0 | ElTy->getElementType(Index), |
182 | 0 | Addr.getAlignment().alignmentAtOffset(Offset), Addr.isKnownNonNull()); |
183 | 0 | } |
184 | | |
185 | | /// Given |
186 | | /// %addr = [n x T]* ... |
187 | | /// produce |
188 | | /// %name = getelementptr inbounds %addr, i64 0, i64 index |
189 | | /// where i64 is actually the target word size. |
190 | | /// |
191 | | /// This API assumes that drilling into an array like this is always |
192 | | /// an inbounds operation. |
193 | | Address CreateConstArrayGEP(Address Addr, uint64_t Index, |
194 | 0 | const llvm::Twine &Name = "") { |
195 | 0 | llvm::ArrayType *ElTy = cast<llvm::ArrayType>(Addr.getElementType()); |
196 | 0 | const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); |
197 | 0 | CharUnits EltSize = |
198 | 0 | CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy->getElementType())); |
199 | |
|
200 | 0 | return Address( |
201 | 0 | CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(), |
202 | 0 | {getSize(CharUnits::Zero()), getSize(Index)}, Name), |
203 | 0 | ElTy->getElementType(), |
204 | 0 | Addr.getAlignment().alignmentAtOffset(Index * EltSize), |
205 | 0 | Addr.isKnownNonNull()); |
206 | 0 | } |
207 | | |
208 | | /// Given |
209 | | /// %addr = T* ... |
210 | | /// produce |
211 | | /// %name = getelementptr inbounds %addr, i64 index |
212 | | /// where i64 is actually the target word size. |
213 | | Address CreateConstInBoundsGEP(Address Addr, uint64_t Index, |
214 | 0 | const llvm::Twine &Name = "") { |
215 | 0 | llvm::Type *ElTy = Addr.getElementType(); |
216 | 0 | const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); |
217 | 0 | CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy)); |
218 | |
|
219 | 0 | return Address(CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(), |
220 | 0 | getSize(Index), Name), |
221 | 0 | ElTy, Addr.getAlignment().alignmentAtOffset(Index * EltSize), |
222 | 0 | Addr.isKnownNonNull()); |
223 | 0 | } |
224 | | |
225 | | /// Given |
226 | | /// %addr = T* ... |
227 | | /// produce |
228 | | /// %name = getelementptr inbounds %addr, i64 index |
229 | | /// where i64 is actually the target word size. |
230 | | Address CreateConstGEP(Address Addr, uint64_t Index, |
231 | 0 | const llvm::Twine &Name = "") { |
232 | 0 | const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); |
233 | 0 | CharUnits EltSize = |
234 | 0 | CharUnits::fromQuantity(DL.getTypeAllocSize(Addr.getElementType())); |
235 | |
|
236 | 0 | return Address(CreateGEP(Addr.getElementType(), Addr.getPointer(), |
237 | 0 | getSize(Index), Name), |
238 | 0 | Addr.getElementType(), |
239 | 0 | Addr.getAlignment().alignmentAtOffset(Index * EltSize), |
240 | 0 | NotKnownNonNull); |
241 | 0 | } |
242 | | |
243 | | /// Create GEP with single dynamic index. The address alignment is reduced |
244 | | /// according to the element size. |
245 | | using CGBuilderBaseTy::CreateGEP; |
246 | | Address CreateGEP(Address Addr, llvm::Value *Index, |
247 | 0 | const llvm::Twine &Name = "") { |
248 | 0 | const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); |
249 | 0 | CharUnits EltSize = |
250 | 0 | CharUnits::fromQuantity(DL.getTypeAllocSize(Addr.getElementType())); |
251 | |
|
252 | 0 | return Address( |
253 | 0 | CreateGEP(Addr.getElementType(), Addr.getPointer(), Index, Name), |
254 | 0 | Addr.getElementType(), |
255 | 0 | Addr.getAlignment().alignmentOfArrayElement(EltSize), NotKnownNonNull); |
256 | 0 | } |
257 | | |
258 | | /// Given a pointer to i8, adjust it by a given constant offset. |
259 | | Address CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset, |
260 | 0 | const llvm::Twine &Name = "") { |
261 | 0 | assert(Addr.getElementType() == TypeCache.Int8Ty); |
262 | 0 | return Address(CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(), |
263 | 0 | getSize(Offset), Name), |
264 | 0 | Addr.getElementType(), |
265 | 0 | Addr.getAlignment().alignmentAtOffset(Offset), |
266 | 0 | Addr.isKnownNonNull()); |
267 | 0 | } |
268 | | Address CreateConstByteGEP(Address Addr, CharUnits Offset, |
269 | 0 | const llvm::Twine &Name = "") { |
270 | 0 | assert(Addr.getElementType() == TypeCache.Int8Ty); |
271 | 0 | return Address(CreateGEP(Addr.getElementType(), Addr.getPointer(), |
272 | 0 | getSize(Offset), Name), |
273 | 0 | Addr.getElementType(), |
274 | 0 | Addr.getAlignment().alignmentAtOffset(Offset), |
275 | 0 | NotKnownNonNull); |
276 | 0 | } |
277 | | |
278 | | using CGBuilderBaseTy::CreateConstInBoundsGEP2_32; |
279 | | Address CreateConstInBoundsGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1, |
280 | 0 | const llvm::Twine &Name = "") { |
281 | 0 | const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); |
282 | |
|
283 | 0 | auto *GEP = cast<llvm::GetElementPtrInst>(CreateConstInBoundsGEP2_32( |
284 | 0 | Addr.getElementType(), Addr.getPointer(), Idx0, Idx1, Name)); |
285 | 0 | llvm::APInt Offset( |
286 | 0 | DL.getIndexSizeInBits(Addr.getType()->getPointerAddressSpace()), 0, |
287 | 0 | /*isSigned=*/true); |
288 | 0 | if (!GEP->accumulateConstantOffset(DL, Offset)) |
289 | 0 | llvm_unreachable("offset of GEP with constants is always computable"); |
290 | 0 | return Address(GEP, GEP->getResultElementType(), |
291 | 0 | Addr.getAlignment().alignmentAtOffset( |
292 | 0 | CharUnits::fromQuantity(Offset.getSExtValue())), |
293 | 0 | Addr.isKnownNonNull()); |
294 | 0 | } |
295 | | |
296 | | using CGBuilderBaseTy::CreateMemCpy; |
297 | | llvm::CallInst *CreateMemCpy(Address Dest, Address Src, llvm::Value *Size, |
298 | 0 | bool IsVolatile = false) { |
299 | 0 | return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getAsAlign(), |
300 | 0 | Src.getPointer(), Src.getAlignment().getAsAlign(), Size, |
301 | 0 | IsVolatile); |
302 | 0 | } |
303 | | llvm::CallInst *CreateMemCpy(Address Dest, Address Src, uint64_t Size, |
304 | 0 | bool IsVolatile = false) { |
305 | 0 | return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getAsAlign(), |
306 | 0 | Src.getPointer(), Src.getAlignment().getAsAlign(), Size, |
307 | 0 | IsVolatile); |
308 | 0 | } |
309 | | |
310 | | using CGBuilderBaseTy::CreateMemCpyInline; |
311 | 0 | llvm::CallInst *CreateMemCpyInline(Address Dest, Address Src, uint64_t Size) { |
312 | 0 | return CreateMemCpyInline( |
313 | 0 | Dest.getPointer(), Dest.getAlignment().getAsAlign(), Src.getPointer(), |
314 | 0 | Src.getAlignment().getAsAlign(), getInt64(Size)); |
315 | 0 | } |
316 | | |
317 | | using CGBuilderBaseTy::CreateMemMove; |
318 | | llvm::CallInst *CreateMemMove(Address Dest, Address Src, llvm::Value *Size, |
319 | 0 | bool IsVolatile = false) { |
320 | 0 | return CreateMemMove(Dest.getPointer(), Dest.getAlignment().getAsAlign(), |
321 | 0 | Src.getPointer(), Src.getAlignment().getAsAlign(), |
322 | 0 | Size, IsVolatile); |
323 | 0 | } |
324 | | |
325 | | using CGBuilderBaseTy::CreateMemSet; |
326 | | llvm::CallInst *CreateMemSet(Address Dest, llvm::Value *Value, |
327 | 0 | llvm::Value *Size, bool IsVolatile = false) { |
328 | 0 | return CreateMemSet(Dest.getPointer(), Value, Size, |
329 | 0 | Dest.getAlignment().getAsAlign(), IsVolatile); |
330 | 0 | } |
331 | | |
332 | | using CGBuilderBaseTy::CreateMemSetInline; |
333 | | llvm::CallInst *CreateMemSetInline(Address Dest, llvm::Value *Value, |
334 | 0 | uint64_t Size) { |
335 | 0 | return CreateMemSetInline(Dest.getPointer(), |
336 | 0 | Dest.getAlignment().getAsAlign(), Value, |
337 | 0 | getInt64(Size)); |
338 | 0 | } |
339 | | |
340 | | using CGBuilderBaseTy::CreatePreserveStructAccessIndex; |
341 | | Address CreatePreserveStructAccessIndex(Address Addr, unsigned Index, |
342 | | unsigned FieldIndex, |
343 | 0 | llvm::MDNode *DbgInfo) { |
344 | 0 | llvm::StructType *ElTy = cast<llvm::StructType>(Addr.getElementType()); |
345 | 0 | const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); |
346 | 0 | const llvm::StructLayout *Layout = DL.getStructLayout(ElTy); |
347 | 0 | auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index)); |
348 | |
|
349 | 0 | return Address(CreatePreserveStructAccessIndex(ElTy, Addr.getPointer(), |
350 | 0 | Index, FieldIndex, DbgInfo), |
351 | 0 | ElTy->getElementType(Index), |
352 | 0 | Addr.getAlignment().alignmentAtOffset(Offset)); |
353 | 0 | } |
354 | | |
355 | | using CGBuilderBaseTy::CreateLaunderInvariantGroup; |
356 | 0 | Address CreateLaunderInvariantGroup(Address Addr) { |
357 | 0 | return Addr.withPointer(CreateLaunderInvariantGroup(Addr.getPointer()), |
358 | 0 | Addr.isKnownNonNull()); |
359 | 0 | } |
360 | | }; |
361 | | |
362 | | } // end namespace CodeGen |
363 | | } // end namespace clang |
364 | | |
365 | | #endif |