//===-- CharacterExpr.cpp -------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//

#include "flang/Lower/CharacterExpr.h"
#include "flang/Lower/ConvertType.h"
#include "flang/Lower/DoLoopHelper.h"
#include "flang/Lower/IntrinsicCall.h"

//===----------------------------------------------------------------------===//
// CharacterExprHelper implementation
//===----------------------------------------------------------------------===//

/// Get fir.char<kind> type with the same kind as inside str.
static fir::CharacterType getCharacterType(mlir::Type type) {
  if (auto boxType = type.dyn_cast<fir::BoxCharType>())
    return boxType.getEleTy();
  if (auto refType = type.dyn_cast<fir::ReferenceType>())
    type = refType.getEleTy();
  if (auto seqType = type.dyn_cast<fir::SequenceType>()) {
    assert(seqType.getShape().size() == 1 && "rank must be 1");
    type = seqType.getEleTy();
  }
  if (auto charType = type.dyn_cast<fir::CharacterType>())
    return charType;
  llvm_unreachable("Invalid character value type");
}

static fir::CharacterType getCharacterType(const fir::CharBoxValue &box) {
  return getCharacterType(box.getBuffer().getType());
}

static bool needToMaterialize(const fir::CharBoxValue &box) {
  return box.getBuffer().getType().isa<fir::SequenceType>() ||
         box.getBuffer().getType().isa<fir::CharacterType>();
}

static std::optional<fir::SequenceType::Extent>
getCompileTimeLength(const fir::CharBoxValue &box) {
  // FIXME: should this just return box.getLen() ??
  auto type = box.getBuffer().getType();
  if (type.isa<fir::CharacterType>())
    return 1;
  if (auto refType = type.dyn_cast<fir::ReferenceType>())
    type = refType.getEleTy();
  if (auto seqType = type.dyn_cast<fir::SequenceType>()) {
    auto shape = seqType.getShape();
    assert(shape.size() == 1 && "only scalar character supported");
    if (shape[0] != fir::SequenceType::getUnknownExtent())
      return shape[0];
  }
  return {};
}

fir::CharBoxValue Fortran::lower::CharacterExprHelper::materializeValue(
    const fir::CharBoxValue &str) {
  if (!needToMaterialize(str))
    return str;
  auto variable = builder.create<fir::AllocaOp>(loc, str.getBuffer().getType());
  builder.create<fir::StoreOp>(loc, str.getBuffer(), variable);
  return {variable, str.getLen()};
}

fir::CharBoxValue
Fortran::lower::CharacterExprHelper::toDataLengthPair(mlir::Value character) {
  // TODO: get rid of toDataLengthPair when adding support for arrays
  auto charBox = toExtendedValue(character).getCharBox();
  assert(charBox && "Array unsupported in character lowering helper");
  return *charBox;
}

