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