summaryrefslogtreecommitdiff
path: root/include/llvm/Target/TargetCallingConv.h
blob: 9cc52a591b36c2a03341d81e21026682e8c1d7d1 (plain)
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
//===-- llvm/Target/TargetCallingConv.h - Calling Convention ----*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines types for working with calling-convention information.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_TARGET_TARGETCALLINGCONV_H
#define LLVM_TARGET_TARGETCALLINGCONV_H

#include "llvm/Support/DataTypes.h"
#include "llvm/Support/MathExtras.h"
#include <string>

namespace llvm {

namespace ISD {
  struct ArgFlagsTy {
  private:
    static const uint64_t NoFlagSet      = 0ULL;
    static const uint64_t ZExt           = 1ULL<<0;  ///< Zero extended
    static const uint64_t ZExtOffs       = 0;
    static const uint64_t SExt           = 1ULL<<1;  ///< Sign extended
    static const uint64_t SExtOffs       = 1;
    static const uint64_t InReg          = 1ULL<<2;  ///< Passed in register
    static const uint64_t InRegOffs      = 2;
    static const uint64_t SRet           = 1ULL<<3;  ///< Hidden struct-ret ptr
    static const uint64_t SRetOffs       = 3;
    static const uint64_t ByVal          = 1ULL<<4;  ///< Struct passed by value
    static const uint64_t ByValOffs      = 4;
    static const uint64_t Nest           = 1ULL<<5;  ///< Nested fn static chain
    static const uint64_t NestOffs       = 5;
    static const uint64_t Returned       = 1ULL<<6;  ///< Always returned
    static const uint64_t ReturnedOffs   = 6;
    static const uint64_t ByValAlign     = 0xFULL<<7; ///< Struct alignment
    static const uint64_t ByValAlignOffs = 7;
    static const uint64_t Split          = 1ULL<<11;
    static const uint64_t SplitOffs      = 11;
    static const uint64_t OrigAlign      = 0x1FULL<<27;
    static const uint64_t OrigAlignOffs  = 27;
    static const uint64_t ByValSize      = 0xffffffffULL<<32; ///< Struct size
    static const uint64_t ByValSizeOffs  = 32;

    static const uint64_t One            = 1ULL; ///< 1 of this type, for shifts

    uint64_t Flags;
  public:
    ArgFlagsTy() : Flags(0) { }

    bool isZExt()      const { return Flags & ZExt; }
    void setZExt()     { Flags |= One << ZExtOffs; }

    bool isSExt()      const { return Flags & SExt; }
    void setSExt()     { Flags |= One << SExtOffs; }

    bool isInReg()     const { return Flags & InReg; }
    void setInReg()    { Flags |= One << InRegOffs; }

    bool isSRet()      const { return Flags & SRet; }
    void setSRet()     { Flags |= One << SRetOffs; }

    bool isByVal()     const { return Flags & ByVal; }
    void setByVal()    { Flags |= One << ByValOffs; }

    bool isNest()      const { return Flags & Nest; }
    void setNest()     { Flags |= One << NestOffs; }

    bool isReturned()  const { return Flags & Returned; }
    void setReturned() { Flags |= One << ReturnedOffs; }

    unsigned getByValAlign() const {
      return (unsigned)
        ((One << ((Flags & ByValAlign) >> ByValAlignOffs)) / 2);
    }
    void setByValAlign(unsigned A) {
      Flags = (Flags & ~ByValAlign) |
        (uint64_t(Log2_32(A) + 1) << ByValAlignOffs);
    }

    bool isSplit()   const { return Flags & Split; }
    void setSplit()  { Flags |= One << SplitOffs; }

    unsigned getOrigAlign() const {
      return (unsigned)
        ((One << ((Flags & OrigAlign) >> OrigAlignOffs)) / 2);
    }
    void setOrigAlign(unsigned A) {
      Flags = (Flags & ~OrigAlign) |
        (uint64_t(Log2_32(A) + 1) << OrigAlignOffs);
    }

    unsigned getByValSize() const {
      return (unsigned)((Flags & ByValSize) >> ByValSizeOffs);
    }
    void setByValSize(unsigned S) {
      Flags = (Flags & ~ByValSize) | (uint64_t(S) << ByValSizeOffs);
    }

    /// getRawBits - Represent the flags as a bunch of bits.
    uint64_t getRawBits() const { return Flags; }
  };

  /// 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;
    EVT ArgVT;
    bool Used;

    /// Index original Function's argument.
    unsigned OrigArgIndex;

    /// 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() : VT(MVT::Other), Used(false) {}
    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;
    }
  };

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

    /// 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() : IsFixed(false) {}
    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 llvm namespace

#endif