fir::ExtendedValue
Fortran::lower::CharacterExprHelper::toExtendedValue(mlir::Value character,
                                                     mlir::Value len) {
  auto lenType = getLengthType();
  auto type = character.getType();
  auto base = character;
  mlir::Value resultLen = len;
  llvm::SmallVector<mlir::Value, 2> extents;

  if (auto refType = type.dyn_cast<fir::ReferenceType>())
    type = refType.getEleTy();

  if (auto arrayType = type.dyn_cast<fir::SequenceType>()) {
    type = arrayType.getEleTy();
    auto shape = arrayType.getShape();
    auto cstLen = shape[0];
    if (!resultLen && cstLen != fir::SequenceType::getUnknownExtent())
      resultLen = builder.createIntegerConstant(loc, lenType, cstLen);
    // FIXME: only allow `?` in last dimension ?
    auto typeExtents =
        llvm::ArrayRef<fir::SequenceType::Extent>{shape}.drop_front();
    auto indexType = builder.getIndexType();
    for (auto extent : typeExtents) {
      if (extent == fir::SequenceType::getUnknownExtent())
        break;
      extents.emplace_back(
          builder.createIntegerConstant(loc, indexType, extent));
    }
    // Last extent might be missing in case of assumed-size. If more extents
    // could not be deduced from type, that's an error (a fir.box should
    // have been used in the interface).
    if (extents.size() + 1 < typeExtents.size())
      mlir::emitError(loc, "cannot retrieve array extents from type");
  } else if (type.isa<fir::CharacterType>()) {
    if (!resultLen)
      resultLen = builder.createIntegerConstant(loc, lenType, 1);
  } else if (auto boxCharType = type.dyn_cast<fir::BoxCharType>()) {
    auto refType = builder.getRefType(boxCharType.getEleTy());
    auto unboxed =
        builder.create<fir::UnboxCharOp>(loc, refType, lenType, character);
    base = unboxed.getResult(0);
    if (!resultLen)
      resultLen = unboxed.getResult(1);
  } else if (type.isa<fir::BoxType>()) {
    mlir::emitError(loc, "descriptor or derived type not yet handled");
  } else {
    llvm_unreachable("Cannot translate mlir::Value to character ExtendedValue");
  }

  if (!resultLen)
    mlir::emitError(loc, "no dynamic length found for character");
  if (!extents.empty())
    return fir::CharArrayBoxValue{base, resultLen, extents};
  return fir::CharBoxValue{base, resultLen};
}

/// Get fir.ref<fir.char<kind>> type.
mlir::Type Fortran::lower::CharacterExprHelper::getReferenceType(
    const fir::CharBoxValue &box) const {
  return builder.getRefType(getCharacterType(box));
}

mlir::Value
Fortran::lower::CharacterExprHelper::createEmbox(const fir::CharBoxValue &box) {
  // BoxChar require a reference.
  auto str = box;
  if (needToMaterialize(box))
    str = materializeValue(box);
  auto kind = getCharacterType(str).getFKind();
  auto boxCharType = fir::BoxCharType::get(builder.getContext(), kind);
  auto refType = getReferenceType(str);
  // So far, fir.emboxChar fails lowering to llvm when it is given
  // fir.ref<fir.array<len x fir.char<kind>>> types, so convert to
  // fir.ref<fir.char<kind>> if needed.
  auto buff = str.getBuffer();
  buff = builder.createConvert(loc, refType, buff);
  // Convert in case the provided length is not of the integer type that must
  // be used in boxchar.
  auto lenType = getLengthType();
  auto len = str.getLen();
  len = builder.createConvert(loc, lenType, len);
  return builder.create<fir::EmboxCharOp>(loc, boxCharType, buff, len);
}

mlir::Value Fortran::lower::CharacterExprHelper::createLoadCharAt(
    const fir::CharBoxValue &str, mlir::Value index) {
  // In case this is addressing a length one character scalar simply return
  // the single character.
  if (str.getBuffer().getType().isa<fir::CharacterType>())
    return str.getBuffer();
  auto addr = builder.create<fir::CoordinateOp>(loc, getReferenceType(str),
                                                str.getBuffer(), index);
  return builder.create<fir::LoadOp>(loc, addr);
}

void Fortran::lower::CharacterExprHelper::createStoreCharAt(
    const fir::CharBoxValue &str, mlir::Value index, mlir::Value c) {
  assert(!needToMaterialize(str) && "not in memory");
  auto addr = builder.create<fir::CoordinateOp>(loc, getReferenceType(str),
                                                str.getBuffer(), index);
  builder.create<fir::StoreOp>(loc, c, addr);
}

void Fortran::lower::CharacterExprHelper::createCopy(
    const fir::CharBoxValue &dest, const fir::CharBoxValue &src,
    mlir::Value count) {
  Fortran::lower::DoLoopHelper{builder, loc}.createLoop(
      count, [&](Fortran::lower::FirOpBuilder &, mlir::Value index) {
        auto charVal = createLoadCharAt(src, index);
        createStoreCharAt(dest, index, charVal);
      });
}

