//===-- Target.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
//
//===----------------------------------------------------------------------===//
//
// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
//
//===----------------------------------------------------------------------===//

#include "flang/Optimizer/CodeGen/Target.h"
#include "flang/Optimizer/Builder/Todo.h"
#include "flang/Optimizer/Dialect/FIRType.h"
#include "flang/Optimizer/Dialect/Support/KindMapping.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/TypeRange.h"
#include "llvm/ADT/TypeSwitch.h"
#include <cmath>

#define DEBUG_TYPE "flang-codegen-target"

using namespace fir;

namespace fir::details {
llvm::StringRef Attributes::getIntExtensionAttrName() const {
  // The attribute names are available via LLVM dialect interfaces
  // like getZExtAttrName(), getByValAttrName(), etc., so we'd better
  // use them than literals.
  if (isZeroExt())
    return "llvm.zeroext";
  else if (isSignExt())
    return "llvm.signext";
  return {};
}
} // namespace fir::details

// Reduce a REAL/float type to the floating point semantics.
static const llvm::fltSemantics &floatToSemantics(const KindMapping &kindMap,
                                                  mlir::Type type) {
  assert(isa_real(type));
  return mlir::cast<mlir::FloatType>(type).getFloatSemantics();
}

static void typeTodo(const llvm::fltSemantics *sem, mlir::Location loc,
                     const std::string &context) {
  if (sem == &llvm::APFloat::IEEEhalf()) {
    TODO(loc, "COMPLEX(KIND=2): for " + context + " type");
  } else if (sem == &llvm::APFloat::BFloat()) {
    TODO(loc, "COMPLEX(KIND=3): " + context + " type");
  } else if (sem == &llvm::APFloat::x87DoubleExtended()) {
    TODO(loc, "COMPLEX(KIND=10): " + context + " type");
  } else {
    TODO(loc, "complex for this precision for " + context + " type");
  }
}

namespace {
template <typename S>
struct GenericTarget : public CodeGenSpecifics {
  using CodeGenSpecifics::CodeGenSpecifics;
  using AT = CodeGenSpecifics::Attributes;

  mlir::Type complexMemoryType(mlir::Type eleTy) const override {
    assert(fir::isa_real(eleTy));
    // Use a type that will be translated into LLVM as:
    // { t, t }   struct of 2 eleTy
    return mlir::TupleType::get(eleTy.getContext(),
                                mlir::TypeRange{eleTy, eleTy});
  }

  mlir::Type boxcharMemoryType(mlir::Type eleTy) const override {
    auto idxTy = mlir::IntegerType::get(eleTy.getContext(), S::defaultWidth);
    auto ptrTy = fir::ReferenceType::get(eleTy);
    // Use a type that will be translated into LLVM as:
    // { t*, index }
    return mlir::TupleType::get(eleTy.getContext(),
                                mlir::TypeRange{ptrTy, idxTy});
  }

  Marshalling boxcharArgumentType(mlir::Type eleTy) const override {
    CodeGenSpecifics::Marshalling marshal;
    auto idxTy = mlir::IntegerType::get(eleTy.getContext(), S::defaultWidth);
    auto ptrTy = fir::ReferenceType::get(eleTy);
    marshal.emplace_back(ptrTy, AT{});
    // Characters are passed in a split format with all pointers first (in the
    // declared position) and all LEN arguments appended after all of the dummy
    // arguments.
    // NB: Other conventions/ABIs can/should be supported via options.
    marshal.emplace_back(idxTy, AT{/*alignment=*/0, /*byval=*/false,
                                   /*sret=*/false, /*append=*/true});
    return marshal;
  }

  CodeGenSpecifics::Marshalling
  structArgumentType(mlir::Location loc, fir::RecordType,
                     const Marshalling &) const override {
    TODO(loc, "passing VALUE BIND(C) derived type for this target");
  }

  CodeGenSpecifics::Marshalling
  structReturnType(mlir::Location loc, fir::RecordType ty) const override {
    TODO(loc, "returning BIND(C) derived type for this target");
  }

  CodeGenSpecifics::Marshalling
  integerArgumentType(mlir::Location loc,
                      mlir::IntegerType argTy) const override {
    CodeGenSpecifics::Marshalling marshal;
    AT::IntegerExtension intExt = AT::IntegerExtension::None;
    if (argTy.getWidth() < getCIntTypeWidth()) {
      // isSigned() and isUnsigned() branches below are dead code currently.
      // If needed, we can generate calls with signed/unsigned argument types
      // to more precisely match C side (e.g. for Fortran runtime functions
      // with 'unsigned short' arguments).
      if (argTy.isSigned())
        intExt = AT::IntegerExtension::Sign;
      else if (argTy.isUnsigned())
        intExt = AT::IntegerExtension::Zero;
      else if (argTy.isSignless()) {
        // Zero extend for 'i1' and sign extend for other types.
        if (argTy.getWidth() == 1)
          intExt = AT::IntegerExtension::Zero;
        else
          intExt = AT::IntegerExtension::Sign;
      }
    }

    marshal.emplace_back(argTy, AT{/*alignment=*/0, /*byval=*/false,
                                   /*sret=*/false, /*append=*/false,
                                   /*intExt=*/intExt});
    return marshal;
  }

  CodeGenSpecifics::Marshalling
  integerReturnType(mlir::Location loc,
                    mlir::IntegerType argTy) const override {
    return integerArgumentType(loc, argTy);
  }

  // Width of 'int' type is 32-bits for almost all targets, except
  // for AVR and MSP430 (see TargetInfo initializations
  // in clang/lib/Basic/Targets).
  unsigned char getCIntTypeWidth() const override { return 32; }
};
} // namespace

//===----------------------------------------------------------------------===//
// i386 (x86 32 bit) linux target specifics.
//===----------------------------------------------------------------------===//

namespace {
struct TargetI386 : public GenericTarget<TargetI386> {
  using GenericTarget::GenericTarget;

  static constexpr int defaultWidth = 32;

  CodeGenSpecifics::Marshalling
  complexArgumentType(mlir::Location, mlir::Type eleTy) const override {
    assert(fir::isa_real(eleTy));
    CodeGenSpecifics::Marshalling marshal;
    // Use a type that will be translated into LLVM as:
    // { t, t }   struct of 2 eleTy, byval, align 4
    auto structTy =
        mlir::TupleType::get(eleTy.getContext(), mlir::TypeRange{eleTy, eleTy});
    marshal.emplace_back(fir::ReferenceType::get(structTy),
                         AT{/*alignment=*/4, /*byval=*/true});
    return marshal;
  }

  CodeGenSpecifics::Marshalling
  complexReturnType(mlir::Location loc, mlir::Type eleTy) const override {
    assert(fir::isa_real(eleTy));
    CodeGenSpecifics::Marshalling marshal;
    const auto *sem = &floatToSemantics(kindMap, eleTy);
    if (sem == &llvm::APFloat::IEEEsingle()) {
      // i64   pack both floats in a 64-bit GPR
      marshal.emplace_back(mlir::IntegerType::get(eleTy.getContext(), 64),
                           AT{});
    } else if (sem == &llvm::APFloat::IEEEdouble()) {
      // Use a type that will be translated into LLVM as:
      // { t, t }   struct of 2 eleTy, sret, align 4
      auto structTy = mlir::TupleType::get(eleTy.getContext(),
                                           mlir::TypeRange{eleTy, eleTy});
      marshal.emplace_back(fir::ReferenceType::get(structTy),
                           AT{/*alignment=*/4, /*byval=*/false, /*sret=*/true});
    } else {
      typeTodo(sem, loc, "return");
    }
    return marshal;
  }
};
} // namespace

//===----------------------------------------------------------------------===//
// i386 (x86 32 bit) Windows target specifics.
//===----------------------------------------------------------------------===//

namespace {
struct TargetI386Win : public GenericTarget<TargetI386Win> {
  using GenericTarget::GenericTarget;

  static constexpr int defaultWidth = 32;

  CodeGenSpecifics::Marshalling
  complexArgumentType(mlir::Location loc, mlir::Type eleTy) const override {
    CodeGenSpecifics::Marshalling marshal;
    // Use a type that will be translated into LLVM as:
    // { t, t }   struct of 2 eleTy, byval, align 4
    auto structTy =
        mlir::TupleType::get(eleTy.getContext(), mlir::TypeRange{eleTy, eleTy});
    marshal.emplace_back(fir::ReferenceType::get(structTy),
                         AT{/*align=*/4, /*byval=*/true});
    return marshal;
  }

  CodeGenSpecifics::Marshalling
  complexReturnType(mlir::Location loc, mlir::Type eleTy) const override {
    CodeGenSpecifics::Marshalling marshal;
    const auto *sem = &floatToSemantics(kindMap, eleTy);
    if (sem == &llvm::APFloat::IEEEsingle()) {
      // i64   pack both floats in a 64-bit GPR
      marshal.emplace_back(mlir::IntegerType::get(eleTy.getContext(), 64),
                           AT{});
    } else if (sem == &llvm::APFloat::IEEEdouble()) {
      // Use a type that will be translated into LLVM as:
      // { double, double }   struct of 2 double, sret, align 8
      marshal.emplace_back(
          fir::ReferenceType::get(mlir::TupleType::get(
              eleTy.getContext(), mlir::TypeRange{eleTy, eleTy})),
          AT{/*align=*/8, /*byval=*/false, /*sret=*/true});
    } else if (sem == &llvm::APFloat::IEEEquad()) {
      // Use a type that will be translated into LLVM as:
      // { fp128, fp128 }   struct of 2 fp128, sret, align 16
      marshal.emplace_back(
          fir::ReferenceType::get(mlir::TupleType::get(
              eleTy.getContext(), mlir::TypeRange{eleTy, eleTy})),
          AT{/*align=*/16, /*byval=*/false, /*sret=*/true});
    } else if (sem == &llvm::APFloat::x87DoubleExtended()) {
      // Use a type that will be translated into LLVM as:
      // { x86_fp80, x86_fp80 }   struct of 2 x86_fp80, sret, align 4
      marshal.emplace_back(
          fir::ReferenceType::get(mlir::TupleType::get(
              eleTy.getContext(), mlir::TypeRange{eleTy, eleTy})),
          AT{/*align=*/4, /*byval=*/false, /*sret=*/true});
    } else {
      typeTodo(sem, loc, "return");
    }
    return marshal;
  }
};
} // namespace

//===----------------------------------------------------------------------===//
// x86_64 (x86 64 bit) linux target specifics.
//===----------------------------------------------------------------------===//

namespace {
struct TargetX86_64 : public GenericTarget<TargetX86_64> {
  using GenericTarget::GenericTarget;

  static constexpr int defaultWidth = 64;

