Replace WTF::move with WTFMove
[WebKit-https.git] / Source / JavaScriptCore / b3 / B3Value.h
1 /*
2  * Copyright (C) 2015 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #ifndef B3Value_h
27 #define B3Value_h
28
29 #if ENABLE(B3_JIT)
30
31 #include "AirArg.h"
32 #include "B3Effects.h"
33 #include "B3Opcode.h"
34 #include "B3Origin.h"
35 #include "B3Type.h"
36 #include "B3ValueKey.h"
37 #include <wtf/CommaPrinter.h>
38 #include <wtf/FastMalloc.h>
39 #include <wtf/Noncopyable.h>
40
41 namespace JSC { namespace B3 {
42
43 class BasicBlock;
44 class CheckValue;
45 class Procedure;
46
47 class JS_EXPORT_PRIVATE Value {
48     WTF_MAKE_NONCOPYABLE(Value);
49     WTF_MAKE_FAST_ALLOCATED;
50 public:
51     typedef Vector<Value*, 3> AdjacencyList;
52
53     static const char* const dumpPrefix;
54
55     static bool accepts(Opcode) { return true; }
56
57     virtual ~Value();
58
59     unsigned index() const { return m_index; }
60     
61     // Note that the opcode is immutable, except for replacing values with Identity or Nop.
62     Opcode opcode() const { return m_opcode; }
63
64     Origin origin() const { return m_origin; }
65     
66     Value*& child(unsigned index) { return m_children[index]; }
67     Value* child(unsigned index) const { return m_children[index]; }
68
69     Value*& lastChild() { return m_children.last(); }
70     Value* lastChild() const { return m_children.last(); }
71
72     unsigned numChildren() const { return m_children.size(); }
73
74     Type type() const { return m_type; }
75     void setType(Type type) { m_type = type; }
76
77     // This is useful when lowering. Note that this is only valid for non-void values.
78     Air::Arg::Type airType() const { return Air::Arg::typeForB3Type(type()); }
79     Air::Arg::Width airWidth() const { return Air::Arg::widthForB3Type(type()); }
80
81     AdjacencyList& children() { return m_children; } 
82     const AdjacencyList& children() const { return m_children; }
83
84     void replaceWithIdentity(Value*);
85     void replaceWithNop();
86
87     void dump(PrintStream&) const;
88     void deepDump(const Procedure&, PrintStream&) const;
89
90     // This is how you cast Values. For example, if you want to do something provided that we have a
91     // ArgumentRegValue, you can do:
92     //
93     // if (ArgumentRegValue* argumentReg = value->as<ArgumentRegValue>()) {
94     //     things
95     // }
96     //
97     // This will return null if this opcode() != ArgumentReg. This works because this returns nullptr
98     // if T::accepts(opcode()) returns false.
99     template<typename T>
100     T* as();
101     template<typename T>
102     const T* as() const;
103
104     // What follows are a bunch of helpers for inspecting and modifying values. Note that we have a
105     // bunch of different idioms for implementing such helpers. You can use virtual methods, and
106     // override from the various Value subclasses. You can put the method inside Value and make it
107     // non-virtual, and the implementation can switch on opcode. The method could be inline or not.
108     // If a method is specific to some Value subclass, you could put it in the subclass, or you could
109     // put it on Value anyway. It's fine to pick whatever feels right, and we shouldn't restrict
110     // ourselves to any particular idiom.
111
112     bool isConstant() const;
113     bool isInteger() const;
114     
115     virtual Value* negConstant(Procedure&) const;
116     virtual Value* addConstant(Procedure&, int32_t other) const;
117     virtual Value* addConstant(Procedure&, const Value* other) const;
118     virtual Value* subConstant(Procedure&, const Value* other) const;
119     virtual Value* mulConstant(Procedure&, const Value* other) const;
120     virtual Value* checkAddConstant(Procedure&, const Value* other) const;
121     virtual Value* checkSubConstant(Procedure&, const Value* other) const;
122     virtual Value* checkMulConstant(Procedure&, const Value* other) const;
123     virtual Value* checkNegConstant(Procedure&) const;
124     virtual Value* divConstant(Procedure&, const Value* other) const; // This chooses ChillDiv semantics for integers.
125     virtual Value* modConstant(Procedure&, const Value* other) const; // This chooses ChillMod semantics.
126     virtual Value* bitAndConstant(Procedure&, const Value* other) const;
127     virtual Value* bitOrConstant(Procedure&, const Value* other) const;
128     virtual Value* bitXorConstant(Procedure&, const Value* other) const;
129     virtual Value* shlConstant(Procedure&, const Value* other) const;
130     virtual Value* sShrConstant(Procedure&, const Value* other) const;
131     virtual Value* zShrConstant(Procedure&, const Value* other) const;
132     virtual Value* bitwiseCastConstant(Procedure&) const;
133     virtual Value* doubleToFloatConstant(Procedure&) const;
134     virtual Value* floatToDoubleConstant(Procedure&) const;
135     virtual Value* absConstant(Procedure&) const;
136     virtual Value* ceilConstant(Procedure&) const;
137     virtual Value* sqrtConstant(Procedure&) const;
138
139     virtual TriState equalConstant(const Value* other) const;
140     virtual TriState notEqualConstant(const Value* other) const;
141     virtual TriState lessThanConstant(const Value* other) const;
142     virtual TriState greaterThanConstant(const Value* other) const;
143     virtual TriState lessEqualConstant(const Value* other) const;
144     virtual TriState greaterEqualConstant(const Value* other) const;
145     virtual TriState aboveConstant(const Value* other) const;
146     virtual TriState belowConstant(const Value* other) const;
147     virtual TriState aboveEqualConstant(const Value* other) const;
148     virtual TriState belowEqualConstant(const Value* other) const;
149     virtual TriState equalOrUnorderedConstant(const Value* other) const;
150
151     // If the value is a comparison then this returns the inverted form of that comparison, if
152     // possible. It can be impossible for double comparisons, where for example LessThan and
153     // GreaterEqual behave differently. If this returns a value, it is a new value, which must be
154     // either inserted into some block or deleted.
155     Value* invertedCompare(Procedure&) const;
156
157     bool hasInt32() const;
158     int32_t asInt32() const;
159     bool isInt32(int32_t) const;
160     
161     bool hasInt64() const;
162     int64_t asInt64() const;
163     bool isInt64(int64_t) const;
164
165     bool hasInt() const;
166     int64_t asInt() const;
167     bool isInt(int64_t value) const;
168
169     bool hasIntPtr() const;
170     intptr_t asIntPtr() const;
171     bool isIntPtr(intptr_t) const;
172
173     bool hasDouble() const;
174     double asDouble() const;
175     bool isEqualToDouble(double) const; // We say "isEqualToDouble" because "isDouble" would be a bit equality.
176
177     bool hasFloat() const;
178     float asFloat() const;
179
180     bool hasNumber() const;
181     template<typename T> bool representableAs() const;
182     template<typename T> T asNumber() const;
183
184     // Booleans in B3 are Const32(0) or Const32(1). So this is true if the type is Int32 and the only
185     // possible return values are 0 or 1. It's OK for this method to conservatively return false.
186     bool returnsBool() const;
187
188     bool isNegativeZero() const;
189
190     TriState asTriState() const;
191     bool isLikeZero() const { return asTriState() == FalseTriState; }
192     bool isLikeNonZero() const { return asTriState() == TrueTriState; }
193
194     Effects effects() const;
195
196     // This returns a ValueKey that describes that this Value returns when it executes. Returns an
197     // empty ValueKey if this Value is impure. Note that an operation that returns Void could still
198     // have a non-empty ValueKey. This happens for example with Check operations.
199     ValueKey key() const;
200
201     // Makes sure that none of the children are Identity's. If a child points to Identity, this will
202     // repoint it at the Identity's child. For simplicity, this will follow arbitrarily long chains
203     // of Identity's.
204     void performSubstitution();
205
206 protected:
207     virtual void dumpChildren(CommaPrinter&, PrintStream&) const;
208     virtual void dumpMeta(CommaPrinter&, PrintStream&) const;
209
210 private:
211     friend class Procedure;
212
213     // Checks that this opcode is valid for use with B3::Value.
214 #if ASSERT_DISABLED
215     static void checkOpcode(Opcode) { }
216 #else
217     static void checkOpcode(Opcode);
218 #endif
219
220 protected:
221     enum CheckedOpcodeTag { CheckedOpcode };
222     
223     // Instantiate values via Procedure.
224     // This form requires specifying the type explicitly:
225     template<typename... Arguments>
226     explicit Value(unsigned index, CheckedOpcodeTag, Opcode opcode, Type type, Origin origin, Value* firstChild, Arguments... arguments)
227         : m_index(index)
228         , m_opcode(opcode)
229         , m_type(type)
230         , m_origin(origin)
231         , m_children{ firstChild, arguments... }
232     {
233     }
234     // This form is for specifying the type explicitly when the opcode has no children:
235     explicit Value(unsigned index, CheckedOpcodeTag, Opcode opcode, Type type, Origin origin)
236         : m_index(index)
237         , m_opcode(opcode)
238         , m_type(type)
239         , m_origin(origin)
240     {
241     }
242     // This form is for those opcodes that can infer their type from the opcode and first child:
243     template<typename... Arguments>
244     explicit Value(unsigned index, CheckedOpcodeTag, Opcode opcode, Origin origin, Value* firstChild)
245         : m_index(index)
246         , m_opcode(opcode)
247         , m_type(typeFor(opcode, firstChild))
248         , m_origin(origin)
249         , m_children{ firstChild }
250     {
251     }
252     // This form is for those opcodes that can infer their type from the opcode and first and second child:
253     template<typename... Arguments>
254     explicit Value(unsigned index, CheckedOpcodeTag, Opcode opcode, Origin origin, Value* firstChild, Value* secondChild, Arguments... arguments)
255         : m_index(index)
256         , m_opcode(opcode)
257         , m_type(typeFor(opcode, firstChild, secondChild))
258         , m_origin(origin)
259         , m_children{ firstChild, secondChild, arguments... }
260     {
261     }
262     // This form is for those opcodes that can infer their type from the opcode alone, and that don't
263     // take any arguments:
264     explicit Value(unsigned index, CheckedOpcodeTag, Opcode opcode, Origin origin)
265         : m_index(index)
266         , m_opcode(opcode)
267         , m_type(typeFor(opcode, nullptr))
268         , m_origin(origin)
269     {
270     }
271     // Use this form for varargs.
272     explicit Value(unsigned index, CheckedOpcodeTag, Opcode opcode, Type type, Origin origin, const AdjacencyList& children)
273         : m_index(index)
274         , m_opcode(opcode)
275         , m_type(type)
276         , m_origin(origin)
277         , m_children(children)
278     {
279     }
280     explicit Value(unsigned index, CheckedOpcodeTag, Opcode opcode, Type type, Origin origin, AdjacencyList&& children)
281         : m_index(index)
282         , m_opcode(opcode)
283         , m_type(type)
284         , m_origin(origin)
285         , m_children(WTFMove(children))
286     {
287     }
288
289     // This is the constructor you end up actually calling, if you're instantiating Value
290     // directly.
291     template<typename... Arguments>
292     explicit Value(unsigned index, Opcode opcode, Arguments&&... arguments)
293         : Value(index, CheckedOpcode, opcode, std::forward<Arguments>(arguments)...)
294     {
295         checkOpcode(opcode);
296     }
297
298 private:
299     friend class CheckValue; // CheckValue::convertToAdd() modifies m_opcode.
300     
301     static Type typeFor(Opcode, Value* firstChild, Value* secondChild = nullptr);
302
303     // This group of fields is arranged to fit in 64 bits.
304     unsigned m_index;
305     Opcode m_opcode;
306     Type m_type;
307     
308     Origin m_origin;
309     AdjacencyList m_children;
310
311 public:
312     BasicBlock* owner { nullptr }; // computed by Procedure::resetValueOwners().
313 };
314
315 class DeepValueDump {
316 public:
317     DeepValueDump(const Procedure& proc, const Value* value)
318         : m_proc(proc)
319         , m_value(value)
320     {
321     }
322
323     void dump(PrintStream& out) const
324     {
325         if (m_value)
326             m_value->deepDump(m_proc, out);
327         else
328             out.print("<null>");
329     }
330
331 private:
332     const Procedure& m_proc;
333     const Value* m_value;
334 };
335
336 inline DeepValueDump deepDump(const Procedure& proc, const Value* value)
337 {
338     return DeepValueDump(proc, value);
339 }
340
341 } } // namespace JSC::B3
342
343 #endif // ENABLE(B3_JIT)
344
345 #endif // B3Value_h
346