Commit d83057b4 authored by ahaas's avatar ahaas Committed by Commit bot

[wasm] Change the return type of traps for tests, and added ftoi64 instructions.

Before this change traps always returned a 32 bit word in tests. With this
change traps return either a 32 bit word or a64 bit word, depending on the size
of the actual return value of the test.

Additionally this CL implements the wasm instructions I64SCONVERTF32,
I64UCONVERTF32, I64SCONVERTF64, and I64UCONVERTF64.

R=titzer@chromium.org

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

Cr-Commit-Position: refs/heads/master@{#32800}
parent a8354693
......@@ -223,10 +223,31 @@ class WasmTrapHelper : public ZoneObject {
end = thrw;
} else {
// End the control flow with returning 0xdeadbeef
Node* ret_dead = graph()->NewNode(common()->Return(),
jsgraph()->Int32Constant(0xdeadbeef),
*effect_ptr, *control_ptr);
end = ret_dead;
Node* ret_value;
if (builder_->GetFunctionSignature()->return_count() > 0) {
switch (builder_->GetFunctionSignature()->GetReturn()) {
case wasm::kAstI32:
ret_value = jsgraph()->Int32Constant(0xdeadbeef);
break;
case wasm::kAstI64:
ret_value = jsgraph()->Int64Constant(0xdeadbeefdeadbeef);
break;
case wasm::kAstF32:
ret_value = jsgraph()->Float32Constant(bit_cast<float>(0xdeadbeef));
break;
case wasm::kAstF64:
ret_value = jsgraph()->Float64Constant(
bit_cast<double>(0xdeadbeefdeadbeef));
break;
default:
UNREACHABLE();
ret_value = nullptr;
}
} else {
ret_value = jsgraph()->Int32Constant(0xdeadbeef);
}
end = graph()->NewNode(jsgraph()->common()->Return(), ret_value,
*effect_ptr, *control_ptr);
}
MergeControlToEnd(jsgraph(), end);
......@@ -234,7 +255,8 @@ class WasmTrapHelper : public ZoneObject {
};
WasmGraphBuilder::WasmGraphBuilder(Zone* zone, JSGraph* jsgraph)
WasmGraphBuilder::WasmGraphBuilder(Zone* zone, JSGraph* jsgraph,
wasm::FunctionSig* function_signature)
: zone_(zone),
jsgraph_(jsgraph),
module_(nullptr),
......@@ -245,7 +267,8 @@ WasmGraphBuilder::WasmGraphBuilder(Zone* zone, JSGraph* jsgraph)
effect_(nullptr),
cur_buffer_(def_buffer_),
cur_bufsize_(kDefaultBufferSize),
trap_(new (zone) WasmTrapHelper(this)) {
trap_(new (zone) WasmTrapHelper(this)),
function_signature_(function_signature) {
DCHECK_NOT_NULL(jsgraph_);
}
......@@ -843,6 +866,42 @@ Node* WasmGraphBuilder::Unop(wasm::WasmOpcode opcode, Node* input) {
case wasm::kExprF64UConvertI64:
op = m->RoundUint64ToFloat64();
break;
case wasm::kExprI64SConvertF32: {
Node* trunc = graph()->NewNode(m->TryTruncateFloat32ToInt64(), input);
Node* result =
graph()->NewNode(jsgraph()->common()->Projection(0), trunc);
Node* overflow =
graph()->NewNode(jsgraph()->common()->Projection(1), trunc);
trap_->ZeroCheck64(kTrapFloatUnrepresentable, overflow);
return result;
}
case wasm::kExprI64SConvertF64: {
Node* trunc = graph()->NewNode(m->TryTruncateFloat64ToInt64(), input);
Node* result =
graph()->NewNode(jsgraph()->common()->Projection(0), trunc);
Node* overflow =
graph()->NewNode(jsgraph()->common()->Projection(1), trunc);
trap_->ZeroCheck64(kTrapFloatUnrepresentable, overflow);
return result;
}
case wasm::kExprI64UConvertF32: {
Node* trunc = graph()->NewNode(m->TryTruncateFloat32ToUint64(), input);
Node* result =
graph()->NewNode(jsgraph()->common()->Projection(0), trunc);
Node* overflow =
graph()->NewNode(jsgraph()->common()->Projection(1), trunc);
trap_->ZeroCheck64(kTrapFloatUnrepresentable, overflow);
return result;
}
case wasm::kExprI64UConvertF64: {
Node* trunc = graph()->NewNode(m->TryTruncateFloat64ToUint64(), input);
Node* result =
graph()->NewNode(jsgraph()->common()->Projection(0), trunc);
Node* overflow =
graph()->NewNode(jsgraph()->common()->Projection(1), trunc);
trap_->ZeroCheck64(kTrapFloatUnrepresentable, overflow);
return result;
}
case wasm::kExprF64ReinterpretI64:
op = m->BitcastInt64ToFloat64();
break;
......@@ -1616,7 +1675,7 @@ Handle<JSFunction> CompileJSToWasmWrapper(Isolate* isolate,
Node* control = nullptr;
Node* effect = nullptr;
WasmGraphBuilder builder(&zone, &jsgraph);
WasmGraphBuilder builder(&zone, &jsgraph, func->sig);
builder.set_control_ptr(&control);
builder.set_effect_ptr(&effect);
builder.set_module(module);
......@@ -1698,7 +1757,7 @@ Handle<Code> CompileWasmToJSWrapper(Isolate* isolate, wasm::ModuleEnv* module,
Node* control = nullptr;
Node* effect = nullptr;
WasmGraphBuilder builder(&zone, &jsgraph);
WasmGraphBuilder builder(&zone, &jsgraph, func->sig);
builder.set_control_ptr(&control);
builder.set_effect_ptr(&effect);
builder.set_module(module);
......@@ -1786,7 +1845,7 @@ Handle<Code> CompileWasmFunction(wasm::ErrorThrower& thrower, Isolate* isolate,
&zone, MachineType::PointerRepresentation(),
InstructionSelector::SupportedMachineOperatorFlags());
JSGraph jsgraph(isolate, &graph, &common, nullptr, nullptr, &machine);
WasmGraphBuilder builder(&zone, &jsgraph);
WasmGraphBuilder builder(&zone, &jsgraph, function.sig);
wasm::TreeResult result = wasm::BuildTFGraph(
&builder, &env, // --
module_env->module->module_start, // --
......
......@@ -55,7 +55,7 @@ Handle<JSFunction> CompileJSToWasmWrapper(Isolate* isolate,
class WasmTrapHelper;
class WasmGraphBuilder {
public:
WasmGraphBuilder(Zone* z, JSGraph* g);
WasmGraphBuilder(Zone* z, JSGraph* g, wasm::FunctionSig* function_signature);
Node** Buffer(size_t count) {
if (count > cur_bufsize_) {
......@@ -132,6 +132,8 @@ class WasmGraphBuilder {
void set_effect_ptr(Node** effect) { this->effect_ = effect; }
wasm::FunctionSig* GetFunctionSignature() { return function_signature_; }
private:
static const int kDefaultBufferSize = 16;
friend class WasmTrapHelper;
......@@ -149,6 +151,7 @@ class WasmGraphBuilder {
Node* def_buffer_[kDefaultBufferSize];
WasmTrapHelper* trap_;
wasm::FunctionSig* function_signature_;
// Internal helper methods.
JSGraph* jsgraph() { return jsgraph_; }
......
......@@ -32,7 +32,12 @@
// Currently, in tests, we just return 0xdeadbeef from the function in which
// the trap occurs if the runtime context is not available to throw a JavaScript
// exception.
#define CHECK_TRAP(x) CHECK_EQ(0xdeadbeef, (x)&0xFFFFFFFF)
#define CHECK_TRAP32(x) \
CHECK_EQ(0xdeadbeef, (bit_cast<uint32_t>(x)) & 0xFFFFFFFF)
#define CHECK_TRAP64(x) \
CHECK_EQ(0xdeadbeefdeadbeef, (bit_cast<uint64_t>(x)) & 0xFFFFFFFFFFFFFFFF)
#define CHECK_TRAP(x) CHECK_TRAP32(x)
using namespace v8::base;
using namespace v8::internal;
......@@ -214,7 +219,7 @@ class WasmFunctionCompiler : public HandleAndZoneScope,
CallDescriptor* descriptor() { return descriptor_; }
void Build(const byte* start, const byte* end) {
compiler::WasmGraphBuilder builder(main_zone(), &jsgraph);
compiler::WasmGraphBuilder builder(main_zone(), &jsgraph, env.sig);
TreeResult result = BuildTFGraph(&builder, &env, start, end);
if (result.failed()) {
ptrdiff_t pc = result.error_pc - result.start;
......@@ -973,10 +978,10 @@ TEST(Run_WASM_Int64DivS_trap) {
WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
BUILD(r, WASM_I64_DIVS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
CHECK_EQ(0, r.Call(as64(0), as64(100)));
CHECK_TRAP(r.Call(as64(100), as64(0)));
CHECK_TRAP(r.Call(as64(-1001), as64(0)));
CHECK_TRAP(r.Call(std::numeric_limits<int64_t>::min(), as64(-1)));
CHECK_TRAP(r.Call(std::numeric_limits<int64_t>::min(), as64(0)));
CHECK_TRAP64(r.Call(as64(100), as64(0)));
CHECK_TRAP64(r.Call(as64(-1001), as64(0)));
CHECK_TRAP64(r.Call(std::numeric_limits<int64_t>::min(), as64(-1)));
CHECK_TRAP64(r.Call(std::numeric_limits<int64_t>::min(), as64(0)));
}
......@@ -985,9 +990,9 @@ TEST(Run_WASM_Int64RemS_trap) {
BUILD(r, WASM_I64_REMS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
CHECK_EQ(33, r.Call(as64(133), as64(100)));
CHECK_EQ(0, r.Call(std::numeric_limits<int64_t>::min(), as64(-1)));
CHECK_TRAP(r.Call(as64(100), as64(0)));
CHECK_TRAP(r.Call(as64(-1001), as64(0)));
CHECK_TRAP(r.Call(std::numeric_limits<int64_t>::min(), as64(0)));
CHECK_TRAP64(r.Call(as64(100), as64(0)));
CHECK_TRAP64(r.Call(as64(-1001), as64(0)));
CHECK_TRAP64(r.Call(std::numeric_limits<int64_t>::min(), as64(0)));
}
......@@ -996,9 +1001,9 @@ TEST(Run_WASM_Int64DivU_trap) {
BUILD(r, WASM_I64_DIVU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
CHECK_EQ(0, r.Call(as64(0), as64(100)));
CHECK_EQ(0, r.Call(std::numeric_limits<int64_t>::min(), as64(-1)));
CHECK_TRAP(r.Call(as64(100), as64(0)));
CHECK_TRAP(r.Call(as64(-1001), as64(0)));
CHECK_TRAP(r.Call(std::numeric_limits<int64_t>::min(), as64(0)));
CHECK_TRAP64(r.Call(as64(100), as64(0)));
CHECK_TRAP64(r.Call(as64(-1001), as64(0)));
CHECK_TRAP64(r.Call(std::numeric_limits<int64_t>::min(), as64(0)));
}
......@@ -1006,9 +1011,9 @@ TEST(Run_WASM_Int64RemU_trap) {
WasmRunner<int64_t> r(MachineType::Int64(), MachineType::Int64());
BUILD(r, WASM_I64_REMU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)));
CHECK_EQ(17, r.Call(as64(217), as64(100)));
CHECK_TRAP(r.Call(as64(100), as64(0)));
CHECK_TRAP(r.Call(as64(-1001), as64(0)));
CHECK_TRAP(r.Call(std::numeric_limits<int64_t>::min(), as64(0)));
CHECK_TRAP64(r.Call(as64(100), as64(0)));
CHECK_TRAP64(r.Call(as64(-1001), as64(0)));
CHECK_TRAP64(r.Call(std::numeric_limits<int64_t>::min(), as64(0)));
CHECK_EQ(std::numeric_limits<int64_t>::min(),
r.Call(std::numeric_limits<int64_t>::min(), as64(-1)));
}
......@@ -1020,7 +1025,7 @@ TEST(Run_WASM_Int64DivS_byzero_const) {
BUILD(r, WASM_I64_DIVS(WASM_GET_LOCAL(0), WASM_I64(denom)));
for (int64_t val = -7; val < 8; val++) {
if (denom == 0) {
CHECK_TRAP(r.Call(val));
CHECK_TRAP64(r.Call(val));
} else {
CHECK_EQ(val / denom, r.Call(val));
}
......@@ -1036,7 +1041,7 @@ TEST(Run_WASM_Int64DivU_byzero_const) {
for (uint64_t val = 0xfffffffffffffff0; val < 8; val++) {
if (denom == 0) {
CHECK_TRAP(r.Call(val));
CHECK_TRAP64(r.Call(val));
} else {
CHECK_EQ(val / denom, r.Call(val));
}
......@@ -3243,6 +3248,60 @@ TEST(Run_Wasm_F64UConvertI64) {
}
TEST(Run_Wasm_I64SConvertF32) {
WasmRunner<int64_t> r(MachineType::Float32());
BUILD(r, WASM_I64_SCONVERT_F32(WASM_GET_LOCAL(0)));
FOR_FLOAT32_INPUTS(i) {
if (*i < 9223372036854775808.0 && *i > -9223372036854775809.0) {
CHECK_EQ(static_cast<int64_t>(*i), r.Call(*i));
} else {
CHECK_TRAP64(r.Call(*i));
}
}
}
TEST(Run_Wasm_I64SConvertF64) {
WasmRunner<int64_t> r(MachineType::Float64());
BUILD(r, WASM_I64_SCONVERT_F64(WASM_GET_LOCAL(0)));
FOR_FLOAT64_INPUTS(i) {
if (*i < 9223372036854775808.0 && *i > -9223372036854775809.0) {
CHECK_EQ(static_cast<int64_t>(*i), r.Call(*i));
} else {
CHECK_TRAP64(r.Call(*i));
}
}
}
TEST(Run_Wasm_I64UConvertF32) {
WasmRunner<uint64_t> r(MachineType::Float32());
BUILD(r, WASM_I64_UCONVERT_F32(WASM_GET_LOCAL(0)));
FOR_FLOAT32_INPUTS(i) {
if (*i < 18446744073709551616.0 && *i >= 0) {
CHECK_EQ(static_cast<uint64_t>(*i), r.Call(*i));
} else {
CHECK_TRAP64(r.Call(*i));
}
}
}
TEST(Run_Wasm_I64UConvertF64) {
WasmRunner<uint64_t> r(MachineType::Float64());
BUILD(r, WASM_I64_UCONVERT_F64(WASM_GET_LOCAL(0)));
FOR_FLOAT64_INPUTS(i) {
if (*i < 18446744073709551616.0 && *i >= 0) {
CHECK_EQ(static_cast<uint64_t>(*i), r.Call(*i));
} else {
CHECK_TRAP64(r.Call(*i));
}
}
}
#endif
......
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