void Fortran::lower::CharacterExprHelper::createPadding(
    const fir::CharBoxValue &str, mlir::Value lower, mlir::Value upper) {
  auto blank = createBlankConstant(getCharacterType(str));
  // Always create the loop, if upper < lower, no iteration will be
  // executed.
  Fortran::lower::DoLoopHelper{builder, loc}.createLoop(
      lower, upper, [&](Fortran::lower::FirOpBuilder &, mlir::Value index) {
        createStoreCharAt(str, index, blank);
      });
}

fir::CharBoxValue
Fortran::lower::CharacterExprHelper::createTemp(mlir::Type type,
                                                mlir::Value len) {
  assert(type.isa<fir::CharacterType>() && "expected fir character type");
  llvm::SmallVector<mlir::Value, 3> sizes{len};
  auto ref = builder.allocateLocal(loc, type, llvm::StringRef{}, sizes);
  return {ref, len};
}

// Simple length one character assignment without loops.
void Fortran::lower::CharacterExprHelper::createLengthOneAssign(
    const fir::CharBoxValue &lhs, const fir::CharBoxValue &rhs) {
  auto addr = lhs.getBuffer();
  auto val = rhs.getBuffer();
  // If rhs value resides in memory, load it.
  if (!needToMaterialize(rhs))
    val = builder.create<fir::LoadOp>(loc, val);
  auto valTy = val.getType();
  // Precondition is rhs is size 1, but it may be wrapped in a fir.array.
  if (auto seqTy = valTy.dyn_cast<fir::SequenceType>()) {
    auto zero = builder.createIntegerConstant(loc, builder.getIndexType(), 0);
    valTy = seqTy.getEleTy();
    val = builder.create<fir::ExtractValueOp>(loc, valTy, val, zero);
  }
  auto addrTy = fir::ReferenceType::get(valTy);
  addr = builder.createConvert(loc, addrTy, addr);
  assert(fir::dyn_cast_ptrEleTy(addr.getType()) == val.getType());
  builder.create<fir::StoreOp>(loc, val, addr);
}

void Fortran::lower::CharacterExprHelper::createAssign(
    const fir::CharBoxValue &lhs, const fir::CharBoxValue &rhs) {
  auto rhsCstLen = getCompileTimeLength(rhs);
  auto lhsCstLen = getCompileTimeLength(lhs);
  bool compileTimeSameLength =
      lhsCstLen && rhsCstLen && *lhsCstLen == *rhsCstLen;

  if (compileTimeSameLength && *lhsCstLen == 1) {
    createLengthOneAssign(lhs, rhs);
    return;
  }

  // Copy the minimum of the lhs and rhs lengths and pad the lhs remainder
  // if needed.
  mlir::Value copyCount = lhs.getLen();
  if (!compileTimeSameLength)
    copyCount =
        Fortran::lower::genMin(builder, loc, {lhs.getLen(), rhs.getLen()});

  fir::CharBoxValue safeRhs = rhs;
  if (needToMaterialize(rhs)) {
    // TODO: revisit now that character constant handling changed.
    // Need to materialize the constant to get its elements.
    // (No equivalent of fir.coordinate_of for array value).
    safeRhs = materializeValue(rhs);
  } else {
    // If rhs is in memory, always assumes rhs might overlap with lhs
    // in a way that require a temp for the copy. That can be optimize later.
    // Only create a temp of copyCount size because we do not need more from
    // rhs.
    auto temp = createTemp(getCharacterType(rhs), copyCount);
    createCopy(temp, rhs, copyCount);
    safeRhs = temp;
  }

  // Actual copy
  createCopy(lhs, safeRhs, copyCount);

  // Pad if needed.
  if (!compileTimeSameLength) {
    auto one = builder.createIntegerConstant(loc, lhs.getLen().getType(), 1);
    auto maxPadding = builder.create<mlir::SubIOp>(loc, lhs.getLen(), one);
    createPadding(lhs, copyCount, maxPadding);
  }
}

