| 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 | |