LCOV - code coverage report
Current view: top level - js/src/jit/x64 - CodeGenerator-x64.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 51 427 11.9 %
Date: 2017-07-14 16:53:18 Functions: 8 51 15.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=8 sts=4 et sw=4 tw=99:
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "jit/x64/CodeGenerator-x64.h"
       8             : 
       9             : #include "mozilla/MathAlgorithms.h"
      10             : 
      11             : #include "jit/IonCaches.h"
      12             : #include "jit/MIR.h"
      13             : 
      14             : #include "jsscriptinlines.h"
      15             : 
      16             : #include "jit/MacroAssembler-inl.h"
      17             : #include "jit/shared/CodeGenerator-shared-inl.h"
      18             : 
      19             : using namespace js;
      20             : using namespace js::jit;
      21             : 
      22             : using mozilla::DebugOnly;
      23             : 
      24           8 : CodeGeneratorX64::CodeGeneratorX64(MIRGenerator* gen, LIRGraph* graph, MacroAssembler* masm)
      25           8 :   : CodeGeneratorX86Shared(gen, graph, masm)
      26             : {
      27           8 : }
      28             : 
      29             : ValueOperand
      30         185 : CodeGeneratorX64::ToValue(LInstruction* ins, size_t pos)
      31             : {
      32         185 :     return ValueOperand(ToRegister(ins->getOperand(pos)));
      33             : }
      34             : 
      35             : ValueOperand
      36         263 : CodeGeneratorX64::ToOutValue(LInstruction* ins)
      37             : {
      38         263 :     return ValueOperand(ToRegister(ins->getDef(0)));
      39             : }
      40             : 
      41             : ValueOperand
      42           0 : CodeGeneratorX64::ToTempValue(LInstruction* ins, size_t pos)
      43             : {
      44           0 :     return ValueOperand(ToRegister(ins->getTemp(pos)));
      45             : }
      46             : 
      47             : Operand
      48           0 : CodeGeneratorX64::ToOperand64(const LInt64Allocation& a64)
      49             : {
      50           0 :     const LAllocation& a = a64.value();
      51           0 :     MOZ_ASSERT(!a.isFloatReg());
      52           0 :     if (a.isGeneralReg())
      53           0 :         return Operand(a.toGeneralReg()->reg());
      54           0 :     return Operand(masm.getStackPointer(), ToStackOffset(a));
      55             : }
      56             : 
      57             : FrameSizeClass
      58           8 : FrameSizeClass::FromDepth(uint32_t frameDepth)
      59             : {
      60           8 :     return FrameSizeClass::None();
      61             : }
      62             : 
      63             : FrameSizeClass
      64           8 : FrameSizeClass::ClassLimit()
      65             : {
      66           8 :     return FrameSizeClass(0);
      67             : }
      68             : 
      69             : uint32_t
      70           0 : FrameSizeClass::frameSize() const
      71             : {
      72           0 :     MOZ_CRASH("x64 does not use frame size classes");
      73             : }
      74             : 
      75             : void
      76          53 : CodeGeneratorX64::visitValue(LValue* value)
      77             : {
      78          53 :     LDefinition* reg = value->getDef(0);
      79          53 :     masm.moveValue(value->value(), ToRegister(reg));
      80          53 : }
      81             : 
      82             : void
      83          34 : CodeGeneratorX64::visitBox(LBox* box)
      84             : {
      85          34 :     const LAllocation* in = box->getOperand(0);
      86          34 :     const LDefinition* result = box->getDef(0);
      87             : 
      88          34 :     if (IsFloatingPointType(box->type())) {
      89           2 :         ScratchDoubleScope scratch(masm);
      90           1 :         FloatRegister reg = ToFloatRegister(in);
      91           1 :         if (box->type() == MIRType::Float32) {
      92           0 :             masm.convertFloat32ToDouble(reg, scratch);
      93           0 :             reg = scratch;
      94             :         }
      95           1 :         masm.vmovq(reg, ToRegister(result));
      96             :     } else {
      97          33 :         masm.boxValue(ValueTypeFromMIRType(box->type()), ToRegister(in), ToRegister(result));
      98             :     }
      99          34 : }
     100             : 
     101             : void
     102         109 : CodeGeneratorX64::visitUnbox(LUnbox* unbox)
     103             : {
     104         109 :     MUnbox* mir = unbox->mir();
     105             : 
     106         109 :     if (mir->fallible()) {
     107          80 :         const ValueOperand value = ToValue(unbox, LUnbox::Input);
     108             :         Assembler::Condition cond;
     109          80 :         switch (mir->type()) {
     110             :           case MIRType::Int32:
     111          12 :             cond = masm.testInt32(Assembler::NotEqual, value);
     112          12 :             break;
     113             :           case MIRType::Boolean:
     114          14 :             cond = masm.testBoolean(Assembler::NotEqual, value);
     115          14 :             break;
     116             :           case MIRType::Object:
     117          33 :             cond = masm.testObject(Assembler::NotEqual, value);
     118          33 :             break;
     119             :           case MIRType::String:
     120          21 :             cond = masm.testString(Assembler::NotEqual, value);
     121          21 :             break;
     122             :           case MIRType::Symbol:
     123           0 :             cond = masm.testSymbol(Assembler::NotEqual, value);
     124           0 :             break;
     125             :           default:
     126           0 :             MOZ_CRASH("Given MIRType cannot be unboxed.");
     127             :         }
     128          80 :         bailoutIf(cond, unbox->snapshot());
     129             :     }
     130             : 
     131         109 :     Operand input = ToOperand(unbox->getOperand(LUnbox::Input));
     132         109 :     Register result = ToRegister(unbox->output());
     133         109 :     switch (mir->type()) {
     134             :       case MIRType::Int32:
     135          14 :         masm.unboxInt32(input, result);
     136          14 :         break;
     137             :       case MIRType::Boolean:
     138          24 :         masm.unboxBoolean(input, result);
     139          24 :         break;
     140             :       case MIRType::Object:
     141          47 :         masm.unboxObject(input, result);
     142          47 :         break;
     143             :       case MIRType::String:
     144          24 :         masm.unboxString(input, result);
     145          24 :         break;
     146             :       case MIRType::Symbol:
     147           0 :         masm.unboxSymbol(input, result);
     148           0 :         break;
     149             :       default:
     150           0 :         MOZ_CRASH("Given MIRType cannot be unboxed.");
     151             :     }
     152         109 : }
     153             : 
     154             : void
     155           0 : CodeGeneratorX64::visitCompareB(LCompareB* lir)
     156             : {
     157           0 :     MCompare* mir = lir->mir();
     158             : 
     159           0 :     const ValueOperand lhs = ToValue(lir, LCompareB::Lhs);
     160           0 :     const LAllocation* rhs = lir->rhs();
     161           0 :     const Register output = ToRegister(lir->output());
     162             : 
     163           0 :     MOZ_ASSERT(mir->jsop() == JSOP_STRICTEQ || mir->jsop() == JSOP_STRICTNE);
     164             : 
     165             :     // Load boxed boolean in ScratchReg.
     166           0 :     ScratchRegisterScope scratch(masm);
     167           0 :     if (rhs->isConstant())
     168           0 :         masm.moveValue(rhs->toConstant()->toJSValue(), scratch);
     169             :     else
     170           0 :         masm.boxValue(JSVAL_TYPE_BOOLEAN, ToRegister(rhs), scratch);
     171             : 
     172             :     // Perform the comparison.
     173           0 :     masm.cmpPtr(lhs.valueReg(), scratch);
     174           0 :     masm.emitSet(JSOpToCondition(mir->compareType(), mir->jsop()), output);
     175           0 : }
     176             : 
     177             : void
     178           0 : CodeGeneratorX64::visitCompareBAndBranch(LCompareBAndBranch* lir)
     179             : {
     180           0 :     MCompare* mir = lir->cmpMir();
     181             : 
     182           0 :     const ValueOperand lhs = ToValue(lir, LCompareBAndBranch::Lhs);
     183           0 :     const LAllocation* rhs = lir->rhs();
     184             : 
     185           0 :     MOZ_ASSERT(mir->jsop() == JSOP_STRICTEQ || mir->jsop() == JSOP_STRICTNE);
     186             : 
     187             :     // Load boxed boolean in ScratchReg.
     188           0 :     ScratchRegisterScope scratch(masm);
     189           0 :     if (rhs->isConstant())
     190           0 :         masm.moveValue(rhs->toConstant()->toJSValue(), scratch);
     191             :     else
     192           0 :         masm.boxValue(JSVAL_TYPE_BOOLEAN, ToRegister(rhs), scratch);
     193             : 
     194             :     // Perform the comparison.
     195           0 :     masm.cmpPtr(lhs.valueReg(), scratch);
     196           0 :     emitBranch(JSOpToCondition(mir->compareType(), mir->jsop()), lir->ifTrue(), lir->ifFalse());
     197           0 : }
     198             : 
     199             : void
     200           0 : CodeGeneratorX64::visitCompareBitwise(LCompareBitwise* lir)
     201             : {
     202           0 :     MCompare* mir = lir->mir();
     203           0 :     const ValueOperand lhs = ToValue(lir, LCompareBitwise::LhsInput);
     204           0 :     const ValueOperand rhs = ToValue(lir, LCompareBitwise::RhsInput);
     205           0 :     const Register output = ToRegister(lir->output());
     206             : 
     207           0 :     MOZ_ASSERT(IsEqualityOp(mir->jsop()));
     208             : 
     209           0 :     masm.cmpPtr(lhs.valueReg(), rhs.valueReg());
     210           0 :     masm.emitSet(JSOpToCondition(mir->compareType(), mir->jsop()), output);
     211           0 : }
     212             : 
     213             : void
     214           0 : CodeGeneratorX64::visitCompareBitwiseAndBranch(LCompareBitwiseAndBranch* lir)
     215             : {
     216           0 :     MCompare* mir = lir->cmpMir();
     217             : 
     218           0 :     const ValueOperand lhs = ToValue(lir, LCompareBitwiseAndBranch::LhsInput);
     219           0 :     const ValueOperand rhs = ToValue(lir, LCompareBitwiseAndBranch::RhsInput);
     220             : 
     221           0 :     MOZ_ASSERT(mir->jsop() == JSOP_EQ || mir->jsop() == JSOP_STRICTEQ ||
     222             :                mir->jsop() == JSOP_NE || mir->jsop() == JSOP_STRICTNE);
     223             : 
     224           0 :     masm.cmpPtr(lhs.valueReg(), rhs.valueReg());
     225           0 :     emitBranch(JSOpToCondition(mir->compareType(), mir->jsop()), lir->ifTrue(), lir->ifFalse());
     226           0 : }
     227             : 
     228             : void
     229           0 : CodeGeneratorX64::visitCompareI64(LCompareI64* lir)
     230             : {
     231           0 :     MCompare* mir = lir->mir();
     232           0 :     MOZ_ASSERT(mir->compareType() == MCompare::Compare_Int64 ||
     233             :                mir->compareType() == MCompare::Compare_UInt64);
     234             : 
     235           0 :     const LInt64Allocation lhs = lir->getInt64Operand(LCompareI64::Lhs);
     236           0 :     const LInt64Allocation rhs = lir->getInt64Operand(LCompareI64::Rhs);
     237           0 :     Register lhsReg = ToRegister64(lhs).reg;
     238           0 :     Register output = ToRegister(lir->output());
     239             : 
     240           0 :     if (IsConstant(rhs))
     241           0 :         masm.cmpPtr(lhsReg, ImmWord(ToInt64(rhs)));
     242             :     else
     243           0 :         masm.cmpPtr(lhsReg, ToOperand64(rhs));
     244             : 
     245           0 :     bool isSigned = mir->compareType() == MCompare::Compare_Int64;
     246           0 :     masm.emitSet(JSOpToCondition(lir->jsop(), isSigned), output);
     247           0 : }
     248             : 
     249             : void
     250           0 : CodeGeneratorX64::visitCompareI64AndBranch(LCompareI64AndBranch* lir)
     251             : {
     252           0 :     MCompare* mir = lir->cmpMir();
     253           0 :     MOZ_ASSERT(mir->compareType() == MCompare::Compare_Int64 ||
     254             :                mir->compareType() == MCompare::Compare_UInt64);
     255             : 
     256           0 :     LInt64Allocation lhs = lir->getInt64Operand(LCompareI64::Lhs);
     257           0 :     LInt64Allocation rhs = lir->getInt64Operand(LCompareI64::Rhs);
     258           0 :     Register lhsReg = ToRegister64(lhs).reg;
     259             : 
     260           0 :     if (IsConstant(rhs))
     261           0 :         masm.cmpPtr(lhsReg, ImmWord(ToInt64(rhs)));
     262             :     else
     263           0 :         masm.cmpPtr(lhsReg, ToOperand64(rhs));
     264             : 
     265           0 :     bool isSigned = mir->compareType() == MCompare::Compare_Int64;
     266           0 :     emitBranch(JSOpToCondition(lir->jsop(), isSigned), lir->ifTrue(), lir->ifFalse());
     267           0 : }
     268             : 
     269             : void
     270           0 : CodeGeneratorX64::visitDivOrModI64(LDivOrModI64* lir)
     271             : {
     272           0 :     Register lhs = ToRegister(lir->lhs());
     273           0 :     Register rhs = ToRegister(lir->rhs());
     274           0 :     Register output = ToRegister(lir->output());
     275             : 
     276           0 :     MOZ_ASSERT_IF(lhs != rhs, rhs != rax);
     277           0 :     MOZ_ASSERT(rhs != rdx);
     278           0 :     MOZ_ASSERT_IF(output == rax, ToRegister(lir->remainder()) == rdx);
     279           0 :     MOZ_ASSERT_IF(output == rdx, ToRegister(lir->remainder()) == rax);
     280             : 
     281           0 :     Label done;
     282             : 
     283             :     // Put the lhs in rax.
     284           0 :     if (lhs != rax)
     285           0 :         masm.mov(lhs, rax);
     286             : 
     287             :     // Handle divide by zero.
     288           0 :     if (lir->canBeDivideByZero()) {
     289           0 :         masm.branchTestPtr(Assembler::Zero, rhs, rhs, trap(lir, wasm::Trap::IntegerDivideByZero));
     290             :     }
     291             : 
     292             :     // Handle an integer overflow exception from INT64_MIN / -1.
     293           0 :     if (lir->canBeNegativeOverflow()) {
     294           0 :         Label notmin;
     295           0 :         masm.branchPtr(Assembler::NotEqual, lhs, ImmWord(INT64_MIN), &notmin);
     296           0 :         masm.branchPtr(Assembler::NotEqual, rhs, ImmWord(-1), &notmin);
     297           0 :         if (lir->mir()->isMod())
     298           0 :             masm.xorl(output, output);
     299             :         else
     300           0 :             masm.jump(trap(lir, wasm::Trap::IntegerOverflow));
     301           0 :         masm.jump(&done);
     302           0 :         masm.bind(&notmin);
     303             :     }
     304             : 
     305             :     // Sign extend the lhs into rdx to make rdx:rax.
     306           0 :     masm.cqo();
     307           0 :     masm.idivq(rhs);
     308             : 
     309           0 :     masm.bind(&done);
     310           0 : }
     311             : 
     312             : void
     313           0 : CodeGeneratorX64::visitUDivOrModI64(LUDivOrModI64* lir)
     314             : {
     315           0 :     Register lhs = ToRegister(lir->lhs());
     316           0 :     Register rhs = ToRegister(lir->rhs());
     317             : 
     318           0 :     DebugOnly<Register> output = ToRegister(lir->output());
     319           0 :     MOZ_ASSERT_IF(lhs != rhs, rhs != rax);
     320           0 :     MOZ_ASSERT(rhs != rdx);
     321           0 :     MOZ_ASSERT_IF(output.value == rax, ToRegister(lir->remainder()) == rdx);
     322           0 :     MOZ_ASSERT_IF(output.value == rdx, ToRegister(lir->remainder()) == rax);
     323             : 
     324             :     // Put the lhs in rax.
     325           0 :     if (lhs != rax)
     326           0 :         masm.mov(lhs, rax);
     327             : 
     328           0 :     Label done;
     329             : 
     330             :     // Prevent divide by zero.
     331           0 :     if (lir->canBeDivideByZero())
     332           0 :         masm.branchTestPtr(Assembler::Zero, rhs, rhs, trap(lir, wasm::Trap::IntegerDivideByZero));
     333             : 
     334             :     // Zero extend the lhs into rdx to make (rdx:rax).
     335           0 :     masm.xorl(rdx, rdx);
     336           0 :     masm.udivq(rhs);
     337             : 
     338           0 :     masm.bind(&done);
     339           0 : }
     340             : 
     341             : void
     342           0 : CodeGeneratorX64::visitWasmSelectI64(LWasmSelectI64* lir)
     343             : {
     344           0 :     MOZ_ASSERT(lir->mir()->type() == MIRType::Int64);
     345             : 
     346           0 :     Register cond = ToRegister(lir->condExpr());
     347             : 
     348           0 :     Operand falseExpr = ToOperandOrRegister64(lir->falseExpr());
     349             : 
     350           0 :     Register64 out = ToOutRegister64(lir);
     351           0 :     MOZ_ASSERT(ToRegister64(lir->trueExpr()) == out, "true expr is reused for input");
     352             : 
     353           0 :     masm.test32(cond, cond);
     354           0 :     masm.cmovzq(falseExpr, out.reg);
     355           0 : }
     356             : 
     357             : void
     358           0 : CodeGeneratorX64::visitWasmReinterpretFromI64(LWasmReinterpretFromI64* lir)
     359             : {
     360           0 :     MOZ_ASSERT(lir->mir()->type() == MIRType::Double);
     361           0 :     MOZ_ASSERT(lir->mir()->input()->type() == MIRType::Int64);
     362           0 :     masm.vmovq(ToRegister(lir->input()), ToFloatRegister(lir->output()));
     363           0 : }
     364             : 
     365             : void
     366           0 : CodeGeneratorX64::visitWasmReinterpretToI64(LWasmReinterpretToI64* lir)
     367             : {
     368           0 :     MOZ_ASSERT(lir->mir()->type() == MIRType::Int64);
     369           0 :     MOZ_ASSERT(lir->mir()->input()->type() == MIRType::Double);
     370           0 :     masm.vmovq(ToFloatRegister(lir->input()), ToRegister(lir->output()));
     371           0 : }
     372             : 
     373             : void
     374           0 : CodeGeneratorX64::visitWasmUint32ToDouble(LWasmUint32ToDouble* lir)
     375             : {
     376           0 :     masm.convertUInt32ToDouble(ToRegister(lir->input()), ToFloatRegister(lir->output()));
     377           0 : }
     378             : 
     379             : void
     380           0 : CodeGeneratorX64::visitWasmUint32ToFloat32(LWasmUint32ToFloat32* lir)
     381             : {
     382           0 :     masm.convertUInt32ToFloat32(ToRegister(lir->input()), ToFloatRegister(lir->output()));
     383           0 : }
     384             : 
     385             : void
     386           0 : CodeGeneratorX64::visitLoadTypedArrayElementStatic(LLoadTypedArrayElementStatic* ins)
     387             : {
     388           0 :     MOZ_CRASH("NYI");
     389             : }
     390             : 
     391             : void
     392           0 : CodeGeneratorX64::visitStoreTypedArrayElementStatic(LStoreTypedArrayElementStatic* ins)
     393             : {
     394           0 :     MOZ_CRASH("NYI");
     395             : }
     396             : 
     397             : void
     398           0 : CodeGeneratorX64::wasmStore(const wasm::MemoryAccessDesc& access, const LAllocation* value,
     399             :                             Operand dstAddr)
     400             : {
     401           0 :     if (value->isConstant()) {
     402           0 :         MOZ_ASSERT(!access.isSimd());
     403             : 
     404           0 :         masm.memoryBarrier(access.barrierBefore());
     405             : 
     406           0 :         const MConstant* mir = value->toConstant();
     407           0 :         Imm32 cst = Imm32(mir->type() == MIRType::Int32 ? mir->toInt32() : mir->toInt64());
     408             : 
     409           0 :         size_t storeOffset = masm.size();
     410           0 :         switch (access.type()) {
     411             :           case Scalar::Int8:
     412             :           case Scalar::Uint8:
     413           0 :             masm.movb(cst, dstAddr);
     414           0 :             break;
     415             :           case Scalar::Int16:
     416             :           case Scalar::Uint16:
     417           0 :             masm.movw(cst, dstAddr);
     418           0 :             break;
     419             :           case Scalar::Int32:
     420             :           case Scalar::Uint32:
     421           0 :             masm.movl(cst, dstAddr);
     422           0 :             break;
     423             :           case Scalar::Int64:
     424             :           case Scalar::Float32:
     425             :           case Scalar::Float64:
     426             :           case Scalar::Float32x4:
     427             :           case Scalar::Int8x16:
     428             :           case Scalar::Int16x8:
     429             :           case Scalar::Int32x4:
     430             :           case Scalar::Uint8Clamped:
     431             :           case Scalar::MaxTypedArrayViewType:
     432           0 :             MOZ_CRASH("unexpected array type");
     433             :         }
     434           0 :         masm.append(access, storeOffset, masm.framePushed());
     435             : 
     436           0 :         masm.memoryBarrier(access.barrierAfter());
     437             :     } else {
     438           0 :         masm.wasmStore(access, ToAnyRegister(value), dstAddr);
     439             :     }
     440           0 : }
     441             : 
     442             : template <typename T>
     443             : void
     444           0 : CodeGeneratorX64::emitWasmLoad(T* ins)
     445             : {
     446           0 :     const MWasmLoad* mir = ins->mir();
     447             : 
     448           0 :     uint32_t offset = mir->access().offset();
     449           0 :     MOZ_ASSERT(offset < wasm::OffsetGuardLimit);
     450             : 
     451           0 :     const LAllocation* ptr = ins->ptr();
     452           0 :     Operand srcAddr = ptr->isBogus()
     453             :                       ? Operand(HeapReg, offset)
     454           0 :                       : Operand(HeapReg, ToRegister(ptr), TimesOne, offset);
     455             : 
     456           0 :     if (mir->type() == MIRType::Int64)
     457           0 :         masm.wasmLoadI64(mir->access(), srcAddr, ToOutRegister64(ins));
     458             :     else
     459           0 :         masm.wasmLoad(mir->access(), srcAddr, ToAnyRegister(ins->output()));
     460           0 : }
     461             : 
     462             : void
     463           0 : CodeGeneratorX64::visitWasmLoad(LWasmLoad* ins)
     464             : {
     465           0 :     emitWasmLoad(ins);
     466           0 : }
     467             : 
     468             : void
     469           0 : CodeGeneratorX64::visitWasmLoadI64(LWasmLoadI64* ins)
     470             : {
     471           0 :     emitWasmLoad(ins);
     472           0 : }
     473             : 
     474             : template <typename T>
     475             : void
     476           0 : CodeGeneratorX64::emitWasmStore(T* ins)
     477             : {
     478           0 :     const MWasmStore* mir = ins->mir();
     479             : 
     480           0 :     uint32_t offset = mir->access().offset();
     481           0 :     MOZ_ASSERT(offset < wasm::OffsetGuardLimit);
     482             : 
     483           0 :     const LAllocation* value = ins->getOperand(ins->ValueIndex);
     484           0 :     const LAllocation* ptr = ins->ptr();
     485           0 :     Operand dstAddr = ptr->isBogus()
     486             :                       ? Operand(HeapReg, offset)
     487           0 :                       : Operand(HeapReg, ToRegister(ptr), TimesOne, offset);
     488             : 
     489           0 :     wasmStore(mir->access(), value, dstAddr);
     490           0 : }
     491             : 
     492             : void
     493           0 : CodeGeneratorX64::visitWasmStore(LWasmStore* ins)
     494             : {
     495           0 :     emitWasmStore(ins);
     496           0 : }
     497             : 
     498             : void
     499           0 : CodeGeneratorX64::visitWasmStoreI64(LWasmStoreI64* ins)
     500             : {
     501           0 :     emitWasmStore(ins);
     502           0 : }
     503             : 
     504             : void
     505           0 : CodeGeneratorX64::visitAsmJSLoadHeap(LAsmJSLoadHeap* ins)
     506             : {
     507           0 :     const MAsmJSLoadHeap* mir = ins->mir();
     508           0 :     MOZ_ASSERT(mir->offset() < wasm::OffsetGuardLimit);
     509             : 
     510           0 :     const LAllocation* ptr = ins->ptr();
     511           0 :     const LDefinition* out = ins->output();
     512             : 
     513           0 :     Scalar::Type accessType = mir->access().type();
     514           0 :     MOZ_ASSERT(!Scalar::isSimdType(accessType));
     515             : 
     516           0 :     Operand srcAddr = ptr->isBogus()
     517           0 :                       ? Operand(HeapReg, mir->offset())
     518           0 :                       : Operand(HeapReg, ToRegister(ptr), TimesOne, mir->offset());
     519             : 
     520           0 :     uint32_t before = masm.size();
     521           0 :     masm.wasmLoad(mir->access(), srcAddr, ToAnyRegister(out));
     522           0 :     uint32_t after = masm.size();
     523           0 :     verifyLoadDisassembly(before, after, accessType, srcAddr, *out->output());
     524           0 : }
     525             : 
     526             : void
     527           0 : CodeGeneratorX64::visitAsmJSStoreHeap(LAsmJSStoreHeap* ins)
     528             : {
     529           0 :     const MAsmJSStoreHeap* mir = ins->mir();
     530           0 :     MOZ_ASSERT(mir->offset() < wasm::OffsetGuardLimit);
     531             : 
     532           0 :     const LAllocation* ptr = ins->ptr();
     533           0 :     const LAllocation* value = ins->value();
     534             : 
     535           0 :     Scalar::Type accessType = mir->access().type();
     536           0 :     MOZ_ASSERT(!Scalar::isSimdType(accessType));
     537             : 
     538           0 :     canonicalizeIfDeterministic(accessType, value);
     539             : 
     540           0 :     Operand dstAddr = ptr->isBogus()
     541           0 :                       ? Operand(HeapReg, mir->offset())
     542           0 :                       : Operand(HeapReg, ToRegister(ptr), TimesOne, mir->offset());
     543             : 
     544           0 :     uint32_t before = masm.size();
     545           0 :     wasmStore(mir->access(), value, dstAddr);
     546           0 :     uint32_t after = masm.size();
     547           0 :     verifyStoreDisassembly(before, after, accessType, dstAddr, *value);
     548           0 : }
     549             : 
     550             : void
     551           0 : CodeGeneratorX64::visitAsmJSCompareExchangeHeap(LAsmJSCompareExchangeHeap* ins)
     552             : {
     553           0 :     MAsmJSCompareExchangeHeap* mir = ins->mir();
     554           0 :     MOZ_ASSERT(mir->access().offset() == 0);
     555             : 
     556           0 :     Register ptr = ToRegister(ins->ptr());
     557           0 :     Register oldval = ToRegister(ins->oldValue());
     558           0 :     Register newval = ToRegister(ins->newValue());
     559           0 :     MOZ_ASSERT(ins->addrTemp()->isBogusTemp());
     560             : 
     561           0 :     Scalar::Type accessType = mir->access().type();
     562           0 :     BaseIndex srcAddr(HeapReg, ptr, TimesOne);
     563             : 
     564           0 :     masm.compareExchangeToTypedIntArray(accessType == Scalar::Uint32 ? Scalar::Int32 : accessType,
     565             :                                         srcAddr,
     566             :                                         oldval,
     567             :                                         newval,
     568             :                                         InvalidReg,
     569           0 :                                         ToAnyRegister(ins->output()));
     570           0 : }
     571             : 
     572             : void
     573           0 : CodeGeneratorX64::visitAsmJSAtomicExchangeHeap(LAsmJSAtomicExchangeHeap* ins)
     574             : {
     575           0 :     MAsmJSAtomicExchangeHeap* mir = ins->mir();
     576           0 :     MOZ_ASSERT(mir->access().offset() == 0);
     577             : 
     578           0 :     Register ptr = ToRegister(ins->ptr());
     579           0 :     Register value = ToRegister(ins->value());
     580           0 :     MOZ_ASSERT(ins->addrTemp()->isBogusTemp());
     581             : 
     582           0 :     Scalar::Type accessType = mir->access().type();
     583           0 :     MOZ_ASSERT(accessType <= Scalar::Uint32);
     584             : 
     585           0 :     BaseIndex srcAddr(HeapReg, ptr, TimesOne);
     586             : 
     587           0 :     masm.atomicExchangeToTypedIntArray(accessType == Scalar::Uint32 ? Scalar::Int32 : accessType,
     588             :                                        srcAddr,
     589             :                                        value,
     590             :                                        InvalidReg,
     591           0 :                                        ToAnyRegister(ins->output()));
     592           0 : }
     593             : 
     594             : void
     595           0 : CodeGeneratorX64::visitAsmJSAtomicBinopHeap(LAsmJSAtomicBinopHeap* ins)
     596             : {
     597           0 :     MAsmJSAtomicBinopHeap* mir = ins->mir();
     598           0 :     MOZ_ASSERT(mir->access().offset() == 0);
     599           0 :     MOZ_ASSERT(mir->hasUses());
     600             : 
     601           0 :     Register ptr = ToRegister(ins->ptr());
     602           0 :     const LAllocation* value = ins->value();
     603           0 :     Register temp = ins->temp()->isBogusTemp() ? InvalidReg : ToRegister(ins->temp());
     604           0 :     AnyRegister output = ToAnyRegister(ins->output());
     605           0 :     MOZ_ASSERT(ins->addrTemp()->isBogusTemp());
     606             : 
     607           0 :     Scalar::Type accessType = mir->access().type();
     608           0 :     if (accessType == Scalar::Uint32)
     609           0 :         accessType = Scalar::Int32;
     610             : 
     611           0 :     AtomicOp op = mir->operation();
     612           0 :     BaseIndex srcAddr(HeapReg, ptr, TimesOne);
     613             : 
     614           0 :     if (value->isConstant()) {
     615           0 :         atomicBinopToTypedIntArray(op, accessType, Imm32(ToInt32(value)), srcAddr, temp, InvalidReg,
     616           0 :                                    output);
     617             :     } else {
     618           0 :         atomicBinopToTypedIntArray(op, accessType, ToRegister(value), srcAddr, temp, InvalidReg,
     619           0 :                                    output);
     620             :     }
     621           0 : }
     622             : 
     623             : void
     624           0 : CodeGeneratorX64::visitAsmJSAtomicBinopHeapForEffect(LAsmJSAtomicBinopHeapForEffect* ins)
     625             : {
     626           0 :     MAsmJSAtomicBinopHeap* mir = ins->mir();
     627           0 :     MOZ_ASSERT(mir->access().offset() == 0);
     628           0 :     MOZ_ASSERT(!mir->hasUses());
     629             : 
     630           0 :     Register ptr = ToRegister(ins->ptr());
     631           0 :     const LAllocation* value = ins->value();
     632           0 :     MOZ_ASSERT(ins->addrTemp()->isBogusTemp());
     633             : 
     634           0 :     Scalar::Type accessType = mir->access().type();
     635           0 :     AtomicOp op = mir->operation();
     636             : 
     637           0 :     BaseIndex srcAddr(HeapReg, ptr, TimesOne);
     638             : 
     639           0 :     if (value->isConstant())
     640           0 :         atomicBinopToTypedIntArray(op, accessType, Imm32(ToInt32(value)), srcAddr);
     641             :     else
     642           0 :         atomicBinopToTypedIntArray(op, accessType, ToRegister(value), srcAddr);
     643           0 : }
     644             : 
     645             : void
     646           0 : CodeGeneratorX64::visitTruncateDToInt32(LTruncateDToInt32* ins)
     647             : {
     648           0 :     FloatRegister input = ToFloatRegister(ins->input());
     649           0 :     Register output = ToRegister(ins->output());
     650             : 
     651             :     // On x64, branchTruncateDouble uses vcvttsd2sq. Unlike the x86
     652             :     // implementation, this should handle most doubles and we can just
     653             :     // call a stub if it fails.
     654           0 :     emitTruncateDouble(input, output, ins->mir());
     655           0 : }
     656             : 
     657             : void
     658           0 : CodeGeneratorX64::visitTruncateFToInt32(LTruncateFToInt32* ins)
     659             : {
     660           0 :     FloatRegister input = ToFloatRegister(ins->input());
     661           0 :     Register output = ToRegister(ins->output());
     662             : 
     663             :     // On x64, branchTruncateFloat32 uses vcvttss2sq. Unlike the x86
     664             :     // implementation, this should handle most floats and we can just
     665             :     // call a stub if it fails.
     666           0 :     emitTruncateFloat32(input, output, ins->mir());
     667           0 : }
     668             : 
     669             : void
     670           0 : CodeGeneratorX64::visitWrapInt64ToInt32(LWrapInt64ToInt32* lir)
     671             : {
     672           0 :     const LAllocation* input = lir->getOperand(0);
     673           0 :     Register output = ToRegister(lir->output());
     674             : 
     675           0 :     if (lir->mir()->bottomHalf())
     676           0 :         masm.movl(ToOperand(input), output);
     677             :     else
     678           0 :         MOZ_CRASH("Not implemented.");
     679           0 : }
     680             : 
     681             : void
     682           0 : CodeGeneratorX64::visitExtendInt32ToInt64(LExtendInt32ToInt64* lir)
     683             : {
     684           0 :     const LAllocation* input = lir->getOperand(0);
     685           0 :     Register output = ToRegister(lir->output());
     686             : 
     687           0 :     if (lir->mir()->isUnsigned())
     688           0 :         masm.movl(ToOperand(input), output);
     689             :     else
     690           0 :         masm.movslq(ToOperand(input), output);
     691           0 : }
     692             : 
     693             : void
     694           0 : CodeGeneratorX64::visitWasmTruncateToInt64(LWasmTruncateToInt64* lir)
     695             : {
     696           0 :     FloatRegister input = ToFloatRegister(lir->input());
     697           0 :     Register64 output = ToOutRegister64(lir);
     698             : 
     699           0 :     MWasmTruncateToInt64* mir = lir->mir();
     700           0 :     MIRType inputType = mir->input()->type();
     701             : 
     702           0 :     MOZ_ASSERT(inputType == MIRType::Double || inputType == MIRType::Float32);
     703             : 
     704           0 :     auto* ool = new(alloc()) OutOfLineWasmTruncateCheck(mir, input);
     705           0 :     addOutOfLineCode(ool, mir);
     706             : 
     707           0 :     FloatRegister temp = mir->isUnsigned() ? ToFloatRegister(lir->temp()) : InvalidFloatReg;
     708             : 
     709           0 :     Label* oolEntry = ool->entry();
     710           0 :     Label* oolRejoin = ool->rejoin();
     711           0 :     if (inputType == MIRType::Double) {
     712           0 :         if (mir->isUnsigned())
     713           0 :             masm.wasmTruncateDoubleToUInt64(input, output, oolEntry, oolRejoin, temp);
     714             :         else
     715           0 :             masm.wasmTruncateDoubleToInt64(input, output, oolEntry, oolRejoin, temp);
     716             :     } else {
     717           0 :         if (mir->isUnsigned())
     718           0 :             masm.wasmTruncateFloat32ToUInt64(input, output, oolEntry, oolRejoin, temp);
     719             :         else
     720           0 :             masm.wasmTruncateFloat32ToInt64(input, output, oolEntry, oolRejoin, temp);
     721             :     }
     722           0 : }
     723             : 
     724             : void
     725           0 : CodeGeneratorX64::visitInt64ToFloatingPoint(LInt64ToFloatingPoint* lir)
     726             : {
     727           0 :     Register64 input = ToRegister64(lir->getInt64Operand(0));
     728           0 :     FloatRegister output = ToFloatRegister(lir->output());
     729             : 
     730           0 :     MInt64ToFloatingPoint* mir = lir->mir();
     731           0 :     bool isUnsigned = mir->isUnsigned();
     732             : 
     733           0 :     MIRType outputType = mir->type();
     734           0 :     MOZ_ASSERT(outputType == MIRType::Double || outputType == MIRType::Float32);
     735           0 :     MOZ_ASSERT(isUnsigned == !lir->getTemp(0)->isBogusTemp());
     736             : 
     737           0 :     if (outputType == MIRType::Double) {
     738           0 :         if (isUnsigned)
     739           0 :             masm.convertUInt64ToDouble(input, output, ToRegister(lir->getTemp(0)));
     740             :         else
     741           0 :             masm.convertInt64ToDouble(input, output);
     742             :     } else {
     743           0 :         if (isUnsigned)
     744           0 :             masm.convertUInt64ToFloat32(input, output, ToRegister(lir->getTemp(0)));
     745             :         else
     746           0 :             masm.convertInt64ToFloat32(input, output);
     747             :     }
     748           0 : }
     749             : 
     750             : void
     751           0 : CodeGeneratorX64::visitNotI64(LNotI64* lir)
     752             : {
     753           0 :     masm.cmpq(Imm32(0), ToRegister(lir->input()));
     754           0 :     masm.emitSet(Assembler::Equal, ToRegister(lir->output()));
     755           0 : }
     756             : 
     757             : void
     758           0 : CodeGeneratorX64::visitClzI64(LClzI64* lir)
     759             : {
     760           0 :     Register64 input = ToRegister64(lir->getInt64Operand(0));
     761           0 :     Register64 output = ToOutRegister64(lir);
     762           0 :     masm.clz64(input, output.reg);
     763           0 : }
     764             : 
     765             : void
     766           0 : CodeGeneratorX64::visitCtzI64(LCtzI64* lir)
     767             : {
     768           0 :     Register64 input = ToRegister64(lir->getInt64Operand(0));
     769           0 :     Register64 output = ToOutRegister64(lir);
     770           0 :     masm.ctz64(input, output.reg);
     771           0 : }
     772             : 
     773             : void
     774           0 : CodeGeneratorX64::visitTestI64AndBranch(LTestI64AndBranch* lir)
     775             : {
     776           0 :     Register input = ToRegister(lir->input());
     777           0 :     masm.testq(input, input);
     778           0 :     emitBranch(Assembler::NonZero, lir->ifTrue(), lir->ifFalse());
     779           0 : }

Generated by: LCOV version 1.13