  CodeGenSpecifics::Marshalling
  complexArgumentType(mlir::Location loc, mlir::Type eleTy) const override {
    CodeGenSpecifics::Marshalling marshal;
    const auto *sem = &floatToSemantics(kindMap, eleTy);
    if (sem == &llvm::APFloat::IEEEsingle()) {
      // <2 x t>   vector of 2 eleTy
      marshal.emplace_back(fir::VectorType::get(2, eleTy), AT{});
    } else if (sem == &llvm::APFloat::IEEEdouble()) {
      // FIXME: In case of SSE register exhaustion, the ABI here may be
      // incorrect since LLVM may pass the real via register and the imaginary
      // part via the stack while the ABI it should be all in register or all
      // in memory. Register occupancy must be analyzed here.
      // two distinct double arguments
      marshal.emplace_back(eleTy, AT{});
      marshal.emplace_back(eleTy, AT{});
    } else if (sem == &llvm::APFloat::x87DoubleExtended()) {
      // Use a type that will be translated into LLVM as:
      // { x86_fp80, x86_fp80 }  struct of 2 fp128, byval, align 16
      marshal.emplace_back(
          fir::ReferenceType::get(mlir::TupleType::get(
              eleTy.getContext(), mlir::TypeRange{eleTy, eleTy})),
          AT{/*align=*/16, /*byval=*/true});
    } else if (sem == &llvm::APFloat::IEEEquad()) {
      // Use a type that will be translated into LLVM as:
      // { fp128, fp128 }   struct of 2 fp128, byval, align 16
      marshal.emplace_back(
          fir::ReferenceType::get(mlir::TupleType::get(
              eleTy.getContext(), mlir::TypeRange{eleTy, eleTy})),
          AT{/*align=*/16, /*byval=*/true});
    } else {
      typeTodo(sem, loc, "argument");
    }
    return marshal;
  }

  CodeGenSpecifics::Marshalling
  complexReturnType(mlir::Location loc, mlir::Type eleTy) const override {
    CodeGenSpecifics::Marshalling marshal;
    const auto *sem = &floatToSemantics(kindMap, eleTy);
    if (sem == &llvm::APFloat::IEEEsingle()) {
      // <2 x t>   vector of 2 eleTy
      marshal.emplace_back(fir::VectorType::get(2, eleTy), AT{});
    } else if (sem == &llvm::APFloat::IEEEdouble()) {
      // Use a type that will be translated into LLVM as:
      // { double, double }   struct of 2 double
      marshal.emplace_back(mlir::TupleType::get(eleTy.getContext(),
                                                mlir::TypeRange{eleTy, eleTy}),
                           AT{});
    } else if (sem == &llvm::APFloat::x87DoubleExtended()) {
      // { x86_fp80, x86_fp80 }
      marshal.emplace_back(mlir::TupleType::get(eleTy.getContext(),
                                                mlir::TypeRange{eleTy, eleTy}),
                           AT{});
    } else if (sem == &llvm::APFloat::IEEEquad()) {
      // Use a type that will be translated into LLVM as:
      // { fp128, fp128 }   struct of 2 fp128, sret, align 16
      marshal.emplace_back(
          fir::ReferenceType::get(mlir::TupleType::get(
              eleTy.getContext(), mlir::TypeRange{eleTy, eleTy})),
          AT{/*align=*/16, /*byval=*/false, /*sret=*/true});
    } else {
      typeTodo(sem, loc, "return");
    }
    return marshal;
  }

  /// X86-64 argument classes from System V ABI version 1.0 section 3.2.3.
  enum ArgClass {
    Integer = 0,
    SSE,
    SSEUp,
    X87,
    X87Up,
    ComplexX87,
    NoClass,
    Memory
  };

  /// Classify an argument type or a field of an aggregate type argument.
  /// See System V ABI version 1.0 section 3.2.3.
  /// The Lo and Hi class are set to the class of the lower eight eightbytes
  /// and upper eight eightbytes on return.
  /// If this is called for an aggregate field, the caller is responsible to
  /// do the post-merge.
  void classify(mlir::Location loc, mlir::Type type, std::uint64_t byteOffset,
                ArgClass &Lo, ArgClass &Hi) const {
    Hi = Lo = ArgClass::NoClass;
    ArgClass &current = byteOffset < 8 ? Lo : Hi;
    // System V AMD64 ABI 3.2.3. version 1.0
    llvm::TypeSwitch<mlir::Type>(type)
        .Case([&](mlir::IntegerType intTy) {
          if (intTy.getWidth() == 128)
            Hi = Lo = ArgClass::Integer;
          else
            current = ArgClass::Integer;
        })
        .template Case<mlir::FloatType>([&](mlir::Type floatTy) {
          const auto *sem = &floatToSemantics(kindMap, floatTy);
          if (sem == &llvm::APFloat::x87DoubleExtended()) {
            Lo = ArgClass::X87;
            Hi = ArgClass::X87Up;
          } else if (sem == &llvm::APFloat::IEEEquad()) {
            Lo = ArgClass::SSE;
            Hi = ArgClass::SSEUp;
          } else {
            current = ArgClass::SSE;
          }
        })
        .Case([&](mlir::ComplexType cmplx) {
          const auto *sem = &floatToSemantics(kindMap, cmplx.getElementType());
          if (sem == &llvm::APFloat::x87DoubleExtended()) {
            current = ArgClass::ComplexX87;
          } else {
            fir::SequenceType::Shape shape{2};
            classifyArray(loc,
                          fir::SequenceType::get(shape, cmplx.getElementType()),
                          byteOffset, Lo, Hi);
          }
        })
        .Case([&](fir::LogicalType logical) {
          if (kindMap.getLogicalBitsize(logical.getFKind()) == 128)
            Hi = Lo = ArgClass::Integer;
          else
            current = ArgClass::Integer;
        })
        .Case(
            [&](fir::CharacterType character) { current = ArgClass::Integer; })
        .Case([&](fir::SequenceType seqTy) {
          // Array component.
          classifyArray(loc, seqTy, byteOffset, Lo, Hi);
        })
        .Case([&](fir::RecordType recTy) {
          // Component that is a derived type.
          classifyStruct(loc, recTy, byteOffset, Lo, Hi);
        })
        .Case([&](fir::VectorType vecTy) {
          // Previously marshalled SSE eight byte for a previous struct
          // argument.
          auto *sem = fir::isa_real(vecTy.getEleTy())
                          ? &floatToSemantics(kindMap, vecTy.getEleTy())
                          : nullptr;
          // Not expecting to hit this todo in standard code (it would
          // require some vector type extension).
          if (!(sem == &llvm::APFloat::IEEEsingle() && vecTy.getLen() <= 2) &&
              !(sem == &llvm::APFloat::IEEEhalf() && vecTy.getLen() <= 4))
            TODO(loc, "passing vector argument to C by value");
          current = SSE;
        })
        .Default([&](mlir::Type ty) {
          if (fir::conformsWithPassByRef(ty))
            current = ArgClass::Integer; // Pointers.
          else
            TODO(loc, "unsupported component type for BIND(C), VALUE derived "
                      "type argument");
        });
  }

  // Classify fields of a derived type starting at \p offset. Returns the new
  // offset. Post-merge is left to the caller.
  std::uint64_t classifyStruct(mlir::Location loc, fir::RecordType recTy,
                               std::uint64_t byteOffset, ArgClass &Lo,
                               ArgClass &Hi) const {
    for (auto component : recTy.getTypeList()) {
      if (byteOffset > 16) {
        // See 3.2.3 p. 1 and note 15. Note that when the offset is bigger
        // than 16 bytes here, it is not a single _m256 and or _m512 entity
        // that could fit in AVX registers.
        Lo = Hi = ArgClass::Memory;
        return byteOffset;
      }
      mlir::Type compType = component.second;
      auto [compSize, compAlign] = fir::getTypeSizeAndAlignmentOrCrash(
          loc, compType, getDataLayout(), kindMap);
      byteOffset = llvm::alignTo(byteOffset, compAlign);
      ArgClass LoComp, HiComp;
      classify(loc, compType, byteOffset, LoComp, HiComp);
      Lo = mergeClass(Lo, LoComp);
      Hi = mergeClass(Hi, HiComp);
      byteOffset = byteOffset + llvm::alignTo(compSize, compAlign);
      if (Lo == ArgClass::Memory || Hi == ArgClass::Memory)
        return byteOffset;
    }
    return byteOffset;
  }

  // Classify fields of a constant size array type starting at \p offset.
  // Returns the new offset. Post-merge is left to the caller.
  void classifyArray(mlir::Location loc, fir::SequenceType seqTy,
                     std::uint64_t byteOffset, ArgClass &Lo,
                     ArgClass &Hi) const {
    mlir::Type eleTy = seqTy.getEleTy();
    const std::uint64_t arraySize = seqTy.getConstantArraySize();
    auto [eleSize, eleAlign] = fir::getTypeSizeAndAlignmentOrCrash(
        loc, eleTy, getDataLayout(), kindMap);
    std::uint64_t eleStorageSize = llvm::alignTo(eleSize, eleAlign);
    for (std::uint64_t i = 0; i < arraySize; ++i) {
      byteOffset = llvm::alignTo(byteOffset, eleAlign);
      if (byteOffset > 16) {
        // See 3.2.3 p. 1 and note 15. Same as in classifyStruct.
        Lo = Hi = ArgClass::Memory;
        return;
      }
      ArgClass LoComp, HiComp;
      classify(loc, eleTy, byteOffset, LoComp, HiComp);
      Lo = mergeClass(Lo, LoComp);
      Hi = mergeClass(Hi, HiComp);
      byteOffset = byteOffset + eleStorageSize;
      if (Lo == ArgClass::Memory || Hi == ArgClass::Memory)
        return;
    }
  }

  // Goes through the previously marshalled arguments and count the
  // register occupancy to check if there are enough registers left.
  bool hasEnoughRegisters(mlir::Location loc, int neededIntRegisters,
                          int neededSSERegisters,
                          const Marshalling &previousArguments) const {
    int availIntRegisters = 6;
    int availSSERegisters = 8;
    for (auto typeAndAttr : previousArguments) {
      const auto &attr = std::get<Attributes>(typeAndAttr);
      if (attr.isByVal())
        continue; // Previous argument passed on the stack.
      ArgClass Lo, Hi;
      Lo = Hi = ArgClass::NoClass;
      classify(loc, std::get<mlir::Type>(typeAndAttr), 0, Lo, Hi);
      // post merge is not needed here since previous aggregate arguments
      // were marshalled into simpler arguments.
      if (Lo == ArgClass::Integer)
        --availIntRegisters;
      else if (Lo == SSE)
        --availSSERegisters;
      if (Hi == ArgClass::Integer)
        --availIntRegisters;
      else if (Hi == ArgClass::SSE)
        --availSSERegisters;
    }
    return availSSERegisters >= neededSSERegisters &&
           availIntRegisters >= neededIntRegisters;
  }

  /// Argument class merging as described in System V ABI 3.2.3 point 4.
  ArgClass mergeClass(ArgClass accum, ArgClass field) const {
    assert((accum != ArgClass::Memory && accum != ArgClass::ComplexX87) &&
           "Invalid accumulated classification during merge.");
    if (accum == field || field == NoClass)
      return accum;
    if (field == ArgClass::Memory)
      return ArgClass::Memory;
    if (accum == NoClass)
      return field;
    if (accum == Integer || field == Integer)
      return ArgClass::Integer;
    if (field == ArgClass::X87 || field == ArgClass::X87Up ||
        field == ArgClass::ComplexX87 || accum == ArgClass::X87 ||
        accum == ArgClass::X87Up)
      return Memory;
    return SSE;
  }

