← Back to AILP Home

tbb and ERR

Nitpick's tbb<N> types (tbb8, tbb16, tbb32, tbb64) are "taggable bit-banged" integers: each carries an additional in-band sentinel pattern, the ERR value, that represents "this slot does not hold a meaningful number" (typically: arithmetic failure).

Decision D-16 (Phase 3): ERR is always sticky on tbb operations. Any binary op where at least one operand is ERR must produce ERR.

The sentinel

For each width, ERR is the most-negative two's-complement value (INT8_MIN, INT16_MIN, INT32_MIN, INT64_MIN). The codegen helper TBBCodegen::getErrSentinel(Type*) materialises the width-specific constant; TBBCodegen::isErr(...) tests for it.

Arithmetic is sticky

func:main = int32() {
    tbb32:a = 10t32;
    tbb32:b = ERR;
    tbb32:c = a + b;        // c == ERR
    tbb32:d = a * b;        // d == ERR
    tbb32:e = -b;           // e == ERR  (unary neg is sticky too)
    pass 0i32;
};

All of + - * / % neg short-circuit to ERR if either operand is ERR — see src/backend/ir/tbb_codegen.cpp lines 189 / 236 / 276 / 316 / 357 / 398.

Sentinel healing on width promotion

When a narrower tbb is sign-extended to a wider one (e.g. tbb8tbb16), the ERR sentinel must be re-sentineled at the new width, not naively sext'd (the wider pattern is a valid value). This is the "sentinel healing" guard at tbb_codegen.cpp:439-457.

func:main = int32() {
    tbb8:e8  = ERR;
    tbb16:e16 = e8 as tbb16;   // e16 == tbb16 ERR (INT16_MIN), not 0xFF80
    pass 0i32;
};

Comparisons (D-16a)

bool has no ERR state, so the sticky rule has to be expressed through the boolean. Decision D-16a: any comparison involving ERR evaluates to false for ==, <, <=, >, >=, and to true for !=. Equivalently: "ERR is unequal to everything, including itself."

func:main = int32() {
    tbb32:a = 5t32;
    tbb32:e = ERR;

    if (e == e)  { println(`unreachable`); };   // false: ERR != ERR
    if (e != a)  { println(`reached`); };        // true
    if (e <= a)  { println(`unreachable`); };   // false
    pass 0i32;
};

The bool itself is not sentinel-tagged. If you need to detect ERR explicitly, use is_err(x) (the codegen helper exposed as a builtin) — see the tbb chapter of the operators cookbook for the canonical form.

Bitwise ops

The same sticky rule applies to bitwise operators when defined for tbb types. A bit-flip of ERR is ERR; an AND / OR / XOR with ERR on either side is ERR. (Per-op tests in run_bug_tests_03123.sh.)

Interplay with pick

A pick expression on a tbb selector must cover ERR (or use the wildcard (*)). See pick-exhaustiveness.md for the rule and the diagnostic.

Fixtures