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/machine-operator.h"
6 
7 #include "src/base/lazy-instance.h"
8 #include "src/compiler/opcodes.h"
9 #include "src/compiler/operator.h"
10 
11 namespace v8 {
12 namespace internal {
13 namespace compiler {
14 
operator <<(OStream & os,const WriteBarrierKind & write_barrier_kind)15 OStream& operator<<(OStream& os, const WriteBarrierKind& write_barrier_kind) {
16   switch (write_barrier_kind) {
17     case kNoWriteBarrier:
18       return os << "NoWriteBarrier";
19     case kFullWriteBarrier:
20       return os << "FullWriteBarrier";
21   }
22   UNREACHABLE();
23   return os;
24 }
25 
26 
operator <<(OStream & os,const StoreRepresentation & rep)27 OStream& operator<<(OStream& os, const StoreRepresentation& rep) {
28   return os << "(" << rep.machine_type() << " : " << rep.write_barrier_kind()
29             << ")";
30 }
31 
32 
33 template <>
34 struct StaticParameterTraits<StoreRepresentation> {
PrintTov8::internal::compiler::StaticParameterTraits35   static OStream& PrintTo(OStream& os, const StoreRepresentation& rep) {
36     return os << rep;
37   }
HashCodev8::internal::compiler::StaticParameterTraits38   static int HashCode(const StoreRepresentation& rep) {
39     return rep.machine_type() + rep.write_barrier_kind();
40   }
Equalsv8::internal::compiler::StaticParameterTraits41   static bool Equals(const StoreRepresentation& rep1,
42                      const StoreRepresentation& rep2) {
43     return rep1 == rep2;
44   }
45 };
46 
47 
48 template <>
49 struct StaticParameterTraits<LoadRepresentation> {
PrintTov8::internal::compiler::StaticParameterTraits50   static OStream& PrintTo(OStream& os, LoadRepresentation type) {  // NOLINT
51     return os << type;
52   }
HashCodev8::internal::compiler::StaticParameterTraits53   static int HashCode(LoadRepresentation type) { return type; }
Equalsv8::internal::compiler::StaticParameterTraits54   static bool Equals(LoadRepresentation lhs, LoadRepresentation rhs) {
55     return lhs == rhs;
56   }
57 };
58 
59 
60 #define PURE_OP_LIST(V)                                                       \
61   V(Word32And, Operator::kAssociative | Operator::kCommutative, 2, 1)         \
62   V(Word32Or, Operator::kAssociative | Operator::kCommutative, 2, 1)          \
63   V(Word32Xor, Operator::kAssociative | Operator::kCommutative, 2, 1)         \
64   V(Word32Shl, Operator::kNoProperties, 2, 1)                                 \
65   V(Word32Shr, Operator::kNoProperties, 2, 1)                                 \
66   V(Word32Sar, Operator::kNoProperties, 2, 1)                                 \
67   V(Word32Ror, Operator::kNoProperties, 2, 1)                                 \
68   V(Word32Equal, Operator::kCommutative, 2, 1)                                \
69   V(Word64And, Operator::kAssociative | Operator::kCommutative, 2, 1)         \
70   V(Word64Or, Operator::kAssociative | Operator::kCommutative, 2, 1)          \
71   V(Word64Xor, Operator::kAssociative | Operator::kCommutative, 2, 1)         \
72   V(Word64Shl, Operator::kNoProperties, 2, 1)                                 \
73   V(Word64Shr, Operator::kNoProperties, 2, 1)                                 \
74   V(Word64Sar, Operator::kNoProperties, 2, 1)                                 \
75   V(Word64Ror, Operator::kNoProperties, 2, 1)                                 \
76   V(Word64Equal, Operator::kCommutative, 2, 1)                                \
77   V(Int32Add, Operator::kAssociative | Operator::kCommutative, 2, 1)          \
78   V(Int32AddWithOverflow, Operator::kAssociative | Operator::kCommutative, 2, \
79     2)                                                                        \
80   V(Int32Sub, Operator::kNoProperties, 2, 1)                                  \
81   V(Int32SubWithOverflow, Operator::kNoProperties, 2, 2)                      \
82   V(Int32Mul, Operator::kAssociative | Operator::kCommutative, 2, 1)          \
83   V(Int32Div, Operator::kNoProperties, 2, 1)                                  \
84   V(Int32UDiv, Operator::kNoProperties, 2, 1)                                 \
85   V(Int32Mod, Operator::kNoProperties, 2, 1)                                  \
86   V(Int32UMod, Operator::kNoProperties, 2, 1)                                 \
87   V(Int32LessThan, Operator::kNoProperties, 2, 1)                             \
88   V(Int32LessThanOrEqual, Operator::kNoProperties, 2, 1)                      \
89   V(Uint32LessThan, Operator::kNoProperties, 2, 1)                            \
90   V(Uint32LessThanOrEqual, Operator::kNoProperties, 2, 1)                     \
91   V(Int64Add, Operator::kAssociative | Operator::kCommutative, 2, 1)          \
92   V(Int64Sub, Operator::kNoProperties, 2, 1)                                  \
93   V(Int64Mul, Operator::kAssociative | Operator::kCommutative, 2, 1)          \
94   V(Int64Div, Operator::kNoProperties, 2, 1)                                  \
95   V(Int64UDiv, Operator::kNoProperties, 2, 1)                                 \
96   V(Int64Mod, Operator::kNoProperties, 2, 1)                                  \
97   V(Int64UMod, Operator::kNoProperties, 2, 1)                                 \
98   V(Int64LessThan, Operator::kNoProperties, 2, 1)                             \
99   V(Int64LessThanOrEqual, Operator::kNoProperties, 2, 1)                      \
100   V(ChangeFloat32ToFloat64, Operator::kNoProperties, 1, 1)                    \
101   V(ChangeFloat64ToInt32, Operator::kNoProperties, 1, 1)                      \
102   V(ChangeFloat64ToUint32, Operator::kNoProperties, 1, 1)                     \
103   V(ChangeInt32ToFloat64, Operator::kNoProperties, 1, 1)                      \
104   V(ChangeInt32ToInt64, Operator::kNoProperties, 1, 1)                        \
105   V(ChangeUint32ToFloat64, Operator::kNoProperties, 1, 1)                     \
106   V(ChangeUint32ToUint64, Operator::kNoProperties, 1, 1)                      \
107   V(TruncateFloat64ToFloat32, Operator::kNoProperties, 1, 1)                  \
108   V(TruncateFloat64ToInt32, Operator::kNoProperties, 1, 1)                    \
109   V(TruncateInt64ToInt32, Operator::kNoProperties, 1, 1)                      \
110   V(Float64Add, Operator::kCommutative, 2, 1)                                 \
111   V(Float64Sub, Operator::kNoProperties, 2, 1)                                \
112   V(Float64Mul, Operator::kCommutative, 2, 1)                                 \
113   V(Float64Div, Operator::kNoProperties, 2, 1)                                \
114   V(Float64Mod, Operator::kNoProperties, 2, 1)                                \
115   V(Float64Sqrt, Operator::kNoProperties, 1, 1)                               \
116   V(Float64Equal, Operator::kCommutative, 2, 1)                               \
117   V(Float64LessThan, Operator::kNoProperties, 2, 1)                           \
118   V(Float64LessThanOrEqual, Operator::kNoProperties, 2, 1)
119 
120 
121 #define MACHINE_TYPE_LIST(V) \
122   V(MachFloat32)             \
123   V(MachFloat64)             \
124   V(MachInt8)                \
125   V(MachUint8)               \
126   V(MachInt16)               \
127   V(MachUint16)              \
128   V(MachInt32)               \
129   V(MachUint32)              \
130   V(MachInt64)               \
131   V(MachUint64)              \
132   V(MachAnyTagged)           \
133   V(RepBit)                  \
134   V(RepWord8)                \
135   V(RepWord16)               \
136   V(RepWord32)               \
137   V(RepWord64)               \
138   V(RepFloat32)              \
139   V(RepFloat64)              \
140   V(RepTagged)
141 
142 
143 struct MachineOperatorBuilderImpl {
144 #define PURE(Name, properties, input_count, output_count)                 \
145   struct Name##Operator FINAL : public SimpleOperator {                   \
146     Name##Operator()                                                      \
147         : SimpleOperator(IrOpcode::k##Name, Operator::kPure | properties, \
148                          input_count, output_count, #Name) {}             \
149   };                                                                      \
150   Name##Operator k##Name;
151   PURE_OP_LIST(PURE)
152 #undef PURE
153 
154 #define LOAD(Type)                                                            \
155   struct Load##Type##Operator FINAL : public Operator1<LoadRepresentation> {  \
156     Load##Type##Operator()                                                    \
157         : Operator1<LoadRepresentation>(                                      \
158               IrOpcode::kLoad, Operator::kNoThrow | Operator::kNoWrite, 2, 1, \
159               "Load", k##Type) {}                                             \
160   };                                                                          \
161   Load##Type##Operator k##Load##Type;
162   MACHINE_TYPE_LIST(LOAD)
163 #undef LOAD
164 
165 #define STORE(Type)                                                           \
166   struct Store##Type##Operator : public Operator1<StoreRepresentation> {      \
167     explicit Store##Type##Operator(WriteBarrierKind write_barrier_kind)       \
168         : Operator1<StoreRepresentation>(                                     \
169               IrOpcode::kStore, Operator::kNoRead | Operator::kNoThrow, 3, 0, \
170               "Store", StoreRepresentation(k##Type, write_barrier_kind)) {}   \
171   };                                                                          \
172   struct Store##Type##NoWriteBarrier##Operator FINAL                          \
173       : public Store##Type##Operator {                                        \
174     Store##Type##NoWriteBarrier##Operator()                                   \
175         : Store##Type##Operator(kNoWriteBarrier) {}                           \
176   };                                                                          \
177   struct Store##Type##FullWriteBarrier##Operator FINAL                        \
178       : public Store##Type##Operator {                                        \
179     Store##Type##FullWriteBarrier##Operator()                                 \
180         : Store##Type##Operator(kFullWriteBarrier) {}                         \
181   };                                                                          \
182   Store##Type##NoWriteBarrier##Operator k##Store##Type##NoWriteBarrier;       \
183   Store##Type##FullWriteBarrier##Operator k##Store##Type##FullWriteBarrier;
184   MACHINE_TYPE_LIST(STORE)
185 #undef STORE
186 };
187 
188 
189 static base::LazyInstance<MachineOperatorBuilderImpl>::type kImpl =
190     LAZY_INSTANCE_INITIALIZER;
191 
192 
MachineOperatorBuilder(MachineType word)193 MachineOperatorBuilder::MachineOperatorBuilder(MachineType word)
194     : impl_(kImpl.Get()), word_(word) {
195   DCHECK(word == kRepWord32 || word == kRepWord64);
196 }
197 
198 
199 #define PURE(Name, properties, input_count, output_count) \
200   const Operator* MachineOperatorBuilder::Name() { return &impl_.k##Name; }
PURE_OP_LIST(PURE) const201 PURE_OP_LIST(PURE)
202 #undef PURE
203 
204 
205 const Operator* MachineOperatorBuilder::Load(LoadRepresentation rep) {
206   switch (rep) {
207 #define LOAD(Type) \
208   case k##Type:    \
209     return &impl_.k##Load##Type;
210     MACHINE_TYPE_LIST(LOAD)
211 #undef LOAD
212 
213     default:
214       break;
215   }
216   UNREACHABLE();
217   return NULL;
218 }
219 
220 
Store(StoreRepresentation rep)221 const Operator* MachineOperatorBuilder::Store(StoreRepresentation rep) {
222   switch (rep.machine_type()) {
223 #define STORE(Type)                                     \
224   case k##Type:                                         \
225     switch (rep.write_barrier_kind()) {                 \
226       case kNoWriteBarrier:                             \
227         return &impl_.k##Store##Type##NoWriteBarrier;   \
228       case kFullWriteBarrier:                           \
229         return &impl_.k##Store##Type##FullWriteBarrier; \
230     }                                                   \
231     break;
232     MACHINE_TYPE_LIST(STORE)
233 #undef STORE
234 
235     default:
236       break;
237   }
238   UNREACHABLE();
239   return NULL;
240 }
241 
242 }  // namespace compiler
243 }  // namespace internal
244 }  // namespace v8
245