//===--- SwiftCallingConv.cpp - Lowering for the Swift calling convention -===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// Implementation of the abstract lowering for the Swift calling convention.
//
//===----------------------------------------------------------------------===//

#include "clang/CodeGen/SwiftCallingConv.h"
#include "ABIInfo.h"
#include "CodeGenModule.h"
#include "TargetInfo.h"
#include "clang/Basic/TargetInfo.h"
#include <optional>

using namespace clang;
using namespace CodeGen;
using namespace swiftcall;

static const SwiftABIInfo &getSwiftABIInfo(CodeGenModule &CGM) {
  return CGM.getTargetCodeGenInfo().getSwiftABIInfo();
}

static bool isPowerOf2(unsigned n) {
  return n == (n & -n);
}

/// Given two types with the same size, try to find a common type.
static llvm::Type *getCommonType(llvm::Type *first, llvm::Type *second) {
  assert(first != second);

  // Allow pointers to merge with integers, but prefer the integer type.
  if (first->isIntegerTy()) {
    if (second->isPointerTy()) return first;
  } else if (first->isPointerTy()) {
    if (second->isIntegerTy()) return second;
    if (second->isPointerTy()) return first;

  // Allow two vectors to be merged (given that they have the same size).
  // This assumes that we never have two different vector register sets.
  } else if (auto firstVecTy = dyn_cast<llvm::VectorType>(first)) {
    if (auto secondVecTy = dyn_cast<llvm::VectorType>(second)) {
      if (auto commonTy = getCommonType(firstVecTy->getElementType(),
                                        secondVecTy->getElementType())) {
        return (commonTy == firstVecTy->getElementType() ? first : second);
      }
    }
  }

  return nullptr;
}

static CharUnits getTypeStoreSize(CodeGenModule &CGM, llvm::Type *type) {
  return CharUnits::fromQuantity(CGM.getDataLayout().getTypeStoreSize(type));
}

static CharUnits getTypeAllocSize(CodeGenModule &CGM, llvm::Type *type) {
  return CharUnits::fromQuantity(CGM.getDataLayout().getTypeAllocSize(type));
}

void SwiftAggLowering::addTypedData(QualType type, CharUnits begin) {
  // Deal with various aggregate types as special cases:

  // Record types.
  if (auto recType = type->getAs<RecordType>()) {
    addTypedData(recType->getDecl(), begin);

  // Array types.
  } else if (type->isArrayType()) {
    // Incomplete array types (flexible array members?) don't provide
    // data to lay out, and the other cases shouldn't be possible.
    auto arrayType = CGM.getContext().getAsConstantArrayType(type);
    if (!arrayType) return;

    QualType eltType = arrayType->getElementType();
    auto eltSize = CGM.getContext().getTypeSizeInChars(eltType);
    for (uint64_t i = 0, e = arrayType->getZExtSize(); i != e; ++i) {
      addTypedData(eltType, begin + i * eltSize);
    }

  // Complex types.
  } else if (auto complexType = type->getAs<ComplexType>()) {
    auto eltType = complexType->getElementType();
    auto eltSize = CGM.getContext().getTypeSizeInChars(eltType);
    auto eltLLVMType = CGM.getTypes().ConvertType(eltType);
    addTypedData(eltLLVMType, begin, begin + eltSize);
    addTypedData(eltLLVMType, begin + eltSize, begin + 2 * eltSize);

  // Member pointer types.
  } else if (type->getAs<MemberPointerType>()) {
    // Just add it all as opaque.
    addOpaqueData(begin, begin + CGM.getContext().getTypeSizeInChars(type));

    // Atomic types.
  } else if (const auto *atomicType = type->getAs<AtomicType>()) {
    auto valueType = atomicType->getValueType();
    auto atomicSize = CGM.getContext().getTypeSizeInChars(atomicType);
    auto valueSize = CGM.getContext().getTypeSizeInChars(valueType);

    addTypedData(atomicType->getValueType(), begin);

    // Add atomic padding.
    auto atomicPadding = atomicSize - valueSize;
    if (atomicPadding > CharUnits::Zero())
      addOpaqueData(begin + valueSize, begin + atomicSize);

    // Everything else is scalar and should not convert as an LLVM aggregate.
  } else {
    // We intentionally convert as !ForMem because we want to preserve
    // that a type was an i1.
    auto *llvmType = CGM.getTypes().ConvertType(type);
    addTypedData(llvmType, begin);
  }
}

void SwiftAggLowering::addTypedData(const RecordDecl *record, CharUnits begin) {
  addTypedData(record, begin, CGM.getContext().getASTRecordLayout(record));
}

void SwiftAggLowering::addTypedData(const RecordDecl *record, CharUnits begin,
                                    const ASTRecordLayout &layout) {
  // Unions are a special case.
  if (record->isUnion()) {
    for (auto *field : record->fields()) {
      if (field->isBitField()) {
        addBitFieldData(field, begin, 0);
      } else {
        addTypedData(field->getType(), begin);
      }
    }
    return;
  }

  // Note that correctness does not rely on us adding things in
  // their actual order of layout; it's just somewhat more efficient
  // for the builder.

  // With that in mind, add "early" C++ data.
  auto cxxRecord = dyn_cast<CXXRecordDecl>(record);
  if (cxxRecord) {
    //   - a v-table pointer, if the class adds its own
    if (layout.hasOwnVFPtr()) {
      addTypedData(CGM.Int8PtrTy, begin);
    }

    //   - non-virtual bases
    for (auto &baseSpecifier : cxxRecord->bases()) {
      if (baseSpecifier.isVirtual()) continue;

      auto baseRecord = baseSpecifier.getType()->getAsCXXRecordDecl();
      addTypedData(baseRecord, begin + layout.getBaseClassOffset(baseRecord));
    }

    //   - a vbptr if the class adds its own
    if (layout.hasOwnVBPtr()) {
      addTypedData(CGM.Int8PtrTy, begin + layout.getVBPtrOffset());
    }
  }

  // Add fields.
  for (auto *field : record->fields()) {
    auto fieldOffsetInBits = layout.getFieldOffset(field->getFieldIndex());
    if (field->isBitField()) {
      addBitFieldData(field, begin, fieldOffsetInBits);
    } else {
      addTypedData(field->getType(),
              begin + CGM.getContext().toCharUnitsFromBits(fieldOffsetInBits));
    }
  }

  // Add "late" C++ data:
  if (cxxRecord) {
    //   - virtual bases
    for (auto &vbaseSpecifier : cxxRecord->vbases()) {
      auto baseRecord = vbaseSpecifier.getType()->getAsCXXRecordDecl();
      addTypedData(baseRecord, begin + layout.getVBaseClassOffset(baseRecord));
    }
  }
}

void SwiftAggLowering::addBitFieldData(const FieldDecl *bitfield,
                                       CharUnits recordBegin,
                                       uint64_t bitfieldBitBegin) {
  assert(bitfield->isBitField());
  auto &ctx = CGM.getContext();
  auto width = bitfield->getBitWidthValue(ctx);

  // We can ignore zero-width bit-fields.
  if (width == 0) return;

  // toCharUnitsFromBits rounds down.
  CharUnits bitfieldByteBegin = ctx.toCharUnitsFromBits(bitfieldBitBegin);

  // Find the offset of the last byte that is partially occupied by the
  // bit-field; since we otherwise expect exclusive ends, the end is the
  // next byte.
  uint64_t bitfieldBitLast = bitfieldBitBegin + width - 1;
  CharUnits bitfieldByteEnd =
    ctx.toCharUnitsFromBits(bitfieldBitLast) + CharUnits::One();
  addOpaqueData(recordBegin + bitfieldByteBegin,
                recordBegin + bitfieldByteEnd);
}

void SwiftAggLowering::addTypedData(llvm::Type *type, CharUnits begin) {
  assert(type && "didn't provide type for typed data");
  addTypedData(type, begin, begin + getTypeStoreSize(CGM, type));
}