  /// Argument class post merging as described in System V ABI 3.2.3 point 5.
  void postMerge(std::uint64_t byteSize, ArgClass &Lo, ArgClass &Hi) const {
    if (Hi == ArgClass::Memory)
      Lo = ArgClass::Memory;
    if (Hi == ArgClass::X87Up && Lo != ArgClass::X87)
      Lo = ArgClass::Memory;
    if (byteSize > 16 && (Lo != ArgClass::SSE || Hi != ArgClass::SSEUp))
      Lo = ArgClass::Memory;
    if (Hi == ArgClass::SSEUp && Lo != ArgClass::SSE)
      Hi = SSE;
  }

  /// When \p recTy is a one field record type that can be passed
  /// like the field on its own, returns the field type. Returns
  /// a null type otherwise.
  mlir::Type passAsFieldIfOneFieldStruct(fir::RecordType recTy,
                                         bool allowComplex = false) const {
    auto typeList = recTy.getTypeList();
    if (typeList.size() != 1)
      return {};
    mlir::Type fieldType = typeList[0].second;
    if (mlir::isa<mlir::FloatType, mlir::IntegerType, fir::LogicalType>(
            fieldType))
      return fieldType;
    if (allowComplex && mlir::isa<mlir::ComplexType>(fieldType))
      return fieldType;
    if (mlir::isa<fir::CharacterType>(fieldType)) {
      // Only CHARACTER(1) are expected in BIND(C) contexts, which is the only
      // contexts where derived type may be passed in registers.
      assert(mlir::cast<fir::CharacterType>(fieldType).getLen() == 1 &&
             "fir.type value arg character components must have length 1");
      return fieldType;
    }
    // Complex field that needs to be split, or array.
    return {};
  }

  mlir::Type pickLLVMArgType(mlir::Location loc, mlir::MLIRContext *context,
                             ArgClass argClass,
                             std::uint64_t partByteSize) const {
    if (argClass == ArgClass::SSE) {
      if (partByteSize > 16)
        TODO(loc, "passing struct as a real > 128 bits in register");
      // Clang uses vector type when several fp fields are marshalled
      // into a single SSE register (like  <n x smallest fp field> ).
      // It should make no difference from an ABI point of view to just
      // select an fp type of the right size, and it makes things simpler
      // here.
      if (partByteSize > 8)
        return mlir::Float128Type::get(context);
      if (partByteSize > 4)
        return mlir::Float64Type::get(context);
      if (partByteSize > 2)
        return mlir::Float32Type::get(context);
      return mlir::Float16Type::get(context);
    }
    assert(partByteSize <= 8 &&
           "expect integer part of aggregate argument to fit into eight bytes");
    if (partByteSize > 4)
      return mlir::IntegerType::get(context, 64);
    if (partByteSize > 2)
      return mlir::IntegerType::get(context, 32);
    if (partByteSize > 1)
      return mlir::IntegerType::get(context, 16);
    return mlir::IntegerType::get(context, 8);
  }

  /// Marshal a derived type passed by value like a C struct.
  CodeGenSpecifics::Marshalling
  structArgumentType(mlir::Location loc, fir::RecordType recTy,
                     const Marshalling &previousArguments) const override {
    std::uint64_t byteOffset = 0;
    ArgClass Lo, Hi;
    Lo = Hi = ArgClass::NoClass;
    byteOffset = classifyStruct(loc, recTy, byteOffset, Lo, Hi);
    postMerge(byteOffset, Lo, Hi);
    if (Lo == ArgClass::Memory || Lo == ArgClass::X87 ||
        Lo == ArgClass::ComplexX87)
      return passOnTheStack(loc, recTy, /*isResult=*/false);
    int neededIntRegisters = 0;
    int neededSSERegisters = 0;
    if (Lo == ArgClass::SSE)
      ++neededSSERegisters;
    else if (Lo == ArgClass::Integer)
      ++neededIntRegisters;
    if (Hi == ArgClass::SSE)
      ++neededSSERegisters;
    else if (Hi == ArgClass::Integer)
      ++neededIntRegisters;
    // C struct should not be split into LLVM registers if LLVM codegen is not
    // able to later assign actual registers to all of them (struct passing is
    // all in registers or all on the stack).
    if (!hasEnoughRegisters(loc, neededIntRegisters, neededSSERegisters,
                            previousArguments))
      return passOnTheStack(loc, recTy, /*isResult=*/false);

    if (auto fieldType = passAsFieldIfOneFieldStruct(recTy)) {
      CodeGenSpecifics::Marshalling marshal;
      marshal.emplace_back(fieldType, AT{});
      return marshal;
    }
    if (Hi == ArgClass::NoClass || Hi == ArgClass::SSEUp) {
      // Pass a single integer or floating point argument.
      mlir::Type lowType =
          pickLLVMArgType(loc, recTy.getContext(), Lo, byteOffset);
      CodeGenSpecifics::Marshalling marshal;
      marshal.emplace_back(lowType, AT{});
      return marshal;
    }
    // Split into two integer or floating point arguments.
    // Note that for the first argument, this will always pick i64 or f64 which
    // may be bigger than needed if some struct padding ends the first eight
    // byte (e.g. for `{i32, f64}`). It is valid from an X86-64 ABI and
    // semantic point of view, but it may not match the LLVM IR interface clang
    // would produce for the equivalent C code (the assembly will still be
    // compatible).  This allows keeping the logic simpler here since it
    // avoids computing the "data" size of the Lo part.
    mlir::Type lowType = pickLLVMArgType(loc, recTy.getContext(), Lo, 8u);
    mlir::Type hiType =
        pickLLVMArgType(loc, recTy.getContext(), Hi, byteOffset - 8u);
    CodeGenSpecifics::Marshalling marshal;
    marshal.emplace_back(lowType, AT{});
    marshal.emplace_back(hiType, AT{});
    return marshal;
  }

  CodeGenSpecifics::Marshalling
  structReturnType(mlir::Location loc, fir::RecordType recTy) const override {
    std::uint64_t byteOffset = 0;
    ArgClass Lo, Hi;
    Lo = Hi = ArgClass::NoClass;
    byteOffset = classifyStruct(loc, recTy, byteOffset, Lo, Hi);
    mlir::MLIRContext *context = recTy.getContext();
    postMerge(byteOffset, Lo, Hi);
    if (Lo == ArgClass::Memory)
      return passOnTheStack(loc, recTy, /*isResult=*/true);

    // Note that X87/ComplexX87 are passed in memory, but returned via %st0
    // %st1 registers. Here, they are returned as fp80 or {fp80, fp80} by
    // passAsFieldIfOneFieldStruct, and LLVM will use the expected registers.

    // Note that {_Complex long double} is not 100% clear from an ABI
    // perspective because the aggregate post merger rules say it should be
    // passed in memory because it is bigger than 2 eight bytes. This has the
    // funny effect of
    // {_Complex long double} return to be dealt with differently than
    // _Complex long double.

    if (auto fieldType =
            passAsFieldIfOneFieldStruct(recTy, /*allowComplex=*/true)) {
      if (auto complexType = mlir::dyn_cast<mlir::ComplexType>(fieldType))
        return complexReturnType(loc, complexType.getElementType());
      CodeGenSpecifics::Marshalling marshal;
      marshal.emplace_back(fieldType, AT{});
      return marshal;
    }

    if (Hi == ArgClass::NoClass || Hi == ArgClass::SSEUp) {
      // Return a single integer or floating point argument.
      mlir::Type lowType = pickLLVMArgType(loc, context, Lo, byteOffset);
      CodeGenSpecifics::Marshalling marshal;
      marshal.emplace_back(lowType, AT{});
      return marshal;
    }
    // Will be returned in two different registers. Generate {lowTy, HiTy} for
    // the LLVM IR result type.
    CodeGenSpecifics::Marshalling marshal;
    mlir::Type lowType = pickLLVMArgType(loc, context, Lo, 8u);
    mlir::Type hiType = pickLLVMArgType(loc, context, Hi, byteOffset - 8u);
    marshal.emplace_back(mlir::TupleType::get(context, {lowType, hiType}),
                         AT{});
    return marshal;
  }

  /// Marshal an argument that must be passed on the stack.
  CodeGenSpecifics::Marshalling
  passOnTheStack(mlir::Location loc, mlir::Type ty, bool isResult) const {
    CodeGenSpecifics::Marshalling marshal;
    auto sizeAndAlign =
        fir::getTypeSizeAndAlignmentOrCrash(loc, ty, getDataLayout(), kindMap);
    // The stack is always 8 byte aligned (note 14 in 3.2.3).
    unsigned short align =
        std::max(sizeAndAlign.second, static_cast<unsigned short>(8));
    marshal.emplace_back(fir::ReferenceType::get(ty),
                         AT{align, /*byval=*/!isResult, /*sret=*/isResult});
    return marshal;
  }
};
} // namespace

//===----------------------------------------------------------------------===//
// x86_64 (x86 64 bit) Windows target specifics.
//===----------------------------------------------------------------------===//

namespace {
struct TargetX86_64Win : public GenericTarget<TargetX86_64Win> {
  using GenericTarget::GenericTarget;

  static constexpr int defaultWidth = 64;

  CodeGenSpecifics::Marshalling
  complexArgumentType(mlir::Location loc, mlir::Type eleTy) const override {
    CodeGenSpecifics::Marshalling marshal;
    const auto *sem = &floatToSemantics(kindMap, eleTy);
    if (sem == &llvm::APFloat::IEEEsingle()) {
      // i64   pack both floats in a 64-bit GPR
      marshal.emplace_back(mlir::IntegerType::get(eleTy.getContext(), 64),
                           AT{});
    } else if (sem == &llvm::APFloat::IEEEdouble()) {
      // Use a type that will be translated into LLVM as:
      // { double, double }   struct of 2 double, byval, align 8
      marshal.emplace_back(
          fir::ReferenceType::get(mlir::TupleType::get(
              eleTy.getContext(), mlir::TypeRange{eleTy, eleTy})),
          AT{/*align=*/8, /*byval=*/true});
    } else if (sem == &llvm::APFloat::IEEEquad() ||
               sem == &llvm::APFloat::x87DoubleExtended()) {
      // Use a type that will be translated into LLVM as:
      // { t, t }   struct of 2 eleTy, byval, align 16
      marshal.emplace_back(
          fir::ReferenceType::get(mlir::TupleType::get(
              eleTy.getContext(), mlir::TypeRange{eleTy, eleTy})),
          AT{/*align=*/16, /*byval=*/true});
    } else {
      typeTodo(sem, loc, "argument");
    }
    return marshal;
  }

