[turbofan] Fix passing float parameters on the stack

There was an issue with passing float32 parameters, if the value was
spilled on the stack and passed as stack parameter.
First, we sometimes reduced the stack pointer by 8 bytes instead of 4,
and second, there was a mismatch between movsd and movss.

R=titzer@chromium.org

Bug: chromium:718858
Change-Id: Ia884df369ddd95adeff3733f9715f589996f0b65
Also-By: ahaas@chromium.org
Reviewed-on: https://chromium-review.googlesource.com/684738
Reviewed-by: Andreas Haas <ahaas@chromium.org>
Reviewed-by: Ben Titzer <titzer@chromium.org>
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48181}
This commit is contained in:
Clemens Hammacher 2017-09-27 12:10:25 +02:00 committed by Commit Bot
parent fb35717fde
commit 8f0cd1c244
3 changed files with 78 additions and 6 deletions

View File

@ -1921,15 +1921,15 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ movss(Operand(esp, 0), i.InputDoubleRegister(0));
frame_access_state()->IncreaseSPDelta(kFloatSize / kPointerSize);
} else if (HasImmediateInput(instr, 0)) {
__ Move(kScratchDoubleReg, i.InputDouble(0));
__ sub(esp, Immediate(kDoubleSize));
__ Move(kScratchDoubleReg, i.InputFloat32(0));
__ sub(esp, Immediate(kFloatSize));
__ movss(Operand(esp, 0), kScratchDoubleReg);
frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
frame_access_state()->IncreaseSPDelta(kFloatSize / kPointerSize);
} else {
__ movsd(kScratchDoubleReg, i.InputOperand(0));
__ sub(esp, Immediate(kDoubleSize));
__ movss(kScratchDoubleReg, i.InputOperand(0));
__ sub(esp, Immediate(kFloatSize));
__ movss(Operand(esp, 0), kScratchDoubleReg);
frame_access_state()->IncreaseSPDelta(kDoubleSize / kPointerSize);
frame_access_state()->IncreaseSPDelta(kFloatSize / kPointerSize);
}
break;
case kIA32PushFloat64:

View File

@ -0,0 +1,55 @@
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
load('test/mjsunit/wasm/wasm-constants.js');
load('test/mjsunit/wasm/wasm-module-builder.js');
let types = [kWasmI32, kWasmF32, kWasmF64];
let type_names = ["i32", "f32", "f64"];
let type_const = [wasmI32Const, wasmF32Const, wasmF64Const];
function f(values, shift, num_const_params, ...args) {
assertEquals(
values.length + num_const_params, args.length, 'number of arguments');
args.forEach((arg_val, idx) => {
const expected =
idx < values.length ? values[(idx + shift) % values.length] : idx;
assertEquals(expected, arg_val, 'arg #' + idx + ', shifted by ' + shift);
});
}
types.forEach((type, type_idx) => {
for (let num_params = 3; num_params < 32; num_params += 4) {
print(
'Testing ' + num_params + ' parameters of type ' +
type_names[type_idx] + '...');
for (let num_const_params = 0; num_const_params <= 3; ++num_const_params) {
for (let shift = 2; shift <= 5; shift += 3) {
let builder = new WasmModuleBuilder();
let params_outer = new Array(num_params).fill(type);
sig_outer = makeSig(params_outer, []);
let params_inner = new Array(num_params + num_const_params).fill(type);
sig_inner = makeSig(params_inner, []);
let body = [];
for (let i = 0; i < num_params; ++i)
body.push(kExprGetLocal, (i + shift) % num_params);
for (let i = 0; i < num_const_params; ++i)
body.push(...type_const[type_idx](num_params + i));
body.push(kExprCallFunction, 0);
builder.addImport('', 'f', sig_inner);
builder.addFunction(undefined, sig_outer)
.addBody(body)
.exportAs('main');
let values = new Array(num_params).fill(0).map((_, i) => 123 - 3 * i);
instance = builder.instantiate(
{'': {'f': f.bind(null, values, shift, num_const_params)}});
instance.exports.main(...values);
}
}
}
});

View File

@ -414,3 +414,20 @@ function assertWasmThrows(runtime_id, values, code) {
}
throw new MjsUnitAssertionError('Did not throw expected: ' + runtime_id + values);
}
function wasmI32Const(val) {
let bytes = [kExprI32Const];
for (let i = 0; i < 4; ++i) {
bytes.push(0x80 | ((val >> (7 * i)) & 0x7f));
}
bytes.push((val >> (7 * 4)) & 0x7f);
return bytes;
}
function wasmF32Const(f) {
return [kExprF32Const].concat(Array.from(new Uint8Array((new Float32Array([f])).buffer)));
}
function wasmF64Const(f) {
return [kExprF64Const].concat(Array.from(new Uint8Array((new Float64Array([f])).buffer)));
}