void SwiftAggLowering::addTypedData(llvm::Type *type,
                                    CharUnits begin, CharUnits end) {
  assert(type && "didn't provide type for typed data");
  assert(getTypeStoreSize(CGM, type) == end - begin);

  // Legalize vector types.
  if (auto vecTy = dyn_cast<llvm::VectorType>(type)) {
    SmallVector<llvm::Type*, 4> componentTys;
    legalizeVectorType(CGM, end - begin, vecTy, componentTys);
    assert(componentTys.size() >= 1);

    // Walk the initial components.
    for (size_t i = 0, e = componentTys.size(); i != e - 1; ++i) {
      llvm::Type *componentTy = componentTys[i];
      auto componentSize = getTypeStoreSize(CGM, componentTy);
      assert(componentSize < end - begin);
      addLegalTypedData(componentTy, begin, begin + componentSize);
      begin += componentSize;
    }

    return addLegalTypedData(componentTys.back(), begin, end);
  }

  // Legalize integer types.
  if (auto intTy = dyn_cast<llvm::IntegerType>(type)) {
    if (!isLegalIntegerType(CGM, intTy))
      return addOpaqueData(begin, end);
  }

  // All other types should be legal.
  return addLegalTypedData(type, begin, end);
}

void SwiftAggLowering::addLegalTypedData(llvm::Type *type,
                                         CharUnits begin, CharUnits end) {
  // Require the type to be naturally aligned.
  if (!begin.isZero() && !begin.isMultipleOf(getNaturalAlignment(CGM, type))) {

    // Try splitting vector types.
    if (auto vecTy = dyn_cast<llvm::VectorType>(type)) {
      auto split = splitLegalVectorType(CGM, end - begin, vecTy);
      auto eltTy = split.first;
      auto numElts = split.second;

      auto eltSize = (end - begin) / numElts;
      assert(eltSize == getTypeStoreSize(CGM, eltTy));
      for (size_t i = 0, e = numElts; i != e; ++i) {
        addLegalTypedData(eltTy, begin, begin + eltSize);
        begin += eltSize;
      }
      assert(begin == end);
      return;
    }

    return addOpaqueData(begin, end);
  }

  addEntry(type, begin, end);
}

void SwiftAggLowering::addEntry(llvm::Type *type,
                                CharUnits begin, CharUnits end) {
  assert((!type ||
          (!isa<llvm::StructType>(type) && !isa<llvm::ArrayType>(type))) &&
         "cannot add aggregate-typed data");
  assert(!type || begin.isMultipleOf(getNaturalAlignment(CGM, type)));

  // Fast path: we can just add entries to the end.
  if (Entries.empty() || Entries.back().End <= begin) {
    Entries.push_back({begin, end, type});
    return;
  }

  // Find the first existing entry that ends after the start of the new data.
  // TODO: do a binary search if Entries is big enough for it to matter.
  size_t index = Entries.size() - 1;
  while (index != 0) {
    if (Entries[index - 1].End <= begin) break;
    --index;
  }

  // The entry ends after the start of the new data.
  // If the entry starts after the end of the new data, there's no conflict.
  if (Entries[index].Begin >= end) {
    // This insertion is potentially O(n), but the way we generally build
    // these layouts makes that unlikely to matter: we'd need a union of
    // several very large types.
    Entries.insert(Entries.begin() + index, {begin, end, type});
    return;
  }

  // Otherwise, the ranges overlap.  The new range might also overlap
  // with later ranges.
restartAfterSplit:

  // Simplest case: an exact overlap.
  if (Entries[index].Begin == begin && Entries[index].End == end) {
    // If the types match exactly, great.
    if (Entries[index].Type == type) return;

    // If either type is opaque, make the entry opaque and return.
    if (Entries[index].Type == nullptr) {
      return;
    } else if (type == nullptr) {
      Entries[index].Type = nullptr;
      return;
    }

    // If they disagree in an ABI-agnostic way, just resolve the conflict
    // arbitrarily.
    if (auto entryType = getCommonType(Entries[index].Type, type)) {
      Entries[index].Type = entryType;
      return;
    }

    // Otherwise, make the entry opaque.
    Entries[index].Type = nullptr;
    return;
  }

  // Okay, we have an overlapping conflict of some sort.

  // If we have a vector type, split it.
  if (auto vecTy = dyn_cast_or_null<llvm::VectorType>(type)) {
    auto eltTy = vecTy->getElementType();
    CharUnits eltSize =
        (end - begin) / cast<llvm::FixedVectorType>(vecTy)->getNumElements();
    assert(eltSize == getTypeStoreSize(CGM, eltTy));
    for (unsigned i = 0,
                  e = cast<llvm::FixedVectorType>(vecTy)->getNumElements();
         i != e; ++i) {
      addEntry(eltTy, begin, begin + eltSize);
      begin += eltSize;
    }
    assert(begin == end);
    return;
  }

  // If the entry is a vector type, split it and try again.
  if (Entries[index].Type && Entries[index].Type->isVectorTy()) {
    splitVectorEntry(index);
    goto restartAfterSplit;
  }

  // Okay, we have no choice but to make the existing entry opaque.

  Entries[index].Type = nullptr;

  // Stretch the start of the entry to the beginning of the range.
  if (begin < Entries[index].Begin) {
    Entries[index].Begin = begin;
    assert(index == 0 || begin >= Entries[index - 1].End);
  }

  // Stretch the end of the entry to the end of the range; but if we run
  // into the start of the next entry, just leave the range there and repeat.
  while (end > Entries[index].End) {
    assert(Entries[index].Type == nullptr);

    // If the range doesn't overlap the next entry, we're done.
    if (index == Entries.size() - 1 || end <= Entries[index + 1].Begin) {
      Entries[index].End = end;
      break;
    }

    // Otherwise, stretch to the start of the next entry.
    Entries[index].End = Entries[index + 1].Begin;

    // Continue with the next entry.
    index++;

    // This entry needs to be made opaque if it is not already.
    if (Entries[index].Type == nullptr)
      continue;

    // Split vector entries unless we completely subsume them.
    if (Entries[index].Type->isVectorTy() &&
        end < Entries[index].End) {
      splitVectorEntry(index);
    }

    // Make the entry opaque.
    Entries[index].Type = nullptr;
  }
}

