bytecode-traits.h 10 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_INTERPRETER_BYTECODE_TRAITS_H_
#define V8_INTERPRETER_BYTECODE_TRAITS_H_

#include "src/interpreter/bytecodes.h"

namespace v8 {
namespace internal {
namespace interpreter {

14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
template <OperandTypeInfo>
struct OperandTypeInfoTraits {
  static const bool kIsScalable = false;
  static const bool kIsUnsigned = false;
  static const OperandSize kUnscaledSize = OperandSize::kNone;
};

#define DECLARE_OPERAND_TYPE_INFO(Name, Scalable, Unsigned, BaseSize) \
  template <>                                                         \
  struct OperandTypeInfoTraits<OperandTypeInfo::k##Name> {            \
    static const bool kIsScalable = Scalable;                         \
    static const bool kIsUnsigned = Unsigned;                         \
    static const OperandSize kUnscaledSize = BaseSize;                \
  };
OPERAND_TYPE_INFO_LIST(DECLARE_OPERAND_TYPE_INFO)
#undef DECLARE_OPERAND_TYPE_INFO

31
template <OperandType>
32
struct OperandTraits {
33 34
  typedef OperandTypeInfoTraits<OperandTypeInfo::kNone> TypeInfoTraits;
  static const OperandTypeInfo kOperandTypeInfo = OperandTypeInfo::kNone;
35
};
36

37 38 39 40 41
#define DECLARE_OPERAND_TYPE_TRAITS(Name, InfoType)           \
  template <>                                                 \
  struct OperandTraits<OperandType::k##Name> {                \
    typedef OperandTypeInfoTraits<InfoType> TypeInfoTraits;   \
    static const OperandTypeInfo kOperandTypeInfo = InfoType; \
42
  };
43 44
OPERAND_TYPE_LIST(DECLARE_OPERAND_TYPE_TRAITS)
#undef DECLARE_OPERAND_TYPE_TRAITS
45

46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
template <OperandType operand_type, OperandScale operand_scale>
struct OperandScaler {
  template <bool, OperandSize, OperandScale>
  struct Helper {
    static const int kSize = 0;
  };
  template <OperandSize size, OperandScale scale>
  struct Helper<false, size, scale> {
    static const int kSize = static_cast<int>(size);
  };
  template <OperandSize size, OperandScale scale>
  struct Helper<true, size, scale> {
    static const int kSize = static_cast<int>(size) * static_cast<int>(scale);
  };

  static const int kSize =
62 63
      Helper<OperandTraits<operand_type>::TypeInfoTraits::kIsScalable,
             OperandTraits<operand_type>::TypeInfoTraits::kUnscaledSize,
64 65 66 67
             operand_scale>::kSize;
  static const OperandSize kOperandSize = static_cast<OperandSize>(kSize);
};

68 69 70 71 72 73 74 75 76 77 78 79
template <OperandType>
struct RegisterOperandTraits {
  static const int kIsRegisterOperand = 0;
};

#define DECLARE_REGISTER_OPERAND(Name, _)              \
  template <>                                          \
  struct RegisterOperandTraits<OperandType::k##Name> { \
    static const int kIsRegisterOperand = 1;           \
  };
REGISTER_OPERAND_TYPE_LIST(DECLARE_REGISTER_OPERAND)
#undef DECLARE_REGISTER_OPERAND
80

81
template <AccumulatorUse, OperandType...>
82 83
struct BytecodeTraits {};

84 85 86 87
template <AccumulatorUse accumulator_use, OperandType operand_0,
          OperandType operand_1, OperandType operand_2, OperandType operand_3>
