summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/ftl/FTLOutput.h
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/ftl/FTLOutput.h')
-rw-r--r--Source/JavaScriptCore/ftl/FTLOutput.h531
1 files changed, 531 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/ftl/FTLOutput.h b/Source/JavaScriptCore/ftl/FTLOutput.h
new file mode 100644
index 000000000..dd50c2411
--- /dev/null
+++ b/Source/JavaScriptCore/ftl/FTLOutput.h
@@ -0,0 +1,531 @@
+/*
+ * Copyright (C) 2013-2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef FTLOutput_h
+#define FTLOutput_h
+
+#include "DFGCommon.h"
+
+#if ENABLE(FTL_JIT)
+
+#include "B3ArgumentRegValue.h"
+#include "B3BasicBlockInlines.h"
+#include "B3CCallValue.h"
+#include "B3Compilation.h"
+#include "B3Const32Value.h"
+#include "B3ConstPtrValue.h"
+#include "B3ControlValue.h"
+#include "B3MemoryValue.h"
+#include "B3Procedure.h"
+#include "B3SlotBaseValue.h"
+#include "B3SwitchValue.h"
+#include "B3UpsilonValue.h"
+#include "B3ValueInlines.h"
+#include "FTLAbbreviatedTypes.h"
+#include "FTLAbstractHeapRepository.h"
+#include "FTLCommonValues.h"
+#include "FTLState.h"
+#include "FTLSwitchCase.h"
+#include "FTLTypedPointer.h"
+#include "FTLValueFromBlock.h"
+#include "FTLWeight.h"
+#include "FTLWeightedTarget.h"
+#include <wtf/OrderMaker.h>
+#include <wtf/StringPrintStream.h>
+
+// FIXME: remove this once everything can be generated through B3.
+#if COMPILER(GCC_OR_CLANG)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmissing-noreturn"
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif // COMPILER(GCC_OR_CLANG)
+
+namespace JSC {
+
+namespace DFG { struct Node; }
+
+namespace FTL {
+
+enum Scale { ScaleOne, ScaleTwo, ScaleFour, ScaleEight, ScalePtr };
+
+class Output : public CommonValues {
+public:
+ Output(State&);
+ ~Output();
+
+ void initialize(AbstractHeapRepository&);
+
+ void setFrequency(double value)
+ {
+ m_frequency = value;
+ }
+
+ LBasicBlock newBlock();
+
+ LBasicBlock insertNewBlocksBefore(LBasicBlock nextBlock)
+ {
+ LBasicBlock lastNextBlock = m_nextBlock;
+ m_nextBlock = nextBlock;
+ return lastNextBlock;
+ }
+
+ void applyBlockOrder();
+
+ LBasicBlock appendTo(LBasicBlock, LBasicBlock nextBlock);
+ void appendTo(LBasicBlock);
+
+ void setOrigin(DFG::Node* node) { m_origin = node; }
+ B3::Origin origin() { return B3::Origin(m_origin); }
+
+ LValue framePointer() { return m_block->appendNew<B3::Value>(m_proc, B3::FramePointer, origin()); }
+
+ B3::SlotBaseValue* lockedStackSlot(size_t bytes);
+
+ LValue constBool(bool value) { return m_block->appendNew<B3::Const32Value>(m_proc, origin(), value); }
+ LValue constInt32(int32_t value) { return m_block->appendNew<B3::Const32Value>(m_proc, origin(), value); }
+ template<typename T>
+ LValue constIntPtr(T* value) { return m_block->appendNew<B3::ConstPtrValue>(m_proc, origin(), value); }
+ template<typename T>
+ LValue constIntPtr(T value) { return m_block->appendNew<B3::ConstPtrValue>(m_proc, origin(), value); }
+ LValue constInt64(int64_t value) { return m_block->appendNew<B3::Const64Value>(m_proc, origin(), value); }
+ LValue constDouble(double value) { return m_block->appendNew<B3::ConstDoubleValue>(m_proc, origin(), value); }
+
+ LValue phi(LType type) { return m_block->appendNew<B3::Value>(m_proc, B3::Phi, type, origin()); }
+ template<typename... Params>
+ LValue phi(LType, ValueFromBlock, Params... theRest);
+ template<typename VectorType>
+ LValue phi(LType, const VectorType&);
+ void addIncomingToPhi(LValue phi, ValueFromBlock);
+ template<typename... Params>
+ void addIncomingToPhi(LValue phi, ValueFromBlock, Params... theRest);
+
+ LValue add(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Add, origin(), left, right); }
+ LValue sub(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Sub, origin(), left, right); }
+ LValue mul(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Mul, origin(), left, right); }
+ LValue div(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Div, origin(), left, right); }
+ LValue chillDiv(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::ChillDiv, origin(), left, right); }
+ LValue mod(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Mod, origin(), left, right); }
+ LValue chillMod(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::ChillMod, origin(), left, right); }
+ LValue neg(LValue);
+
+ LValue doubleAdd(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Add, origin(), left, right); }
+ LValue doubleSub(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Sub, origin(), left, right); }
+ LValue doubleMul(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Mul, origin(), left, right); }
+ LValue doubleDiv(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Div, origin(), left, right); }
+ LValue doubleMod(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Mod, origin(), left, right); }
+ LValue doubleNeg(LValue value) { return neg(value); }
+
+ LValue bitAnd(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::BitAnd, origin(), left, right); }
+ LValue bitOr(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::BitOr, origin(), left, right); }
+ LValue bitXor(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::BitXor, origin(), left, right); }
+ LValue shl(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Shl, origin(), left, castToInt32(right)); }
+ LValue aShr(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::SShr, origin(), left, castToInt32(right)); }
+ LValue lShr(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::ZShr, origin(), left, castToInt32(right)); }
+ LValue bitNot(LValue);
+ LValue logicalNot(LValue);
+
+ LValue ctlz32(LValue operand) { return m_block->appendNew<B3::Value>(m_proc, B3::Clz, origin(), operand); }
+ LValue addWithOverflow32(LValue left, LValue right) { CRASH(); }
+ LValue subWithOverflow32(LValue left, LValue right) { CRASH(); }
+ LValue mulWithOverflow32(LValue left, LValue right) { CRASH(); }
+ LValue addWithOverflow64(LValue left, LValue right) { CRASH(); }
+ LValue subWithOverflow64(LValue left, LValue right) { CRASH(); }
+ LValue mulWithOverflow64(LValue left, LValue right) { CRASH(); }
+ LValue doubleAbs(LValue value) { return m_block->appendNew<B3::Value>(m_proc, B3::Abs, origin(), value); }
+ LValue doubleCeil(LValue operand) { return m_block->appendNew<B3::Value>(m_proc, B3::Ceil, origin(), operand); }
+ LValue doubleFloor(LValue operand) { return m_block->appendNew<B3::Value>(m_proc, B3::Floor, origin(), operand); }
+
+ LValue doubleSin(LValue value)
+ {
+ double (*sinDouble)(double) = sin;
+ return callWithoutSideEffects(B3::Double, sinDouble, value);
+ }
+ LValue doubleCos(LValue value)
+ {
+ double (*cosDouble)(double) = cos;
+ return callWithoutSideEffects(B3::Double, cosDouble, value);
+ }
+
+ LValue doublePow(LValue xOperand, LValue yOperand)
+ {
+ double (*powDouble)(double, double) = pow;
+ return callWithoutSideEffects(B3::Double, powDouble, xOperand, yOperand);
+ }
+
+ LValue doublePowi(LValue xOperand, LValue yOperand);
+
+ LValue doubleSqrt(LValue value) { return m_block->appendNew<B3::Value>(m_proc, B3::Sqrt, origin(), value); }
+
+ LValue doubleLog(LValue value)
+ {
+ double (*logDouble)(double) = log;
+ return callWithoutSideEffects(B3::Double, logDouble, value);
+ }
+
+ static bool hasSensibleDoubleToInt();
+ LValue doubleToInt(LValue);
+ LValue doubleToUInt(LValue);
+
+ LValue signExt32To64(LValue value) { return m_block->appendNew<B3::Value>(m_proc, B3::SExt32, origin(), value); }
+ LValue zeroExt(LValue value, LType type)
+ {
+ if (value->type() == type)
+ return value;
+ return m_block->appendNew<B3::Value>(m_proc, B3::ZExt32, origin(), value);
+ }
+ LValue zeroExtPtr(LValue value) { return zeroExt(value, B3::Int64); }
+ LValue intToDouble(LValue value) { return m_block->appendNew<B3::Value>(m_proc, B3::IToD, origin(), value); }
+ LValue unsignedToDouble(LValue);
+ LValue castToInt32(LValue value)
+ {
+ return value->type() == B3::Int32 ? value :
+ m_block->appendNew<B3::Value>(m_proc, B3::Trunc, origin(), value);
+ }
+ LValue doubleToFloat(LValue value) { return m_block->appendNew<B3::Value>(m_proc, B3::DoubleToFloat, origin(), value); }
+ LValue floatToDouble(LValue value) { return m_block->appendNew<B3::Value>(m_proc, B3::FloatToDouble, origin(), value); }
+ LValue bitCast(LValue, LType);
+ LValue fround(LValue doubleValue);
+
+ LValue load(TypedPointer, LType);
+ void store(LValue, TypedPointer);
+
+ LValue load8SignExt32(TypedPointer);
+ LValue load8ZeroExt32(TypedPointer);
+ LValue load16SignExt32(TypedPointer);
+ LValue load16ZeroExt32(TypedPointer);
+ LValue load32(TypedPointer pointer) { return load(pointer, B3::Int32); }
+ LValue load64(TypedPointer pointer) { return load(pointer, B3::Int64); }
+ LValue loadPtr(TypedPointer pointer) { return load(pointer, B3::pointerType()); }
+ LValue loadFloat(TypedPointer pointer) { return load(pointer, B3::Float); }
+ LValue loadDouble(TypedPointer pointer) { return load(pointer, B3::Double); }
+ void store32As8(LValue value, TypedPointer pointer);
+ void store32As16(LValue value, TypedPointer pointer);
+ void store32(LValue value, TypedPointer pointer)
+ {
+ ASSERT(value->type() == B3::Int32);
+ store(value, pointer);
+ }
+ void store64(LValue value, TypedPointer pointer)
+ {
+ ASSERT(value->type() == B3::Int64);
+ store(value, pointer);
+ }
+ void storePtr(LValue value, TypedPointer pointer)
+ {
+ ASSERT(value->type() == B3::pointerType());
+ store(value, pointer);
+ }
+ void storeFloat(LValue value, TypedPointer pointer)
+ {
+ ASSERT(value->type() == B3::Float);
+ store(value, pointer);
+ }
+ void storeDouble(LValue value, TypedPointer pointer)
+ {
+ ASSERT(value->type() == B3::Double);
+ store(value, pointer);
+ }
+
+ enum LoadType {
+ Load8SignExt32,
+ Load8ZeroExt32,
+ Load16SignExt32,
+ Load16ZeroExt32,
+ Load32,
+ Load64,
+ LoadPtr,
+ LoadFloat,
+ LoadDouble
+ };
+
+ LValue load(TypedPointer, LoadType);
+
+ enum StoreType {
+ Store32As8,
+ Store32As16,
+ Store32,
+ Store64,
+ StorePtr,
+ StoreFloat,
+ StoreDouble
+ };
+
+ void store(LValue, TypedPointer, StoreType);
+
+ LValue addPtr(LValue value, ptrdiff_t immediate = 0)
+ {
+ if (!immediate)
+ return value;
+ return add(value, constIntPtr(immediate));
+ }
+
+ // Construct an address by offsetting base by the requested amount and ascribing
+ // the requested abstract heap to it.
+ TypedPointer address(const AbstractHeap& heap, LValue base, ptrdiff_t offset = 0)
+ {
+ return TypedPointer(heap, addPtr(base, offset));
+ }
+ // Construct an address by offsetting base by the amount specified by the field,
+ // and optionally an additional amount (use this with care), and then creating
+ // a TypedPointer with the given field as the heap.
+ TypedPointer address(LValue base, const AbstractHeap& field, ptrdiff_t offset = 0)
+ {
+ return address(field, base, offset + field.offset());
+ }
+
+ LValue baseIndex(LValue base, LValue index, Scale, ptrdiff_t offset = 0);
+
+ TypedPointer baseIndex(const AbstractHeap& heap, LValue base, LValue index, Scale scale, ptrdiff_t offset = 0)
+ {
+ return TypedPointer(heap, baseIndex(base, index, scale, offset));
+ }
+ TypedPointer baseIndex(IndexedAbstractHeap& heap, LValue base, LValue index, JSValue indexAsConstant = JSValue(), ptrdiff_t offset = 0)
+ {
+ return heap.baseIndex(*this, base, index, indexAsConstant, offset);
+ }
+
+ TypedPointer absolute(void* address)
+ {
+ return TypedPointer(m_heaps->absolute[address], constIntPtr(address));
+ }
+
+ LValue load8SignExt32(LValue base, const AbstractHeap& field) { return load8SignExt32(address(base, field)); }
+ LValue load8ZeroExt32(LValue base, const AbstractHeap& field) { return load8ZeroExt32(address(base, field)); }
+ LValue load16SignExt32(LValue base, const AbstractHeap& field) { return load16SignExt32(address(base, field)); }
+ LValue load16ZeroExt32(LValue base, const AbstractHeap& field) { return load16ZeroExt32(address(base, field)); }
+ LValue load32(LValue base, const AbstractHeap& field) { return load32(address(base, field)); }
+ LValue load64(LValue base, const AbstractHeap& field) { return load64(address(base, field)); }
+ LValue loadPtr(LValue base, const AbstractHeap& field) { return loadPtr(address(base, field)); }
+ LValue loadDouble(LValue base, const AbstractHeap& field) { return loadDouble(address(base, field)); }
+ void store32(LValue value, LValue base, const AbstractHeap& field) { store32(value, address(base, field)); }
+ void store64(LValue value, LValue base, const AbstractHeap& field) { store64(value, address(base, field)); }
+ void storePtr(LValue value, LValue base, const AbstractHeap& field) { storePtr(value, address(base, field)); }
+ void storeDouble(LValue value, LValue base, const AbstractHeap& field) { storeDouble(value, address(base, field)); }
+
+ // FIXME: Explore adding support for value range constraints to B3. Maybe it could be as simple as having
+ // a load instruction that guarantees that its result is non-negative.
+ // https://bugs.webkit.org/show_bug.cgi?id=151458
+ void ascribeRange(LValue, const ValueRange&) { }
+ LValue nonNegative32(LValue loadInstruction) { return loadInstruction; }
+ LValue load32NonNegative(TypedPointer pointer) { return load32(pointer); }
+ LValue load32NonNegative(LValue base, const AbstractHeap& field) { return load32(base, field); }
+
+ LValue equal(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Equal, origin(), left, right); }
+ LValue notEqual(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::NotEqual, origin(), left, right); }
+ LValue above(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Above, origin(), left, right); }
+ LValue aboveOrEqual(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::AboveEqual, origin(), left, right); }
+ LValue below(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Below, origin(), left, right); }
+ LValue belowOrEqual(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::BelowEqual, origin(), left, right); }
+ LValue greaterThan(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::GreaterThan, origin(), left, right); }
+ LValue greaterThanOrEqual(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::GreaterEqual, origin(), left, right); }
+ LValue lessThan(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::LessThan, origin(), left, right); }
+ LValue lessThanOrEqual(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::LessEqual, origin(), left, right); }
+
+ LValue doubleEqual(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::Equal, origin(), left, right); }
+ LValue doubleEqualOrUnordered(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::EqualOrUnordered, origin(), left, right); }
+ LValue doubleNotEqualOrUnordered(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::NotEqual, origin(), left, right); }
+ LValue doubleLessThan(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::LessThan, origin(), left, right); }
+ LValue doubleLessThanOrEqual(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::LessEqual, origin(), left, right); }
+ LValue doubleGreaterThan(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::GreaterThan, origin(), left, right); }
+ LValue doubleGreaterThanOrEqual(LValue left, LValue right) { return m_block->appendNew<B3::Value>(m_proc, B3::GreaterEqual, origin(), left, right); }
+ LValue doubleNotEqualAndOrdered(LValue left, LValue right) { return logicalNot(doubleEqualOrUnordered(left, right)); }
+ LValue doubleLessThanOrUnordered(LValue left, LValue right) { return logicalNot(doubleGreaterThanOrEqual(left, right)); }
+ LValue doubleLessThanOrEqualOrUnordered(LValue left, LValue right) { return logicalNot(doubleGreaterThan(left, right)); }
+ LValue doubleGreaterThanOrUnordered(LValue left, LValue right) { return logicalNot(doubleLessThanOrEqual(left, right)); }
+ LValue doubleGreaterThanOrEqualOrUnordered(LValue left, LValue right) { return logicalNot(doubleLessThan(left, right)); }
+
+ LValue isZero32(LValue value) { return m_block->appendNew<B3::Value>(m_proc, B3::Equal, origin(), value, int32Zero); }
+ LValue notZero32(LValue value) { return m_block->appendNew<B3::Value>(m_proc, B3::NotEqual, origin(), value, int32Zero); }
+ LValue isZero64(LValue value) { return m_block->appendNew<B3::Value>(m_proc, B3::Equal, origin(), value, int64Zero); }
+ LValue notZero64(LValue value) { return m_block->appendNew<B3::Value>(m_proc, B3::NotEqual, origin(), value, int64Zero); }
+ LValue isNull(LValue value) { return isZero64(value); }
+ LValue notNull(LValue value) { return notZero64(value); }
+
+ LValue testIsZero32(LValue value, LValue mask) { return isZero32(bitAnd(value, mask)); }
+ LValue testNonZero32(LValue value, LValue mask) { return notZero32(bitAnd(value, mask)); }
+ LValue testIsZero64(LValue value, LValue mask) { return isZero64(bitAnd(value, mask)); }
+ LValue testNonZero64(LValue value, LValue mask) { return notZero64(bitAnd(value, mask)); }
+ LValue testIsZeroPtr(LValue value, LValue mask) { return isNull(bitAnd(value, mask)); }
+ LValue testNonZeroPtr(LValue value, LValue mask) { return notNull(bitAnd(value, mask)); }
+
+ LValue select(LValue value, LValue taken, LValue notTaken) { return m_block->appendNew<B3::Value>(m_proc, B3::Select, origin(), value, taken, notTaken); }
+ LValue extractValue(LValue aggVal, unsigned index) { CRASH(); }
+
+ template<typename VectorType>
+ LValue call(LType type, LValue function, const VectorType& vector)
+ {
+ B3::CCallValue* result = m_block->appendNew<B3::CCallValue>(m_proc, type, origin(), function);
+ result->children().appendVector(vector);
+ return result;
+ }
+ LValue call(LType type, LValue function) { return m_block->appendNew<B3::CCallValue>(m_proc, type, origin(), function); }
+ LValue call(LType type, LValue function, LValue arg1) { return m_block->appendNew<B3::CCallValue>(m_proc, type, origin(), function, arg1); }
+ template<typename... Args>
+ LValue call(LType type, LValue function, LValue arg1, Args... args) { return m_block->appendNew<B3::CCallValue>(m_proc, type, origin(), function, arg1, args...); }
+
+ template<typename FunctionType>
+ LValue operation(FunctionType function) { return constIntPtr(bitwise_cast<void*>(function)); }
+
+ void jump(LBasicBlock destination) { m_block->appendNew<B3::ControlValue>(m_proc, B3::Jump, origin(), B3::FrequentedBlock(destination)); }
+ void branch(LValue condition, LBasicBlock taken, Weight takenWeight, LBasicBlock notTaken, Weight notTakenWeight);
+ void branch(LValue condition, WeightedTarget taken, WeightedTarget notTaken)
+ {
+ branch(condition, taken.target(), taken.weight(), notTaken.target(), notTaken.weight());
+ }
+
+ // Branches to an already-created handler if true, "falls through" if false. Fall-through is
+ // simulated by creating a continuation for you.
+ void check(LValue condition, WeightedTarget taken, Weight notTakenWeight);
+
+ // Same as check(), but uses Weight::inverse() to compute the notTakenWeight.
+ void check(LValue condition, WeightedTarget taken);
+
+ template<typename VectorType>
+ void switchInstruction(LValue value, const VectorType& cases, LBasicBlock fallThrough, Weight fallThroughWeight)
+ {
+ B3::SwitchValue* switchValue = m_block->appendNew<B3::SwitchValue>(
+ m_proc, origin(), value, B3::FrequentedBlock(fallThrough));
+ for (const SwitchCase& switchCase : cases) {
+ int64_t value = switchCase.value()->asInt();
+ B3::FrequentedBlock target(switchCase.target(), switchCase.weight().frequencyClass());
+ switchValue->appendCase(B3::SwitchCase(value, target));
+ }
+ }
+
+ void ret(LValue value) { m_block->appendNew<B3::ControlValue>(m_proc, B3::Return, origin(), value); }
+
+ void unreachable() { m_block->appendNew<B3::ControlValue>(m_proc, B3::Oops, origin()); }
+
+ B3::CheckValue* speculate(LValue value)
+ {
+ return m_block->appendNew<B3::CheckValue>(m_proc, B3::Check, origin(), value);
+ }
+
+ B3::CheckValue* speculateAdd(LValue left, LValue right)
+ {
+ return m_block->appendNew<B3::CheckValue>(m_proc, B3::CheckAdd, origin(), left, right);
+ }
+
+ B3::CheckValue* speculateSub(LValue left, LValue right)
+ {
+ return m_block->appendNew<B3::CheckValue>(m_proc, B3::CheckSub, origin(), left, right);
+ }
+
+ B3::CheckValue* speculateMul(LValue left, LValue right)
+ {
+ return m_block->appendNew<B3::CheckValue>(m_proc, B3::CheckMul, origin(), left, right);
+ }
+
+ B3::PatchpointValue* patchpoint(LType type)
+ {
+ return m_block->appendNew<B3::PatchpointValue>(m_proc, type, origin());
+ }
+
+ void trap()
+ {
+ m_block->appendNew<B3::ControlValue>(m_proc, B3::Oops, origin());
+ }
+
+ ValueFromBlock anchor(LValue value)
+ {
+ B3::UpsilonValue* upsilon = m_block->appendNew<B3::UpsilonValue>(m_proc, origin(), value);
+ return ValueFromBlock(upsilon, m_block);
+ }
+
+#if PLATFORM(COCOA)
+#pragma mark - States
+#endif
+ B3::Procedure& m_proc;
+
+ DFG::Node* m_origin { nullptr };
+ LBasicBlock m_block { nullptr };
+ LBasicBlock m_nextBlock { nullptr };
+
+ AbstractHeapRepository* m_heaps;
+
+ double m_frequency { 1 };
+
+private:
+ OrderMaker<LBasicBlock> m_blockOrder;
+
+ template<typename Function, typename... Args>
+ LValue callWithoutSideEffects(B3::Type type, Function function, LValue arg1, Args... args)
+ {
+ return m_block->appendNew<B3::CCallValue>(m_proc, type, origin(), B3::Effects::none(),
+ m_block->appendNew<B3::ConstPtrValue>(m_proc, origin(), bitwise_cast<void*>(function)),
+ arg1, args...);
+ }
+
+};
+
+template<typename... Params>
+inline LValue Output::phi(LType type, ValueFromBlock value, Params... theRest)
+{
+ LValue phiNode = phi(type);
+ addIncomingToPhi(phiNode, value, theRest...);
+ return phiNode;
+}
+
+template<typename VectorType>
+inline LValue Output::phi(LType type, const VectorType& vector)
+{
+ LValue phiNode = phi(type);
+ for (const ValueFromBlock& valueFromBlock : vector)
+ addIncomingToPhi(phiNode, valueFromBlock);
+ return phiNode;
+}
+
+inline void Output::addIncomingToPhi(LValue phi, ValueFromBlock value)
+{
+ value.value()->as<B3::UpsilonValue>()->setPhi(phi);
+}
+
+template<typename... Params>
+inline void Output::addIncomingToPhi(LValue phi, ValueFromBlock value, Params... theRest)
+{
+ addIncomingToPhi(phi, value);
+ addIncomingToPhi(phi, theRest...);
+}
+
+inline LValue Output::bitCast(LValue value, LType type)
+{
+ ASSERT_UNUSED(type, type == int64 || type == doubleType);
+ return m_block->appendNew<B3::Value>(m_proc, B3::BitwiseCast, origin(), value);
+}
+
+inline LValue Output::fround(LValue doubleValue)
+{
+ return floatToDouble(doubleToFloat(doubleValue));
+}
+
+#if COMPILER(GCC_OR_CLANG)
+#pragma GCC diagnostic pop
+#endif // COMPILER(GCC_OR_CLANG)
+
+} } // namespace JSC::FTL
+
+#endif // ENABLE(FTL_JIT)
+
+#endif // FTLOutput_h