Commit 3ede3487 authored by Andreas Haas's avatar Andreas Haas Committed by Commit Bot

[mips][turbofan] Implement on-stack returns.

This is the implementation of crrev.com/c/766371 for mips.

Original description:

Add the ability to return (multiple) return values on the stack:

- Extend stack frames with a new buffer region for return slots.
  This region is located at the end of a caller's frame such that
  its slots can be indexed as caller frame slots in a callee
  (located beyond its parameters) and assigned return values.
- Adjust stack frame constructon and deconstruction accordingly.
- Extend linkage computation to support register plus stack returns.
- Reserve return slots in caller frame when respective calls occur.
- Introduce and generate architecture instructions ('peek') for
  reading back results from return slots in the caller.
- Aggressive tests.
- Some minor clean-up.

R=v8-mips-ports@googlegroups.com

Change-Id: I2f30cc297771ec74b0b935b6ea28d3d61a986d5c
Reviewed-on: https://chromium-review.googlesource.com/839660Reviewed-by: 's avatarIvica Bogosavljevic <ivica.bogosavljevic@mips.com>
Commit-Queue: Ivica Bogosavljevic <ivica.bogosavljevic@mips.com>
Commit-Queue: Andreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#50272}
parent 77f96a5d
......@@ -1708,6 +1708,23 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
frame_access_state()->IncreaseSPDelta(1);
}
break;
case kMipsPeek: {
int reverse_slot = MiscField::decode(instr->opcode());
int offset =
FrameSlotToFPOffset(frame()->GetTotalFrameSlotCount() - reverse_slot);
if (instr->OutputAt(0)->IsFPRegister()) {
LocationOperand* op = LocationOperand::cast(instr->OutputAt(0));
if (op->representation() == MachineRepresentation::kFloat64) {
__ Ldc1(i.OutputDoubleRegister(), MemOperand(fp, offset));
} else {
DCHECK_EQ(op->representation(), MachineRepresentation::kFloat32);
__ lwc1(i.OutputSingleRegister(0), MemOperand(fp, offset));
}
} else {
__ lw(i.OutputRegister(0), MemOperand(fp, offset));
}
break;
}
case kMipsStackClaim: {
__ Subu(sp, sp, Operand(i.InputInt32(0)));
frame_access_state()->IncreaseSPDelta(i.InputInt32(0) / kPointerSize);
......@@ -3393,10 +3410,12 @@ void CodeGenerator::AssembleConstructFrame() {
const RegList saves = descriptor->CalleeSavedRegisters();
const RegList saves_fpu = descriptor->CalleeSavedFPRegisters();
const int returns = frame()->GetReturnSlotCount();
// Skip callee-saved slots, which are pushed below.
// Skip callee-saved and return slots, which are pushed below.
shrink_slots -= base::bits::CountPopulation(saves);
shrink_slots -= 2 * base::bits::CountPopulation(saves_fpu);
shrink_slots -= returns;
if (shrink_slots > 0) {
__ Subu(sp, sp, Operand(shrink_slots * kPointerSize));
}
......@@ -3411,12 +3430,22 @@ void CodeGenerator::AssembleConstructFrame() {
__ MultiPush(saves);
DCHECK_EQ(kNumCalleeSaved, base::bits::CountPopulation(saves) + 1);
}
if (returns != 0) {
// Create space for returns.
__ Subu(sp, sp, Operand(returns * kPointerSize));
}
}
void CodeGenerator::AssembleReturn(InstructionOperand* pop) {
CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
int pop_count = static_cast<int>(descriptor->StackParameterCount());
const int returns = frame()->GetReturnSlotCount();
if (returns != 0) {
__ Addu(sp, sp, Operand(returns * kPointerSize));
}
// Restore GP registers.
const RegList saves = descriptor->CalleeSavedRegisters();
if (saves != 0) {
......
......@@ -128,6 +128,7 @@ namespace compiler {
V(MipsFloat32Min) \
V(MipsFloat64Min) \
V(MipsPush) \
V(MipsPeek) \
V(MipsStoreToStackSlot) \
V(MipsByteSwap32) \
V(MipsStackClaim) \
......
......@@ -1203,7 +1203,28 @@ void InstructionSelector::EmitPrepareArguments(
void InstructionSelector::EmitPrepareResults(ZoneVector<PushParameter>* results,
const CallDescriptor* descriptor,
Node* node) {
// TODO(ahaas): Port.
MipsOperandGenerator g(this);
int reverse_slot = 0;
for (PushParameter output : *results) {
if (!output.location.IsCallerFrameSlot()) continue;
++reverse_slot;
// Skip any alignment holes in nodes.
if (output.node != nullptr) {
DCHECK(!descriptor->IsCFunctionCall());
if (output.location.GetType() == MachineType::Float32()) {
MarkAsFloat32(output.node);
} else if (output.location.GetType() == MachineType::Float64()) {
MarkAsFloat64(output.node);
}
InstructionOperand result = g.DefineAsRegister(output.node);
Emit(kMipsPeek | MiscField::encode(reverse_slot), result);
}
if (output.location.GetType() == MachineType::Float64()) {
// Float64 require an implicit second slot.
++reverse_slot;
}
}
}
bool InstructionSelector::IsTailCallAddressImmediate() { return false; }
......
......@@ -170,7 +170,7 @@
##############################################################################
# TODO(ahaas): Port multiple return values to ARM, MIPS, S390 and PPC
['arch == arm64 or arch == mips or arch == mips64 or arch == mipsel or arch == mips64el or arch == s390 or arch == s390x or arch == ppc or arch == ppc64', {
['arch == arm64 or arch == mips64 or arch == mips64el or arch == s390 or arch == s390x or arch == ppc or arch == ppc64', {
'test-multiple-return/*': [SKIP],
}],
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment