// 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 { template 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 { \ 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 template struct OperandTraits { typedef OperandTypeInfoTraits TypeInfoTraits; static const OperandTypeInfo kOperandTypeInfo = OperandTypeInfo::kNone; }; #define DECLARE_OPERAND_TYPE_TRAITS(Name, InfoType) \ template <> \ struct OperandTraits { \ typedef OperandTypeInfoTraits TypeInfoTraits; \ static const OperandTypeInfo kOperandTypeInfo = InfoType; \ }; OPERAND_TYPE_LIST(DECLARE_OPERAND_TYPE_TRAITS) #undef DECLARE_OPERAND_TYPE_TRAITS template struct OperandScaler { template struct Helper { static const int kSize = 0; }; template struct Helper { static const int kSize = static_cast(size); }; template struct Helper { static const int kSize = static_cast(size) * static_cast(scale); }; static const int kSize = Helper::TypeInfoTraits::kIsScalable, OperandTraits::TypeInfoTraits::kUnscaledSize, operand_scale>::kSize; static const OperandSize kOperandSize = static_cast(kSize); }; template struct RegisterOperandTraits { static const int kIsRegisterOperand = 0; }; #define DECLARE_REGISTER_OPERAND(Name, _) \ template <> \ struct RegisterOperandTraits { \ static const int kIsRegisterOperand = 1; \ }; REGISTER_OPERAND_TYPE_LIST(DECLARE_REGISTER_OPERAND) #undef DECLARE_REGISTER_OPERAND template struct BytecodeTraits {}; template struct BytecodeTraits { static const OperandType* GetOperandTypes() { static const OperandType operand_types[] = {operand_0, operand_1, operand_2, operand_3, OperandType::kNone}; return operand_types; } static const OperandTypeInfo* GetOperandTypeInfos() { static const OperandTypeInfo operand_type_infos[] = { OperandTraits::kOperandTypeInfo, OperandTraits::kOperandTypeInfo, OperandTraits::kOperandTypeInfo, OperandTraits::kOperandTypeInfo, OperandTypeInfo::kNone}; return operand_type_infos; } static const OperandSize* GetOperandSizes(OperandScale operand_scale) { switch (operand_scale) { #define CASE(Name, _) \ case OperandScale::k##Name: { \ static const OperandSize kOperandSizes[] = { \ OperandScaler::kOperandSize, \ OperandScaler::kOperandSize, \ OperandScaler::kOperandSize, \ OperandScaler::kOperandSize, \ }; \ return kOperandSizes; \ } OPERAND_SCALE_LIST(CASE) #undef CASE } UNREACHABLE(); return nullptr; } template static inline bool HasAnyOperandsOfType() { return operand_0 == ot || operand_1 == ot || operand_2 == ot || operand_3 == ot; } static inline bool IsScalable() { return (OperandTraits::TypeInfoTraits::kIsScalable | OperandTraits::TypeInfoTraits::kIsScalable | OperandTraits::TypeInfoTraits::kIsScalable | OperandTraits::TypeInfoTraits::kIsScalable); } static const AccumulatorUse kAccumulatorUse = accumulator_use; static const int kOperandCount = 4; static const int kRegisterOperandCount = RegisterOperandTraits::kIsRegisterOperand + RegisterOperandTraits::kIsRegisterOperand + RegisterOperandTraits::kIsRegisterOperand + RegisterOperandTraits::kIsRegisterOperand; static const int kRegisterOperandBitmap = RegisterOperandTraits::kIsRegisterOperand + (RegisterOperandTraits::kIsRegisterOperand << 1) + (RegisterOperandTraits::kIsRegisterOperand << 2) + (RegisterOperandTraits::kIsRegisterOperand << 3); }; template struct BytecodeTraits { static const OperandType* GetOperandTypes() { static const OperandType operand_types[] = {operand_0, operand_1, operand_2, OperandType::kNone}; return operand_types; } static const OperandTypeInfo* GetOperandTypeInfos() { static const OperandTypeInfo operand_type_infos[] = { OperandTraits::kOperandTypeInfo, OperandTraits::kOperandTypeInfo, OperandTraits::kOperandTypeInfo, OperandTypeInfo::kNone}; return operand_type_infos; } static const OperandSize* GetOperandSizes(OperandScale operand_scale) { switch (operand_scale) { #define CASE(Name, _) \ case OperandScale::k##Name: { \ static const OperandSize kOperandSizes[] = { \ OperandScaler::kOperandSize, \ OperandScaler::kOperandSize, \ OperandScaler::kOperandSize, \ }; \ return kOperandSizes; \ } OPERAND_SCALE_LIST(CASE) #undef CASE } UNREACHABLE(); return nullptr; } template static inline bool HasAnyOperandsOfType() { return operand_0 == ot || operand_1 == ot || operand_2 == ot; } static inline bool IsScalable() { return (OperandTraits::TypeInfoTraits::kIsScalable | OperandTraits::TypeInfoTraits::kIsScalable | OperandTraits::TypeInfoTraits::kIsScalable); } static const AccumulatorUse kAccumulatorUse = accumulator_use; static const int kOperandCount = 3; static const int kRegisterOperandCount = RegisterOperandTraits::kIsRegisterOperand + RegisterOperandTraits::kIsRegisterOperand + RegisterOperandTraits::kIsRegisterOperand; static const int kRegisterOperandBitmap = RegisterOperandTraits::kIsRegisterOperand + (RegisterOperandTraits::kIsRegisterOperand << 1) + (RegisterOperandTraits::kIsRegisterOperand << 2); }; template struct BytecodeTraits { static const OperandType* GetOperandTypes() { static const OperandType operand_types[] = {operand_0, operand_1, OperandType::kNone}; return operand_types; } static const OperandTypeInfo* GetOperandTypeInfos() { static const OperandTypeInfo operand_type_infos[] = { OperandTraits::kOperandTypeInfo, OperandTraits::kOperandTypeInfo, OperandTypeInfo::kNone}; return operand_type_infos; } static const OperandSize* GetOperandSizes(OperandScale operand_scale) { switch (operand_scale) { #define CASE(Name, _) \ case OperandScale::k##Name: { \ static const OperandSize kOperandSizes[] = { \ OperandScaler::kOperandSize, \ OperandScaler::kOperandSize, \ }; \ return kOperandSizes; \ } OPERAND_SCALE_LIST(CASE) #undef CASE } UNREACHABLE(); return nullptr; } template static inline bool HasAnyOperandsOfType() { return operand_0 == ot || operand_1 == ot; } static inline bool IsScalable() { return (OperandTraits::TypeInfoTraits::kIsScalable | OperandTraits::TypeInfoTraits::kIsScalable); } static const AccumulatorUse kAccumulatorUse = accumulator_use; static const int kOperandCount = 2; static const int kRegisterOperandCount = RegisterOperandTraits::kIsRegisterOperand + RegisterOperandTraits::kIsRegisterOperand; static const int kRegisterOperandBitmap = RegisterOperandTraits::kIsRegisterOperand + (RegisterOperandTraits::kIsRegisterOperand << 1); }; template struct BytecodeTraits { static const OperandType* GetOperandTypes() { static const OperandType operand_types[] = {operand_0, OperandType::kNone}; return operand_types; } static const OperandTypeInfo* GetOperandTypeInfos() { static const OperandTypeInfo operand_type_infos[] = { OperandTraits::kOperandTypeInfo, OperandTypeInfo::kNone}; return operand_type_infos; } static const OperandSize* GetOperandSizes(OperandScale operand_scale) { switch (operand_scale) { #define CASE(Name, _) \ case OperandScale::k##Name: { \ static const OperandSize kOperandSizes[] = { \ OperandScaler::kOperandSize, \ }; \ return kOperandSizes; \ } OPERAND_SCALE_LIST(CASE) #undef CASE } UNREACHABLE(); return nullptr; } template static inline bool HasAnyOperandsOfType() { return operand_0 == ot; } static inline bool IsScalable() { return OperandTraits::TypeInfoTraits::kIsScalable; } static const AccumulatorUse kAccumulatorUse = accumulator_use; static const int kOperandCount = 1; static const int kRegisterOperandCount = RegisterOperandTraits::kIsRegisterOperand; static const int kRegisterOperandBitmap = RegisterOperandTraits::kIsRegisterOperand; }; template struct BytecodeTraits { static const OperandType* GetOperandTypes() { static const OperandType operand_types[] = {OperandType::kNone}; return operand_types; } static const OperandTypeInfo* GetOperandTypeInfos() { static const OperandTypeInfo operand_type_infos[] = { OperandTypeInfo::kNone}; return operand_type_infos; } static const OperandSize* GetOperandSizes(OperandScale operand_scale) { return nullptr; } template static inline bool HasAnyOperandsOfType() { return false; } static inline bool IsScalable() { return false; } static const AccumulatorUse kAccumulatorUse = accumulator_use; static const int kOperandCount = 0; static const int kRegisterOperandCount = 0; static const int kRegisterOperandBitmap = 0; }; static OperandSize ScaledOperandSize(OperandType operand_type, OperandScale operand_scale) { STATIC_ASSERT(static_cast(OperandScale::kQuadruple) == 4 && OperandScale::kLast == OperandScale::kQuadruple); int index = static_cast(operand_scale) >> 1; switch (operand_type) { #define CASE(Name, TypeInfo) \ case OperandType::k##Name: { \ static const OperandSize kOperandSizes[] = { \ OperandScaler::kOperandSize, \ OperandScaler::kOperandSize, \ OperandScaler::kOperandSize}; \ return kOperandSizes[index]; \ } OPERAND_TYPE_LIST(CASE) #undef CASE } UNREACHABLE(); return OperandSize::kNone; } } // namespace interpreter } // namespace internal } // namespace v8 #endif // V8_INTERPRETER_BYTECODE_TRAITS_H_