//===----- ABIInfo.h - ABI information access & encapsulation ---*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_LIB_CODEGEN_ABIINFO_H
#define LLVM_CLANG_LIB_CODEGEN_ABIINFO_H

#include "clang/AST/Type.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/Type.h"

namespace llvm {
  class Value;
  class LLVMContext;
  class DataLayout;
}

namespace clang {
  class ASTContext;
  class TargetInfo;

  namespace CodeGen {
    class ABIArgInfo;
    class Address;
    class CGCXXABI;
    class CGFunctionInfo;
    class CodeGenFunction;
    class CodeGenTypes;
  }

  // FIXME: All of this stuff should be part of the target interface
  // somehow. It is currently here because it is not clear how to factor
  // the targets to support this, since the Targets currently live in a
  // layer below types n'stuff.


  /// ABIInfo - Target specific hooks for defining how a type should be
  /// passed or returned from functions.
  class ABIInfo {
  public:
    CodeGen::CodeGenTypes &CGT;
  protected:
    llvm::CallingConv::ID RuntimeCC;
    llvm::CallingConv::ID BuiltinCC;
  public:
    ABIInfo(CodeGen::CodeGenTypes &cgt)
      : CGT(cgt),
        RuntimeCC(llvm::CallingConv::C),
        BuiltinCC(llvm::CallingConv::C) {}

    virtual ~ABIInfo();

    CodeGen::CGCXXABI &getCXXABI() const;
    ASTContext &getContext() const;
    llvm::LLVMContext &getVMContext() const;
    const llvm::DataLayout &getDataLayout() const;
    const TargetInfo &getTarget() const;

    /// Return the calling convention to use for system runtime
    /// functions.
    llvm::CallingConv::ID getRuntimeCC() const {
      return RuntimeCC;
    }

    /// Return the calling convention to use for compiler builtins
    llvm::CallingConv::ID getBuiltinCC() const {
      return BuiltinCC;
    }

    virtual void computeInfo(CodeGen::CGFunctionInfo &FI) const = 0;

    /// EmitVAArg - Emit the target dependent code to load a value of
    /// \arg Ty from the va_list pointed to by \arg VAListAddr.

    // FIXME: This is a gaping layering violation if we wanted to drop
    // the ABI information any lower than CodeGen. Of course, for
    // VAArg handling it has to be at this level; there is no way to
    // abstract this out.
    virtual CodeGen::Address EmitVAArg(CodeGen::CodeGenFunction &CGF,
                                       CodeGen::Address VAListAddr,
                                       QualType Ty) const = 0;

    /// Emit the target dependent code to load a value of
    /// \arg Ty from the \c __builtin_ms_va_list pointed to by \arg VAListAddr.
    virtual CodeGen::Address EmitMSVAArg(CodeGen::CodeGenFunction &CGF,
                                         CodeGen::Address VAListAddr,
                                         QualType Ty) const;

    virtual bool isHomogeneousAggregateBaseType(QualType Ty) const;

    virtual bool isHomogeneousAggregateSmallEnough(const Type *Base,
                                                   uint64_t Members) const;

    virtual bool shouldSignExtUnsignedType(QualType Ty) const;

    bool isHomogeneousAggregate(QualType Ty, const Type *&Base,
                                uint64_t &Members) const;

    /// A convenience method to return an indirect ABIArgInfo with an
    /// expected alignment equal to the ABI alignment of the given type.
    CodeGen::ABIArgInfo
    getNaturalAlignIndirect(QualType Ty, bool ByRef = true,
                            bool Realign = false,
                            llvm::Type *Padding = nullptr) const;

    CodeGen::ABIArgInfo
    getNaturalAlignIndirectInReg(QualType Ty, bool Realign = false) const;
  };
}  // end namespace clang

#endif