[JSC] Add signExt() to FTLB3Output
[WebKit-https.git] / Source / JavaScriptCore / ftl / FTLOutput.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 FTLOutput_h
27 #define FTLOutput_h
28
29 #if ENABLE(FTL_JIT)
30 #if !FTL_USES_B3
31
32 #include "DFGCommon.h"
33 #include "FTLAbbreviations.h"
34 #include "FTLAbstractHeapRepository.h"
35 #include "FTLCommonValues.h"
36 #include "FTLIntrinsicRepository.h"
37 #include "FTLState.h"
38 #include "FTLSwitchCase.h"
39 #include "FTLTypedPointer.h"
40 #include "FTLWeight.h"
41 #include "FTLWeightedTarget.h"
42 #include <wtf/StringPrintStream.h>
43
44 namespace JSC { namespace FTL {
45
46 // Idiomatic LLVM IR builder specifically designed for FTL. This uses our own lowering
47 // terminology, and has some of its own notions:
48 //
49 // We say that a "reference" is what LLVM considers to be a "pointer". That is, it has
50 // an element type and can be passed directly to memory access instructions. Note that
51 // broadly speaking the users of FTL::Output should only use references for alloca'd
52 // slots for mutable local variables.
53 //
54 // We say that a "pointer" is what LLVM considers to be a pointer-width integer.
55 //
56 // We say that a "typed pointer" is a pointer that carries TBAA meta-data (i.e. an
57 // AbstractHeap). These should usually not have further computation performed on them
58 // prior to access, though there are exceptions (like offsetting into the payload of
59 // a typed pointer to a JSValue).
60 //
61 // We say that "get" and "set" are what LLVM considers to be "load" and "store". Get
62 // and set take references.
63 //
64 // We say that "load" and "store" are operations that take a typed pointer. These
65 // operations translate the pointer into a reference (or, a pointer in LLVM-speak),
66 // emit get or set on the reference (or, load and store in LLVM-speak), and apply the
67 // TBAA meta-data to the get or set.
68
69 enum Scale { ScaleOne, ScaleTwo, ScaleFour, ScaleEight, ScalePtr };
70
71 class Output : public IntrinsicRepository {
72 public:
73     Output(State&);
74     ~Output();
75     
76     void initialize(LModule, LValue, AbstractHeapRepository&);
77     
78     LBasicBlock insertNewBlocksBefore(LBasicBlock nextBlock)
79     {
80         LBasicBlock lastNextBlock = m_nextBlock;
81         m_nextBlock = nextBlock;
82         return lastNextBlock;
83     }
84     
85     LBasicBlock appendTo(LBasicBlock, LBasicBlock nextBlock);
86     
87     void appendTo(LBasicBlock);
88     
89     LBasicBlock newBlock(const char* name = "");
90     
91     LValue param(unsigned index) { return getParam(m_function, index); }
92     LValue constBool(bool value) { return constInt(boolean, value); }
93     LValue constInt32(int32_t value) { return constInt(int32, value); }
94     template<typename T>
95     LValue constIntPtr(T* value) { return constInt(intPtr, bitwise_cast<intptr_t>(value)); }
96     template<typename T>
97     LValue constIntPtr(T value) { return constInt(intPtr, static_cast<intptr_t>(value)); }
98     LValue constInt64(int64_t value) { return constInt(int64, value); }
99     LValue constDouble(double value) { return constReal(doubleType, value); }
100     
101     LValue phi(LType type) { return buildPhi(m_builder, type); }
102     template<typename... Params>
103     LValue phi(LType type, ValueFromBlock value, Params... theRest)
104     {
105         LValue result = phi(type, theRest...);
106         addIncoming(result, value);
107         return result;
108     }
109     template<typename VectorType>
110     LValue phi(LType type, const VectorType& vector)
111     {
112         LValue result = phi(type);
113         for (unsigned i = 0; i < vector.size(); ++i)
114             addIncoming(result, vector[i]);
115         return result;
116     }
117     void addIncomingToPhi(LValue phi, ValueFromBlock value)
118     {
119         addIncoming(phi, value);
120     }
121     
122     LValue add(LValue left, LValue right) { return buildAdd(m_builder, left, right); }
123     LValue sub(LValue left, LValue right) { return buildSub(m_builder, left, right); }
124     LValue mul(LValue left, LValue right) { return buildMul(m_builder, left, right); }
125     LValue div(LValue left, LValue right) { return buildDiv(m_builder, left, right); }
126     LValue rem(LValue left, LValue right) { return buildRem(m_builder, left, right); }
127     LValue neg(LValue value) { return buildNeg(m_builder, value); }
128
129     LValue doubleAdd(LValue left, LValue right) { return buildFAdd(m_builder, left, right); }
130     LValue doubleSub(LValue left, LValue right) { return buildFSub(m_builder, left, right); }
131     LValue doubleMul(LValue left, LValue right) { return buildFMul(m_builder, left, right); }
132     LValue doubleDiv(LValue left, LValue right) { return buildFDiv(m_builder, left, right); }
133     LValue doubleRem(LValue left, LValue right) { return buildFRem(m_builder, left, right); }
134     LValue doubleNeg(LValue value) { return buildFNeg(m_builder, value); }
135
136     LValue bitAnd(LValue left, LValue right) { return buildAnd(m_builder, left, right); }
137     LValue bitOr(LValue left, LValue right) { return buildOr(m_builder, left, right); }
138     LValue bitXor(LValue left, LValue right) { return buildXor(m_builder, left, right); }
139     LValue shl(LValue left, LValue right) { return buildShl(m_builder, left, right); }
140     LValue aShr(LValue left, LValue right) { return buildAShr(m_builder, left, right); } // arithmetic = signed
141     LValue lShr(LValue left, LValue right) { return buildLShr(m_builder, left, right); } // logical = unsigned
142     LValue bitNot(LValue value) { return buildNot(m_builder, value); }
143     
144     LValue insertElement(LValue vector, LValue element, LValue index) { return buildInsertElement(m_builder, vector, element, index); }
145
146     LValue ceil64(LValue operand)
147     {
148         return call(doubleType, ceil64Intrinsic(), operand);
149     }
150     LValue ctlz32(LValue operand)
151     {
152         return call(int32, ctlz32Intrinsic(), operand, booleanFalse);
153     }
154     LValue addWithOverflow32(LValue left, LValue right)
155     {
156         return call(int32, addWithOverflow32Intrinsic(), left, right);
157     }
158     LValue subWithOverflow32(LValue left, LValue right)
159     {
160         return call(int32, subWithOverflow32Intrinsic(), left, right);
161     }
162     LValue mulWithOverflow32(LValue left, LValue right)
163     {
164         return call(int32, mulWithOverflow32Intrinsic(), left, right);
165     }
166     LValue addWithOverflow64(LValue left, LValue right)
167     {
168         return call(int64, addWithOverflow64Intrinsic(), left, right);
169     }
170     LValue subWithOverflow64(LValue left, LValue right)
171     {
172         return call(int64, subWithOverflow64Intrinsic(), left, right);
173     }
174     LValue mulWithOverflow64(LValue left, LValue right)
175     {
176         return call(int64, mulWithOverflow64Intrinsic(), left, right);
177     }
178     LValue doubleAbs(LValue value)
179     {
180         return call(doubleType, doubleAbsIntrinsic(), value);
181     }
182
183     LValue doubleSin(LValue value)
184     {
185         return call(doubleType, doubleSinIntrinsic(), value);
186     }
187     LValue doubleCos(LValue value)
188     {
189         return call(doubleType, doubleCosIntrinsic(), value);
190     }
191
192     LValue doublePow(LValue xOperand, LValue yOperand)
193     {
194         return call(doubleType, doublePowIntrinsic(), xOperand, yOperand);
195     }
196
197     LValue doublePowi(LValue xOperand, LValue yOperand)
198     {
199         return call(doubleType, doublePowiIntrinsic(), xOperand, yOperand);
200     }
201
202     LValue doubleSqrt(LValue value)
203     {
204         return call(doubleType, doubleSqrtIntrinsic(), value);
205     }
206
207     LValue doubleLog(LValue value)
208     {
209         return call(doubleType, doubleLogIntrinsic(), value);
210     }
211
212     static bool hasSensibleDoubleToInt() { return isX86(); }
213     LValue sensibleDoubleToInt(LValue);
214
215     LValue signExt32To64(LValue value) { return signExt(value, int64); }
216     LValue zeroExt(LValue value, LType type) { return buildZExt(m_builder, value, type); }
217     LValue zeroExtPtr(LValue value) { return zeroExt(value, intPtr); }
218     LValue fpToInt(LValue value, LType type) { return buildFPToSI(m_builder, value, type); }
219     LValue fpToUInt(LValue value, LType type) { return buildFPToUI(m_builder, value, type); }
220     LValue fpToInt32(LValue value) { return fpToInt(value, int32); }
221     LValue fpToUInt32(LValue value) { return fpToUInt(value, int32); }
222     LValue intToFP(LValue value, LType type) { return buildSIToFP(m_builder, value, type); }
223     LValue intToDouble(LValue value) { return intToFP(value, doubleType); }
224     LValue unsignedToFP(LValue value, LType type) { return buildUIToFP(m_builder, value, type); }
225     LValue unsignedToDouble(LValue value) { return unsignedToFP(value, doubleType); }
226     LValue intCast(LValue value, LType type) { return buildIntCast(m_builder, value, type); }
227     LValue castToInt32(LValue value) { return intCast(value, int32); }
228     LValue fpCast(LValue value, LType type) { return buildFPCast(m_builder, value, type); }
229     LValue intToPtr(LValue value, LType type) { return buildIntToPtr(m_builder, value, type); }
230     LValue ptrToInt(LValue value, LType type) { return buildPtrToInt(m_builder, value, type); }
231     LValue bitCast(LValue value, LType type) { return buildBitCast(m_builder, value, type); }
232
233     LValue fround(LValue doubleValue);
234     
235     // Hilariously, the #define machinery in the stdlib means that this method is actually called
236     // __builtin_alloca. So far this appears benign. :-|
237     LValue alloca(LType type) { return buildAlloca(m_builder, type); }
238     
239     // Access the value of an alloca. Also used as a low-level implementation primitive for
240     // load(). Never use this to load from "pointers" in the FTL sense, since FTL pointers
241     // are actually integers. This requires an LLVM pointer. Broadly speaking, you don't
242     // have any LLVM pointers even if you really think you do. A TypedPointer is not an
243     // LLVM pointer. See comment block at top of this file to understand the distinction
244     // between LLVM pointers, FTL pointers, and FTL references.
245     LValue get(LValue reference) { return buildLoad(m_builder, reference); }
246     // Similar to get() but for storing to the value in an alloca.
247     LValue set(LValue value, LValue reference) { return buildStore(m_builder, value, reference); }
248     
249     LValue load(TypedPointer, LType refType);
250     void store(LValue, TypedPointer, LType refType);
251
252     LValue load8SignExt32(TypedPointer);
253     LValue load8ZeroExt32(TypedPointer);
254     LValue load16SignExt32(TypedPointer);
255     LValue load16ZeroExt32(TypedPointer);
256     LValue load32(TypedPointer pointer) { return load(pointer, ref32); }
257     LValue load64(TypedPointer pointer) { return load(pointer, ref64); }
258     LValue loadPtr(TypedPointer pointer) { return load(pointer, refPtr); }
259     LValue loadFloatToDouble(TypedPointer pointer) { return buildFPCast(m_builder, load(pointer, refFloat), doubleType); }
260     LValue loadDouble(TypedPointer pointer) { return load(pointer, refDouble); }
261     void store16(LValue value, TypedPointer pointer) { store(value, pointer, ref16); }
262     void store32(LValue value, TypedPointer pointer) { store(value, pointer, ref32); }
263     void store64(LValue value, TypedPointer pointer) { store(value, pointer, ref64); }
264     void storePtr(LValue value, TypedPointer pointer) { store(value, pointer, refPtr); }
265     void storeDouble(LValue value, TypedPointer pointer) { store(value, pointer, refDouble); }
266
267     LValue addPtr(LValue value, ptrdiff_t immediate = 0)
268     {
269         if (!immediate)
270             return value;
271         return add(value, constIntPtr(immediate));
272     }
273     
274     // Construct an address by offsetting base by the requested amount and ascribing
275     // the requested abstract heap to it.
276     TypedPointer address(const AbstractHeap& heap, LValue base, ptrdiff_t offset = 0)
277     {
278         return TypedPointer(heap, addPtr(base, offset));
279     }
280     // Construct an address by offsetting base by the amount specified by the field,
281     // and optionally an additional amount (use this with care), and then creating
282     // a TypedPointer with the given field as the heap.
283     TypedPointer address(LValue base, const AbstractField& field, ptrdiff_t offset = 0)
284     {
285         return address(field, base, offset + field.offset());
286     }
287     
288     LValue baseIndex(LValue base, LValue index, Scale, ptrdiff_t offset = 0);
289
290     TypedPointer baseIndex(const AbstractHeap& heap, LValue base, LValue index, Scale scale, ptrdiff_t offset = 0)
291     {
292         return TypedPointer(heap, baseIndex(base, index, scale, offset));
293     }
294     TypedPointer baseIndex(IndexedAbstractHeap& heap, LValue base, LValue index, JSValue indexAsConstant = JSValue(), ptrdiff_t offset = 0)
295     {
296         return heap.baseIndex(*this, base, index, indexAsConstant, offset);
297     }
298     
299     TypedPointer absolute(void* address)
300     {
301         return TypedPointer(m_heaps->absolute[address], constIntPtr(address));
302     }
303
304     LValue load8SignExt32(LValue base, const AbstractField& field) { return load8SignExt32(address(base, field)); }
305     LValue load8ZeroExt32(LValue base, const AbstractField& field) { return load8ZeroExt32(address(base, field)); }
306     LValue load16SignExt32(LValue base, const AbstractField& field) { return load16SignExt32(address(base, field)); }
307     LValue load16ZeroExt32(LValue base, const AbstractField& field) { return load16ZeroExt32(address(base, field)); }
308     LValue load32(LValue base, const AbstractField& field) { return load32(address(base, field)); }
309     LValue load64(LValue base, const AbstractField& field) { return load64(address(base, field)); }
310     LValue loadPtr(LValue base, const AbstractField& field) { return loadPtr(address(base, field)); }
311     LValue loadDouble(LValue base, const AbstractField& field) { return loadDouble(address(base, field)); }
312     void store32(LValue value, LValue base, const AbstractField& field) { store32(value, address(base, field)); }
313     void store64(LValue value, LValue base, const AbstractField& field) { store64(value, address(base, field)); }
314     void storePtr(LValue value, LValue base, const AbstractField& field) { storePtr(value, address(base, field)); }
315     void storeDouble(LValue value, LValue base, const AbstractField& field) { storeDouble(value, address(base, field)); }
316     
317     void ascribeRange(LValue loadInstruction, const ValueRange& range)
318     {
319         range.decorateInstruction(m_context, loadInstruction, rangeKind);
320     }
321     
322     LValue nonNegative32(LValue loadInstruction)
323     {
324         ascribeRange(loadInstruction, nonNegativeInt32);
325         return loadInstruction;
326     }
327     
328     LValue load32NonNegative(TypedPointer pointer) { return nonNegative32(load32(pointer)); }
329     LValue load32NonNegative(LValue base, const AbstractField& field) { return nonNegative32(load32(base, field)); }
330     
331     LValue icmp(LIntPredicate cond, LValue left, LValue right) { return buildICmp(m_builder, cond, left, right); }
332     LValue equal(LValue left, LValue right) { return icmp(LLVMIntEQ, left, right); }
333     LValue notEqual(LValue left, LValue right) { return icmp(LLVMIntNE, left, right); }
334     LValue above(LValue left, LValue right) { return icmp(LLVMIntUGT, left, right); }
335     LValue aboveOrEqual(LValue left, LValue right) { return icmp(LLVMIntUGE, left, right); }
336     LValue below(LValue left, LValue right) { return icmp(LLVMIntULT, left, right); }
337     LValue belowOrEqual(LValue left, LValue right) { return icmp(LLVMIntULE, left, right); }
338     LValue greaterThan(LValue left, LValue right) { return icmp(LLVMIntSGT, left, right); }
339     LValue greaterThanOrEqual(LValue left, LValue right) { return icmp(LLVMIntSGE, left, right); }
340     LValue lessThan(LValue left, LValue right) { return icmp(LLVMIntSLT, left, right); }
341     LValue lessThanOrEqual(LValue left, LValue right) { return icmp(LLVMIntSLE, left, right); }
342     
343     LValue fcmp(LRealPredicate cond, LValue left, LValue right) { return buildFCmp(m_builder, cond, left, right); }
344     LValue doubleEqual(LValue left, LValue right) { return fcmp(LLVMRealOEQ, left, right); }
345     LValue doubleNotEqualOrUnordered(LValue left, LValue right) { return fcmp(LLVMRealUNE, left, right); }
346     LValue doubleLessThan(LValue left, LValue right) { return fcmp(LLVMRealOLT, left, right); }
347     LValue doubleLessThanOrEqual(LValue left, LValue right) { return fcmp(LLVMRealOLE, left, right); }
348     LValue doubleGreaterThan(LValue left, LValue right) { return fcmp(LLVMRealOGT, left, right); }
349     LValue doubleGreaterThanOrEqual(LValue left, LValue right) { return fcmp(LLVMRealOGE, left, right); }
350     LValue doubleEqualOrUnordered(LValue left, LValue right) { return fcmp(LLVMRealUEQ, left, right); }
351     LValue doubleNotEqual(LValue left, LValue right) { return fcmp(LLVMRealONE, left, right); }
352     LValue doubleLessThanOrUnordered(LValue left, LValue right) { return fcmp(LLVMRealULT, left, right); }
353     LValue doubleLessThanOrEqualOrUnordered(LValue left, LValue right) { return fcmp(LLVMRealULE, left, right); }
354     LValue doubleGreaterThanOrUnordered(LValue left, LValue right) { return fcmp(LLVMRealUGT, left, right); }
355     LValue doubleGreaterThanOrEqualOrUnordered(LValue left, LValue right) { return fcmp(LLVMRealUGE, left, right); }
356     
357     LValue isZero32(LValue value) { return equal(value, int32Zero); }
358     LValue notZero32(LValue value) { return notEqual(value, int32Zero); }
359     LValue isZero64(LValue value) { return equal(value, int64Zero); }
360     LValue notZero64(LValue value) { return notEqual(value, int64Zero); }
361     LValue isNull(LValue value) { return equal(value, intPtrZero); }
362     LValue notNull(LValue value) { return notEqual(value, intPtrZero); }
363     
364     LValue testIsZero32(LValue value, LValue mask) { return isZero32(bitAnd(value, mask)); }
365     LValue testNonZero32(LValue value, LValue mask) { return notZero32(bitAnd(value, mask)); }
366     LValue testIsZero64(LValue value, LValue mask) { return isZero64(bitAnd(value, mask)); }
367     LValue testNonZero64(LValue value, LValue mask) { return notZero64(bitAnd(value, mask)); }
368     LValue testIsZeroPtr(LValue value, LValue mask) { return isNull(bitAnd(value, mask)); }
369     LValue testNonZeroPtr(LValue value, LValue mask) { return notNull(bitAnd(value, mask)); }
370     
371     LValue select(LValue value, LValue taken, LValue notTaken) { return buildSelect(m_builder, value, taken, notTaken); }
372     LValue extractValue(LValue aggVal, unsigned index) { return buildExtractValue(m_builder, aggVal, index); }
373     
374     LValue fence(LAtomicOrdering ordering = LLVMAtomicOrderingSequentiallyConsistent, SynchronizationScope scope = CrossThread) { return buildFence(m_builder, ordering, scope); }
375     LValue fenceAcqRel() { return fence(LLVMAtomicOrderingAcquireRelease); }
376     
377     template<typename VectorType>
378     LValue call(LType, LValue function, const VectorType& vector) { return buildCall(m_builder, function, vector); }
379     LValue call(LType, LValue function) { return buildCall(m_builder, function); }
380     LValue call(LType, LValue function, LValue arg1) { return buildCall(m_builder, function, arg1); }
381     template<typename... Args>
382     LValue call(LType, LValue function, LValue arg1, Args... args) { return buildCall(m_builder, function, arg1, args...); }
383     
384     template<typename FunctionType>
385     LValue operation(FunctionType function)
386     {
387         return intToPtr(constIntPtr(function), pointerType(operationType(function)));
388     }
389     
390     void jump(LBasicBlock destination) { buildBr(m_builder, 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         LValue inst = buildSwitch(m_builder, value, cases, fallThrough);
408         
409         double total = 0;
410         if (!fallThroughWeight)
411             return;
412         total += fallThroughWeight.value();
413         for (unsigned i = cases.size(); i--;) {
414             if (!cases[i].weight())
415                 return;
416             total += cases[i].weight().value();
417         }
418         
419         Vector<LValue> mdArgs;
420         mdArgs.append(branchWeights);
421         mdArgs.append(constInt32(fallThroughWeight.scaleToTotal(total)));
422         for (unsigned i = 0; i < cases.size(); ++i)
423             mdArgs.append(constInt32(cases[i].weight().scaleToTotal(total)));
424         
425         setMetadata(inst, profKind, mdNode(m_context, mdArgs));
426     }
427     
428     void ret(LValue value) { buildRet(m_builder, value); }
429     
430     void unreachable() { buildUnreachable(m_builder); }
431     
432     void trap()
433     {
434         call(voidType, trapIntrinsic());
435     }
436     
437     ValueFromBlock anchor(LValue value)
438     {
439         return ValueFromBlock(value, m_block);
440     }
441     
442     LValue m_function;
443     AbstractHeapRepository* m_heaps;
444     LBuilder m_builder;
445     LBasicBlock m_block;
446     LBasicBlock m_nextBlock;
447
448 private:
449     LValue signExt(LValue value, LType type) { return buildSExt(m_builder, value, type); }
450 };
451
452 inline LValue Output::load8SignExt32(TypedPointer pointer)
453 {
454     LValue value8 = load(pointer, ref8);
455     return signExt(value8, int32);
456 }
457
458 inline LValue Output::load8ZeroExt32(TypedPointer pointer)
459 {
460     LValue value8 = load(pointer, ref8);
461     return zeroExt(value8, int32);
462 }
463
464 inline LValue Output::load16SignExt32(TypedPointer pointer)
465 {
466     LValue value16 = load(pointer, ref16);
467     return signExt(value16, int32);
468 }
469
470 inline LValue Output::load16ZeroExt32(TypedPointer pointer)
471 {
472     LValue value16 = load(pointer, ref16);
473     return zeroExt(value16, int32);
474 }
475
476 inline LValue Output::fround(LValue doubleValue)
477 {
478     LValue floatValue = buildFPCast(m_builder, doubleValue, floatType);
479     return buildFPCast(m_builder, floatValue, doubleType);
480 }
481
482 #define FTL_NEW_BLOCK(output, nameArguments) \
483     (LIKELY(!verboseCompilationEnabled()) \
484     ? (output).newBlock() \
485     : (output).newBlock((toCString nameArguments).data()))
486
487 } } // namespace JSC::FTL
488
489 #endif // !FTL_USES_B3
490 #endif // ENABLE(FTL_JIT)
491
492 #endif // FTLOutput_h
493