123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379 |
- //===-- 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
|