From 1b0e6b542d9a9fcf0049a2f90bf364a83e6e925e Mon Sep 17 00:00:00 2001 From: Abel Stuker Date: Thu, 20 Nov 2025 00:34:38 +0100 Subject: [PATCH 1/3] Fix unreachable reinterpret instruction execution --- src/Interpreter/interpreter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Interpreter/interpreter.cpp b/src/Interpreter/interpreter.cpp index 9f22c6ac..88dfa6a1 100644 --- a/src/Interpreter/interpreter.cpp +++ b/src/Interpreter/interpreter.cpp @@ -432,7 +432,7 @@ bool Interpreter::interpret(Module *m, bool waiting) { continue; // conversion operations - case 0xa7 ... 0xbb: + case 0xa7 ... 0xbf: success &= i_instr_conversion(m, opcode); continue; From 5a970072f246c41d55364acca7b1e54547427cb2 Mon Sep 17 00:00:00 2001 From: Abel Stuker Date: Fri, 21 Nov 2025 20:17:51 +0100 Subject: [PATCH 2/3] Fix support for scientific notation in latch spec tests --- tests/latch/src/util/spec.util.ts | 47 +++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/tests/latch/src/util/spec.util.ts b/tests/latch/src/util/spec.util.ts index 07f034a1..2ad91be2 100644 --- a/tests/latch/src/util/spec.util.ts +++ b/tests/latch/src/util/spec.util.ts @@ -21,9 +21,10 @@ export function parseResult(input: string): WASM.Value | undefined { let value; delta = consume(input, cursor, /^[^)]*/d); if (type === WASM.Type.f32 || type === WASM.Type.f64) { - value = parseHexFloat(input.slice(cursor, cursor + delta)); + value = parseFloat(input.slice(cursor, cursor + delta)); } else { - value = parseInteger(input.slice(cursor, cursor + delta)); + const bytes = type === WASM.Type.i64 ? 8 : 4; + value = parseInteger(input.slice(cursor, cursor + delta), bytes); } if (value === undefined) { @@ -51,9 +52,10 @@ export function parseArguments(input: string, index: Cursor): WASM.Value[] { delta = consume(input, cursor, /^[^)]*/d); let maybe: number | undefined; if (type === WASM.Type.f32 || type === WASM.Type.f64) { - maybe = parseHexFloat(input.slice(cursor, cursor + delta)); + maybe = parseFloat(input.slice(cursor, cursor + delta)); } else { - maybe = parseInteger(input.slice(cursor, cursor + delta)); + const bytes = type === WASM.Type.i64 ? 8 : 4; + maybe = parseInteger(input.slice(cursor, cursor + delta), bytes); } if (maybe !== undefined) { @@ -97,7 +99,7 @@ function sign(integer: number): number { return Math.sign(integer) || 1; } -function parseHexFloat(input: string): number { +function parseFloat(input: string): number { if (input.includes('-inf')) { return -Infinity; } @@ -106,8 +108,17 @@ function parseHexFloat(input: string): number { return Infinity; } - const radix: number = input.includes('0x') ? 16 : 10; - let base: string = input, mantissa, exponent = 0; + if (input.includes('0x')) { + return parseHexFloat(input); + } + + return Number(input); +} + +function parseHexFloat(input: string): number { + const radix = 16; + let base: string = input; + let exponent = 0; const splitIndex = input.indexOf('p'); if (splitIndex !== -1) { @@ -116,6 +127,8 @@ function parseHexFloat(input: string): number { } const dotIndex = base.indexOf('.'); + let mantissa: number; + if (dotIndex !== -1) { const [integer, fractional] = base.split('.').map(hexStr => parseInt(hexStr, radix)); const fraction = fractional / Math.pow(radix, base.length - dotIndex - 1); @@ -131,12 +144,22 @@ function parseInteger(hex: string, bytes: number = 4): number { if (!hex.includes('0x')) { return parseInt(hex); } - const mask = parseInt('0x80' + '00'.repeat(bytes - 1), 16); - let integer = parseInt(hex, 16); - if (integer >= mask) { - integer = integer - mask * 2; + + const bigIntValue = BigInt(hex); + const bitSize = bytes * 8; + const signBit = BigInt(1) << BigInt(bitSize - 1); + const mask = (BigInt(1) << BigInt(bitSize)) - BigInt(1); + + // mask to the correct bit width + const masked = bigIntValue & mask; + // check if negative (sign bit is set) + if (masked >= signBit) { + // convert from two's complement + const result = masked - (BigInt(1) << BigInt(bitSize)); + return Number(result); } - return integer; + + return Number(masked); } export function find(regex: RegExp, input: string) { From b1b6790ce577dfefb071313571e493485838f92f Mon Sep 17 00:00:00 2001 From: Abel Stuker Date: Sat, 22 Nov 2025 10:50:49 +0100 Subject: [PATCH 3/3] Revert "Fix support for scientific notation in latch spec tests" This reverts commit 820678c7a1255e238c898717c8513669923b2461. --- tests/latch/src/util/spec.util.ts | 47 ++++++++----------------------- 1 file changed, 12 insertions(+), 35 deletions(-) diff --git a/tests/latch/src/util/spec.util.ts b/tests/latch/src/util/spec.util.ts index 2ad91be2..07f034a1 100644 --- a/tests/latch/src/util/spec.util.ts +++ b/tests/latch/src/util/spec.util.ts @@ -21,10 +21,9 @@ export function parseResult(input: string): WASM.Value | undefined { let value; delta = consume(input, cursor, /^[^)]*/d); if (type === WASM.Type.f32 || type === WASM.Type.f64) { - value = parseFloat(input.slice(cursor, cursor + delta)); + value = parseHexFloat(input.slice(cursor, cursor + delta)); } else { - const bytes = type === WASM.Type.i64 ? 8 : 4; - value = parseInteger(input.slice(cursor, cursor + delta), bytes); + value = parseInteger(input.slice(cursor, cursor + delta)); } if (value === undefined) { @@ -52,10 +51,9 @@ export function parseArguments(input: string, index: Cursor): WASM.Value[] { delta = consume(input, cursor, /^[^)]*/d); let maybe: number | undefined; if (type === WASM.Type.f32 || type === WASM.Type.f64) { - maybe = parseFloat(input.slice(cursor, cursor + delta)); + maybe = parseHexFloat(input.slice(cursor, cursor + delta)); } else { - const bytes = type === WASM.Type.i64 ? 8 : 4; - maybe = parseInteger(input.slice(cursor, cursor + delta), bytes); + maybe = parseInteger(input.slice(cursor, cursor + delta)); } if (maybe !== undefined) { @@ -99,7 +97,7 @@ function sign(integer: number): number { return Math.sign(integer) || 1; } -function parseFloat(input: string): number { +function parseHexFloat(input: string): number { if (input.includes('-inf')) { return -Infinity; } @@ -108,17 +106,8 @@ function parseFloat(input: string): number { return Infinity; } - if (input.includes('0x')) { - return parseHexFloat(input); - } - - return Number(input); -} - -function parseHexFloat(input: string): number { - const radix = 16; - let base: string = input; - let exponent = 0; + const radix: number = input.includes('0x') ? 16 : 10; + let base: string = input, mantissa, exponent = 0; const splitIndex = input.indexOf('p'); if (splitIndex !== -1) { @@ -127,8 +116,6 @@ function parseHexFloat(input: string): number { } const dotIndex = base.indexOf('.'); - let mantissa: number; - if (dotIndex !== -1) { const [integer, fractional] = base.split('.').map(hexStr => parseInt(hexStr, radix)); const fraction = fractional / Math.pow(radix, base.length - dotIndex - 1); @@ -144,22 +131,12 @@ function parseInteger(hex: string, bytes: number = 4): number { if (!hex.includes('0x')) { return parseInt(hex); } - - const bigIntValue = BigInt(hex); - const bitSize = bytes * 8; - const signBit = BigInt(1) << BigInt(bitSize - 1); - const mask = (BigInt(1) << BigInt(bitSize)) - BigInt(1); - - // mask to the correct bit width - const masked = bigIntValue & mask; - // check if negative (sign bit is set) - if (masked >= signBit) { - // convert from two's complement - const result = masked - (BigInt(1) << BigInt(bitSize)); - return Number(result); + const mask = parseInt('0x80' + '00'.repeat(bytes - 1), 16); + let integer = parseInt(hex, 16); + if (integer >= mask) { + integer = integer - mask * 2; } - - return Number(masked); + return integer; } export function find(regex: RegExp, input: string) {