// 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 { // TODO(rmcilroy): consider simplifying this to avoid the template magic. // Template helpers to deduce the number of operands each bytecode has. #define OPERAND_TERM OperandType::kNone, OperandType::kNone, OperandType::kNone 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 TypeInfo; }; #define DECLARE_OPERAND_TYPE_TRAITS(Name, InfoType) \ template <> \ struct OperandTraits { \ typedef OperandTypeInfoTraits TypeInfo; \ }; OPERAND_TYPE_LIST(DECLARE_OPERAND_TYPE_TRAITS) #undef DECLARE_OPERAND_TYPE_TRAITS 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 OperandType GetOperandType(int i) { DCHECK(0 <= i && i < kOperandCount); const OperandType kOperands[] = {operand_0, operand_1, operand_2, operand_3}; return kOperands[i]; } template static inline bool HasAnyOperandsOfType() { return operand_0 == ot || operand_1 == ot || operand_2 == ot || operand_3 == ot; } static inline bool IsScalable() { return (OperandTraits::TypeInfo::kIsScalable | OperandTraits::TypeInfo::kIsScalable | OperandTraits::TypeInfo::kIsScalable | OperandTraits::TypeInfo::kIsScalable); } 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 inline OperandType GetOperandType(int i) { DCHECK(0 <= i && i <= 2); const OperandType kOperands[] = {operand_0, operand_1, operand_2}; return kOperands[i]; } template static inline bool HasAnyOperandsOfType() { return operand_0 == ot || operand_1 == ot || operand_2 == ot; } static inline bool IsScalable() { return (OperandTraits::TypeInfo::kIsScalable | OperandTraits::TypeInfo::kIsScalable | OperandTraits::TypeInfo::kIsScalable); } 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 inline OperandType GetOperandType(int i) { DCHECK(0 <= i && i < kOperandCount); const OperandType kOperands[] = {operand_0, operand_1}; return kOperands[i]; } template static inline bool HasAnyOperandsOfType() { return operand_0 == ot || operand_1 == ot; } static inline bool IsScalable() { return (OperandTraits::TypeInfo::kIsScalable | OperandTraits::TypeInfo::kIsScalable); } 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 inline OperandType GetOperandType(int i) { DCHECK(i == 0); return operand_0; } template static inline bool HasAnyOperandsOfType() { return operand_0 == ot; } static inline bool IsScalable() { return OperandTraits::TypeInfo::kIsScalable; } static const int kOperandCount = 1; static const int kRegisterOperandCount = RegisterOperandTraits::kIsRegisterOperand; static const int kRegisterOperandBitmap = RegisterOperandTraits::kIsRegisterOperand; }; template <> struct BytecodeTraits { static inline OperandType GetOperandType(int i) { UNREACHABLE(); return OperandType::kNone; } template static inline bool HasAnyOperandsOfType() { return false; } static inline bool IsScalable() { return false; } static const int kOperandCount = 0; static const int kRegisterOperandCount = 0; static const int kRegisterOperandBitmap = 0; }; template struct OperandScaler { static int Multiply(int size, int operand_scale) { return 0; } }; template <> struct OperandScaler { static int Multiply(int size, int operand_scale) { return size; } }; template <> struct OperandScaler { static int Multiply(int size, int operand_scale) { return size * operand_scale; } }; static OperandSize ScaledOperandSize(OperandType operand_type, OperandScale operand_scale) { switch (operand_type) { #define CASE(Name, TypeInfo) \ case OperandType::k##Name: { \ OperandSize base_size = OperandTypeInfoTraits::kUnscaledSize; \ int size = \ OperandScaler::kIsScalable>::Multiply( \ static_cast(base_size), static_cast(operand_scale)); \ OperandSize operand_size = static_cast(size); \ DCHECK(operand_size == OperandSize::kByte || \ operand_size == OperandSize::kShort || \ operand_size == OperandSize::kQuad); \ return operand_size; \ } OPERAND_TYPE_LIST(CASE) #undef CASE } UNREACHABLE(); return OperandSize::kNone; } } // namespace interpreter } // namespace internal } // namespace v8 #endif // V8_INTERPRETER_BYTECODE_TRAITS_H_