  CodeGenSpecifics::Marshalling
  complexReturnType(mlir::Location loc, mlir::Type eleTy) const override {
    CodeGenSpecifics::Marshalling marshal;
    const auto *sem = &floatToSemantics(kindMap, eleTy);
    if (sem == &llvm::APFloat::IEEEsingle()) {
      // i64   pack both floats in a 64-bit GPR
      marshal.emplace_back(mlir::IntegerType::get(eleTy.getContext(), 64),
                           AT{});
    } else if (sem == &llvm::APFloat::IEEEdouble()) {
      // Use a type that will be translated into LLVM as:
      // { double, double }   struct of 2 double, sret, align 8
      marshal.emplace_back(
          fir::ReferenceType::get(mlir::TupleType::get(
              eleTy.getContext(), mlir::TypeRange{eleTy, eleTy})),
          AT{/*align=*/8, /*byval=*/false, /*sret=*/true});
    } else if (sem == &llvm::APFloat::IEEEquad() ||
               sem == &llvm::APFloat::x87DoubleExtended()) {
      // Use a type that will be translated into LLVM as:
      // { t, t }   struct of 2 eleTy, sret, align 16
      marshal.emplace_back(
          fir::ReferenceType::get(mlir::TupleType::get(
              eleTy.getContext(), mlir::TypeRange{eleTy, eleTy})),
          AT{/*align=*/16, /*byval=*/false, /*sret=*/true});
    } else {
      typeTodo(sem, loc, "return");
    }
    return marshal;
  }
};
} // namespace

//===----------------------------------------------------------------------===//
// AArch64 target specifics.
//===----------------------------------------------------------------------===//

namespace {
// AArch64 procedure call standard:
// https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst#parameter-passing
struct TargetAArch64 : public GenericTarget<TargetAArch64> {
  using GenericTarget::GenericTarget;

  static constexpr int defaultWidth = 64;

  CodeGenSpecifics::Marshalling
  complexArgumentType(mlir::Location loc, mlir::Type eleTy) const override {
    CodeGenSpecifics::Marshalling marshal;
    const auto *sem = &floatToSemantics(kindMap, eleTy);
    if (sem == &llvm::APFloat::IEEEsingle() ||
        sem == &llvm::APFloat::IEEEdouble() ||
        sem == &llvm::APFloat::IEEEquad()) {
      // [2 x t]   array of 2 eleTy
      marshal.emplace_back(fir::SequenceType::get({2}, eleTy), AT{});
    } else {
      typeTodo(sem, loc, "argument");
    }
    return marshal;
  }

  CodeGenSpecifics::Marshalling
  integerArgumentType(mlir::Location loc,
                      mlir::IntegerType argTy) const override {
    if (argTy.getWidth() < getCIntTypeWidth() && argTy.isSignless()) {
      AT::IntegerExtension intExt;
      if (argTy.getWidth() == 1) {
        // Zero extend for 'i1'.
        intExt = AT::IntegerExtension::Zero;
      } else {
        if (triple.isOSDarwin()) {
          // On Darwin, sign extend. The apple developer guide specifies this as
          // a divergence from the AArch64PCS:
          // https://developer.apple.com/documentation/xcode/writing-arm64-code-for-apple-platforms#Pass-arguments-to-functions-correctly
          intExt = AT::IntegerExtension::Sign;
        } else {
          // On linux, pass directly and do not extend.
          intExt = AT::IntegerExtension::None;
        }
      }
      CodeGenSpecifics::Marshalling marshal;
      marshal.emplace_back(argTy, AT{/*alignment=*/0, /*byval=*/false,
                                     /*sret=*/false, /*append=*/false,
                                     /*intExt=*/intExt});
      return marshal;
    }
    return GenericTarget::integerArgumentType(loc, argTy);
  }

  CodeGenSpecifics::Marshalling
  complexReturnType(mlir::Location loc, mlir::Type eleTy) const override {
    CodeGenSpecifics::Marshalling marshal;
    const auto *sem = &floatToSemantics(kindMap, eleTy);
    if (sem == &llvm::APFloat::IEEEsingle() ||
        sem == &llvm::APFloat::IEEEdouble() ||
        sem == &llvm::APFloat::IEEEquad()) {
      // Use a type that will be translated into LLVM as:
      // { t, t }   struct of 2 eleTy
      marshal.emplace_back(mlir::TupleType::get(eleTy.getContext(),
                                                mlir::TypeRange{eleTy, eleTy}),
                           AT{});
    } else {
      typeTodo(sem, loc, "return");
    }
    return marshal;
  }

  // Flatten a RecordType::TypeList containing more record types or array type
  static std::optional<std::vector<mlir::Type>>
  flattenTypeList(const RecordType::TypeList &types) {
    std::vector<mlir::Type> flatTypes;
    // The flat list will be at least the same size as the non-flat list.
    flatTypes.reserve(types.size());
    for (auto [c, type] : types) {
      // Flatten record type
      if (auto recTy = mlir::dyn_cast<RecordType>(type)) {
        auto subTypeList = flattenTypeList(recTy.getTypeList());
        if (!subTypeList)
          return std::nullopt;
        llvm::copy(*subTypeList, std::back_inserter(flatTypes));
        continue;
      }

      // Flatten array type
      if (auto seqTy = mlir::dyn_cast<SequenceType>(type)) {
        if (seqTy.hasDynamicExtents())
          return std::nullopt;
        std::size_t n = seqTy.getConstantArraySize();
        auto eleTy = seqTy.getElementType();
        // Flatten array of record types
        if (auto recTy = mlir::dyn_cast<RecordType>(eleTy)) {
          auto subTypeList = flattenTypeList(recTy.getTypeList());
          if (!subTypeList)
            return std::nullopt;
          for (std::size_t i = 0; i < n; ++i)
            llvm::copy(*subTypeList, std::back_inserter(flatTypes));
        } else {
          std::fill_n(std::back_inserter(flatTypes),
                      seqTy.getConstantArraySize(), eleTy);
        }
        continue;
      }

      // Other types are already flat
      flatTypes.push_back(type);
    }
    return flatTypes;
  }

  // Determine if the type is a Homogenous Floating-point Aggregate (HFA). An
  // HFA is a record type with up to 4 floating-point members of the same type.
  static std::optional<int> usedRegsForHFA(fir::RecordType ty) {
    RecordType::TypeList types = ty.getTypeList();
    if (types.empty() || types.size() > 4)
      return std::nullopt;

    std::optional<std::vector<mlir::Type>> flatTypes = flattenTypeList(types);
    if (!flatTypes || flatTypes->size() > 4) {
      return std::nullopt;
    }

    if (!isa_real(flatTypes->front())) {
      return std::nullopt;
    }

    return llvm::all_equal(*flatTypes) ? std::optional<int>{flatTypes->size()}
                                       : std::nullopt;
  }

  struct NRegs {
    int n{0};
    bool isSimd{false};
  };

  NRegs usedRegsForRecordType(mlir::Location loc, fir::RecordType type) const {
    if (std::optional<int> size = usedRegsForHFA(type))
      return {*size, true};

    auto [size, align] = fir::getTypeSizeAndAlignmentOrCrash(
        loc, type, getDataLayout(), kindMap);

    if (size <= 16)
      return {static_cast<int>((size + 7) / 8), false};

    // Pass on the stack, i.e. no registers used
    return {};
  }

  NRegs usedRegsForType(mlir::Location loc, mlir::Type type) const {
    return llvm::TypeSwitch<mlir::Type, NRegs>(type)
        .Case([&](mlir::IntegerType intTy) {
          return intTy.getWidth() == 128 ? NRegs{2, false} : NRegs{1, false};
        })
        .Case([&](mlir::FloatType) { return NRegs{1, true}; })
        .Case([&](mlir::ComplexType) { return NRegs{2, true}; })
        .Case([&](fir::LogicalType) { return NRegs{1, false}; })
        .Case([&](fir::CharacterType) { return NRegs{1, false}; })
        .Case([&](fir::SequenceType ty) {
          assert(ty.getShape().size() == 1 &&
                 "invalid array dimensions in BIND(C)");
          NRegs nregs = usedRegsForType(loc, ty.getEleTy());
          nregs.n *= ty.getShape()[0];
          return nregs;
        })
        .Case(
            [&](fir::RecordType ty) { return usedRegsForRecordType(loc, ty); })
        .Case([&](fir::VectorType) {
          TODO(loc, "passing vector argument to C by value is not supported");
          return NRegs{};
        })
        .Default([&](auto ty) {
          if (fir::conformsWithPassByRef(ty))
            return NRegs{1, false}; // Pointers take 1 integer register
          TODO(loc, "unsupported component type for BIND(C), VALUE derived "
                    "type argument");
          return NRegs{};
        });
  }

  bool hasEnoughRegisters(mlir::Location loc, fir::RecordType type,
                          const Marshalling &previousArguments) const {
    int availIntRegisters = 8;
    int availSIMDRegisters = 8;

    // Check previous arguments to see how many registers are used already
    for (auto [type, attr] : previousArguments) {
      if (availIntRegisters <= 0 || availSIMDRegisters <= 0)
        break;

      if (attr.isByVal())
        continue; // Previous argument passed on the stack

      NRegs nregs = usedRegsForType(loc, type);
      if (nregs.isSimd)
        availSIMDRegisters -= nregs.n;
      else
        availIntRegisters -= nregs.n;
    }

    NRegs nregs = usedRegsForRecordType(loc, type);

    if (nregs.isSimd)
      return nregs.n <= availSIMDRegisters;

    return nregs.n <= availIntRegisters;
  }

  CodeGenSpecifics::Marshalling
  passOnTheStack(mlir::Location loc, mlir::Type ty, bool isResult) const {
    CodeGenSpecifics::Marshalling marshal;
    auto sizeAndAlign =
        fir::getTypeSizeAndAlignmentOrCrash(loc, ty, getDataLayout(), kindMap);
    // The stack is always 8 byte aligned
    unsigned short align =
        std::max(sizeAndAlign.second, static_cast<unsigned short>(8));
    marshal.emplace_back(fir::ReferenceType::get(ty),
                         AT{align, /*byval=*/!isResult, /*sret=*/isResult});
    return marshal;
  }

  /// AAPCS64 "Parameter passing rules" B.4: "If the argument type is a
  /// Composite Type that is larger than 16 bytes, then the argument is copied
  /// to memory allocated by the caller and the argument is replaced by a
  /// pointer to the copy." Marking such an argument `byval` instead would let
  /// the target lower it as a by-value aggregate, which does not match this
  /// rule.
  CodeGenSpecifics::Marshalling passIndirectly(mlir::Location loc,
                                               mlir::Type ty) const {
    CodeGenSpecifics::Marshalling marshal;
    auto sizeAndAlign =
        fir::getTypeSizeAndAlignmentOrCrash(loc, ty, getDataLayout(), kindMap);
    // The pointee is the caller's copy, so the alignment reported for the
    // pointer is the natural alignment of the aggregate.
    marshal.emplace_back(
        fir::ReferenceType::get(ty),
        AT{sizeAndAlign.second, /*byval=*/false, /*sret=*/false,
           /*append=*/false, /*intExt=*/AT::IntegerExtension::None,
           /*indirect=*/true});
    return marshal;
  }

