[JSC] Add signExt() to FTLB3Output
[WebKit-https.git] / Source / JavaScriptCore / ftl / FTLB3Output.h
1 /*
2  * Copyright (C) 2013-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 FTLB3Output_h
27 #define FTLB3Output_h
28
29 #include "DFGCommon.h"
30
31 #if ENABLE(FTL_JIT)
32 #if FTL_USES_B3
33
34 #include "B3ArgumentRegValue.h"
35 #include "B3BasicBlockInlines.h"
36 #include "B3CCallValue.h"
37 #include "B3Compilation.h"
38 #include "B3Const32Value.h"
39 #include "B3ConstPtrValue.h"
40 #include "B3ControlValue.h"
41 #include "B3MemoryValue.h"
42 #include "B3Procedure.h"
43 #include "B3StackSlotValue.h"
44 #include "B3SwitchValue.h"
45 #include "B3UpsilonValue.h"
46 #include "B3ValueInlines.h"
47 #include "FTLAbbreviatedTypes.h"
48 #include "FTLAbstractHeapRepository.h"
49 #include "FTLCommonValues.h"
50 #include "FTLState.h"
51 #include "FTLSwitchCase.h"
52 #include "FTLTypedPointer.h"
53 #include "FTLValueFromBlock.h"
54 #include "FTLWeight.h"
55 #include "FTLWeightedTarget.h"
56 #include <wtf/StringPrintStream.h>
57
58 // FIXME: remove this once everything can be generated through B3.
59 #if COMPILER(CLANG)
60 #pragma clang diagnostic push
61 #pragma clang diagnostic ignored "-Wmissing-noreturn"
62 #pragma clang diagnostic ignored "-Wunused-parameter"
63 #endif // COMPILER(CLANG)
64
65 namespace JSC {
66
67 namespace DFG { struct Node; }
68
69 namespace FTL {
70
71 enum Scale { ScaleOne, ScaleTwo, ScaleFour, ScaleEight, ScalePtr };
72
73 class Output : public CommonValues {
74 public:
75     Output(State&);
76     ~Output();
77
78     void initialize(AbstractHeapRepository&);
79
80     LBasicBlock newBlock(const char* name = "")
81     {
82         UNUSED_PARAM(name);
83         return m_proc.addBlock();
84     }
85
86     LBasicBlock insertNewBlocksBefore(LBasicBlock nextBlock)
87     {
88         LBasicBlock lastNextBlock = m_nextBlock;
89         m_nextBlock = nextBlock;
90         return lastNextBlock;
91     }
92
93     LBasicBlock appendTo(LBasicBlock, LBasicBlock nextBlock);
94     void appendTo(LBasicBlock);
95
96     void setOrigin(DFG::Node* node) { m_origin = node; }
97     B3::Origin origin() { return B3::Origin(m_origin); }
98
99     LValue framePointer() { return m_block->appendNew<B3::Value>(m_proc, B3::FramePointer, origin()); }
100
101     LValue lockedStackSlot(size_t bytes);
102
103     LValue constBool(bool value) { return m_block->appendNew<B3::Const32Value>(m_proc, origin(), value); }
104     LValue constInt32(int32_t value) { return m_block->appendNew<B3::Const32Value>(m_proc, origin(), value); }
105     template<typename T>
106     LValue constIntPtr(T* value) { return m_block->appendNew<B3::ConstPtrValue>(m_proc, origin(), value); }
107     template<typename T>
108     LValue constIntPtr(T value) { return m_block->appendNew<B3::ConstPtrValue>(m_proc, origin(), value); }
109     LValue constInt64(int64_t value) { return m_block->appendNew<B3::Const64Value>(m_proc, origin(), value); }
110     LValue constDouble(double value) { return m_block->appendNew<B3::ConstDoubleValue>(m_proc, origin(), value); }
111
112     LValue phi(LType type) { return m_block->appendNew<B3::Value>(m_proc, B3::Phi, type, origin()); }
113     template<typename... Params>
114     LValue phi(LType, ValueFromBlock, Params... theRest);
115     template<typename VectorType>
116     LValue phi(LType, const VectorType&);
117     void addIncomingToPhi(LValue phi, ValueFromBlock);
118     template<typename... Params>
119     void addIncomingToPhi(LValue phi, ValueFromBlock, Params... theRest);
120
121     LValue add(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Add, origin(), left, right); }
122     LValue sub(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Sub, origin(), left, right); }
123     LValue mul(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Mul, origin(), left, right); }
124     LValue div(LValue left, LValue right) { CRASH(); }
125     LValue rem(LValue left, LValue right) { CRASH(); }
126     LValue neg(LValue value)
127     {
128         LValue zero = m_block->appendIntConstant(m_proc, origin(), value->type(), 0);
129         return sub(zero, value);
130     }
131
132     LValue doubleAdd(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Add, origin(), left, right); }
133     LValue doubleSub(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Sub, origin(), left, right); }
134     LValue doubleMul(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Mul, origin(), left, right); }
135     LValue doubleDiv(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Div, origin(), left, right); }
136     LValue doubleRem(LValue left, LValue right) { CRASH(); }
137     LValue doubleNeg(LValue value)
138     {
139         return sub(doubleZero, value);
140     }
141
142     LValue bitAnd(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::BitAnd, origin(), left, right); }
143     LValue bitOr(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::BitOr, origin(), left, right); }
144     LValue bitXor(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::BitXor, origin(), left, right); }
145     LValue shl(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Shl, origin(), left, castToInt32(right)); }
146     LValue aShr(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::SShr, origin(), left, castToInt32(right)); }
147     LValue lShr(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::ZShr, origin(), left, castToInt32(right)); }
148     LValue bitNot(LValue);
149
150     LValue ceil64(LValue operand) { CRASH(); }
151     LValue ctlz32(LValue operand) { return m_block->appendNew<B3::Value>(m_proc, B3::Clz, origin(), operand); }
152     LValue addWithOverflow32(LValue left, LValue right) { CRASH(); }
153     LValue subWithOverflow32(LValue left, LValue right) { CRASH(); }
154     LValue mulWithOverflow32(LValue left, LValue right) { CRASH(); }
155     LValue addWithOverflow64(LValue left, LValue right) { CRASH(); }
156     LValue subWithOverflow64(LValue left, LValue right) { CRASH(); }
157     LValue mulWithOverflow64(LValue left, LValue right) { CRASH(); }
158     LValue doubleAbs(LValue value) { CRASH(); }
159
160     LValue doubleSin(LValue value) { return callWithoutSideEffects(B3::Double, sin, value); }
161     LValue doubleCos(LValue value) { return callWithoutSideEffects(B3::Double, cos, value); }
162
163     LValue doublePow(LValue xOperand, LValue yOperand) { return callWithoutSideEffects(B3::Double, pow, xOperand, yOperand); }
164
165     LValue doublePowi(LValue xOperand, LValue yOperand) { CRASH(); }
166
167     LValue doubleSqrt(LValue value) { return m_block->appendNew<B3::Value>(m_proc, B3::Sqrt, origin(), value); }
168
169     LValue doubleLog(LValue value) { return callWithoutSideEffects(B3::Double, log, value); }
170
171     static bool hasSensibleDoubleToInt() { CRASH(); }
172     LValue sensibleDoubleToInt(LValue) { CRASH(); }
173
174     LValue signExt32To64(LValue value) { return m_block->appendNew<B3::Value>(m_proc, B3::SExt32, origin(), value); }
175     LValue zeroExt(LValue value, LType type) { return m_block->appendNew<B3::Value>(m_proc, B3::ZExt32, type, origin(), value); }
176     LValue zeroExtPtr(LValue value) { return zeroExt(value, B3::Int64); }
177     LValue fpToInt(LValue value, LType type) { CRASH(); }
178     LValue fpToUInt(LValue value, LType type) { CRASH(); }
179     LValue fpToInt32(LValue value) { CRASH(); }
180     LValue fpToUInt32(LValue value) { CRASH(); }
181     LValue intToFP(LValue value, LType type) { CRASH(); }
182     LValue intToDouble(LValue value) { return m_block->appendNew<B3::Value>(m_proc, B3::IToD, origin(), value); }
183     LValue unsignedToFP(LValue value, LType type) { CRASH(); }
184     LValue unsignedToDouble(LValue value) { CRASH(); }
185     LValue intCast(LValue value, LType type) { CRASH(); }
186     LValue castToInt32(LValue value)
187     {
188         return value->type() == B3::Int32 ? value :
189             m_block->appendNew<B3::Value>(m_proc, B3::Trunc, origin(), value);
190     }
191     LValue fpCast(LValue value, LType type) { CRASH(); }
192     LValue intToPtr(LValue value, LType type) { CRASH(); }
193     LValue ptrToInt(LValue value, LType type) { CRASH(); }
194     LValue bitCast(LValue, LType);
195
196     LValue fround(LValue doubleValue) { CRASH(); }
197
198     LValue load(TypedPointer, LType);
199     void store(LValue, TypedPointer);
200
201     LValue load8SignExt32(TypedPointer);
202     LValue load8ZeroExt32(TypedPointer);
203     LValue load16SignExt32(TypedPointer);
204     LValue load16ZeroExt32(TypedPointer);
205     LValue load32(TypedPointer pointer) { return load(pointer, B3::Int32); }
206     LValue load64(TypedPointer pointer) { return load(pointer, B3::Int64); }
207     LValue loadPtr(TypedPointer pointer) { return load(pointer, B3::pointerType()); }
208     LValue loadFloatToDouble(TypedPointer);
209     LValue loadDouble(TypedPointer pointer) { return load(pointer, B3::Double); }
210     void store32(LValue value, TypedPointer pointer) { store(value, pointer); }
211     void store64(LValue value, TypedPointer pointer) { store(value, pointer); }
212     void storePtr(LValue value, TypedPointer pointer) { store(value, pointer); }
213     void storeDouble(LValue value, TypedPointer pointer) { store(value, pointer); }
214
215     LValue addPtr(LValue value, ptrdiff_t immediate = 0)
216     {
217         if (!immediate)
218             return value;
219         return add(value, constIntPtr(immediate));
220     }
221
222     // Construct an address by offsetting base by the requested amount and ascribing
223     // the requested abstract heap to it.
224     TypedPointer address(const AbstractHeap& heap, LValue base, ptrdiff_t offset = 0)
225     {
226         return TypedPointer(heap, addPtr(base, offset));
227     }
228     // Construct an address by offsetting base by the amount specified by the field,
229     // and optionally an additional amount (use this with care), and then creating
230     // a TypedPointer with the given field as the heap.
231     TypedPointer address(LValue base, const AbstractField& field, ptrdiff_t offset = 0)
232     {
233         return address(field, base, offset + field.offset());
234     }
235
236     LValue baseIndex(LValue base, LValue index, Scale, ptrdiff_t offset = 0);
237
238     TypedPointer baseIndex(const AbstractHeap& heap, LValue base, LValue index, Scale scale, ptrdiff_t offset = 0)
239     {
240         return TypedPointer(heap, baseIndex(base, index, scale, offset));
241     }
242     TypedPointer baseIndex(IndexedAbstractHeap& heap, LValue base, LValue index, JSValue indexAsConstant = JSValue(), ptrdiff_t offset = 0)
243     {
244         return heap.baseIndex(*this, base, index, indexAsConstant, offset);
245     }
246
247     TypedPointer absolute(void* address)
248     {
249         return TypedPointer(m_heaps->absolute[address], constIntPtr(address));
250     }
251
252     LValue load8SignExt32(LValue base, const AbstractField& field) { return load8SignExt32(address(base, field)); }
253     LValue load8ZeroExt32(LValue base, const AbstractField& field) { return load8ZeroExt32(address(base, field)); }
254     LValue load16SignExt32(LValue base, const AbstractField& field) { return load16SignExt32(address(base, field)); }
255     LValue load16ZeroExt32(LValue base, const AbstractField& field) { return load16ZeroExt32(address(base, field)); }
256     LValue load32(LValue base, const AbstractField& field) { return load32(address(base, field)); }
257     LValue load64(LValue base, const AbstractField& field) { return load64(address(base, field)); }
258     LValue loadPtr(LValue base, const AbstractField& field) { return loadPtr(address(base, field)); }
259     LValue loadDouble(LValue base, const AbstractField& field) { return loadDouble(address(base, field)); }
260     void store32(LValue value, LValue base, const AbstractField& field) { store32(value, address(base, field)); }
261     void store64(LValue value, LValue base, const AbstractField& field) { store64(value, address(base, field)); }
262     void storePtr(LValue value, LValue base, const AbstractField& field) { storePtr(value, address(base, field)); }
263     void storeDouble(LValue value, LValue base, const AbstractField& field) { storeDouble(value, address(base, field)); }
264
265     // FIXME: Explore adding support for value range constraints to B3. Maybe it could be as simple as having
266     // a load instruction that guarantees that its result is non-negative.
267     // https://bugs.webkit.org/show_bug.cgi?id=151458
268     void ascribeRange(LValue, const ValueRange&) { }
269     LValue nonNegative32(LValue loadInstruction) { return loadInstruction; }
270     LValue load32NonNegative(TypedPointer pointer) { return load32(pointer); }
271     LValue load32NonNegative(LValue base, const AbstractField& field) { return load32(base, field); }
272
273     LValue equal(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Equal, origin(), left, right); }
274     LValue notEqual(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::NotEqual, origin(), left, right); }
275     LValue above(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Above, origin(), left, right); }
276     LValue aboveOrEqual(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::AboveEqual, origin(), left, right); }
277     LValue below(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Below, origin(), left, right); }
278     LValue belowOrEqual(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::BelowEqual, origin(), left, right); }
279     LValue greaterThan(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::GreaterThan, origin(), left, right); }
280     LValue greaterThanOrEqual(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::GreaterEqual, origin(), left, right); }
281     LValue lessThan(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::LessThan, origin(), left, right); }
282     LValue lessThanOrEqual(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::LessEqual, origin(), left, right); }
283
284     LValue doubleEqual(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Equal, origin(), left, right); }
285     LValue doubleNotEqualOrUnordered(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::NotEqual, origin(), left, right); }
286     LValue doubleLessThan(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::LessThan, origin(), left, right); }
287     LValue doubleLessThanOrEqual(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::LessEqual, origin(), left, right); }
288     LValue doubleGreaterThan(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::GreaterThan, origin(), left, right); }
289     LValue doubleGreaterThanOrEqual(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::GreaterEqual, origin(), left, right); }
290     LValue doubleEqualOrUnordered(LValue left, LValue right) { CRASH(); }
291     LValue doubleNotEqual(LValue left, LValue right) { CRASH(); }
292     LValue doubleLessThanOrUnordered(LValue left, LValue right)
293     {
294         return m_block->appendNew<B3::Value>(
295             m_proc, B3::Equal, origin(),
296             m_block->appendNew<B3::Value>(m_proc, B3::GreaterEqual, origin(), left, right),
297             int32Zero);
298     }
299     LValue doubleLessThanOrEqualOrUnordered(LValue left, LValue right)
300     {
301         return m_block->appendNew<B3::Value>(
302             m_proc, B3::Equal, origin(),
303             m_block->appendNew<B3::Value>(m_proc, B3::GreaterThan, origin(), left, right),
304             int32Zero);
305     }
306     LValue doubleGreaterThanOrUnordered(LValue left, LValue right)
307     {
308         return m_block->appendNew<B3::Value>(
309             m_proc, B3::Equal, origin(),
310             m_block->appendNew<B3::Value>(m_proc, B3::LessEqual, origin(), left, right),
311             int32Zero);
312     }
313     LValue doubleGreaterThanOrEqualOrUnordered(LValue left, LValue right)
314     {
315         return m_block->appendNew<B3::Value>(
316             m_proc, B3::Equal, origin(),
317             m_block->appendNew<B3::Value>(m_proc, B3::LessThan, origin(), left, right),
318             int32Zero);
319     }
320
321     LValue isZero32(LValue value) { return m_block->appendNew<B3::Value>(m_proc, B3::Equal, origin(), value, int32Zero); }
322     LValue notZero32(LValue value) { return m_block->appendNew<B3::Value>(m_proc, B3::NotEqual, origin(), value, int32Zero); }
323     LValue isZero64(LValue value) { return m_block->appendNew<B3::Value>(m_proc, B3::Equal, origin(), value, int64Zero); }
324     LValue notZero64(LValue value) { return m_block->appendNew<B3::Value>(m_proc, B3::NotEqual, origin(), value, int64Zero); }
325     LValue isNull(LValue value) { return isZero64(value); }
326     LValue notNull(LValue value) { return notZero64(value); }
327
328     LValue testIsZero32(LValue value, LValue mask) { return isZero32(bitAnd(value, mask)); }
329     LValue testNonZero32(LValue value, LValue mask) { return notZero32(bitAnd(value, mask)); }
330     LValue testIsZero64(LValue value, LValue mask) { return isZero64(bitAnd(value, mask)); }
331     LValue testNonZero64(LValue value, LValue mask) { return notZero64(bitAnd(value, mask)); }
332     LValue testIsZeroPtr(LValue value, LValue mask) { return isNull(bitAnd(value, mask)); }
333     LValue testNonZeroPtr(LValue value, LValue mask) { return notNull(bitAnd(value, mask)); }
334
335     LValue select(LValue value, LValue taken, LValue notTaken) { return m_block->appendNew<B3::Value>(m_proc, B3::Select, origin(), value, taken, notTaken); }
336     LValue extractValue(LValue aggVal, unsigned index) { CRASH(); }
337
338     LValue fence(LAtomicOrdering ordering = LLVMAtomicOrderingSequentiallyConsistent, SynchronizationScope scope = CrossThread) { CRASH(); }
339     LValue fenceAcqRel() { CRASH(); }
340
341     template<typename VectorType>
342     LValue call(LType type, LValue function, const VectorType& vector) { return m_block->appendNew<B3::CCallValue>(m_proc, type, origin(), B3::Value::AdjacencyList(vector)); }
343     LValue call(LType type, LValue function) { return m_block->appendNew<B3::CCallValue>(m_proc, type, origin()); }
344     LValue call(LType type, LValue function, LValue arg1) { return m_block->appendNew<B3::CCallValue>(m_proc, type, origin(), arg1); }
345     template<typename... Args>
346     LValue call(LType type, LValue function, LValue arg1, Args... args) { return m_block->appendNew<B3::CCallValue>(m_proc, type, origin(), arg1, args...); }
347
348     template<typename FunctionType>
349     LValue operation(FunctionType function) { return constIntPtr(bitwise_cast<void*>(function)); }
350
351     void jump(LBasicBlock destination) { m_block->appendNew<B3::ControlValue>(m_proc, B3::Jump, origin(), B3::FrequentedBlock(destination)); }
352     void branch(LValue condition, LBasicBlock taken, Weight takenWeight, LBasicBlock notTaken, Weight notTakenWeight);
353     void branch(LValue condition, WeightedTarget taken, WeightedTarget notTaken)
354     {
355         branch(condition, taken.target(), taken.weight(), notTaken.target(), notTaken.weight());
356     }
357
358     // Branches to an already-created handler if true, "falls through" if false. Fall-through is
359     // simulated by creating a continuation for you.
360     void check(LValue condition, WeightedTarget taken, Weight notTakenWeight) { CRASH(); }
361
362     // Same as check(), but uses Weight::inverse() to compute the notTakenWeight.
363     void check(LValue condition, WeightedTarget taken) { CRASH(); }
364
365     template<typename VectorType>
366     void switchInstruction(LValue value, const VectorType& cases, LBasicBlock fallThrough, Weight fallThroughWeight) { CRASH(); }
367
368     void ret(LValue value) { m_block->appendNew<B3::ControlValue>(m_proc, B3::Return, origin(), value); }
369
370     void unreachable() { m_block->appendNew<B3::ControlValue>(m_proc, B3::Oops, origin()); }
371
372     template<typename Functor>
373     void speculate(LValue value, const StackmapArgumentList& arguments, const Functor& functor)
374     {
375         B3::CheckValue* check = speculate(value, arguments);
376         check->setGenerator(functor);
377     }
378
379     B3::CheckValue* speculate(LValue value, const StackmapArgumentList& arguments)
380     {
381         B3::CheckValue* check = speculate(value);
382         for (LValue value : arguments)
383             check->append(B3::ConstrainedValue(value));
384         return check;
385     }
386
387     B3::CheckValue* speculate(LValue value)
388     {
389         return m_block->appendNew<B3::CheckValue>(m_proc, B3::Check, origin(), value);
390     }
391
392     B3::CheckValue* speculateAdd(LValue left, LValue right)
393     {
394         return m_block->appendNew<B3::CheckValue>(m_proc, B3::CheckAdd, origin(), left, right);
395     }
396
397     B3::CheckValue* speculateSub(LValue left, LValue right)
398     {
399         return m_block->appendNew<B3::CheckValue>(m_proc, B3::CheckSub, origin(), left, right);
400     }
401
402     B3::CheckValue* speculateMul(LValue left, LValue right)
403     {
404         return m_block->appendNew<B3::CheckValue>(m_proc, B3::CheckMul, origin(), left, right);
405     }
406
407     B3::PatchpointValue* patchpoint(LType type)
408     {
409         return m_block->appendNew<B3::PatchpointValue>(m_proc, type, origin());
410     }
411
412     void trap() { CRASH(); }
413
414     ValueFromBlock anchor(LValue value)
415     {
416         B3::UpsilonValue* upsilon = m_block->appendNew<B3::UpsilonValue>(m_proc, origin(), value);
417         return ValueFromBlock(upsilon, m_block);
418     }
419
420 #pragma mark - Intrinsics
421
422     LValue stackmapIntrinsic() { CRASH(); }
423     LValue frameAddressIntrinsic() { CRASH(); }
424     LValue patchpointInt64Intrinsic() { CRASH(); }
425     LValue patchpointVoidIntrinsic() { CRASH(); }
426
427 #pragma mark - States
428     B3::Procedure& m_proc;
429
430     DFG::Node* m_origin { nullptr };
431     LBasicBlock m_block { nullptr };
432     LBasicBlock m_nextBlock { nullptr };
433
434     AbstractHeapRepository* m_heaps;
435
436 private:
437     template<typename Function, typename... Args>
438     LValue callWithoutSideEffects(B3::Type type, Function function, LValue arg1, Args... args)
439     {
440         return m_block->appendNew<B3::CCallValue>(m_proc, type, origin(), B3::Effects::none(),
441             m_block->appendNew<B3::ConstPtrValue>(m_proc, origin(), bitwise_cast<void*>(function)),
442             arg1, args...);
443     }
444
445 };
446
447 template<typename... Params>
448 inline LValue Output::phi(LType type, ValueFromBlock value, Params... theRest)
449 {
450     LValue phiNode = phi(type);
451     addIncomingToPhi(phiNode, value, theRest...);
452     return phiNode;
453 }
454
455 template<typename VectorType>
456 inline LValue Output::phi(LType type, const VectorType& vector)
457 {
458     LValue phiNode = phi(type);
459     for (const ValueFromBlock& valueFromBlock : vector)
460         addIncomingToPhi(phiNode, valueFromBlock);
461     return phiNode;
462 }
463
464 inline void Output::addIncomingToPhi(LValue phi, ValueFromBlock value)
465 {
466     value.value()->as<B3::UpsilonValue>()->setPhi(phi);
467 }
468
469 template<typename... Params>
470 inline void Output::addIncomingToPhi(LValue phi, ValueFromBlock value, Params... theRest)
471 {
472     addIncomingToPhi(phi, value);
473     addIncomingToPhi(phi, theRest...);
474 }
475
476 inline LValue Output::bitNot(LValue value)
477 {
478     return m_block->appendNew<B3::Value>(m_proc, B3::BitXor, origin(),
479         value,
480         m_block->appendIntConstant(m_proc, origin(), value->type(), -1));
481 }
482
483 inline LValue Output::bitCast(LValue value, LType type)
484 {
485     ASSERT_UNUSED(type, type == int64 || type == doubleType);
486     return m_block->appendNew<B3::Value>(m_proc, B3::BitwiseCast, origin(), value);
487 }
488
489 #if COMPILER(CLANG)
490 #pragma clang diagnostic pop
491 #endif // COMPILER(CLANG)
492
493 #define FTL_NEW_BLOCK(output, nameArguments) \
494     (LIKELY(!verboseCompilationEnabled()) \
495     ? (output).newBlock() \
496     : (output).newBlock((toCString nameArguments).data()))
497
498 } } // namespace JSC::FTL
499
500 #endif // FTL_USES_B3
501 #endif // ENABLE(FTL_JIT)
502
503 #endif // FTLB3Output_h