summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/ftl/FTLOutput.h
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2016-04-10 09:28:39 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2016-04-10 09:28:39 +0000
commit32761a6cee1d0dee366b885b7b9c777e67885688 (patch)
treed6bec92bebfb216f4126356e55518842c2f476a1 /Source/JavaScriptCore/ftl/FTLOutput.h
parenta4e969f4965059196ca948db781e52f7cfebf19e (diff)
downloadWebKitGtk-tarball-32761a6cee1d0dee366b885b7b9c777e67885688.tar.gz
webkitgtk-2.4.11webkitgtk-2.4.11
Diffstat (limited to 'Source/JavaScriptCore/ftl/FTLOutput.h')
-rw-r--r--Source/JavaScriptCore/ftl/FTLOutput.h697
1 files changed, 297 insertions, 400 deletions
diff --git a/Source/JavaScriptCore/ftl/FTLOutput.h b/Source/JavaScriptCore/ftl/FTLOutput.h
index dd50c2411..2ec873503 100644
--- a/Source/JavaScriptCore/ftl/FTLOutput.h
+++ b/Source/JavaScriptCore/ftl/FTLOutput.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013-2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -20,259 +20,228 @@
* 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.
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef FTLOutput_h
#define FTLOutput_h
-#include "DFGCommon.h"
+#include <wtf/Platform.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 "DFGCommon.h"
+#include "FTLAbbreviations.h"
#include "FTLAbstractHeapRepository.h"
#include "FTLCommonValues.h"
-#include "FTLState.h"
-#include "FTLSwitchCase.h"
+#include "FTLIntrinsicRepository.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 {
+namespace JSC { namespace FTL {
+
+// Idiomatic LLVM IR builder specifically designed for FTL. This uses our own lowering
+// terminology, and has some of its own notions:
+//
+// We say that a "reference" is what LLVM considers to be a "pointer". That is, it has
+// an element type and can be passed directly to memory access instructions. Note that
+// broadly speaking the users of FTL::Output should only use references for alloca'd
+// slots for mutable local variables.
+//
+// We say that a "pointer" is what LLVM considers to be a pointer-width integer.
+//
+// We say that a "typed pointer" is a pointer that carries TBAA meta-data (i.e. an
+// AbstractHeap). These should usually not have further computation performed on them
+// prior to access, though there are exceptions (like offsetting into the payload of
+// a typed pointer to a JSValue).
+//
+// We say that "get" and "set" are what LLVM considers to be "load" and "store". Get
+// and set take references.
+//
+// We say that "load" and "store" are operations that take a typed pointer. These
+// operations translate the pointer into a reference (or, a pointer in LLVM-speak),
+// emit get or set on the reference (or, load and store in LLVM-speak), and apply the
+// TBAA meta-data to the get or set.
enum Scale { ScaleOne, ScaleTwo, ScaleFour, ScaleEight, ScalePtr };
-class Output : public CommonValues {
+class Output : public IntrinsicRepository {
public:
- Output(State&);
+ Output(LContext);
~Output();
-
- void initialize(AbstractHeapRepository&);
-
- void setFrequency(double value)
+
+ void initialize(LModule module, LValue function, AbstractHeapRepository& heaps)
{
- m_frequency = value;
+ IntrinsicRepository::initialize(module);
+ m_function = function;
+ m_heaps = &heaps;
}
-
- 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); }
+
+ LBasicBlock appendTo(LBasicBlock block, LBasicBlock nextBlock)
+ {
+ appendTo(block);
+ return insertNewBlocksBefore(nextBlock);
+ }
+
+ void appendTo(LBasicBlock block)
+ {
+ m_block = block;
+
+ llvm->PositionBuilderAtEnd(m_builder, block);
+ }
+ LBasicBlock newBlock(const char* name = "")
+ {
+ if (!m_nextBlock)
+ return appendBasicBlock(m_context, m_function, name);
+ return insertBasicBlock(m_context, m_nextBlock, name);
+ }
+
+ LValue param(unsigned index) { return getParam(m_function, index); }
+ LValue constBool(bool value) { return constInt(boolean, value); }
+ LValue constInt8(int8_t value) { return constInt(int8, value); }
+ LValue constInt32(int32_t value) { return constInt(int32, value); }
template<typename T>
- LValue constIntPtr(T* value) { return m_block->appendNew<B3::ConstPtrValue>(m_proc, origin(), value); }
+ LValue constIntPtr(T* value) { return constInt(intPtr, bitwise_cast<intptr_t>(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);
+ LValue constIntPtr(T value) { return constInt(intPtr, static_cast<intptr_t>(value)); }
+ LValue constInt64(int64_t value) { return constInt(int64, value); }
+ LValue constDouble(double value) { return constReal(doubleType, value); }
+
+ LValue phi(LType type) { return buildPhi(m_builder, type); }
+ LValue phi(LType type, ValueFromBlock value1)
+ {
+ return buildPhi(m_builder, type, value1);
+ }
+ LValue phi(LType type, ValueFromBlock value1, ValueFromBlock value2)
+ {
+ return buildPhi(m_builder, type, value1, value2);
+ }
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)
+ LValue phi(LType type, const VectorType& vector)
{
- double (*sinDouble)(double) = sin;
- return callWithoutSideEffects(B3::Double, sinDouble, value);
+ LValue result = phi(type);
+ for (unsigned i = 0; i < vector.size(); ++i)
+ addIncoming(result, vector[i]);
+ return result;
}
- LValue doubleCos(LValue value)
+
+ LValue add(LValue left, LValue right) { return buildAdd(m_builder, left, right); }
+ LValue sub(LValue left, LValue right) { return buildSub(m_builder, left, right); }
+ LValue mul(LValue left, LValue right) { return buildMul(m_builder, left, right); }
+ LValue div(LValue left, LValue right) { return buildDiv(m_builder, left, right); }
+ LValue rem(LValue left, LValue right) { return buildRem(m_builder, left, right); }
+ LValue neg(LValue value) { return buildNeg(m_builder, value); }
+
+ LValue doubleAdd(LValue left, LValue right) { return buildFAdd(m_builder, left, right); }
+ LValue doubleSub(LValue left, LValue right) { return buildFSub(m_builder, left, right); }
+ LValue doubleMul(LValue left, LValue right) { return buildFMul(m_builder, left, right); }
+ LValue doubleDiv(LValue left, LValue right) { return buildFDiv(m_builder, left, right); }
+ LValue doubleRem(LValue left, LValue right) { return buildFRem(m_builder, left, right); }
+ LValue doubleNeg(LValue value) { return buildFNeg(m_builder, value); }
+
+ LValue bitAnd(LValue left, LValue right) { return buildAnd(m_builder, left, right); }
+ LValue bitOr(LValue left, LValue right) { return buildOr(m_builder, left, right); }
+ LValue bitXor(LValue left, LValue right) { return buildXor(m_builder, left, right); }
+ LValue shl(LValue left, LValue right) { return buildShl(m_builder, left, right); }
+ LValue aShr(LValue left, LValue right) { return buildAShr(m_builder, left, right); }
+ LValue lShr(LValue left, LValue right) { return buildLShr(m_builder, left, right); }
+ LValue bitNot(LValue value) { return buildNot(m_builder, value); }
+
+ LValue insertElement(LValue vector, LValue element, LValue index) { return buildInsertElement(m_builder, vector, element, index); }
+
+ LValue addWithOverflow32(LValue left, LValue right)
{
- double (*cosDouble)(double) = cos;
- return callWithoutSideEffects(B3::Double, cosDouble, value);
+ return call(addWithOverflow32Intrinsic(), left, right);
}
-
- LValue doublePow(LValue xOperand, LValue yOperand)
+ LValue subWithOverflow32(LValue left, LValue right)
{
- double (*powDouble)(double, double) = pow;
- return callWithoutSideEffects(B3::Double, powDouble, xOperand, yOperand);
+ return call(subWithOverflow32Intrinsic(), left, right);
}
-
- 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)
+ LValue mulWithOverflow32(LValue left, LValue right)
{
- double (*logDouble)(double) = log;
- return callWithoutSideEffects(B3::Double, logDouble, value);
+ return call(mulWithOverflow32Intrinsic(), left, right);
}
-
- 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)
+ LValue addWithOverflow64(LValue left, LValue right)
{
- if (value->type() == type)
- return value;
- return m_block->appendNew<B3::Value>(m_proc, B3::ZExt32, origin(), value);
+ return call(addWithOverflow64Intrinsic(), left, right);
}
- 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)
+ LValue subWithOverflow64(LValue left, LValue right)
{
- return value->type() == B3::Int32 ? value :
- m_block->appendNew<B3::Value>(m_proc, B3::Trunc, origin(), value);
+ return call(subWithOverflow64Intrinsic(), left, right);
}
- 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)
+ LValue mulWithOverflow64(LValue left, LValue right)
{
- ASSERT(value->type() == B3::Int32);
- store(value, pointer);
+ return call(mulWithOverflow64Intrinsic(), left, right);
}
- void store64(LValue value, TypedPointer pointer)
+ LValue doubleAbs(LValue value)
{
- ASSERT(value->type() == B3::Int64);
- store(value, pointer);
+ return call(doubleAbsIntrinsic(), value);
}
- void storePtr(LValue value, TypedPointer pointer)
+
+ static bool hasSensibleDoubleToInt() { return isX86(); }
+ LValue sensibleDoubleToInt(LValue value)
{
- ASSERT(value->type() == B3::pointerType());
- store(value, pointer);
+ RELEASE_ASSERT(isX86());
+ return call(
+ x86SSE2CvtTSD2SIIntrinsic(),
+ insertElement(
+ insertElement(getUndef(vectorType(doubleType, 2)), value, int32Zero),
+ doubleZero, int32One));
}
- void storeFloat(LValue value, TypedPointer pointer)
+
+ LValue signExt(LValue value, LType type) { return buildSExt(m_builder, value, type); }
+ LValue zeroExt(LValue value, LType type) { return buildZExt(m_builder, value, type); }
+ LValue fpToInt(LValue value, LType type) { return buildFPToSI(m_builder, value, type); }
+ LValue fpToUInt(LValue value, LType type) { return buildFPToUI(m_builder, value, type); }
+ LValue fpToInt32(LValue value) { return fpToInt(value, int32); }
+ LValue fpToUInt32(LValue value) { return fpToUInt(value, int32); }
+ LValue intToFP(LValue value, LType type) { return buildSIToFP(m_builder, value, type); }
+ LValue intToDouble(LValue value) { return intToFP(value, doubleType); }
+ LValue unsignedToFP(LValue value, LType type) { return buildUIToFP(m_builder, value, type); }
+ LValue unsignedToDouble(LValue value) { return unsignedToFP(value, doubleType); }
+ LValue intCast(LValue value, LType type) { return buildIntCast(m_builder, value, type); }
+ LValue castToInt32(LValue value) { return intCast(value, int32); }
+ LValue fpCast(LValue value, LType type) { return buildFPCast(m_builder, value, type); }
+ LValue intToPtr(LValue value, LType type) { return buildIntToPtr(m_builder, value, type); }
+ LValue bitCast(LValue value, LType type) { return buildBitCast(m_builder, value, type); }
+
+ LValue alloca(LType type) { return buildAlloca(m_builder, type); }
+ LValue get(LValue reference) { return buildLoad(m_builder, reference); }
+ LValue set(LValue value, LValue reference) { return buildStore(m_builder, value, reference); }
+
+ LValue load(TypedPointer pointer, LType refType)
{
- ASSERT(value->type() == B3::Float);
- store(value, pointer);
+ LValue result = get(intToPtr(pointer.value(), refType));
+ pointer.heap().decorateInstruction(result, *m_heaps);
+ return result;
}
- void storeDouble(LValue value, TypedPointer pointer)
+ void store(LValue value, TypedPointer pointer, LType refType)
{
- ASSERT(value->type() == B3::Double);
- store(value, pointer);
+ LValue result = set(value, intToPtr(pointer.value(), refType));
+ pointer.heap().decorateInstruction(result, *m_heaps);
}
-
- 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 load8(TypedPointer pointer) { return load(pointer, ref8); }
+ LValue load16(TypedPointer pointer) { return load(pointer, ref16); }
+ LValue load32(TypedPointer pointer) { return load(pointer, ref32); }
+ LValue load64(TypedPointer pointer) { return load(pointer, ref64); }
+ LValue loadPtr(TypedPointer pointer) { return load(pointer, refPtr); }
+ LValue loadFloat(TypedPointer pointer) { return load(pointer, refFloat); }
+ LValue loadDouble(TypedPointer pointer) { return load(pointer, refDouble); }
+ void store8(LValue value, TypedPointer pointer) { store(value, pointer, ref8); }
+ void store16(LValue value, TypedPointer pointer) { store(value, pointer, ref16); }
+ void store32(LValue value, TypedPointer pointer) { store(value, pointer, ref32); }
+ void store64(LValue value, TypedPointer pointer) { store(value, pointer, ref64); }
+ void storePtr(LValue value, TypedPointer pointer) { store(value, pointer, refPtr); }
+ void storeFloat(LValue value, TypedPointer pointer) { store(value, pointer, refFloat); }
+ void storeDouble(LValue value, TypedPointer pointer) { store(value, pointer, refDouble); }
LValue addPtr(LValue value, ptrdiff_t immediate = 0)
{
@@ -280,7 +249,7 @@ public:
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)
@@ -290,13 +259,36 @@ public:
// 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)
+ TypedPointer address(LValue base, const AbstractField& field, ptrdiff_t offset = 0)
{
return address(field, base, offset + field.offset());
}
-
- LValue baseIndex(LValue base, LValue index, Scale, ptrdiff_t offset = 0);
-
+
+ LValue baseIndex(LValue base, LValue index, Scale scale, ptrdiff_t offset = 0)
+ {
+ LValue accumulatedOffset;
+
+ switch (scale) {
+ case ScaleOne:
+ accumulatedOffset = index;
+ break;
+ case ScaleTwo:
+ accumulatedOffset = shl(index, intPtrOne);
+ break;
+ case ScaleFour:
+ accumulatedOffset = shl(index, intPtrTwo);
+ break;
+ case ScaleEight:
+ case ScalePtr:
+ accumulatedOffset = shl(index, intPtrThree);
+ break;
+ }
+
+ if (offset)
+ accumulatedOffset = add(accumulatedOffset, constIntPtr(offset));
+
+ return add(base, accumulatedOffset);
+ }
TypedPointer baseIndex(const AbstractHeap& heap, LValue base, LValue index, Scale scale, ptrdiff_t offset = 0)
{
return TypedPointer(heap, baseIndex(base, index, scale, offset));
@@ -305,227 +297,132 @@ public:
{
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 load8(LValue base, const AbstractField& field) { return load8(address(base, field)); }
+ LValue load16(LValue base, const AbstractField& field) { return load16(address(base, field)); }
+ LValue load32(LValue base, const AbstractField& field) { return load32(address(base, field)); }
+ LValue load64(LValue base, const AbstractField& field) { return load64(address(base, field)); }
+ LValue loadPtr(LValue base, const AbstractField& field) { return loadPtr(address(base, field)); }
+ LValue loadDouble(LValue base, const AbstractField& field) { return loadDouble(address(base, field)); }
+ void store32(LValue value, LValue base, const AbstractField& field) { store32(value, address(base, field)); }
+ void store64(LValue value, LValue base, const AbstractField& field) { store64(value, address(base, field)); }
+ void storePtr(LValue value, LValue base, const AbstractField& field) { storePtr(value, address(base, field)); }
+ void storeDouble(LValue value, LValue base, const AbstractField& field) { storeDouble(value, address(base, field)); }
+
+ LValue icmp(LIntPredicate cond, LValue left, LValue right) { return buildICmp(m_builder, cond, left, right); }
+ LValue equal(LValue left, LValue right) { return icmp(LLVMIntEQ, left, right); }
+ LValue notEqual(LValue left, LValue right) { return icmp(LLVMIntNE, left, right); }
+ LValue above(LValue left, LValue right) { return icmp(LLVMIntUGT, left, right); }
+ LValue aboveOrEqual(LValue left, LValue right) { return icmp(LLVMIntUGE, left, right); }
+ LValue below(LValue left, LValue right) { return icmp(LLVMIntULT, left, right); }
+ LValue belowOrEqual(LValue left, LValue right) { return icmp(LLVMIntULE, left, right); }
+ LValue greaterThan(LValue left, LValue right) { return icmp(LLVMIntSGT, left, right); }
+ LValue greaterThanOrEqual(LValue left, LValue right) { return icmp(LLVMIntSGE, left, right); }
+ LValue lessThan(LValue left, LValue right) { return icmp(LLVMIntSLT, left, right); }
+ LValue lessThanOrEqual(LValue left, LValue right) { return icmp(LLVMIntSLE, left, right); }
+
+ LValue fcmp(LRealPredicate cond, LValue left, LValue right) { return buildFCmp(m_builder, cond, left, right); }
+ LValue doubleEqual(LValue left, LValue right) { return fcmp(LLVMRealOEQ, left, right); }
+ LValue doubleNotEqualOrUnordered(LValue left, LValue right) { return fcmp(LLVMRealUNE, left, right); }
+ LValue doubleLessThan(LValue left, LValue right) { return fcmp(LLVMRealOLT, left, right); }
+ LValue doubleLessThanOrEqual(LValue left, LValue right) { return fcmp(LLVMRealOLE, left, right); }
+ LValue doubleGreaterThan(LValue left, LValue right) { return fcmp(LLVMRealOGT, left, right); }
+ LValue doubleGreaterThanOrEqual(LValue left, LValue right) { return fcmp(LLVMRealOGE, left, right); }
+ LValue doubleEqualOrUnordered(LValue left, LValue right) { return fcmp(LLVMRealUEQ, left, right); }
+ LValue doubleNotEqual(LValue left, LValue right) { return fcmp(LLVMRealONE, left, right); }
+ LValue doubleLessThanOrUnordered(LValue left, LValue right) { return fcmp(LLVMRealULT, left, right); }
+ LValue doubleLessThanOrEqualOrUnordered(LValue left, LValue right) { return fcmp(LLVMRealULE, left, right); }
+ LValue doubleGreaterThanOrUnordered(LValue left, LValue right) { return fcmp(LLVMRealUGT, left, right); }
+ LValue doubleGreaterThanOrEqualOrUnordered(LValue left, LValue right) { return fcmp(LLVMRealUGE, left, right); }
+
+ LValue isZero8(LValue value) { return equal(value, int8Zero); }
+ LValue notZero8(LValue value) { return notEqual(value, int8Zero); }
+ LValue isZero32(LValue value) { return equal(value, int32Zero); }
+ LValue notZero32(LValue value) { return notEqual(value, int32Zero); }
+ LValue isZero64(LValue value) { return equal(value, int64Zero); }
+ LValue notZero64(LValue value) { return notEqual(value, int64Zero); }
+ LValue isNull(LValue value) { return equal(value, intPtrZero); }
+ LValue notNull(LValue value) { return notEqual(value, intPtrZero); }
+
+ LValue testIsZero8(LValue value, LValue mask) { return isZero8(bitAnd(value, mask)); }
+ LValue testNonZero8(LValue value, LValue mask) { return notZero8(bitAnd(value, mask)); }
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(); }
-
+
+ LValue select(LValue value, LValue taken, LValue notTaken) { return buildSelect(m_builder, value, taken, notTaken); }
+ LValue extractValue(LValue aggVal, unsigned index) { return buildExtractValue(m_builder, aggVal, index); }
+
+ LValue fence(LAtomicOrdering ordering = LLVMAtomicOrderingSequentiallyConsistent, SynchronizationScope scope = CrossThread) { return buildFence(m_builder, ordering, scope); }
+ LValue fenceAcqRel() { return fence(LLVMAtomicOrderingAcquireRelease); }
+
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...); }
-
+ LValue call(LValue function, const VectorType& vector) { return buildCall(m_builder, function, vector); }
+ LValue call(LValue function) { return buildCall(m_builder, function); }
+ LValue call(LValue function, LValue arg1) { return buildCall(m_builder, function, arg1); }
+ LValue call(LValue function, LValue arg1, LValue arg2) { return buildCall(m_builder, function, arg1, arg2); }
+ LValue call(LValue function, LValue arg1, LValue arg2, LValue arg3) { return buildCall(m_builder, function, arg1, arg2, arg3); }
+ LValue call(LValue function, LValue arg1, LValue arg2, LValue arg3, LValue arg4) { return buildCall(m_builder, function, arg1, arg2, arg3, arg4); }
+ LValue call(LValue function, LValue arg1, LValue arg2, LValue arg3, LValue arg4, LValue arg5) { return buildCall(m_builder, function, arg1, arg2, arg3, arg4, arg5); }
+ LValue call(LValue function, LValue arg1, LValue arg2, LValue arg3, LValue arg4, LValue arg5, LValue arg6) { return buildCall(m_builder, function, arg1, arg2, arg3, arg4, arg5, arg6); }
+ LValue call(LValue function, LValue arg1, LValue arg2, LValue arg3, LValue arg4, LValue arg5, LValue arg6, LValue arg7) { return buildCall(m_builder, function, arg1, arg2, arg3, arg4, arg5, arg6, arg7); }
+ LValue call(LValue function, LValue arg1, LValue arg2, LValue arg3, LValue arg4, LValue arg5, LValue arg6, LValue arg7, LValue arg8) { return buildCall(m_builder, function, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); }
+
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)
+ LValue operation(FunctionType function)
{
- branch(condition, taken.target(), taken.weight(), notTaken.target(), notTaken.weight());
+ return intToPtr(constIntPtr(function), pointerType(operationType(function)));
}
-
- // 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);
+ void jump(LBasicBlock destination) { buildBr(m_builder, destination); }
+ void branch(LValue condition, LBasicBlock taken, LBasicBlock notTaken) { buildCondBr(m_builder, condition, taken, notTaken); }
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)
+ void switchInstruction(LValue value, const VectorType& cases, LBasicBlock fallThrough) { buildSwitch(m_builder, value, cases, fallThrough); }
+ void ret(LValue value) { buildRet(m_builder, value); }
+
+ void unreachable() { buildUnreachable(m_builder); }
+
+ void trap()
{
- return m_block->appendNew<B3::CheckValue>(m_proc, B3::CheckMul, origin(), left, right);
+ call(trapIntrinsic());
}
-
- B3::PatchpointValue* patchpoint(LType type)
+
+ void crashNonTerminal()
{
- return m_block->appendNew<B3::PatchpointValue>(m_proc, type, origin());
+ call(intToPtr(constIntPtr(abort), pointerType(functionType(voidType))));
}
-
- void trap()
+ void crash()
{
- m_block->appendNew<B3::ControlValue>(m_proc, B3::Oops, origin());
+ crashNonTerminal();
+ unreachable();
}
-
+
ValueFromBlock anchor(LValue value)
{
- B3::UpsilonValue* upsilon = m_block->appendNew<B3::UpsilonValue>(m_proc, origin(), value);
- return ValueFromBlock(upsilon, m_block);
+ return ValueFromBlock(value, 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...);
- }
-
+ LValue m_function;
+ AbstractHeapRepository* m_heaps;
+ LBuilder m_builder;
+ LBasicBlock m_block;
+ LBasicBlock m_nextBlock;
};
-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)
+#define FTL_NEW_BLOCK(output, nameArguments) \
+ (LIKELY(!::JSC::DFG::verboseCompilationEnabled()) \
+ ? (output).newBlock() \
+ : (output).newBlock((toCString nameArguments).data()))
} } // namespace JSC::FTL
#endif // ENABLE(FTL_JIT)
#endif // FTLOutput_h
+