/// Replace the entry of vector type at offset 'index' with a sequence
/// of its component vectors.
void SwiftAggLowering::splitVectorEntry(unsigned index) {
  auto vecTy = cast<llvm::VectorType>(Entries[index].Type);
  auto split = splitLegalVectorType(CGM, Entries[index].getWidth(), vecTy);

  auto eltTy = split.first;
  CharUnits eltSize = getTypeStoreSize(CGM, eltTy);
  auto numElts = split.second;
  Entries.insert(Entries.begin() + index + 1, numElts - 1, StorageEntry());

  CharUnits begin = Entries[index].Begin;
  for (unsigned i = 0; i != numElts; ++i) {
    unsigned idx = index + i;
    Entries[idx].Type = eltTy;
    Entries[idx].Begin = begin;
    Entries[idx].End = begin + eltSize;
    begin += eltSize;
  }
}

/// Given a power-of-two unit size, return the offset of the aligned unit
/// of that size which contains the given offset.
///
/// In other words, round down to the nearest multiple of the unit size.
static CharUnits getOffsetAtStartOfUnit(CharUnits offset, CharUnits unitSize) {
  assert(isPowerOf2(unitSize.getQuantity()));
  auto unitMask = ~(unitSize.getQuantity() - 1);
  return CharUnits::fromQuantity(offset.getQuantity() & unitMask);
}

static bool areBytesInSameUnit(CharUnits first, CharUnits second,
                               CharUnits chunkSize) {
  return getOffsetAtStartOfUnit(first, chunkSize)
      == getOffsetAtStartOfUnit(second, chunkSize);
}

static bool isMergeableEntryType(llvm::Type *type) {
  // Opaquely-typed memory is always mergeable.
  if (type == nullptr) return true;

  // Pointers and integers are always mergeable.  In theory we should not
  // merge pointers, but (1) it doesn't currently matter in practice because
  // the chunk size is never greater than the size of a pointer and (2)
  // Swift IRGen uses integer types for a lot of things that are "really"
  // just storing pointers (like std::optional<SomePointer>).  If we ever have a
  // target that would otherwise combine pointers, we should put some effort
  // into fixing those cases in Swift IRGen and then call out pointer types
  // here.

  // Floating-point and vector types should never be merged.
  // Most such types are too large and highly-aligned to ever trigger merging
  // in practice, but it's important for the rule to cover at least 'half'
  // and 'float', as well as things like small vectors of 'i1' or 'i8'.
  return (!type->isFloatingPointTy() && !type->isVectorTy());
}