  CodeGenSpecifics::Marshalling
  structType(mlir::Location loc, fir::RecordType type, bool isResult) const {
    NRegs nregs = usedRegsForRecordType(loc, type);

    // If the type needs no registers it is too large to be passed in
    // registers. As an argument it is passed indirectly; as a result it is
    // returned via the caller-provided indirect result buffer (sret).
    if (nregs.n == 0) {
      if (isResult)
        return passOnTheStack(loc, type, /*isResult=*/true);
      return passIndirectly(loc, type);
    }

    CodeGenSpecifics::Marshalling marshal;

    mlir::Type pcsType;
    if (nregs.isSimd) {
      pcsType = type;
    } else {
      pcsType = fir::SequenceType::get(
          nregs.n, mlir::IntegerType::get(type.getContext(), 64));
    }

    marshal.emplace_back(pcsType, AT{});
    return marshal;
  }

  CodeGenSpecifics::Marshalling
  structArgumentType(mlir::Location loc, fir::RecordType ty,
                     const Marshalling &previousArguments) const override {
    if (!hasEnoughRegisters(loc, ty, previousArguments)) {
      return passOnTheStack(loc, ty, /*isResult=*/false);
    }

    return structType(loc, ty, /*isResult=*/false);
  }

  CodeGenSpecifics::Marshalling
  structReturnType(mlir::Location loc, fir::RecordType ty) const override {
    return structType(loc, ty, /*isResult=*/true);
  }
};
} // namespace

//===----------------------------------------------------------------------===//
// PPC (AIX 32 bit) target specifics.
//===----------------------------------------------------------------------===//
namespace {
struct TargetPPC : public GenericTarget<TargetPPC> {
  using GenericTarget::GenericTarget;

  static constexpr int defaultWidth = 32;

  CodeGenSpecifics::Marshalling
  complexArgumentType(mlir::Location, mlir::Type eleTy) const override {
    CodeGenSpecifics::Marshalling marshal;
    // two distinct element type arguments (re, im)
    marshal.emplace_back(eleTy, AT{});
    marshal.emplace_back(eleTy, AT{});
    return marshal;
  }

  CodeGenSpecifics::Marshalling
  complexReturnType(mlir::Location, mlir::Type eleTy) const override {
    CodeGenSpecifics::Marshalling marshal;
    // Use a type that will be translated into LLVM as:
    // { t, t }   struct of 2 element type
    marshal.emplace_back(
        mlir::TupleType::get(eleTy.getContext(), mlir::TypeRange{eleTy, eleTy}),
        AT{});
    return marshal;
  }
};
} // namespace

//===----------------------------------------------------------------------===//
// PPC64 (AIX 64 bit) target specifics.
//===----------------------------------------------------------------------===//

namespace {
struct TargetPPC64 : public GenericTarget<TargetPPC64> {
  using GenericTarget::GenericTarget;

  static constexpr int defaultWidth = 64;

  CodeGenSpecifics::Marshalling
  complexArgumentType(mlir::Location, mlir::Type eleTy) const override {
    CodeGenSpecifics::Marshalling marshal;
    // two distinct element type arguments (re, im)
    marshal.emplace_back(eleTy, AT{});
    marshal.emplace_back(eleTy, AT{});
    return marshal;
  }

  CodeGenSpecifics::Marshalling
  complexReturnType(mlir::Location, mlir::Type eleTy) const override {
    CodeGenSpecifics::Marshalling marshal;
    // Use a type that will be translated into LLVM as:
    // { t, t }   struct of 2 element type
    marshal.emplace_back(
        mlir::TupleType::get(eleTy.getContext(), mlir::TypeRange{eleTy, eleTy}),
        AT{});
    return marshal;
  }

  CodeGenSpecifics::Marshalling
  structType(mlir::Location loc, fir::RecordType ty, bool isResult) const {
    CodeGenSpecifics::Marshalling marshal;
    auto sizeAndAlign{
        fir::getTypeSizeAndAlignmentOrCrash(loc, ty, getDataLayout(), kindMap)};
    unsigned short align{
        std::max(sizeAndAlign.second, static_cast<unsigned short>(8))};
    marshal.emplace_back(fir::ReferenceType::get(ty),
                         AT{align, /*byval*/ !isResult, /*sret*/ isResult});
    return marshal;
  }

  CodeGenSpecifics::Marshalling
  structArgumentType(mlir::Location loc, fir::RecordType ty,
                     const Marshalling &previousArguments) const override {
    return structType(loc, ty, false);
  }

  CodeGenSpecifics::Marshalling
  structReturnType(mlir::Location loc, fir::RecordType ty) const override {
    return structType(loc, ty, true);
  }
};
} // namespace

//===----------------------------------------------------------------------===//
// PPC64le linux target specifics.
//===----------------------------------------------------------------------===//

namespace {
struct TargetPPC64le : public GenericTarget<TargetPPC64le> {
  using GenericTarget::GenericTarget;

  static constexpr int defaultWidth{64};

  CodeGenSpecifics::Marshalling
  complexArgumentType(mlir::Location, mlir::Type eleTy) const override {
    CodeGenSpecifics::Marshalling marshal;
    // two distinct element type arguments (re, im)
    marshal.emplace_back(eleTy, AT{});
    marshal.emplace_back(eleTy, AT{});
    return marshal;
  }

  CodeGenSpecifics::Marshalling
  complexReturnType(mlir::Location, mlir::Type eleTy) const override {
    CodeGenSpecifics::Marshalling marshal;
    // Use a type that will be translated into LLVM as:
    // { t, t }   struct of 2 element type
    marshal.emplace_back(
        mlir::TupleType::get(eleTy.getContext(), mlir::TypeRange{eleTy, eleTy}),
        AT{});
    return marshal;
  }

  unsigned getElemWidth(mlir::Type ty) const {
    unsigned width{};
    llvm::TypeSwitch<mlir::Type>(ty)
        .Case([&](mlir::ComplexType cmplx) {
          auto elemType{
              mlir::dyn_cast<mlir::FloatType>(cmplx.getElementType())};
          width = elemType.getWidth();
        })
        .Case([&](mlir::FloatType real) { width = real.getWidth(); });
    return width;
  }

  // Determine if all derived types components are of the same float type with
  // the same width. Complex(4) is considered 2 floats and complex(8) 2 doubles.
  bool hasSameFloatAndWidth(
      fir::RecordType recTy,
      std::pair<mlir::Type, unsigned> &firstTypeAndWidth) const {
    for (auto comp : recTy.getTypeList()) {
      mlir::Type compType{comp.second};
      if (mlir::isa<fir::RecordType>(compType)) {
        auto rc{hasSameFloatAndWidth(mlir::cast<fir::RecordType>(compType),
                                     firstTypeAndWidth)};
        if (!rc)
          return false;
      } else {
        mlir::Type ty;
        bool isFloatType{false};
        if (mlir::isa<mlir::FloatType, mlir::ComplexType>(compType)) {
          ty = compType;
          isFloatType = true;
        } else if (auto seqTy = mlir::dyn_cast<fir::SequenceType>(compType)) {
          ty = seqTy.getEleTy();
          isFloatType = mlir::isa<mlir::FloatType, mlir::ComplexType>(ty);
        }

        if (!isFloatType) {
          return false;
        }
        auto width{getElemWidth(ty)};
        if (firstTypeAndWidth.first == nullptr) {
          firstTypeAndWidth.first = ty;
          firstTypeAndWidth.second = width;
        } else if (width != firstTypeAndWidth.second) {
          return false;
        }
      }
    }
    return true;
  }

  CodeGenSpecifics::Marshalling
  passOnTheStack(mlir::Location loc, mlir::Type ty, bool isResult) const {
    CodeGenSpecifics::Marshalling marshal;
    auto sizeAndAlign{
        fir::getTypeSizeAndAlignmentOrCrash(loc, ty, getDataLayout(), kindMap)};
    unsigned short align{
        std::max(sizeAndAlign.second, static_cast<unsigned short>(8))};
    marshal.emplace_back(fir::ReferenceType::get(ty),
                         AT{align, /*byval=*/!isResult, /*sret=*/isResult});
    return marshal;
  }

  CodeGenSpecifics::Marshalling
  structType(mlir::Location loc, fir::RecordType recTy, bool isResult) const {
    CodeGenSpecifics::Marshalling marshal;
    auto sizeAndAlign{fir::getTypeSizeAndAlignmentOrCrash(
        loc, recTy, getDataLayout(), kindMap)};
    auto recordTypeSize{sizeAndAlign.first};
    mlir::Type seqTy;
    std::pair<mlir::Type, unsigned> firstTyAndWidth{nullptr, 0};

    // If there are less than or equal to 8 floats, the structure is flatten as
    // an array of floats.
    constexpr uint64_t maxNoOfFloats{8};

    // i64 type
    mlir::Type elemTy{mlir::IntegerType::get(recTy.getContext(), defaultWidth)};
    uint64_t nElem{static_cast<uint64_t>(
        std::ceil(static_cast<float>(recordTypeSize * 8) / defaultWidth))};

    // If the derived type components contains are all floats with the same
    // width, the argument is passed as an array of floats.
    if (hasSameFloatAndWidth(recTy, firstTyAndWidth)) {
      uint64_t n{};
      auto firstType{firstTyAndWidth.first};

      // Type is either float or complex
      if (auto cmplx = mlir::dyn_cast<mlir::ComplexType>(firstType)) {
        auto fltType{mlir::dyn_cast<mlir::FloatType>(cmplx.getElementType())};
        n = static_cast<uint64_t>(8 * recordTypeSize / fltType.getWidth());
        if (n <= maxNoOfFloats) {
          nElem = n;
          elemTy = fltType;
        }
      } else if (mlir::isa<mlir::FloatType>(firstType)) {
        auto elemSizeAndAlign{fir::getTypeSizeAndAlignmentOrCrash(
            loc, firstType, getDataLayout(), kindMap)};
        n = static_cast<uint64_t>(recordTypeSize / elemSizeAndAlign.first);
        if (n <= maxNoOfFloats) {
          nElem = n;
          elemTy = firstType;
        }
      }
      // Neither float nor complex
      assert(n > 0 && "unexpected type");
    }

    // For function returns, only flattened if there are less than 8
    // floats in total.
    if (isResult &&
        ((mlir::isa<mlir::FloatType>(elemTy) && nElem > maxNoOfFloats) ||
         !mlir::isa<mlir::FloatType>(elemTy))) {
      return passOnTheStack(loc, recTy, isResult);
    }

    seqTy = fir::SequenceType::get(nElem, elemTy);
    marshal.emplace_back(seqTy, AT{});
    return marshal;
  }

  CodeGenSpecifics::Marshalling
  structArgumentType(mlir::Location loc, fir::RecordType recType,
                     const Marshalling &previousArguments) const override {
    auto sizeAndAlign{fir::getTypeSizeAndAlignmentOrCrash(
        loc, recType, getDataLayout(), kindMap)};
    if (sizeAndAlign.first > 64) {
      return passOnTheStack(loc, recType, false);
    }
    return structType(loc, recType, false);
  }

  CodeGenSpecifics::Marshalling
  structReturnType(mlir::Location loc, fir::RecordType recType) const override {
    return structType(loc, recType, true);
  }
};
} // namespace

//===----------------------------------------------------------------------===//
// sparc (sparc 32 bit) target specifics.
//===----------------------------------------------------------------------===//

