diff --git a/tslang/lib/TypeScript/MLIRGenImpl.h b/tslang/lib/TypeScript/MLIRGenImpl.h index 1f55d5c62..c1b71b94e 100644 --- a/tslang/lib/TypeScript/MLIRGenImpl.h +++ b/tslang/lib/TypeScript/MLIRGenImpl.h @@ -9645,7 +9645,8 @@ class MLIRGenImpl { //case 8: //case 16: - case 32: + // a literal in [2^31, 2^32) does not fit s32; it takes s64 (default branch), not u32, + // so arithmetic with other integer literals does not wrap case 64: case 128: unsignedVal = true; diff --git a/tslang/test/tester/CMakeLists.txt b/tslang/test/tester/CMakeLists.txt index d8ae1e3f8..81abd0a6d 100644 --- a/tslang/test/tester/CMakeLists.txt +++ b/tslang/test/tester/CMakeLists.txt @@ -273,6 +273,7 @@ tslang_add_test(NAME test-compile-00-equals COMMAND test-runner "${PROJECT_SOURC tslang_add_test(NAME test-compile-00-bool-arith-ops COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00bool_arith_ops.ts") tslang_add_test(NAME test-compile-00-int64-shift-bitwise COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00int64_shift_bitwise.ts") tslang_add_test(NAME test-compile-00-int64-mul-literal COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00int64_mul_literal.ts") +tslang_add_test(NAME test-compile-00-int-literal-above-s32 COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00int_literal_above_s32.ts") tslang_add_test(NAME test-compile-00-literal-union-arith COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00literal_union_arith.ts") tslang_add_test(NAME test-compile-00-literal-union-cast COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00literal_union_cast.ts") tslang_add_test(NAME test-compile-00-bool-const-array COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00bool_const_array.ts") @@ -826,6 +827,7 @@ tslang_add_test(NAME test-jit-00-equals COMMAND test-runner -jit "${PROJECT_SOUR tslang_add_test(NAME test-jit-00-bool-arith-ops COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00bool_arith_ops.ts") tslang_add_test(NAME test-jit-00-int64-shift-bitwise COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00int64_shift_bitwise.ts") tslang_add_test(NAME test-jit-00-int64-mul-literal COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00int64_mul_literal.ts") +tslang_add_test(NAME test-jit-00-int-literal-above-s32 COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00int_literal_above_s32.ts") tslang_add_test(NAME test-jit-00-literal-union-arith COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00literal_union_arith.ts") tslang_add_test(NAME test-jit-00-literal-union-cast COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00literal_union_cast.ts") tslang_add_test(NAME test-jit-00-bool-const-array COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00bool_const_array.ts") @@ -1836,6 +1838,7 @@ set(TSLANG_CORPUS 00bool_arith_ops.ts 00int64_shift_bitwise.ts 00int64_mul_literal.ts + 00int_literal_above_s32.ts 00literal_union_arith.ts 00literal_union_cast.ts 00bool_const_array.ts diff --git a/tslang/test/tester/tests/00int_literal_above_s32.ts b/tslang/test/tester/tests/00int_literal_above_s32.ts new file mode 100644 index 000000000..23fca0e6b --- /dev/null +++ b/tslang/test/tester/tests/00int_literal_above_s32.ts @@ -0,0 +1,45 @@ +// regression test: an integer literal that does not fit s32 gets a 64-bit type. +// +// bug found and fixed: a literal in [2^31, 2^32) (3000000000, 2147483648, 0xFFFFFFFF) was typed u32, +// so arithmetic with other integer literals was done in 32 bits: `1 + 3000000000` printed +// -1294967295. Such a literal is now s64, like 5000000000 already was; smaller literals stay s32. + +function main() { + const x = 3000000000; + print(x); + assert(`${x}` == "3000000000", "const"); + + const sum = 1 + 3000000000; + print(sum); + assert(`${sum}` == "3000000001", "1 + 3000000000"); + + const twice = 3000000000 * 2; + assert(`${twice}` == "6000000000", "3000000000 * 2"); + + let z = 3000000000; + z += 3000000000; + assert(`${z}` == "6000000000", "z += 3000000000"); + + const allOnes = 0xFFFFFFFF + 1; + assert(`${allOnes}` == "4294967296", "0xFFFFFFFF + 1"); + + const belowMin = -2147483649; + assert(`${belowMin}` == "-2147483649", "-2147483649"); + + const minPlus = 2147483648 + 1; + assert(`${minPlus}` == "2147483649", "2147483648 + 1"); + + // a literal that fits s32 is still s32 + const small = 2147483647; + assert(`${small}` == "2147483647", "s32 max"); + + // narrowing into a declared 32-bit type still works + const m: s32 = -2147483648; + assert(`${m}` == "-2147483648", "s32 min"); + const u: u32 = 0xFFFFFFFF; + assert(`${u}` == "4294967295", "u32 max"); + const v: u32 = 3000000000; + assert(`${v}` == "3000000000", "u32 3000000000"); + + print("done."); +} diff --git a/tslang/test/tester/tests/02numbers.ts b/tslang/test/tester/tests/02numbers.ts index a646254e4..0d9fdd5d3 100644 --- a/tslang/test/tester/tests/02numbers.ts +++ b/tslang/test/tester/tests/02numbers.ts @@ -139,7 +139,8 @@ function testNums(): void { testRightU(0x30000004, 0, 0x30000004) testLeft(1, 29, 0x20000000) testLeft(1, 30, 0x40000000) - testLeft(1, 31, 0x80000000 >> 0) + // 0x80000000 is an s64 literal, so `0x80000000 >> 0` no longer narrows it to 32 bits + testLeft(1, 31, -2147483648) //testLeft(1, 32, 1); tt = 2;