diff options
author | thegeorg <thegeorg@yandex-team.com> | 2024-03-13 13:58:24 +0300 |
---|---|---|
committer | thegeorg <thegeorg@yandex-team.com> | 2024-03-13 14:11:53 +0300 |
commit | 11a895b7e15d1c5a1f52706396b82e3f9db953cb (patch) | |
tree | fabc6d883b0f946151f61ae7865cee9f529a1fdd /contrib/libs/clang16/lib/CodeGen/CGBuilder.h | |
parent | 9685917341315774aad5733b1793b1e533a88bbb (diff) | |
download | ydb-11a895b7e15d1c5a1f52706396b82e3f9db953cb.tar.gz |
Export clang-format16 via ydblib project
6e6be3a95868fde888d801b7590af4044049563f
Diffstat (limited to 'contrib/libs/clang16/lib/CodeGen/CGBuilder.h')
-rw-r--r-- | contrib/libs/clang16/lib/CodeGen/CGBuilder.h | 379 |
1 files changed, 379 insertions, 0 deletions
diff --git a/contrib/libs/clang16/lib/CodeGen/CGBuilder.h b/contrib/libs/clang16/lib/CodeGen/CGBuilder.h new file mode 100644 index 0000000000..2fcfea64ed --- /dev/null +++ b/contrib/libs/clang16/lib/CodeGen/CGBuilder.h @@ -0,0 +1,379 @@ +//===-- CGBuilder.h - Choose IRBuilder implementation ----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H +#define LLVM_CLANG_LIB_CODEGEN_CGBUILDER_H + +#include "Address.h" +#include "CodeGenTypeCache.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Type.h" + +namespace clang { +namespace CodeGen { + +class CodeGenFunction; + +/// This is an IRBuilder insertion helper that forwards to +/// CodeGenFunction::InsertHelper, which adds necessary metadata to +/// instructions. +class CGBuilderInserter final : public llvm::IRBuilderDefaultInserter { +public: + CGBuilderInserter() = default; + explicit CGBuilderInserter(CodeGenFunction *CGF) : CGF(CGF) {} + + /// This forwards to CodeGenFunction::InsertHelper. + void InsertHelper(llvm::Instruction *I, const llvm::Twine &Name, + llvm::BasicBlock *BB, + llvm::BasicBlock::iterator InsertPt) const override; + +private: + CodeGenFunction *CGF = nullptr; +}; + +typedef CGBuilderInserter CGBuilderInserterTy; + +typedef llvm::IRBuilder<llvm::ConstantFolder, CGBuilderInserterTy> + CGBuilderBaseTy; + +class CGBuilderTy : public CGBuilderBaseTy { + /// Storing a reference to the type cache here makes it a lot easier + /// to build natural-feeling, target-specific IR. + const CodeGenTypeCache &TypeCache; + +public: + CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::LLVMContext &C) + : CGBuilderBaseTy(C), TypeCache(TypeCache) {} + CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::LLVMContext &C, + const llvm::ConstantFolder &F, + const CGBuilderInserterTy &Inserter) + : CGBuilderBaseTy(C, F, Inserter), TypeCache(TypeCache) {} + CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::Instruction *I) + : CGBuilderBaseTy(I), TypeCache(TypeCache) {} + CGBuilderTy(const CodeGenTypeCache &TypeCache, llvm::BasicBlock *BB) + : CGBuilderBaseTy(BB), TypeCache(TypeCache) {} + + llvm::ConstantInt *getSize(CharUnits N) { + return llvm::ConstantInt::get(TypeCache.SizeTy, N.getQuantity()); + } + llvm::ConstantInt *getSize(uint64_t N) { + return llvm::ConstantInt::get(TypeCache.SizeTy, N); + } + + // Note that we intentionally hide the CreateLoad APIs that don't + // take an alignment. + llvm::LoadInst *CreateLoad(Address Addr, const llvm::Twine &Name = "") { + return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(), + Addr.getAlignment().getAsAlign(), Name); + } + llvm::LoadInst *CreateLoad(Address Addr, const char *Name) { + // This overload is required to prevent string literals from + // ending up in the IsVolatile overload. + return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(), + Addr.getAlignment().getAsAlign(), Name); + } + llvm::LoadInst *CreateLoad(Address Addr, bool IsVolatile, + const llvm::Twine &Name = "") { + return CreateAlignedLoad(Addr.getElementType(), Addr.getPointer(), + Addr.getAlignment().getAsAlign(), IsVolatile, + Name); + } + + using CGBuilderBaseTy::CreateAlignedLoad; + llvm::LoadInst *CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr, + CharUnits Align, + const llvm::Twine &Name = "") { + assert(llvm::cast<llvm::PointerType>(Addr->getType()) + ->isOpaqueOrPointeeTypeMatches(Ty)); + return CreateAlignedLoad(Ty, Addr, Align.getAsAlign(), Name); + } + + // Note that we intentionally hide the CreateStore APIs that don't + // take an alignment. + llvm::StoreInst *CreateStore(llvm::Value *Val, Address Addr, + bool IsVolatile = false) { + return CreateAlignedStore(Val, Addr.getPointer(), + Addr.getAlignment().getAsAlign(), IsVolatile); + } + + using CGBuilderBaseTy::CreateAlignedStore; + llvm::StoreInst *CreateAlignedStore(llvm::Value *Val, llvm::Value *Addr, + CharUnits Align, + bool IsVolatile = false) { + return CreateAlignedStore(Val, Addr, Align.getAsAlign(), IsVolatile); + } + + // FIXME: these "default-aligned" APIs should be removed, + // but I don't feel like fixing all the builtin code right now. + llvm::StoreInst *CreateDefaultAlignedStore(llvm::Value *Val, + llvm::Value *Addr, + bool IsVolatile = false) { + return CGBuilderBaseTy::CreateStore(Val, Addr, IsVolatile); + } + + /// Emit a load from an i1 flag variable. + llvm::LoadInst *CreateFlagLoad(llvm::Value *Addr, + const llvm::Twine &Name = "") { + assert(llvm::cast<llvm::PointerType>(Addr->getType()) + ->isOpaqueOrPointeeTypeMatches(getInt1Ty())); + return CreateAlignedLoad(getInt1Ty(), Addr, CharUnits::One(), Name); + } + + /// Emit a store to an i1 flag variable. + llvm::StoreInst *CreateFlagStore(bool Value, llvm::Value *Addr) { + assert(llvm::cast<llvm::PointerType>(Addr->getType()) + ->isOpaqueOrPointeeTypeMatches(getInt1Ty())); + return CreateAlignedStore(getInt1(Value), Addr, CharUnits::One()); + } + + // Temporarily use old signature; clang will be updated to an Address overload + // in a subsequent patch. + llvm::AtomicCmpXchgInst * + CreateAtomicCmpXchg(llvm::Value *Ptr, llvm::Value *Cmp, llvm::Value *New, + llvm::AtomicOrdering SuccessOrdering, + llvm::AtomicOrdering FailureOrdering, + llvm::SyncScope::ID SSID = llvm::SyncScope::System) { + return CGBuilderBaseTy::CreateAtomicCmpXchg( + Ptr, Cmp, New, llvm::MaybeAlign(), SuccessOrdering, FailureOrdering, + SSID); + } + + // Temporarily use old signature; clang will be updated to an Address overload + // in a subsequent patch. + llvm::AtomicRMWInst * + CreateAtomicRMW(llvm::AtomicRMWInst::BinOp Op, llvm::Value *Ptr, + llvm::Value *Val, llvm::AtomicOrdering Ordering, + llvm::SyncScope::ID SSID = llvm::SyncScope::System) { + return CGBuilderBaseTy::CreateAtomicRMW(Op, Ptr, Val, llvm::MaybeAlign(), + Ordering, SSID); + } + + using CGBuilderBaseTy::CreateAddrSpaceCast; + Address CreateAddrSpaceCast(Address Addr, llvm::Type *Ty, + const llvm::Twine &Name = "") { + assert(cast<llvm::PointerType>(Ty)->isOpaqueOrPointeeTypeMatches( + Addr.getElementType()) && + "Should not change the element type"); + return Addr.withPointer(CreateAddrSpaceCast(Addr.getPointer(), Ty, Name)); + } + + /// Cast the element type of the given address to a different type, + /// preserving information like the alignment and address space. + Address CreateElementBitCast(Address Addr, llvm::Type *Ty, + const llvm::Twine &Name = "") { + auto *PtrTy = Ty->getPointerTo(Addr.getAddressSpace()); + return Address(CreateBitCast(Addr.getPointer(), PtrTy, Name), Ty, + Addr.getAlignment()); + } + + using CGBuilderBaseTy::CreatePointerBitCastOrAddrSpaceCast; + Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty, + llvm::Type *ElementTy, + const llvm::Twine &Name = "") { + llvm::Value *Ptr = + CreatePointerBitCastOrAddrSpaceCast(Addr.getPointer(), Ty, Name); + return Address(Ptr, ElementTy, Addr.getAlignment()); + } + + /// Given + /// %addr = {T1, T2...}* ... + /// produce + /// %name = getelementptr inbounds %addr, i32 0, i32 index + /// + /// This API assumes that drilling into a struct like this is always an + /// inbounds operation. + using CGBuilderBaseTy::CreateStructGEP; + Address CreateStructGEP(Address Addr, unsigned Index, + const llvm::Twine &Name = "") { + llvm::StructType *ElTy = cast<llvm::StructType>(Addr.getElementType()); + const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); + const llvm::StructLayout *Layout = DL.getStructLayout(ElTy); + auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index)); + + return Address( + CreateStructGEP(Addr.getElementType(), Addr.getPointer(), Index, Name), + ElTy->getElementType(Index), + Addr.getAlignment().alignmentAtOffset(Offset)); + } + + /// Given + /// %addr = [n x T]* ... + /// produce + /// %name = getelementptr inbounds %addr, i64 0, i64 index + /// where i64 is actually the target word size. + /// + /// This API assumes that drilling into an array like this is always + /// an inbounds operation. + Address CreateConstArrayGEP(Address Addr, uint64_t Index, + const llvm::Twine &Name = "") { + llvm::ArrayType *ElTy = cast<llvm::ArrayType>(Addr.getElementType()); + const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); + CharUnits EltSize = + CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy->getElementType())); + + return Address( + CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(), + {getSize(CharUnits::Zero()), getSize(Index)}, Name), + ElTy->getElementType(), + Addr.getAlignment().alignmentAtOffset(Index * EltSize)); + } + + /// Given + /// %addr = T* ... + /// produce + /// %name = getelementptr inbounds %addr, i64 index + /// where i64 is actually the target word size. + Address CreateConstInBoundsGEP(Address Addr, uint64_t Index, + const llvm::Twine &Name = "") { + llvm::Type *ElTy = Addr.getElementType(); + const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); + CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy)); + + return Address(CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(), + getSize(Index), Name), + ElTy, + Addr.getAlignment().alignmentAtOffset(Index * EltSize)); + } + + /// Given + /// %addr = T* ... + /// produce + /// %name = getelementptr inbounds %addr, i64 index + /// where i64 is actually the target word size. + Address CreateConstGEP(Address Addr, uint64_t Index, + const llvm::Twine &Name = "") { + const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); + CharUnits EltSize = + CharUnits::fromQuantity(DL.getTypeAllocSize(Addr.getElementType())); + + return Address(CreateGEP(Addr.getElementType(), Addr.getPointer(), + getSize(Index), Name), + Addr.getElementType(), + Addr.getAlignment().alignmentAtOffset(Index * EltSize)); + } + + /// Create GEP with single dynamic index. The address alignment is reduced + /// according to the element size. + using CGBuilderBaseTy::CreateGEP; + Address CreateGEP(Address Addr, llvm::Value *Index, + const llvm::Twine &Name = "") { + const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); + CharUnits EltSize = + CharUnits::fromQuantity(DL.getTypeAllocSize(Addr.getElementType())); + + return Address( + CreateGEP(Addr.getElementType(), Addr.getPointer(), Index, Name), + Addr.getElementType(), + Addr.getAlignment().alignmentOfArrayElement(EltSize)); + } + + /// Given a pointer to i8, adjust it by a given constant offset. + Address CreateConstInBoundsByteGEP(Address Addr, CharUnits Offset, + const llvm::Twine &Name = "") { + assert(Addr.getElementType() == TypeCache.Int8Ty); + return Address(CreateInBoundsGEP(Addr.getElementType(), Addr.getPointer(), + getSize(Offset), Name), + Addr.getElementType(), + Addr.getAlignment().alignmentAtOffset(Offset)); + } + Address CreateConstByteGEP(Address Addr, CharUnits Offset, + const llvm::Twine &Name = "") { + assert(Addr.getElementType() == TypeCache.Int8Ty); + return Address(CreateGEP(Addr.getElementType(), Addr.getPointer(), + getSize(Offset), Name), + Addr.getElementType(), + Addr.getAlignment().alignmentAtOffset(Offset)); + } + + using CGBuilderBaseTy::CreateConstInBoundsGEP2_32; + Address CreateConstInBoundsGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1, + const llvm::Twine &Name = "") { + const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); + + auto *GEP = cast<llvm::GetElementPtrInst>(CreateConstInBoundsGEP2_32( + Addr.getElementType(), Addr.getPointer(), Idx0, Idx1, Name)); + llvm::APInt Offset( + DL.getIndexSizeInBits(Addr.getType()->getPointerAddressSpace()), 0, + /*isSigned=*/true); + if (!GEP->accumulateConstantOffset(DL, Offset)) + llvm_unreachable("offset of GEP with constants is always computable"); + return Address(GEP, GEP->getResultElementType(), + Addr.getAlignment().alignmentAtOffset( + CharUnits::fromQuantity(Offset.getSExtValue()))); + } + + using CGBuilderBaseTy::CreateMemCpy; + llvm::CallInst *CreateMemCpy(Address Dest, Address Src, llvm::Value *Size, + bool IsVolatile = false) { + return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getAsAlign(), + Src.getPointer(), Src.getAlignment().getAsAlign(), Size, + IsVolatile); + } + llvm::CallInst *CreateMemCpy(Address Dest, Address Src, uint64_t Size, + bool IsVolatile = false) { + return CreateMemCpy(Dest.getPointer(), Dest.getAlignment().getAsAlign(), + Src.getPointer(), Src.getAlignment().getAsAlign(), Size, + IsVolatile); + } + + using CGBuilderBaseTy::CreateMemCpyInline; + llvm::CallInst *CreateMemCpyInline(Address Dest, Address Src, uint64_t Size) { + return CreateMemCpyInline( + Dest.getPointer(), Dest.getAlignment().getAsAlign(), Src.getPointer(), + Src.getAlignment().getAsAlign(), getInt64(Size)); + } + + using CGBuilderBaseTy::CreateMemMove; + llvm::CallInst *CreateMemMove(Address Dest, Address Src, llvm::Value *Size, + bool IsVolatile = false) { + return CreateMemMove(Dest.getPointer(), Dest.getAlignment().getAsAlign(), + Src.getPointer(), Src.getAlignment().getAsAlign(), + Size, IsVolatile); + } + + using CGBuilderBaseTy::CreateMemSet; + llvm::CallInst *CreateMemSet(Address Dest, llvm::Value *Value, + llvm::Value *Size, bool IsVolatile = false) { + return CreateMemSet(Dest.getPointer(), Value, Size, + Dest.getAlignment().getAsAlign(), IsVolatile); + } + + using CGBuilderBaseTy::CreateMemSetInline; + llvm::CallInst *CreateMemSetInline(Address Dest, llvm::Value *Value, + uint64_t Size) { + return CreateMemSetInline(Dest.getPointer(), + Dest.getAlignment().getAsAlign(), Value, + getInt64(Size)); + } + + using CGBuilderBaseTy::CreatePreserveStructAccessIndex; + Address CreatePreserveStructAccessIndex(Address Addr, unsigned Index, + unsigned FieldIndex, + llvm::MDNode *DbgInfo) { + llvm::StructType *ElTy = cast<llvm::StructType>(Addr.getElementType()); + const llvm::DataLayout &DL = BB->getParent()->getParent()->getDataLayout(); + const llvm::StructLayout *Layout = DL.getStructLayout(ElTy); + auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index)); + + return Address(CreatePreserveStructAccessIndex(ElTy, Addr.getPointer(), + Index, FieldIndex, DbgInfo), + ElTy->getElementType(Index), + Addr.getAlignment().alignmentAtOffset(Offset)); + } + + using CGBuilderBaseTy::CreateLaunderInvariantGroup; + Address CreateLaunderInvariantGroup(Address Addr) { + return Addr.withPointer(CreateLaunderInvariantGroup(Addr.getPointer())); + } +}; + +} // end namespace CodeGen +} // end namespace clang + +#endif |