//===-- 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 "CGValue.h"
#include "CodeGenTypeCache.h"
#include "llvm/Analysis/Utils/Local.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/GEPNoWrapFlags.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Type.h"

namespace clang {
namespace CodeGen {

class CGBuilderTy;
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 {
  friend CGBuilderTy;

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::iterator InsertPt) const override;

private:
  CodeGenFunction *CGF = nullptr;
};

typedef CGBuilderInserter CGBuilderInserterTy;

typedef llvm::IRBuilder<llvm::ConstantFolder, CGBuilderInserterTy>
    CGBuilderBaseTy;

class CGBuilderTy : public CGBuilderBaseTy {
  friend class Address;

  /// Storing a reference to the type cache here makes it a lot easier
  /// to build natural-feeling, target-specific IR.
  const CodeGenTypeCache &TypeCache;

  CodeGenFunction *getCGF() const { return getInserter().CGF; }

  llvm::Value *emitRawPointerFromAddress(Address Addr) const {
    return Addr.getBasePointer();
  }

  template <bool IsInBounds>
  Address createConstGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1,
                             const llvm::Twine &Name) {
    const llvm::DataLayout &DL = BB->getDataLayout();
    llvm::Value *V;
    if (IsInBounds)
      V = CreateConstInBoundsGEP2_32(Addr.getElementType(),
                                     emitRawPointerFromAddress(Addr), Idx0,
                                     Idx1, Name);
    else
      V = CreateConstGEP2_32(Addr.getElementType(),
                             emitRawPointerFromAddress(Addr), Idx0, Idx1, Name);
    llvm::APInt Offset(
        DL.getIndexSizeInBits(Addr.getType()->getPointerAddressSpace()), 0,
        /*isSigned=*/true);
    if (!llvm::GEPOperator::accumulateConstantOffset(
            Addr.getElementType(), {getInt32(Idx0), getInt32(Idx1)}, DL,
            Offset))
      llvm_unreachable(
          "accumulateConstantOffset with constant indices should not fail.");
    llvm::Type *ElementTy = llvm::GetElementPtrInst::getIndexedType(
        Addr.getElementType(), {Idx0, Idx1});
    return Address(V, ElementTy,
                   Addr.getAlignment().alignmentAtOffset(
                       CharUnits::fromQuantity(Offset.getSExtValue())),
                   IsInBounds ? Addr.isKnownNonNull() : NotKnownNonNull);
  }

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(),
                             emitRawPointerFromAddress(Addr),
                             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(),
                             emitRawPointerFromAddress(Addr),
                             Addr.getAlignment().getAsAlign(), Name);
  }
  llvm::LoadInst *CreateLoad(Address Addr, bool IsVolatile,
                             const llvm::Twine &Name = "") {
    return CreateAlignedLoad(
        Addr.getElementType(), emitRawPointerFromAddress(Addr),
        Addr.getAlignment().getAsAlign(), IsVolatile, Name);
  }

  using CGBuilderBaseTy::CreateAlignedLoad;
  llvm::LoadInst *CreateAlignedLoad(llvm::Type *Ty, llvm::Value *Addr,
                                    CharUnits Align,
                                    const llvm::Twine &Name = "") {
    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, emitRawPointerFromAddress(Addr),
                              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 = "") {
    return CreateAlignedLoad(getInt1Ty(), Addr, CharUnits::One(), Name);
  }

  /// Emit a store to an i1 flag variable.
  llvm::StoreInst *CreateFlagStore(bool Value, llvm::Value *Addr) {
    return CreateAlignedStore(getInt1(Value), Addr, CharUnits::One());
  }

  llvm::AtomicCmpXchgInst *
  CreateAtomicCmpXchg(Address Addr, llvm::Value *Cmp, llvm::Value *New,
                      llvm::AtomicOrdering SuccessOrdering,
                      llvm::AtomicOrdering FailureOrdering,
                      llvm::SyncScope::ID SSID = llvm::SyncScope::System) {
    return CGBuilderBaseTy::CreateAtomicCmpXchg(
        Addr.emitRawPointer(*getCGF()), Cmp, New,
        Addr.getAlignment().getAsAlign(), SuccessOrdering, FailureOrdering,
        SSID);
  }

  llvm::AtomicRMWInst *
  CreateAtomicRMW(llvm::AtomicRMWInst::BinOp Op, Address Addr, llvm::Value *Val,
                  llvm::AtomicOrdering Ordering,
                  llvm::SyncScope::ID SSID = llvm::SyncScope::System) {
    return CGBuilderBaseTy::CreateAtomicRMW(
        Op, Addr.emitRawPointer(*getCGF()), Val,
        Addr.getAlignment().getAsAlign(), Ordering, SSID);
  }

  using CGBuilderBaseTy::CreateAddrSpaceCast;
  Address CreateAddrSpaceCast(Address Addr, llvm::Type *Ty,
                              llvm::Type *ElementTy,
                              const llvm::Twine &Name = "") {
    if (!Addr.hasOffset())
      return Address(CreateAddrSpaceCast(Addr.getBasePointer(), Ty, Name),
                     ElementTy, Addr.getAlignment(), Addr.getPointerAuthInfo(),
                     /*Offset=*/nullptr, Addr.isKnownNonNull());
    // Eagerly force a raw address if these is an offset.
    return RawAddress(
        CreateAddrSpaceCast(Addr.emitRawPointer(*getCGF()), Ty, Name),
        ElementTy, Addr.getAlignment(), Addr.isKnownNonNull());
  }

  using CGBuilderBaseTy::CreatePointerBitCastOrAddrSpaceCast;
  Address CreatePointerBitCastOrAddrSpaceCast(Address Addr, llvm::Type *Ty,
                                              llvm::Type *ElementTy,
                                              const llvm::Twine &Name = "") {
    if (Addr.getType()->getAddressSpace() == Ty->getPointerAddressSpace())
      return Addr.withElementType(ElementTy);
    return CreateAddrSpaceCast(Addr, Ty, ElementTy, Name);
  }

  /// Given
  ///   %addr = {T1, T2...}* ...
  /// produce
  ///   %name = getelementptr inbounds nuw %addr, i32 0, i32 index
  ///
  /// This API assumes that drilling into a struct like this is always an
  /// inbounds and nuw 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->getDataLayout();
    const llvm::StructLayout *Layout = DL.getStructLayout(ElTy);
    auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index));

    return Address(CreateStructGEP(Addr.getElementType(), Addr.getBasePointer(),
                                   Index, Name),
                   ElTy->getElementType(Index),
                   Addr.getAlignment().alignmentAtOffset(Offset),
                   Addr.isKnownNonNull());
  }

  /// 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->getDataLayout();
    CharUnits EltSize =
        CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy->getElementType()));

    return Address(
        CreateInBoundsGEP(Addr.getElementType(), Addr.getBasePointer(),
                          {getSize(CharUnits::Zero()), getSize(Index)}, Name),
        ElTy->getElementType(),
        Addr.getAlignment().alignmentAtOffset(Index * EltSize),
        Addr.isKnownNonNull());
  }

  /// 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->getDataLayout();
    CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy));

    return Address(
        CreateInBoundsGEP(ElTy, Addr.getBasePointer(), getSize(Index), Name),
        ElTy, Addr.getAlignment().alignmentAtOffset(Index * EltSize),
        Addr.isKnownNonNull());
  }

  /// 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 = "") {
    llvm::Type *ElTy = Addr.getElementType();
    const llvm::DataLayout &DL = BB->getDataLayout();
    CharUnits EltSize = CharUnits::fromQuantity(DL.getTypeAllocSize(ElTy));

    return Address(CreateGEP(ElTy, Addr.getBasePointer(), 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(CodeGenFunction &CGF, Address Addr, llvm::Value *Index,
                    const llvm::Twine &Name = "") {
    const llvm::DataLayout &DL = BB->getDataLayout();
    CharUnits EltSize =
        CharUnits::fromQuantity(DL.getTypeAllocSize(Addr.getElementType()));

    return Address(
        CreateGEP(Addr.getElementType(), Addr.emitRawPointer(CGF), 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.getBasePointer(),
                          getSize(Offset), Name),
        Addr.getElementType(), Addr.getAlignment().alignmentAtOffset(Offset),
        Addr.isKnownNonNull());
  }

  Address CreateConstByteGEP(Address Addr, CharUnits Offset,
                             const llvm::Twine &Name = "") {
    assert(Addr.getElementType() == TypeCache.Int8Ty);
    return Address(CreateGEP(Addr.getElementType(), Addr.getBasePointer(),
                             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 = "") {
    return createConstGEP2_32<true>(Addr, Idx0, Idx1, Name);
  }

  using CGBuilderBaseTy::CreateConstGEP2_32;
  Address CreateConstGEP2_32(Address Addr, unsigned Idx0, unsigned Idx1,
                             const llvm::Twine &Name = "") {
    return createConstGEP2_32<false>(Addr, Idx0, Idx1, Name);
  }

  Address CreateGEP(Address Addr, ArrayRef<llvm::Value *> IdxList,
                    llvm::Type *ElementType, CharUnits Align,
                    const Twine &Name = "",
                    llvm::GEPNoWrapFlags NW = llvm::GEPNoWrapFlags::none()) {
    llvm::Value *Ptr = emitRawPointerFromAddress(Addr);
    return RawAddress(CreateGEP(Addr.getElementType(), Ptr, IdxList, Name, NW),
                      ElementType, Align);
  }

  using CGBuilderBaseTy::CreateInBoundsGEP;
  Address CreateInBoundsGEP(Address Addr, ArrayRef<llvm::Value *> IdxList,
                            llvm::Type *ElementType, CharUnits Align,
                            const Twine &Name = "") {
    return RawAddress(CreateInBoundsGEP(Addr.getElementType(),
                                        emitRawPointerFromAddress(Addr),
                                        IdxList, Name),
                      ElementType, Align, Addr.isKnownNonNull());
  }

  using CGBuilderBaseTy::CreateIsNull;
  llvm::Value *CreateIsNull(Address Addr, const Twine &Name = "") {
    if (!Addr.hasOffset())
      return CreateIsNull(Addr.getBasePointer(), Name);
    // The pointer isn't null if Addr has an offset since offsets can always
    // be applied inbound.
    return llvm::ConstantInt::getFalse(Context);
  }

  using CGBuilderBaseTy::CreateMemCpy;
  llvm::CallInst *CreateMemCpy(Address Dest, Address Src, llvm::Value *Size,
                               bool IsVolatile = false) {
    llvm::Value *DestPtr = emitRawPointerFromAddress(Dest);
    llvm::Value *SrcPtr = emitRawPointerFromAddress(Src);
    return CreateMemCpy(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr,
                        Src.getAlignment().getAsAlign(), Size, IsVolatile);
  }
  llvm::CallInst *CreateMemCpy(Address Dest, Address Src, uint64_t Size,
                               bool IsVolatile = false) {
    llvm::Value *DestPtr = emitRawPointerFromAddress(Dest);
    llvm::Value *SrcPtr = emitRawPointerFromAddress(Src);
    return CreateMemCpy(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr,
                        Src.getAlignment().getAsAlign(), Size, IsVolatile);
  }

  using CGBuilderBaseTy::CreateMemCpyInline;
  llvm::CallInst *CreateMemCpyInline(Address Dest, Address Src, uint64_t Size) {
    llvm::Value *DestPtr = emitRawPointerFromAddress(Dest);
    llvm::Value *SrcPtr = emitRawPointerFromAddress(Src);
    return CreateMemCpyInline(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr,
                              Src.getAlignment().getAsAlign(), getInt64(Size));
  }

  using CGBuilderBaseTy::CreateMemMove;
  llvm::CallInst *CreateMemMove(Address Dest, Address Src, llvm::Value *Size,
                                bool IsVolatile = false) {
    llvm::Value *DestPtr = emitRawPointerFromAddress(Dest);
    llvm::Value *SrcPtr = emitRawPointerFromAddress(Src);
    return CreateMemMove(DestPtr, Dest.getAlignment().getAsAlign(), SrcPtr,
                         Src.getAlignment().getAsAlign(), Size, IsVolatile);
  }

  using CGBuilderBaseTy::CreateMemSet;
  llvm::CallInst *CreateMemSet(Address Dest, llvm::Value *Value,
                               llvm::Value *Size, bool IsVolatile = false) {
    return CreateMemSet(emitRawPointerFromAddress(Dest), Value, Size,
                        Dest.getAlignment().getAsAlign(), IsVolatile);
  }

  using CGBuilderBaseTy::CreateMemSetInline;
  llvm::CallInst *CreateMemSetInline(Address Dest, llvm::Value *Value,
                                     uint64_t Size) {
    return CreateMemSetInline(emitRawPointerFromAddress(Dest),
                              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->getDataLayout();
    const llvm::StructLayout *Layout = DL.getStructLayout(ElTy);
    auto Offset = CharUnits::fromQuantity(Layout->getElementOffset(Index));

    return Address(
        CreatePreserveStructAccessIndex(ElTy, emitRawPointerFromAddress(Addr),
                                        Index, FieldIndex, DbgInfo),
        ElTy->getElementType(Index),
        Addr.getAlignment().alignmentAtOffset(Offset));
  }

  using CGBuilderBaseTy::CreatePreserveUnionAccessIndex;
  Address CreatePreserveUnionAccessIndex(Address Addr, unsigned FieldIndex,
                                         llvm::MDNode *DbgInfo) {
    Addr.replaceBasePointer(CreatePreserveUnionAccessIndex(
        Addr.getBasePointer(), FieldIndex, DbgInfo));
    return Addr;
  }

  using CGBuilderBaseTy::CreateLaunderInvariantGroup;
  Address CreateLaunderInvariantGroup(Address Addr) {
    Addr.replaceBasePointer(CreateLaunderInvariantGroup(Addr.getBasePointer()));
    return Addr;
  }

  using CGBuilderBaseTy::CreateStripInvariantGroup;
  Address CreateStripInvariantGroup(Address Addr) {
    Addr.replaceBasePointer(CreateStripInvariantGroup(Addr.getBasePointer()));
    return Addr;
  }
};

} // end namespace CodeGen
} // end namespace clang

#endif
