aboutsummaryrefslogtreecommitdiff
path: root/include/llvm/CodeGen/TargetCallingConv.h
blob: aebeeecbe506548876caaa2bbd4f2f92cff1aaf6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
//===-- 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/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 IsNest : 1;     ///< Nested fn static chain
    unsigned IsReturned : 1; ///< Always returned
    unsigned IsSplit : 1;
    unsigned IsInAlloca : 1;   ///< Passed with inalloca
    unsigned IsSplitEnd : 1;   ///< Last part of a split
    unsigned IsSwiftSelf : 1;  ///< Swift self parameter
    unsigned IsSwiftError : 1; ///< Swift error parameter
    unsigned IsHva : 1;        ///< HVA field for
    unsigned IsHvaStart : 1;   ///< HVA structure start
    unsigned IsSecArgPass : 1; ///< Second argument
    unsigned ByValAlign : 4;   ///< Log 2 of byval alignment
    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 ByValSize; ///< Byval struct size

    unsigned PointerAddrSpace; ///< Address space of pointer argument

  public:
    ArgFlagsTy()
        : IsZExt(0), IsSExt(0), IsInReg(0), IsSRet(0), IsByVal(0), IsNest(0),
          IsReturned(0), IsSplit(0), IsInAlloca(0), IsSplitEnd(0),
          IsSwiftSelf(0), IsSwiftError(0), IsHva(0), IsHvaStart(0),
          IsSecArgPass(0), ByValAlign(0), OrigAlign(0),
          IsInConsecutiveRegsLast(0), IsInConsecutiveRegs(0),
          IsCopyElisionCandidate(0), IsPointer(0), ByValSize(0),
          PointerAddrSpace(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 isInAlloca() const { return IsInAlloca; }
    void setInAlloca() { IsInAlloca = 1; }

    bool isSwiftSelf() const { return IsSwiftSelf; }
    void setSwiftSelf() { IsSwiftSelf = 1; }

    bool isSwiftError() const { return IsSwiftError; }
    void setSwiftError() { IsSwiftError = 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() { IsReturned = 1; }

    bool isInConsecutiveRegs()  const { return IsInConsecutiveRegs; }
    void setInConsecutiveRegs() { IsInConsecutiveRegs = 1; }

    bool isInConsecutiveRegsLast() const { return IsInConsecutiveRegsLast; }
    void setInConsecutiveRegsLast() { IsInConsecutiveRegsLast = 1; }

    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; }

    unsigned getByValAlign() const { return (1U << ByValAlign) / 2; }
    void setByValAlign(unsigned A) {
      ByValAlign = Log2_32(A) + 1;
      assert(getByValAlign() == A && "bitfield overflow");
    }

    unsigned getOrigAlign() const { return (1U << OrigAlign) / 2; }
    void setOrigAlign(unsigned A) {
      OrigAlign = Log2_32(A) + 1;
      assert(getOrigAlign() == A && "bitfield overflow");
    }

    unsigned getByValSize() const { return ByValSize; }
    void setByValSize(unsigned S) { ByValSize = 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, EVT vt, EVT argvt, bool isfixed,
              unsigned origIdx, unsigned partOffs)
      : Flags(flags), IsFixed(isfixed), OrigArgIndex(origIdx),
        PartOffset(partOffs) {
      VT = vt.getSimpleVT();
      ArgVT = argvt;
    }
  };

} // end namespace ISD
} // end namespace llvm

#endif // LLVM_CODEGEN_TARGETCALLINGCONV_H