namespace {
struct TargetSparc : public GenericTarget<TargetSparc> {
  using GenericTarget::GenericTarget;

  static constexpr int defaultWidth = 32;

  CodeGenSpecifics::Marshalling
  complexArgumentType(mlir::Location, mlir::Type eleTy) const override {
    assert(fir::isa_real(eleTy));
    CodeGenSpecifics::Marshalling marshal;
    // Use a type that will be translated into LLVM as:
    // { t, t }   struct of 2 eleTy
    auto structTy =
        mlir::TupleType::get(eleTy.getContext(), mlir::TypeRange{eleTy, eleTy});
    marshal.emplace_back(fir::ReferenceType::get(structTy), AT{});
    return marshal;
  }

  CodeGenSpecifics::Marshalling
  complexReturnType(mlir::Location loc, mlir::Type eleTy) const override {
    assert(fir::isa_real(eleTy));
    CodeGenSpecifics::Marshalling marshal;
    // Use a type that will be translated into LLVM as:
    // { t, t }   struct of 2 eleTy, byval
    auto structTy =
        mlir::TupleType::get(eleTy.getContext(), mlir::TypeRange{eleTy, eleTy});
    marshal.emplace_back(fir::ReferenceType::get(structTy),
                         AT{/*alignment=*/0, /*byval=*/true});
    return marshal;
  }
};
} // namespace

//===----------------------------------------------------------------------===//
// sparcv9 (sparc 64 bit) target specifics.
//===----------------------------------------------------------------------===//

namespace {
struct TargetSparcV9 : public GenericTarget<TargetSparcV9> {
  using GenericTarget::GenericTarget;

  static constexpr int defaultWidth = 64;

  CodeGenSpecifics::Marshalling
  complexArgumentType(mlir::Location loc, mlir::Type eleTy) const override {
    CodeGenSpecifics::Marshalling marshal;
    const auto *sem = &floatToSemantics(kindMap, eleTy);
    if (sem == &llvm::APFloat::IEEEsingle() ||
        sem == &llvm::APFloat::IEEEdouble()) {
      // two distinct float, double arguments
      marshal.emplace_back(eleTy, AT{});
      marshal.emplace_back(eleTy, AT{});
    } else if (sem == &llvm::APFloat::IEEEquad()) {
      // Use a type that will be translated into LLVM as:
      // { fp128, fp128 }   struct of 2 fp128, byval, align 16
      marshal.emplace_back(
          fir::ReferenceType::get(mlir::TupleType::get(
              eleTy.getContext(), mlir::TypeRange{eleTy, eleTy})),
          AT{/*align=*/16, /*byval=*/true});
    } else {
      typeTodo(sem, loc, "argument");
    }
    return marshal;
  }

  CodeGenSpecifics::Marshalling
  complexReturnType(mlir::Location loc, mlir::Type eleTy) const override {
    CodeGenSpecifics::Marshalling marshal;
    // Use a type that will be translated into LLVM as:
    // { eleTy, eleTy }   struct of 2 eleTy
    marshal.emplace_back(
        mlir::TupleType::get(eleTy.getContext(), mlir::TypeRange{eleTy, eleTy}),
        AT{});
    return marshal;
  }
};
} // namespace

//===----------------------------------------------------------------------===//
// RISCV64 linux target specifics.
//===----------------------------------------------------------------------===//

namespace {
struct TargetRISCV64 : public GenericTarget<TargetRISCV64> {
  using GenericTarget::GenericTarget;

  static constexpr int defaultWidth = 64;

  CodeGenSpecifics::Marshalling
  complexArgumentType(mlir::Location loc, mlir::Type eleTy) const override {
    CodeGenSpecifics::Marshalling marshal;
    const auto *sem = &floatToSemantics(kindMap, eleTy);
    if (sem == &llvm::APFloat::IEEEsingle() ||
        sem == &llvm::APFloat::IEEEdouble()) {
      // Two distinct element type arguments (re, im)
      marshal.emplace_back(eleTy, AT{});
      marshal.emplace_back(eleTy, AT{});
    } else {
      typeTodo(sem, loc, "argument");
    }
    return marshal;
  }

  CodeGenSpecifics::Marshalling
  complexReturnType(mlir::Location loc, mlir::Type eleTy) const override {
    CodeGenSpecifics::Marshalling marshal;
    const auto *sem = &floatToSemantics(kindMap, eleTy);
    if (sem == &llvm::APFloat::IEEEsingle() ||
        sem == &llvm::APFloat::IEEEdouble()) {
      // Use a type that will be translated into LLVM as:
      // { t, t }   struct of 2 eleTy, byVal
      marshal.emplace_back(mlir::TupleType::get(eleTy.getContext(),
                                                mlir::TypeRange{eleTy, eleTy}),
                           AT{/*alignment=*/0, /*byval=*/true});
    } else {
      typeTodo(sem, loc, "return");
    }
    return marshal;
  }
};
} // namespace

//===----------------------------------------------------------------------===//
// AMDGPU linux target specifics.
//===----------------------------------------------------------------------===//

namespace {
struct TargetAMDGPU : public GenericTarget<TargetAMDGPU> {
  using GenericTarget::GenericTarget;

  // Default size (in bits) of the index type for strings.
  static constexpr int defaultWidth = 64;

  CodeGenSpecifics::Marshalling
  complexArgumentType(mlir::Location loc, mlir::Type eleTy) const override {
    CodeGenSpecifics::Marshalling marshal;
    const auto *sem = &floatToSemantics(kindMap, eleTy);
    if (sem == &llvm::APFloat::IEEEsingle()) {
      // Lower COMPLEX(KIND=4) as an array of two element values.
      marshal.emplace_back(fir::SequenceType::get({2}, eleTy), AT{});
    } else if (sem == &llvm::APFloat::IEEEdouble()) {
      // Pass COMPLEX(KIND=8) as two separate arguments.
      marshal.emplace_back(eleTy, AT{});
      marshal.emplace_back(eleTy, AT{});
    } else {
      typeTodo(sem, loc, "argument");
    }
    return marshal;
  }

  CodeGenSpecifics::Marshalling
  complexReturnType(mlir::Location loc, mlir::Type eleTy) const override {
    CodeGenSpecifics::Marshalling marshal;
    const auto *sem = &floatToSemantics(kindMap, eleTy);
    if (sem == &llvm::APFloat::IEEEsingle()) {
      // Return COMPLEX(KIND=4) as an array of two elements.
      marshal.emplace_back(fir::SequenceType::get({2}, eleTy), AT{});
    } else if (sem == &llvm::APFloat::IEEEdouble()) {
      // Return COMPLEX(KIND=8) via an aggregate with two fields.
      marshal.emplace_back(mlir::TupleType::get(eleTy.getContext(),
                                                mlir::TypeRange{eleTy, eleTy}),
                           AT{});
    } else {
      typeTodo(sem, loc, "return");
    }
    return marshal;
  }
};
} // namespace

//===----------------------------------------------------------------------===//
// NVPTX linux target specifics.
//===----------------------------------------------------------------------===//

namespace {
struct TargetNVPTX : public GenericTarget<TargetNVPTX> {
  using GenericTarget::GenericTarget;

  // Default size (in bits) of the index type for strings.
  static constexpr int defaultWidth = 64;

  CodeGenSpecifics::Marshalling
  complexArgumentType(mlir::Location loc, mlir::Type eleTy) const override {
    CodeGenSpecifics::Marshalling marshal;
    TODO(loc, "handle complex argument types");
    return marshal;
  }

  CodeGenSpecifics::Marshalling
  complexReturnType(mlir::Location loc, mlir::Type eleTy) const override {
    CodeGenSpecifics::Marshalling marshal;
    TODO(loc, "handle complex return types");
    return marshal;
  }
};
} // namespace

//===----------------------------------------------------------------------===//
// LoongArch64 linux target specifics.
//===----------------------------------------------------------------------===//

namespace {
struct TargetLoongArch64 : public GenericTarget<TargetLoongArch64> {
  using GenericTarget::GenericTarget;

  static constexpr int defaultWidth = 64;
  static constexpr int GRLen = defaultWidth; /* eight bytes */
  static constexpr int GRLenInChar = GRLen / 8;
  static constexpr int FRLen = defaultWidth; /* eight bytes */

  CodeGenSpecifics::Marshalling
  complexArgumentType(mlir::Location loc, mlir::Type eleTy) const override {
    CodeGenSpecifics::Marshalling marshal;
    const auto *sem = &floatToSemantics(kindMap, eleTy);
    if (sem == &llvm::APFloat::IEEEsingle() ||
        sem == &llvm::APFloat::IEEEdouble()) {
      // Two distinct element type arguments (re, im)
      marshal.emplace_back(eleTy, AT{});
      marshal.emplace_back(eleTy, AT{});
    } else if (sem == &llvm::APFloat::IEEEquad()) {
      // Use a type that will be translated into LLVM as:
      // { fp128, fp128 }   struct of 2 fp128, byval
      marshal.emplace_back(
          fir::ReferenceType::get(mlir::TupleType::get(
              eleTy.getContext(), mlir::TypeRange{eleTy, eleTy})),
          AT{/*align=*/16, /*byval=*/true});
    } else {
      typeTodo(sem, loc, "argument");
    }
    return marshal;
  }

  CodeGenSpecifics::Marshalling
  complexReturnType(mlir::Location loc, mlir::Type eleTy) const override {
    CodeGenSpecifics::Marshalling marshal;
    const auto *sem = &floatToSemantics(kindMap, eleTy);
    if (sem == &llvm::APFloat::IEEEsingle() ||
        sem == &llvm::APFloat::IEEEdouble()) {
      // Use a type that will be translated into LLVM as:
      // { t, t }   struct of 2 eleTy, byVal
      marshal.emplace_back(mlir::TupleType::get(eleTy.getContext(),
                                                mlir::TypeRange{eleTy, eleTy}),
                           AT{/*alignment=*/0, /*byval=*/true});
    } else if (sem == &llvm::APFloat::IEEEquad()) {
      // Use a type that will be translated into LLVM as:
      // { fp128, fp128 }   struct of 2 fp128, sret, align 16
      marshal.emplace_back(
          fir::ReferenceType::get(mlir::TupleType::get(
              eleTy.getContext(), mlir::TypeRange{eleTy, eleTy})),
          AT{/*align=*/16, /*byval=*/false, /*sret=*/true});
    } else {
      typeTodo(sem, loc, "return");
    }
    return marshal;
  }

  CodeGenSpecifics::Marshalling
  integerArgumentType(mlir::Location loc,
                      mlir::IntegerType argTy) const override {
    if (argTy.getWidth() == 32) {
      // LA64 LP64D ABI requires unsigned 32 bit integers to be sign extended.
      // Therefore, Flang also follows it if a function needs to be
      // interoperable with C.
      //
      // Currently, it only adds `signext` attribute to the dummy arguments and
      // return values in the function signatures, but it does not add the
      // corresponding attribute to the actual arguments and return values in
      // `fir.call` instruction. Thanks to LLVM's integration of all these
      // attributes, the modification is still effective.
      CodeGenSpecifics::Marshalling marshal;
      AT::IntegerExtension intExt = AT::IntegerExtension::Sign;
      marshal.emplace_back(argTy, AT{/*alignment=*/0, /*byval=*/false,
                                     /*sret=*/false, /*append=*/false,
                                     /*intExt=*/intExt});
      return marshal;
    }

    return GenericTarget::integerArgumentType(loc, argTy);
  }

