1 // Copyright 2013 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.
5 #ifndef V8_COMPILER_COMMON_OPERATOR_H_
6 #define V8_COMPILER_COMMON_OPERATOR_H_
10 #include "src/assembler.h"
11 #include "src/compiler/linkage.h"
12 #include "src/compiler/opcodes.h"
13 #include "src/compiler/operator.h"
14 #include "src/unique.h"
23 class ControlOperator : public Operator1<int> {
25 ControlOperator(IrOpcode::Value opcode, uint16_t properties, int inputs,
26 int outputs, int controls, const char* mnemonic)
27 : Operator1<int>(opcode, properties, inputs, outputs, mnemonic,
30 virtual OStream& PrintParameter(OStream& os) const { return os; } // NOLINT
31 int ControlInputCount() const { return parameter(); }
34 class CallOperator : public Operator1<CallDescriptor*> {
36 CallOperator(CallDescriptor* descriptor, const char* mnemonic)
37 : Operator1<CallDescriptor*>(
38 IrOpcode::kCall, descriptor->properties(), descriptor->InputCount(),
39 descriptor->ReturnCount(), mnemonic, descriptor) {}
41 virtual OStream& PrintParameter(OStream& os) const { // NOLINT
42 return os << "[" << *parameter() << "]";
46 // Interface for building common operators that can be used at any level of IR,
47 // including JavaScript, mid-level, and low-level.
48 // TODO(titzer): Move the mnemonics into SimpleOperator and Operator1 classes.
49 class CommonOperatorBuilder {
51 explicit CommonOperatorBuilder(Zone* zone) : zone_(zone) {}
53 #define CONTROL_OP(name, inputs, controls) \
54 return new (zone_) ControlOperator(IrOpcode::k##name, Operator::kFoldable, \
55 inputs, 0, controls, #name);
57 Operator* Start(int num_formal_parameters) {
58 // Outputs are formal parameters, plus context, receiver, and JSFunction.
59 int outputs = num_formal_parameters + 3;
60 return new (zone_) ControlOperator(IrOpcode::kStart, Operator::kFoldable, 0,
63 Operator* Dead() { CONTROL_OP(Dead, 0, 0); }
64 Operator* End() { CONTROL_OP(End, 0, 1); }
65 Operator* Branch() { CONTROL_OP(Branch, 1, 1); }
66 Operator* IfTrue() { CONTROL_OP(IfTrue, 0, 1); }
67 Operator* IfFalse() { CONTROL_OP(IfFalse, 0, 1); }
68 Operator* Throw() { CONTROL_OP(Throw, 1, 1); }
69 Operator* LazyDeoptimization() { CONTROL_OP(LazyDeoptimization, 0, 1); }
70 Operator* Continuation() { CONTROL_OP(Continuation, 0, 1); }
72 Operator* Deoptimize() {
74 ControlOperator(IrOpcode::kDeoptimize, 0, 1, 0, 1, "Deoptimize");
78 return new (zone_) ControlOperator(IrOpcode::kReturn, 0, 1, 0, 1, "Return");
81 Operator* Merge(int controls) {
82 return new (zone_) ControlOperator(IrOpcode::kMerge, Operator::kFoldable, 0,
83 0, controls, "Merge");
86 Operator* Loop(int controls) {
87 return new (zone_) ControlOperator(IrOpcode::kLoop, Operator::kFoldable, 0,
91 Operator* Parameter(int index) {
92 return new (zone_) Operator1<int>(IrOpcode::kParameter, Operator::kPure, 1,
93 1, "Parameter", index);
95 Operator* Int32Constant(int32_t value) {
96 return new (zone_) Operator1<int>(IrOpcode::kInt32Constant, Operator::kPure,
97 0, 1, "Int32Constant", value);
99 Operator* Int64Constant(int64_t value) {
101 Operator1<int64_t>(IrOpcode::kInt64Constant, Operator::kPure, 0, 1,
102 "Int64Constant", value);
104 Operator* Float64Constant(double value) {
106 Operator1<double>(IrOpcode::kFloat64Constant, Operator::kPure, 0, 1,
107 "Float64Constant", value);
109 Operator* ExternalConstant(ExternalReference value) {
110 return new (zone_) Operator1<ExternalReference>(IrOpcode::kExternalConstant,
111 Operator::kPure, 0, 1,
112 "ExternalConstant", value);
114 Operator* NumberConstant(double value) {
116 Operator1<double>(IrOpcode::kNumberConstant, Operator::kPure, 0, 1,
117 "NumberConstant", value);
119 Operator* HeapConstant(PrintableUnique<Object> value) {
120 return new (zone_) Operator1<PrintableUnique<Object> >(
121 IrOpcode::kHeapConstant, Operator::kPure, 0, 1, "HeapConstant", value);
123 Operator* Phi(int arguments) {
124 DCHECK(arguments > 0); // Disallow empty phis.
125 return new (zone_) Operator1<int>(IrOpcode::kPhi, Operator::kPure,
126 arguments, 1, "Phi", arguments);
128 Operator* EffectPhi(int arguments) {
129 DCHECK(arguments > 0); // Disallow empty phis.
130 return new (zone_) Operator1<int>(IrOpcode::kEffectPhi, Operator::kPure, 0,
131 0, "EffectPhi", arguments);
133 Operator* StateValues(int arguments) {
134 return new (zone_) Operator1<int>(IrOpcode::kStateValues, Operator::kPure,
135 arguments, 1, "StateValues", arguments);
137 Operator* FrameState(BailoutId ast_id) {
138 return new (zone_) Operator1<BailoutId>(
139 IrOpcode::kFrameState, Operator::kPure, 3, 1, "FrameState", ast_id);
141 Operator* Call(CallDescriptor* descriptor) {
142 return new (zone_) CallOperator(descriptor, "Call");
144 Operator* Projection(int index) {
145 return new (zone_) Operator1<int>(IrOpcode::kProjection, Operator::kPure, 1,
146 1, "Projection", index);
154 template <typename T>
155 struct CommonOperatorTraits {
156 static inline bool Equals(T a, T b);
157 static inline bool HasValue(Operator* op);
158 static inline T ValueOf(Operator* op);
162 struct CommonOperatorTraits<int32_t> {
163 static inline bool Equals(int32_t a, int32_t b) { return a == b; }
164 static inline bool HasValue(Operator* op) {
165 return op->opcode() == IrOpcode::kInt32Constant ||
166 op->opcode() == IrOpcode::kNumberConstant;
168 static inline int32_t ValueOf(Operator* op) {
169 if (op->opcode() == IrOpcode::kNumberConstant) {
170 // TODO(titzer): cache the converted int32 value in NumberConstant.
171 return FastD2I(reinterpret_cast<Operator1<double>*>(op)->parameter());
173 CHECK_EQ(IrOpcode::kInt32Constant, op->opcode());
174 return static_cast<Operator1<int32_t>*>(op)->parameter();
179 struct CommonOperatorTraits<uint32_t> {
180 static inline bool Equals(uint32_t a, uint32_t b) { return a == b; }
181 static inline bool HasValue(Operator* op) {
182 return CommonOperatorTraits<int32_t>::HasValue(op);
184 static inline uint32_t ValueOf(Operator* op) {
185 if (op->opcode() == IrOpcode::kNumberConstant) {
186 // TODO(titzer): cache the converted uint32 value in NumberConstant.
187 return FastD2UI(reinterpret_cast<Operator1<double>*>(op)->parameter());
189 return static_cast<uint32_t>(CommonOperatorTraits<int32_t>::ValueOf(op));
194 struct CommonOperatorTraits<int64_t> {
195 static inline bool Equals(int64_t a, int64_t b) { return a == b; }
196 static inline bool HasValue(Operator* op) {
197 return op->opcode() == IrOpcode::kInt32Constant ||
198 op->opcode() == IrOpcode::kInt64Constant ||
199 op->opcode() == IrOpcode::kNumberConstant;
201 static inline int64_t ValueOf(Operator* op) {
202 if (op->opcode() == IrOpcode::kInt32Constant) {
203 return static_cast<int64_t>(CommonOperatorTraits<int32_t>::ValueOf(op));
205 CHECK_EQ(IrOpcode::kInt64Constant, op->opcode());
206 return static_cast<Operator1<int64_t>*>(op)->parameter();
211 struct CommonOperatorTraits<uint64_t> {
212 static inline bool Equals(uint64_t a, uint64_t b) { return a == b; }
213 static inline bool HasValue(Operator* op) {
214 return CommonOperatorTraits<int64_t>::HasValue(op);
216 static inline uint64_t ValueOf(Operator* op) {
217 return static_cast<uint64_t>(CommonOperatorTraits<int64_t>::ValueOf(op));
222 struct CommonOperatorTraits<double> {
223 static inline bool Equals(double a, double b) {
224 return DoubleRepresentation(a).bits == DoubleRepresentation(b).bits;
226 static inline bool HasValue(Operator* op) {
227 return op->opcode() == IrOpcode::kFloat64Constant ||
228 op->opcode() == IrOpcode::kInt32Constant ||
229 op->opcode() == IrOpcode::kNumberConstant;
231 static inline double ValueOf(Operator* op) {
232 if (op->opcode() == IrOpcode::kFloat64Constant ||
233 op->opcode() == IrOpcode::kNumberConstant) {
234 return reinterpret_cast<Operator1<double>*>(op)->parameter();
236 return static_cast<double>(CommonOperatorTraits<int32_t>::ValueOf(op));
241 struct CommonOperatorTraits<ExternalReference> {
242 static inline bool Equals(ExternalReference a, ExternalReference b) {
245 static inline bool HasValue(Operator* op) {
246 return op->opcode() == IrOpcode::kExternalConstant;
248 static inline ExternalReference ValueOf(Operator* op) {
249 CHECK_EQ(IrOpcode::kExternalConstant, op->opcode());
250 return static_cast<Operator1<ExternalReference>*>(op)->parameter();
254 template <typename T>
255 struct CommonOperatorTraits<PrintableUnique<T> > {
256 static inline bool HasValue(Operator* op) {
257 return op->opcode() == IrOpcode::kHeapConstant;
259 static inline PrintableUnique<T> ValueOf(Operator* op) {
260 CHECK_EQ(IrOpcode::kHeapConstant, op->opcode());
261 return static_cast<Operator1<PrintableUnique<T> >*>(op)->parameter();
265 template <typename T>
266 struct CommonOperatorTraits<Handle<T> > {
267 static inline bool HasValue(Operator* op) {
268 return CommonOperatorTraits<PrintableUnique<T> >::HasValue(op);
270 static inline Handle<T> ValueOf(Operator* op) {
271 return CommonOperatorTraits<PrintableUnique<T> >::ValueOf(op).handle();
276 template <typename T>
277 inline T ValueOf(Operator* op) {
278 return CommonOperatorTraits<T>::ValueOf(op);
282 } // namespace v8::internal::compiler
284 #endif // V8_COMPILER_COMMON_OPERATOR_H_