bool SwiftAggLowering::shouldMergeEntries(const StorageEntry &first,
                                          const StorageEntry &second,
                                          CharUnits chunkSize) {
  // Only merge entries that overlap the same chunk.  We test this first
  // despite being a bit more expensive because this is the condition that
  // tends to prevent merging.
  if (!areBytesInSameUnit(first.End - CharUnits::One(), second.Begin,
                          chunkSize))
    return false;

  return (isMergeableEntryType(first.Type) &&
          isMergeableEntryType(second.Type));
}

void SwiftAggLowering::finish() {
  if (Entries.empty()) {
    Finished = true;
    return;
  }

  // We logically split the layout down into a series of chunks of this size,
  // which is generally the size of a pointer.
  const CharUnits chunkSize = getMaximumVoluntaryIntegerSize(CGM);

  // First pass: if two entries should be merged, make them both opaque
  // and stretch one to meet the next.
  // Also, remember if there are any opaque entries.
  bool hasOpaqueEntries = (Entries[0].Type == nullptr);
  for (size_t i = 1, e = Entries.size(); i != e; ++i) {
    if (shouldMergeEntries(Entries[i - 1], Entries[i], chunkSize)) {
      Entries[i - 1].Type = nullptr;
      Entries[i].Type = nullptr;
      Entries[i - 1].End = Entries[i].Begin;
      hasOpaqueEntries = true;

    } else if (Entries[i].Type == nullptr) {
      hasOpaqueEntries = true;
    }
  }

  // The rest of the algorithm leaves non-opaque entries alone, so if we
  // have no opaque entries, we're done.
  if (!hasOpaqueEntries) {
    Finished = true;
    return;
  }

  // Okay, move the entries to a temporary and rebuild Entries.
  auto orig = std::move(Entries);
  assert(Entries.empty());

  for (size_t i = 0, e = orig.size(); i != e; ++i) {
    // Just copy over non-opaque entries.
    if (orig[i].Type != nullptr) {
      Entries.push_back(orig[i]);
      continue;
    }

    // Scan forward to determine the full extent of the next opaque range.
    // We know from the first pass that only contiguous ranges will overlap
    // the same aligned chunk.
    auto begin = orig[i].Begin;
    auto end = orig[i].End;
    while (i + 1 != e &&
           orig[i + 1].Type == nullptr &&
           end == orig[i + 1].Begin) {
      end = orig[i + 1].End;
      i++;
    }

    // Add an entry per intersected chunk.
    do {
      // Find the smallest aligned storage unit in the maximal aligned
      // storage unit containing 'begin' that contains all the bytes in
      // the intersection between the range and this chunk.
      CharUnits localBegin = begin;
      CharUnits chunkBegin = getOffsetAtStartOfUnit(localBegin, chunkSize);
      CharUnits chunkEnd = chunkBegin + chunkSize;
      CharUnits localEnd = std::min(end, chunkEnd);

      // Just do a simple loop over ever-increasing unit sizes.
      CharUnits unitSize = CharUnits::One();
      CharUnits unitBegin, unitEnd;
      for (; ; unitSize *= 2) {
        assert(unitSize <= chunkSize);
        unitBegin = getOffsetAtStartOfUnit(localBegin, unitSize);
        unitEnd = unitBegin + unitSize;
        if (unitEnd >= localEnd) break;
      }

      // Add an entry for this unit.
      auto entryTy =
        llvm::IntegerType::get(CGM.getLLVMContext(),
                               CGM.getContext().toBits(unitSize));
      Entries.push_back({unitBegin, unitEnd, entryTy});

      // The next chunk starts where this chunk left off.
      begin = localEnd;
    } while (begin != end);
  }

  // Okay, finally finished.
  Finished = true;
}

