blob: b8136051bbb20eec6c127b9a21c2891742781eed [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// Copyright 2015 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_TRAITS_H_
6#define V8_INTERPRETER_BYTECODE_TRAITS_H_
7
8#include "src/interpreter/bytecodes.h"
9
10namespace v8 {
11namespace internal {
12namespace interpreter {
13
14// TODO(rmcilroy): consider simplifying this to avoid the template magic.
15
16// Template helpers to deduce the number of operands each bytecode has.
17#define OPERAND_TERM OperandType::kNone, OperandType::kNone, OperandType::kNone
18
19template <OperandType>
20struct OperandTraits {};
21
22#define DECLARE_OPERAND_SIZE(Name, Size) \
23 template <> \
24 struct OperandTraits<OperandType::k##Name> { \
25 static const OperandSize kSizeType = Size; \
26 static const int kSize = static_cast<int>(Size); \
27 };
28OPERAND_TYPE_LIST(DECLARE_OPERAND_SIZE)
29#undef DECLARE_OPERAND_SIZE
30
Ben Murdoch097c5b22016-05-18 11:27:45 +010031template <OperandType>
32struct RegisterOperandTraits {
33 static const int kIsRegisterOperand = 0;
34};
35
36#define DECLARE_REGISTER_OPERAND(Name, _) \
37 template <> \
38 struct RegisterOperandTraits<OperandType::k##Name> { \
39 static const int kIsRegisterOperand = 1; \
40 };
41REGISTER_OPERAND_TYPE_LIST(DECLARE_REGISTER_OPERAND)
42#undef DECLARE_REGISTER_OPERAND
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000043
44template <OperandType... Args>
45struct BytecodeTraits {};
46
47template <OperandType operand_0, OperandType operand_1, OperandType operand_2,
48 OperandType operand_3>
49struct BytecodeTraits<operand_0, operand_1, operand_2, operand_3,
50 OPERAND_TERM> {
51 static OperandType GetOperandType(int i) {
52 DCHECK(0 <= i && i < kOperandCount);
53 const OperandType kOperands[] = {operand_0, operand_1, operand_2,
54 operand_3};
55 return kOperands[i];
56 }
57
58 static inline OperandSize GetOperandSize(int i) {
59 DCHECK(0 <= i && i < kOperandCount);
60 const OperandSize kOperandSizes[] =
61 {OperandTraits<operand_0>::kSizeType,
62 OperandTraits<operand_1>::kSizeType,
63 OperandTraits<operand_2>::kSizeType,
64 OperandTraits<operand_3>::kSizeType};
65 return kOperandSizes[i];
66 }
67
68 static inline int GetOperandOffset(int i) {
69 DCHECK(0 <= i && i < kOperandCount);
70 const int kOffset0 = 1;
71 const int kOffset1 = kOffset0 + OperandTraits<operand_0>::kSize;
72 const int kOffset2 = kOffset1 + OperandTraits<operand_1>::kSize;
73 const int kOffset3 = kOffset2 + OperandTraits<operand_2>::kSize;
74 const int kOperandOffsets[] = {kOffset0, kOffset1, kOffset2, kOffset3};
75 return kOperandOffsets[i];
76 }
77
Ben Murdoch097c5b22016-05-18 11:27:45 +010078 template <OperandType ot>
79 static inline bool HasAnyOperandsOfType() {
80 return operand_0 == ot || operand_1 == ot || operand_2 == ot ||
81 operand_3 == ot;
82 }
83
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000084 static const int kOperandCount = 4;
Ben Murdoch097c5b22016-05-18 11:27:45 +010085 static const int kRegisterOperandCount =
86 RegisterOperandTraits<operand_0>::kIsRegisterOperand +
87 RegisterOperandTraits<operand_1>::kIsRegisterOperand +
88 RegisterOperandTraits<operand_2>::kIsRegisterOperand +
89 RegisterOperandTraits<operand_3>::kIsRegisterOperand;
90 static const int kRegisterOperandBitmap =
91 RegisterOperandTraits<operand_0>::kIsRegisterOperand +
92 (RegisterOperandTraits<operand_1>::kIsRegisterOperand << 1) +
93 (RegisterOperandTraits<operand_2>::kIsRegisterOperand << 2) +
94 (RegisterOperandTraits<operand_3>::kIsRegisterOperand << 3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000095 static const int kSize =
96 1 + OperandTraits<operand_0>::kSize + OperandTraits<operand_1>::kSize +
97 OperandTraits<operand_2>::kSize + OperandTraits<operand_3>::kSize;
98};
99
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000100template <OperandType operand_0, OperandType operand_1, OperandType operand_2>
101struct BytecodeTraits<operand_0, operand_1, operand_2, OPERAND_TERM> {
102 static inline OperandType GetOperandType(int i) {
103 DCHECK(0 <= i && i <= 2);
104 const OperandType kOperands[] = {operand_0, operand_1, operand_2};
105 return kOperands[i];
106 }
107
108 static inline OperandSize GetOperandSize(int i) {
109 DCHECK(0 <= i && i < kOperandCount);
110 const OperandSize kOperandSizes[] =
111 {OperandTraits<operand_0>::kSizeType,
112 OperandTraits<operand_1>::kSizeType,
113 OperandTraits<operand_2>::kSizeType};
114 return kOperandSizes[i];
115 }
116
117 static inline int GetOperandOffset(int i) {
118 DCHECK(0 <= i && i < kOperandCount);
119 const int kOffset0 = 1;
120 const int kOffset1 = kOffset0 + OperandTraits<operand_0>::kSize;
121 const int kOffset2 = kOffset1 + OperandTraits<operand_1>::kSize;
122 const int kOperandOffsets[] = {kOffset0, kOffset1, kOffset2};
123 return kOperandOffsets[i];
124 }
125
Ben Murdoch097c5b22016-05-18 11:27:45 +0100126 template <OperandType ot>
127 static inline bool HasAnyOperandsOfType() {
128 return operand_0 == ot || operand_1 == ot || operand_2 == ot;
129 }
130
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000131 static const int kOperandCount = 3;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100132 static const int kRegisterOperandCount =
133 RegisterOperandTraits<operand_0>::kIsRegisterOperand +
134 RegisterOperandTraits<operand_1>::kIsRegisterOperand +
135 RegisterOperandTraits<operand_2>::kIsRegisterOperand;
136 static const int kRegisterOperandBitmap =
137 RegisterOperandTraits<operand_0>::kIsRegisterOperand +
138 (RegisterOperandTraits<operand_1>::kIsRegisterOperand << 1) +
139 (RegisterOperandTraits<operand_2>::kIsRegisterOperand << 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000140 static const int kSize =
141 1 + OperandTraits<operand_0>::kSize + OperandTraits<operand_1>::kSize +
142 OperandTraits<operand_2>::kSize;
143};
144
145template <OperandType operand_0, OperandType operand_1>
146struct BytecodeTraits<operand_0, operand_1, OPERAND_TERM> {
147 static inline OperandType GetOperandType(int i) {
148 DCHECK(0 <= i && i < kOperandCount);
149 const OperandType kOperands[] = {operand_0, operand_1};
150 return kOperands[i];
151 }
152
153 static inline OperandSize GetOperandSize(int i) {
154 DCHECK(0 <= i && i < kOperandCount);
155 const OperandSize kOperandSizes[] =
156 {OperandTraits<operand_0>::kSizeType,
157 OperandTraits<operand_1>::kSizeType};
158 return kOperandSizes[i];
159 }
160
161 static inline int GetOperandOffset(int i) {
162 DCHECK(0 <= i && i < kOperandCount);
163 const int kOffset0 = 1;
164 const int kOffset1 = kOffset0 + OperandTraits<operand_0>::kSize;
165 const int kOperandOffsets[] = {kOffset0, kOffset1};
166 return kOperandOffsets[i];
167 }
168
Ben Murdoch097c5b22016-05-18 11:27:45 +0100169 template <OperandType ot>
170 static inline bool HasAnyOperandsOfType() {
171 return operand_0 == ot || operand_1 == ot;
172 }
173
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000174 static const int kOperandCount = 2;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100175 static const int kRegisterOperandCount =
176 RegisterOperandTraits<operand_0>::kIsRegisterOperand +
177 RegisterOperandTraits<operand_1>::kIsRegisterOperand;
178 static const int kRegisterOperandBitmap =
179 RegisterOperandTraits<operand_0>::kIsRegisterOperand +
180 (RegisterOperandTraits<operand_1>::kIsRegisterOperand << 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000181 static const int kSize =
182 1 + OperandTraits<operand_0>::kSize + OperandTraits<operand_1>::kSize;
183};
184
185template <OperandType operand_0>
186struct BytecodeTraits<operand_0, OPERAND_TERM> {
187 static inline OperandType GetOperandType(int i) {
188 DCHECK(i == 0);
189 return operand_0;
190 }
191
192 static inline OperandSize GetOperandSize(int i) {
193 DCHECK(i == 0);
194 return OperandTraits<operand_0>::kSizeType;
195 }
196
197 static inline int GetOperandOffset(int i) {
198 DCHECK(i == 0);
199 return 1;
200 }
201
Ben Murdoch097c5b22016-05-18 11:27:45 +0100202 template <OperandType ot>
203 static inline bool HasAnyOperandsOfType() {
204 return operand_0 == ot;
205 }
206
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000207 static const int kOperandCount = 1;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100208 static const int kRegisterOperandCount =
209 RegisterOperandTraits<operand_0>::kIsRegisterOperand;
210 static const int kRegisterOperandBitmap =
211 RegisterOperandTraits<operand_0>::kIsRegisterOperand;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000212 static const int kSize = 1 + OperandTraits<operand_0>::kSize;
213};
214
215template <>
216struct BytecodeTraits<OperandType::kNone, OPERAND_TERM> {
217 static inline OperandType GetOperandType(int i) {
218 UNREACHABLE();
219 return OperandType::kNone;
220 }
221
222 static inline OperandSize GetOperandSize(int i) {
223 UNREACHABLE();
224 return OperandSize::kNone;
225 }
226
227 static inline int GetOperandOffset(int i) {
228 UNREACHABLE();
229 return 1;
230 }
231
Ben Murdoch097c5b22016-05-18 11:27:45 +0100232 template <OperandType ot>
233 static inline bool HasAnyOperandsOfType() {
234 return false;
235 }
236
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000237 static const int kOperandCount = 0;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100238 static const int kRegisterOperandCount = 0;
239 static const int kRegisterOperandBitmap = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000240 static const int kSize = 1 + OperandTraits<OperandType::kNone>::kSize;
241};
242
243} // namespace interpreter
244} // namespace internal
245} // namespace v8
246
247#endif // V8_INTERPRETER_BYTECODE_TRAITS_H_