1/*
2 * Copyright (C) 2014 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(DFG_JIT)
29
30namespace JSC {
31
32class CallFrame;
33class JSGlobalObject;
34using EncodedJSValue = int64_t;
35
36namespace DFG {
37
38// Arith::Mode describes the mode of an arithmetic operation that speculates integer.
39// Note that not all modes are valid for all operations.
40namespace Arith {
41enum Mode {
42 NotSet, // Arithmetic mode is either not relevant because we're using doubles anyway or we are at a phase in compilation where we don't know what we're doing, yet. Should never see this after FixupPhase except for nodes that take doubles as inputs already.
43 Unchecked, // Don't check anything and just do the direct hardware operation.
44 CheckOverflow, // Check for overflow but don't bother with negative zero.
45 CheckOverflowAndNegativeZero, // Check for both overflow and negative zero.
46 DoOverflow // Up-convert to the smallest type that soundly represents all possible results after input type speculation.
47};
48
49// Define the type of operation the rounding operation will perform.
50enum class RoundingMode {
51 Int32, // The round operation produces a integer and -0 is considered as 0.
52 Int32WithNegativeZeroCheck, // The round operation produces a integer and checks for -0.
53 Double // The round operation produce a double. The result can be -0, NaN or (+/-)Infinity.
54};
55
56
57// This macro defines a set of information about all known arith unary generic node.
58#define FOR_EACH_DFG_ARITH_UNARY_OP(macro) \
59 macro(Sin, sin) \
60 macro(Sinh, sinh) \
61 macro(Cos, cos) \
62 macro(Cosh, cosh) \
63 macro(Tan, tan) \
64 macro(Tanh, tanh) \
65 macro(ASin, asin) \
66 macro(ASinh, asinh) \
67 macro(ACos, acos) \
68 macro(ACosh, acosh) \
69 macro(ATan, atan) \
70 macro(ATanh, atanh) \
71 macro(Log, log) \
72 macro(Log10, log10) \
73 macro(Log1p, log1p) \
74 macro(Log2, log2) \
75 macro(Cbrt, cbrt) \
76 macro(Exp, exp) \
77 macro(Expm1, expm1) \
78
79enum class UnaryType : uint32_t {
80#define DFG_ARITH_UNARY_ENUM(capitalizedName, lowerName) capitalizedName,
81 FOR_EACH_DFG_ARITH_UNARY_OP(DFG_ARITH_UNARY_ENUM)
82#undef DFG_ARITH_UNARY_ENUM
83};
84
85typedef double (*UnaryFunction)(double);
86typedef double (*UnaryOperation)(JSGlobalObject*, EncodedJSValue);
87
88} // namespace Arith
89
90inline bool doesOverflow(Arith::Mode mode)
91{
92 switch (mode) {
93 case Arith::NotSet:
94 ASSERT_NOT_REACHED();
95#if ASSERT_DISABLED
96 FALLTHROUGH;
97#endif
98 case Arith::Unchecked:
99 case Arith::CheckOverflow:
100 case Arith::CheckOverflowAndNegativeZero:
101 return false;
102 case Arith::DoOverflow:
103 return true;
104 }
105 ASSERT_NOT_REACHED();
106 return true;
107}
108
109// It's only valid to call this once you've determined that you don't need to *do*
110// overflow. For most nodes, that's implicit.
111inline bool shouldCheckOverflow(Arith::Mode mode)
112{
113 switch (mode) {
114 case Arith::NotSet:
115 case Arith::DoOverflow:
116 ASSERT_NOT_REACHED();
117 return true;
118 case Arith::Unchecked:
119 return false;
120 case Arith::CheckOverflow:
121 case Arith::CheckOverflowAndNegativeZero:
122 return true;
123 }
124 ASSERT_NOT_REACHED();
125 return true;
126}
127
128inline bool shouldCheckNegativeZero(Arith::Mode mode)
129{
130 switch (mode) {
131 case Arith::NotSet:
132 case Arith::DoOverflow:
133 ASSERT_NOT_REACHED();
134 return true;
135 case Arith::Unchecked:
136 case Arith::CheckOverflow:
137 return false;
138 case Arith::CheckOverflowAndNegativeZero:
139 return true;
140 }
141 ASSERT_NOT_REACHED();
142 return true;
143}
144
145inline bool subsumes(Arith::Mode earlier, Arith::Mode later)
146{
147 switch (earlier) {
148 case Arith::CheckOverflow:
149 switch (later) {
150 case Arith::Unchecked:
151 case Arith::CheckOverflow:
152 return true;
153 default:
154 return false;
155 }
156 case Arith::CheckOverflowAndNegativeZero:
157 switch (later) {
158 case Arith::Unchecked:
159 case Arith::CheckOverflow:
160 case Arith::CheckOverflowAndNegativeZero:
161 return true;
162 default:
163 return false;
164 }
165 default:
166 return earlier == later;
167 }
168}
169
170inline bool producesInteger(Arith::RoundingMode mode)
171{
172 return mode == Arith::RoundingMode::Int32WithNegativeZeroCheck || mode == Arith::RoundingMode::Int32;
173}
174
175inline bool shouldCheckNegativeZero(Arith::RoundingMode mode)
176{
177 return mode == Arith::RoundingMode::Int32WithNegativeZeroCheck;
178}
179
180Arith::UnaryFunction arithUnaryFunction(Arith::UnaryType);
181Arith::UnaryOperation arithUnaryOperation(Arith::UnaryType);
182
183} } // namespace JSC::DFG
184
185namespace WTF {
186
187class PrintStream;
188void printInternal(PrintStream&, JSC::DFG::Arith::Mode);
189void printInternal(PrintStream&, JSC::DFG::Arith::RoundingMode);
190void printInternal(PrintStream&, JSC::DFG::Arith::UnaryType);
191
192} // namespace WTF
193
194#endif // ENABLE(DFG_JIT)
195