// 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/bytecode-operands.h" namespace v8 { namespace internal { namespace interpreter { 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 template <OperandType> struct OperandTraits { using TypeInfoTraits = OperandTypeInfoTraits<OperandTypeInfo::kNone>; static const OperandTypeInfo kOperandTypeInfo = OperandTypeInfo::kNone; }; #define DECLARE_OPERAND_TYPE_TRAITS(Name, InfoType) \ template <> \ struct OperandTraits<OperandType::k##Name> { \ using TypeInfoTraits = OperandTypeInfoTraits<InfoType>; \ static const OperandTypeInfo kOperandTypeInfo = InfoType; \ }; OPERAND_TYPE_LIST(DECLARE_OPERAND_TYPE_TRAITS) #undef DECLARE_OPERAND_TYPE_TRAITS 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 = Helper<OperandTraits<operand_type>::TypeInfoTraits::kIsScalable, OperandTraits<operand_type>::TypeInfoTraits::kUnscaledSize, operand_scale>::kSize; static const OperandSize kOperandSize = static_cast<OperandSize>(kSize); }; template <int... values> struct SumHelper; template <int value> struct SumHelper<value> { static const int kValue = value; }; template <int value, int... values> struct SumHelper<value, values...> { static const int kValue = value + SumHelper<values...>::kValue; }; template <AccumulatorUse accumulator_use, OperandType... operands> struct BytecodeTraits { static const OperandType kOperandTypes[]; static const OperandTypeInfo kOperandTypeInfos[]; static const OperandSize kSingleScaleOperandSizes[]; static const OperandSize kDoubleScaleOperandSizes[]; static const OperandSize kQuadrupleScaleOperandSizes[]; static const int kSingleScaleSize = SumHelper< 1, OperandScaler<operands, OperandScale::kSingle>::kSize...>::kValue; static const int kDoubleScaleSize = SumHelper< 1, OperandScaler<operands, OperandScale::kDouble>::kSize...>::kValue; static const int kQuadrupleScaleSize = SumHelper< 1, OperandScaler<operands, OperandScale::kQuadruple>::kSize...>::kValue; static const AccumulatorUse kAccumulatorUse = accumulator_use; static const int kOperandCount = sizeof...(operands); }; template <AccumulatorUse accumulator_use, OperandType... operands> STATIC_CONST_MEMBER_DEFINITION const OperandType BytecodeTraits<accumulator_use, operands...>::kOperandTypes[] = { operands...}; template <AccumulatorUse accumulator_use, OperandType... operands> STATIC_CONST_MEMBER_DEFINITION const OperandTypeInfo BytecodeTraits<accumulator_use, operands...>::kOperandTypeInfos[] = { OperandTraits<operands>::kOperandTypeInfo...}; template <AccumulatorUse accumulator_use, OperandType... operands> STATIC_CONST_MEMBER_DEFINITION const OperandSize BytecodeTraits<accumulator_use, operands...>::kSingleScaleOperandSizes[] = { OperandScaler<operands, OperandScale::kSingle>::kOperandSize...}; template <AccumulatorUse accumulator_use, OperandType... operands> STATIC_CONST_MEMBER_DEFINITION const OperandSize BytecodeTraits<accumulator_use, operands...>::kDoubleScaleOperandSizes[] = { OperandScaler<operands, OperandScale::kDouble>::kOperandSize...}; template <AccumulatorUse accumulator_use, OperandType... operands> STATIC_CONST_MEMBER_DEFINITION const OperandSize BytecodeTraits< accumulator_use, operands...>::kQuadrupleScaleOperandSizes[] = { OperandScaler<operands, OperandScale::kQuadruple>::kOperandSize...}; template <AccumulatorUse accumulator_use> struct BytecodeTraits<accumulator_use> { static const OperandType kOperandTypes[]; static const OperandTypeInfo kOperandTypeInfos[]; static const OperandSize kSingleScaleOperandSizes[]; static const OperandSize kDoubleScaleOperandSizes[]; static const OperandSize kQuadrupleScaleOperandSizes[]; static const int kSingleScaleSize = 1; static const int kDoubleScaleSize = 1; static const int kQuadrupleScaleSize = 1; static const AccumulatorUse kAccumulatorUse = accumulator_use; static const int kOperandCount = 0; }; template <AccumulatorUse accumulator_use> STATIC_CONST_MEMBER_DEFINITION const OperandType BytecodeTraits<accumulator_use>::kOperandTypes[] = {OperandType::kNone}; template <AccumulatorUse accumulator_use> STATIC_CONST_MEMBER_DEFINITION const OperandTypeInfo BytecodeTraits<accumulator_use>::kOperandTypeInfos[] = { OperandTypeInfo::kNone}; template <AccumulatorUse accumulator_use> STATIC_CONST_MEMBER_DEFINITION const OperandSize BytecodeTraits<accumulator_use>::kSingleScaleOperandSizes[] = { OperandSize::kNone}; template <AccumulatorUse accumulator_use> STATIC_CONST_MEMBER_DEFINITION const OperandSize BytecodeTraits<accumulator_use>::kDoubleScaleOperandSizes[] = { OperandSize::kNone}; template <AccumulatorUse accumulator_use> STATIC_CONST_MEMBER_DEFINITION const OperandSize BytecodeTraits<accumulator_use>::kQuadrupleScaleOperandSizes[] = { OperandSize::kNone}; } // namespace interpreter } // namespace internal } // namespace v8 #endif // V8_INTERPRETER_BYTECODE_TRAITS_H_