//==-- SwiftCallingConv.h - Swift ABI lowering -----------------------------==//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Defines constants and types related to Swift ABI lowering.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_CODEGEN_SWIFTCALLINGCONV_H
#define LLVM_CLANG_CODEGEN_SWIFTCALLINGCONV_H

#include "clang/AST/CanonicalType.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/Type.h"
#include "llvm/Support/TrailingObjects.h"
#include <cassert>

namespace llvm {
  class IntegerType;
  class Type;
  class StructType;
  class VectorType;
}

namespace clang {
class Decl;
class FieldDecl;
class ASTRecordLayout;

namespace CodeGen {
class ABIArgInfo;
class CodeGenModule;
class CGFunctionInfo;

namespace swiftcall {

class SwiftAggLowering {
  CodeGenModule &CGM;

  struct StorageEntry {
    CharUnits Begin;
    CharUnits End;
    llvm::Type *Type;

    CharUnits getWidth() const {
      return End - Begin;
    }
  };
  SmallVector<StorageEntry, 4> Entries;
  bool Finished = false;

public:
  SwiftAggLowering(CodeGenModule &CGM) : CGM(CGM) {}

  void addOpaqueData(CharUnits begin, CharUnits end) {
    addEntry(nullptr, begin, end);
  }

  void addTypedData(QualType type, CharUnits begin);
  void addTypedData(const RecordDecl *record, CharUnits begin);
  void addTypedData(const RecordDecl *record, CharUnits begin,
                    const ASTRecordLayout &layout);
  void addTypedData(llvm::Type *type, CharUnits begin);
  void addTypedData(llvm::Type *type, CharUnits begin, CharUnits end);

  void finish();

  /// Does this lowering require passing any data?
  bool empty() const {
    assert(Finished && "didn't finish lowering before calling empty()");
    return Entries.empty();
  }

  /// According to the target Swift ABI, should a value with this lowering
  /// be passed indirectly?
  ///
  /// Note that this decision is based purely on the data layout of the
  /// value and does not consider whether the type is address-only,
  /// must be passed indirectly to match a function abstraction pattern, or
  /// anything else that is expected to be handled by high-level lowering.
  ///
  /// \param asReturnValue - if true, answer whether it should be passed
  ///   indirectly as a return value; if false, answer whether it should be
  ///   passed indirectly as an argument
  bool shouldPassIndirectly(bool asReturnValue) const;

  using EnumerationCallback =
    llvm::function_ref<void(CharUnits offset, CharUnits end, llvm::Type *type)>;

  /// Enumerate the expanded components of this type.
  ///
  /// The component types will always be legal vector, floating-point,
  /// integer, or pointer types.
  void enumerateComponents(EnumerationCallback callback) const;

  /// Return the types for a coerce-and-expand operation.
  ///
  /// The first type matches the memory layout of the data that's been
  /// added to this structure, including explicit [N x i8] arrays for any
  /// internal padding.
  ///
  /// The second type removes any internal padding members and, if only
  /// one element remains, is simply that element type.
  std::pair<llvm::StructType*, llvm::Type*> getCoerceAndExpandTypes() const;

private:
  void addBitFieldData(const FieldDecl *field, CharUnits begin,
                       uint64_t bitOffset);
  void addLegalTypedData(llvm::Type *type, CharUnits begin, CharUnits end);
  void addEntry(llvm::Type *type, CharUnits begin, CharUnits end);
  void splitVectorEntry(unsigned index);
};

/// Should an aggregate which expands to the given type sequence
/// be passed/returned indirectly under swiftcall?
bool shouldPassIndirectly(CodeGenModule &CGM,
                          ArrayRef<llvm::Type*> types,
                          bool asReturnValue);

/// Return the maximum voluntary integer size for the current target.
CharUnits getMaximumVoluntaryIntegerSize(CodeGenModule &CGM);

/// Return the Swift CC's notion of the natural alignment of a type.
CharUnits getNaturalAlignment(CodeGenModule &CGM, llvm::Type *type);

/// Is the given integer type "legal" for Swift's perspective on the
/// current platform?
bool isLegalIntegerType(CodeGenModule &CGM, llvm::IntegerType *type);

/// Is the given vector type "legal" for Swift's perspective on the
/// current platform?
bool isLegalVectorType(CodeGenModule &CGM, CharUnits vectorSize,
                       llvm::VectorType *vectorTy);
bool isLegalVectorType(CodeGenModule &CGM, CharUnits vectorSize,
                       llvm::Type *eltTy, unsigned numElts);

/// Minimally split a legal vector type.
std::pair<llvm::Type*, unsigned>
splitLegalVectorType(CodeGenModule &CGM, CharUnits vectorSize,
                     llvm::VectorType *vectorTy);

/// Turn a vector type in a sequence of legal component vector types.
///
/// The caller may assume that the sum of the data sizes of the resulting
/// types will equal the data size of the vector type.
void legalizeVectorType(CodeGenModule &CGM, CharUnits vectorSize,
                        llvm::VectorType *vectorTy,
                        llvm::SmallVectorImpl<llvm::Type*> &types);

/// Should a C++ record type be passed and returned indirectly?
bool shouldPassCXXRecordIndirectly(CodeGenModule &CGM,
                                   const CXXRecordDecl *record);

/// Classify the rules for how to return a particular type.
ABIArgInfo classifyReturnType(CodeGenModule &CGM, CanQualType type);

/// Classify the rules for how to pass a particular type.
ABIArgInfo classifyArgumentType(CodeGenModule &CGM, CanQualType type);

/// Compute the ABI information of a swiftcall function.  This is a
/// private interface for Clang.
void computeABIInfo(CodeGenModule &CGM, CGFunctionInfo &FI);

/// Is swifterror lowered to a register by the target ABI.
bool isSwiftErrorLoweredInRegister(CodeGenModule &CGM);

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

#endif
