//===-- TypeConverter.h -- type conversion ----------------------*- 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
//
//===----------------------------------------------------------------------===//
//
// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
//
//===----------------------------------------------------------------------===//

#ifndef FORTRAN_OPTIMIZER_CODEGEN_TYPECONVERTER_H
#define FORTRAN_OPTIMIZER_CODEGEN_TYPECONVERTER_H

#include "DescriptorModel.h"
#include "Target.h"
#include "flang/Lower/Todo.h" // remove when TODO's are done
#include "flang/Optimizer/Dialect/FIRType.h"
#include "flang/Optimizer/Support/FIRContext.h"
#include "flang/Optimizer/Support/KindMapping.h"
#include "mlir/Conversion/LLVMCommon/TypeConverter.h"
#include "llvm/Support/Debug.h"

// Position of the different values in a `fir.box`.
static constexpr unsigned kAddrPosInBox = 0;
static constexpr unsigned kElemLenPosInBox = 1;
static constexpr unsigned kVersionPosInBox = 2;
static constexpr unsigned kRankPosInBox = 3;
static constexpr unsigned kTypePosInBox = 4;
static constexpr unsigned kAttributePosInBox = 5;
static constexpr unsigned kF18AddendumPosInBox = 6;
static constexpr unsigned kDimsPosInBox = 7;
static constexpr unsigned kOptTypePtrPosInBox = 8;
static constexpr unsigned kOptRowTypePosInBox = 9;

namespace fir {

/// FIR type converter
/// This converts FIR types to LLVM types (for now)
class LLVMTypeConverter : public mlir::LLVMTypeConverter {
public:
  LLVMTypeConverter(mlir::ModuleOp module)
      : mlir::LLVMTypeConverter(module.getContext()),
        kindMapping(getKindMapping(module)),
        specifics(CodeGenSpecifics::get(module.getContext(),
                                        getTargetTriple(module),
                                        getKindMapping(module))) {
    LLVM_DEBUG(llvm::dbgs() << "FIR type converter\n");

    // Each conversion should return a value of type mlir::Type.
    addConversion([&](BoxType box) { return convertBoxType(box); });
    addConversion([&](BoxCharType boxchar) {
      LLVM_DEBUG(llvm::dbgs() << "type convert: " << boxchar << '\n');
      return convertType(specifics->boxcharMemoryType(boxchar.getEleTy()));
    });
    addConversion([&](BoxProcType boxproc) {
      // TODO: Support for this type will be added later when the Fortran 2003
      // procedure pointer feature is implemented.
      return llvm::None;
    });
    addConversion(
        [&](fir::CharacterType charTy) { return convertCharType(charTy); });
    addConversion([&](HeapType heap) { return convertPointerLike(heap); });
    addConversion([&](fir::IntegerType intTy) {
      return mlir::IntegerType::get(
          &getContext(), kindMapping.getIntegerBitsize(intTy.getFKind()));
    });
    addConversion([&](fir::LogicalType boolTy) {
      return mlir::IntegerType::get(
          &getContext(), kindMapping.getLogicalBitsize(boolTy.getFKind()));
    });
    addConversion([&](fir::LLVMPointerType pointer) {
      return convertPointerLike(pointer);
    });
    addConversion(
        [&](fir::PointerType pointer) { return convertPointerLike(pointer); });
    addConversion(
        [&](fir::RecordType derived) { return convertRecordType(derived); });
    addConversion([&](fir::FieldType field) {
      // Convert to i32 because of LLVM GEP indexing restriction.
      return mlir::IntegerType::get(field.getContext(), 32);
    });
    addConversion([&](fir::LenType field) {
      // Get size of len paramter from the descriptor.
      return getModel<Fortran::runtime::typeInfo::TypeParameterValue>()(
          &getContext());
    });
    addConversion(
        [&](fir::ComplexType cmplx) { return convertComplexType(cmplx); });
    addConversion(
        [&](fir::RealType real) { return convertRealType(real.getFKind()); });
    addConversion(
        [&](fir::ReferenceType ref) { return convertPointerLike(ref); });
    addConversion([&](fir::SequenceType sequence) {
      return convertSequenceType(sequence);
    });
    addConversion([&](fir::TypeDescType tdesc) {
      return convertTypeDescType(tdesc.getContext());
    });
    addConversion([&](fir::VectorType vecTy) {
      return mlir::VectorType::get(llvm::ArrayRef<int64_t>(vecTy.getLen()),
                                   convertType(vecTy.getEleTy()));
    });
    addConversion([&](mlir::TupleType tuple) {
      LLVM_DEBUG(llvm::dbgs() << "type convert: " << tuple << '\n');
      llvm::SmallVector<mlir::Type> inMembers;
      tuple.getFlattenedTypes(inMembers);
      llvm::SmallVector<mlir::Type> members;
      for (auto mem : inMembers)
        members.push_back(convertType(mem).cast<mlir::Type>());
      return mlir::LLVM::LLVMStructType::getLiteral(&getContext(), members,
                                                    /*isPacked=*/false);
    });
  }

  // i32 is used here because LLVM wants i32 constants when indexing into struct
  // types. Indexing into other aggregate types is more flexible.
  mlir::Type offsetType() { return mlir::IntegerType::get(&getContext(), 32); }

  // i64 can be used to index into aggregates like arrays
  mlir::Type indexType() { return mlir::IntegerType::get(&getContext(), 64); }

  // fir.type<name(p : TY'...){f : TY...}>  -->  llvm<"%name = { ty... }">
  mlir::Type convertRecordType(fir::RecordType derived) {
    auto name = derived.getName();
    auto st = mlir::LLVM::LLVMStructType::getIdentified(&getContext(), name);
    llvm::SmallVector<mlir::Type> members;
    for (auto mem : derived.getTypeList()) {
      members.push_back(convertType(mem.second).cast<mlir::Type>());
    }
    if (mlir::succeeded(st.setBody(members, /*isPacked=*/false)))
      return st;
    return mlir::Type();
  }

  // Is an extended descriptor needed given the element type of a fir.box type ?
  // Extended descriptors are required for derived types.
  bool requiresExtendedDesc(mlir::Type boxElementType) {
    auto eleTy = fir::unwrapSequenceType(boxElementType);
    return eleTy.isa<fir::RecordType>();
  }

  // Magic value to indicate we do not know the rank of an entity, either
  // because it is assumed rank or because we have not determined it yet.
  static constexpr int unknownRank() { return -1; }

  // This corresponds to the descriptor as defined in ISO_Fortran_binding.h and
  // the addendum defined in descriptor.h.
  mlir::Type convertBoxType(BoxType box, int rank = unknownRank()) {
    // (base_addr*, elem_len, version, rank, type, attribute, f18Addendum, [dim]
    llvm::SmallVector<mlir::Type> dataDescFields;
    mlir::Type ele = box.getEleTy();
    // remove fir.heap/fir.ref/fir.ptr
    if (auto removeIndirection = fir::dyn_cast_ptrEleTy(ele))
      ele = removeIndirection;
    auto eleTy = convertType(ele);
    // base_addr*
    if (ele.isa<SequenceType>() && eleTy.isa<mlir::LLVM::LLVMPointerType>())
      dataDescFields.push_back(eleTy);
    else
      dataDescFields.push_back(mlir::LLVM::LLVMPointerType::get(eleTy));
    // elem_len
    dataDescFields.push_back(
        getDescFieldTypeModel<kElemLenPosInBox>()(&getContext()));
    // version
    dataDescFields.push_back(
        getDescFieldTypeModel<kVersionPosInBox>()(&getContext()));
    // rank
    dataDescFields.push_back(
        getDescFieldTypeModel<kRankPosInBox>()(&getContext()));
    // type
    dataDescFields.push_back(
        getDescFieldTypeModel<kTypePosInBox>()(&getContext()));
    // attribute
    dataDescFields.push_back(
        getDescFieldTypeModel<kAttributePosInBox>()(&getContext()));
    // f18Addendum
    dataDescFields.push_back(
        getDescFieldTypeModel<kF18AddendumPosInBox>()(&getContext()));
    // [dims]
    if (rank == unknownRank()) {
      if (auto seqTy = ele.dyn_cast<SequenceType>())
        rank = seqTy.getDimension();
      else
        rank = 0;
    }
    if (rank > 0) {
      auto rowTy = getDescFieldTypeModel<kDimsPosInBox>()(&getContext());
      dataDescFields.push_back(mlir::LLVM::LLVMArrayType::get(rowTy, rank));
    }
    // opt-type-ptr: i8* (see fir.tdesc)
    if (requiresExtendedDesc(ele)) {
      dataDescFields.push_back(
          getExtendedDescFieldTypeModel<kOptTypePtrPosInBox>()(&getContext()));
      auto rowTy =
          getExtendedDescFieldTypeModel<kOptRowTypePosInBox>()(&getContext());
      dataDescFields.push_back(mlir::LLVM::LLVMArrayType::get(rowTy, 1));
      if (auto recTy = fir::unwrapSequenceType(ele).dyn_cast<fir::RecordType>())
        if (recTy.getNumLenParams() > 0) {
          // The descriptor design needs to be clarified regarding the number of
          // length parameters in the addendum. Since it can change for
          // polymorphic allocatables, it seems all length parameters cannot
          // always possibly be placed in the addendum.
          TODO_NOLOC("extended descriptor derived with length parameters");
          unsigned numLenParams = recTy.getNumLenParams();
          dataDescFields.push_back(
              mlir::LLVM::LLVMArrayType::get(rowTy, numLenParams));
        }
    }
    return mlir::LLVM::LLVMPointerType::get(
        mlir::LLVM::LLVMStructType::getLiteral(&getContext(), dataDescFields,
                                               /*isPacked=*/false));
  }

  unsigned characterBitsize(fir::CharacterType charTy) {
    return kindMapping.getCharacterBitsize(charTy.getFKind());
  }

