c68aabb0db7ac81582451a43b7d5d5dcee3824fb
[WebKit-https.git] / Source / JavaScriptCore / b3 / B3Opcode.h
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 "B3Type.h"
31 #include <wtf/Optional.h>
32 #include <wtf/StdLibExtras.h>
33
34 namespace JSC { namespace B3 {
35
36 // Warning: In B3, an Opcode is just one part of a Kind. Kind is used the way that an opcode
37 // would be used in simple IRs. See B3Kind.h.
38
39 enum Opcode : int16_t {
40     // A no-op that returns Void, useful for when you want to remove a value.
41     Nop,
42     
43     // Polymorphic identity, usable with any value type.
44     Identity,
45
46     // Constants. Use the ConstValue* classes. Constants exist in the control flow, so that we can
47     // reason about where we would construct them. Large constants are expensive to create.
48     Const32,
49     Const64,
50     ConstDouble,
51     ConstFloat,
52
53     // B3 supports non-SSA variables. These are accessed using Get and Set opcodes. Use the
54     // VariableValue class. It's a good idea to run fixSSA() to turn these into SSA. The
55     // optimizer will do that eventually, but if your input tends to use these opcodes, you
56     // should run fixSSA() directly before launching the optimizer.
57     Set,
58     Get,
59
60     // Gets the base address of a StackSlot.
61     SlotBase,
62
63     // The magical argument register. This is viewed as executing at the top of the program
64     // regardless of where in control flow you put it, and the compiler takes care to ensure that we
65     // don't clobber the value by register allocation or calls (either by saving the argument to the
66     // stack or preserving it in a callee-save register). Use the ArgumentRegValue class. The return
67     // type is either pointer() (for GPRs) or Double (for FPRs).
68     ArgumentReg,
69
70     // The frame pointer. You can put this anywhere in control flow but it will always yield the
71     // frame pointer, with a caveat: if our compiler changes the frame pointer temporarily for some
72     // silly reason, the FramePointer intrinsic will return where the frame pointer *should* be not
73     // where it happens to be right now.
74     FramePointer,
75
76     // Polymorphic math, usable with any value type.
77     Add,
78     Sub,
79     Mul,
80     Div, // All bets are off as to what will happen when you execute this for -2^31/-1 and x/0.
81     UDiv,
82     Mod, // All bets are off as to what will happen when you execute this for -2^31%-1 and x%0.
83     UMod,
84
85
86     // Polymorphic negation. Note that we only need this for floating point, since integer negation
87     // is exactly like Sub(0, x). But that's not true for floating point. Sub(0, 0) is 0, while
88     // Neg(0) is -0. Also, we canonicalize Sub(0, x) into Neg(x) in case of integers.
89     Neg,
90
91     // Integer math.
92     BitAnd,
93     BitOr,
94     BitXor,
95     Shl,
96     SShr, // Arithmetic Shift.
97     ZShr, // Logical Shift.
98     RotR, // Rotate Right.
99     RotL, // Rotate Left.
100     Clz, // Count leading zeros.
101
102     // Floating point math.
103     Abs,
104     Ceil,
105     Floor,
106     Sqrt,
107
108     // Casts and such.
109     // Bitwise Cast of Double->Int64 or Int64->Double
110     BitwiseCast,
111     // Takes and returns Int32:
112     SExt8,
113     SExt16,
114     // Takes Int32 and returns Int64:
115     SExt32,
116     ZExt32,
117     // Does a bitwise truncation of Int64->Int32 and Double->Float:
118     Trunc,
119     // Takes ints and returns floating point value. Note that we don't currently provide the opposite operation,
120     // because double-to-int conversions have weirdly different semantics on different platforms. Use
121     // a patchpoint if you need to do that.
122     IToD,
123     IToF,
124     // Convert between double and float.
125     FloatToDouble,
126     DoubleToFloat,
127
128     // Polymorphic comparisons, usable with any value type. Returns int32 0 or 1. Note that "Not"
129     // is just Equal(x, 0), and "ToBoolean" is just NotEqual(x, 0).
130     Equal,
131     NotEqual,
132     LessThan,
133     GreaterThan,
134     LessEqual,
135     GreaterEqual,
136
137     // Integer comparisons. Returns int32 0 or 1.
138     Above,
139     Below,
140     AboveEqual,
141     BelowEqual,
142
143     // Unordered floating point compare: values are equal or either one is NaN.
144     EqualOrUnordered,
145
146     // SSA form of conditional move. The first child is evaluated for truthiness. If true, the second child
147     // is returned. Otherwise, the third child is returned.
148     Select,
149
150     // Memory loads. Opcode indicates how we load and the loaded type. These use MemoryValue.
151     // These return Int32:
152     Load8Z,
153     Load8S,
154     Load16Z,
155     Load16S,
156     // This returns whatever the return type is:
157     Load,
158
159     // Memory stores. Opcode indicates how the value is stored. These use MemoryValue.
160     // These take an Int32 value:
161     Store8,
162     Store16,
163     // This is a polymorphic store for Int32, Int64, Float, and Double.
164     Store,
165
166     // This is used to compute the actual address of a Wasm memory operation. It takes an IntPtr
167     // and a pinned register then computes the appropriate IntPtr address. For the use-case of
168     // Wasm it is important that the first child initially be a ZExt32 so the top bits are cleared.
169     // We do WasmAddress(ZExt32(ptr), ...) so that we can avoid generating extraneous moves in Air.
170     WasmAddress,
171     
172     // This is used to represent standalone fences - i.e. fences that are not part of other
173     // instructions. It's expressive enough to expose mfence on x86 and dmb ish/ishst on ARM. On
174     // x86, it also acts as a compiler store-store fence in those cases where it would have been a
175     // dmb ishst on ARM.
176     Fence,
177
178     // This is a regular ordinary C function call, using the system C calling convention. Make sure
179     // that the arguments are passed using the right types. The first argument is the callee.
180     CCall,
181
182     // This is a patchpoint. Use the PatchpointValue class. This is viewed as behaving like a call,
183     // but only emits code via a code generation callback. That callback gets to emit code inline.
184     // You can pass a stackmap along with constraints on how each stackmap argument must be passed.
185     // It's legal to request that a stackmap argument is in some register and it's legal to request
186     // that a stackmap argument is at some offset from the top of the argument passing area on the
187     // stack.
188     Patchpoint,
189
190     // Checked math. Use the CheckValue class. Like a Patchpoint, this takes a code generation
191     // callback. That callback gets to emit some code after the epilogue, and gets to link the jump
192     // from the check, and the choice of registers. You also get to supply a stackmap. Note that you
193     // are not allowed to jump back into the mainline code from your slow path, since the compiler
194     // will assume that the execution of these instructions proves that overflow didn't happen. For
195     // example, if you have two CheckAdd's:
196     //
197     // a = CheckAdd(x, y)
198     // b = CheckAdd(x, y)
199     //
200     // Then it's valid to change this to:
201     //
202     // a = CheckAdd(x, y)
203     // b = Identity(a)
204     //
205     // This is valid regardless of the callbacks used by the two CheckAdds. They may have different
206     // callbacks. Yet, this transformation is valid even if they are different because we know that
207     // after the first CheckAdd executes, the second CheckAdd could not have possibly taken slow
208     // path. Therefore, the second CheckAdd's callback is irrelevant.
209     //
210     // Note that the first two children of these operations have ValueRep's as input constraints but do
211     // not have output constraints.
212     CheckAdd,
213     CheckSub,
214     CheckMul,
215
216     // Check that side-exits. Use the CheckValue class. Like CheckAdd and friends, this has a
217     // stackmap with a generation callback. This takes an int argument that this branches on, with
218     // full branch fusion in the instruction selector. A true value jumps to the generator's slow
219     // path. Note that the predicate child is has both an input ValueRep. The input constraint must be
220     // WarmAny. It will not have an output constraint.
221     Check,
222
223     // Special Wasm opcode that takes a Int32, a special pinned gpr and an offset. This node exists
224     // to allow us to CSE WasmBoundsChecks if both use the same pointer and one dominates the other.
225     // Without some such node B3 would not have enough information about the inner workings of wasm
226     // to be able to perform such optimizations.
227     WasmBoundsCheck,
228
229     // SSA support, in the style of DFG SSA.
230     Upsilon, // This uses the UpsilonValue class.
231     Phi,
232
233     // Jump.
234     Jump,
235     
236     // Polymorphic branch, usable with any integer type. Branches if not equal to zero. The 0-index
237     // successor is the true successor.
238     Branch,
239
240     // Switch. Switches over either Int32 or Int64. Uses the SwitchValue class.
241     Switch,
242     
243     // Multiple entrypoints are supported via the EntrySwitch operation. Place this in the root
244     // block and list the entrypoints as the successors. All blocks backwards-reachable from
245     // EntrySwitch are duplicated for each entrypoint.
246     EntrySwitch,
247
248     // Return. Note that B3 procedures don't know their return type, so this can just return any
249     // type.
250     Return,
251
252     // This is a terminal that indicates that we will never get here.
253     Oops
254 };
255
256 inline bool isCheckMath(Opcode opcode)
257 {
258     switch (opcode) {
259     case CheckAdd:
260     case CheckSub:
261     case CheckMul:
262         return true;
263     default:
264         return false;
265     }
266 }
267
268 Optional<Opcode> invertedCompare(Opcode, Type);
269
270 inline Opcode constPtrOpcode()
271 {
272     if (is64Bit())
273         return Const64;
274     return Const32;
275 }
276
277 inline bool isConstant(Opcode opcode)
278 {
279     switch (opcode) {
280     case Const32:
281     case Const64:
282     case ConstDouble:
283     case ConstFloat:
284         return true;
285     default:
286         return false;
287     }
288 }
289
290 inline bool isDefinitelyTerminal(Opcode opcode)
291 {
292     switch (opcode) {
293     case Jump:
294     case Branch:
295     case Switch:
296     case Oops:
297     case Return:
298         return true;
299     default:
300         return false;
301     }
302 }
303
304 } } // namespace JSC::B3
305
306 namespace WTF {
307
308 class PrintStream;
309
310 JS_EXPORT_PRIVATE void printInternal(PrintStream&, JSC::B3::Opcode);
311
312 } // namespace WTF
313
314 #endif // ENABLE(B3_JIT)