// 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 OperandTraits {}; #define DECLARE_OPERAND_SIZE(Name, Size) \ template <> \ struct OperandTraits { \ static const OperandSize kSizeType = Size; \ static const int kSize = static_cast(Size); \ }; OPERAND_TYPE_LIST(DECLARE_OPERAND_SIZE) #undef DECLARE_OPERAND_SIZE 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]; } static inline OperandSize GetOperandSize(int i) { DCHECK(0 <= i && i < kOperandCount); const OperandSize kOperandSizes[] = {OperandTraits::kSizeType, OperandTraits::kSizeType, OperandTraits::kSizeType, OperandTraits::kSizeType}; return kOperandSizes[i]; } static inline int GetOperandOffset(int i) { DCHECK(0 <= i && i < kOperandCount); const int kOffset0 = 1; const int kOffset1 = kOffset0 + OperandTraits::kSize; const int kOffset2 = kOffset1 + OperandTraits::kSize; const int kOffset3 = kOffset2 + OperandTraits::kSize; const int kOperandOffsets[] = {kOffset0, kOffset1, kOffset2, kOffset3}; return kOperandOffsets[i]; } static const int kOperandCount = 4; static const int kSize = 1 + OperandTraits::kSize + OperandTraits::kSize + OperandTraits::kSize + OperandTraits::kSize; }; 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]; } static inline OperandSize GetOperandSize(int i) { DCHECK(0 <= i && i < kOperandCount); const OperandSize kOperandSizes[] = {OperandTraits::kSizeType, OperandTraits::kSizeType, OperandTraits::kSizeType}; return kOperandSizes[i]; } static inline int GetOperandOffset(int i) { DCHECK(0 <= i && i < kOperandCount); const int kOffset0 = 1; const int kOffset1 = kOffset0 + OperandTraits::kSize; const int kOffset2 = kOffset1 + OperandTraits::kSize; const int kOperandOffsets[] = {kOffset0, kOffset1, kOffset2}; return kOperandOffsets[i]; } static const int kOperandCount = 3; static const int kSize = 1 + OperandTraits::kSize + OperandTraits::kSize + OperandTraits::kSize; }; template struct BytecodeTraits { static inline OperandType GetOperandType(int i) { DCHECK(0 <= i && i < kOperandCount); const OperandType kOperands[] = {operand_0, operand_1}; return kOperands[i]; } static inline OperandSize GetOperandSize(int i) { DCHECK(0 <= i && i < kOperandCount); const OperandSize kOperandSizes[] = {OperandTraits::kSizeType, OperandTraits::kSizeType}; return kOperandSizes[i]; } static inline int GetOperandOffset(int i) { DCHECK(0 <= i && i < kOperandCount); const int kOffset0 = 1; const int kOffset1 = kOffset0 + OperandTraits::kSize; const int kOperandOffsets[] = {kOffset0, kOffset1}; return kOperandOffsets[i]; } static const int kOperandCount = 2; static const int kSize = 1 + OperandTraits::kSize + OperandTraits::kSize; }; template struct BytecodeTraits { static inline OperandType GetOperandType(int i) { DCHECK(i == 0); return operand_0; } static inline OperandSize GetOperandSize(int i) { DCHECK(i == 0); return OperandTraits::kSizeType; } static inline int GetOperandOffset(int i) { DCHECK(i == 0); return 1; } static const int kOperandCount = 1; static const int kSize = 1 + OperandTraits::kSize; }; template <> struct BytecodeTraits { static inline OperandType GetOperandType(int i) { UNREACHABLE(); return OperandType::kNone; } static inline OperandSize GetOperandSize(int i) { UNREACHABLE(); return OperandSize::kNone; } static inline int GetOperandOffset(int i) { UNREACHABLE(); return 1; } static const int kOperandCount = 0; static const int kSize = 1 + OperandTraits::kSize; }; } // namespace interpreter } // namespace internal } // namespace v8 #endif // V8_INTERPRETER_BYTECODE_TRAITS_H_