Diff
Modified: trunk/JSTests/ChangeLog (209851 => 209852)
--- trunk/JSTests/ChangeLog 2016-12-15 03:48:49 UTC (rev 209851)
+++ trunk/JSTests/ChangeLog 2016-12-15 04:36:08 UTC (rev 209852)
@@ -1,3 +1,22 @@
+2016-12-14 Keith Miller <[email protected]>
+
+ Wasm should decode constants correctly
+ https://bugs.webkit.org/show_bug.cgi?id=165886
+
+ Reviewed by Saam Barati.
+
+ * wasm/Builder.js:
+ (const._isValidValue):
+ * wasm/Builder_WebAssemblyBinary.js:
+ (const.putOp):
+ * wasm/LowLevelBinary.js:
+ (export.default.LowLevelBinary.prototype.float):
+ (export.default.LowLevelBinary.prototype.double):
+ * wasm/function-tests/f32-const.js: Added.
+ * wasm/function-tests/f64-const.js: Added.
+ * wasm/function-tests/i32-const.js: Added.
+ * wasm/wasm.json:
+
2016-12-14 Saam Barati <[email protected]>
WebAssembly: Add various low hanging fruit that will allow us to run the LLVM torture tests in Wasm
Modified: trunk/JSTests/wasm/Builder.js (209851 => 209852)
--- trunk/JSTests/wasm/Builder.js 2016-12-15 03:48:49 UTC (rev 209851)
+++ trunk/JSTests/wasm/Builder.js 2016-12-15 04:36:08 UTC (rev 209852)
@@ -35,7 +35,8 @@
const _isValidValue = (value, type) => {
switch (type) {
- case "i32": return ((value & 0xFFFFFFFF) >>> 0) === value;
+ // We allow both signed and unsigned numbers.
+ case "i32": return -(2 ** 31) <= value && value < 2 ** 32;
case "i64": throw new Error(`Unimplemented: value check for ${type}`); // FIXME https://bugs.webkit.org/show_bug.cgi?id=163420 64-bit values
case "f32": return typeof(value) === "number" && isFinite(value);
case "f64": return typeof(value) === "number" && isFinite(value);
Modified: trunk/JSTests/wasm/Builder_WebAssemblyBinary.js (209851 => 209852)
--- trunk/JSTests/wasm/Builder_WebAssemblyBinary.js 2016-12-15 03:48:49 UTC (rev 209851)
+++ trunk/JSTests/wasm/Builder_WebAssemblyBinary.js 2016-12-15 04:36:08 UTC (rev 209852)
@@ -72,6 +72,15 @@
put(bin, type, op.immediates[i]);
}
break;
+ case "i32.const": {
+ assert.eq(op.immediates.length, 1);
+ let imm = op.immediates[0];
+ // Do a static cast to make large int32s signed.
+ if (imm >= 2 ** 31)
+ imm = imm - (2 ** 32);
+ put(bin, "varint32", imm);
+ break;
+ }
case "br_table":
put(bin, "varuint32", op.immediates.length - 1);
for (let imm of op.immediates)
Modified: trunk/JSTests/wasm/LowLevelBinary.js (209851 => 209852)
--- trunk/JSTests/wasm/LowLevelBinary.js 2016-12-15 03:48:49 UTC (rev 209851)
+++ trunk/JSTests/wasm/LowLevelBinary.js 2016-12-15 04:36:08 UTC (rev 209852)
@@ -122,6 +122,30 @@
this._push8(v >>> 16);
this._push8(v >>> 24);
}
+ float(v) {
+ if (isNaN(v))
+ throw new RangeError("unimplemented, NaNs");
+ // Unfortunately, we cannot just view the actual buffer as a Float32Array since it needs to be 4 byte aligned
+ let buffer = new ArrayBuffer(4);
+ let floatView = new Float32Array(buffer);
+ let int8View = new Uint8Array(buffer);
+ floatView[0] = v;
+ for (let byte of int8View)
+ this._push8(byte);
+ }
+
+ double(v) {
+ if (isNaN(v))
+ throw new RangeError("unimplemented, NaNs");
+ // Unfortunately, we cannot just view the actual buffer as a Float64Array since it needs to be 4 byte aligned
+ let buffer = new ArrayBuffer(8);
+ let floatView = new Float64Array(buffer);
+ let int8View = new Uint8Array(buffer);
+ floatView[0] = v;
+ for (let byte of int8View)
+ this._push8(byte);
+ }
+
varuint32(v) {
assert.isNumber(v);
if (v < varuint32Min || varuint32Max < v)
Added: trunk/JSTests/wasm/function-tests/f32-const.js (0 => 209852)
--- trunk/JSTests/wasm/function-tests/f32-const.js (rev 0)
+++ trunk/JSTests/wasm/function-tests/f32-const.js 2016-12-15 04:36:08 UTC (rev 209852)
@@ -0,0 +1,26 @@
+import * as assert from '../assert.js';
+import Builder from '../Builder.js';
+
+const builder = (new Builder())
+ .Type().End()
+ .Function().End()
+ .Export()
+ .Function("answer")
+ .Function("minInt")
+ .End()
+ .Code()
+ .Function("answer", { params: [], ret: "f32" })
+ .F32Const(.5)
+ .End()
+
+ .Function("minInt", { params: [], ret: "f32" })
+ .F32Const(-1)
+ .End()
+
+ .End();
+
+const bin = builder.WebAssembly().get();
+const module = new WebAssembly.Module(bin);
+const instance = new WebAssembly.Instance(module);
+assert.eq(instance.exports.answer(), .5);
+assert.eq(instance.exports.minInt(), -1);
Added: trunk/JSTests/wasm/function-tests/f64-const.js (0 => 209852)
--- trunk/JSTests/wasm/function-tests/f64-const.js (rev 0)
+++ trunk/JSTests/wasm/function-tests/f64-const.js 2016-12-15 04:36:08 UTC (rev 209852)
@@ -0,0 +1,26 @@
+import * as assert from '../assert.js';
+import Builder from '../Builder.js';
+
+const builder = (new Builder())
+ .Type().End()
+ .Function().End()
+ .Export()
+ .Function("answer")
+ .Function("minInt")
+ .End()
+ .Code()
+ .Function("answer", { params: [], ret: "f64" })
+ .F64Const(42.424242)
+ .End()
+
+ .Function("minInt", { params: [], ret: "f64" })
+ .F64Const(-1)
+ .End()
+
+ .End();
+
+const bin = builder.WebAssembly().get();
+const module = new WebAssembly.Module(bin);
+const instance = new WebAssembly.Instance(module);
+assert.eq(instance.exports.answer(), 42.424242);
+assert.eq(instance.exports.minInt(), -1);
Added: trunk/JSTests/wasm/function-tests/i32-const.js (0 => 209852)
--- trunk/JSTests/wasm/function-tests/i32-const.js (rev 0)
+++ trunk/JSTests/wasm/function-tests/i32-const.js 2016-12-15 04:36:08 UTC (rev 209852)
@@ -0,0 +1,31 @@
+import * as assert from '../assert.js';
+import Builder from '../Builder.js';
+
+
+const builder = (new Builder())
+ .Type().End()
+ .Function().End()
+ .Export()
+ .Function("answer")
+ .Function("minInt")
+ .End()
+ .Code()
+ .Function("answer", { params: [], ret: "i32" })
+ .I32Const(42)
+ .End()
+
+ .Function("minInt", { params: [], ret: "i32" })
+ .I32Const(-1)
+ .End()
+
+ .Function("minInt", { params: [], ret: "i32" })
+ .I32Const(0xffffffff)
+ .End()
+ .End();
+
+const bin = builder.WebAssembly().get();
+const module = new WebAssembly.Module(bin);
+const instance = new WebAssembly.Instance(module);
+assert.eq(instance.exports.answer(), 42);
+assert.eq(instance.exports.minInt(), -1);
+assert.eq(instance.exports.minInt(), -1);
Modified: trunk/JSTests/wasm/wasm.json (209851 => 209852)
--- trunk/JSTests/wasm/wasm.json 2016-12-15 03:48:49 UTC (rev 209851)
+++ trunk/JSTests/wasm/wasm.json 2016-12-15 04:36:08 UTC (rev 209852)
@@ -56,8 +56,8 @@
"end": { "category": "control", "value": 11, "return": [], "parameter": [], "immediate": [], "description": "end a block, loop, or if" },
"i32.const": { "category": "special", "value": 65, "return": ["i32"], "parameter": [], "immediate": [{"name": "value", "type": "varint32"}], "description": "a constant value interpreted as i32" },
"i64.const": { "category": "special", "value": 66, "return": ["i64"], "parameter": [], "immediate": [{"name": "value", "type": "varint64"}], "description": "a constant value interpreted as i64" },
- "f64.const": { "category": "special", "value": 68, "return": ["f64"], "parameter": [], "immediate": [{"name": "value", "type": "uint64"}], "description": "a constant value interpreted as f64" },
- "f32.const": { "category": "special", "value": 67, "return": ["f32"], "parameter": [], "immediate": [{"name": "value", "type": "uint32"}], "description": "a constant value interpreted as f32" },
+ "f64.const": { "category": "special", "value": 68, "return": ["f64"], "parameter": [], "immediate": [{"name": "value", "type": "double"}], "description": "a constant value interpreted as f64" },
+ "f32.const": { "category": "special", "value": 67, "return": ["f32"], "parameter": [], "immediate": [{"name": "value", "type": "float"}], "description": "a constant value interpreted as f32" },
"get_local": { "category": "special", "value": 32, "return": ["any"], "parameter": [], "immediate": [{"name": "local_index", "type": "varuint32"}], "description": "read a local variable or parameter" },
"set_local": { "category": "special", "value": 33, "return": [], "parameter": ["any"], "immediate": [{"name": "local_index", "type": "varuint32"}], "description": "write a local variable or parameter" },
"tee_local": { "category": "special", "value": 34, "return": ["any"], "parameter": ["any"], "immediate": [{"name": "local_index", "type": "varuint32"}], "description": "write a local variable or parameter and return the same value" },
Modified: trunk/Source/_javascript_Core/ChangeLog (209851 => 209852)
--- trunk/Source/_javascript_Core/ChangeLog 2016-12-15 03:48:49 UTC (rev 209851)
+++ trunk/Source/_javascript_Core/ChangeLog 2016-12-15 04:36:08 UTC (rev 209852)
@@ -1,3 +1,17 @@
+2016-12-14 Keith Miller <[email protected]>
+
+ Wasm should decode constants correctly
+ https://bugs.webkit.org/show_bug.cgi?id=165886
+
+ Reviewed by Saam Barati.
+
+ This patch fixes how we decode the constant part of i32, i64, f32,
+ and f64.const opcodes.
+
+ * wasm/WasmFunctionParser.h:
+ (JSC::Wasm::FunctionParser<Context>::parseExpression):
+ * wasm/wasm.json:
+
2016-12-14 Saam Barati <[email protected]>
WebAssembly: Add various low hanging fruit that will allow us to run the LLVM torture tests in Wasm
Modified: trunk/Source/_javascript_Core/wasm/WasmFunctionParser.h (209851 => 209852)
--- trunk/Source/_javascript_Core/wasm/WasmFunctionParser.h 2016-12-15 03:48:49 UTC (rev 209851)
+++ trunk/Source/_javascript_Core/wasm/WasmFunctionParser.h 2016-12-15 04:36:08 UTC (rev 209852)
@@ -302,20 +302,34 @@
}
#undef CREATE_CASE
- case OpType::F32Const:
- case OpType::I32Const: {
+ case OpType::F32Const: {
uint32_t constant;
- if (!parseVarUInt32(constant))
+ if (!parseUInt32(constant))
return false;
+ m_expressionStack.append(m_context.addConstant(F32, constant));
+ return true;
+ }
+
+ case OpType::I32Const: {
+ int32_t constant;
+ if (!parseVarInt32(constant))
+ return false;
m_expressionStack.append(m_context.addConstant(I32, constant));
return true;
}
- case OpType::F64Const:
- case OpType::I64Const: {
+ case OpType::F64Const: {
uint64_t constant;
- if (!parseVarUInt64(constant))
+ if (!parseUInt64(constant))
return false;
+ m_expressionStack.append(m_context.addConstant(F64, constant));
+ return true;
+ }
+
+ case OpType::I64Const: {
+ int64_t constant;
+ if (!parseVarInt64(constant))
+ return false;
m_expressionStack.append(m_context.addConstant(I64, constant));
return true;
}
Modified: trunk/Source/_javascript_Core/wasm/wasm.json (209851 => 209852)
--- trunk/Source/_javascript_Core/wasm/wasm.json 2016-12-15 03:48:49 UTC (rev 209851)
+++ trunk/Source/_javascript_Core/wasm/wasm.json 2016-12-15 04:36:08 UTC (rev 209852)
@@ -56,13 +56,13 @@
"end": { "category": "control", "value": 11, "return": [], "parameter": [], "immediate": [], "description": "end a block, loop, or if" },
"i32.const": { "category": "special", "value": 65, "return": ["i32"], "parameter": [], "immediate": [{"name": "value", "type": "varint32"}], "description": "a constant value interpreted as i32" },
"i64.const": { "category": "special", "value": 66, "return": ["i64"], "parameter": [], "immediate": [{"name": "value", "type": "varint64"}], "description": "a constant value interpreted as i64" },
- "f64.const": { "category": "special", "value": 68, "return": ["f64"], "parameter": [], "immediate": [{"name": "value", "type": "uint64"}], "description": "a constant value interpreted as f64" },
- "f32.const": { "category": "special", "value": 67, "return": ["f32"], "parameter": [], "immediate": [{"name": "value", "type": "uint32"}], "description": "a constant value interpreted as f32" },
- "get_local": { "category": "special", "value": 32, "return": ["local"], "parameter": [], "immediate": [{"name": "local_index", "type": "varuint32"}], "description": "read a local variable or parameter" },
- "set_local": { "category": "special", "value": 33, "return": [], "parameter": ["local"], "immediate": [{"name": "local_index", "type": "varuint32"}], "description": "write a local variable or parameter" },
- "tee_local": { "category": "special", "value": 34, "return": ["prev"], "parameter": ["any"], "immediate": [{"name": "local_index", "type": "varuint32"}], "description": "write a local variable or parameter and return the same value" },
- "get_global": { "category": "special", "value": 35, "return": ["global"], "parameter": [], "immediate": [{"name": "global_index", "type": "varuint32"}], "description": "read a global variable" },
- "set_global": { "category": "special", "value": 36, "return": [""], "parameter": ["global"], "immediate": [{"name": "global_index", "type": "varuint32"}], "description": "write a global variable" },
+ "f64.const": { "category": "special", "value": 68, "return": ["f64"], "parameter": [], "immediate": [{"name": "value", "type": "double"}], "description": "a constant value interpreted as f64" },
+ "f32.const": { "category": "special", "value": 67, "return": ["f32"], "parameter": [], "immediate": [{"name": "value", "type": "float"}], "description": "a constant value interpreted as f32" },
+ "get_local": { "category": "special", "value": 32, "return": ["any"], "parameter": [], "immediate": [{"name": "local_index", "type": "varuint32"}], "description": "read a local variable or parameter" },
+ "set_local": { "category": "special", "value": 33, "return": [], "parameter": ["any"], "immediate": [{"name": "local_index", "type": "varuint32"}], "description": "write a local variable or parameter" },
+ "tee_local": { "category": "special", "value": 34, "return": ["any"], "parameter": ["any"], "immediate": [{"name": "local_index", "type": "varuint32"}], "description": "write a local variable or parameter and return the same value" },
+ "get_global": { "category": "special", "value": 35, "return": ["any"], "parameter": [], "immediate": [{"name": "global_index", "type": "varuint32"}], "description": "read a global variable" },
+ "set_global": { "category": "special", "value": 36, "return": [], "parameter": ["any"], "immediate": [{"name": "global_index", "type": "varuint32"}], "description": "write a global variable" },
"call": { "category": "call", "value": 16, "return": ["call"], "parameter": ["call"], "immediate": [{"name": "function_index", "type": "varuint32"}], "description": "call a function by its index" },
"call_indirect": { "category": "call", "value": 17, "return": ["call"], "parameter": ["call"], "immediate": [{"name": "type_index", "type": "varuint32"}, {"name": "reserved", "type": "varuint1"}], "description": "call a function indirect with an expected signature" },
"i32.load8_s": { "category": "memory", "value": 44, "return": ["i32"], "parameter": ["addr"], "immediate": [{"name": "flags", "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },