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