michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * vim: set ts=8 sts=4 et sw=4 tw=99: michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "jit/x64/Lowering-x64.h" michael@0: michael@0: #include "jit/MIR.h" michael@0: #include "jit/x64/Assembler-x64.h" michael@0: michael@0: #include "jit/shared/Lowering-shared-inl.h" michael@0: michael@0: using namespace js; michael@0: using namespace js::jit; michael@0: michael@0: bool michael@0: LIRGeneratorX64::useBox(LInstruction *lir, size_t n, MDefinition *mir, michael@0: LUse::Policy policy, bool useAtStart) michael@0: { michael@0: JS_ASSERT(mir->type() == MIRType_Value); michael@0: michael@0: if (!ensureDefined(mir)) michael@0: return false; michael@0: lir->setOperand(n, LUse(mir->virtualRegister(), policy, useAtStart)); michael@0: return true; michael@0: } michael@0: michael@0: bool michael@0: LIRGeneratorX64::useBoxFixed(LInstruction *lir, size_t n, MDefinition *mir, Register reg1, Register) michael@0: { michael@0: JS_ASSERT(mir->type() == MIRType_Value); michael@0: michael@0: if (!ensureDefined(mir)) michael@0: return false; michael@0: lir->setOperand(n, LUse(reg1, mir->virtualRegister())); michael@0: return true; michael@0: } michael@0: michael@0: LAllocation michael@0: LIRGeneratorX64::useByteOpRegister(MDefinition *mir) michael@0: { michael@0: return useRegister(mir); michael@0: } michael@0: michael@0: LAllocation michael@0: LIRGeneratorX64::useByteOpRegisterOrNonDoubleConstant(MDefinition *mir) michael@0: { michael@0: return useRegisterOrNonDoubleConstant(mir); michael@0: } michael@0: michael@0: LDefinition michael@0: LIRGeneratorX64::tempToUnbox() michael@0: { michael@0: return temp(); michael@0: } michael@0: michael@0: bool michael@0: LIRGeneratorX64::visitBox(MBox *box) michael@0: { michael@0: MDefinition *opd = box->getOperand(0); michael@0: michael@0: // If the operand is a constant, emit near its uses. michael@0: if (opd->isConstant() && box->canEmitAtUses()) michael@0: return emitAtUses(box); michael@0: michael@0: if (opd->isConstant()) michael@0: return define(new(alloc()) LValue(opd->toConstant()->value()), box, LDefinition(LDefinition::BOX)); michael@0: michael@0: LBox *ins = new(alloc()) LBox(opd->type(), useRegister(opd)); michael@0: return define(ins, box, LDefinition(LDefinition::BOX)); michael@0: } michael@0: michael@0: bool michael@0: LIRGeneratorX64::visitUnbox(MUnbox *unbox) michael@0: { michael@0: MDefinition *box = unbox->getOperand(0); michael@0: LUnboxBase *lir; michael@0: if (IsFloatingPointType(unbox->type())) michael@0: lir = new(alloc()) LUnboxFloatingPoint(useRegisterAtStart(box), unbox->type()); michael@0: else michael@0: lir = new(alloc()) LUnbox(useRegisterAtStart(box)); michael@0: michael@0: if (unbox->fallible() && !assignSnapshot(lir, unbox->bailoutKind())) michael@0: return false; michael@0: michael@0: return define(lir, unbox); michael@0: } michael@0: michael@0: bool michael@0: LIRGeneratorX64::visitReturn(MReturn *ret) michael@0: { michael@0: MDefinition *opd = ret->getOperand(0); michael@0: JS_ASSERT(opd->type() == MIRType_Value); michael@0: michael@0: LReturn *ins = new(alloc()) LReturn; michael@0: ins->setOperand(0, useFixed(opd, JSReturnReg)); michael@0: return add(ins); michael@0: } michael@0: michael@0: bool michael@0: LIRGeneratorX64::defineUntypedPhi(MPhi *phi, size_t lirIndex) michael@0: { michael@0: return defineTypedPhi(phi, lirIndex); michael@0: } michael@0: michael@0: void michael@0: LIRGeneratorX64::lowerUntypedPhiInput(MPhi *phi, uint32_t inputPosition, LBlock *block, size_t lirIndex) michael@0: { michael@0: lowerTypedPhiInput(phi, inputPosition, block, lirIndex); michael@0: } michael@0: michael@0: bool michael@0: LIRGeneratorX64::visitAsmJSUnsignedToDouble(MAsmJSUnsignedToDouble *ins) michael@0: { michael@0: JS_ASSERT(ins->input()->type() == MIRType_Int32); michael@0: LAsmJSUInt32ToDouble *lir = new(alloc()) LAsmJSUInt32ToDouble(useRegisterAtStart(ins->input())); michael@0: return define(lir, ins); michael@0: } michael@0: michael@0: bool michael@0: LIRGeneratorX64::visitAsmJSUnsignedToFloat32(MAsmJSUnsignedToFloat32 *ins) michael@0: { michael@0: JS_ASSERT(ins->input()->type() == MIRType_Int32); michael@0: LAsmJSUInt32ToFloat32 *lir = new(alloc()) LAsmJSUInt32ToFloat32(useRegisterAtStart(ins->input())); michael@0: return define(lir, ins); michael@0: } michael@0: michael@0: bool michael@0: LIRGeneratorX64::visitAsmJSLoadHeap(MAsmJSLoadHeap *ins) michael@0: { michael@0: MDefinition *ptr = ins->ptr(); michael@0: JS_ASSERT(ptr->type() == MIRType_Int32); michael@0: michael@0: // The X64 does not inline an explicit bounds check so has no need to keep the michael@0: // index in a register, however only a positive index is accepted because a michael@0: // negative offset encoded as an offset in the addressing mode would not wrap michael@0: // back into the protected area reserved for the heap. michael@0: if (ptr->isConstant() && ptr->toConstant()->value().toInt32() >= 0) { michael@0: LAsmJSLoadHeap *lir = new(alloc()) LAsmJSLoadHeap(LAllocation(ptr->toConstant()->vp())); michael@0: return define(lir, ins); michael@0: } michael@0: return define(new(alloc()) LAsmJSLoadHeap(useRegisterAtStart(ptr)), ins); michael@0: } michael@0: michael@0: bool michael@0: LIRGeneratorX64::visitAsmJSStoreHeap(MAsmJSStoreHeap *ins) michael@0: { michael@0: MDefinition *ptr = ins->ptr(); michael@0: JS_ASSERT(ptr->type() == MIRType_Int32); michael@0: LAsmJSStoreHeap *lir; michael@0: michael@0: // Note only a positive constant index is accepted because a negative offset michael@0: // encoded as an offset in the addressing mode would not wrap back into the michael@0: // protected area reserved for the heap. michael@0: LAllocation ptrAlloc = useRegisterOrNonNegativeConstantAtStart(ptr); michael@0: switch (ins->viewType()) { michael@0: case ArrayBufferView::TYPE_INT8: case ArrayBufferView::TYPE_UINT8: michael@0: case ArrayBufferView::TYPE_INT16: case ArrayBufferView::TYPE_UINT16: michael@0: case ArrayBufferView::TYPE_INT32: case ArrayBufferView::TYPE_UINT32: michael@0: lir = new(alloc()) LAsmJSStoreHeap(ptrAlloc, useRegisterOrConstantAtStart(ins->value())); michael@0: break; michael@0: case ArrayBufferView::TYPE_FLOAT32: case ArrayBufferView::TYPE_FLOAT64: michael@0: lir = new(alloc()) LAsmJSStoreHeap(ptrAlloc, useRegisterAtStart(ins->value())); michael@0: break; michael@0: default: MOZ_ASSUME_UNREACHABLE("unexpected array type"); michael@0: } michael@0: michael@0: return add(lir, ins); michael@0: } michael@0: michael@0: bool michael@0: LIRGeneratorX64::visitAsmJSLoadFuncPtr(MAsmJSLoadFuncPtr *ins) michael@0: { michael@0: return define(new(alloc()) LAsmJSLoadFuncPtr(useRegister(ins->index()), temp()), ins); michael@0: } michael@0: michael@0: bool michael@0: LIRGeneratorX64::visitStoreTypedArrayElementStatic(MStoreTypedArrayElementStatic *ins) michael@0: { michael@0: MOZ_ASSUME_UNREACHABLE("NYI"); michael@0: }