fir::CharBoxValue Fortran::lower::CharacterExprHelper::createConcatenate(
    const fir::CharBoxValue &lhs, const fir::CharBoxValue &rhs) {
  mlir::Value len =
      builder.create<mlir::AddIOp>(loc, lhs.getLen(), rhs.getLen());
  auto temp = createTemp(getCharacterType(rhs), len);
  createCopy(temp, lhs, lhs.getLen());
  auto one = builder.createIntegerConstant(loc, len.getType(), 1);
  auto upperBound = builder.create<mlir::SubIOp>(loc, len, one);
  auto lhsLen =
      builder.createConvert(loc, builder.getIndexType(), lhs.getLen());
  Fortran::lower::DoLoopHelper{builder, loc}.createLoop(
      lhs.getLen(), upperBound, one,
      [&](Fortran::lower::FirOpBuilder &bldr, mlir::Value index) {
        auto rhsIndex = bldr.create<mlir::SubIOp>(loc, index, lhsLen);
        auto charVal = createLoadCharAt(rhs, rhsIndex);
        createStoreCharAt(temp, index, charVal);
      });
  return temp;
}

fir::CharBoxValue Fortran::lower::CharacterExprHelper::createSubstring(
    const fir::CharBoxValue &box, llvm::ArrayRef<mlir::Value> bounds) {
  // Constant need to be materialize in memory to use fir.coordinate_of.
  auto str = box;
  if (needToMaterialize(box))
    str = materializeValue(box);

  auto nbounds{bounds.size()};
  if (nbounds < 1 || nbounds > 2) {
    mlir::emitError(loc, "Incorrect number of bounds in substring");
    return {mlir::Value{}, mlir::Value{}};
  }
  mlir::SmallVector<mlir::Value, 2> castBounds;
  // Convert bounds to length type to do safe arithmetic on it.
  for (auto bound : bounds)
    castBounds.push_back(builder.createConvert(loc, getLengthType(), bound));
  auto lowerBound = castBounds[0];
  // FIR CoordinateOp is zero based but Fortran substring are one based.
  auto one = builder.createIntegerConstant(loc, lowerBound.getType(), 1);
  auto offset = builder.create<mlir::SubIOp>(loc, lowerBound, one).getResult();
  auto idxType = builder.getIndexType();
  if (offset.getType() != idxType)
    offset = builder.createConvert(loc, idxType, offset);
  auto substringRef = builder.create<fir::CoordinateOp>(
      loc, getReferenceType(str), str.getBuffer(), offset);

  // Compute the length.
  mlir::Value substringLen{};
  if (nbounds < 2) {
    substringLen =
        builder.create<mlir::SubIOp>(loc, str.getLen(), castBounds[0]);
  } else {
    substringLen =
        builder.create<mlir::SubIOp>(loc, castBounds[1], castBounds[0]);
  }
  substringLen = builder.create<mlir::AddIOp>(loc, substringLen, one);

  // Set length to zero if bounds were reversed (Fortran 2018 9.4.1)
  auto zero = builder.createIntegerConstant(loc, substringLen.getType(), 0);
  auto cdt = builder.create<mlir::CmpIOp>(loc, mlir::CmpIPredicate::slt,
                                          substringLen, zero);
  substringLen = builder.create<mlir::SelectOp>(loc, cdt, zero, substringLen);

  return {substringRef, substringLen};
}

mlir::Value Fortran::lower::CharacterExprHelper::createLenTrim(
    const fir::CharBoxValue &str) {
  return {};
}

mlir::Value Fortran::lower::CharacterExprHelper::createTemp(mlir::Type type,
                                                            int len) {
  assert(type.isa<fir::CharacterType>() && "expected fir character type");
  assert(len >= 0 && "expected positive length");
  fir::SequenceType::Shape shape{len};
  auto seqType = fir::SequenceType::get(shape, type);
  return builder.create<fir::AllocaOp>(loc, seqType);
}