  /// Flatten non-basic types, resulting in an array of types containing only
  /// `IntegerType` and `FloatType`.
  llvm::SmallVector<mlir::Type> flattenTypeList(mlir::Location loc,
                                                const mlir::Type type) const {
    llvm::SmallVector<mlir::Type> flatTypes;

    llvm::TypeSwitch<mlir::Type>(type)
        .Case([&](mlir::IntegerType intTy) {
          if (intTy.getWidth() != 0)
            flatTypes.push_back(intTy);
        })
        .Case([&](mlir::FloatType floatTy) {
          if (floatTy.getWidth() != 0)
            flatTypes.push_back(floatTy);
        })
        .Case([&](mlir::ComplexType cmplx) {
          const auto *sem = &floatToSemantics(kindMap, cmplx.getElementType());
          if (sem == &llvm::APFloat::IEEEsingle() ||
              sem == &llvm::APFloat::IEEEdouble() ||
              sem == &llvm::APFloat::IEEEquad())
            std::fill_n(std::back_inserter(flatTypes), 2,
                        cmplx.getElementType());
          else
            TODO(loc, "unsupported complex type(not IEEEsingle, IEEEdouble, "
                      "IEEEquad) as a structure component for BIND(C), "
                      "VALUE derived type argument and type return");
        })
        .Case([&](fir::LogicalType logicalTy) {
          const unsigned width =
              kindMap.getLogicalBitsize(logicalTy.getFKind());
          if (width != 0)
            flatTypes.push_back(
                mlir::IntegerType::get(type.getContext(), width));
        })
        .Case([&](fir::CharacterType charTy) {
          assert(kindMap.getCharacterBitsize(charTy.getFKind()) <= 8 &&
                 "the bit size of characterType as an interoperable type must "
                 "not exceed 8");
          for (unsigned i = 0; i < charTy.getLen(); ++i)
            flatTypes.push_back(mlir::IntegerType::get(type.getContext(), 8));
        })
        .Case([&](fir::SequenceType seqTy) {
          if (!seqTy.hasDynamicExtents()) {
            const std::uint64_t numOfEle = seqTy.getConstantArraySize();
            mlir::Type eleTy = seqTy.getEleTy();
            if (!mlir::isa<mlir::IntegerType, mlir::FloatType>(eleTy)) {
              llvm::SmallVector<mlir::Type> subTypeList =
                  flattenTypeList(loc, eleTy);
              if (subTypeList.size() != 0)
                for (std::uint64_t i = 0; i < numOfEle; ++i)
                  llvm::copy(subTypeList, std::back_inserter(flatTypes));
            } else {
              std::fill_n(std::back_inserter(flatTypes), numOfEle, eleTy);
            }
          } else
            TODO(loc, "unsupported dynamic extent sequence type as a structure "
                      "component for BIND(C), "
                      "VALUE derived type argument and type return");
        })
        .Case([&](fir::RecordType recTy) {
          for (auto &component : recTy.getTypeList()) {
            mlir::Type eleTy = component.second;
            llvm::SmallVector<mlir::Type> subTypeList =
                flattenTypeList(loc, eleTy);
            if (subTypeList.size() != 0)
              llvm::copy(subTypeList, std::back_inserter(flatTypes));
          }
        })
        .Case([&](fir::VectorType vecTy) {
          auto sizeAndAlign = fir::getTypeSizeAndAlignmentOrCrash(
              loc, vecTy, getDataLayout(), kindMap);
          if (sizeAndAlign.first == 2 * GRLenInChar)
            flatTypes.push_back(
                mlir::IntegerType::get(type.getContext(), 2 * GRLen));
          else
            TODO(loc, "unsupported vector width(must be 128 bits)");
        })
        .Default([&](mlir::Type ty) {
          if (fir::conformsWithPassByRef(ty))
            flatTypes.push_back(
                mlir::IntegerType::get(type.getContext(), GRLen));
          else
            TODO(loc, "unsupported component type for BIND(C), VALUE derived "
                      "type argument and type return");
        });

    return flatTypes;
  }

  /// Determine if a struct is eligible to be passed in FARs (and GARs) (i.e.,
  /// when flattened it contains a single fp value, fp+fp, or int+fp of
  /// appropriate size).
  bool detectFARsEligibleStruct(mlir::Location loc, fir::RecordType recTy,
                                mlir::Type &field1Ty,
                                mlir::Type &field2Ty) const {
    field1Ty = field2Ty = nullptr;
    llvm::SmallVector<mlir::Type> flatTypes = flattenTypeList(loc, recTy);
    size_t flatSize = flatTypes.size();

    // Cannot be eligible if the number of flattened types is equal to 0 or
    // greater than 2.
    if (flatSize == 0 || flatSize > 2)
      return false;

    bool isFirstAvaliableFloat = false;

    assert((mlir::isa<mlir::IntegerType, mlir::FloatType>(flatTypes[0])) &&
           "Type must be integerType or floatType after flattening");
    if (auto floatTy = mlir::dyn_cast<mlir::FloatType>(flatTypes[0])) {
      const unsigned Size = floatTy.getWidth();
      // Can't be eligible if larger than the FP registers. Half precision isn't
      // currently supported on LoongArch and the ABI hasn't been confirmed, so
      // default to the integer ABI in that case.
      if (Size > FRLen || Size < 32)
        return false;
      isFirstAvaliableFloat = true;
      field1Ty = floatTy;
    } else if (auto intTy = mlir::dyn_cast<mlir::IntegerType>(flatTypes[0])) {
      if (intTy.getWidth() > GRLen)
        return false;
      field1Ty = intTy;
    }

    // flatTypes has two elements
    if (flatSize == 2) {
      assert((mlir::isa<mlir::IntegerType, mlir::FloatType>(flatTypes[1])) &&
             "Type must be integerType or floatType after flattening");
      if (auto floatTy = mlir::dyn_cast<mlir::FloatType>(flatTypes[1])) {
        const unsigned Size = floatTy.getWidth();
        if (Size > FRLen || Size < 32)
          return false;
        field2Ty = floatTy;
        return true;
      } else if (auto intTy = mlir::dyn_cast<mlir::IntegerType>(flatTypes[1])) {
        // Can't be eligible if an integer type was already found (int+int pairs
        // are not eligible).
        if (!isFirstAvaliableFloat)
          return false;
        if (intTy.getWidth() > GRLen)
          return false;
        field2Ty = intTy;
        return true;
      }
    }

    // return isFirstAvaliableFloat if flatTypes only has one element
    return isFirstAvaliableFloat;
  }

  bool checkTypeHasEnoughRegs(mlir::Location loc, int &GARsLeft, int &FARsLeft,
                              const mlir::Type type) const {
    if (!type)
      return true;

    llvm::TypeSwitch<mlir::Type>(type)
        .Case([&](mlir::IntegerType intTy) {
          const unsigned width = intTy.getWidth();
          if (width > 128)
            TODO(loc,
                 "integerType with width exceeding 128 bits is unsupported");
          if (width == 0)
            return;
          if (width <= GRLen)
            --GARsLeft;
          else if (width <= 2 * GRLen)
            GARsLeft = GARsLeft - 2;
        })
        .Case([&](mlir::FloatType floatTy) {
          const unsigned width = floatTy.getWidth();
          if (width > 128)
            TODO(loc, "floatType with width exceeding 128 bits is unsupported");
          if (width == 0)
            return;
          if (width == 32 || width == 64)
            --FARsLeft;
          else if (width <= GRLen)
            --GARsLeft;
          else if (width <= 2 * GRLen)
            GARsLeft = GARsLeft - 2;
        })
        .Default([&](mlir::Type ty) {
          if (fir::conformsWithPassByRef(ty))
            --GARsLeft; // Pointers.
          else
            TODO(loc, "unsupported component type for BIND(C), VALUE derived "
                      "type argument and type return");
        });

    return GARsLeft >= 0 && FARsLeft >= 0;
  }

  bool hasEnoughRegisters(mlir::Location loc, int GARsLeft, int FARsLeft,
                          const Marshalling &previousArguments,
                          const mlir::Type &field1Ty,
                          const mlir::Type &field2Ty) const {
    for (auto &typeAndAttr : previousArguments) {
      const auto &attr = std::get<Attributes>(typeAndAttr);
      if (attr.isByVal()) {
        // Previous argument passed on the stack, and its address is passed in
        // GAR.
        --GARsLeft;
        continue;
      }

      // Previous aggregate arguments were marshalled into simpler arguments.
      const auto &type = std::get<mlir::Type>(typeAndAttr);
      llvm::SmallVector<mlir::Type> flatTypes = flattenTypeList(loc, type);

      for (auto &flatTy : flatTypes) {
        if (!checkTypeHasEnoughRegs(loc, GARsLeft, FARsLeft, flatTy))
          return false;
      }
    }

    if (!checkTypeHasEnoughRegs(loc, GARsLeft, FARsLeft, field1Ty))
      return false;
    if (!checkTypeHasEnoughRegs(loc, GARsLeft, FARsLeft, field2Ty))
      return false;
    return true;
  }

  /// LoongArch64 subroutine calling sequence ABI in:
  /// https://github.com/loongson/la-abi-specs/blob/release/lapcs.adoc#subroutine-calling-sequence
  CodeGenSpecifics::Marshalling
  classifyStruct(mlir::Location loc, fir::RecordType recTy, int GARsLeft,
                 int FARsLeft, bool isResult,
                 const Marshalling &previousArguments) const {
    CodeGenSpecifics::Marshalling marshal;

    auto [recSize, recAlign] = fir::getTypeSizeAndAlignmentOrCrash(
        loc, recTy, getDataLayout(), kindMap);
    mlir::MLIRContext *context = recTy.getContext();

    if (recSize == 0) {
      TODO(loc, "unsupported empty struct type for BIND(C), "
                "VALUE derived type argument and type return");
    }

    if (recSize > 2 * GRLenInChar) {
      marshal.emplace_back(
          fir::ReferenceType::get(recTy),
          AT{recAlign, /*byval=*/!isResult, /*sret=*/isResult});
      return marshal;
    }

    // Pass by FARs(and GARs)
    mlir::Type field1Ty = nullptr, field2Ty = nullptr;
    if (detectFARsEligibleStruct(loc, recTy, field1Ty, field2Ty) &&
        hasEnoughRegisters(loc, GARsLeft, FARsLeft, previousArguments, field1Ty,
                           field2Ty)) {
      if (!isResult) {
        if (field1Ty)
          marshal.emplace_back(field1Ty, AT{});
        if (field2Ty)
          marshal.emplace_back(field2Ty, AT{});
      } else {
        // field1Ty is always preferred over field2Ty for assignment, so there
        // will never be a case where field1Ty == nullptr and field2Ty !=
        // nullptr.
        if (field1Ty && !field2Ty)
          marshal.emplace_back(field1Ty, AT{});
        else if (field1Ty && field2Ty)
          marshal.emplace_back(
              mlir::TupleType::get(context,
                                   mlir::TypeRange{field1Ty, field2Ty}),
              AT{/*alignment=*/0, /*byval=*/true});
      }
      return marshal;
    }

    if (recSize <= GRLenInChar) {
      marshal.emplace_back(mlir::IntegerType::get(context, GRLen), AT{});
      return marshal;
    }

    if (recAlign == 2 * GRLenInChar) {
      marshal.emplace_back(mlir::IntegerType::get(context, 2 * GRLen), AT{});
      return marshal;
    }

    // recSize > GRLenInChar && recSize <= 2 * GRLenInChar
    marshal.emplace_back(
        fir::SequenceType::get({2}, mlir::IntegerType::get(context, GRLen)),
        AT{});
    return marshal;
  }

