Commit 965e6bdc authored by ahaas's avatar ahaas Committed by Commit bot

[wasm] Wasm functions with int64 parameters can now be called from JS.

All wasm spec tests can now be run on ia32.

R=titzer@chromium.org

Review URL: https://codereview.chromium.org/1899753004

Cr-Commit-Position: refs/heads/master@{#35663}
parent 5459468d
......@@ -79,8 +79,10 @@ static int GetParameterIndexAfterLowering(
return result;
}
static int GetParameterCountAfterLowering(
int Int64Lowering::GetParameterCountAfterLowering(
Signature<MachineRepresentation>* signature) {
// GetParameterIndexAfterLowering(parameter_count) returns the parameter count
// after lowering.
return GetParameterIndexAfterLowering(
signature, static_cast<int>(signature->parameter_count()));
}
......@@ -177,7 +179,9 @@ void Int64Lowering::LowerNode(Node* node) {
NodeProperties::ChangeOp(node, store_op);
ReplaceNode(node, node, high_node);
} else {
DefaultLowering(node);
if (HasReplacementLow(node->InputAt(2))) {
node->ReplaceInput(2, GetReplacementLow(node->InputAt(2)));
}
}
break;
}
......
......@@ -23,6 +23,9 @@ class Int64Lowering {
void LowerGraph();
static int GetParameterCountAfterLowering(
Signature<MachineRepresentation>* signature);
private:
enum class State : uint8_t { kUnvisited, kOnStack, kVisited };
......
......@@ -2203,8 +2203,12 @@ Node* WasmGraphBuilder::ToJS(Node* node, Node* context, wasm::LocalType type) {
case wasm::kAstI64:
// TODO(titzer): i64->JS has no good solution right now. Using lower 32
// bits.
node =
graph()->NewNode(jsgraph()->machine()->TruncateInt64ToInt32(), node);
if (jsgraph()->machine()->Is64()) {
// On 32 bit platforms we do not have to do the truncation because the
// node we get in as a parameter only contains the low word anyways.
node = graph()->NewNode(jsgraph()->machine()->TruncateInt64ToInt32(),
node);
}
return BuildChangeInt32ToTagged(node);
case wasm::kAstF32:
node = graph()->NewNode(jsgraph()->machine()->ChangeFloat32ToFloat64(),
......@@ -2369,7 +2373,11 @@ Node* WasmGraphBuilder::FromJS(Node* node, Node* context,
num = graph()->NewNode(jsgraph()->machine()->TruncateFloat64ToInt32(
TruncationMode::kJavaScript),
num);
num = graph()->NewNode(jsgraph()->machine()->ChangeInt32ToInt64(), num);
if (jsgraph()->machine()->Is64()) {
// We cannot change an int32 to an int64 on a 32 bit platform. Instead
// we will split the parameter node later.
num = graph()->NewNode(jsgraph()->machine()->ChangeInt32ToInt64(), num);
}
break;
case wasm::kAstF32:
num = graph()->NewNode(jsgraph()->machine()->TruncateFloat64ToFloat32(),
......@@ -2459,28 +2467,40 @@ Node* WasmGraphBuilder::BuildHeapNumberValueIndexConstant() {
void WasmGraphBuilder::BuildJSToWasmWrapper(Handle<Code> wasm_code,
wasm::FunctionSig* sig) {
int params = static_cast<int>(sig->parameter_count());
int count = params + 3;
int wasm_count = static_cast<int>(sig->parameter_count());
int param_count;
if (jsgraph()->machine()->Is64()) {
param_count = static_cast<int>(sig->parameter_count());
} else {
param_count = Int64Lowering::GetParameterCountAfterLowering(sig);
}
int count = param_count + 3;
Node** args = Buffer(count);
// Build the start and the JS parameter nodes.
Node* start = Start(params + 5);
Node* start = Start(param_count + 5);
*control_ = start;
*effect_ = start;
// Create the context parameter
Node* context = graph()->NewNode(
jsgraph()->common()->Parameter(
Linkage::GetJSCallContextParamIndex(params + 1), "%context"),
Linkage::GetJSCallContextParamIndex(wasm_count + 1), "%context"),
graph()->start());
int pos = 0;
args[pos++] = Constant(wasm_code);
// Convert JS parameters to WASM numbers.
for (int i = 0; i < params; i++) {
for (int i = 0; i < wasm_count; i++) {
Node* param =
graph()->NewNode(jsgraph()->common()->Parameter(i + 1), start);
args[pos++] = FromJS(param, context, sig->GetParam(i));
Node* wasm_param = FromJS(param, context, sig->GetParam(i));
args[pos++] = wasm_param;
if (jsgraph()->machine()->Is32() && sig->GetParam(i) == wasm::kAstI64) {
// We make up the high word with SAR to get the proper sign extension.
args[pos++] = graph()->NewNode(jsgraph()->machine()->Word32Sar(),
wasm_param, jsgraph()->Int32Constant(31));
}
}
args[pos++] = *effect_;
......@@ -2489,9 +2509,18 @@ void WasmGraphBuilder::BuildJSToWasmWrapper(Handle<Code> wasm_code,
// Call the WASM code.
CallDescriptor* desc =
wasm::ModuleEnv::GetWasmCallDescriptor(jsgraph()->zone(), sig);
if (jsgraph()->machine()->Is32()) {
desc = wasm::ModuleEnv::GetI32WasmCallDescriptor(jsgraph()->zone(), desc);
}
Node* call = graph()->NewNode(jsgraph()->common()->Call(desc), count, args);
Node* retval = call;
if (jsgraph()->machine()->Is32() && sig->return_count() > 0 &&
sig->GetReturn(0) == wasm::kAstI64) {
// The return values comes as two values, we pick the low word.
retval = graph()->NewNode(jsgraph()->common()->Projection(0), retval);
}
Node* jsval =
ToJS(call, context,
ToJS(retval, context,
sig->return_count() == 0 ? wasm::kAstStmt : sig->GetReturn());
Node* ret =
graph()->NewNode(jsgraph()->common()->Return(), jsval, call, start);
......@@ -2504,11 +2533,17 @@ void WasmGraphBuilder::BuildWasmToJSWrapper(Handle<JSFunction> function,
wasm::FunctionSig* sig) {
int js_count = function->shared()->internal_formal_parameter_count();
int wasm_count = static_cast<int>(sig->parameter_count());
int param_count;
if (jsgraph()->machine()->Is64()) {
param_count = wasm_count;
} else {
param_count = Int64Lowering::GetParameterCountAfterLowering(sig);
}
// Build the start and the parameter nodes.
Isolate* isolate = jsgraph()->isolate();
CallDescriptor* desc;
Node* start = Start(wasm_count + 3);
Node* start = Start(param_count + 3);
*effect_ = start;
*control_ = start;
// JS context is the last parameter.
......@@ -2544,9 +2579,15 @@ void WasmGraphBuilder::BuildWasmToJSWrapper(Handle<JSFunction> function,
args[pos++] = jsgraph()->Constant(global);
// Convert WASM numbers to JS values.
int param_index = 0;
for (int i = 0; i < wasm_count; i++) {
Node* param = graph()->NewNode(jsgraph()->common()->Parameter(i), start);
Node* param =
graph()->NewNode(jsgraph()->common()->Parameter(param_index++), start);
args[pos++] = ToJS(param, context, sig->GetParam(i));
if (jsgraph()->machine()->Is32() && sig->GetParam(i) == wasm::kAstI64) {
// On 32 bit platforms we have to skip the high word of int64 parameters.
param_index++;
}
}
if (add_new_target_undefined) {
......@@ -2563,10 +2604,19 @@ void WasmGraphBuilder::BuildWasmToJSWrapper(Handle<JSFunction> function,
Node* call = graph()->NewNode(jsgraph()->common()->Call(desc), pos, args);
// Convert the return value back.
Node* ret;
Node* val =
FromJS(call, context,
sig->return_count() == 0 ? wasm::kAstStmt : sig->GetReturn());
Node* ret = graph()->NewNode(jsgraph()->common()->Return(), val, call, start);
if (jsgraph()->machine()->Is32() && sig->return_count() > 0 &&
sig->GetReturn() == wasm::kAstI64) {
ret = graph()->NewNode(jsgraph()->common()->Return(), val,
graph()->NewNode(jsgraph()->machine()->Word32Sar(),
val, jsgraph()->Int32Constant(31)),
call, start);
} else {
ret = graph()->NewNode(jsgraph()->common()->Return(), val, call, start);
}
MergeControlToEnd(jsgraph(), ret);
}
......@@ -2890,6 +2940,9 @@ Handle<Code> CompileWasmToJSWrapper(Isolate* isolate, wasm::ModuleEnv* module,
// Schedule and compile to machine code.
CallDescriptor* incoming =
wasm::ModuleEnv::GetWasmCallDescriptor(&zone, sig);
if (machine.Is32()) {
incoming = wasm::ModuleEnv::GetI32WasmCallDescriptor(&zone, incoming);
}
Code::Flags flags = Code::ComputeFlags(Code::WASM_TO_JS_FUNCTION);
bool debugging =
#if DEBUG
......@@ -2960,6 +3013,11 @@ Handle<Code> CompileWasmFunction(wasm::ErrorThrower& thrower, Isolate* isolate,
wasm::TreeResult result =
wasm::BuildTFGraph(isolate->allocator(), &builder, body);
if (machine.Is32()) {
Int64Lowering r(&graph, &machine, &common, &zone, function.sig);
r.LowerGraph();
}
if (result.failed()) {
if (FLAG_trace_wasm_compiler) {
OFStream os(stdout);
......
......@@ -41,6 +41,28 @@ function assertFunction(module, func) {
return exp;
}
(function I64SubTest() {
var builder = new WasmModuleBuilder();
builder.addMemory(1, 1, true);
builder.addFunction("sub", [kAstI64, kAstI64, kAstI64])
.addBody([
kExprI64Sub, // --
kExprGetLocal, 0, // --
kExprGetLocal, 1]) // --
.exportFunc()
var module = builder.instantiate();
assertModule(module, kPageSize);
// Check the properties of the sub function.
var sub = assertFunction(module, "sub");
assertEquals(-55, sub(33, 88));
assertEquals(-55555, sub(33333, 88888));
assertEquals(-5555555, sub(3333333, 8888888));
})();
(function SubTest() {
var builder = new WasmModuleBuilder();
......
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