void SwiftAggLowering::enumerateComponents(EnumerationCallback callback) const {
  assert(Finished && "haven't yet finished lowering");

  for (auto &entry : Entries) {
    callback(entry.Begin, entry.End, entry.Type);
  }
}

std::pair<llvm::StructType*, llvm::Type*>
SwiftAggLowering::getCoerceAndExpandTypes() const {
  assert(Finished && "haven't yet finished lowering");

  auto &ctx = CGM.getLLVMContext();

  if (Entries.empty()) {
    auto type = llvm::StructType::get(ctx);
    return { type, type };
  }

  SmallVector<llvm::Type*, 8> elts;
  CharUnits lastEnd = CharUnits::Zero();
  bool hasPadding = false;
  bool packed = false;
  for (auto &entry : Entries) {
    if (entry.Begin != lastEnd) {
      auto paddingSize = entry.Begin - lastEnd;
      assert(!paddingSize.isNegative());

      auto padding = llvm::ArrayType::get(llvm::Type::getInt8Ty(ctx),
                                          paddingSize.getQuantity());
      elts.push_back(padding);
      hasPadding = true;
    }

    if (!packed && !entry.Begin.isMultipleOf(CharUnits::fromQuantity(
                       CGM.getDataLayout().getABITypeAlign(entry.Type))))
      packed = true;

    elts.push_back(entry.Type);

    lastEnd = entry.Begin + getTypeAllocSize(CGM, entry.Type);
    assert(entry.End <= lastEnd);
  }

  // We don't need to adjust 'packed' to deal with possible tail padding
  // because we never do that kind of access through the coercion type.
  auto coercionType = llvm::StructType::get(ctx, elts, packed);

  llvm::Type *unpaddedType = coercionType;
  if (hasPadding) {
    elts.clear();
    for (auto &entry : Entries) {
      elts.push_back(entry.Type);
    }
    if (elts.size() == 1) {
      unpaddedType = elts[0];
    } else {
      unpaddedType = llvm::StructType::get(ctx, elts, /*packed*/ false);
    }
  } else if (Entries.size() == 1) {
    unpaddedType = Entries[0].Type;
  }

  return { coercionType, unpaddedType };
}

bool SwiftAggLowering::shouldPassIndirectly(bool asReturnValue) const {
  assert(Finished && "haven't yet finished lowering");

  // Empty types don't need to be passed indirectly.
  if (Entries.empty()) return false;

  // Avoid copying the array of types when there's just a single element.
  if (Entries.size() == 1) {
    return getSwiftABIInfo(CGM).shouldPassIndirectly(Entries.back().Type,
                                                     asReturnValue);
  }

  SmallVector<llvm::Type*, 8> componentTys;
  componentTys.reserve(Entries.size());
  for (auto &entry : Entries) {
    componentTys.push_back(entry.Type);
  }
  return getSwiftABIInfo(CGM).shouldPassIndirectly(componentTys, asReturnValue);
}

bool swiftcall::shouldPassIndirectly(CodeGenModule &CGM,
                                     ArrayRef<llvm::Type*> componentTys,
                                     bool asReturnValue) {
  return getSwiftABIInfo(CGM).shouldPassIndirectly(componentTys, asReturnValue);
}

CharUnits swiftcall::getMaximumVoluntaryIntegerSize(CodeGenModule &CGM) {
  // Currently always the size of an ordinary pointer.
  return CGM.getContext().toCharUnitsFromBits(
      CGM.getContext().getTargetInfo().getPointerWidth(LangAS::Default));
}

CharUnits swiftcall::getNaturalAlignment(CodeGenModule &CGM, llvm::Type *type) {
  // For Swift's purposes, this is always just the store size of the type
  // rounded up to a power of 2.
  auto size = (unsigned long long) getTypeStoreSize(CGM, type).getQuantity();
  size = llvm::bit_ceil(size);
  assert(CGM.getDataLayout().getABITypeAlign(type) <= size);
  return CharUnits::fromQuantity(size);
}