  /// Marshal a derived type passed by value like a C struct.
  CodeGenSpecifics::Marshalling
  structArgumentType(mlir::Location loc, fir::RecordType recTy,
                     const Marshalling &previousArguments) const override {
    int GARsLeft = 8;
    int FARsLeft = FRLen ? 8 : 0;

    return classifyStruct(loc, recTy, GARsLeft, FARsLeft, /*isResult=*/false,
                          previousArguments);
  }

  CodeGenSpecifics::Marshalling
  structReturnType(mlir::Location loc, fir::RecordType recTy) const override {
    // The rules for return and argument types are the same.
    int GARsLeft = 2;
    int FARsLeft = FRLen ? 2 : 0;
    return classifyStruct(loc, recTy, GARsLeft, FARsLeft, /*isResult=*/true,
                          {});
  }
};
} // namespace

//===----------------------------------------------------------------------===//
// SystemZ target specifics.
//===----------------------------------------------------------------------===//

namespace {
struct TargetSystemZ : public GenericTarget<TargetSystemZ> {
  using GenericTarget::GenericTarget;

  static constexpr int defaultWidth = 64;

  auto complexType(mlir::Type eleTy, bool isResult) const {
    assert(fir::isa_real(eleTy));
    CodeGenSpecifics::Marshalling marshal;
    unsigned short align{std::max(
        static_cast<unsigned short>(getDataLayout().getTypeABIAlignment(eleTy)),
        static_cast<unsigned short>(8))};
    marshal.emplace_back(
        fir::ReferenceType::get(mlir::TupleType::get(
            eleTy.getContext(), mlir::TypeRange{eleTy, eleTy})),
        AT{/*align=*/align, /*byval=*/false, /*sret=*/isResult,
           /*append=*/false, /*intExt=*/AT::IntegerExtension::None,
           /*indirect=*/!isResult});
    return marshal;
  }

  CodeGenSpecifics::Marshalling
  complexArgumentType(mlir::Location /*loc*/, mlir::Type eleTy) const override {
    return complexType(eleTy, false);
  }

  CodeGenSpecifics::Marshalling
  complexReturnType(mlir::Location /*loc*/, mlir::Type eleTy) const override {
    return complexType(eleTy, true);
  }

  CodeGenSpecifics::Marshalling
  integerArgumentType(mlir::Location loc,
                      mlir::IntegerType argTy) const override {
    // SystemZ ABI requires all integers < 64 bits to be sign/zero extended.
    // Handle widths 32 to 63 explicitly; GenericTarget handles widths < 32
    // including the i1 zero-extension special case.
    if (argTy.getWidth() >= 32 && argTy.getWidth() < 64) {
      AT::IntegerExtension intExt = argTy.isUnsigned()
                                        ? AT::IntegerExtension::Zero
                                        : AT::IntegerExtension::Sign;
      CodeGenSpecifics::Marshalling marshal;
      marshal.emplace_back(argTy, AT{/*alignment=*/0, /*byval=*/false,
                                     /*sret=*/false, /*append=*/false,
                                     /*intExt=*/intExt});
      return marshal;
    }
    return GenericTarget::integerArgumentType(loc, argTy);
  }

  // Check for a single floating-point member recursively.
  static mlir::Type getSingleFPMember(fir::RecordType recTy) {
    auto typeList = recTy.getTypeList();
    if (typeList.size() != 1)
      return {};
    mlir::Type fieldTy = typeList[0].second;
    if (auto nestedRec = mlir::dyn_cast<fir::RecordType>(fieldTy))
      return getSingleFPMember(nestedRec);
    if (auto floatTy = mlir::dyn_cast<mlir::FloatType>(fieldTy))
      if (floatTy.getWidth() <= 64)
        return floatTy;
    return {};
  }

  CodeGenSpecifics::Marshalling
  structArgumentType(mlir::Location loc, fir::RecordType ty,
                     const Marshalling &previousArguments) const override {
    CodeGenSpecifics::Marshalling marshal;
    // Single FP member <= 8 bytes passed in FPR.
    if (mlir::Type fpTy = getSingleFPMember(ty)) {
      marshal.emplace_back(fpTy, AT{});
      return marshal;
    }
    // Small structs passed in GPR (1, 2, 4, 8 bytes).
    auto sizeAndAlign{
        fir::getTypeSizeAndAlignmentOrCrash(loc, ty, getDataLayout(), kindMap)};
    uint64_t byteSize = sizeAndAlign.first;
    if (byteSize == 1 || byteSize == 2 || byteSize == 4 || byteSize == 8) {
      marshal.emplace_back(
          mlir::IntegerType::get(ty.getContext(), byteSize * 8), AT{});
      return marshal;
    }
    // Larger structs passed via implicit reference (pointer in register/stack).
    unsigned short align{
        std::max(sizeAndAlign.second, static_cast<unsigned short>(8))};
    marshal.emplace_back(fir::ReferenceType::get(ty),
                         AT{/*align=*/align, /*byval=*/false, /*sret=*/false,
                            /*append=*/false,
                            /*intExt=*/AT::IntegerExtension::None,
                            /*indirect=*/true});
    return marshal;
  }

  CodeGenSpecifics::Marshalling
  structReturnType(mlir::Location loc, fir::RecordType ty) const override {
    CodeGenSpecifics::Marshalling marshal;
    auto sizeAndAlign{
        fir::getTypeSizeAndAlignmentOrCrash(loc, ty, getDataLayout(), kindMap)};
    unsigned short align{
        std::max(sizeAndAlign.second, static_cast<unsigned short>(8))};
    marshal.emplace_back(fir::ReferenceType::get(ty),
                         AT{/*align=*/align, /*byval=*/false, /*sret=*/true});
    return marshal;
  }
};
} // namespace

// Instantiate the overloaded target instance based on the triple value.
// TODO: Add other targets to this file as needed.
std::unique_ptr<fir::CodeGenSpecifics> fir::CodeGenSpecifics::get(
    mlir::MLIRContext *ctx, llvm::Triple &&trp, KindMapping &&kindMap,
    llvm::StringRef targetCPU, mlir::LLVM::TargetFeaturesAttr targetFeatures,
    llvm::StringRef targetABI, const mlir::DataLayout &dl) {
  switch (trp.getArch()) {
  default:
    break;
  case llvm::Triple::ArchType::x86:
    if (trp.isOSWindows())
      return std::make_unique<TargetI386Win>(ctx, std::move(trp),
                                             std::move(kindMap), targetCPU,
                                             targetFeatures, targetABI, dl);
    else
      return std::make_unique<TargetI386>(ctx, std::move(trp),
                                          std::move(kindMap), targetCPU,
                                          targetFeatures, targetABI, dl);
  case llvm::Triple::ArchType::x86_64:
    if (trp.isOSWindows())
      return std::make_unique<TargetX86_64Win>(ctx, std::move(trp),
                                               std::move(kindMap), targetCPU,
                                               targetFeatures, targetABI, dl);
    else
      return std::make_unique<TargetX86_64>(ctx, std::move(trp),
                                            std::move(kindMap), targetCPU,
                                            targetFeatures, targetABI, dl);
  case llvm::Triple::ArchType::aarch64:
    return std::make_unique<TargetAArch64>(ctx, std::move(trp),
                                           std::move(kindMap), targetCPU,
                                           targetFeatures, targetABI, dl);
  case llvm::Triple::ArchType::ppc:
    return std::make_unique<TargetPPC>(ctx, std::move(trp), std::move(kindMap),
                                       targetCPU, targetFeatures, targetABI,
                                       dl);
  case llvm::Triple::ArchType::ppc64:
    return std::make_unique<TargetPPC64>(ctx, std::move(trp),
                                         std::move(kindMap), targetCPU,
                                         targetFeatures, targetABI, dl);
  case llvm::Triple::ArchType::ppc64le:
    return std::make_unique<TargetPPC64le>(ctx, std::move(trp),
                                           std::move(kindMap), targetCPU,
                                           targetFeatures, targetABI, dl);
  case llvm::Triple::ArchType::sparc:
    return std::make_unique<TargetSparc>(ctx, std::move(trp),
                                         std::move(kindMap), targetCPU,
                                         targetFeatures, targetABI, dl);
  case llvm::Triple::ArchType::sparcv9:
    return std::make_unique<TargetSparcV9>(ctx, std::move(trp),
                                           std::move(kindMap), targetCPU,
                                           targetFeatures, targetABI, dl);
  case llvm::Triple::ArchType::riscv64:
    return std::make_unique<TargetRISCV64>(ctx, std::move(trp),
                                           std::move(kindMap), targetCPU,
                                           targetFeatures, targetABI, dl);
  case llvm::Triple::ArchType::amdgpu:
    return std::make_unique<TargetAMDGPU>(ctx, std::move(trp),
                                          std::move(kindMap), targetCPU,
                                          targetFeatures, targetABI, dl);
  case llvm::Triple::ArchType::nvptx64:
    return std::make_unique<TargetNVPTX>(ctx, std::move(trp),
                                         std::move(kindMap), targetCPU,
                                         targetFeatures, targetABI, dl);
  case llvm::Triple::ArchType::loongarch64:
    return std::make_unique<TargetLoongArch64>(ctx, std::move(trp),
                                               std::move(kindMap), targetCPU,
                                               targetFeatures, targetABI, dl);
  case llvm::Triple::ArchType::systemz:
    return std::make_unique<TargetSystemZ>(ctx, std::move(trp),
                                           std::move(kindMap), targetCPU,
                                           targetFeatures, targetABI, dl);
  }
  TODO(mlir::UnknownLoc::get(ctx), "target not implemented");
}

std::unique_ptr<fir::CodeGenSpecifics> fir::CodeGenSpecifics::get(
    mlir::MLIRContext *ctx, llvm::Triple &&trp, KindMapping &&kindMap,
    llvm::StringRef targetCPU, mlir::LLVM::TargetFeaturesAttr targetFeatures,
    llvm::StringRef targetABI, const mlir::DataLayout &dl,
    llvm::StringRef tuneCPU) {
  std::unique_ptr<fir::CodeGenSpecifics> CGS =
      fir::CodeGenSpecifics::get(ctx, std::move(trp), std::move(kindMap),
                                 targetCPU, targetFeatures, targetABI, dl);

  CGS->tuneCPU = tuneCPU;
  return CGS;
}
