• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_INTERPRETER_BYTECODE_OPERANDS_H_
6 #define V8_INTERPRETER_BYTECODE_OPERANDS_H_
7 
8 #include "src/globals.h"
9 
10 namespace v8 {
11 namespace internal {
12 namespace interpreter {
13 
14 #define INVALID_OPERAND_TYPE_LIST(V) V(None, OperandTypeInfo::kNone)
15 
16 #define REGISTER_INPUT_OPERAND_TYPE_LIST(V)        \
17   V(Reg, OperandTypeInfo::kScalableSignedByte)     \
18   V(RegList, OperandTypeInfo::kScalableSignedByte) \
19   V(RegPair, OperandTypeInfo::kScalableSignedByte)
20 
21 #define REGISTER_OUTPUT_OPERAND_TYPE_LIST(V)          \
22   V(RegOut, OperandTypeInfo::kScalableSignedByte)     \
23   V(RegOutList, OperandTypeInfo::kScalableSignedByte) \
24   V(RegOutPair, OperandTypeInfo::kScalableSignedByte) \
25   V(RegOutTriple, OperandTypeInfo::kScalableSignedByte)
26 
27 #define SIGNED_SCALABLE_SCALAR_OPERAND_TYPE_LIST(V) \
28   V(Imm, OperandTypeInfo::kScalableSignedByte)
29 
30 #define UNSIGNED_SCALABLE_SCALAR_OPERAND_TYPE_LIST(V) \
31   V(Idx, OperandTypeInfo::kScalableUnsignedByte)      \
32   V(UImm, OperandTypeInfo::kScalableUnsignedByte)     \
33   V(RegCount, OperandTypeInfo::kScalableUnsignedByte)
34 
35 #define UNSIGNED_FIXED_SCALAR_OPERAND_TYPE_LIST(V)    \
36   V(Flag8, OperandTypeInfo::kFixedUnsignedByte)       \
37   V(IntrinsicId, OperandTypeInfo::kFixedUnsignedByte) \
38   V(RuntimeId, OperandTypeInfo::kFixedUnsignedShort)  \
39   V(NativeContextIndex, OperandTypeInfo::kScalableUnsignedByte)
40 
41 // Carefully ordered for operand type range checks below.
42 #define NON_REGISTER_OPERAND_TYPE_LIST(V)       \
43   INVALID_OPERAND_TYPE_LIST(V)                  \
44   UNSIGNED_FIXED_SCALAR_OPERAND_TYPE_LIST(V)    \
45   UNSIGNED_SCALABLE_SCALAR_OPERAND_TYPE_LIST(V) \
46   SIGNED_SCALABLE_SCALAR_OPERAND_TYPE_LIST(V)
47 
48 // Carefully ordered for operand type range checks below.
49 #define REGISTER_OPERAND_TYPE_LIST(V) \
50   REGISTER_INPUT_OPERAND_TYPE_LIST(V) \
51   REGISTER_OUTPUT_OPERAND_TYPE_LIST(V)
52 
53 // The list of operand types used by bytecodes.
54 // Carefully ordered for operand type range checks below.
55 #define OPERAND_TYPE_LIST(V)        \
56   NON_REGISTER_OPERAND_TYPE_LIST(V) \
57   REGISTER_OPERAND_TYPE_LIST(V)
58 
59 // Enumeration of scaling factors applicable to scalable operands. Code
60 // relies on being able to cast values to integer scaling values.
61 #define OPERAND_SCALE_LIST(V) \
62   V(Single, 1)                \
63   V(Double, 2)                \
64   V(Quadruple, 4)
65 
66 enum class OperandScale : uint8_t {
67 #define DECLARE_OPERAND_SCALE(Name, Scale) k##Name = Scale,
68   OPERAND_SCALE_LIST(DECLARE_OPERAND_SCALE)
69 #undef DECLARE_OPERAND_SCALE
70       kLast = kQuadruple
71 };
72 
73 // Enumeration of the size classes of operand types used by
74 // bytecodes. Code relies on being able to cast values to integer
75 // types to get the size in bytes.
76 enum class OperandSize : uint8_t {
77   kNone = 0,
78   kByte = 1,
79   kShort = 2,
80   kQuad = 4,
81   kLast = kQuad
82 };
83 
84 // Primitive operand info used that summarize properties of operands.
85 // Columns are Name, IsScalable, IsUnsigned, UnscaledSize.
86 #define OPERAND_TYPE_INFO_LIST(V)                         \
87   V(None, false, false, OperandSize::kNone)               \
88   V(ScalableSignedByte, true, false, OperandSize::kByte)  \
89   V(ScalableUnsignedByte, true, true, OperandSize::kByte) \
90   V(FixedUnsignedByte, false, true, OperandSize::kByte)   \
91   V(FixedUnsignedShort, false, true, OperandSize::kShort)
92 
93 enum class OperandTypeInfo : uint8_t {
94 #define DECLARE_OPERAND_TYPE_INFO(Name, ...) k##Name,
95   OPERAND_TYPE_INFO_LIST(DECLARE_OPERAND_TYPE_INFO)
96 #undef DECLARE_OPERAND_TYPE_INFO
97 };
98 
99 // Enumeration of operand types used by bytecodes.
100 enum class OperandType : uint8_t {
101 #define DECLARE_OPERAND_TYPE(Name, _) k##Name,
102   OPERAND_TYPE_LIST(DECLARE_OPERAND_TYPE)
103 #undef DECLARE_OPERAND_TYPE
104 #define COUNT_OPERAND_TYPES(x, _) +1
105   // The COUNT_OPERAND macro will turn this into kLast = -1 +1 +1... which will
106   // evaluate to the same value as the last operand.
107   kLast = -1 OPERAND_TYPE_LIST(COUNT_OPERAND_TYPES)
108 #undef COUNT_OPERAND_TYPES
109 };
110 
111 enum class AccumulatorUse : uint8_t {
112   kNone = 0,
113   kRead = 1 << 0,
114   kWrite = 1 << 1,
115   kReadWrite = kRead | kWrite
116 };
117 
118 inline AccumulatorUse operator&(AccumulatorUse lhs, AccumulatorUse rhs) {
119   int result = static_cast<int>(lhs) & static_cast<int>(rhs);
120   return static_cast<AccumulatorUse>(result);
121 }
122 
123 inline AccumulatorUse operator|(AccumulatorUse lhs, AccumulatorUse rhs) {
124   int result = static_cast<int>(lhs) | static_cast<int>(rhs);
125   return static_cast<AccumulatorUse>(result);
126 }
127 
128 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
129                                            const AccumulatorUse& use);
130 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
131                                            const OperandScale& operand_scale);
132 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
133                                            const OperandSize& operand_size);
134 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
135                                            const OperandType& operand_type);
136 
137 class BytecodeOperands : public AllStatic {
138  public:
139   // The total number of bytecode operand types used.
140   static const int kOperandTypeCount = static_cast<int>(OperandType::kLast) + 1;
141 
142 // The total number of bytecode operand scales used.
143 #define OPERAND_SCALE_COUNT(...) +1
144   static const int kOperandScaleCount =
145       0 OPERAND_SCALE_LIST(OPERAND_SCALE_COUNT);
146 #undef OPERAND_SCALE_COUNT
147 
148   // Returns true if |accumulator_use| reads the accumulator.
ReadsAccumulator(AccumulatorUse accumulator_use)149   static constexpr bool ReadsAccumulator(AccumulatorUse accumulator_use) {
150     return accumulator_use == AccumulatorUse::kRead ||
151            accumulator_use == AccumulatorUse::kReadWrite;
152   }
153 
154   // Returns true if |accumulator_use| writes the accumulator.
WritesAccumulator(AccumulatorUse accumulator_use)155   static constexpr bool WritesAccumulator(AccumulatorUse accumulator_use) {
156     return accumulator_use == AccumulatorUse::kWrite ||
157            accumulator_use == AccumulatorUse::kReadWrite;
158   }
159 
160   // Returns true if |operand_type| is a scalable signed byte.
IsScalableSignedByte(OperandType operand_type)161   static constexpr bool IsScalableSignedByte(OperandType operand_type) {
162     return operand_type >= OperandType::kImm &&
163            operand_type <= OperandType::kRegOutTriple;
164   }
165 
166   // Returns true if |operand_type| is a scalable unsigned byte.
IsScalableUnsignedByte(OperandType operand_type)167   static constexpr bool IsScalableUnsignedByte(OperandType operand_type) {
168     return operand_type >= OperandType::kIdx &&
169            operand_type <= OperandType::kRegCount;
170   }
171 };
172 
173 }  // namespace interpreter
174 }  // namespace internal
175 }  // namespace v8
176 
177 #endif  // V8_INTERPRETER_BYTECODE_OPERANDS_H_
178