bool swiftcall::isLegalIntegerType(CodeGenModule &CGM,
                                   llvm::IntegerType *intTy) {
  auto size = intTy->getBitWidth();
  switch (size) {
  case 1:
  case 8:
  case 16:
  case 32:
  case 64:
    // Just assume that the above are always legal.
    return true;

  case 128:
    return CGM.getContext().getTargetInfo().hasInt128Type();

  default:
    return false;
  }
}

bool swiftcall::isLegalVectorType(CodeGenModule &CGM, CharUnits vectorSize,
                                  llvm::VectorType *vectorTy) {
  return isLegalVectorType(
      CGM, vectorSize, vectorTy->getElementType(),
      cast<llvm::FixedVectorType>(vectorTy)->getNumElements());
}

bool swiftcall::isLegalVectorType(CodeGenModule &CGM, CharUnits vectorSize,
                                  llvm::Type *eltTy, unsigned numElts) {
  assert(numElts > 1 && "illegal vector length");
  return getSwiftABIInfo(CGM).isLegalVectorType(vectorSize, eltTy, numElts);
}

std::pair<llvm::Type*, unsigned>
swiftcall::splitLegalVectorType(CodeGenModule &CGM, CharUnits vectorSize,
                                llvm::VectorType *vectorTy) {
  auto numElts = cast<llvm::FixedVectorType>(vectorTy)->getNumElements();
  auto eltTy = vectorTy->getElementType();

  // Try to split the vector type in half.
  if (numElts >= 4 && isPowerOf2(numElts)) {
    if (isLegalVectorType(CGM, vectorSize / 2, eltTy, numElts / 2))
      return {llvm::FixedVectorType::get(eltTy, numElts / 2), 2};
  }

  return {eltTy, numElts};
}

void swiftcall::legalizeVectorType(CodeGenModule &CGM, CharUnits origVectorSize,
                                   llvm::VectorType *origVectorTy,
                             llvm::SmallVectorImpl<llvm::Type*> &components) {
  // If it's already a legal vector type, use it.
  if (isLegalVectorType(CGM, origVectorSize, origVectorTy)) {
    components.push_back(origVectorTy);
    return;
  }

  // Try to split the vector into legal subvectors.
  auto numElts = cast<llvm::FixedVectorType>(origVectorTy)->getNumElements();
  auto eltTy = origVectorTy->getElementType();
  assert(numElts != 1);

  // The largest size that we're still considering making subvectors of.
  // Always a power of 2.
  unsigned logCandidateNumElts = llvm::Log2_32(numElts);
  unsigned candidateNumElts = 1U << logCandidateNumElts;
  assert(candidateNumElts <= numElts && candidateNumElts * 2 > numElts);

  // Minor optimization: don't check the legality of this exact size twice.
  if (candidateNumElts == numElts) {
    logCandidateNumElts--;
    candidateNumElts >>= 1;
  }

  CharUnits eltSize = (origVectorSize / numElts);
  CharUnits candidateSize = eltSize * candidateNumElts;

  // The sensibility of this algorithm relies on the fact that we never
  // have a legal non-power-of-2 vector size without having the power of 2
  // also be legal.
  while (logCandidateNumElts > 0) {
    assert(candidateNumElts == 1U << logCandidateNumElts);
    assert(candidateNumElts <= numElts);
    assert(candidateSize == eltSize * candidateNumElts);

    // Skip illegal vector sizes.
    if (!isLegalVectorType(CGM, candidateSize, eltTy, candidateNumElts)) {
      logCandidateNumElts--;
      candidateNumElts /= 2;
      candidateSize /= 2;
      continue;
    }

    // Add the right number of vectors of this size.
    auto numVecs = numElts >> logCandidateNumElts;
    components.append(numVecs,
                      llvm::FixedVectorType::get(eltTy, candidateNumElts));
    numElts -= (numVecs << logCandidateNumElts);

    if (numElts == 0) return;

    // It's possible that the number of elements remaining will be legal.
    // This can happen with e.g. <7 x float> when <3 x float> is legal.
    // This only needs to be separately checked if it's not a power of 2.
    if (numElts > 2 && !isPowerOf2(numElts) &&
        isLegalVectorType(CGM, eltSize * numElts, eltTy, numElts)) {
      components.push_back(llvm::FixedVectorType::get(eltTy, numElts));
      return;
    }

    // Bring vecSize down to something no larger than numElts.
    do {
      logCandidateNumElts--;
      candidateNumElts /= 2;
      candidateSize /= 2;
    } while (candidateNumElts > numElts);
  }

  // Otherwise, just append a bunch of individual elements.
  components.append(numElts, eltTy);
}

