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 "CGValue.h" |
14 | #include "CodeGenTypeCache.h" |
15 | #include "llvm/Analysis/Utils/Local.h" |
16 | #include "llvm/IR/DataLayout.h" |
17 | #include "llvm/IR/GEPNoWrapFlags.h" |
18 | #include "llvm/IR/IRBuilder.h" |
19 | #include "llvm/IR/Type.h" |
20 | |
21 | namespace clang { |
22 | namespace CodeGen { |
23 | |
24 | class CGBuilderTy; |
25 | class CodeGenFunction; |
26 | |
27 | /// This is an IRBuilder insertion helper that forwards to |
28 | /// CodeGenFunction::InsertHelper, which adds necessary metadata to |
29 | /// instructions. |
30 | class CGBuilderInserter final : public llvm::IRBuilderDefaultInserter { |
31 | friend CGBuilderTy; |
32 | |
33 | public: |
34 | CGBuilderInserter() = default; |
35 | explicit CGBuilderInserter(CodeGenFunction *CGF) : CGF(CGF) {} |
36 | |
37 | /// This forwards to CodeGenFunction::InsertHelper. |
38 | void InsertHelper(llvm::Instruction *I, const llvm::Twine &Name, |
39 | llvm::BasicBlock::iterator InsertPt) const override; |
40 | |
41 | private: |
42 | CodeGenFunction *CGF = nullptr; |
43 | }; |
44 | |
45 | typedef CGBuilderInserter CGBuilderInserterTy; |
46 | |
47 | typedef llvm::IRBuilder<llvm::ConstantFolder, CGBuilderInserterTy> |
48 | CGBuilderBaseTy; |
49 | |
50 | class CGBuilderTy : public CGBuilderBaseTy { |
51 | friend class Address; |
52 | |
53 | /// Storing a reference to the type cache here makes it a lot easier |
54 | /// to build natural-feeling, target-specific IR. |
55 | const CodeGenTypeCache &TypeCache; |
56 | |
57 | CodeGenFunction *getCGF() const { return getInserter().CGF; } |
58 | |
59 | llvm::Value *emitRawPointerFromAddress(Address Addr) const { |
60 | return Addr.getBasePointer(); |
61 | } |
62 | |
63 | template <bool IsInBounds> |
64 | Address createConstGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1, |
65 | const llvm::Twine &Name) { |
66 | const llvm::DataLayout &DL = BB->getDataLayout(); |
67 | llvm::Value *V; |
68 | if (IsInBounds) |
69 | V = CreateConstInBoundsGEP2_32(Ty: Addr.getElementType(), |
70 | Ptr: emitRawPointerFromAddress(Addr), Idx0, |
71 | Idx1, Name); |
72 | else |
73 | V = CreateConstGEP2_32(Ty: Addr.getElementType(), |
74 | Ptr: emitRawPointerFromAddress(Addr), Idx0, Idx1, Name); |
75 | llvm::APInt Offset( |
76 | DL.getIndexSizeInBits(AS: Addr.getType()->getPointerAddressSpace()), 0, |
77 | /*isSigned=*/true); |
78 | if (!llvm::GEPOperator::accumulateConstantOffset( |
79 | SourceType: Addr.getElementType(), Index: {getInt32(C: Idx0), getInt32(C: Idx1)}, DL, |
80 | Offset)) |
81 | llvm_unreachable( |
82 | "accumulateConstantOffset with constant indices should not fail." ); |
83 | llvm::Type *ElementTy = llvm::GetElementPtrInst::getIndexedType( |
84 | Ty: Addr.getElementType(), IdxList: {Idx0, Idx1}); |
85 | return Address(V, ElementTy, |
86 | Addr.getAlignment().alignmentAtOffset( |
87 | offset: CharUnits::fromQuantity(Quantity: Offset.getSExtValue())), |
88 | IsInBounds ? Addr.isKnownNonNull() : NotKnownNonNull); |
89 | } |
90 | |
91 | public: |
92 | CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::LLVMContext &C) |
93 | : CGBuilderBaseTy(C), TypeCache(TypeCache) {} |
94 | CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::LLVMContext &C, |
95 | const llvm::ConstantFolder &F, |
96 | const CGBuilderInserterTy &Inserter) |
97 | : CGBuilderBaseTy(C, F, Inserter), TypeCache(TypeCache) {} |
98 | CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::Instruction *I) |
99 | : CGBuilderBaseTy(I), TypeCache(TypeCache) {} |
100 | CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::BasicBlock *BB) |
101 | : CGBuilderBaseTy(BB), TypeCache(TypeCache) {} |
102 | |
103 | llvm::ConstantInt *getSize(CharUnits N) { |
104 | return llvm::ConstantInt::get(Ty: TypeCache.SizeTy, V: N.getQuantity()); |
105 | } |
106 | llvm::ConstantInt *getSize(uint64_t N) { |
107 | return llvm::ConstantInt::get(Ty: TypeCache.SizeTy, V: N); |
108 | } |
109 | |
110 | // Note that we intentionally hide the CreateLoad APIs that don't |
111 | // take an alignment. |
112 | llvm::LoadInst *CreateLoad(Address Addr, const llvm::Twine &Name = "" ) { |
113 | return CreateAlignedLoad(Ty: Addr.getElementType(), |
114 | Ptr: emitRawPointerFromAddress(Addr), |
115 | Align: Addr.getAlignment().getAsAlign(), Name); |
116 | } |
117 | llvm::LoadInst *CreateLoad(Address Addr, const char *Name) { |
118 | // This overload is required to prevent string literals from |
119 | // ending up in the IsVolatile overload. |
120 | return CreateAlignedLoad(Ty: Addr.getElementType(), |
121 | Ptr: emitRawPointerFromAddress(Addr), |
122 | Align: Addr.getAlignment().getAsAlign(), Name); |
123 | } |
124 | llvm::LoadInst *CreateLoad(Address Addr, bool IsVolatile, |
125 | const llvm::Twine &Name = "" ) { |
126 | return CreateAlignedLoad( |
127 | Ty: Addr.getElementType(), Ptr: emitRawPointerFromAddress(Addr), |
128 | Align: Addr.getAlignment().getAsAlign(), isVolatile: IsVolatile, Name); |
129 | } |
130 | |
131 | using CGBuilderBaseTy::CreateAlignedLoad; |
132 | llvm::LoadInst *CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr, |
133 | CharUnits Align, |
134 | const llvm::Twine &Name = "" ) { |
135 | return CreateAlignedLoad(Ty, Ptr: Addr, Align: Align.getAsAlign(), Name); |
136 | } |
137 | |
138 | // Note that we intentionally hide the CreateStore APIs that don't |
139 | // take an alignment. |
140 | llvm::StoreInst *CreateStore(llvm::Value *Val, Address Addr, |
141 | bool IsVolatile = false) { |
142 | return CreateAlignedStore(Val, Ptr: emitRawPointerFromAddress(Addr), |
143 | Align: Addr.getAlignment().getAsAlign(), isVolatile: IsVolatile); |
144 | } |
145 | |
146 | using CGBuilderBaseTy::CreateAlignedStore; |
147 | llvm::StoreInst *CreateAlignedStore(llvm::Value *Val, llvm::Value *Addr, |
148 | CharUnits Align, |
149 | bool IsVolatile = false) { |
150 | return CreateAlignedStore(Val, Ptr: Addr, Align: Align.getAsAlign(), isVolatile: IsVolatile); |
151 | } |
152 | |
153 | // FIXME: these "default-aligned" APIs should be removed, |
154 | // but I don't feel like fixing all the builtin code right now. |
155 | llvm::StoreInst *CreateDefaultAlignedStore(llvm::Value *Val, |
156 | llvm::Value *Addr, |
157 | bool IsVolatile = false) { |
158 | return CGBuilderBaseTy::CreateStore(Val, Ptr: Addr, isVolatile: IsVolatile); |
159 | } |
160 | |
161 | /// Emit a load from an i1 flag variable. |
162 | llvm::LoadInst *CreateFlagLoad(llvm::Value *Addr, |
163 | const llvm::Twine &Name = "" ) { |
164 | return CreateAlignedLoad(Ty: getInt1Ty(), Addr, Align: CharUnits::One(), Name); |
165 | } |
166 | |
167 | /// Emit a store to an i1 flag variable. |
168 | llvm::StoreInst *CreateFlagStore(bool Value, llvm::Value *Addr) { |
169 | return CreateAlignedStore(Val: getInt1(V: Value), Addr, Align: CharUnits::One()); |
170 | } |
171 | |
172 | llvm::AtomicCmpXchgInst * |
173 | CreateAtomicCmpXchg(Address Addr, llvm::Value *Cmp, llvm::Value *New, |
174 | llvm::AtomicOrdering SuccessOrdering, |
175 | llvm::AtomicOrdering FailureOrdering, |
176 | llvm::SyncScope::ID SSID = llvm::SyncScope::System) { |
177 | return CGBuilderBaseTy::CreateAtomicCmpXchg( |
178 | Ptr: Addr.emitRawPointer(CGF&: *getCGF()), Cmp, New, |
179 | Align: Addr.getAlignment().getAsAlign(), SuccessOrdering, FailureOrdering, |
180 | SSID); |
181 | } |
182 | |
183 | llvm::AtomicRMWInst * |
184 | CreateAtomicRMW(llvm::AtomicRMWInst::BinOp Op, Address Addr, llvm::Value *Val, |
185 | llvm::AtomicOrdering Ordering, |
186 | llvm::SyncScope::ID SSID = llvm::SyncScope::System) { |
187 | return CGBuilderBaseTy::CreateAtomicRMW( |
188 | Op, Ptr: Addr.emitRawPointer(CGF&: *getCGF()), Val, |
189 | Align: Addr.getAlignment().getAsAlign(), Ordering, SSID); |
190 | } |
191 | |
192 | using CGBuilderBaseTy::CreateAddrSpaceCast; |
193 | Address CreateAddrSpaceCast(Address Addr, llvm::Type *Ty, |
194 | llvm::Type *ElementTy, |
195 | const llvm::Twine &Name = "" ) { |
196 | if (!Addr.hasOffset()) |
197 | return Address(CreateAddrSpaceCast(V: Addr.getBasePointer(), DestTy: Ty, Name), |
198 | ElementTy, Addr.getAlignment(), Addr.getPointerAuthInfo(), |
199 | /*Offset=*/nullptr, Addr.isKnownNonNull()); |
200 | // Eagerly force a raw address if these is an offset. |
201 | return RawAddress( |
202 | CreateAddrSpaceCast(V: Addr.emitRawPointer(CGF&: *getCGF()), DestTy: Ty, Name), |
203 | ElementTy, Addr.getAlignment(), Addr.isKnownNonNull()); |
204 | } |
205 | |
206 | using CGBuilderBaseTy::CreatePointerBitCastOrAddrSpaceCast; |
207 | Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty, |
208 | llvm::Type *ElementTy, |
209 | const llvm::Twine &Name = "" ) { |
210 | if (Addr.getType()->getAddressSpace() == Ty->getPointerAddressSpace()) |
211 | return Addr.withElementType(ElemTy: ElementTy); |
212 | return CreateAddrSpaceCast(Addr, Ty, ElementTy, Name); |
213 | } |
214 | |
215 | /// Given |
216 | /// %addr = {T1, T2...}* ... |
217 | /// produce |
218 | /// %name = getelementptr inbounds nuw %addr, i32 0, i32 index |
219 | /// |
220 | /// This API assumes that drilling into a struct like this is always an |
221 | /// inbounds and nuw operation. |
222 | using CGBuilderBaseTy::CreateStructGEP; |
223 | Address CreateStructGEP(Address Addr, unsigned Index, |
224 | const llvm::Twine &Name = "" ) { |
225 | llvm::StructType *ElTy = cast<llvm::StructType>(Val: Addr.getElementType()); |
226 | const llvm::DataLayout &DL = BB->getDataLayout(); |
227 | const llvm::StructLayout *Layout = DL.getStructLayout(Ty: ElTy); |
228 | auto Offset = CharUnits::fromQuantity(Quantity: Layout->getElementOffset(Idx: Index)); |
229 | |
230 | return Address(CreateStructGEP(Ty: Addr.getElementType(), Ptr: Addr.getBasePointer(), |
231 | Idx: Index, Name), |
232 | ElTy->getElementType(N: Index), |
233 | Addr.getAlignment().alignmentAtOffset(offset: Offset), |
234 | Addr.isKnownNonNull()); |
235 | } |
236 | |
237 | /// Given |
238 | /// %addr = [n x T]* ... |
239 | /// produce |
240 | /// %name = getelementptr inbounds %addr, i64 0, i64 index |
241 | /// where i64 is actually the target word size. |
242 | /// |
243 | /// This API assumes that drilling into an array like this is always |
244 | /// an inbounds operation. |
245 | Address CreateConstArrayGEP(Address Addr, uint64_t Index, |
246 | const llvm::Twine &Name = "" ) { |
247 | llvm::ArrayType *ElTy = cast<llvm::ArrayType>(Val: Addr.getElementType()); |
248 | const llvm::DataLayout &DL = BB->getDataLayout(); |
249 | CharUnits EltSize = |
250 | CharUnits::fromQuantity(Quantity: DL.getTypeAllocSize(Ty: ElTy->getElementType())); |
251 | |
252 | return Address( |
253 | CreateInBoundsGEP(Ty: Addr.getElementType(), Ptr: Addr.getBasePointer(), |
254 | IdxList: {getSize(N: CharUnits::Zero()), getSize(N: Index)}, Name), |
255 | ElTy->getElementType(), |
256 | Addr.getAlignment().alignmentAtOffset(offset: Index * EltSize), |
257 | Addr.isKnownNonNull()); |
258 | } |
259 | |
260 | /// Given |
261 | /// %addr = T* ... |
262 | /// produce |
263 | /// %name = getelementptr inbounds %addr, i64 index |
264 | /// where i64 is actually the target word size. |
265 | Address CreateConstInBoundsGEP(Address Addr, uint64_t Index, |
266 | const llvm::Twine &Name = "" ) { |
267 | llvm::Type *ElTy = Addr.getElementType(); |
268 | const llvm::DataLayout &DL = BB->getDataLayout(); |
269 | CharUnits EltSize = CharUnits::fromQuantity(Quantity: DL.getTypeAllocSize(Ty: ElTy)); |
270 | |
271 | return Address( |
272 | CreateInBoundsGEP(Ty: ElTy, Ptr: Addr.getBasePointer(), IdxList: getSize(N: Index), Name), |
273 | ElTy, Addr.getAlignment().alignmentAtOffset(offset: Index * EltSize), |
274 | Addr.isKnownNonNull()); |
275 | } |
276 | |
277 | /// Given |
278 | /// %addr = T* ... |
279 | /// produce |
280 | /// %name = getelementptr inbounds %addr, i64 index |
281 | /// where i64 is actually the target word size. |
282 | Address CreateConstGEP(Address Addr, uint64_t Index, |
283 | const llvm::Twine &Name = "" ) { |
284 | llvm::Type *ElTy = Addr.getElementType(); |
285 | const llvm::DataLayout &DL = BB->getDataLayout(); |
286 | CharUnits EltSize = CharUnits::fromQuantity(Quantity: DL.getTypeAllocSize(Ty: ElTy)); |
287 | |
288 | return Address(CreateGEP(Ty: ElTy, Ptr: Addr.getBasePointer(), IdxList: getSize(N: Index), Name), |
289 | Addr.getElementType(), |
290 | Addr.getAlignment().alignmentAtOffset(offset: Index * EltSize)); |
291 | } |
292 | |
293 | /// Create GEP with single dynamic index. The address alignment is reduced |
294 | /// according to the element size. |
295 | using CGBuilderBaseTy::CreateGEP; |
296 | Address CreateGEP(CodeGenFunction &CGF, Address Addr, llvm::Value *Index, |
297 | const llvm::Twine &Name = "" ) { |
298 | const llvm::DataLayout &DL = BB->getDataLayout(); |
299 | CharUnits EltSize = |
300 | CharUnits::fromQuantity(Quantity: DL.getTypeAllocSize(Ty: Addr.getElementType())); |
301 | |
302 | return Address( |
303 | CreateGEP(Ty: Addr.getElementType(), Ptr: Addr.emitRawPointer(CGF), IdxList: Index, Name), |
304 | Addr.getElementType(), |
305 | Addr.getAlignment().alignmentOfArrayElement(elementSize: EltSize)); |
306 | } |
307 | |
308 | /// Given a pointer to i8, adjust it by a given constant offset. |
309 | Address CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset, |
310 | const llvm::Twine &Name = "" ) { |
311 | assert(Addr.getElementType() == TypeCache.Int8Ty); |
312 | return Address( |
313 | CreateInBoundsGEP(Ty: Addr.getElementType(), Ptr: Addr.getBasePointer(), |
314 | IdxList: getSize(N: Offset), Name), |
315 | Addr.getElementType(), Addr.getAlignment().alignmentAtOffset(offset: Offset), |
316 | Addr.isKnownNonNull()); |
317 | } |
318 | |
319 | Address CreateConstByteGEP(Address Addr, CharUnits Offset, |
320 | const llvm::Twine &Name = "" ) { |
321 | assert(Addr.getElementType() == TypeCache.Int8Ty); |
322 | return Address(CreateGEP(Ty: Addr.getElementType(), Ptr: Addr.getBasePointer(), |
323 | IdxList: getSize(N: Offset), Name), |
324 | Addr.getElementType(), |
325 | Addr.getAlignment().alignmentAtOffset(offset: Offset)); |
326 | } |
327 | |
328 | using CGBuilderBaseTy::CreateConstInBoundsGEP2_32; |
329 | Address CreateConstInBoundsGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1, |
330 | const llvm::Twine &Name = "" ) { |
331 | return createConstGEP2_32<true>(Addr, Idx0, Idx1, Name); |
332 | } |
333 | |
334 | using CGBuilderBaseTy::CreateConstGEP2_32; |
335 | Address CreateConstGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1, |
336 | const llvm::Twine &Name = "" ) { |
337 | return createConstGEP2_32<false>(Addr, Idx0, Idx1, Name); |
338 | } |
339 | |
340 | Address CreateGEP(Address Addr, ArrayRef<llvm::Value *> IdxList, |
341 | llvm::Type *ElementType, CharUnits Align, |
342 | const Twine &Name = "" , |
343 | llvm::GEPNoWrapFlags NW = llvm::GEPNoWrapFlags::none()) { |
344 | llvm::Value *Ptr = emitRawPointerFromAddress(Addr); |
345 | return RawAddress(CreateGEP(Ty: Addr.getElementType(), Ptr, IdxList, Name, NW), |
346 | ElementType, Align); |
347 | } |
348 | |
349 | using CGBuilderBaseTy::CreateInBoundsGEP; |
350 | Address CreateInBoundsGEP(Address Addr, ArrayRef<llvm::Value *> IdxList, |
351 | llvm::Type *ElementType, CharUnits Align, |
352 | const Twine &Name = "" ) { |
353 | return RawAddress(CreateInBoundsGEP(Ty: Addr.getElementType(), |
354 | Ptr: emitRawPointerFromAddress(Addr), |
355 | IdxList, Name), |
356 | ElementType, Align, Addr.isKnownNonNull()); |
357 | } |
358 | |
359 | using CGBuilderBaseTy::CreateIsNull; |
360 | llvm::Value *CreateIsNull(Address Addr, const Twine &Name = "" ) { |
361 | if (!Addr.hasOffset()) |
362 | return CreateIsNull(Arg: Addr.getBasePointer(), Name); |
363 | // The pointer isn't null if Addr has an offset since offsets can always |
364 | // be applied inbound. |
365 | return llvm::ConstantInt::getFalse(Context); |
366 | } |
367 | |
368 | using CGBuilderBaseTy::CreateMemCpy; |
369 | llvm::CallInst *CreateMemCpy(Address Dest, Address Src, llvm::Value *Size, |
370 | bool IsVolatile = false) { |
371 | llvm::Value *DestPtr = emitRawPointerFromAddress(Addr: Dest); |
372 | llvm::Value *SrcPtr = emitRawPointerFromAddress(Addr: Src); |
373 | return CreateMemCpy(Dst: DestPtr, DstAlign: Dest.getAlignment().getAsAlign(), Src: SrcPtr, |
374 | SrcAlign: Src.getAlignment().getAsAlign(), Size, isVolatile: IsVolatile); |
375 | } |
376 | llvm::CallInst *CreateMemCpy(Address Dest, Address Src, uint64_t Size, |
377 | bool IsVolatile = false) { |
378 | llvm::Value *DestPtr = emitRawPointerFromAddress(Addr: Dest); |
379 | llvm::Value *SrcPtr = emitRawPointerFromAddress(Addr: Src); |
380 | return CreateMemCpy(Dst: DestPtr, DstAlign: Dest.getAlignment().getAsAlign(), Src: SrcPtr, |
381 | SrcAlign: Src.getAlignment().getAsAlign(), Size, isVolatile: IsVolatile); |
382 | } |
383 | |
384 | using CGBuilderBaseTy::CreateMemCpyInline; |
385 | llvm::CallInst *CreateMemCpyInline(Address Dest, Address Src, uint64_t Size) { |
386 | llvm::Value *DestPtr = emitRawPointerFromAddress(Addr: Dest); |
387 | llvm::Value *SrcPtr = emitRawPointerFromAddress(Addr: Src); |
388 | return CreateMemCpyInline(Dst: DestPtr, DstAlign: Dest.getAlignment().getAsAlign(), Src: SrcPtr, |
389 | SrcAlign: Src.getAlignment().getAsAlign(), Size: getInt64(C: Size)); |
390 | } |
391 | |
392 | using CGBuilderBaseTy::CreateMemMove; |
393 | llvm::CallInst *CreateMemMove(Address Dest, Address Src, llvm::Value *Size, |
394 | bool IsVolatile = false) { |
395 | llvm::Value *DestPtr = emitRawPointerFromAddress(Addr: Dest); |
396 | llvm::Value *SrcPtr = emitRawPointerFromAddress(Addr: Src); |
397 | return CreateMemMove(Dst: DestPtr, DstAlign: Dest.getAlignment().getAsAlign(), Src: SrcPtr, |
398 | SrcAlign: Src.getAlignment().getAsAlign(), Size, isVolatile: IsVolatile); |
399 | } |
400 | |
401 | using CGBuilderBaseTy::CreateMemSet; |
402 | llvm::CallInst *CreateMemSet(Address Dest, llvm::Value *Value, |
403 | llvm::Value *Size, bool IsVolatile = false) { |
404 | return CreateMemSet(Ptr: emitRawPointerFromAddress(Addr: Dest), Val: Value, Size, |
405 | Align: Dest.getAlignment().getAsAlign(), isVolatile: IsVolatile); |
406 | } |
407 | |
408 | using CGBuilderBaseTy::CreateMemSetInline; |
409 | llvm::CallInst *CreateMemSetInline(Address Dest, llvm::Value *Value, |
410 | uint64_t Size) { |
411 | return CreateMemSetInline(Dst: emitRawPointerFromAddress(Addr: Dest), |
412 | DstAlign: Dest.getAlignment().getAsAlign(), Val: Value, |
413 | Size: getInt64(C: Size)); |
414 | } |
415 | |
416 | using CGBuilderBaseTy::CreatePreserveStructAccessIndex; |
417 | Address CreatePreserveStructAccessIndex(Address Addr, unsigned Index, |
418 | unsigned FieldIndex, |
419 | llvm::MDNode *DbgInfo) { |
420 | llvm::StructType *ElTy = cast<llvm::StructType>(Val: Addr.getElementType()); |
421 | const llvm::DataLayout &DL = BB->getDataLayout(); |
422 | const llvm::StructLayout *Layout = DL.getStructLayout(Ty: ElTy); |
423 | auto Offset = CharUnits::fromQuantity(Quantity: Layout->getElementOffset(Idx: Index)); |
424 | |
425 | return Address( |
426 | CreatePreserveStructAccessIndex(ElTy, Base: emitRawPointerFromAddress(Addr), |
427 | Index, FieldIndex, DbgInfo), |
428 | ElTy->getElementType(N: Index), |
429 | Addr.getAlignment().alignmentAtOffset(offset: Offset)); |
430 | } |
431 | |
432 | using CGBuilderBaseTy::CreatePreserveUnionAccessIndex; |
433 | Address CreatePreserveUnionAccessIndex(Address Addr, unsigned FieldIndex, |
434 | llvm::MDNode *DbgInfo) { |
435 | Addr.replaceBasePointer(P: CreatePreserveUnionAccessIndex( |
436 | Base: Addr.getBasePointer(), FieldIndex, DbgInfo)); |
437 | return Addr; |
438 | } |
439 | |
440 | using CGBuilderBaseTy::CreateLaunderInvariantGroup; |
441 | Address CreateLaunderInvariantGroup(Address Addr) { |
442 | Addr.replaceBasePointer(P: CreateLaunderInvariantGroup(Ptr: Addr.getBasePointer())); |
443 | return Addr; |
444 | } |
445 | |
446 | using CGBuilderBaseTy::CreateStripInvariantGroup; |
447 | Address CreateStripInvariantGroup(Address Addr) { |
448 | Addr.replaceBasePointer(P: CreateStripInvariantGroup(Ptr: Addr.getBasePointer())); |
449 | return Addr; |
450 | } |
451 | }; |
452 | |
453 | } // end namespace CodeGen |
454 | } // end namespace clang |
455 | |
456 | #endif |
457 | |