1/*
2 * Copyright (C) 2015-2016 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#pragma once
27
28#if ENABLE(B3_JIT)
29
30#include "B3CheckValue.h"
31#include "B3Const32Value.h"
32#include "B3Const64Value.h"
33#include "B3ConstDoubleValue.h"
34#include "B3ConstFloatValue.h"
35#include "B3PatchpointValue.h"
36#include "B3PhiChildren.h"
37#include "B3Procedure.h"
38#include "B3Value.h"
39#include <wtf/GraphNodeWorklist.h>
40
41namespace JSC { namespace B3 {
42
43template<typename BottomProvider>
44void Value::replaceWithBottom(const BottomProvider& bottomProvider)
45{
46 if (m_type == Void) {
47 replaceWithNop();
48 return;
49 }
50
51 if (isConstant())
52 return;
53
54 replaceWithIdentity(bottomProvider(m_origin, m_type));
55}
56
57template<typename T>
58inline T* Value::as()
59{
60 if (T::accepts(kind()))
61 return static_cast<T*>(this);
62 return nullptr;
63}
64
65template<typename T>
66inline const T* Value::as() const
67{
68 return const_cast<Value*>(this)->as<T>();
69}
70
71inline bool Value::isConstant() const
72{
73 return B3::isConstant(opcode());
74}
75
76inline bool Value::isInteger() const
77{
78 return type() == Int32 || type() == Int64;
79}
80
81inline bool Value::hasInt32() const
82{
83 return !!as<Const32Value>();
84}
85
86inline int32_t Value::asInt32() const
87{
88 return as<Const32Value>()->value();
89}
90
91inline bool Value::isInt32(int32_t value) const
92{
93 return hasInt32() && asInt32() == value;
94}
95
96inline bool Value::hasInt64() const
97{
98 return !!as<Const64Value>();
99}
100
101inline int64_t Value::asInt64() const
102{
103 return as<Const64Value>()->value();
104}
105
106inline bool Value::isInt64(int64_t value) const
107{
108 return hasInt64() && asInt64() == value;
109}
110
111inline bool Value::hasInt() const
112{
113 return hasInt32() || hasInt64();
114}
115
116inline int64_t Value::asInt() const
117{
118 return hasInt32() ? asInt32() : asInt64();
119}
120
121inline bool Value::isInt(int64_t value) const
122{
123 return hasInt() && asInt() == value;
124}
125
126inline bool Value::hasIntPtr() const
127{
128 if (is64Bit())
129 return hasInt64();
130 return hasInt32();
131}
132
133inline intptr_t Value::asIntPtr() const
134{
135 if (is64Bit())
136 return asInt64();
137 return asInt32();
138}
139
140inline bool Value::isIntPtr(intptr_t value) const
141{
142 return hasIntPtr() && asIntPtr() == value;
143}
144
145inline bool Value::hasDouble() const
146{
147 return !!as<ConstDoubleValue>();
148}
149
150inline double Value::asDouble() const
151{
152 return as<ConstDoubleValue>()->value();
153}
154
155inline bool Value::isEqualToDouble(double value) const
156{
157 return hasDouble() && asDouble() == value;
158}
159
160inline bool Value::hasFloat() const
161{
162 return !!as<ConstFloatValue>();
163}
164
165inline float Value::asFloat() const
166{
167 return as<ConstFloatValue>()->value();
168}
169
170inline bool Value::hasNumber() const
171{
172 return hasInt() || hasDouble() || hasFloat();
173}
174
175inline bool Value::isNegativeZero() const
176{
177 if (hasDouble()) {
178 double value = asDouble();
179 return !value && std::signbit(value);
180 }
181 if (hasFloat()) {
182 float value = asFloat();
183 return !value && std::signbit(value);
184 }
185 return false;
186}
187
188template<typename T>
189inline bool Value::isRepresentableAs() const
190{
191 switch (opcode()) {
192 case Const32:
193 return B3::isRepresentableAs<T>(asInt32());
194 case Const64:
195 return B3::isRepresentableAs<T>(asInt64());
196 case ConstDouble:
197 return B3::isRepresentableAs<T>(asDouble());
198 case ConstFloat:
199 return B3::isRepresentableAs<T>(asFloat());
200 default:
201 return false;
202 }
203}
204
205template<typename T>
206inline T Value::asNumber() const
207{
208 switch (opcode()) {
209 case Const32:
210 return static_cast<T>(asInt32());
211 case Const64:
212 return static_cast<T>(asInt64());
213 case ConstDouble:
214 return static_cast<T>(asDouble());
215 case ConstFloat:
216 return static_cast<T>(asFloat());
217 default:
218 return T();
219 }
220}
221
222template<typename Functor>
223void Value::walk(const Functor& functor, PhiChildren* phiChildren)
224{
225 GraphNodeWorklist<Value*> worklist;
226 worklist.push(this);
227 while (Value* value = worklist.pop()) {
228 WalkStatus status = functor(value);
229 switch (status) {
230 case Continue:
231 if (value->opcode() == Phi) {
232 if (phiChildren)
233 worklist.pushAll(phiChildren->at(value).values());
234 } else
235 worklist.pushAll(value->children());
236 break;
237 case IgnoreChildren:
238 break;
239 case Stop:
240 return;
241 }
242 }
243}
244
245} } // namespace JSC::B3
246
247#endif // ENABLE(B3_JIT)
248