bool swiftcall::mustPassRecordIndirectly(CodeGenModule &CGM,
                                         const RecordDecl *record) {
  // FIXME: should we not rely on the standard computation in Sema, just in
  // case we want to diverge from the platform ABI (e.g. on targets where
  // that uses the MSVC rule)?
  return !record->canPassInRegisters();
}

static ABIArgInfo classifyExpandedType(SwiftAggLowering &lowering,
                                       bool forReturn,
                                       CharUnits alignmentForIndirect) {
  if (lowering.empty()) {
    return ABIArgInfo::getIgnore();
  } else if (lowering.shouldPassIndirectly(forReturn)) {
    return ABIArgInfo::getIndirect(alignmentForIndirect, /*byval*/ false);
  } else {
    auto types = lowering.getCoerceAndExpandTypes();
    return ABIArgInfo::getCoerceAndExpand(types.first, types.second);
  }
}

static ABIArgInfo classifyType(CodeGenModule &CGM, CanQualType type,
                               bool forReturn) {
  if (auto recordType = dyn_cast<RecordType>(type)) {
    auto record = recordType->getDecl();
    auto &layout = CGM.getContext().getASTRecordLayout(record);

    if (mustPassRecordIndirectly(CGM, record))
      return ABIArgInfo::getIndirect(layout.getAlignment(), /*byval*/ false);

    SwiftAggLowering lowering(CGM);
    lowering.addTypedData(recordType->getDecl(), CharUnits::Zero(), layout);
    lowering.finish();

    return classifyExpandedType(lowering, forReturn, layout.getAlignment());
  }

  // Just assume that all of our target ABIs can support returning at least
  // two integer or floating-point values.
  if (isa<ComplexType>(type)) {
    return (forReturn ? ABIArgInfo::getDirect() : ABIArgInfo::getExpand());
  }

  // Vector types may need to be legalized.
  if (isa<VectorType>(type)) {
    SwiftAggLowering lowering(CGM);
    lowering.addTypedData(type, CharUnits::Zero());
    lowering.finish();

    CharUnits alignment = CGM.getContext().getTypeAlignInChars(type);
    return classifyExpandedType(lowering, forReturn, alignment);
  }

  // Member pointer types need to be expanded, but it's a simple form of
  // expansion that 'Direct' can handle.  Note that CanBeFlattened should be
  // true for this to work.

  // 'void' needs to be ignored.
  if (type->isVoidType()) {
    return ABIArgInfo::getIgnore();
  }

  // Everything else can be passed directly.
  return ABIArgInfo::getDirect();
}

ABIArgInfo swiftcall::classifyReturnType(CodeGenModule &CGM, CanQualType type) {
  return classifyType(CGM, type, /*forReturn*/ true);
}

ABIArgInfo swiftcall::classifyArgumentType(CodeGenModule &CGM,
                                           CanQualType type) {
  return classifyType(CGM, type, /*forReturn*/ false);
}

void swiftcall::computeABIInfo(CodeGenModule &CGM, CGFunctionInfo &FI) {
  auto &retInfo = FI.getReturnInfo();
  retInfo = classifyReturnType(CGM, FI.getReturnType());

  for (unsigned i = 0, e = FI.arg_size(); i != e; ++i) {
    auto &argInfo = FI.arg_begin()[i];
    argInfo.info = classifyArgumentType(CGM, argInfo.type);
  }
}

// Is swifterror lowered to a register by the target ABI.
bool swiftcall::isSwiftErrorLoweredInRegister(CodeGenModule &CGM) {
  return getSwiftABIInfo(CGM).isSwiftErrorInRegister();
}
