From 9cafe070113167f2d7fc1365e1dc783a5f008c84 Mon Sep 17 00:00:00 2001 From: Sean Stangl Date: Wed, 10 Jun 2015 20:08:45 -0700 Subject: [PATCH] Bug 1173642 - Import unimplemented ARM64 Ion components. r=efaust --- js/src/jit/arm64/CodeGenerator-arm64.cpp | 746 +++++++++++++++++++++++ js/src/jit/arm64/CodeGenerator-arm64.h | 276 +++++++++ js/src/jit/arm64/LIR-arm64.h | 467 ++++++++++++++ js/src/jit/arm64/LOpcodes-arm64.h | 29 + js/src/jit/arm64/Lowering-arm64.cpp | 321 ++++++++++ js/src/jit/arm64/Lowering-arm64.h | 121 ++++ 6 files changed, 1960 insertions(+) create mode 100644 js/src/jit/arm64/CodeGenerator-arm64.cpp create mode 100644 js/src/jit/arm64/CodeGenerator-arm64.h create mode 100644 js/src/jit/arm64/LIR-arm64.h create mode 100644 js/src/jit/arm64/LOpcodes-arm64.h create mode 100644 js/src/jit/arm64/Lowering-arm64.cpp create mode 100644 js/src/jit/arm64/Lowering-arm64.h diff --git a/js/src/jit/arm64/CodeGenerator-arm64.cpp b/js/src/jit/arm64/CodeGenerator-arm64.cpp new file mode 100644 index 00000000000..fd037b99063 --- /dev/null +++ b/js/src/jit/arm64/CodeGenerator-arm64.cpp @@ -0,0 +1,746 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sts=4 et sw=4 tw=99: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "jit/arm64/CodeGenerator-arm64.h" + +#include "mozilla/MathAlgorithms.h" + +#include "jscntxt.h" +#include "jscompartment.h" +#include "jsnum.h" + +#include "jit/CodeGenerator.h" +#include "jit/JitCompartment.h" +#include "jit/JitFrames.h" +#include "jit/MIR.h" +#include "jit/MIRGraph.h" +#include "vm/Shape.h" +#include "vm/TraceLogging.h" + +#include "jsscriptinlines.h" + +#include "jit/shared/CodeGenerator-shared-inl.h" + +using namespace js; +using namespace js::jit; + +using mozilla::FloorLog2; +using mozilla::NegativeInfinity; +using JS::GenericNaN; + +// shared +CodeGeneratorARM64::CodeGeneratorARM64(MIRGenerator* gen, LIRGraph* graph, MacroAssembler* masm) + : CodeGeneratorShared(gen, graph, masm) +{ +} + +bool +CodeGeneratorARM64::generatePrologue() +{ + MOZ_CRASH("generatePrologue"); +} + +bool +CodeGeneratorARM64::generateEpilogue() +{ + MOZ_CRASH("generateEpilogue"); +} + +bool +CodeGeneratorARM64::generateOutOfLineCode() +{ + MOZ_CRASH("generateOutOfLineCode"); +} + +void +CodeGeneratorARM64::emitBranch(Assembler::Condition cond, MBasicBlock* mirTrue, MBasicBlock* mirFalse) +{ + MOZ_CRASH("emitBranch"); +} + +void +OutOfLineBailout::accept(CodeGeneratorARM64* codegen) +{ + MOZ_CRASH("accept"); +} + +void +CodeGeneratorARM64::visitTestIAndBranch(LTestIAndBranch* test) +{ + MOZ_CRASH("visitTestIAndBranch"); +} + +void +CodeGeneratorARM64::visitCompare(LCompare* comp) +{ + MOZ_CRASH("visitCompare"); +} + +void +CodeGeneratorARM64::visitCompareAndBranch(LCompareAndBranch* comp) +{ + MOZ_CRASH("visitCompareAndBranch"); +} + +void +CodeGeneratorARM64::bailoutIf(Assembler::Condition condition, LSnapshot* snapshot) +{ + MOZ_CRASH("bailoutIf"); +} + +void +CodeGeneratorARM64::bailoutFrom(Label* label, LSnapshot* snapshot) +{ + MOZ_CRASH("bailoutFrom"); +} + +void +CodeGeneratorARM64::bailout(LSnapshot* snapshot) +{ + MOZ_CRASH("bailout"); +} + +void +CodeGeneratorARM64::visitOutOfLineBailout(OutOfLineBailout* ool) +{ + MOZ_CRASH("visitOutOfLineBailout"); +} + +void +CodeGeneratorARM64::visitMinMaxD(LMinMaxD* ins) +{ + MOZ_CRASH("visitMinMaxD"); +} + +void +CodeGeneratorARM64::visitMinMaxF(LMinMaxF* ins) +{ + MOZ_CRASH("visitMinMaxF"); +} + +void +CodeGeneratorARM64::visitAbsD(LAbsD* ins) +{ + MOZ_CRASH("visitAbsD"); +} + +void +CodeGeneratorARM64::visitAbsF(LAbsF* ins) +{ + MOZ_CRASH("visitAbsF"); +} + +void +CodeGeneratorARM64::visitSqrtD(LSqrtD* ins) +{ + MOZ_CRASH("visitSqrtD"); +} + +void +CodeGeneratorARM64::visitSqrtF(LSqrtF* ins) +{ + MOZ_CRASH("visitSqrtF"); +} + +// FIXME: Uh, is this a static function? It looks like it is... +template +ARMRegister +toWRegister(const T* a) +{ + return ARMRegister(ToRegister(a), 32); +} + +// FIXME: Uh, is this a static function? It looks like it is... +template +ARMRegister +toXRegister(const T* a) +{ + return ARMRegister(ToRegister(a), 64); +} + +js::jit::Operand +toWOperand(const LAllocation* a) +{ + MOZ_CRASH("toWOperand"); +} + +vixl::CPURegister +ToCPURegister(const LAllocation* a, Scalar::Type type) +{ + MOZ_CRASH("ToCPURegister"); +} + +vixl::CPURegister +ToCPURegister(const LDefinition* d, Scalar::Type type) +{ + return ToCPURegister(d->output(), type); +} + +void +CodeGeneratorARM64::visitAddI(LAddI* ins) +{ + MOZ_CRASH("visitAddI"); +} + +void +CodeGeneratorARM64::visitSubI(LSubI* ins) +{ + MOZ_CRASH("visitSubI"); +} + +void +CodeGeneratorARM64::visitMulI(LMulI* ins) +{ + MOZ_CRASH("visitMulI"); +} + + +void +CodeGeneratorARM64::visitDivI(LDivI* ins) +{ + MOZ_CRASH("visitDivI"); +} + +void +CodeGeneratorARM64::visitDivPowTwoI(LDivPowTwoI* ins) +{ + MOZ_CRASH("CodeGeneratorARM64::visitDivPowTwoI"); +} + +void +CodeGeneratorARM64::modICommon(MMod* mir, Register lhs, Register rhs, Register output, + LSnapshot* snapshot, Label& done) +{ + MOZ_CRASH("CodeGeneratorARM64::modICommon"); +} + +void +CodeGeneratorARM64::visitModI(LModI* ins) +{ + MOZ_CRASH("visitModI"); +} + +void +CodeGeneratorARM64::visitModPowTwoI(LModPowTwoI* ins) +{ + MOZ_CRASH("visitModPowTwoI"); +} + +void +CodeGeneratorARM64::visitModMaskI(LModMaskI* ins) +{ + MOZ_CRASH("CodeGeneratorARM64::visitModMaskI"); +} + +void +CodeGeneratorARM64::visitBitNotI(LBitNotI* ins) +{ + MOZ_CRASH("visitBitNotI"); +} + +void +CodeGeneratorARM64::visitBitOpI(LBitOpI* ins) +{ + MOZ_CRASH("visitBitOpI"); +} + +void +CodeGeneratorARM64::visitShiftI(LShiftI* ins) +{ + MOZ_CRASH("visitShiftI"); +} + +void +CodeGeneratorARM64::visitUrshD(LUrshD* ins) +{ + MOZ_CRASH("visitUrshD"); +} + +void +CodeGeneratorARM64::visitPowHalfD(LPowHalfD* ins) +{ + MOZ_CRASH("visitPowHalfD"); +} + +MoveOperand +CodeGeneratorARM64::toMoveOperand(const LAllocation a) const +{ + MOZ_CRASH("toMoveOperand"); +} + +class js::jit::OutOfLineTableSwitch : public OutOfLineCodeBase +{ + MTableSwitch* mir_; + Vector codeLabels_; + + void accept(CodeGeneratorARM64* codegen) { + codegen->visitOutOfLineTableSwitch(this); + } + + public: + OutOfLineTableSwitch(TempAllocator& alloc, MTableSwitch* mir) + : mir_(mir), + codeLabels_(alloc) + { } + + MTableSwitch* mir() const { + return mir_; + } + + bool addCodeLabel(CodeLabel label) { + return codeLabels_.append(label); + } + CodeLabel codeLabel(unsigned i) { + return codeLabels_[i]; + } +}; + +void +CodeGeneratorARM64::visitOutOfLineTableSwitch(OutOfLineTableSwitch* ool) +{ + MOZ_CRASH("visitOutOfLineTableSwitch"); +} + +void +CodeGeneratorARM64::emitTableSwitchDispatch(MTableSwitch* mir, Register index_, Register base_) +{ + MOZ_CRASH("emitTableSwitchDispatch"); +} + +void +CodeGeneratorARM64::visitMathD(LMathD* math) +{ + MOZ_CRASH("visitMathD"); +} + +void +CodeGeneratorARM64::visitMathF(LMathF* math) +{ + MOZ_CRASH("visitMathF"); +} + +void +CodeGeneratorARM64::visitFloor(LFloor* lir) +{ + MOZ_CRASH("visitFloor"); +} + +void +CodeGeneratorARM64::visitFloorF(LFloorF* lir) +{ + MOZ_CRASH("visitFloorF"); +} + +void +CodeGeneratorARM64::visitCeil(LCeil* lir) +{ + MOZ_CRASH("visitCeil"); +} + +void +CodeGeneratorARM64::visitCeilF(LCeilF* lir) +{ + MOZ_CRASH("visitCeilF"); +} + +void +CodeGeneratorARM64::visitRound(LRound* lir) +{ + MOZ_CRASH("visitRound"); +} + +void +CodeGeneratorARM64::visitRoundF(LRoundF* lir) +{ + MOZ_CRASH("visitRoundF"); +} + +void +CodeGeneratorARM64::visitClzI(LClzI* lir) +{ + MOZ_CRASH("visitClzI"); +} + +void +CodeGeneratorARM64::emitRoundDouble(FloatRegister src, Register dest, Label* fail) +{ + MOZ_CRASH("CodeGeneratorARM64::emitRoundDouble"); +} + +void +CodeGeneratorARM64::visitTruncateDToInt32(LTruncateDToInt32* ins) +{ + MOZ_CRASH("visitTruncateDToInt32"); +} + +void +CodeGeneratorARM64::visitTruncateFToInt32(LTruncateFToInt32* ins) +{ + MOZ_CRASH("visitTruncateFToInt32"); +} + +static const uint32_t FrameSizes[] = { 128, 256, 512, 1024 }; + +FrameSizeClass +FrameSizeClass::FromDepth(uint32_t frameDepth) +{ + return FrameSizeClass::None(); +} + +FrameSizeClass +FrameSizeClass::ClassLimit() +{ + return FrameSizeClass(0); +} + +uint32_t +FrameSizeClass::frameSize() const +{ + MOZ_CRASH("arm64 does not use frame size classes"); +} + +ValueOperand +CodeGeneratorARM64::ToValue(LInstruction* ins, size_t pos) +{ + return ValueOperand(ToRegister(ins->getOperand(pos))); +} + +ValueOperand +CodeGeneratorARM64::ToOutValue(LInstruction* ins) +{ + Register payloadReg = ToRegister(ins->getDef(0)); + return ValueOperand(payloadReg); +} + +ValueOperand +CodeGeneratorARM64::ToTempValue(LInstruction* ins, size_t pos) +{ + MOZ_CRASH("CodeGeneratorARM64::ToTempValue"); +} + +void +CodeGeneratorARM64::visitValue(LValue* value) +{ + MOZ_CRASH("visitValue"); +} + +void +CodeGeneratorARM64::visitBox(LBox* box) +{ + MOZ_CRASH("visitBox"); +} + +void +CodeGeneratorARM64::visitUnbox(LUnbox* unbox) +{ + MOZ_CRASH("visitUnbox"); +} + +void +CodeGeneratorARM64::visitDouble(LDouble* ins) +{ + MOZ_CRASH("visitDouble"); +} + +void +CodeGeneratorARM64::visitFloat32(LFloat32* ins) +{ + MOZ_CRASH("visitFloat32"); +} + +Register +CodeGeneratorARM64::splitTagForTest(const ValueOperand& value) +{ + MOZ_CRASH("splitTagForTest"); +} + +void +CodeGeneratorARM64::visitTestDAndBranch(LTestDAndBranch* test) +{ + MOZ_CRASH("visitTestDAndBranch"); +} + +void +CodeGeneratorARM64::visitTestFAndBranch(LTestFAndBranch* test) +{ + MOZ_CRASH("visitTestFAndBranch"); +} + +void +CodeGeneratorARM64::visitCompareD(LCompareD* comp) +{ + MOZ_CRASH("visitCompareD"); +} + +void +CodeGeneratorARM64::visitCompareF(LCompareF* comp) +{ + MOZ_CRASH("visitCompareF"); +} + +void +CodeGeneratorARM64::visitCompareDAndBranch(LCompareDAndBranch* comp) +{ + MOZ_CRASH("visitCompareDAndBranch"); +} + +void +CodeGeneratorARM64::visitCompareFAndBranch(LCompareFAndBranch* comp) +{ + MOZ_CRASH("visitCompareFAndBranch"); +} + +void +CodeGeneratorARM64::visitCompareB(LCompareB* lir) +{ + MOZ_CRASH("visitCompareB"); +} + +void +CodeGeneratorARM64::visitCompareBAndBranch(LCompareBAndBranch* lir) +{ + MOZ_CRASH("visitCompareBAndBranch"); +} + +void +CodeGeneratorARM64::visitCompareV(LCompareV* lir) +{ + MOZ_CRASH("visitCompareV"); +} + +void +CodeGeneratorARM64::visitCompareVAndBranch(LCompareVAndBranch* lir) +{ + MOZ_CRASH("visitCompareVAndBranch"); +} + +void +CodeGeneratorARM64::visitBitAndAndBranch(LBitAndAndBranch* baab) +{ + MOZ_CRASH("visitBitAndAndBranch"); +} + +void +CodeGeneratorARM64::visitAsmJSUInt32ToDouble(LAsmJSUInt32ToDouble* lir) +{ + MOZ_CRASH("visitAsmJSUInt32ToDouble"); +} + +void +CodeGeneratorARM64::visitAsmJSUInt32ToFloat32(LAsmJSUInt32ToFloat32* lir) +{ + MOZ_CRASH("visitAsmJSUInt32ToFloat32"); +} + +void +CodeGeneratorARM64::visitNotI(LNotI* ins) +{ + MOZ_CRASH("visitNotI"); +} + +// NZCV +// NAN -> 0011 +// == -> 0110 +// < -> 1000 +// > -> 0010 +void +CodeGeneratorARM64::visitNotD(LNotD* ins) +{ + MOZ_CRASH("visitNotD"); +} + +void +CodeGeneratorARM64::visitNotF(LNotF* ins) +{ + MOZ_CRASH("visitNotF"); +} + +void +CodeGeneratorARM64::visitLoadSlotV(LLoadSlotV* load) +{ + MOZ_CRASH("CodeGeneratorARM64::visitLoadSlotV"); +} + +void +CodeGeneratorARM64::visitLoadSlotT(LLoadSlotT* load) +{ + MOZ_CRASH("CodeGeneratorARM64::visitLoadSlotT"); +} + +void +CodeGeneratorARM64::visitStoreSlotT(LStoreSlotT* store) +{ + MOZ_CRASH("CodeGeneratorARM64::visitStoreSlotT"); +} + +void +CodeGeneratorARM64::visitLoadElementT(LLoadElementT* load) +{ + MOZ_CRASH("CodeGeneratorARM64::visitLoadElementT"); +} + +void +CodeGeneratorARM64::storeElementTyped(const LAllocation* value, MIRType valueType, + MIRType elementType, Register elements, + const LAllocation* index) +{ + MOZ_CRASH("CodeGeneratorARM64::storeElementTyped"); +} + +void +CodeGeneratorARM64::visitGuardShape(LGuardShape* guard) +{ + MOZ_CRASH("visitGuardShape"); +} + +void +CodeGeneratorARM64::visitGuardObjectGroup(LGuardObjectGroup* guard) +{ + MOZ_CRASH("visitGuardObjectGroup"); +} + +void +CodeGeneratorARM64::visitGuardClass(LGuardClass* guard) +{ + MOZ_CRASH("CodeGeneratorARM64::visitGuardClass"); +} + +void +CodeGeneratorARM64::visitInterruptCheck(LInterruptCheck* lir) +{ + MOZ_CRASH("CodeGeneratorARM64::visitInterruptCheck"); +} + +void +CodeGeneratorARM64::generateInvalidateEpilogue() +{ + MOZ_CRASH("generateInvalidateEpilogue"); +} + +void +CodeGeneratorARM64::visitRandom(LRandom* ins) +{ + MOZ_CRASH("visitRandom"); +} + +template +Register +getBase(U* mir) +{ + switch (mir->base()) { + case U::Heap: return HeapReg; + case U::Global: return GlobalReg; + } + return InvalidReg; +} + +void +CodeGeneratorARM64::visitLoadTypedArrayElementStatic(LLoadTypedArrayElementStatic* ins) +{ + MOZ_CRASH("CodeGeneratorARM64::visitLoadTypedArrayElementStatic"); +} + +void +CodeGeneratorARM64::visitStoreTypedArrayElementStatic(LStoreTypedArrayElementStatic* ins) +{ + MOZ_CRASH("CodeGeneratorARM64::visitStoreTypedArrayElementStatic"); +} + +void +CodeGeneratorARM64::visitAsmJSCall(LAsmJSCall* ins) +{ + MOZ_CRASH("visitAsmJSCall"); +} + +void +CodeGeneratorARM64::visitAsmJSLoadHeap(LAsmJSLoadHeap* ins) +{ + MOZ_CRASH("visitAsmJSLoadHeap"); +} + +void +CodeGeneratorARM64::visitAsmJSStoreHeap(LAsmJSStoreHeap* ins) +{ + MOZ_CRASH("visitAsmJSStoreHeap"); +} + +void +CodeGeneratorARM64::visitAsmJSCompareExchangeHeap(LAsmJSCompareExchangeHeap* ins) +{ + MOZ_CRASH("visitAsmJSCompareExchangeHeap"); +} + +void +CodeGeneratorARM64::visitAsmJSAtomicBinopHeap(LAsmJSAtomicBinopHeap* ins) +{ + MOZ_CRASH("visitAsmJSAtomicBinopHeap"); +} + +void +CodeGeneratorARM64::visitAsmJSPassStackArg(LAsmJSPassStackArg* ins) +{ + MOZ_CRASH("visitAsmJSPassStackArg"); +} + +void +CodeGeneratorARM64::visitUDiv(LUDiv* ins) +{ + MOZ_CRASH("visitUDiv"); +} + +void +CodeGeneratorARM64::visitUMod(LUMod* ins) +{ + MOZ_CRASH("visitUMod"); +} + +void +CodeGeneratorARM64::visitEffectiveAddress(LEffectiveAddress* ins) +{ + MOZ_CRASH("visitEffectiveAddress"); +} + +void +CodeGeneratorARM64::visitAsmJSLoadGlobalVar(LAsmJSLoadGlobalVar* ins) +{ + MOZ_CRASH("visitAsmJSLoadGlobalVar"); +} + +void +CodeGeneratorARM64::visitAsmJSStoreGlobalVar(LAsmJSStoreGlobalVar* ins) +{ + MOZ_CRASH("visitAsmJSStoreGlobalVar"); +} + +void +CodeGeneratorARM64::visitAsmJSLoadFuncPtr(LAsmJSLoadFuncPtr* ins) +{ + MOZ_CRASH("visitAsmJSLoadFuncPtr"); +} + +void +CodeGeneratorARM64::visitAsmJSLoadFFIFunc(LAsmJSLoadFFIFunc* ins) +{ + MOZ_CRASH("visitAsmJSLoadFFIFunc"); +} + +void +CodeGeneratorARM64::visitNegI(LNegI* ins) +{ + MOZ_CRASH("visitNegI"); +} + +void +CodeGeneratorARM64::visitNegD(LNegD* ins) +{ + MOZ_CRASH("visitNegD"); +} + +void +CodeGeneratorARM64::visitNegF(LNegF* ins) +{ + MOZ_CRASH("visitNegF"); +} diff --git a/js/src/jit/arm64/CodeGenerator-arm64.h b/js/src/jit/arm64/CodeGenerator-arm64.h new file mode 100644 index 00000000000..94c9bce87aa --- /dev/null +++ b/js/src/jit/arm64/CodeGenerator-arm64.h @@ -0,0 +1,276 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sts=4 et sw=4 tw=99: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef jit_arm64_CodeGenerator_arm64_h +#define jit_arm64_CodeGenerator_arm64_h + +#include "jit/arm64/Assembler-arm64.h" +#include "jit/shared/CodeGenerator-shared.h" + +namespace js { +namespace jit { + +class OutOfLineBailout; +class OutOfLineTableSwitch; + +class CodeGeneratorARM64 : public CodeGeneratorShared +{ + friend class MoveResolverARM64; + + CodeGeneratorARM64* thisFromCtor() { return this; } + + public: + CodeGeneratorARM64(MIRGenerator* gen, LIRGraph* graph, MacroAssembler* masm); + + protected: + // Label for the common return path. + NonAssertingLabel returnLabel_; + NonAssertingLabel deoptLabel_; + + // FIXME: VIXL Operand does not match the platform-agnostic Operand, + // which is just a union of possible arguments. + inline Operand ToOperand(const LAllocation& a) { + MOZ_CRASH("ToOperand"); + } + inline Operand ToOperand(const LAllocation* a) { + return ToOperand(*a); + } + inline Operand ToOperand(const LDefinition* def) { + return ToOperand(def->output()); + } + + MoveOperand toMoveOperand(const LAllocation a) const; + + void bailoutIf(Assembler::Condition condition, LSnapshot* snapshot); + void bailoutFrom(Label* label, LSnapshot* snapshot); + void bailout(LSnapshot* snapshot); + + template + void bailoutCmpPtr(Assembler::Condition c, T1 lhs, T2 rhs, LSnapshot* snapshot) { + masm.cmpPtr(lhs, rhs); + return bailoutIf(c, snapshot); + } + void bailoutTestPtr(Assembler::Condition c, Register lhs, Register rhs, LSnapshot* snapshot) { + masm.testPtr(lhs, rhs); + return bailoutIf(c, snapshot); + } + template + void bailoutCmp32(Assembler::Condition c, T1 lhs, T2 rhs, LSnapshot* snapshot) { + masm.cmp32(lhs, rhs); + return bailoutIf(c, snapshot); + } + template + void bailoutTest32(Assembler::Condition c, T1 lhs, T2 rhs, LSnapshot* snapshot) { + masm.test32(lhs, rhs); + return bailoutIf(c, snapshot); + } + void bailoutIfFalseBool(Register reg, LSnapshot* snapshot) { + masm.test32(reg, Imm32(0xFF)); + return bailoutIf(Assembler::Zero, snapshot); + } + + protected: + bool generatePrologue(); + bool generateEpilogue(); + bool generateOutOfLineCode(); + + void emitRoundDouble(FloatRegister src, Register dest, Label* fail); + + // Emits a branch that directs control flow to the true block if |cond| is + // true, and the false block if |cond| is false. + void emitBranch(Assembler::Condition cond, MBasicBlock* ifTrue, MBasicBlock* ifFalse); + + void testNullEmitBranch(Assembler::Condition cond, const ValueOperand& value, + MBasicBlock* ifTrue, MBasicBlock* ifFalse) + { + cond = masm.testNull(cond, value); + emitBranch(cond, ifTrue, ifFalse); + } + void testUndefinedEmitBranch(Assembler::Condition cond, const ValueOperand& value, + MBasicBlock* ifTrue, MBasicBlock* ifFalse) + { + cond = masm.testUndefined(cond, value); + emitBranch(cond, ifTrue, ifFalse); + } + void testObjectEmitBranch(Assembler::Condition cond, const ValueOperand& value, + MBasicBlock* ifTrue, MBasicBlock* ifFalse) + { + cond = masm.testObject(cond, value); + emitBranch(cond, ifTrue, ifFalse); + } + void testZeroEmitBranch(Assembler::Condition cond, Register reg, + MBasicBlock* ifTrue, MBasicBlock* ifFalse) + { + MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual); + masm.cmpPtr(reg, ImmWord(0)); + emitBranch(cond, ifTrue, ifFalse); + } + + void emitTableSwitchDispatch(MTableSwitch* mir, Register index, Register base); + + public: + // Instruction visitors. + virtual void visitMinMaxD(LMinMaxD* ins); + virtual void visitMinMaxF(LMinMaxF* math); + virtual void visitAbsD(LAbsD* ins); + virtual void visitAbsF(LAbsF* ins); + virtual void visitSqrtD(LSqrtD* ins); + virtual void visitSqrtF(LSqrtF* ins); + virtual void visitAddI(LAddI* ins); + virtual void visitSubI(LSubI* ins); + virtual void visitBitNotI(LBitNotI* ins); + virtual void visitBitOpI(LBitOpI* ins); + + virtual void visitMulI(LMulI* ins); + + virtual void visitDivI(LDivI* ins); + virtual void visitDivPowTwoI(LDivPowTwoI* ins); + virtual void visitModI(LModI* ins); + virtual void visitModPowTwoI(LModPowTwoI* ins); + virtual void visitModMaskI(LModMaskI* ins); + virtual void visitPowHalfD(LPowHalfD* ins); + virtual void visitShiftI(LShiftI* ins); + virtual void visitUrshD(LUrshD* ins); + + virtual void visitTestIAndBranch(LTestIAndBranch* test); + virtual void visitCompare(LCompare* comp); + virtual void visitCompareAndBranch(LCompareAndBranch* comp); + virtual void visitTestDAndBranch(LTestDAndBranch* test); + virtual void visitTestFAndBranch(LTestFAndBranch* test); + virtual void visitCompareD(LCompareD* comp); + virtual void visitCompareF(LCompareF* comp); + virtual void visitCompareDAndBranch(LCompareDAndBranch* comp); + virtual void visitCompareFAndBranch(LCompareFAndBranch* comp); + virtual void visitCompareB(LCompareB* lir); + virtual void visitCompareBAndBranch(LCompareBAndBranch* lir); + virtual void visitCompareV(LCompareV* lir); + virtual void visitCompareVAndBranch(LCompareVAndBranch* lir); + virtual void visitBitAndAndBranch(LBitAndAndBranch* baab); + virtual void visitAsmJSUInt32ToDouble(LAsmJSUInt32ToDouble* lir); + virtual void visitAsmJSUInt32ToFloat32(LAsmJSUInt32ToFloat32* lir); + virtual void visitNotI(LNotI* ins); + virtual void visitNotD(LNotD* ins); + virtual void visitNotF(LNotF* ins); + + virtual void visitMathD(LMathD* math); + virtual void visitMathF(LMathF* math); + virtual void visitFloor(LFloor* lir); + virtual void visitFloorF(LFloorF* lir); + virtual void visitCeil(LCeil* lir); + virtual void visitCeilF(LCeilF* lir); + virtual void visitRound(LRound* lir); + virtual void visitRoundF(LRoundF* lir); + virtual void visitTruncateDToInt32(LTruncateDToInt32* ins); + virtual void visitTruncateFToInt32(LTruncateFToInt32* ins); + + virtual void visitClzI(LClzI* lir); + // Out of line visitors. + void visitOutOfLineBailout(OutOfLineBailout* ool); + void visitOutOfLineTableSwitch(OutOfLineTableSwitch* ool); + + protected: + ValueOperand ToValue(LInstruction* ins, size_t pos); + ValueOperand ToOutValue(LInstruction* ins); + ValueOperand ToTempValue(LInstruction* ins, size_t pos); + + // Functions for LTestVAndBranch. + Register splitTagForTest(const ValueOperand& value); + + void storeElementTyped(const LAllocation* value, MIRType valueType, MIRType elementType, + Register elements, const LAllocation* index); + + void divICommon(MDiv* mir, Register lhs, Register rhs, Register output, LSnapshot* snapshot, + Label& done); + void modICommon(MMod* mir, Register lhs, Register rhs, Register output, LSnapshot* snapshot, + Label& done); + + public: + void visitBox(LBox* box); + void visitUnbox(LUnbox* unbox); + void visitValue(LValue* value); + void visitDouble(LDouble* ins); + void visitFloat32(LFloat32* ins); + + void visitLoadSlotV(LLoadSlotV* load); + void visitLoadSlotT(LLoadSlotT* load); + void visitStoreSlotT(LStoreSlotT* load); + + void visitLoadElementT(LLoadElementT* load); + + void visitGuardShape(LGuardShape* guard); + void visitGuardObjectGroup(LGuardObjectGroup* guard); + void visitGuardClass(LGuardClass* guard); + + void visitInterruptCheck(LInterruptCheck* lir); + + void visitNegI(LNegI* lir); + void visitNegD(LNegD* lir); + void visitNegF(LNegF* lir); + void visitLoadTypedArrayElementStatic(LLoadTypedArrayElementStatic* ins); + void visitStoreTypedArrayElementStatic(LStoreTypedArrayElementStatic* ins); + void visitAsmJSCall(LAsmJSCall* ins); + void visitAsmJSLoadHeap(LAsmJSLoadHeap* ins); + void visitAsmJSStoreHeap(LAsmJSStoreHeap* ins); + void visitAsmJSCompareExchangeHeap(LAsmJSCompareExchangeHeap* ins); + void visitAsmJSAtomicBinopHeap(LAsmJSAtomicBinopHeap* ins); + void visitAsmJSLoadGlobalVar(LAsmJSLoadGlobalVar* ins); + void visitAsmJSStoreGlobalVar(LAsmJSStoreGlobalVar* ins); + void visitAsmJSLoadFuncPtr(LAsmJSLoadFuncPtr* ins); + void visitAsmJSLoadFFIFunc(LAsmJSLoadFFIFunc* ins); + void visitAsmJSPassStackArg(LAsmJSPassStackArg* ins); + + void generateInvalidateEpilogue(); + + void visitRandom(LRandom* ins); + + protected: + void postAsmJSCall(LAsmJSCall* lir) { + MOZ_CRASH("postAsmJSCall"); + } + + void visitEffectiveAddress(LEffectiveAddress* ins); + void visitUDiv(LUDiv* ins); + void visitUMod(LUMod* ins); + + public: + // Unimplemented SIMD instructions. + void visitSimdSplatX4(LSimdSplatX4* lir) { MOZ_CRASH("NYI"); } + void visitInt32x4(LInt32x4* ins) { MOZ_CRASH("NYI"); } + void visitFloat32x4(LFloat32x4* ins) { MOZ_CRASH("NYI"); } + void visitSimdExtractElementI(LSimdExtractElementI* ins) { MOZ_CRASH("NYI"); } + void visitSimdExtractElementF(LSimdExtractElementF* ins) { MOZ_CRASH("NYI"); } + void visitSimdSignMaskX4(LSimdSignMaskX4* ins) { MOZ_CRASH("NYI"); } + void visitSimdBinaryCompIx4(LSimdBinaryCompIx4* lir) { MOZ_CRASH("NYI"); } + void visitSimdBinaryCompFx4(LSimdBinaryCompFx4* lir) { MOZ_CRASH("NYI"); } + void visitSimdBinaryArithIx4(LSimdBinaryArithIx4* lir) { MOZ_CRASH("NYI"); } + void visitSimdBinaryArithFx4(LSimdBinaryArithFx4* lir) { MOZ_CRASH("NYI"); } + void visitSimdBinaryBitwiseX4(LSimdBinaryBitwiseX4* lir) { MOZ_CRASH("NYI"); } +}; + +typedef CodeGeneratorARM64 CodeGeneratorSpecific; + +// An out-of-line bailout thunk. +class OutOfLineBailout : public OutOfLineCodeBase +{ + protected: // Silence Clang warning. + LSnapshot* snapshot_; + + public: + OutOfLineBailout(LSnapshot* snapshot) + : snapshot_(snapshot) + { } + + void accept(CodeGeneratorARM64* codegen); + + LSnapshot* snapshot() const { + return snapshot_; + } +}; + +} // namespace jit +} // namespace js + +#endif /* jit_arm64_CodeGenerator_arm64_h */ diff --git a/js/src/jit/arm64/LIR-arm64.h b/js/src/jit/arm64/LIR-arm64.h new file mode 100644 index 00000000000..762520908ee --- /dev/null +++ b/js/src/jit/arm64/LIR-arm64.h @@ -0,0 +1,467 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sts=4 et sw=4 tw=99: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef jit_arm64_LIR_arm64_h +#define jit_arm64_LIR_arm64_h + +namespace js { +namespace jit { + +class LBox : public LInstructionHelper<1, 1, 0> +{ + MIRType type_; + + public: + LIR_HEADER(Box); + + LBox(const LAllocation& in_payload, MIRType type) + : type_(type) + { + setOperand(0, in_payload); + } + + MIRType type() const { + return type_; + } + const char* extraName() const { + return StringFromMIRType(type_); + } +}; + +class LUnboxBase : public LInstructionHelper<1, 1, 0> +{ + public: + LUnboxBase(const LAllocation& input) { + setOperand(0, input); + } + + static const size_t Input = 0; + + MUnbox* mir() const { + return mir_->toUnbox(); + } +}; + +class LUnbox : public LUnboxBase +{ + public: + LIR_HEADER(Unbox); + + LUnbox(const LAllocation& input) + : LUnboxBase(input) + { } + + const char* extraName() const { + return StringFromMIRType(mir()->type()); + } +}; + +class LUnboxFloatingPoint : public LUnboxBase +{ + MIRType type_; + + public: + LIR_HEADER(UnboxFloatingPoint); + + LUnboxFloatingPoint(const LAllocation& input, MIRType type) + : LUnboxBase(input), + type_(type) + { } + + MIRType type() const { + return type_; + } + const char* extraName() const { + return StringFromMIRType(type_); + } +}; + +// Convert a 32-bit unsigned integer to a double. +class LAsmJSUInt32ToDouble : public LInstructionHelper<1, 1, 0> +{ + public: + LIR_HEADER(AsmJSUInt32ToDouble) + + LAsmJSUInt32ToDouble(const LAllocation& input) { + setOperand(0, input); + } +}; + +// Convert a 32-bit unsigned integer to a float32. +class LAsmJSUInt32ToFloat32 : public LInstructionHelper<1, 1, 0> +{ + public: + LIR_HEADER(AsmJSUInt32ToFloat32) + + LAsmJSUInt32ToFloat32(const LAllocation& input) { + setOperand(0, input); + } +}; + +class LDivI : public LBinaryMath<1> +{ + public: + LIR_HEADER(DivI); + + LDivI(const LAllocation& lhs, const LAllocation& rhs, + const LDefinition& temp) + { + setOperand(0, lhs); + setOperand(1, rhs); + setTemp(0, temp); + } + + MDiv* mir() const { + return mir_->toDiv(); + } +}; + +// LSoftDivI is a software divide for ARM cores that don't support a hardware +// divide instruction. +// +// It is implemented as a proper C function so it trashes r0, r1, r2 and r3. +// The call also trashes lr, and has the ability to trash ip. The function also +// takes two arguments (dividend in r0, divisor in r1). The LInstruction gets +// encoded such that the divisor and dividend are passed in their apropriate +// registers and end their life at the start of the instruction by the use of +// useFixedAtStart. The result is returned in r0 and the other three registers +// that can be trashed are marked as temps. For the time being, the link +// register is not marked as trashed because we never allocate to the link +// register. The FP registers are not trashed. +class LSoftDivI : public LBinaryMath<3> +{ + public: + LIR_HEADER(SoftDivI); + + LSoftDivI(const LAllocation& lhs, const LAllocation& rhs, + const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3) { + setOperand(0, lhs); + setOperand(1, rhs); + setTemp(0, temp1); + setTemp(1, temp2); + setTemp(2, temp3); + } + + MDiv* mir() const { + return mir_->toDiv(); + } +}; + +class LDivPowTwoI : public LInstructionHelper<1, 1, 0> +{ + const int32_t shift_; + + public: + LIR_HEADER(DivPowTwoI) + + LDivPowTwoI(const LAllocation& lhs, int32_t shift) + : shift_(shift) + { + setOperand(0, lhs); + } + + const LAllocation* numerator() { + return getOperand(0); + } + + int32_t shift() { + return shift_; + } + + MDiv* mir() const { + return mir_->toDiv(); + } +}; + +class LModI : public LBinaryMath<1> +{ + public: + LIR_HEADER(ModI); + + LModI(const LAllocation& lhs, const LAllocation& rhs, + const LDefinition& callTemp) + { + setOperand(0, lhs); + setOperand(1, rhs); + setTemp(0, callTemp); + } + + const LDefinition* callTemp() { + return getTemp(0); + } + + MMod* mir() const { + return mir_->toMod(); + } +}; + +class LSoftModI : public LBinaryMath<4> +{ + public: + LIR_HEADER(SoftModI); + + LSoftModI(const LAllocation& lhs, const LAllocation& rhs, + const LDefinition& temp1, const LDefinition& temp2, const LDefinition& temp3, + const LDefinition& callTemp) + { + setOperand(0, lhs); + setOperand(1, rhs); + setTemp(0, temp1); + setTemp(1, temp2); + setTemp(2, temp3); + setTemp(3, callTemp); + } + + const LDefinition* callTemp() { + return getTemp(3); + } + + MMod* mir() const { + return mir_->toMod(); + } +}; + +class LModPowTwoI : public LInstructionHelper<1, 1, 0> +{ + const int32_t shift_; + + public: + LIR_HEADER(ModPowTwoI); + int32_t shift() + { + return shift_; + } + + LModPowTwoI(const LAllocation& lhs, int32_t shift) + : shift_(shift) + { + setOperand(0, lhs); + } + + MMod* mir() const { + return mir_->toMod(); + } +}; + +class LModMaskI : public LInstructionHelper<1, 1, 1> +{ + const int32_t shift_; + + public: + LIR_HEADER(ModMaskI); + + LModMaskI(const LAllocation& lhs, const LDefinition& temp1, int32_t shift) + : shift_(shift) + { + setOperand(0, lhs); + setTemp(0, temp1); + } + + int32_t shift() const { + return shift_; + } + + MMod* mir() const { + return mir_->toMod(); + } +}; + +class LPowHalfD : public LInstructionHelper<1, 1, 0> +{ + public: + LIR_HEADER(PowHalfD); + LPowHalfD(const LAllocation& input) { + setOperand(0, input); + } + + const LAllocation* input() { + return getOperand(0); + } + const LDefinition* output() { + return getDef(0); + } +}; + +// Takes a tableswitch with an integer to decide +class LTableSwitch : public LInstructionHelper<0, 1, 1> +{ + public: + LIR_HEADER(TableSwitch); + + LTableSwitch(const LAllocation& in, const LDefinition& inputCopy, MTableSwitch* ins) { + setOperand(0, in); + setTemp(0, inputCopy); + setMir(ins); + } + + MTableSwitch* mir() const { + return mir_->toTableSwitch(); + } + + const LAllocation* index() { + return getOperand(0); + } + const LDefinition* tempInt() { + return getTemp(0); + } + // This is added to share the same CodeGenerator prefixes. + const LDefinition* tempPointer() { + return nullptr; + } +}; + +// Takes a tableswitch with an integer to decide +class LTableSwitchV : public LInstructionHelper<0, BOX_PIECES, 2> +{ + public: + LIR_HEADER(TableSwitchV); + + LTableSwitchV(const LDefinition& inputCopy, const LDefinition& floatCopy, + MTableSwitch* ins) + { + setTemp(0, inputCopy); + setTemp(1, floatCopy); + setMir(ins); + } + + MTableSwitch* mir() const { + return mir_->toTableSwitch(); + } + + static const size_t InputValue = 0; + + const LDefinition* tempInt() { + return getTemp(0); + } + const LDefinition* tempFloat() { + return getTemp(1); + } + const LDefinition* tempPointer() { + return nullptr; + } +}; + +class LGuardShape : public LInstructionHelper<0, 1, 1> +{ + public: + LIR_HEADER(GuardShape); + + LGuardShape(const LAllocation& in, const LDefinition& temp) { + setOperand(0, in); + setTemp(0, temp); + } + const MGuardShape* mir() const { + return mir_->toGuardShape(); + } + const LDefinition* tempInt() { + return getTemp(0); + } +}; + +class LGuardObjectGroup : public LInstructionHelper<0, 1, 1> +{ + public: + LIR_HEADER(GuardObjectGroup); + + LGuardObjectGroup(const LAllocation& in, const LDefinition& temp) { + setOperand(0, in); + setTemp(0, temp); + } + const MGuardObjectGroup* mir() const { + return mir_->toGuardObjectGroup(); + } + const LDefinition* tempInt() { + return getTemp(0); + } +}; + +class LMulI : public LBinaryMath<0> +{ + public: + LIR_HEADER(MulI); + + MMul* mir() { + return mir_->toMul(); + } +}; + +class LUDiv : public LBinaryMath<0> +{ + public: + LIR_HEADER(UDiv); + + MDiv* mir() { + return mir_->toDiv(); + } +}; + +class LUMod : public LBinaryMath<0> +{ + public: + LIR_HEADER(UMod); + + MMod* mir() { + return mir_->toMod(); + } +}; + +// This class performs a simple x86 'div', yielding either a quotient or remainder depending on +// whether this instruction is defined to output eax (quotient) or edx (remainder). +class LSoftUDivOrMod : public LBinaryMath<3> +{ + public: + LIR_HEADER(SoftUDivOrMod); + + LSoftUDivOrMod(const LAllocation& lhs, const LAllocation& rhs, const LDefinition& temp1, + const LDefinition& temp2, const LDefinition& temp3) { + setOperand(0, lhs); + setOperand(1, rhs); + setTemp(0, temp1); + setTemp(1, temp2); + setTemp(2, temp3); + } +}; + +class LAsmJSLoadFuncPtr : public LInstructionHelper<1, 1, 1> +{ + public: + LIR_HEADER(AsmJSLoadFuncPtr); + LAsmJSLoadFuncPtr(const LAllocation& index, const LDefinition& temp) { + setOperand(0, index); + setTemp(0, temp); + } + const MAsmJSLoadFuncPtr* mir() const { + return mir_->toAsmJSLoadFuncPtr(); + } + const LAllocation* index() { + return getOperand(0); + } + const LDefinition* temp() { + return getTemp(0); + } +}; + +// Math.random(). +class LRandom : public LCallInstructionHelper<1, 0, 2> +{ + public: + LIR_HEADER(Random) + LRandom(const LDefinition& temp, const LDefinition& temp2) { + setTemp(0, temp); + setTemp(1, temp2); + } + const LDefinition* temp() { + return getTemp(0); + } + const LDefinition* temp2() { + return getTemp(1); + } +}; + +} // namespace jit +} // namespace js + +#endif /* jit_arm64_LIR_arm64_h */ diff --git a/js/src/jit/arm64/LOpcodes-arm64.h b/js/src/jit/arm64/LOpcodes-arm64.h new file mode 100644 index 00000000000..d83225afc1a --- /dev/null +++ b/js/src/jit/arm64/LOpcodes-arm64.h @@ -0,0 +1,29 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sts=4 et sw=4 tw=99: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef jit_arm64_LOpcodes_arm64_h +#define jit_arm64_LOpcodes_arm64_h + +#define LIR_CPU_OPCODE_LIST(_) \ + _(Unbox) \ + _(UnboxFloatingPoint) \ + _(Box) \ + _(DivI) \ + _(SoftDivI) \ + _(DivPowTwoI) \ + _(ModI) \ + _(SoftModI) \ + _(ModPowTwoI) \ + _(ModMaskI) \ + _(PowHalfD) \ + _(AsmJSUInt32ToDouble) \ + _(AsmJSUInt32ToFloat32) \ + _(UDiv) \ + _(UMod) \ + _(SoftUDivOrMod) \ + _(AsmJSLoadFuncPtr) + +#endif /* jit_arm64_LOpcodes_arm64_h */ diff --git a/js/src/jit/arm64/Lowering-arm64.cpp b/js/src/jit/arm64/Lowering-arm64.cpp new file mode 100644 index 00000000000..41524f049d6 --- /dev/null +++ b/js/src/jit/arm64/Lowering-arm64.cpp @@ -0,0 +1,321 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sts=4 et sw=4 tw=99: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/MathAlgorithms.h" + +#include "jit/arm64/Assembler-arm64.h" +#include "jit/Lowering.h" +#include "jit/MIR.h" + +#include "jit/shared/Lowering-shared-inl.h" + +using namespace js; +using namespace js::jit; + +using mozilla::FloorLog2; + +void +LIRGeneratorARM64::useBox(LInstruction* lir, size_t n, MDefinition* mir, + LUse::Policy policy, bool useAtStart) +{ + MOZ_CRASH("useBox"); +} + +void +LIRGeneratorARM64::useBoxFixed(LInstruction* lir, size_t n, MDefinition* mir, Register reg1, Register) +{ + MOZ_CRASH("useBoxFixed"); +} + +LAllocation +LIRGeneratorARM64::useByteOpRegister(MDefinition* mir) +{ + MOZ_CRASH("useByteOpRegister"); +} + +LAllocation +LIRGeneratorARM64::useByteOpRegisterOrNonDoubleConstant(MDefinition* mir) +{ + MOZ_CRASH("useByteOpRegisterOrNonDoubleConstant"); +} + +void +LIRGeneratorARM64::lowerConstantDouble(double d, MInstruction* mir) +{ + MOZ_CRASH("lowerConstantDouble"); +} + +void +LIRGeneratorARM64::lowerConstantFloat32(float d, MInstruction* mir) +{ + MOZ_CRASH("lowerConstantFloat32"); +} + +void +LIRGeneratorARM64::visitConstant(MConstant* ins) +{ + MOZ_CRASH("visitConstant"); +} + +void +LIRGeneratorARM64::visitBox(MBox* box) +{ + MOZ_CRASH("visitBox"); +} + +void +LIRGeneratorARM64::visitUnbox(MUnbox* unbox) +{ + MOZ_CRASH("visitUnbox"); +} + +void +LIRGeneratorARM64::visitReturn(MReturn* ret) +{ + MOZ_CRASH("visitReturn"); +} + +// x = !y +void +LIRGeneratorARM64::lowerForALU(LInstructionHelper<1, 1, 0>* ins, MDefinition* mir, MDefinition* input) +{ + MOZ_CRASH("lowerForALU"); +} + +// z = x+y +void +LIRGeneratorARM64::lowerForALU(LInstructionHelper<1, 2, 0>* ins, MDefinition* mir, + MDefinition* lhs, MDefinition* rhs) +{ + MOZ_CRASH("lowerForALU"); +} + +void +LIRGeneratorARM64::lowerForFPU(LInstructionHelper<1, 1, 0>* ins, MDefinition* mir, MDefinition* input) +{ + MOZ_CRASH("lowerForFPU"); +} + +template +void +LIRGeneratorARM64::lowerForFPU(LInstructionHelper<1, 2, Temps>* ins, MDefinition* mir, + MDefinition* lhs, MDefinition* rhs) +{ + MOZ_CRASH("lowerForFPU"); +} + +template void LIRGeneratorARM64::lowerForFPU(LInstructionHelper<1, 2, 0>* ins, MDefinition* mir, + MDefinition* lhs, MDefinition* rhs); +template void LIRGeneratorARM64::lowerForFPU(LInstructionHelper<1, 2, 1>* ins, MDefinition* mir, + MDefinition* lhs, MDefinition* rhs); + +void +LIRGeneratorARM64::lowerForBitAndAndBranch(LBitAndAndBranch* baab, MInstruction* mir, + MDefinition* lhs, MDefinition* rhs) +{ + MOZ_CRASH("lowerForBitAndAndBranch"); +} + +void +LIRGeneratorARM64::defineUntypedPhi(MPhi* phi, size_t lirIndex) +{ + MOZ_CRASH("defineUntypedPhi"); +} + +void +LIRGeneratorARM64::lowerUntypedPhiInput(MPhi* phi, uint32_t inputPosition, + LBlock* block, size_t lirIndex) +{ + MOZ_CRASH("lowerUntypedPhiInput"); +} + +void +LIRGeneratorARM64::lowerForShift(LInstructionHelper<1, 2, 0>* ins, + MDefinition* mir, MDefinition* lhs, MDefinition* rhs) +{ + MOZ_CRASH("lowerForShift"); +} + +void +LIRGeneratorARM64::lowerDivI(MDiv* div) +{ + MOZ_CRASH("lowerDivI"); +} + +void +LIRGeneratorARM64::lowerMulI(MMul* mul, MDefinition* lhs, MDefinition* rhs) +{ + MOZ_CRASH("lowerMulI"); +} + +void +LIRGeneratorARM64::lowerModI(MMod* mod) +{ + MOZ_CRASH("lowerModI"); +} + +void +LIRGeneratorARM64::visitPowHalf(MPowHalf* ins) +{ + MOZ_CRASH("visitPowHalf"); +} + +LTableSwitch* +LIRGeneratorARM64::newLTableSwitch(const LAllocation& in, const LDefinition& inputCopy, + MTableSwitch* tableswitch) +{ + MOZ_CRASH("newLTableSwitch"); +} + +LTableSwitchV* +LIRGeneratorARM64::newLTableSwitchV(MTableSwitch* tableswitch) +{ + MOZ_CRASH("newLTableSwitchV"); +} + +void +LIRGeneratorARM64::visitGuardShape(MGuardShape* ins) +{ + MOZ_CRASH("visitGuardShape"); +} + +void +LIRGeneratorARM64::visitGuardObjectGroup(MGuardObjectGroup* ins) +{ + MOZ_CRASH("visitGuardObjectGroup"); +} + +void +LIRGeneratorARM64::lowerUrshD(MUrsh* mir) +{ + MOZ_CRASH("lowerUrshD"); +} + +void +LIRGeneratorARM64::visitAsmJSNeg(MAsmJSNeg* ins) +{ + MOZ_CRASH("visitAsmJSNeg"); +} + +void +LIRGeneratorARM64::lowerUDiv(MDiv* div) +{ + MOZ_CRASH("lowerUDiv"); +} + +void +LIRGeneratorARM64::lowerUMod(MMod* mod) +{ + MOZ_CRASH("lowerUMod"); +} + +void +LIRGeneratorARM64::visitAsmJSUnsignedToDouble(MAsmJSUnsignedToDouble* ins) +{ + MOZ_CRASH("visitAsmJSUnsignedToDouble"); +} + +void +LIRGeneratorARM64::visitAsmJSUnsignedToFloat32(MAsmJSUnsignedToFloat32* ins) +{ + MOZ_CRASH("visitAsmJSUnsignedToFloat32"); +} + +void +LIRGeneratorARM64::visitAsmJSLoadHeap(MAsmJSLoadHeap* ins) +{ + MOZ_CRASH("visitAsmJSLoadHeap"); +} + +void +LIRGeneratorARM64::visitAsmJSStoreHeap(MAsmJSStoreHeap* ins) +{ + MOZ_CRASH("visitAsmJSStoreHeap"); +} + +void +LIRGeneratorARM64::visitAsmJSLoadFuncPtr(MAsmJSLoadFuncPtr* ins) +{ + MOZ_CRASH("visitAsmJSLoadFuncPtr"); +} + +void +LIRGeneratorARM64::visitAsmJSCompareExchangeHeap(MAsmJSCompareExchangeHeap* ins) +{ + MOZ_CRASH("visitAsmJSCompareExchangeHeap"); +} + +void +LIRGeneratorARM64::visitAsmJSAtomicBinopHeap(MAsmJSAtomicBinopHeap* ins) +{ + MOZ_CRASH("visitAsmJSAtomicBinopHeap"); +} + +void +LIRGeneratorARM64::lowerTruncateDToInt32(MTruncateToInt32* ins) +{ + MOZ_CRASH("lowerTruncateDToInt32"); +} + +void +LIRGeneratorARM64::lowerTruncateFToInt32(MTruncateToInt32* ins) +{ + MOZ_CRASH("lowerTruncateFToInt32"); +} + +void +LIRGeneratorARM64::visitStoreTypedArrayElementStatic(MStoreTypedArrayElementStatic* ins) +{ + MOZ_CRASH("NYI"); +} + +void +LIRGeneratorARM64::visitSimdBinaryArith(MSimdBinaryArith* ins) +{ + MOZ_CRASH("NYI"); +} + +void +LIRGeneratorARM64::visitSimdSelect(MSimdSelect* ins) +{ + MOZ_CRASH("NYI"); +} + +void +LIRGeneratorARM64::visitSimdSplatX4(MSimdSplatX4* ins) +{ + MOZ_CRASH("NYI"); +} + +void +LIRGeneratorARM64::visitSimdValueX4(MSimdValueX4* ins) +{ + MOZ_CRASH("NYI"); +} + +void +LIRGeneratorARM64::visitAtomicTypedArrayElementBinop(MAtomicTypedArrayElementBinop* ins) +{ + MOZ_CRASH("NYI"); +} + +void +LIRGeneratorARM64::visitCompareExchangeTypedArrayElement(MCompareExchangeTypedArrayElement* ins) +{ + MOZ_CRASH("NYI"); +} + +void +LIRGeneratorARM64::visitSubstr(MSubstr* ins) +{ + MOZ_CRASH("visitSubstr"); +} + +void +LIRGeneratorARM64::visitRandom(MRandom* ins) +{ + MOZ_CRASH("visitRandom"); +} diff --git a/js/src/jit/arm64/Lowering-arm64.h b/js/src/jit/arm64/Lowering-arm64.h new file mode 100644 index 00000000000..68fcaee6a24 --- /dev/null +++ b/js/src/jit/arm64/Lowering-arm64.h @@ -0,0 +1,121 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sts=4 et sw=4 tw=99: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef jit_arm64_Lowering_arm64_h +#define jit_arm64_Lowering_arm64_h + +#include "jit/shared/Lowering-shared.h" + +namespace js { +namespace jit { + +class LIRGeneratorARM64 : public LIRGeneratorShared +{ + public: + LIRGeneratorARM64(MIRGenerator* gen, MIRGraph& graph, LIRGraph& lirGraph) + : LIRGeneratorShared(gen, graph, lirGraph) + { } + + protected: + // Adds a box input to an instruction, setting operand |n| to the type and + // |n+1| to the payload. + void useBox(LInstruction* lir, size_t n, MDefinition* mir, + LUse::Policy policy = LUse::REGISTER, bool useAtStart = false); + void useBoxFixed(LInstruction* lir, size_t n, MDefinition* mir, Register reg1, Register reg2); + + LAllocation useByteOpRegister(MDefinition* mir); + LAllocation useByteOpRegisterOrNonDoubleConstant(MDefinition* mir); + + inline LDefinition tempToUnbox() { + return temp(); + } + + bool needTempForPostBarrier() { return true; } + + // ARM64 has a scratch register, so no need for another temp for dispatch ICs. + LDefinition tempForDispatchCache(MIRType outputType = MIRType_None) { + return LDefinition::BogusTemp(); + } + + void lowerUntypedPhiInput(MPhi* phi, uint32_t inputPosition, LBlock* block, size_t lirIndex); + void defineUntypedPhi(MPhi* phi, size_t lirIndex); + void lowerForShift(LInstructionHelper<1, 2, 0>* ins, MDefinition* mir, MDefinition* lhs, + MDefinition* rhs); + void lowerUrshD(MUrsh* mir); + + void lowerForALU(LInstructionHelper<1, 1, 0>* ins, MDefinition* mir, MDefinition* input); + void lowerForALU(LInstructionHelper<1, 2, 0>* ins, MDefinition* mir, + MDefinition* lhs, MDefinition* rhs); + + void lowerForFPU(LInstructionHelper<1, 1, 0>* ins, MDefinition* mir, MDefinition* input); + + template + void lowerForFPU(LInstructionHelper<1, 2, Temps>* ins, MDefinition* mir, + MDefinition* lhs, MDefinition* rhs); + + void lowerForCompIx4(LSimdBinaryCompIx4* ins, MSimdBinaryComp* mir, + MDefinition* lhs, MDefinition* rhs) + { + return lowerForFPU(ins, mir, lhs, rhs); + } + + void lowerForCompFx4(LSimdBinaryCompFx4* ins, MSimdBinaryComp* mir, + MDefinition* lhs, MDefinition* rhs) + { + return lowerForFPU(ins, mir, lhs, rhs); + } + + void lowerForBitAndAndBranch(LBitAndAndBranch* baab, MInstruction* mir, + MDefinition* lhs, MDefinition* rhs); + void lowerConstantDouble(double d, MInstruction* ins); + void lowerConstantFloat32(float d, MInstruction* ins); + void lowerTruncateDToInt32(MTruncateToInt32* ins); + void lowerTruncateFToInt32(MTruncateToInt32* ins); + void lowerDivI(MDiv* div); + void lowerModI(MMod* mod); + void lowerMulI(MMul* mul, MDefinition* lhs, MDefinition* rhs); + void lowerUDiv(MDiv* div); + void lowerUMod(MMod* mod); + void visitPowHalf(MPowHalf* ins); + void visitAsmJSNeg(MAsmJSNeg* ins); + + LTableSwitchV* newLTableSwitchV(MTableSwitch* ins); + LTableSwitch* newLTableSwitch(const LAllocation& in, + const LDefinition& inputCopy, + MTableSwitch* ins); + + public: + void visitConstant(MConstant* ins); + void visitBox(MBox* box); + void visitUnbox(MUnbox* unbox); + void visitReturn(MReturn* ret); + void lowerPhi(MPhi* phi); + void visitGuardShape(MGuardShape* ins); + void visitGuardObjectGroup(MGuardObjectGroup* ins); + void visitAsmJSUnsignedToDouble(MAsmJSUnsignedToDouble* ins); + void visitAsmJSUnsignedToFloat32(MAsmJSUnsignedToFloat32* ins); + void visitAsmJSLoadHeap(MAsmJSLoadHeap* ins); + void visitAsmJSStoreHeap(MAsmJSStoreHeap* ins); + void visitAsmJSLoadFuncPtr(MAsmJSLoadFuncPtr* ins); + void visitAsmJSCompareExchangeHeap(MAsmJSCompareExchangeHeap* ins); + void visitAsmJSAtomicBinopHeap(MAsmJSAtomicBinopHeap* ins); + void visitStoreTypedArrayElementStatic(MStoreTypedArrayElementStatic* ins); + void visitSimdBinaryArith(MSimdBinaryArith* ins); + void visitSimdSelect(MSimdSelect* ins); + void visitSimdSplatX4(MSimdSplatX4* ins); + void visitSimdValueX4(MSimdValueX4* ins); + void visitCompareExchangeTypedArrayElement(MCompareExchangeTypedArrayElement* ins); + void visitAtomicTypedArrayElementBinop(MAtomicTypedArrayElementBinop* ins); + void visitSubstr(MSubstr* ins); + void visitRandom(MRandom* ins); +}; + +typedef LIRGeneratorARM64 LIRGeneratorSpecific; + +} // namespace jit +} // namespace js + +#endif /* jit_arm64_Lowering_arm64_h */