// Returns integer with code for blank. The integer has the same
// size as the character. Blank has ascii space code for all kinds.
mlir::Value Fortran::lower::CharacterExprHelper::createBlankConstantCode(
    fir::CharacterType type) {
  auto bits = builder.getKindMap().getCharacterBitsize(type.getFKind());
  auto intType = builder.getIntegerType(bits);
  return builder.createIntegerConstant(loc, intType, ' ');
}

mlir::Value Fortran::lower::CharacterExprHelper::createBlankConstant(
    fir::CharacterType type) {
  return builder.createConvert(loc, type, createBlankConstantCode(type));
}

void Fortran::lower::CharacterExprHelper::createCopy(mlir::Value dest,
                                                     mlir::Value src,
                                                     mlir::Value count) {
  createCopy(toDataLengthPair(dest), toDataLengthPair(src), count);
}

void Fortran::lower::CharacterExprHelper::createPadding(mlir::Value str,
                                                        mlir::Value lower,
                                                        mlir::Value upper) {
  createPadding(toDataLengthPair(str), lower, upper);
}

mlir::Value Fortran::lower::CharacterExprHelper::createSubstring(
    mlir::Value str, llvm::ArrayRef<mlir::Value> bounds) {
  return createEmbox(createSubstring(toDataLengthPair(str), bounds));
}

void Fortran::lower::CharacterExprHelper::createAssign(mlir::Value lhs,
                                                       mlir::Value rhs) {
  createAssign(toDataLengthPair(lhs), toDataLengthPair(rhs));
}

mlir::Value
Fortran::lower::CharacterExprHelper::createLenTrim(mlir::Value str) {
  return createLenTrim(toDataLengthPair(str));
}

void Fortran::lower::CharacterExprHelper::createAssign(mlir::Value lptr,
                                                       mlir::Value llen,
                                                       mlir::Value rptr,
                                                       mlir::Value rlen) {
  createAssign(fir::CharBoxValue{lptr, llen}, fir::CharBoxValue{rptr, rlen});
}

mlir::Value
Fortran::lower::CharacterExprHelper::createConcatenate(mlir::Value lhs,
                                                       mlir::Value rhs) {
  return createEmbox(
      createConcatenate(toDataLengthPair(lhs), toDataLengthPair(rhs)));
}

mlir::Value
Fortran::lower::CharacterExprHelper::createEmboxChar(mlir::Value addr,
                                                     mlir::Value len) {
  return createEmbox(fir::CharBoxValue{addr, len});
}

std::pair<mlir::Value, mlir::Value>
Fortran::lower::CharacterExprHelper::createUnboxChar(mlir::Value boxChar) {
  auto box = toDataLengthPair(boxChar);
  return {box.getBuffer(), box.getLen()};
}

mlir::Value
Fortran::lower::CharacterExprHelper::createCharacterTemp(mlir::Type type,
                                                         mlir::Value len) {
  return createEmbox(createTemp(type, len));
}

std::pair<mlir::Value, mlir::Value>
Fortran::lower::CharacterExprHelper::materializeCharacter(mlir::Value str) {
  auto box = toDataLengthPair(str);
  if (needToMaterialize(box))
    box = materializeValue(box);
  return {box.getBuffer(), box.getLen()};
}

bool Fortran::lower::CharacterExprHelper::isCharacterLiteral(mlir::Type type) {
  if (auto seqType = type.dyn_cast<fir::SequenceType>())
    return (seqType.getShape().size() == 1) &&
           seqType.getEleTy().isa<fir::CharacterType>();
  return false;
}

bool Fortran::lower::CharacterExprHelper::isCharacter(mlir::Type type) {
  if (type.isa<fir::BoxCharType>())
    return true;
  if (auto refType = type.dyn_cast<fir::ReferenceType>())
    type = refType.getEleTy();
  if (auto seqType = type.dyn_cast<fir::SequenceType>())
    if (seqType.getShape().size() == 1)
      type = seqType.getEleTy();
  return type.isa<fir::CharacterType>();
}

int Fortran::lower::CharacterExprHelper::getCharacterKind(mlir::Type type) {
  return getCharacterType(type).getFKind();
}
