//===-- llvm/CodeGen/TargetCallingConv.h - Calling Convention ---*- C++ -*-===//
 
//
 
// 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
 
//
 
//===----------------------------------------------------------------------===//
 
//
 
// This file defines types for working with calling-convention information.
 
//
 
//===----------------------------------------------------------------------===//
 
 
 
#ifndef LLVM_CODEGEN_TARGETCALLINGCONV_H
 
#define LLVM_CODEGEN_TARGETCALLINGCONV_H
 
 
 
#include "llvm/CodeGen/ValueTypes.h"
 
#include "llvm/Support/Alignment.h"
 
#include "llvm/Support/MachineValueType.h"
 
#include "llvm/Support/MathExtras.h"
 
#include <cassert>
 
#include <climits>
 
#include <cstdint>
 
 
 
namespace llvm {
 
namespace ISD {
 
 
 
  struct ArgFlagsTy {
 
  private:
 
    unsigned IsZExt : 1;     ///< Zero extended
 
    unsigned IsSExt : 1;     ///< Sign extended
 
    unsigned IsInReg : 1;    ///< Passed in register
 
    unsigned IsSRet : 1;     ///< Hidden struct-ret ptr
 
    unsigned IsByVal : 1;    ///< Struct passed by value
 
    unsigned IsByRef : 1;    ///< Passed in memory
 
    unsigned IsNest : 1;     ///< Nested fn static chain
 
    unsigned IsReturned : 1; ///< Always returned
 
    unsigned IsSplit : 1;
 
    unsigned IsInAlloca : 1;   ///< Passed with inalloca
 
    unsigned IsPreallocated : 1; ///< ByVal without the copy
 
    unsigned IsSplitEnd : 1;   ///< Last part of a split
 
    unsigned IsSwiftSelf : 1;  ///< Swift self parameter
 
    unsigned IsSwiftAsync : 1;  ///< Swift async context parameter
 
    unsigned IsSwiftError : 1; ///< Swift error parameter
 
    unsigned IsCFGuardTarget : 1; ///< Control Flow Guard target
 
    unsigned IsHva : 1;        ///< HVA field for
 
    unsigned IsHvaStart : 1;   ///< HVA structure start
 
    unsigned IsSecArgPass : 1; ///< Second argument
 
    unsigned MemAlign : 4;     ///< Log 2 of alignment when arg is passed in memory
 
                               ///< (including byval/byref). The max alignment is
 
                               ///< verified in IR verification.
 
    unsigned OrigAlign : 5;    ///< Log 2 of original alignment
 
    unsigned IsInConsecutiveRegsLast : 1;
 
    unsigned IsInConsecutiveRegs : 1;
 
    unsigned IsCopyElisionCandidate : 1; ///< Argument copy elision candidate
 
    unsigned IsPointer : 1;
 
 
 
    unsigned ByValOrByRefSize = 0; ///< Byval or byref struct size
 
 
 
    unsigned PointerAddrSpace = 0; ///< Address space of pointer argument
 
 
 
  public:
 
    ArgFlagsTy()
 
        : IsZExt(0), IsSExt(0), IsInReg(0), IsSRet(0), IsByVal(0), IsByRef(0),
 
          IsNest(0), IsReturned(0), IsSplit(0), IsInAlloca(0),
 
          IsPreallocated(0), IsSplitEnd(0), IsSwiftSelf(0), IsSwiftAsync(0),
 
          IsSwiftError(0), IsCFGuardTarget(0), IsHva(0), IsHvaStart(0),
 
          IsSecArgPass(0), MemAlign(0), OrigAlign(0),
 
          IsInConsecutiveRegsLast(0), IsInConsecutiveRegs(0),
 
          IsCopyElisionCandidate(0), IsPointer(0) {
 
      static_assert(sizeof(*this) == 3 * sizeof(unsigned), "flags are too big");
 
    }
 
 
 
    bool isZExt() const { return IsZExt; }
 