  // fir.char<k,?>  -->  llvm<"ix">          where ix is scaled by kind mapping
  // fir.char<k,n>  -->  llvm.array<n x "ix">
  mlir::Type convertCharType(fir::CharacterType charTy) {
    auto iTy = mlir::IntegerType::get(&getContext(), characterBitsize(charTy));
    if (charTy.getLen() == fir::CharacterType::unknownLen())
      return iTy;
    return mlir::LLVM::LLVMArrayType::get(iTy, charTy.getLen());
  }

  // Use the target specifics to figure out how to map complex to LLVM IR. The
  // use of complex values in function signatures is handled before conversion
  // to LLVM IR dialect here.
  //
  // fir.complex<T> | std.complex<T>    --> llvm<"{t,t}">
  template <typename C>
  mlir::Type convertComplexType(C cmplx) {
    LLVM_DEBUG(llvm::dbgs() << "type convert: " << cmplx << '\n');
    auto eleTy = cmplx.getElementType();
    return convertType(specifics->complexMemoryType(eleTy));
  }

  // convert a front-end kind value to either a std or LLVM IR dialect type
  // fir.real<n>  -->  llvm.anyfloat  where anyfloat is a kind mapping
  mlir::Type convertRealType(fir::KindTy kind) {
    return fromRealTypeID(kindMapping.getRealTypeID(kind), kind);
  }

  template <typename A>
  mlir::Type convertPointerLike(A &ty) {
    mlir::Type eleTy = ty.getEleTy();
    // A sequence type is a special case. A sequence of runtime size on its
    // interior dimensions lowers to a memory reference. In that case, we
    // degenerate the array and do not want a the type to become `T**` but
    // merely `T*`.
    if (auto seqTy = eleTy.dyn_cast<fir::SequenceType>()) {
      if (!seqTy.hasConstantShape() ||
          characterWithDynamicLen(seqTy.getEleTy())) {
        if (seqTy.hasConstantInterior())
          return convertType(seqTy);
        eleTy = seqTy.getEleTy();
      }
    }
    // fir.ref<fir.box> is a special case because fir.box type is already
    // a pointer to a Fortran descriptor at the LLVM IR level. This implies
    // that a fir.ref<fir.box>, that is the address of fir.box is actually
    // the same as a fir.box at the LLVM level.
    // The distinction is kept in fir to denote when a descriptor is expected
    // to be mutable (fir.ref<fir.box>) and when it is not (fir.box).
    if (eleTy.isa<fir::BoxType>())
      return convertType(eleTy);

    return mlir::LLVM::LLVMPointerType::get(convertType(eleTy));
  }

  // fir.array<c ... :any>  -->  llvm<"[...[c x any]]">
  mlir::Type convertSequenceType(SequenceType seq) {
    auto baseTy = convertType(seq.getEleTy());
    if (characterWithDynamicLen(seq.getEleTy()))
      return mlir::LLVM::LLVMPointerType::get(baseTy);
    auto shape = seq.getShape();
    auto constRows = seq.getConstantRows();
    if (constRows) {
      decltype(constRows) i = constRows;
      for (auto e : shape) {
        baseTy = mlir::LLVM::LLVMArrayType::get(baseTy, e);
        if (--i == 0)
          break;
      }
      if (seq.hasConstantShape())
        return baseTy;
    }
    return mlir::LLVM::LLVMPointerType::get(baseTy);
  }

  // fir.tdesc<any>  -->  llvm<"i8*">
  // TODO: For now use a void*, however pointer identity is not sufficient for
  // the f18 object v. class distinction (F2003).
  mlir::Type convertTypeDescType(mlir::MLIRContext *ctx) {
    return mlir::LLVM::LLVMPointerType::get(
        mlir::IntegerType::get(&getContext(), 8));
  }

  /// Convert llvm::Type::TypeID to mlir::Type
  mlir::Type fromRealTypeID(llvm::Type::TypeID typeID, fir::KindTy kind) {
    switch (typeID) {
    case llvm::Type::TypeID::HalfTyID:
      return mlir::FloatType::getF16(&getContext());
    case llvm::Type::TypeID::BFloatTyID:
      return mlir::FloatType::getBF16(&getContext());
    case llvm::Type::TypeID::FloatTyID:
      return mlir::FloatType::getF32(&getContext());
    case llvm::Type::TypeID::DoubleTyID:
      return mlir::FloatType::getF64(&getContext());
    case llvm::Type::TypeID::X86_FP80TyID:
      return mlir::FloatType::getF80(&getContext());
    case llvm::Type::TypeID::FP128TyID:
      return mlir::FloatType::getF128(&getContext());
    default:
      mlir::emitError(mlir::UnknownLoc::get(&getContext()))
          << "unsupported type: !fir.real<" << kind << ">";
      return {};
    }
  }

  KindMapping &getKindMap() { return kindMapping; }

private:
  KindMapping kindMapping;
  std::unique_ptr<CodeGenSpecifics> specifics;
};

} // namespace fir

#endif // FORTRAN_OPTIMIZER_CODEGEN_TYPECONVERTER_H
