Skip to content

Change %mulint primitive behavior #7358

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 23, 2025
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
- Replace ~date with ~day in Date.make\*. https://github.com/rescript-lang/rescript/pull/7324
- Remove `-bs-jsx-mode`. https://github.com/rescript-lang/rescript/pull/7327
- Drop Node.js version <20 support, as it is reaching End-of-Life. https://github.com/rescript-lang/rescript-compiler/pull/7354
- Make the output of integer multiplication consistent with other operations. https://github.com/rescript-lang/rescript/pull/7358

#### :house: Internal

Expand Down
10 changes: 2 additions & 8 deletions compiler/core/js_exp_make.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1607,14 +1607,8 @@ let int32_mul ?comment (e1 : J.expression) (e2 : J.expression) : J.expression =
| {expression_desc = Number (Int {i = i0}); _}, e ->
let i = is_pos_pow i0 in
if i >= 0 then int32_lsl e (small_int i)
else
call ?comment ~info:Js_call_info.builtin_runtime_call
(dot (js_global "Math") Literals.imul)
[e1; e2]
| _ ->
call ?comment ~info:Js_call_info.builtin_runtime_call
(dot (js_global "Math") Literals.imul)
[e1; e2]
else to_int32 (float_mul ?comment e1 e2)
| _ -> to_int32 (float_mul ?comment e1 e2)

let unchecked_int32_mul ?comment e1 e2 : J.expression =
{comment; expression_desc = Bin (Mul, e1, e2)}
Expand Down
2 changes: 0 additions & 2 deletions compiler/ext/literals.ml
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,6 @@ let runtime = "runtime" (* runtime directory *)

let stdlib = "stdlib"

let imul = "imul" (* signed int32 mul *)

let setter_suffix = "#="

let setter_suffix_len = String.length setter_suffix
Expand Down
2 changes: 1 addition & 1 deletion lib/es6/Primitive_hash.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ function unsafe_pop(q) {
RE_EXN_ID: "Assert_failure",
_1: [
"Primitive_hash.res",
70,
73,
12
],
Error: new Error()
Expand Down
2 changes: 1 addition & 1 deletion lib/es6/Stdlib_Int.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ function range(start, end, optionsOpt) {
let range$2 = options.inclusive === true ? range$1 + 1 | 0 : range$1;
length = Math.ceil(range$2 / abs(step)) | 0;
}
return Stdlib_Array.fromInitializer(length, i => start + Math.imul(i, step) | 0);
return Stdlib_Array.fromInitializer(length, i => start + (i * step | 0) | 0);
}

