/Users/buildslave/jenkins/workspace/coverage/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 | 2.12k | CGBuilderInserter() = default; |
29 | 315k | 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 | 338 | : CGBuilderBaseTy(C), TypeCache(TypeCache) {} |
53 | | CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::LLVMContext &C, |
54 | | const llvm::ConstantFolder &F, |
55 | | const CGBuilderInserterTy &Inserter) |
56 | 315k | : CGBuilderBaseTy(C, F, Inserter), TypeCache(TypeCache) {} |
57 | | CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::Instruction *I) |
58 | 198 | : CGBuilderBaseTy(I), TypeCache(TypeCache) {} |
59 | | CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::BasicBlock *BB) |
60 | 1.58k | : CGBuilderBaseTy(BB), TypeCache(TypeCache) {} |
61 | | |
62 | 111k | llvm::ConstantInt *getSize(CharUnits N) { |
63 | 111k | return llvm::ConstantInt::get(TypeCache.SizeTy, N.getQuantity()); |
64 | 111k | } |
65 | 109k | llvm::ConstantInt *getSize(uint64_t N) { |
66 | 109k | return llvm::ConstantInt::get(TypeCache.SizeTy, N); |
67 | 109k | } |
68 | | |
69 | | // Note that we intentionally hide the CreateLoad APIs that don't |
70 | | // take an alignment. |
71 | 92.0k | llvm::LoadInst *CreateLoad(Address Addr, const llvm::Twine &Name = "") { |
72 | 92.0k | return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(), |
73 | 92.0k | Addr.getAlignment().getAsAlign(), Name); |
74 | 92.0k | } |
75 | 118k | 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 | 118k | return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(), |
79 | 118k | Addr.getAlignment().getAsAlign(), Name); |
80 | 118k | } |
81 | | llvm::LoadInst *CreateLoad(Address Addr, bool IsVolatile, |
82 | 1.30M | const llvm::Twine &Name = "") { |
83 | 1.30M | return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(), |
84 | 1.30M | Addr.getAlignment().getAsAlign(), IsVolatile, |
85 | 1.30M | Name); |
86 | 1.30M | } |
87 | | |
88 | | using CGBuilderBaseTy::CreateAlignedLoad; |
89 | | llvm::LoadInst *CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr, |
90 | | CharUnits Align, |
91 | 26.8k | const llvm::Twine &Name = "") { |
92 | 26.8k | assert(llvm::cast<llvm::PointerType>(Addr->getType()) |
93 | 26.8k | ->isOpaqueOrPointeeTypeMatches(Ty)); |
94 | 0 | return CreateAlignedLoad(Ty, Addr, Align.getAsAlign(), Name); |
95 | 26.8k | } |
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 | 1.26M | bool IsVolatile = false) { |
101 | 1.26M | return CreateAlignedStore(Val, Addr.getPointer(), |
102 | 1.26M | Addr.getAlignment().getAsAlign(), IsVolatile); |
103 | 1.26M | } |
104 | | |
105 | | using CGBuilderBaseTy::CreateAlignedStore; |
106 | | llvm::StoreInst *CreateAlignedStore(llvm::Value *Val, llvm::Value *Addr, |
107 | | CharUnits Align, |
108 | 6.72k | bool IsVolatile = false) { |
109 | 6.72k | return CreateAlignedStore(Val, Addr, Align.getAsAlign(), IsVolatile); |
110 | 6.72k | } |
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 | 981 | bool IsVolatile = false) { |
117 | 981 | return CGBuilderBaseTy::CreateStore(Val, Addr, IsVolatile); |
118 | 981 | } |
119 | | |
120 | | /// Emit a load from an i1 flag variable. |
121 | | llvm::LoadInst *CreateFlagLoad(llvm::Value *Addr, |
122 | 239 | const llvm::Twine &Name = "") { |
123 | 239 | assert(llvm::cast<llvm::PointerType>(Addr->getType()) |
124 | 239 | ->isOpaqueOrPointeeTypeMatches(getInt1Ty())); |
125 | 0 | return CreateAlignedLoad(getInt1Ty(), Addr, CharUnits::One(), Name); |
126 | 239 | } |
127 | | |
128 | | /// Emit a store to an i1 flag variable. |
129 | 247 | llvm::StoreInst *CreateFlagStore(bool Value, llvm::Value *Addr) { |
130 | 247 | assert(llvm::cast<llvm::PointerType>(Addr->getType()) |
131 | 247 | ->isOpaqueOrPointeeTypeMatches(getInt1Ty())); |
132 | 0 | return CreateAlignedStore(getInt1(Value), Addr, CharUnits::One()); |
133 | 247 | } |
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 | 550 | llvm::SyncScope::ID SSID = llvm::SyncScope::System) { |
142 | 550 | return CGBuilderBaseTy::CreateAtomicCmpXchg( |
143 | 550 | Ptr, Cmp, New, llvm::MaybeAlign(), SuccessOrdering, FailureOrdering, |
144 | 550 | SSID); |
145 | 550 | } |
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 | 2.21k | llvm::SyncScope::ID SSID = llvm::SyncScope::System) { |
153 | 2.21k | return CGBuilderBaseTy::CreateAtomicRMW(Op, Ptr, Val, llvm::MaybeAlign(), |
154 | 2.21k | Ordering, SSID); |
155 | 2.21k | } |
156 | | |
157 | | using CGBuilderBaseTy::CreateAddrSpaceCast; |
158 | | Address CreateAddrSpaceCast(Address Addr, llvm::Type *Ty, |
159 | 5 | const llvm::Twine &Name = "") { |
160 | 5 | assert(cast<llvm::PointerType>(Ty)->isOpaqueOrPointeeTypeMatches( |
161 | 5 | Addr.getElementType()) && |
162 | 5 | "Should not change the element type"); |
163 | 0 | return Addr.withPointer(CreateAddrSpaceCast(Addr.getPointer(), Ty, Name)); |
164 | 5 | } |
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 | 568k | const llvm::Twine &Name = "") { |
170 | 568k | auto *PtrTy = Ty->getPointerTo(Addr.getAddressSpace()); |
171 | 568k | return Address(CreateBitCast(Addr.getPointer(), PtrTy, Name), Ty, |
172 | 568k | Addr.getAlignment()); |
173 | 568k | } |
174 | | |
175 | | using CGBuilderBaseTy::CreatePointerBitCastOrAddrSpaceCast; |
176 | | Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty, |
177 | | llvm::Type *ElementTy, |
178 | 2.10k | const llvm::Twine &Name = "") { |
179 | 2.10k | llvm::Value *Ptr = |
180 | 2.10k | CreatePointerBitCastOrAddrSpaceCast(Addr.getPointer(), Ty, Name); |
181 | 2.10k | return Address(Ptr, ElementTy, Addr.getAlignment()); |
182 | 2.10k | } |
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 | 277k | const llvm::Twine &Name = "") { |
194 | 277k | llvm::StructType *ElTy = cast<llvm::StructType>(Addr.getElementType()); |
195 | 277k | const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); |
196 | 277k | const llvm::StructLayout *Layout = DL.getStructLayout(ElTy); |
197 | 277k | auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index)); |
198 | | |
199 | 277k | return Address( |
200 | 277k | CreateStructGEP(Addr.getElementType(), Addr.getPointer(), Index, Name), |
201 | 277k | ElTy->getElementType(Index), |
202 | 277k | Addr.getAlignment().alignmentAtOffset(Offset)); |
203 | 277k | } |
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 | 107k | const llvm::Twine &Name = "") { |
215 | 107k | llvm::ArrayType *ElTy = cast<llvm::ArrayType>(Addr.getElementType()); |
216 | 107k | const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); |
217 | 107k | CharUnits EltSize = |
218 | 107k | CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy->getElementType())); |
219 | | |
220 | 107k | return Address( |
221 | 107k | CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(), |
222 | 107k | {getSize(CharUnits::Zero()), getSize(Index)}, Name), |
223 | 107k | ElTy->getElementType(), |
224 | 107k | Addr.getAlignment().alignmentAtOffset(Index * EltSize)); |
225 | 107k | } |
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 | 356 | const llvm::Twine &Name = "") { |
234 | 356 | llvm::Type *ElTy = Addr.getElementType(); |
235 | 356 | const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); |
236 | 356 | CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy)); |
237 | | |
238 | 356 | return Address(CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(), |
239 | 356 | getSize(Index), Name), |
240 | 356 | ElTy, |
241 | 356 | Addr.getAlignment().alignmentAtOffset(Index * EltSize)); |
242 | 356 | } |
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 | 1.19k | const llvm::Twine &Name = "") { |
251 | 1.19k | const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); |
252 | 1.19k | CharUnits EltSize = |
253 | 1.19k | CharUnits::fromQuantity(DL.getTypeAllocSize(Addr.getElementType())); |
254 | | |
255 | 1.19k | return Address(CreateGEP(Addr.getElementType(), Addr.getPointer(), |
256 | 1.19k | getSize(Index), Name), |
257 | 1.19k | Addr.getElementType(), |
258 | 1.19k | Addr.getAlignment().alignmentAtOffset(Index * EltSize)); |
259 | 1.19k | } |
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 | 54 | const llvm::Twine &Name = "") { |
266 | 54 | const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); |
267 | 54 | CharUnits EltSize = |
268 | 54 | CharUnits::fromQuantity(DL.getTypeAllocSize(Addr.getElementType())); |
269 | | |
270 | 54 | return Address( |
271 | 54 | CreateGEP(Addr.getElementType(), Addr.getPointer(), Index, Name), |
272 | 54 | Addr.getElementType(), |
273 | 54 | Addr.getAlignment().alignmentOfArrayElement(EltSize)); |
274 | 54 | } |
275 | | |
276 | | /// Given a pointer to i8, adjust it by a given constant offset. |
277 | | Address CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset, |
278 | 3.50k | const llvm::Twine &Name = "") { |
279 | 3.50k | assert(Addr.getElementType() == TypeCache.Int8Ty); |
280 | 0 | return Address(CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(), |
281 | 3.50k | getSize(Offset), Name), |
282 | 3.50k | Addr.getElementType(), |
283 | 3.50k | Addr.getAlignment().alignmentAtOffset(Offset)); |
284 | 3.50k | } |
285 | | Address CreateConstByteGEP(Address Addr, CharUnits Offset, |
286 | 637 | const llvm::Twine &Name = "") { |
287 | 637 | assert(Addr.getElementType() == TypeCache.Int8Ty); |
288 | 0 | return Address(CreateGEP(Addr.getElementType(), Addr.getPointer(), |
289 | 637 | getSize(Offset), Name), |
290 | 637 | Addr.getElementType(), |
291 | 637 | Addr.getAlignment().alignmentAtOffset(Offset)); |
292 | 637 | } |
293 | | |
294 | | using CGBuilderBaseTy::CreateConstInBoundsGEP2_32; |
295 | | Address CreateConstInBoundsGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1, |
296 | 190 | const llvm::Twine &Name = "") { |
297 | 190 | const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); |
298 | | |
299 | 190 | auto *GEP = cast<llvm::GetElementPtrInst>(CreateConstInBoundsGEP2_32( |
300 | 190 | Addr.getElementType(), Addr.getPointer(), Idx0, Idx1, Name)); |
301 | 190 | llvm::APInt Offset( |
302 | 190 | DL.getIndexSizeInBits(Addr.getType()->getPointerAddressSpace()), 0, |
303 | 190 | /*isSigned=*/true); |
304 | 190 | if (!GEP->accumulateConstantOffset(DL, Offset)) |
305 | 0 | llvm_unreachable("offset of GEP with constants is always computable"); |
306 | 190 | return Address(GEP, GEP->getResultElementType(), |
307 | 190 | Addr.getAlignment().alignmentAtOffset( |
308 | 190 | CharUnits::fromQuantity(Offset.getSExtValue()))); |
309 | 190 | } |
310 | | |
311 | | using CGBuilderBaseTy::CreateMemCpy; |
312 | | llvm::CallInst *CreateMemCpy(Address Dest, Address Src, llvm::Value *Size, |
313 | 16.1k | bool IsVolatile = false) { |
314 | 16.1k | return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getAsAlign(), |
315 | 16.1k | Src.getPointer(), Src.getAlignment().getAsAlign(), Size, |
316 | 16.1k | IsVolatile); |
317 | 16.1k | } |
318 | | llvm::CallInst *CreateMemCpy(Address Dest, Address Src, uint64_t Size, |
319 | 381 | bool IsVolatile = false) { |
320 | 381 | return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getAsAlign(), |
321 | 381 | Src.getPointer(), Src.getAlignment().getAsAlign(), Size, |
322 | 381 | IsVolatile); |
323 | 381 | } |
324 | | |
325 | | using CGBuilderBaseTy::CreateMemCpyInline; |
326 | 4 | llvm::CallInst *CreateMemCpyInline(Address Dest, Address Src, uint64_t Size) { |
327 | 4 | return CreateMemCpyInline( |
328 | 4 | Dest.getPointer(), Dest.getAlignment().getAsAlign(), Src.getPointer(), |
329 | 4 | Src.getAlignment().getAsAlign(), getInt64(Size)); |
330 | 4 | } |
331 | | |
332 | | using CGBuilderBaseTy::CreateMemMove; |
333 | | llvm::CallInst *CreateMemMove(Address Dest, Address Src, llvm::Value *Size, |
334 | 128 | bool IsVolatile = false) { |
335 | 128 | return CreateMemMove(Dest.getPointer(), Dest.getAlignment().getAsAlign(), |
336 | 128 | Src.getPointer(), Src.getAlignment().getAsAlign(), |
337 | 128 | Size, IsVolatile); |
338 | 128 | } |
339 | | |
340 | | using CGBuilderBaseTy::CreateMemSet; |
341 | | llvm::CallInst *CreateMemSet(Address Dest, llvm::Value *Value, |
342 | 2.54k | llvm::Value *Size, bool IsVolatile = false) { |
343 | 2.54k | return CreateMemSet(Dest.getPointer(), Value, Size, |
344 | 2.54k | Dest.getAlignment().getAsAlign(), IsVolatile); |
345 | 2.54k | } |
346 | | |
347 | | using CGBuilderBaseTy::CreateMemSetInline; |
348 | | llvm::CallInst *CreateMemSetInline(Address Dest, llvm::Value *Value, |
349 | 3 | uint64_t Size) { |
350 | 3 | return CreateMemSetInline(Dest.getPointer(), |
351 | 3 | Dest.getAlignment().getAsAlign(), Value, |
352 | 3 | getInt64(Size)); |
353 | 3 | } |
354 | | |
355 | | using CGBuilderBaseTy::CreatePreserveStructAccessIndex; |
356 | | Address CreatePreserveStructAccessIndex(Address Addr, unsigned Index, |
357 | | unsigned FieldIndex, |
358 | 11 | llvm::MDNode *DbgInfo) { |
359 | 11 | llvm::StructType *ElTy = cast<llvm::StructType>(Addr.getElementType()); |
360 | 11 | const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); |
361 | 11 | const llvm::StructLayout *Layout = DL.getStructLayout(ElTy); |
362 | 11 | auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index)); |
363 | | |
364 | 11 | return Address(CreatePreserveStructAccessIndex(ElTy, Addr.getPointer(), |
365 | 11 | Index, FieldIndex, DbgInfo), |
366 | 11 | ElTy->getElementType(Index), |
367 | 11 | Addr.getAlignment().alignmentAtOffset(Offset)); |
368 | 11 | } |
369 | | |
370 | | using CGBuilderBaseTy::CreateLaunderInvariantGroup; |
371 | 11 | Address CreateLaunderInvariantGroup(Address Addr) { |
372 | 11 | return Addr.withPointer(CreateLaunderInvariantGroup(Addr.getPointer())); |
373 | 11 | } |
374 | | }; |
375 | | |
376 | | } // end namespace CodeGen |
377 | | } // end namespace clang |
378 | | |
379 | | #endif |