Skip to content

Tolk: Constant folding of out-of-range shift emits PUSHNAN instead of preserving runtime exception #1973

@Gusarich

Description

@Gusarich

The compiler folds 1 << 1024 into PUSHNAN at compile time, but the equivalent runtime operation throws range_chk (exit code 5). This changes observable behavior based on whether the shift amount is a constant.

const SHIFT: int = 1024;
const CONST_SHIFTED: int = 1 << SHIFT;

@noinline
fun runtime_shift(x: int, s: int): int { return x << s; }

fun onInternalMessage(s: int) {
    return (CONST_SHIFTED, runtime_shift(1, s));
}

Compiles to:

runtime_shift() PROC:<{  //  x s
  LSHIFT
}>

onInternalMessage() PROC:<{  //  s
  PUSHNAN               // const path: silently returns NaN
  1 PUSHINT
  ROT
  runtime_shift() CALLDICT  // runtime path: throws range_chk for s=1024
}>

TVM's LSHIFT throws range_chk (exit code 5) for shift counts outside 0–1023. The constant-folded version bypasses this check entirely and returns NaN instead.

For s = 1024, the runtime path throws while the const path silently yields NaN. The compiler should reject out-of-range constant shifts at compile time.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions