Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
23 changes: 12 additions & 11 deletions tslang/include/TypeScript/LowerToLLVM/CastLogicHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,11 @@ class CastLogicHelper
return castIntToString(in, tch.getIndexTypeBitwidth(), true);
}

// a sign-neutral iN prints signed, as it compares and converts to number: `let a: i32 = -1` is -1,
// not 4294967295; only an unsigned uN prints unsigned
if (isa<mlir::IntegerType>(inType) && isResString)
{
return castIntToString(in, inLLVMType.getIntOrFloatBitWidth(), inType.isSignedInteger());
return castIntToString(in, inLLVMType.getIntOrFloatBitWidth(), !inType.isUnsignedInteger());
}

// a bigint is a signed i64; without this case it fell through to a bare inttoptr, and
Expand Down Expand Up @@ -151,17 +153,16 @@ class CastLogicHelper
}
}

// a signed integer keeps its sign as an index: `let n = s.length; n = -1` held 4294967295 under the
// zext in castLLVMTypesLogic
if (inType.isSignedInteger() && resType.isIndex() && resLLVMType.getIntOrFloatBitWidth() > inType.getIntOrFloatBitWidth())
// a wider integer keeps the value: a signed or sign-neutral (iN) one sign-extends, only an unsigned one
// zero-extends (castLLVMTypesLogic, which sees signless LLVM types only). `let c: i64 = -7` held
// 4294967289, `let n = s.length; n = -1` held 4294967295, and `i16` -300 compared as 65236.
if (auto inIntType = dyn_cast<mlir::IntegerType>(inType))
{
return rewriter.create<LLVM::SExtOp>(loc, resLLVMType, in);
}

// TODO: should be in LLVM cast?
if (inType.isSignedInteger() && resType.isSignedInteger() && resType.getIntOrFloatBitWidth() > inType.getIntOrFloatBitWidth())
{
return rewriter.create<LLVM::SExtOp>(loc, resLLVMType, in);
if (!inIntType.isUnsigned() && inIntType.getWidth() > 1 && (isa<mlir::IntegerType>(resType) || resType.isIndex())
&& resLLVMType.getIntOrFloatBitWidth() > inLLVMType.getIntOrFloatBitWidth())
{
return rewriter.create<LLVM::SExtOp>(loc, resLLVMType, in);
}
}

// an unsigned integer is converted to a float as unsigned: castLLVMTypesLogic only sees the
Expand Down
2 changes: 2 additions & 0 deletions tslang/test/tester/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ tslang_add_test(NAME test-compile-00-generator-return COMMAND test-runner "${PRO
tslang_add_test(NAME test-compile-00-return-inference-undefined COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00return_inference_undefined.ts")
tslang_add_test(NAME test-compile-00-return-falls-off-end COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00return_falls_off_end.ts")
tslang_add_test(NAME test-compile-00-nullish-values COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00nullish_values.ts")
tslang_add_test(NAME test-compile-00-signless-int-signed COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00signless_int_signed.ts")
tslang_add_test(NAME test-compile-00-intersection-type COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00intersection_type.ts")
tslang_add_test(NAME test-compile-00-intersection-type-generic COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00intersection_type_generic.ts")
tslang_add_test(NAME test-compile-00-length COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00length.ts")
Expand Down Expand Up @@ -879,6 +880,7 @@ tslang_add_test(NAME test-jit-00-generator-return COMMAND test-runner -jit "${PR
tslang_add_test(NAME test-jit-00-return-inference-undefined COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00return_inference_undefined.ts")
tslang_add_test(NAME test-jit-00-return-falls-off-end COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00return_falls_off_end.ts")
tslang_add_test(NAME test-jit-00-nullish-values COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00nullish_values.ts")
tslang_add_test(NAME test-jit-00-signless-int-signed COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00signless_int_signed.ts")
tslang_add_test(NAME test-jit-00-union-global-init COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00union_global_init.ts")
tslang_add_test(NAME test-jit-00-intersection-type COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00intersection_type.ts")
tslang_add_test(NAME test-jit-00-intersection-type-generic COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00intersection_type_generic.ts")
Expand Down
41 changes: 41 additions & 0 deletions tslang/test/tester/tests/00signless_int_signed.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// a sign-neutral iN is signed: it prints, widens and compares keeping its sign (`let a: i32 = -1` printed
// 4294967295, `let c: i64 = -7` held 4294967289, `i16` -300 compared as 65236); a uN stays unsigned
function main() {
let a: i32 = -1;
assert(`${a}` == "-1", "i32 prints signed");
assert(a < 0, "i32 compares signed");
const n: number = a;
assert(n == -1, "i32 to number");

let b: i8 = -5;
assert(`${b}` == "-5", "i8 prints signed");

let c: i64 = -7;
assert(`${c}` == "-7", "i32 literal widens to i64 with its sign");
assert(c < 0, "i64 compares signed");

let d: i16 = -300;
assert(d < 0, "i16 widens to compare with its sign");
assert(`${d}` == "-300", "i16 prints signed");

const x: any = a;
assert(`${x}` == "-1", "i32 in any");

let k: i32 = -2;
let m: index = k;
assert(`${m}` == "-2", "i32 widens to index with its sign");

let big: i64 = -9000000000;
assert(`${big}` == "-9000000000" && big < 0, "i64");

// unsigned stays unsigned
let u: u32 = 4294967295;
assert(`${u}` == "4294967295", "u32 prints unsigned");
let u8v: u8 = 255;
let widened: s32 = u8v;
assert(widened == 255, "u8 widens with zeros");
let e: i64 = u;
assert(`${e}` == "4294967295", "u32 widens to i64 with zeros");

print("done.");
}
Loading