1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  * vim: set ts=8 sts=2 et sw=2 tw=80:
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/mips64/Lowering-mips64.h"
8 
9 #include "jit/Lowering.h"
10 #include "jit/mips64/Assembler-mips64.h"
11 #include "jit/MIR.h"
12 
13 #include "jit/shared/Lowering-shared-inl.h"
14 
15 using namespace js;
16 using namespace js::jit;
17 
defineInt64Phi(MPhi * phi,size_t lirIndex)18 void LIRGeneratorMIPS64::defineInt64Phi(MPhi* phi, size_t lirIndex) {
19   defineTypedPhi(phi, lirIndex);
20 }
21 
lowerInt64PhiInput(MPhi * phi,uint32_t inputPosition,LBlock * block,size_t lirIndex)22 void LIRGeneratorMIPS64::lowerInt64PhiInput(MPhi* phi, uint32_t inputPosition,
23                                             LBlock* block, size_t lirIndex) {
24   lowerTypedPhiInput(phi, inputPosition, block, lirIndex);
25 }
26 
useBoxFixed(MDefinition * mir,Register reg1,Register reg2,bool useAtStart)27 LBoxAllocation LIRGeneratorMIPS64::useBoxFixed(MDefinition* mir, Register reg1,
28                                                Register reg2, bool useAtStart) {
29   MOZ_ASSERT(mir->type() == MIRType::Value);
30 
31   ensureDefined(mir);
32   return LBoxAllocation(LUse(reg1, mir->virtualRegister(), useAtStart));
33 }
34 
lowerDivI64(MDiv * div)35 void LIRGeneratorMIPS64::lowerDivI64(MDiv* div) {
36   if (div->isUnsigned()) {
37     lowerUDivI64(div);
38     return;
39   }
40 
41   LDivOrModI64* lir = new (alloc())
42       LDivOrModI64(useRegister(div->lhs()), useRegister(div->rhs()), temp());
43   defineInt64(lir, div);
44 }
45 
lowerWasmBuiltinDivI64(MWasmBuiltinDivI64 * div)46 void LIRGeneratorMIPS64::lowerWasmBuiltinDivI64(MWasmBuiltinDivI64* div) {
47   MOZ_CRASH("We don't use runtime div for this architecture");
48 }
49 
lowerModI64(MMod * mod)50 void LIRGeneratorMIPS64::lowerModI64(MMod* mod) {
51   if (mod->isUnsigned()) {
52     lowerUModI64(mod);
53     return;
54   }
55 
56   LDivOrModI64* lir = new (alloc())
57       LDivOrModI64(useRegister(mod->lhs()), useRegister(mod->rhs()), temp());
58   defineInt64(lir, mod);
59 }
60 
lowerWasmBuiltinModI64(MWasmBuiltinModI64 * mod)61 void LIRGeneratorMIPS64::lowerWasmBuiltinModI64(MWasmBuiltinModI64* mod) {
62   MOZ_CRASH("We don't use runtime mod for this architecture");
63 }
64 
lowerUDivI64(MDiv * div)65 void LIRGeneratorMIPS64::lowerUDivI64(MDiv* div) {
66   LUDivOrModI64* lir = new (alloc())
67       LUDivOrModI64(useRegister(div->lhs()), useRegister(div->rhs()), temp());
68   defineInt64(lir, div);
69 }
70 
lowerUModI64(MMod * mod)71 void LIRGeneratorMIPS64::lowerUModI64(MMod* mod) {
72   LUDivOrModI64* lir = new (alloc())
73       LUDivOrModI64(useRegister(mod->lhs()), useRegister(mod->rhs()), temp());
74   defineInt64(lir, mod);
75 }
76 
lowerBigIntDiv(MBigIntDiv * ins)77 void LIRGeneratorMIPS64::lowerBigIntDiv(MBigIntDiv* ins) {
78   auto* lir = new (alloc()) LBigIntDiv(useRegister(ins->lhs()),
79                                        useRegister(ins->rhs()), temp(), temp());
80   define(lir, ins);
81   assignSafepoint(lir, ins);
82 }
83 
lowerBigIntMod(MBigIntMod * ins)84 void LIRGeneratorMIPS64::lowerBigIntMod(MBigIntMod* ins) {
85   auto* lir = new (alloc()) LBigIntMod(useRegister(ins->lhs()),
86                                        useRegister(ins->rhs()), temp(), temp());
87   define(lir, ins);
88   assignSafepoint(lir, ins);
89 }
90 
lowerAtomicLoad64(MLoadUnboxedScalar * ins)91 void LIRGeneratorMIPS64::lowerAtomicLoad64(MLoadUnboxedScalar* ins) {
92   const LUse elements = useRegister(ins->elements());
93   const LAllocation index =
94       useRegisterOrIndexConstant(ins->index(), ins->storageType());
95 
96   auto* lir = new (alloc()) LAtomicLoad64(elements, index, temp(), tempInt64());
97   define(lir, ins);
98   assignSafepoint(lir, ins);
99 }
100 
lowerAtomicStore64(MStoreUnboxedScalar * ins)101 void LIRGeneratorMIPS64::lowerAtomicStore64(MStoreUnboxedScalar* ins) {
102   LUse elements = useRegister(ins->elements());
103   LAllocation index =
104       useRegisterOrIndexConstant(ins->index(), ins->writeType());
105   LAllocation value = useRegister(ins->value());
106 
107   add(new (alloc()) LAtomicStore64(elements, index, value, tempInt64()), ins);
108 }
109 
visitBox(MBox * box)110 void LIRGenerator::visitBox(MBox* box) {
111   MDefinition* opd = box->getOperand(0);
112 
113   // If the operand is a constant, emit near its uses.
114   if (opd->isConstant() && box->canEmitAtUses()) {
115     emitAtUses(box);
116     return;
117   }
118 
119   if (opd->isConstant()) {
120     define(new (alloc()) LValue(opd->toConstant()->toJSValue()), box,
121            LDefinition(LDefinition::BOX));
122   } else {
123     LBox* ins = new (alloc()) LBox(useRegister(opd), opd->type());
124     define(ins, box, LDefinition(LDefinition::BOX));
125   }
126 }
127 
visitUnbox(MUnbox * unbox)128 void LIRGenerator::visitUnbox(MUnbox* unbox) {
129   MDefinition* box = unbox->getOperand(0);
130   MOZ_ASSERT(box->type() == MIRType::Value);
131 
132   LUnbox* lir;
133   if (IsFloatingPointType(unbox->type())) {
134     lir = new (alloc())
135         LUnboxFloatingPoint(useRegisterAtStart(box), unbox->type());
136   } else if (unbox->fallible()) {
137     // If the unbox is fallible, load the Value in a register first to
138     // avoid multiple loads.
139     lir = new (alloc()) LUnbox(useRegisterAtStart(box));
140   } else {
141     lir = new (alloc()) LUnbox(useAtStart(box));
142   }
143 
144   if (unbox->fallible()) {
145     assignSnapshot(lir, unbox->bailoutKind());
146   }
147 
148   define(lir, unbox);
149 }
150 
visitReturnImpl(MDefinition * opd,bool isGenerator)151 void LIRGenerator::visitReturnImpl(MDefinition* opd, bool isGenerator) {
152   MOZ_ASSERT(opd->type() == MIRType::Value);
153 
154   LReturn* ins = new (alloc()) LReturn(isGenerator);
155   ins->setOperand(0, useFixed(opd, JSReturnReg));
156   add(ins);
157 }
158 
lowerUntypedPhiInput(MPhi * phi,uint32_t inputPosition,LBlock * block,size_t lirIndex)159 void LIRGeneratorMIPS64::lowerUntypedPhiInput(MPhi* phi, uint32_t inputPosition,
160                                               LBlock* block, size_t lirIndex) {
161   lowerTypedPhiInput(phi, inputPosition, block, lirIndex);
162 }
163 
lowerTruncateDToInt32(MTruncateToInt32 * ins)164 void LIRGeneratorMIPS64::lowerTruncateDToInt32(MTruncateToInt32* ins) {
165   MDefinition* opd = ins->input();
166   MOZ_ASSERT(opd->type() == MIRType::Double);
167 
168   define(new (alloc()) LTruncateDToInt32(useRegister(opd), tempDouble()), ins);
169 }
170 
lowerTruncateFToInt32(MTruncateToInt32 * ins)171 void LIRGeneratorMIPS64::lowerTruncateFToInt32(MTruncateToInt32* ins) {
172   MDefinition* opd = ins->input();
173   MOZ_ASSERT(opd->type() == MIRType::Float32);
174 
175   define(new (alloc()) LTruncateFToInt32(useRegister(opd), tempFloat32()), ins);
176 }
177 
visitWasmTruncateToInt64(MWasmTruncateToInt64 * ins)178 void LIRGenerator::visitWasmTruncateToInt64(MWasmTruncateToInt64* ins) {
179   MDefinition* opd = ins->input();
180   MOZ_ASSERT(opd->type() == MIRType::Double || opd->type() == MIRType::Float32);
181 
182   defineInt64(new (alloc()) LWasmTruncateToInt64(useRegister(opd)), ins);
183 }
184 
lowerWasmBuiltinTruncateToInt64(MWasmBuiltinTruncateToInt64 * ins)185 void LIRGeneratorMIPS64::lowerWasmBuiltinTruncateToInt64(
186     MWasmBuiltinTruncateToInt64* ins) {
187   MOZ_CRASH("We don't use it for this architecture");
188 }
189 
visitInt64ToFloatingPoint(MInt64ToFloatingPoint * ins)190 void LIRGenerator::visitInt64ToFloatingPoint(MInt64ToFloatingPoint* ins) {
191   MDefinition* opd = ins->input();
192   MOZ_ASSERT(opd->type() == MIRType::Int64);
193   MOZ_ASSERT(IsFloatingPointType(ins->type()));
194 
195   define(new (alloc()) LInt64ToFloatingPoint(useInt64Register(opd)), ins);
196 }
197 
lowerBuiltinInt64ToFloatingPoint(MBuiltinInt64ToFloatingPoint * ins)198 void LIRGeneratorMIPS64::lowerBuiltinInt64ToFloatingPoint(
199     MBuiltinInt64ToFloatingPoint* ins) {
200   MOZ_CRASH("We don't use it for this architecture");
201 }
202