1// Copyright 2014 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#include "src/compiler/common-operator.h"
6
7#include <limits>
8
9#include "src/compiler/operator-properties-inl.h"
10#include "src/test/test-utils.h"
11
12namespace v8 {
13namespace internal {
14namespace compiler {
15
16
17// -----------------------------------------------------------------------------
18// Shared operators.
19
20
21namespace {
22
23struct SharedOperator {
24  const Operator* (CommonOperatorBuilder::*constructor)();
25  IrOpcode::Value opcode;
26  Operator::Properties properties;
27  int value_input_count;
28  int effect_input_count;
29  int control_input_count;
30  int effect_output_count;
31  int control_output_count;
32};
33
34
35std::ostream& operator<<(std::ostream& os, const SharedOperator& fop) {
36  return os << IrOpcode::Mnemonic(fop.opcode);
37}
38
39
40const SharedOperator kSharedOperators[] = {
41#define SHARED(Name, properties, value_input_count, effect_input_count,        \
42               control_input_count, effect_output_count, control_output_count) \
43  {                                                                            \
44    &CommonOperatorBuilder::Name, IrOpcode::k##Name, properties,               \
45        value_input_count, effect_input_count, control_input_count,            \
46        effect_output_count, control_output_count                              \
47  }
48    SHARED(Dead, Operator::kFoldable, 0, 0, 0, 0, 1),
49    SHARED(End, Operator::kFoldable, 0, 0, 1, 0, 0),
50    SHARED(Branch, Operator::kFoldable, 1, 0, 1, 0, 2),
51    SHARED(IfTrue, Operator::kFoldable, 0, 0, 1, 0, 1),
52    SHARED(IfFalse, Operator::kFoldable, 0, 0, 1, 0, 1),
53    SHARED(Throw, Operator::kFoldable, 1, 0, 1, 0, 1),
54    SHARED(Return, Operator::kNoProperties, 1, 1, 1, 1, 1),
55    SHARED(ControlEffect, Operator::kPure, 0, 0, 1, 1, 0)
56#undef SHARED
57};
58
59
60class CommonSharedOperatorTest
61    : public TestWithZone,
62      public ::testing::WithParamInterface<SharedOperator> {};
63
64}  // namespace
65
66
67TEST_P(CommonSharedOperatorTest, InstancesAreGloballyShared) {
68  const SharedOperator& sop = GetParam();
69  CommonOperatorBuilder common1(zone());
70  CommonOperatorBuilder common2(zone());
71  EXPECT_EQ((common1.*sop.constructor)(), (common2.*sop.constructor)());
72}
73
74
75TEST_P(CommonSharedOperatorTest, NumberOfInputsAndOutputs) {
76  CommonOperatorBuilder common(zone());
77  const SharedOperator& sop = GetParam();
78  const Operator* op = (common.*sop.constructor)();
79
80  EXPECT_EQ(sop.value_input_count, OperatorProperties::GetValueInputCount(op));
81  EXPECT_EQ(sop.effect_input_count,
82            OperatorProperties::GetEffectInputCount(op));
83  EXPECT_EQ(sop.control_input_count,
84            OperatorProperties::GetControlInputCount(op));
85  EXPECT_EQ(
86      sop.value_input_count + sop.effect_input_count + sop.control_input_count,
87      OperatorProperties::GetTotalInputCount(op));
88
89  EXPECT_EQ(0, OperatorProperties::GetValueOutputCount(op));
90  EXPECT_EQ(sop.effect_output_count,
91            OperatorProperties::GetEffectOutputCount(op));
92  EXPECT_EQ(sop.control_output_count,
93            OperatorProperties::GetControlOutputCount(op));
94}
95
96
97TEST_P(CommonSharedOperatorTest, OpcodeIsCorrect) {
98  CommonOperatorBuilder common(zone());
99  const SharedOperator& sop = GetParam();
100  const Operator* op = (common.*sop.constructor)();
101  EXPECT_EQ(sop.opcode, op->opcode());
102}
103
104
105TEST_P(CommonSharedOperatorTest, Properties) {
106  CommonOperatorBuilder common(zone());
107  const SharedOperator& sop = GetParam();
108  const Operator* op = (common.*sop.constructor)();
109  EXPECT_EQ(sop.properties, op->properties());
110}
111
112
113INSTANTIATE_TEST_CASE_P(CommonOperatorTest, CommonSharedOperatorTest,
114                        ::testing::ValuesIn(kSharedOperators));
115
116
117// -----------------------------------------------------------------------------
118// Other operators.
119
120
121namespace {
122
123class CommonOperatorTest : public TestWithZone {
124 public:
125  CommonOperatorTest() : common_(zone()) {}
126  virtual ~CommonOperatorTest() {}
127
128  CommonOperatorBuilder* common() { return &common_; }
129
130 private:
131  CommonOperatorBuilder common_;
132};
133
134
135const int kArguments[] = {1, 5, 6, 42, 100, 10000, kMaxInt};
136
137const float kFloat32Values[] = {
138    std::numeric_limits<float>::min(), -1.0f, -0.0f, 0.0f, 1.0f,
139    std::numeric_limits<float>::max()};
140
141}  // namespace
142
143
144TEST_F(CommonOperatorTest, Float32Constant) {
145  TRACED_FOREACH(float, value, kFloat32Values) {
146    const Operator* op = common()->Float32Constant(value);
147    EXPECT_FLOAT_EQ(value, OpParameter<float>(op));
148    EXPECT_EQ(0, OperatorProperties::GetValueInputCount(op));
149    EXPECT_EQ(0, OperatorProperties::GetTotalInputCount(op));
150    EXPECT_EQ(0, OperatorProperties::GetControlOutputCount(op));
151    EXPECT_EQ(0, OperatorProperties::GetEffectOutputCount(op));
152    EXPECT_EQ(1, OperatorProperties::GetValueOutputCount(op));
153  }
154}
155
156
157TEST_F(CommonOperatorTest, ValueEffect) {
158  TRACED_FOREACH(int, arguments, kArguments) {
159    const Operator* op = common()->ValueEffect(arguments);
160    EXPECT_EQ(arguments, OperatorProperties::GetValueInputCount(op));
161    EXPECT_EQ(arguments, OperatorProperties::GetTotalInputCount(op));
162    EXPECT_EQ(0, OperatorProperties::GetControlOutputCount(op));
163    EXPECT_EQ(1, OperatorProperties::GetEffectOutputCount(op));
164    EXPECT_EQ(0, OperatorProperties::GetValueOutputCount(op));
165  }
166}
167
168
169TEST_F(CommonOperatorTest, Finish) {
170  TRACED_FOREACH(int, arguments, kArguments) {
171    const Operator* op = common()->Finish(arguments);
172    EXPECT_EQ(1, OperatorProperties::GetValueInputCount(op));
173    EXPECT_EQ(arguments, OperatorProperties::GetEffectInputCount(op));
174    EXPECT_EQ(arguments + 1, OperatorProperties::GetTotalInputCount(op));
175    EXPECT_EQ(0, OperatorProperties::GetControlOutputCount(op));
176    EXPECT_EQ(0, OperatorProperties::GetEffectOutputCount(op));
177    EXPECT_EQ(1, OperatorProperties::GetValueOutputCount(op));
178  }
179}
180
181}  // namespace compiler
182}  // namespace internal
183}  // namespace v8
184