zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 4ebbc9047f60d940e31d53bb8800d60c9a92f364 (tree)
parent dd762f7bcff6e02254e6291317a16575a282b0e0
Author: Motiejus Jakštys <motiejus@jakstys.lt>
Date:   Thu, 19 Feb 2026 06:19:39 +0000

stages_test: add Zig InternPool cross-check for pre-interned entries

Wire src/test_exports.zig through build.zig so zig0 tests can import
the real Zig InternPool. Add a test that initializes both the C and Zig
InternPools and compares all 124 pre-interned entries index by index.

Also add rule to skill file: never run `zig build test` or bare
`zig build` (they test upstream Zig and take ages).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

Diffstat:
Mbuild.zig | 21+++++++++++++++++++--
Asrc/test_exports.zig | 3+++
Mstage0/.claude/skills/enable-tests/SKILL.md | 3+++
Mstage0/stages_test.zig | 116+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 141 insertions(+), 2 deletions(-)

diff --git a/build.zig b/build.zig @@ -686,7 +686,7 @@ pub fn build(b: *std.Build) !void { }; const test_zig0_step = b.step("test-zig0", "Run zig0 C implementation tests"); - addZig0TestStep(b, test_zig0_step, zig0_target, optimize, zig0_cc, zig0_no_exec, zig0_valgrind, zig0_test_timeout); + addZig0TestStep(b, test_zig0_step, zig0_target, optimize, zig0_cc, zig0_no_exec, zig0_valgrind, zig0_test_timeout, exe_options); const fmt_zig0 = b.step("fmt-zig0", "Format zig0 C code"); const clang_format = b.addSystemCommand(&.{ "clang-format", "-i" }); @@ -749,7 +749,7 @@ pub fn build(b: *std.Build) !void { all_zig0.dependOn(&zig0_fmt_check.step); all_zig0.dependOn(lint_zig0); for (zig0_compilers) |compiler| { - addZig0TestStep(b, all_zig0, zig0_target, optimize, compiler, false, zig0_valgrind, zig0_test_timeout); + addZig0TestStep(b, all_zig0, zig0_target, optimize, compiler, false, zig0_valgrind, zig0_test_timeout, exe_options); } } @@ -1615,6 +1615,7 @@ fn addZig0TestStep( no_exec: bool, valgrind: bool, test_timeout: ?[]const u8, + exe_options: *std.Build.Step.Options, ) void { const test_mod = b.createModule(.{ .root_source_file = b.path("stage0_test_root.zig"), @@ -1625,6 +1626,22 @@ fn addZig0TestStep( addZig0CSources(b, test_mod, cc, optimize); test_mod.linkSystemLibrary("c", .{}); + // Re-export module rooted in src/ (can resolve compiler-internal imports) + const zig_internals_mod = b.createModule(.{ + .root_source_file = b.path("src/test_exports.zig"), + }); + const aro_mod = b.createModule(.{ + .root_source_file = b.path("lib/compiler/aro/aro.zig"), + }); + const aro_translate_c_mod = b.createModule(.{ + .root_source_file = b.path("lib/compiler/aro_translate_c.zig"), + }); + aro_translate_c_mod.addImport("aro", aro_mod); + zig_internals_mod.addImport("aro", aro_mod); + zig_internals_mod.addImport("aro_translate_c", aro_translate_c_mod); + zig_internals_mod.addOptions("build_options", exe_options); + test_mod.addImport("zig_internals", zig_internals_mod); + const timeout: ?[]const u8 = test_timeout orelse if (valgrind) null else "300"; const test_exe = b.addTest(.{ diff --git a/src/test_exports.zig b/src/test_exports.zig @@ -0,0 +1,3 @@ +pub const InternPool = @import("InternPool.zig"); +// Later: pub const Sema = @import("Sema.zig"); +// Later: pub const Air = @import("Air.zig"); diff --git a/stage0/.claude/skills/enable-tests/SKILL.md b/stage0/.claude/skills/enable-tests/SKILL.md @@ -25,6 +25,9 @@ edit C source files. The worker handles all of that. the worker's claim that tests pass — verify it. 3. **Batch passing tests.** When multiple consecutive tests pass without code changes, commit them together in one commit. +4. **NEVER run `zig build test` or `zig build` without arguments.** These + build and test upstream Zig, which takes ages and is irrelevant to zig0. + Always use `zig build test-zig0 -Dzig0-cc=tcc` for testing. ## File Configuration diff --git a/stage0/stages_test.zig b/stage0/stages_test.zig @@ -8,6 +8,8 @@ const astgen_test = @import("astgen_test.zig"); const sema_test = @import("sema_test.zig"); const c = parser_test.c; const sc = sema_test.c; +const zig_internals = @import("zig_internals"); +const ZigIP = zig_internals.InternPool; const Stage = enum { parser, sema }; @@ -1201,3 +1203,117 @@ const corpus_files = .{ //"../lib/compiler_rt/udivmodti4_test.zig", // 10249535 //"../src/arch/x86_64/CodeGen.zig", // 11086406 }; + +// --------------------------------------------------------------------------- +// InternPool cross-check: C vs Zig reference +// --------------------------------------------------------------------------- + +test "sema: intern pool pre-interned comparison" { + const gpa = std.testing.allocator; + + // Zig InternPool + var zig_ip: ZigIP = ZigIP.empty; + try zig_ip.init(gpa, 1); + defer zig_ip.deinit(gpa); + + // C InternPool + var c_ip = sc.ipInit(); + defer sc.ipDeinit(&c_ip); + + // Both should have 124 pre-interned entries + try std.testing.expectEqual(@as(u32, 124), c_ip.items_len); + + // Compare each entry's key + for (0..c_ip.items_len) |i| { + const c_key = sc.ipIndexToKey(&c_ip, @intCast(i)); + const zig_key = zig_ip.indexToKey(@enumFromInt(i)); + try expectKeysEqual(c_key, zig_key, @intCast(i)); + } +} + +fn expectKeysEqual(c_key: sc.InternPoolKey, zig_key: ZigIP.Key, index: u32) !void { + switch (c_key.tag) { + sc.IP_KEY_INT_TYPE => { + const zig_int = zig_key.int_type; + try std.testing.expectEqual(c_key.data.int_type.bits, zig_int.bits); + // C: 0=unsigned, 1=signed; Zig: Signedness enum { signed=0, unsigned=1 } + const c_is_signed = c_key.data.int_type.signedness != 0; + try std.testing.expectEqual(c_is_signed, zig_int.signedness == .signed); + }, + sc.IP_KEY_SIMPLE_TYPE => { + // SimpleType enum values encode the Index directly in the Zig IP + const zig_st = zig_key.simple_type; + try std.testing.expectEqual(index, @intFromEnum(zig_st)); + }, + sc.IP_KEY_PTR_TYPE => { + const zig_ptr = zig_key.ptr_type; + const c_ptr = c_key.data.ptr_type; + try std.testing.expectEqual(c_ptr.child, @intFromEnum(zig_ptr.child)); + try std.testing.expectEqual(c_ptr.sentinel, @intFromEnum(zig_ptr.sentinel)); + // Compare size + const c_size: u2 = @intCast(c_ptr.flags & sc.PTR_FLAGS_SIZE_MASK); + try std.testing.expectEqual(c_size, @intFromEnum(zig_ptr.flags.size)); + // Compare is_const + const c_is_const = (c_ptr.flags & sc.PTR_FLAGS_IS_CONST) != 0; + try std.testing.expectEqual(c_is_const, zig_ptr.flags.is_const); + }, + sc.IP_KEY_VECTOR_TYPE => { + const zig_vec = zig_key.vector_type; + try std.testing.expectEqual(c_key.data.vector_type.len, zig_vec.len); + try std.testing.expectEqual(c_key.data.vector_type.child, @intFromEnum(zig_vec.child)); + }, + sc.IP_KEY_OPT_TYPE => { + try std.testing.expectEqual(c_key.data.opt_type, @intFromEnum(zig_key.opt_type)); + }, + sc.IP_KEY_ANYFRAME_TYPE => { + try std.testing.expectEqual(c_key.data.anyframe_type, @intFromEnum(zig_key.anyframe_type)); + }, + sc.IP_KEY_ERROR_UNION_TYPE => { + const zig_eu = zig_key.error_union_type; + try std.testing.expectEqual(c_key.data.error_union_type.error_set, @intFromEnum(zig_eu.error_set_type)); + try std.testing.expectEqual(c_key.data.error_union_type.payload, @intFromEnum(zig_eu.payload_type)); + }, + sc.IP_KEY_TUPLE_TYPE => { + // For the pre-interned set this is only empty_tuple_type + const zig_tuple = zig_key.tuple_type; + try std.testing.expectEqual(@as(u32, 0), zig_tuple.types.len); + try std.testing.expectEqual(@as(u32, 0), zig_tuple.values.len); + }, + sc.IP_KEY_UNDEF => { + try std.testing.expectEqual(c_key.data.undef, @intFromEnum(zig_key.undef)); + }, + sc.IP_KEY_SIMPLE_VALUE => { + const zig_sv = zig_key.simple_value; + // Map C SimpleValue enum to Zig SimpleValue enum by comparing the + // Index they encode (Zig SimpleValue values are the IP index itself). + try std.testing.expectEqual(index, @intFromEnum(zig_sv)); + }, + sc.IP_KEY_INT => { + const zig_int = zig_key.int; + // Compare type + try std.testing.expectEqual(c_key.data.int_val.ty, @intFromEnum(zig_int.ty)); + // Compare value + switch (zig_int.storage) { + .u64 => |v| { + try std.testing.expect(!c_key.data.int_val.is_negative); + try std.testing.expectEqual(c_key.data.int_val.value, v); + }, + .i64 => |v| { + if (v < 0) { + try std.testing.expect(c_key.data.int_val.is_negative); + const abs: u64 = @intCast(-v); + try std.testing.expectEqual(c_key.data.int_val.value, abs); + } else { + try std.testing.expect(!c_key.data.int_val.is_negative); + try std.testing.expectEqual(c_key.data.int_val.value, @as(u64, @intCast(v))); + } + }, + else => return error.TestUnexpectedResult, + } + }, + else => { + std.debug.print("unhandled key tag {d} at index {d}\n", .{ c_key.tag, index }); + return error.TestUnexpectedResult; + }, + } +}