astgen: enable array_list.zig corpus test

Fix multiple bugs found via the array_list.zig corpus test:

- Fix anytype param ref/index double-conversion (addStrTok returns
  a ref, don't add ZIR_REF_START_INDEX again)
- Implement is_generic param tracking via is_used_or_discarded
  pointer in ScopeLocalVal
- Fix globalVarDecl declaration src_line: use type_gz.decl_line
  instead of ag->source_line (which was advanced by init expression)
- Fix cppcheck warning: remove redundant (0u << 2) in bitmask
- Implement fetchRemoveRefEntries and ret_param_refs in addFunc
- Add func_fancy case to buildHashSkipMask in test
- Fix valgrind: zero elem_val_imm padding, skip addNodeExtended
  undefined small field, handle more padding-sensitive tags

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-14 15:08:48 +00:00
parent 17f44db36f
commit 23beb0aad2
2 changed files with 224 additions and 40 deletions

View File

@@ -81,6 +81,40 @@ fn buildHashSkipMask(gpa: Allocator, ref: Zir) ![]bool {
}
}
},
.func_fancy => {
// FuncFancy: param_block(1) + body_len(1) + bits(1)
// + trailing cc + ret_ty + noalias + body + SrcLocs(3) + proto_hash(4).
const pi = ref_datas[i].pl_node.payload_index;
const body_len: u32 = ref.extra[pi + 1];
const bits: u32 = ref.extra[pi + 2];
var ei: u32 = pi + 3;
const has_cc_ref: bool = (bits & (1 << 3)) != 0;
const has_cc_body: bool = (bits & (1 << 4)) != 0;
const has_ret_ty_ref: bool = (bits & (1 << 5)) != 0;
const has_ret_ty_body: bool = (bits & (1 << 6)) != 0;
const has_any_noalias: bool = (bits & (1 << 7)) != 0;
if (has_cc_body) {
const cc_body_len = ref.extra[ei];
ei += 1 + cc_body_len;
} else if (has_cc_ref) {
ei += 1;
}
if (has_ret_ty_body) {
const ret_body_len = ref.extra[ei];
ei += 1 + ret_body_len;
} else if (has_ret_ty_ref) {
ei += 1;
}
if (has_any_noalias) ei += 1;
// body + SrcLocs(3) + proto_hash(4)
if (body_len > 0) {
const hash_start = ei + body_len + 3;
for (0..4) |j| {
if (hash_start + j < ref_extra_len)
skip[hash_start + j] = true;
}
}
},
else => {},
}
}
@@ -300,7 +334,35 @@ fn expectEqualZir(gpa: Allocator, ref: Zir, got: c.Zir) !void {
// 3. Compare instruction data field-by-field.
for (0..ref_len) |i| {
try expectEqualData(i, ref_tags[i], ref_datas[i], got.inst_datas[i]);
expectEqualData(i, ref_tags[i], ref_datas[i], got.inst_datas[i]) catch {
// Print nearest declaration for context.
var j: usize = i;
while (j > 0) {
j -= 1;
if (ref_tags[j] == .declaration) {
std.debug.print(" nearest decl at [{d}]: src_node={d}\n", .{
j, ref_datas[j].declaration.src_node,
});
break;
}
}
// Print what tags are at the operand positions if break_inline.
if (ref_tags[i] == .break_inline) {
const r_op = @intFromEnum(ref_datas[i].@"break".operand);
const g_op = got.inst_datas[i].break_data.operand;
if (r_op >= 124 and r_op - 124 < ref_len) {
std.debug.print(" ref operand inst[{d}] tag={d}\n", .{
r_op - 124, @intFromEnum(ref_tags[r_op - 124]),
});
}
if (g_op >= 124 and g_op - 124 < ref_len) {
std.debug.print(" got operand inst[{d}] tag={d}\n", .{
g_op - 124, @intFromEnum(ref_tags[g_op - 124]),
});
}
}
return error.TestExpectedEqual;
};
}
// 4. Compare string bytes.
const ref_sb_len: u32 = @intCast(ref.string_bytes.len);
@@ -370,6 +432,17 @@ fn expectEqualData(
.enum_decl,
.union_decl,
.opaque_decl,
// addNodeExtended sets small = undefined (AstGen.zig:12775).
.this,
.ret_addr,
.error_return_trace,
.frame,
.frame_address,
.breakpoint,
.disable_instrumentation,
.disable_intrinsics,
.in_comptime,
.c_va_start,
=> true,
else => false,
};
@@ -522,6 +595,7 @@ fn expectEqualData(
},
.func,
.func_inferred,
.func_fancy,
.array_type,
.array_type_sentinel,
.array_cat,
@@ -678,6 +752,10 @@ fn expectEqualData(
.@"unreachable",
// .save_err_ret_index data format (operand only):
.save_err_ret_index,
// .float data format (f32 = 4 bytes, second word is padding):
.float,
// .elem_val_imm data format (u32 + u8, 3 bytes padding):
.elem_val_imm,
=> true,
else => false,
};
@@ -853,7 +931,6 @@ test "astgen: corpus astgen_test.zig" {
}
test "astgen: corpus array_list.zig" {
if (true) return error.SkipZigTest; // TODO: +2 ALLOC_MUT / -2 EXTENDED tag mismatch at [6639]
const gpa = std.testing.allocator;
try corpusCheck(gpa, @embedFile("../lib/std/array_list.zig"));
}