| Index: src/compiler/mips64/code-generator-mips64.cc
|
| diff --git a/src/compiler/mips64/code-generator-mips64.cc b/src/compiler/mips64/code-generator-mips64.cc
|
| index 12f7161f98e27cd1d4b2c9f480b9bfb1137535e5..45cf340b65e68ab970eb65a26f2e52d2a4e9cf40 100644
|
| --- a/src/compiler/mips64/code-generator-mips64.cc
|
| +++ b/src/compiler/mips64/code-generator-mips64.cc
|
| @@ -1935,12 +1935,13 @@ static bool convertCondition(FlagsCondition condition, Condition& cc) {
|
| return false;
|
| }
|
|
|
| +void AssembleBranchToLabels(CodeGenerator* gen, MacroAssembler* masm,
|
| + Instruction* instr, FlagsCondition condition,
|
| + Label* tlabel, Label* flabel, bool fallthru) {
|
| +#undef __
|
| +#define __ masm->
|
| + MipsOperandConverter i(gen, instr);
|
|
|
| -// Assembles branches after an instruction.
|
| -void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
|
| - MipsOperandConverter i(this, instr);
|
| - Label* tlabel = branch->true_label;
|
| - Label* flabel = branch->false_label;
|
| Condition cc = kNoCondition;
|
| // MIPS does not have condition code flags, so compare and branch are
|
| // implemented differently than on the other arch's. The compare operations
|
| @@ -1950,17 +1951,17 @@ void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
|
| // they are tested here.
|
|
|
| if (instr->arch_opcode() == kMips64Tst) {
|
| - cc = FlagsConditionToConditionTst(branch->condition);
|
| + cc = FlagsConditionToConditionTst(condition);
|
| __ And(at, i.InputRegister(0), i.InputOperand(1));
|
| __ Branch(tlabel, cc, at, Operand(zero_reg));
|
| } else if (instr->arch_opcode() == kMips64Dadd ||
|
| instr->arch_opcode() == kMips64Dsub) {
|
| - cc = FlagsConditionToConditionOvf(branch->condition);
|
| + cc = FlagsConditionToConditionOvf(condition);
|
| __ dsra32(kScratchReg, i.OutputRegister(), 0);
|
| __ sra(at, i.OutputRegister(), 31);
|
| __ Branch(tlabel, cc, at, Operand(kScratchReg));
|
| } else if (instr->arch_opcode() == kMips64DaddOvf) {
|
| - switch (branch->condition) {
|
| + switch (condition) {
|
| case kOverflow:
|
| __ DaddBranchOvf(i.OutputRegister(), i.InputRegister(0),
|
| i.InputOperand(1), tlabel, flabel);
|
| @@ -1970,11 +1971,11 @@ void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
|
| i.InputOperand(1), flabel, tlabel);
|
| break;
|
| default:
|
| - UNSUPPORTED_COND(kMips64DaddOvf, branch->condition);
|
| + UNSUPPORTED_COND(kMips64DaddOvf, condition);
|
| break;
|
| }
|
| } else if (instr->arch_opcode() == kMips64DsubOvf) {
|
| - switch (branch->condition) {
|
| + switch (condition) {
|
| case kOverflow:
|
| __ DsubBranchOvf(i.OutputRegister(), i.InputRegister(0),
|
| i.InputOperand(1), tlabel, flabel);
|
| @@ -1984,11 +1985,11 @@ void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
|
| i.InputOperand(1), flabel, tlabel);
|
| break;
|
| default:
|
| - UNSUPPORTED_COND(kMips64DsubOvf, branch->condition);
|
| + UNSUPPORTED_COND(kMips64DsubOvf, condition);
|
| break;
|
| }
|
| } else if (instr->arch_opcode() == kMips64MulOvf) {
|
| - switch (branch->condition) {
|
| + switch (condition) {
|
| case kOverflow: {
|
| __ MulBranchOvf(i.OutputRegister(), i.InputRegister(0),
|
| i.InputOperand(1), tlabel, flabel, kScratchReg);
|
| @@ -1998,15 +1999,15 @@ void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
|
| i.InputOperand(1), flabel, tlabel, kScratchReg);
|
| } break;
|
| default:
|
| - UNSUPPORTED_COND(kMips64MulOvf, branch->condition);
|
| + UNSUPPORTED_COND(kMips64MulOvf, condition);
|
| break;
|
| }
|
| } else if (instr->arch_opcode() == kMips64Cmp) {
|
| - cc = FlagsConditionToConditionCmp(branch->condition);
|
| + cc = FlagsConditionToConditionCmp(condition);
|
| __ Branch(tlabel, cc, i.InputRegister(0), i.InputOperand(1));
|
| } else if (instr->arch_opcode() == kMips64CmpS) {
|
| - if (!convertCondition(branch->condition, cc)) {
|
| - UNSUPPORTED_COND(kMips64CmpS, branch->condition);
|
| + if (!convertCondition(condition, cc)) {
|
| + UNSUPPORTED_COND(kMips64CmpS, condition);
|
| }
|
| FPURegister left = i.InputOrZeroSingleRegister(0);
|
| FPURegister right = i.InputOrZeroSingleRegister(1);
|
| @@ -2016,8 +2017,8 @@ void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
|
| }
|
| __ BranchF32(tlabel, nullptr, cc, left, right);
|
| } else if (instr->arch_opcode() == kMips64CmpD) {
|
| - if (!convertCondition(branch->condition, cc)) {
|
| - UNSUPPORTED_COND(kMips64CmpD, branch->condition);
|
| + if (!convertCondition(condition, cc)) {
|
| + UNSUPPORTED_COND(kMips64CmpD, condition);
|
| }
|
| FPURegister left = i.InputOrZeroDoubleRegister(0);
|
| FPURegister right = i.InputOrZeroDoubleRegister(1);
|
| @@ -2031,7 +2032,18 @@ void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
|
| instr->arch_opcode());
|
| UNIMPLEMENTED();
|
| }
|
| - if (!branch->fallthru) __ Branch(flabel); // no fallthru to flabel.
|
| + if (!fallthru) __ Branch(flabel); // no fallthru to flabel.
|
| +#undef __
|
| +#define __ masm()->
|
| +}
|
| +
|
| +// Assembles branches after an instruction.
|
| +void CodeGenerator::AssembleArchBranch(Instruction* instr, BranchInfo* branch) {
|
| + Label* tlabel = branch->true_label;
|
| + Label* flabel = branch->false_label;
|
| +
|
| + AssembleBranchToLabels(this, masm(), instr, branch->condition, tlabel, flabel,
|
| + branch->fallthru);
|
| }
|
|
|
|
|
| @@ -2041,7 +2053,60 @@ void CodeGenerator::AssembleArchJump(RpoNumber target) {
|
|
|
| void CodeGenerator::AssembleArchTrap(Instruction* instr,
|
| FlagsCondition condition) {
|
| - UNREACHABLE();
|
| + class OutOfLineTrap final : public OutOfLineCode {
|
| + public:
|
| + OutOfLineTrap(CodeGenerator* gen, bool frame_elided, Instruction* instr)
|
| + : OutOfLineCode(gen),
|
| + frame_elided_(frame_elided),
|
| + instr_(instr),
|
| + gen_(gen) {}
|
| + void Generate() final {
|
| + MipsOperandConverter i(gen_, instr_);
|
| + Runtime::FunctionId trap_id = static_cast<Runtime::FunctionId>(
|
| + i.InputInt32(instr_->InputCount() - 1));
|
| + bool old_has_frame = __ has_frame();
|
| + if (frame_elided_) {
|
| + __ set_has_frame(true);
|
| + __ EnterFrame(StackFrame::WASM_COMPILED);
|
| + }
|
| + GenerateCallToTrap(trap_id);
|
| + if (frame_elided_) {
|
| + __ set_has_frame(old_has_frame);
|
| + }
|
| + if (FLAG_debug_code) {
|
| + __ stop(GetBailoutReason(kUnexpectedReturnFromWasmTrap));
|
| + }
|
| + }
|
| +
|
| + private:
|
| + void GenerateCallToTrap(Runtime::FunctionId trap_id) {
|
| + if (trap_id == Runtime::kNumFunctions) {
|
| + // We cannot test calls to the runtime in cctest/test-run-wasm.
|
| + // Therefore we emit a call to C here instead of a call to the runtime.
|
| + // We use the context register as the scratch register, because we do
|
| + // not have a context here.
|
| + __ PrepareCallCFunction(0, 0, cp);
|
| + __ CallCFunction(
|
| + ExternalReference::wasm_call_trap_callback_for_testing(isolate()),
|
| + 0);
|
| + } else {
|
| + __ Move(cp, isolate()->native_context());
|
| + gen_->AssembleSourcePosition(instr_);
|
| + __ CallRuntime(trap_id);
|
| + }
|
| + ReferenceMap* reference_map =
|
| + new (gen_->zone()) ReferenceMap(gen_->zone());
|
| + gen_->RecordSafepoint(reference_map, Safepoint::kSimple, 0,
|
| + Safepoint::kNoLazyDeopt);
|
| + }
|
| + bool frame_elided_;
|
| + Instruction* instr_;
|
| + CodeGenerator* gen_;
|
| + };
|
| + bool frame_elided = !frame_access_state()->has_frame();
|
| + auto ool = new (zone()) OutOfLineTrap(this, frame_elided, instr);
|
| + Label* tlabel = ool->entry();
|
| + AssembleBranchToLabels(this, masm(), instr, condition, tlabel, nullptr, true);
|
| }
|
|
|
| // Assembles boolean materializations after an instruction.
|
|
|