astgen: port Phases 4-5 (control flow, expressions, scope chain)
Port scope chain infrastructure, function parameters, local var_decl, control flow (if/for/while/switch/orelse/catch/defer), labeled blocks, break/continue, comparison/boolean/unary operators, array access, field access rvalue, rvalue type coercion optimization, and many builtins from upstream AstGen.zig. test_all.zig corpus passes; 4 remaining corpus files still have mismatches (WIP). Also fix cppcheck/lint issues: safe realloc pattern, null checks, const correctness, enable inline suppressions, comment out test debug output for clean `zig build`. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -608,32 +608,69 @@ fn expectEqualData(
|
||||
/// Unlike expectEqualZir, does not print diagnostics or return errors.
|
||||
fn zirMatches(gpa: Allocator, ref: Zir, got: c.Zir) bool {
|
||||
const ref_len: u32 = @intCast(ref.instructions.len);
|
||||
if (ref_len != got.inst_len) return false;
|
||||
if (ref_len != got.inst_len) {
|
||||
//std.debug.print(" inst_len: ref={d} got={d}\n", .{ ref_len, got.inst_len });
|
||||
}
|
||||
|
||||
const ref_tags = ref.instructions.items(.tag);
|
||||
const ref_datas = ref.instructions.items(.data);
|
||||
for (0..ref_len) |i| {
|
||||
const min_len = @min(ref_len, got.inst_len);
|
||||
var first_tag_mismatch: ?u32 = null;
|
||||
for (0..min_len) |i| {
|
||||
const ref_tag: u8 = @intFromEnum(ref_tags[i]);
|
||||
const got_tag: u8 = @intCast(got.inst_tags[i]);
|
||||
if (ref_tag != got_tag) return false;
|
||||
if (!dataMatches(ref_tags[i], ref_datas[i], got.inst_datas[i])) return false;
|
||||
if (ref_tag != got_tag) {
|
||||
first_tag_mismatch = @intCast(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (first_tag_mismatch) |_| {
|
||||
//const start = if (ftm > 5) ftm - 5 else 0;
|
||||
//const end = @min(ftm + 10, min_len);
|
||||
//std.debug.print(" first tag mismatch at inst[{d}]:\n", .{ftm});
|
||||
//for (start..end) |i| {
|
||||
// const ref_tag: u8 = @intFromEnum(ref_tags[i]);
|
||||
// const got_tag: u8 = @intCast(got.inst_tags[i]);
|
||||
// const marker: u8 = if (i == ftm) '>' else ' ';
|
||||
// std.debug.print(" {c} [{d}] ref_tag={d} got_tag={d}\n", .{ marker, i, ref_tag, got_tag });
|
||||
//}
|
||||
return false;
|
||||
}
|
||||
for (0..min_len) |i| {
|
||||
if (!dataMatches(ref_tags[i], ref_datas[i], got.inst_datas[i])) {
|
||||
//std.debug.print(" inst_datas[{d}] mismatch (tag={d})\n", .{ i, @as(u8, @intFromEnum(ref_tags[i])) });
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (ref_len != got.inst_len) return false;
|
||||
|
||||
const ref_extra_len: u32 = @intCast(ref.extra.len);
|
||||
if (ref_extra_len != got.extra_len) return false;
|
||||
if (ref_extra_len != got.extra_len) {
|
||||
//std.debug.print(" extra_len: ref={d} got={d}\n", .{ ref_extra_len, got.extra_len });
|
||||
return false;
|
||||
}
|
||||
|
||||
const skip = buildHashSkipMask(gpa, ref) catch return false;
|
||||
defer gpa.free(skip);
|
||||
|
||||
for (0..ref_extra_len) |i| {
|
||||
if (skip[i]) continue;
|
||||
if (ref.extra[i] != got.extra[i]) return false;
|
||||
if (ref.extra[i] != got.extra[i]) {
|
||||
//std.debug.print(" extra[{d}]: ref=0x{x:0>8} got=0x{x:0>8}\n", .{ i, ref.extra[i], got.extra[i] });
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const ref_sb_len: u32 = @intCast(ref.string_bytes.len);
|
||||
if (ref_sb_len != got.string_bytes_len) return false;
|
||||
if (ref_sb_len != got.string_bytes_len) {
|
||||
//std.debug.print(" string_bytes_len: ref={d} got={d}\n", .{ ref_sb_len, got.string_bytes_len });
|
||||
return false;
|
||||
}
|
||||
for (0..ref_sb_len) |i| {
|
||||
if (ref.string_bytes[i] != got.string_bytes[i]) return false;
|
||||
if (ref.string_bytes[i] != got.string_bytes[i]) {
|
||||
//std.debug.print(" string_bytes[{d}]: ref=0x{x:0>2} got=0x{x:0>2}\n", .{ i, ref.string_bytes[i], got.string_bytes[i] });
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -728,7 +765,7 @@ const corpus_files = .{
|
||||
};
|
||||
|
||||
/// Returns .pass or .skip for a single corpus entry.
|
||||
fn corpusCheck(gpa: Allocator, _: []const u8, source: [:0]const u8) enum { pass, skip } {
|
||||
fn corpusCheck(gpa: Allocator, name: []const u8, source: [:0]const u8) enum { pass, skip } {
|
||||
var tree = Ast.parse(gpa, source, .zig) catch return .skip;
|
||||
defer tree.deinit(gpa);
|
||||
|
||||
@@ -740,13 +777,18 @@ fn corpusCheck(gpa: Allocator, _: []const u8, source: [:0]const u8) enum { pass,
|
||||
var c_zir = c.astGen(&c_ast);
|
||||
defer c.zirDeinit(&c_zir);
|
||||
|
||||
if (c_zir.has_compile_errors) return .skip;
|
||||
if (c_zir.has_compile_errors) {
|
||||
//std.debug.print(" -> has_compile_errors\n", .{});
|
||||
return .skip;
|
||||
}
|
||||
|
||||
if (zirMatches(gpa, ref_zir, c_zir)) {
|
||||
return .pass;
|
||||
} else {
|
||||
//std.debug.print(" -> zir mismatch\n", .{});
|
||||
return .skip;
|
||||
}
|
||||
_ = name;
|
||||
}
|
||||
|
||||
test "astgen: corpus" {
|
||||
|
||||
@@ -100,6 +100,7 @@ pub fn build(b: *std.Build) !void {
|
||||
"--error-exitcode=1",
|
||||
"--check-level=exhaustive",
|
||||
"--enable=all",
|
||||
"--inline-suppr",
|
||||
"--suppress=missingIncludeSystem",
|
||||
"--suppress=checkersReport",
|
||||
"--suppress=unusedFunction", // TODO remove after plumbing is done
|
||||
|
||||
53
zir.h
53
zir.h
@@ -438,13 +438,64 @@ typedef union {
|
||||
#define ZIR_REF_NONE UINT32_MAX
|
||||
#define ZIR_MAIN_STRUCT_INST 0
|
||||
|
||||
// Selected Zir.Inst.Ref enum values (matching Zig enum order).
|
||||
// Zir.Inst.Ref enum values (matching Zig enum order in Zir.zig).
|
||||
// Types (0-103).
|
||||
#define ZIR_REF_U1_TYPE 2
|
||||
#define ZIR_REF_U8_TYPE 3
|
||||
#define ZIR_REF_I8_TYPE 4
|
||||
#define ZIR_REF_U16_TYPE 5
|
||||
#define ZIR_REF_I16_TYPE 6
|
||||
#define ZIR_REF_U29_TYPE 7
|
||||
#define ZIR_REF_U32_TYPE 8
|
||||
#define ZIR_REF_I32_TYPE 9
|
||||
#define ZIR_REF_U64_TYPE 10
|
||||
#define ZIR_REF_I64_TYPE 11
|
||||
#define ZIR_REF_U128_TYPE 13
|
||||
#define ZIR_REF_I128_TYPE 14
|
||||
#define ZIR_REF_USIZE_TYPE 16
|
||||
#define ZIR_REF_ISIZE_TYPE 17
|
||||
#define ZIR_REF_C_CHAR_TYPE 18
|
||||
#define ZIR_REF_C_SHORT_TYPE 19
|
||||
#define ZIR_REF_C_USHORT_TYPE 20
|
||||
#define ZIR_REF_C_INT_TYPE 21
|
||||
#define ZIR_REF_C_UINT_TYPE 22
|
||||
#define ZIR_REF_C_LONG_TYPE 23
|
||||
#define ZIR_REF_C_ULONG_TYPE 24
|
||||
#define ZIR_REF_C_LONGLONG_TYPE 25
|
||||
#define ZIR_REF_C_ULONGLONG_TYPE 26
|
||||
#define ZIR_REF_C_LONGDOUBLE_TYPE 27
|
||||
#define ZIR_REF_F16_TYPE 28
|
||||
#define ZIR_REF_F32_TYPE 29
|
||||
#define ZIR_REF_F64_TYPE 30
|
||||
#define ZIR_REF_F80_TYPE 31
|
||||
#define ZIR_REF_F128_TYPE 32
|
||||
#define ZIR_REF_ANYOPAQUE_TYPE 33
|
||||
#define ZIR_REF_BOOL_TYPE 34
|
||||
#define ZIR_REF_VOID_TYPE 35
|
||||
#define ZIR_REF_TYPE_TYPE 36
|
||||
#define ZIR_REF_ANYERROR_TYPE 37
|
||||
#define ZIR_REF_COMPTIME_INT_TYPE 38
|
||||
#define ZIR_REF_COMPTIME_FLOAT_TYPE 39
|
||||
#define ZIR_REF_NORETURN_TYPE 40
|
||||
#define ZIR_REF_ANYFRAME_TYPE 41
|
||||
#define ZIR_REF_NULL_TYPE 42
|
||||
#define ZIR_REF_UNDEFINED_TYPE 43
|
||||
#define ZIR_REF_ENUM_LITERAL_TYPE 44
|
||||
#define ZIR_REF_PTR_USIZE_TYPE 45
|
||||
#define ZIR_REF_PTR_CONST_COMPTIME_INT_TYPE 46
|
||||
#define ZIR_REF_MANYPTR_U8_TYPE 47
|
||||
#define ZIR_REF_MANYPTR_CONST_U8_TYPE 48
|
||||
#define ZIR_REF_MANYPTR_CONST_U8_SENTINEL_0_TYPE 49
|
||||
#define ZIR_REF_SLICE_CONST_U8_TYPE 50
|
||||
#define ZIR_REF_SLICE_CONST_U8_SENTINEL_0_TYPE 51
|
||||
#define ZIR_REF_ANYERROR_VOID_ERROR_UNION_TYPE 100
|
||||
#define ZIR_REF_GENERIC_POISON_TYPE 102
|
||||
#define ZIR_REF_EMPTY_TUPLE_TYPE 103
|
||||
// Values (104-123).
|
||||
#define ZIR_REF_UNDEF 104
|
||||
#define ZIR_REF_UNDEF_BOOL 105
|
||||
#define ZIR_REF_UNDEF_USIZE 106
|
||||
#define ZIR_REF_UNDEF_U1 107
|
||||
#define ZIR_REF_ZERO 108
|
||||
#define ZIR_REF_ZERO_USIZE 109
|
||||
#define ZIR_REF_ZERO_U1 110
|
||||
|
||||
Reference in New Issue
Block a user