function rangeWithOptions(start, end, options) {
Expand Down
2 changes: 1 addition & 1 deletion lib/js/Primitive_hash.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ function unsafe_pop(q) {
RE_EXN_ID: "Assert_failure",
_1: [
"Primitive_hash.res",
70,
73,
12
],
Error: new Error()
Expand Down
2 changes: 1 addition & 1 deletion lib/js/Stdlib_Int.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ function range(start, end, optionsOpt) {
let range$2 = options.inclusive === true ? range$1 + 1 | 0 : range$1;
length = Math.ceil(range$2 / abs(step)) | 0;
}
return Stdlib_Array.fromInitializer(length, i => start + Math.imul(i, step) | 0);
return Stdlib_Array.fromInitializer(length, i => start + (i * step | 0) | 0);
}

function rangeWithOptions(start, end, options) {
Expand Down
11 changes: 7 additions & 4 deletions runtime/Primitive_hash.res
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ module String = Primitive_string_extern

@send external charCodeAt: (string, int) => int = "charCodeAt"

// Multiply int32 with C-style overflow behavior
external imul: (int, int) => int = "Math.imul"

type rec cell<'a> = {
content: 'a,
mutable next: option<cell<'a>>,
Expand Down Expand Up @@ -85,19 +88,19 @@ let rotl32 = (x: int, n) => lor(lsl(x, n), lsr(x, 32 - n))

let hash_mix_int = (h, d) => {
let d = ref(d)
d.contents = d.contents * 0xcc9e2d51
d.contents = imul(d.contents, 0xcc9e2d51)
d.contents = rotl32(d.contents, 15)
d.contents = d.contents * 0x1b873593
d.contents = imul(d.contents, 0x1b873593)
let h = ref(lxor(h, d.contents))
h.contents = rotl32(h.contents, 13)
h.contents + lsl(h.contents, 2) + 0xe6546b64
}

let hash_final_mix = h => {
let h = ref(lxor(h, lsr(h, 16)))
h.contents = h.contents * 0x85ebca6b
h.contents = imul(h.contents, 0x85ebca6b)
h.contents = lxor(h.contents, lsr(h.contents, 13))
h.contents = h.contents * 0xc2b2ae35
h.contents = imul(h.contents, 0xc2b2ae35)
lxor(h.contents, lsr(h.contents, 16))
}

Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion tests/tests/src/a_scope_bug.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
function odd(_z) {
while (true) {
let z = _z;
let even = Math.imul(z, z);
let even = z * z | 0;
let a = (even + 4 | 0) + even | 0;
console.log(a.toString());
_z = 32;
Expand Down
2 changes: 1 addition & 1 deletion tests/tests/src/bdd.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ let seed = {
};

function random() {
seed.contents = Math.imul(seed.contents, 25173) + 17431 | 0;
seed.contents = (seed.contents * 25173 | 0) + 17431 | 0;
return (seed.contents & 1) > 0;
}

Expand Down
4 changes: 2 additions & 2 deletions tests/tests/src/belt_list_test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ function sum2(xs, ys) {

Mocha.describe("Belt_list_test", () => {
Mocha.test("makeBy", () => {
let u = Belt_List.makeBy(5, i => Math.imul(i, i));
let f = i => Test_utils.eq("File \"belt_list_test.res\", line 23, characters 20-27", Belt_List.getExn(u, i), Math.imul(i, i));
let u = Belt_List.makeBy(5, i => i * i | 0);
let f = i => Test_utils.eq("File \"belt_list_test.res\", line 23, characters 20-27", Belt_List.getExn(u, i), i * i | 0);
for (let i = 0; i <= 4; ++i) {
f(i);
}
Expand Down
6 changes: 3 additions & 3 deletions tests/tests/src/core/Core_ArrayTests.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ Test.run([
6
], n => {
if (n % 2 === 0) {
return Math.imul(n, n);
return n * n | 0;
}

}), eq, [
Expand Down Expand Up @@ -293,7 +293,7 @@ Test.run([
"filterMap - empty"
], Stdlib_Array.filterMap([], n => {
if (n % 2 === 0) {
return Math.imul(n, n);
return n * n | 0;
}

}), eq, []);
Expand Down Expand Up @@ -406,7 +406,7 @@ Test.run([
"findMap - empty"
], Stdlib_Array.findMap([], n => {
if (n % 2 === 0) {
return Math.imul(n, n);
return n * n | 0;
}

}), eq, undefined);
Expand Down
4 changes: 2 additions & 2 deletions tests/tests/src/core/Core_ResultTests.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ Test.run([
], Stdlib_Result.mapError({
TAG: "Ok",
_0: 5
}, i => Math.imul(i, 3)), eq, {
}, i => i * 3 | 0), eq, {
TAG: "Ok",
_0: 5
});
Expand All @@ -79,7 +79,7 @@ Test.run([
], Stdlib_Result.mapError({
TAG: "Error",
_0: 5
}, i => Math.imul(i, 3)), eq, {
}, i => i * 3 | 0), eq, {
TAG: "Error",
_0: 15
});
Expand Down
2 changes: 1 addition & 1 deletion tests/tests/src/dollar_escape_test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ function $$(x, y) {
let v = 3;

function $$$plus(x, y) {
return Math.imul(x, y);
return x * y | 0;
}

let u = 3;
Expand Down
2 changes: 1 addition & 1 deletion tests/tests/src/ext_pervasives_test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ function $$finally(v, action, f) {
function hash_variant(s) {
let accu = 0;
for (let i = 0, i_finish = s.length; i < i_finish; ++i) {
accu = Math.imul(223, accu) + s.codePointAt(i) | 0;
accu = (223 * accu | 0) + s.codePointAt(i) | 0;
}
accu = accu & 2147483647;
if (accu > 1073741823) {
Expand Down
2 changes: 1 addition & 1 deletion tests/tests/src/ffi_arity_test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import * as Mt from "./mt.mjs";

function f(v) {
if (v % 2 === 0) {
return v => Math.imul(v, v);
return v => v * v | 0;
} else {
return v => v + v | 0;
}
Expand Down
8 changes: 4 additions & 4 deletions tests/tests/src/for_loop_test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ function for_5(x, u) {
};
let arr = Belt_Array.map(x, param => (() => {}));
for (let i = 0, i_finish = x.length; i < i_finish; ++i) {
let k = Math.imul((u << 1), u);
let k = (u << 1) * u | 0;
arr[i] = () => {
v.contents = v.contents + k | 0;
};
Expand Down Expand Up @@ -68,7 +68,7 @@ function for_6(x, u) {
contents: 0
};
for (let i = 0, i_finish = x.length; i < i_finish; ++i) {
let k = Math.imul((u << 1), u);
let k = (u << 1) * u | 0;
let h = (v5.contents << 1);
v2.contents = v2.contents + 1 | 0;
arr[i] = () => {
Expand All @@ -93,7 +93,7 @@ function for_7() {
let arr = Belt_Array.make(21, () => {});
for (let i = 0; i <= 6; ++i) {
for (let j = 0; j <= 2; ++j) {
arr[Math.imul(i, 3) + j | 0] = () => {
arr[(i * 3 | 0) + j | 0] = () => {
v.contents = (v.contents + i | 0) + j | 0;
};
}
Expand All @@ -111,7 +111,7 @@ function for_8() {
let k = (i << 1);
for (let j = 0; j <= 2; ++j) {
let h = i + j | 0;
arr[Math.imul(i, 3) + j | 0] = () => {
arr[(i * 3 | 0) + j | 0] = () => {
v.contents = (((v.contents + i | 0) + j | 0) + h | 0) + k | 0;
};
}
Expand Down
2 changes: 1 addition & 1 deletion tests/tests/src/gpr_1822_test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ let myShape = {

let area;

area = myShape.TAG === "Circle" ? 100 * 3.14 : Math.imul(10, myShape._1);
area = myShape.TAG === "Circle" ? 100 * 3.14 : 10 * myShape._1 | 0;

eq("File \"gpr_1822_test.res\", line 23, characters 3-10", area, 314);

Expand Down
2 changes: 1 addition & 1 deletion tests/tests/src/gpr_2413_test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ function f(x) {
break;
}
let a$3 = x._0._0;
return Math.imul(a$3, a$3);
return a$3 * a$3 | 0;
}

function ff(c) {
Expand Down
2 changes: 1 addition & 1 deletion tests/tests/src/gpr_3536_test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ function xx(obj, a0, a1, a2, a3, a4, a5) {

eq("File \"gpr_3536_test.res\", line 18, characters 12-19", 5, 5);

eq("File \"gpr_3536_test.res\", line 20, characters 12-19", xx(3, (prim0, prim1) => prim0 - prim1 | 0, 2, (prim0, prim1) => prim0 + prim1 | 0, 4, (prim0, prim1) => Math.imul(prim0, prim1), 3), 11);
eq("File \"gpr_3536_test.res\", line 20, characters 12-19", xx(3, (prim0, prim1) => prim0 - prim1 | 0, 2, (prim0, prim1) => prim0 + prim1 | 0, 4, (prim0, prim1) => prim0 * prim1 | 0, 3), 11);

Mt.from_pair_suites("Gpr_3536_test", suites.contents);

Expand Down
4 changes: 2 additions & 2 deletions tests/tests/src/int_overflow_test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import * as Mt from "./mt.mjs";
function hash_variant(s) {
let accu = 0;
for (let i = 0, i_finish = s.length; i < i_finish; ++i) {
accu = Math.imul(223, accu) + s.codePointAt(i) & 2147483647;
accu = (223 * accu | 0) + s.codePointAt(i) & 2147483647;
}
if (accu > 1073741823) {
return accu - -2147483648 | 0;
Expand All @@ -17,7 +17,7 @@ function hash_variant(s) {
function hash_variant2(s) {
let accu = 0;
for (let i = 0, i_finish = s.length; i < i_finish; ++i) {
accu = Math.imul(223, accu) + s.codePointAt(i) | 0;
accu = (223 * accu | 0) + s.codePointAt(i) | 0;
}
accu = accu & 2147483647;
if (accu > 1073741823) {
Expand Down
2 changes: 1 addition & 1 deletion tests/tests/src/mario_game.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -1999,7 +1999,7 @@ function process_collision(dir, c1, c2, state) {
evolve_enemy(o1.dir, typ, s2, o2, context)
];
}
let score = Math.imul(100, state.multiplier);
let score = 100 * state.multiplier | 0;
update_score(state, score);
o2.score = score;
state.multiplier = (state.multiplier << 1);
Expand Down
2 changes: 1 addition & 1 deletion tests/tests/src/miss_colon_test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ function $star$colon(_f, _g) {
if (g.TAG === "Int") {
return {
TAG: "Int",
_0: Math.imul(n, g._0)
_0: n * g._0 | 0
};
}
if (n === 0) {
Expand Down
2 changes: 1 addition & 1 deletion tests/tests/src/recursive_module_test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ function fact(n) {
if (n <= 1) {
return 1;
} else {
return Math.imul(n, M.fact(n - 1 | 0));
return n * M.fact(n - 1 | 0) | 0;
}
}

Expand Down
6 changes: 3 additions & 3 deletions tests/tests/src/recursive_records_test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ rec_cell.next = rec_cell;
function f0(x) {
let rec_cell = {};
Primitive_object.updateDummy(rec_cell, {
content: Math.imul(x, x) - 6 | 0,
content: (x * x | 0) - 6 | 0,
next: rec_cell
});
return rec_cell;
Expand All @@ -49,7 +49,7 @@ function f2(x) {
let rec_cell2 = {};
Primitive_object.updateDummy(rec_cell2, {
TAG: "Cons",
content: Math.imul(x, x) - 6 | 0,
content: (x * x | 0) - 6 | 0,
next: rec_cell2
});
return rec_cell2;
Expand Down Expand Up @@ -93,7 +93,7 @@ rec_cell3.tl = rec_cell3;
function f3(x) {
let rec_cell3 = {};
Primitive_object.updateDummy(rec_cell3, {
hd: Math.imul(x, x) - 6 | 0,
hd: (x * x | 0) - 6 | 0,
tl: rec_cell3
});
return rec_cell3;
Expand Down
2 changes: 1 addition & 1 deletion tests/tests/src/tagged_template_test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ function foo(strings, values) {
let res = "";
let valueCount = values.length;
for (let i = 0; i < valueCount; ++i) {
res = res + Primitive_array.get(strings, i) + Math.imul(Primitive_array.get(values, i), 10).toString();
res = res + Primitive_array.get(strings, i) + (Primitive_array.get(values, i) * 10 | 0).toString();
}
return res + Primitive_array.get(strings, valueCount);
}
Expand Down
2 changes: 1 addition & 1 deletion tests/tests/src/test_export2.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@


function f(x, y) {
return Math.imul(x, y);
return x * y | 0;
}

export {
Expand Down
Loading