Home | History | Annotate | Line # | Download | only in CodeGen
      1 //===-- llvm/CodeGen/TargetCallingConv.h - Calling Convention ---*- C++ -*-===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 //
      9 // This file defines types for working with calling-convention information.
     10 //
     11 //===----------------------------------------------------------------------===//
     12 
     13 #ifndef LLVM_CODEGEN_TARGETCALLINGCONV_H
     14 #define LLVM_CODEGEN_TARGETCALLINGCONV_H
     15 
     16 #include "llvm/CodeGen/ValueTypes.h"
     17 #include "llvm/Support/Alignment.h"
     18 #include "llvm/Support/MachineValueType.h"
     19 #include "llvm/Support/MathExtras.h"
     20 #include <cassert>
     21 #include <climits>
     22 #include <cstdint>
     23 
     24 namespace llvm {
     25 namespace ISD {
     26 
     27   struct ArgFlagsTy {
     28   private:
     29     unsigned IsZExt : 1;     ///< Zero extended
     30     unsigned IsSExt : 1;     ///< Sign extended
     31     unsigned IsInReg : 1;    ///< Passed in register
     32     unsigned IsSRet : 1;     ///< Hidden struct-ret ptr
     33     unsigned IsByVal : 1;    ///< Struct passed by value
     34     unsigned IsByRef : 1;    ///< Passed in memory
     35     unsigned IsNest : 1;     ///< Nested fn static chain
     36     unsigned IsReturned : 1; ///< Always returned
     37     unsigned IsSplit : 1;
     38     unsigned IsInAlloca : 1;   ///< Passed with inalloca
     39     unsigned IsPreallocated : 1; ///< ByVal without the copy
     40     unsigned IsSplitEnd : 1;   ///< Last part of a split
     41     unsigned IsSwiftSelf : 1;  ///< Swift self parameter
     42     unsigned IsSwiftAsync : 1;  ///< Swift async context parameter
     43     unsigned IsSwiftError : 1; ///< Swift error parameter
     44     unsigned IsCFGuardTarget : 1; ///< Control Flow Guard target
     45     unsigned IsHva : 1;        ///< HVA field for
     46     unsigned IsHvaStart : 1;   ///< HVA structure start
     47     unsigned IsSecArgPass : 1; ///< Second argument
     48     unsigned MemAlign : 4;     ///< Log 2 of alignment when arg is passed in memory
     49                                ///< (including byval/byref)
     50     unsigned OrigAlign : 5;    ///< Log 2 of original alignment
     51     unsigned IsInConsecutiveRegsLast : 1;
     52     unsigned IsInConsecutiveRegs : 1;
     53     unsigned IsCopyElisionCandidate : 1; ///< Argument copy elision candidate
     54     unsigned IsPointer : 1;
     55 
     56     unsigned ByValOrByRefSize; ///< Byval or byref struct size
     57 
     58     unsigned PointerAddrSpace; ///< Address space of pointer argument
     59 
     60   public:
     61     ArgFlagsTy()
     62         : IsZExt(0), IsSExt(0), IsInReg(0), IsSRet(0), IsByVal(0), IsByRef(0),
     63           IsNest(0), IsReturned(0), IsSplit(0), IsInAlloca(0),
     64           IsPreallocated(0), IsSplitEnd(0), IsSwiftSelf(0), IsSwiftAsync(0),
     65           IsSwiftError(0), IsCFGuardTarget(0), IsHva(0), IsHvaStart(0),
     66           IsSecArgPass(0), MemAlign(0), OrigAlign(0),
     67           IsInConsecutiveRegsLast(0), IsInConsecutiveRegs(0),
     68           IsCopyElisionCandidate(0), IsPointer(0), ByValOrByRefSize(0),
     69           PointerAddrSpace(0) {
     70       static_assert(sizeof(*this) == 3 * sizeof(unsigned), "flags are too big");
     71     }
     72 
     73     bool isZExt() const { return IsZExt; }
     74     void setZExt() { IsZExt = 1; }
     75 
     76     bool isSExt() const { return IsSExt; }
     77     void setSExt() { IsSExt = 1; }
     78 
     79     bool isInReg() const { return IsInReg; }
     80     void setInReg() { IsInReg = 1; }
     81 
     82     bool isSRet() const { return IsSRet; }
     83     void setSRet() { IsSRet = 1; }
     84 
     85     bool isByVal() const { return IsByVal; }
     86     void setByVal() { IsByVal = 1; }
     87 
     88     bool isByRef() const { return IsByRef; }
     89     void setByRef() { IsByRef = 1; }
     90 
     91     bool isInAlloca() const { return IsInAlloca; }
     92     void setInAlloca() { IsInAlloca = 1; }
     93 
     94     bool isPreallocated() const { return IsPreallocated; }
     95     void setPreallocated() { IsPreallocated = 1; }
     96 
     97     bool isSwiftSelf() const { return IsSwiftSelf; }
     98     void setSwiftSelf() { IsSwiftSelf = 1; }
     99 
    100     bool isSwiftAsync() const { return IsSwiftAsync; }
    101     void setSwiftAsync() { IsSwiftAsync = 1; }
    102 
    103     bool isSwiftError() const { return IsSwiftError; }
    104     void setSwiftError() { IsSwiftError = 1; }
    105 
    106     bool isCFGuardTarget() const { return IsCFGuardTarget; }
    107     void setCFGuardTarget() { IsCFGuardTarget = 1; }
    108 
    109     bool isHva() const { return IsHva; }
    110     void setHva() { IsHva = 1; }
    111 
    112     bool isHvaStart() const { return IsHvaStart; }
    113     void setHvaStart() { IsHvaStart = 1; }
    114 
    115     bool isSecArgPass() const { return IsSecArgPass; }
    116     void setSecArgPass() { IsSecArgPass = 1; }
    117 
    118     bool isNest() const { return IsNest; }
    119     void setNest() { IsNest = 1; }
    120 
    121     bool isReturned() const { return IsReturned; }
    122     void setReturned(bool V = true) { IsReturned = V; }
    123 
    124     bool isInConsecutiveRegs()  const { return IsInConsecutiveRegs; }
    125     void setInConsecutiveRegs(bool Flag = true) { IsInConsecutiveRegs = Flag; }
    126 
    127     bool isInConsecutiveRegsLast() const { return IsInConsecutiveRegsLast; }
    128     void setInConsecutiveRegsLast(bool Flag = true) {
    129       IsInConsecutiveRegsLast = Flag;
    130     }
    131 
    132     bool isSplit()   const { return IsSplit; }
    133     void setSplit()  { IsSplit = 1; }
    134 
    135     bool isSplitEnd()   const { return IsSplitEnd; }
    136     void setSplitEnd()  { IsSplitEnd = 1; }
    137 
    138     bool isCopyElisionCandidate()  const { return IsCopyElisionCandidate; }
    139     void setCopyElisionCandidate() { IsCopyElisionCandidate = 1; }
    140 
    141     bool isPointer()  const { return IsPointer; }
    142     void setPointer() { IsPointer = 1; }
    143 
    144     Align getNonZeroMemAlign() const {
    145       return decodeMaybeAlign(MemAlign).valueOrOne();
    146     }
    147 
    148     void setMemAlign(Align A) {
    149       MemAlign = encode(A);
    150       assert(getNonZeroMemAlign() == A && "bitfield overflow");
    151     }
    152 
    153     Align getNonZeroByValAlign() const {
    154       assert(isByVal());
    155       MaybeAlign A = decodeMaybeAlign(MemAlign);
    156       assert(A && "ByValAlign must be defined");
    157       return *A;
    158     }
    159 
    160     Align getNonZeroOrigAlign() const {
    161       return decodeMaybeAlign(OrigAlign).valueOrOne();
    162     }
    163 
    164     void setOrigAlign(Align A) {
    165       OrigAlign = encode(A);
    166       assert(getNonZeroOrigAlign() == A && "bitfield overflow");
    167     }
    168 
    169     unsigned getByValSize() const {
    170       assert(isByVal() && !isByRef());
    171       return ByValOrByRefSize;
    172     }
    173     void setByValSize(unsigned S) {
    174       assert(isByVal() && !isByRef());
    175       ByValOrByRefSize = S;
    176     }
    177 
    178     unsigned getByRefSize() const {
    179       assert(!isByVal() && isByRef());
    180       return ByValOrByRefSize;
    181     }
    182     void setByRefSize(unsigned S) {
    183       assert(!isByVal() && isByRef());
    184       ByValOrByRefSize = S;
    185     }
    186 
    187     unsigned getPointerAddrSpace() const { return PointerAddrSpace; }
    188     void setPointerAddrSpace(unsigned AS) { PointerAddrSpace = AS; }
    189 };
    190 
    191   /// InputArg - This struct carries flags and type information about a
    192   /// single incoming (formal) argument or incoming (from the perspective
    193   /// of the caller) return value virtual register.
    194   ///
    195   struct InputArg {
    196     ArgFlagsTy Flags;
    197     MVT VT = MVT::Other;
    198     EVT ArgVT;
    199     bool Used = false;
    200 
    201     /// Index original Function's argument.
    202     unsigned OrigArgIndex;
    203     /// Sentinel value for implicit machine-level input arguments.
    204     static const unsigned NoArgIndex = UINT_MAX;
    205 
    206     /// Offset in bytes of current input value relative to the beginning of
    207     /// original argument. E.g. if argument was splitted into four 32 bit
    208     /// registers, we got 4 InputArgs with PartOffsets 0, 4, 8 and 12.
    209     unsigned PartOffset;
    210 
    211     InputArg() = default;
    212     InputArg(ArgFlagsTy flags, EVT vt, EVT argvt, bool used,
    213              unsigned origIdx, unsigned partOffs)
    214       : Flags(flags), Used(used), OrigArgIndex(origIdx), PartOffset(partOffs) {
    215       VT = vt.getSimpleVT();
    216       ArgVT = argvt;
    217     }
    218 
    219     bool isOrigArg() const {
    220       return OrigArgIndex != NoArgIndex;
    221     }
    222 
    223     unsigned getOrigArgIndex() const {
    224       assert(OrigArgIndex != NoArgIndex && "Implicit machine-level argument");
    225       return OrigArgIndex;
    226     }
    227   };
    228 
    229   /// OutputArg - This struct carries flags and a value for a
    230   /// single outgoing (actual) argument or outgoing (from the perspective
    231   /// of the caller) return value virtual register.
    232   ///
    233   struct OutputArg {
    234     ArgFlagsTy Flags;
    235     MVT VT;
    236     EVT ArgVT;
    237 
    238     /// IsFixed - Is this a "fixed" value, ie not passed through a vararg "...".
    239     bool IsFixed = false;
    240 
    241     /// Index original Function's argument.
    242     unsigned OrigArgIndex;
    243 
    244     /// Offset in bytes of current output value relative to the beginning of
    245     /// original argument. E.g. if argument was splitted into four 32 bit
    246     /// registers, we got 4 OutputArgs with PartOffsets 0, 4, 8 and 12.
    247     unsigned PartOffset;
    248 
    249     OutputArg() = default;
    250     OutputArg(ArgFlagsTy flags, EVT vt, EVT argvt, bool isfixed,
    251               unsigned origIdx, unsigned partOffs)
    252       : Flags(flags), IsFixed(isfixed), OrigArgIndex(origIdx),
    253         PartOffset(partOffs) {
    254       VT = vt.getSimpleVT();
    255       ArgVT = argvt;
    256     }
    257   };
    258 
    259 } // end namespace ISD
    260 } // end namespace llvm
    261 
    262 #endif // LLVM_CODEGEN_TARGETCALLINGCONV_H
    263