sema: add add_sat, sub_sat, int_from_bool; more unit tests
Implement three new ZIR instruction handlers: - ZIR_INST_ADD_SAT / ZIR_INST_SUB_SAT: saturating arithmetic, same pattern as existing wrapping ops (zirArithmetic + bin_op AIR) - ZIR_INST_INT_FROM_BOOL: @intFromBool, emits bitcast to u1 (ported from src/Sema.zig zirIntFromBool) Add semaTypeOf entries for AIR_INST_ADD_SAT / AIR_INST_SUB_SAT. Add 10 new sema_test.zig unit tests: intFromBool, add_sat, sub_sat, bit_or, bit_and, f16 add, f64 mul, intcast with computed dest type, and multiple exported functions. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -524,6 +524,8 @@ static TypeIndex semaTypeOf(Sema* sema, AirInstRef ref) {
|
||||
case AIR_INST_SUB_WRAP:
|
||||
case AIR_INST_MUL:
|
||||
case AIR_INST_MUL_WRAP:
|
||||
case AIR_INST_ADD_SAT:
|
||||
case AIR_INST_SUB_SAT:
|
||||
case AIR_INST_BIT_AND:
|
||||
case AIR_INST_BIT_OR:
|
||||
case AIR_INST_XOR:
|
||||
@@ -720,6 +722,19 @@ static AirInstRef zirBoolNot(Sema* sema, SemaBlock* block, uint32_t inst) {
|
||||
return blockAddInst(block, AIR_INST_NOT, data);
|
||||
}
|
||||
|
||||
// zirIntFromBool: handle int_from_bool ZIR instruction (@intFromBool).
|
||||
// Ported from src/Sema.zig zirIntFromBool.
|
||||
// Emits AIR_INST_BITCAST to u1.
|
||||
static AirInstRef zirIntFromBool(Sema* sema, SemaBlock* block, uint32_t inst) {
|
||||
ZirInstRef operand_ref = sema->code.inst_datas[inst].un_node.operand;
|
||||
AirInstRef operand = resolveInst(sema, operand_ref);
|
||||
AirInstData data;
|
||||
memset(&data, 0, sizeof(data));
|
||||
data.ty_op.ty_ref = AIR_REF_FROM_IP(IP_INDEX_U1_TYPE);
|
||||
data.ty_op.operand = operand;
|
||||
return blockAddInst(block, AIR_INST_BITCAST, data);
|
||||
}
|
||||
|
||||
// smallestUnsignedBits: compute the number of bits needed to represent max.
|
||||
// Ported from src/Type.zig smallestUnsignedBits.
|
||||
static uint16_t smallestUnsignedBits(uint16_t max) {
|
||||
@@ -3189,6 +3204,16 @@ static bool analyzeBodyInner(
|
||||
zirArithmetic(sema, block, inst, AIR_INST_MUL_WRAP));
|
||||
i++;
|
||||
continue;
|
||||
case ZIR_INST_ADD_SAT:
|
||||
instMapPut(&sema->inst_map, inst,
|
||||
zirArithmetic(sema, block, inst, AIR_INST_ADD_SAT));
|
||||
i++;
|
||||
continue;
|
||||
case ZIR_INST_SUB_SAT:
|
||||
instMapPut(&sema->inst_map, inst,
|
||||
zirArithmetic(sema, block, inst, AIR_INST_SUB_SAT));
|
||||
i++;
|
||||
continue;
|
||||
|
||||
// Comparisons: same binary pattern as arithmetic.
|
||||
case ZIR_INST_CMP_LT:
|
||||
@@ -3341,6 +3366,11 @@ static bool analyzeBodyInner(
|
||||
zirBoolNot(sema, block, inst));
|
||||
i++;
|
||||
continue;
|
||||
case ZIR_INST_INT_FROM_BOOL:
|
||||
instMapPut(&sema->inst_map, inst,
|
||||
zirIntFromBool(sema, block, inst));
|
||||
i++;
|
||||
continue;
|
||||
case ZIR_INST_NEGATE_WRAP:
|
||||
instMapPut(&sema->inst_map, inst,
|
||||
zirNegateWrap(sema, block, inst));
|
||||
|
||||
@@ -1019,3 +1019,50 @@ test "sema air: same-file inline call with two args" {
|
||||
\\}
|
||||
);
|
||||
}
|
||||
|
||||
test "sema air: intFromBool" {
|
||||
try semaAirRawCheck("export fn f(x: bool) u32 { return @intFromBool(x); }");
|
||||
}
|
||||
|
||||
test "sema air: add_sat" {
|
||||
try semaAirRawCheck("export fn f(x: u32, y: u32) u32 { return x +| y; }");
|
||||
}
|
||||
|
||||
test "sema air: sub_sat" {
|
||||
try semaAirRawCheck("export fn f(x: u32, y: u32) u32 { return x -| y; }");
|
||||
}
|
||||
|
||||
test "sema air: bit_or" {
|
||||
try semaAirRawCheck("export fn f(x: u32, y: u32) u32 { return x | y; }");
|
||||
}
|
||||
|
||||
test "sema air: bit_and" {
|
||||
try semaAirRawCheck("export fn f(x: u32, y: u32) u32 { return x & y; }");
|
||||
}
|
||||
|
||||
test "sema air: f16 add" {
|
||||
try semaAirRawCheck("export fn f(x: f16, y: f16) f16 { return x + y; }");
|
||||
}
|
||||
|
||||
test "sema air: f64 mul" {
|
||||
try semaAirRawCheck("export fn f(x: f64, y: f64) f64 { return x * y; }");
|
||||
}
|
||||
|
||||
test "sema air: intcast computed dest type" {
|
||||
try semaAirRawCheck(
|
||||
\\export fn f(x: u16) u32 {
|
||||
\\ return @intCast(x);
|
||||
\\}
|
||||
);
|
||||
}
|
||||
|
||||
test "sema air: multiple return paths" {
|
||||
try semaAirRawCheck(
|
||||
\\export fn f(x: u32) u32 {
|
||||
\\ return x + 1;
|
||||
\\}
|
||||
\\export fn g(x: u32) u32 {
|
||||
\\ return x * 2;
|
||||
\\}
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user