Three more value-observable behavior families ported from the C corpus to in-language @test, routed by the ratified observability rule (value -> test/lang @test; process-outcome stays in runww). Additive: the .c sources keep running in $(TESTS), so no byte-id coverage is removed -- de-dup is deferred to fold 6 (task #12). 906_callret_unsigned_arith -> callret_unsigned_test: call-result unsigned opcode select keyed by callee return type (#168, the N_CALL twin of gunsigned's module-global #134); operands flow through real calls so the return-type arm is exercised, not N_IDENT. 912_sar_shr -> sar_shr_test: signed >> / >>= must emit SAR not SHR (#136); asserts the i64/i32 value directly, dropping the C 8-bit exit-code encoding. 793_widen_pad_zero -> widen_pad_test: widening a narrow value into a wider tagged slot zeroes the high pad words (#227).
85 lines
2.7 KiB
Plaintext
85 lines
2.7 KiB
Plaintext
// sar_shr_test — a SIGNED right-shift (both plain `>>` and compound `>>=`)
|
|
// must emit SAR (arithmetic, sign-fills the MSB), not SHR (logical, zero-fill),
|
|
// migrated from test/wcc/912_sar_shr_run.c (#136). Pre-fix BOTH stages emitted
|
|
// SHRQ for signed RSHIFT (A_SARQ was absent from the w6a opcode table), so
|
|
// `let i: i32 = -200; i >>= 2;` produced 0x3FFFFFCE (1073741774) instead of
|
|
// -50 — cs==ww held, so byte-id was GREEN while the runtime was wrong. The C
|
|
// .c keeps the .s byte-id net; this file pins the RUNTIME semantics directly,
|
|
// dropping the C original's 8-bit exit-code encoding (assert the i64/i32 value
|
|
// in-language — the whole point of the @test model).
|
|
//
|
|
// Unlike gunsigned/idxarg, the bug lives in the shift codegen itself, not in
|
|
// how the operand is sourced, so indexing a row's operand and then shifting
|
|
// STILL exercises the shift site — a row-loop is appropriate. The VALUE (neg
|
|
// vs pos) is the data dimension and loops; the (type, operator) SHAPE selects
|
|
// distinct shift sites (i32 vs i64; cgbin `>>` vs compound `>>=`), so it is one
|
|
// @test fn per shape over a shared row table. Negatives discriminate SAR from
|
|
// SHR; the positive row is a no-regression control (SAR == SHR on positives).
|
|
|
|
package sar_shr_test;
|
|
|
|
// One shift row: x >> sh (or x >>= sh) must equal want. Each consuming @test
|
|
// fixes the operand TYPE and OPERATOR; the rows vary only sign/magnitude.
|
|
type shrow = struct {
|
|
x: i64,
|
|
sh: i64,
|
|
want: i64,
|
|
};
|
|
|
|
let rows: [3]shrow = [
|
|
shrow { x = -200i64, sh = 2i64, want = -50i64 },
|
|
shrow { x = -8i64, sh = 1i64, want = -4i64 },
|
|
shrow { x = 200i64, sh = 2i64, want = 50i64 },
|
|
];
|
|
|
|
@test fn shift_i64_binop() void = {
|
|
let i: i32 = 0;
|
|
for (i < len(rows)) {
|
|
assert(rows[i].x >> rows[i].sh == rows[i].want);
|
|
i += 1;
|
|
};
|
|
};
|
|
|
|
@test fn shift_i64_compound() void = {
|
|
let i: i32 = 0;
|
|
for (i < len(rows)) {
|
|
let v: i64 = rows[i].x;
|
|
v >>= rows[i].sh;
|
|
assert(v == rows[i].want);
|
|
i += 1;
|
|
};
|
|
};
|
|
|
|
@test fn shift_i32_binop() void = {
|
|
let i: i32 = 0;
|
|
for (i < len(rows)) {
|
|
let x: i32 = rows[i].x: i32;
|
|
let r: i32 = x >> (rows[i].sh: i32);
|
|
assert(r == rows[i].want: i32);
|
|
i += 1;
|
|
};
|
|
};
|
|
|
|
@test fn shift_i32_compound() void = {
|
|
let i: i32 = 0;
|
|
for (i < len(rows)) {
|
|
let v: i32 = rows[i].x: i32;
|
|
v >>= rows[i].sh: i32;
|
|
assert(v == rows[i].want: i32);
|
|
i += 1;
|
|
};
|
|
};
|
|
|
|
@test fn shift_unsigned_ctl() void = {
|
|
// u32 control: 200u32 >> 2 == 50 — SHRQ unchanged by the fix.
|
|
let a: u32 = 200u32;
|
|
a >>= 2u32;
|
|
assert(a == 50u32);
|
|
|
|
// u64 high-bit control: the fix must NOT make unsigned use SAR. A
|
|
// logical SHRQ of 0x8000..0 >> 1 == 0x4000..0; an over-broad SARQ would
|
|
// sign-fill the set MSB → 0xC000..0.
|
|
let b: u64 = 0x8000000000000000u64;
|
|
assert(b >> 1u64 == 0x4000000000000000u64);
|
|
};
|