    void setZExt() { IsZExt = 1; }
 
 
 
    bool isSExt() const { return IsSExt; }
 
    void setSExt() { IsSExt = 1; }
 
 
 
    bool isInReg() const { return IsInReg; }
 
    void setInReg() { IsInReg = 1; }
 
 
 
    bool isSRet() const { return IsSRet; }
 
    void setSRet() { IsSRet = 1; }
 
 
 
    bool isByVal() const { return IsByVal; }
 
    void setByVal() { IsByVal = 1; }
 
 
 
    bool isByRef() const { return IsByRef; }
 
    void setByRef() { IsByRef = 1; }
 
 
 
    bool isInAlloca() const { return IsInAlloca; }
 
    void setInAlloca() { IsInAlloca = 1; }
 
 
 
    bool isPreallocated() const { return IsPreallocated; }
 
    void setPreallocated() { IsPreallocated = 1; }
 
 
 
    bool isSwiftSelf() const { return IsSwiftSelf; }
 
    void setSwiftSelf() { IsSwiftSelf = 1; }
 
 
 
    bool isSwiftAsync() const { return IsSwiftAsync; }
 
    void setSwiftAsync() { IsSwiftAsync = 1; }
 
 
 
    bool isSwiftError() const { return IsSwiftError; }
 
    void setSwiftError() { IsSwiftError = 1; }
 
 
 
    bool isCFGuardTarget() const { return IsCFGuardTarget; }
 
    void setCFGuardTarget() { IsCFGuardTarget = 1; }
 
 
 
    bool isHva() const { return IsHva; }
 
    void setHva() { IsHva = 1; }
 
 
 
    bool isHvaStart() const { return IsHvaStart; }
 
    void setHvaStart() { IsHvaStart = 1; }
 
 
 
    bool isSecArgPass() const { return IsSecArgPass; }
 
    void setSecArgPass() { IsSecArgPass = 1; }
 
 
 
    bool isNest() const { return IsNest; }
 
    void setNest() { IsNest = 1; }
 
 
 
    bool isReturned() const { return IsReturned; }
 
    void setReturned(bool V = true) { IsReturned = V; }
 
 
 
    bool isInConsecutiveRegs()  const { return IsInConsecutiveRegs; }
 
    void setInConsecutiveRegs(bool Flag = true) { IsInConsecutiveRegs = Flag; }
 
 
 
    bool isInConsecutiveRegsLast() const { return IsInConsecutiveRegsLast; }
 
    void setInConsecutiveRegsLast(bool Flag = true) {
 
      IsInConsecutiveRegsLast = Flag;
 
    }
 
 
 
    bool isSplit()   const { return IsSplit; }
 
    void setSplit()  { IsSplit = 1; }
 
 
 
    bool isSplitEnd()   const { return IsSplitEnd; }
 
    void setSplitEnd()  { IsSplitEnd = 1; }
 
 
 
    bool isCopyElisionCandidate()  const { return IsCopyElisionCandidate; }
 
    void setCopyElisionCandidate() { IsCopyElisionCandidate = 1; }
 
 
 
    bool isPointer()  const { return IsPointer; }
 
    void setPointer() { IsPointer = 1; }
 
 
 
    Align getNonZeroMemAlign() const {
 
      return decodeMaybeAlign(MemAlign).valueOrOne();
 
    }
 
 
 
    void setMemAlign(Align A) {
 
      MemAlign = encode(A);
 
      assert(getNonZeroMemAlign() == A && "bitfield overflow");
 
    }
 
 
 
    Align getNonZeroByValAlign() const {
 
      assert(isByVal());
 
      MaybeAlign A = decodeMaybeAlign(MemAlign);
 
      assert(A && "ByValAlign must be defined");
 
      return *A;
 
    }
 
 
 
    Align getNonZeroOrigAlign() const {
 
      return decodeMaybeAlign(OrigAlign).valueOrOne();
 
    }
 
 
 
    void setOrigAlign(Align A) {
 
      OrigAlign = encode(A);
 
      assert(getNonZeroOrigAlign() == A && "bitfield overflow");
 
    }
 
 
 
    unsigned getByValSize() const {
 
      assert(isByVal() && !isByRef());
 
      return ByValOrByRefSize;
 
    }
 
    void setByValSize(unsigned S) {
 
      assert(isByVal() && !isByRef());
 
      ByValOrByRefSize = S;
 
    }
 
 
 
    unsigned getByRefSize() const {
 
      assert(!isByVal() && isByRef());
 
      return ByValOrByRefSize;
 
    }
 
    void setByRefSize(unsigned S) {
 
      assert(!isByVal() && isByRef());
 
      ByValOrByRefSize = S;
 
    }
 
 
 
    unsigned getPointerAddrSpace() const { return PointerAddrSpace; }
 
    void setPointerAddrSpace(unsigned AS) { PointerAddrSpace = AS; }
 
};
 
 
 
  /// InputArg - This struct carries flags and type information about a
 
  /// single incoming (formal) argument or incoming (from the perspective
 
  /// of the caller) return value virtual register.
 
  ///
 
  struct InputArg {
 
    ArgFlagsTy Flags;
 
    MVT VT = MVT::Other;
 
    EVT ArgVT;
 
    bool Used = false;
 
 
 
    /// Index original Function's argument.
 
    unsigned OrigArgIndex;
 
    /// Sentinel value for implicit machine-level input arguments.
 
    static const unsigned NoArgIndex = UINT_MAX;
 
 
 
    /// Offset in bytes of current input value relative to the beginning of
 
    /// original argument. E.g. if argument was splitted into four 32 bit
 
    /// registers, we got 4 InputArgs with PartOffsets 0, 4, 8 and 12.
 
    unsigned PartOffset;
 
 
 
    InputArg() = default;
 
    InputArg(ArgFlagsTy flags, EVT vt, EVT argvt, bool used,
 
             unsigned origIdx, unsigned partOffs)
 
      : Flags(flags), Used(used), OrigArgIndex(origIdx), PartOffset(partOffs) {
 
      VT = vt.getSimpleVT();
 
      ArgVT = argvt;
 
    }
 
 
 
    bool isOrigArg() const {
 
      return OrigArgIndex != NoArgIndex;
 
    }
 
 
 
    unsigned getOrigArgIndex() const {
 
      assert(OrigArgIndex != NoArgIndex && "Implicit machine-level argument");
 
      return OrigArgIndex;
 
    }
 
  };
 
 
 
  /// OutputArg - This struct carries flags and a value for a
 
  /// single outgoing (actual) argument or outgoing (from the perspective
 
  /// of the caller) return value virtual register.
 
  ///
 
  struct OutputArg {
 
    ArgFlagsTy Flags;
 
    MVT VT;
 
    EVT ArgVT;
 
 
 
    /// IsFixed - Is this a "fixed" value, ie not passed through a vararg "...".
 
    bool IsFixed = false;
 
 
 
    /// Index original Function's argument.
 
    unsigned OrigArgIndex;
 
 
 
    /// Offset in bytes of current output value relative to the beginning of
 
    /// original argument. E.g. if argument was splitted into four 32 bit
 
    /// registers, we got 4 OutputArgs with PartOffsets 0, 4, 8 and 12.
 
    unsigned PartOffset;
 
 
 
    OutputArg() = default;
 
    OutputArg(ArgFlagsTy flags, MVT vt, EVT argvt, bool isfixed,
 
              unsigned origIdx, unsigned partOffs)
 
        : Flags(flags), IsFixed(isfixed), OrigArgIndex(origIdx),
 
          PartOffset(partOffs) {
 
      VT = vt;
 
      ArgVT = argvt;
 
    }
 
  };
 
 
 
} // end namespace ISD
 
} // end namespace llvm
 
 
 
#endif // LLVM_CODEGEN_TARGETCALLINGCONV_H