struct BytecodeTraits<accumulator_use, operand_0, operand_1, operand_2,
                      operand_3> {
88 89 90 91 92 93
  static const OperandType* GetOperandTypes() {
    static const OperandType operand_types[] = {operand_0, operand_1, operand_2,
                                                operand_3, OperandType::kNone};
    return operand_types;
  }

94 95 96 97 98 99 100 101 102
  static const OperandTypeInfo* GetOperandTypeInfos() {
    static const OperandTypeInfo operand_type_infos[] = {
        OperandTraits<operand_0>::kOperandTypeInfo,
        OperandTraits<operand_1>::kOperandTypeInfo,
        OperandTraits<operand_2>::kOperandTypeInfo,
        OperandTraits<operand_3>::kOperandTypeInfo, OperandTypeInfo::kNone};
    return operand_type_infos;
  }

103 104 105 106 107 108
  template <OperandType ot>
  static inline bool HasAnyOperandsOfType() {
    return operand_0 == ot || operand_1 == ot || operand_2 == ot ||
           operand_3 == ot;
  }

109
  static inline bool IsScalable() {
110 111 112 113
    return (OperandTraits<operand_0>::TypeInfoTraits::kIsScalable |
            OperandTraits<operand_1>::TypeInfoTraits::kIsScalable |
            OperandTraits<operand_2>::TypeInfoTraits::kIsScalable |
            OperandTraits<operand_3>::TypeInfoTraits::kIsScalable);
114 115
  }

116
  static const AccumulatorUse kAccumulatorUse = accumulator_use;
117
  static const int kOperandCount = 4;
118 119 120 121 122
  static const int kRegisterOperandCount =
      RegisterOperandTraits<operand_0>::kIsRegisterOperand +
      RegisterOperandTraits<operand_1>::kIsRegisterOperand +
      RegisterOperandTraits<operand_2>::kIsRegisterOperand +
      RegisterOperandTraits<operand_3>::kIsRegisterOperand;
123 124
};

125 126 127
template <AccumulatorUse accumulator_use, OperandType operand_0,
          OperandType operand_1, OperandType operand_2>
struct BytecodeTraits<accumulator_use, operand_0, operand_1, operand_2> {
128 129 130 131 132 133
  static const OperandType* GetOperandTypes() {
    static const OperandType operand_types[] = {operand_0, operand_1, operand_2,
                                                OperandType::kNone};
    return operand_types;
  }

134 135 136 137 138 139 140 141
  static const OperandTypeInfo* GetOperandTypeInfos() {
    static const OperandTypeInfo operand_type_infos[] = {
        OperandTraits<operand_0>::kOperandTypeInfo,
        OperandTraits<operand_1>::kOperandTypeInfo,
        OperandTraits<operand_2>::kOperandTypeInfo, OperandTypeInfo::kNone};
    return operand_type_infos;
  }

142 143 144 145 146
  template <OperandType ot>
  static inline bool HasAnyOperandsOfType() {
    return operand_0 == ot || operand_1 == ot || operand_2 == ot;
  }

147
  static inline bool IsScalable() {
148 149 150
    return (OperandTraits<operand_0>::TypeInfoTraits::kIsScalable |
            OperandTraits<operand_1>::TypeInfoTraits::kIsScalable |
            OperandTraits<operand_2>::TypeInfoTraits::kIsScalable);
151 152
  }

153
  static const AccumulatorUse kAccumulatorUse = accumulator_use;
154
  static const int kOperandCount = 3;
155 156 157 158
  static const int kRegisterOperandCount =
      RegisterOperandTraits<operand_0>::kIsRegisterOperand +
      RegisterOperandTraits<operand_1>::kIsRegisterOperand +
      RegisterOperandTraits<operand_2>::kIsRegisterOperand;
159 160
};

161 162 163
template <AccumulatorUse accumulator_use, OperandType operand_0,
          OperandType operand_1>
struct BytecodeTraits<accumulator_use, operand_0, operand_1> {
164 165 166 167 168 169
  static const OperandType* GetOperandTypes() {
    static const OperandType operand_types[] = {operand_0, operand_1,
                                                OperandType::kNone};
    return operand_types;
  }

170 171 172 173 174 175 176
  static const OperandTypeInfo* GetOperandTypeInfos() {
    static const OperandTypeInfo operand_type_infos[] = {
        OperandTraits<operand_0>::kOperandTypeInfo,
        OperandTraits<operand_1>::kOperandTypeInfo, OperandTypeInfo::kNone};
    return operand_type_infos;
  }

177 178 179 180 181
  template <OperandType ot>
  static inline bool HasAnyOperandsOfType() {
    return operand_0 == ot || operand_1 == ot;
  }

182
  static inline bool IsScalable() {
183 184
    return (OperandTraits<operand_0>::TypeInfoTraits::kIsScalable |
            OperandTraits<operand_1>::TypeInfoTraits::kIsScalable);
185 186
  }

187
  static const AccumulatorUse kAccumulatorUse = accumulator_use;
188
  static const int kOperandCount = 2;
189 190 191
  static const int kRegisterOperandCount =
      RegisterOperandTraits<operand_0>::kIsRegisterOperand +
      RegisterOperandTraits<operand_1>::kIsRegisterOperand;
192 193
};

194 195
template <AccumulatorUse accumulator_use, OperandType operand_0>
struct BytecodeTraits<accumulator_use, operand_0> {
196 197 198 199 200
  static const OperandType* GetOperandTypes() {
    static const OperandType operand_types[] = {operand_0, OperandType::kNone};
    return operand_types;
  }

201 202 203 204 205 206
  static const OperandTypeInfo* GetOperandTypeInfos() {
    static const OperandTypeInfo operand_type_infos[] = {
        OperandTraits<operand_0>::kOperandTypeInfo, OperandTypeInfo::kNone};
    return operand_type_infos;
  }

207 208 209 210 211
  template <OperandType ot>
  static inline bool HasAnyOperandsOfType() {
    return operand_0 == ot;
  }

212
  static inline bool IsScalable() {
213
    return OperandTraits<operand_0>::TypeInfoTraits::kIsScalable;
214 215
  }

216
  static const AccumulatorUse kAccumulatorUse = accumulator_use;
217
  static const int kOperandCount = 1;
218 219
  static const int kRegisterOperandCount =
      RegisterOperandTraits<operand_0>::kIsRegisterOperand;
220 221
};

222 223
template <AccumulatorUse accumulator_use>
struct BytecodeTraits<accumulator_use> {
224 225 226 227 228
  static const OperandType* GetOperandTypes() {
    static const OperandType operand_types[] = {OperandType::kNone};
    return operand_types;
  }

229 230 231 232 233 234
  static const OperandTypeInfo* GetOperandTypeInfos() {
    static const OperandTypeInfo operand_type_infos[] = {
        OperandTypeInfo::kNone};
    return operand_type_infos;
  }

235 236 237 238 239
  template <OperandType ot>
  static inline bool HasAnyOperandsOfType() {
    return false;
  }

240 241
  static inline bool IsScalable() { return false; }

242
  static const AccumulatorUse kAccumulatorUse = accumulator_use;
243
  static const int kOperandCount = 0;
244
  static const int kRegisterOperandCount = 0;
245 246
};

247 248
static OperandSize ScaledOperandSize(OperandType operand_type,
                                     OperandScale operand_scale) {
249 250 251
  STATIC_ASSERT(static_cast<int>(OperandScale::kQuadruple) == 4 &&
                OperandScale::kLast == OperandScale::kQuadruple);
  int index = static_cast<int>(operand_scale) >> 1;
252
  switch (operand_type) {
253 254 255 256 257 258 259 260 261 262
#define CASE(Name, TypeInfo)                                    \
  case OperandType::k##Name: {                                  \
    static const OperandSize kOperandSizes[] = {                \
        OperandScaler<OperandType::k##Name,                     \
                      OperandScale::kSingle>::kOperandSize,     \
        OperandScaler<OperandType::k##Name,                     \
                      OperandScale::kDouble>::kOperandSize,     \
        OperandScaler<OperandType::k##Name,                     \
                      OperandScale::kQuadruple>::kOperandSize}; \
    return kOperandSizes[index];                                \
263 264 265 266 267 268 269 270
  }
    OPERAND_TYPE_LIST(CASE)
#undef CASE
  }
  UNREACHABLE();
  return OperandSize::kNone;
}

271 272 273 274 275
}  // namespace interpreter
}  // namespace internal
}  // namespace v8

#endif  // V8_INTERPRETER_BYTECODE_TRAITS_H_