zig

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

commit 4381a387bfa73c523a49d6b5c4d8ea336c7d4275 (tree)
parent d3d3fb8473e25273ddca2e0da8d9c76cc43c794b
Author: Andrew Kelley <andrew@ziglang.org>
Date:   Fri, 27 Feb 2026 18:48:27 -0800

Configuration: complete serialization of Compile steps

Diffstat:
Mlib/compiler/Maker/ScannedConfig.zig | 19++++++++++++++++++-
Mlib/compiler/Maker/Step/Compile.zig | 47+++++++++++++++++++++++------------------------
Mlib/compiler/configurer.zig | 14+++++++++++---
Mlib/std/zig/Configuration.zig | 108+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
4 files changed, 144 insertions(+), 44 deletions(-)

diff --git a/lib/compiler/Maker/ScannedConfig.zig b/lib/compiler/Maker/ScannedConfig.zig @@ -85,6 +85,8 @@ fn printValue(sc: *const ScannedConfig, s: *Serializer, comptime Field: type, fi .flag_length_prefixed_list => comptime unreachable, .enum_optional => comptime unreachable, .union_list => comptime unreachable, + .length_prefixed_list => comptime unreachable, + .flag_union => comptime unreachable, } else if (std.enums.tagName(Field, field_value)) |name| { try s.ident(name); } else { @@ -103,14 +105,29 @@ fn printValue(sc: *const ScannedConfig, s: *Serializer, comptime Field: type, fi try s.value(null, .{}); } }, - .flag_length_prefixed_list => { + .length_prefixed_list, .flag_length_prefixed_list => { try printValue(sc, s, @TypeOf(field_value.slice), field_value.slice); }, .extended => @compileError("TODO"), .union_list => @compileError("TODO"), + .flag_union => try printValue(sc, s, Field.Union, field_value.u), }, else => @compileError("not implemented: " ++ @typeName(Field)), }, + .@"union" => { + switch (field_value) { + inline else => |u, tag| { + if (@TypeOf(u) == void) { + try s.ident(@tagName(tag)); + } else { + var sub_struct = try s.beginStruct(.{}); + try sub_struct.fieldPrefix(@tagName(tag)); + try printValue(sc, s, @TypeOf(u), u); + try sub_struct.end(); + } + }, + } + }, else => @compileError("not implemented: " ++ @typeName(Field)), }, } diff --git a/lib/compiler/Maker/Step/Compile.zig b/lib/compiler/Maker/Step/Compile.zig @@ -134,21 +134,20 @@ fn lowerZigArgs( }, } - if (true) @panic("TODO"); - - { - for (compile.force_undefined_symbols.keys()) |symbol_name| { - try zig_args.append(gpa, "--force_undefined"); - try zig_args.append(gpa, symbol_name.*); - } + for (conf_comp.force_undefined_symbols.slice) |symbol_name| { + try zig_args.appendSlice(gpa, &.{ "--force_undefined", symbol_name.slice(conf) }); } - if (compile.stack_size) |stack_size| { - try zig_args.append(gpa, "--stack"); - try zig_args.append(gpa, try allocPrint(arena, "{}", .{stack_size})); + if (conf_comp.stack_size.value) |stack_size| { + try zig_args.appendSlice(gpa, &.{ "--stack", try allocPrint(arena, "{d}", .{stack_size}) }); } - try addBool(gpa, zig_args, fuzz, "-ffuzz"); + try addBool(gpa, zig_args, "-ffuzz", fuzz); + + if (true) @panic("TODO"); + + var is_linking_libc = conf_comp.flags3.is_linking_libc; + var is_linking_libcpp = conf_comp.flags3.is_linking_libcpp; { // Stores system libraries that have already been seen for at least one @@ -163,14 +162,14 @@ fn lowerZigArgs( var prev_preferred_link_mode: std.builtin.LinkMode = .dynamic; // Track the number of positional arguments so that a nice error can be // emitted if there is nothing to link. - var total_linker_objects: usize = @intFromBool(compile.root_module.root_source_file != null); + var total_linker_objects: usize = @intFromBool(root_module.root_source_file != .none); // Fully recursive iteration including dynamic libraries to detect // libc and libc++ linkage. for (getCompileDependencies(true)) |some_compile| { for (some_compile.root_module.getGraph().modules) |mod| { - if (mod.link_libc == true) compile.is_linking_libc = true; - if (mod.link_libcpp == true) compile.is_linking_libcpp = true; + if (mod.link_libc == true) is_linking_libc = true; + if (mod.link_libcpp == true) is_linking_libcpp = true; } } @@ -465,11 +464,11 @@ fn lowerZigArgs( try zig_args.append(gpa, name); } - if (compile.is_linking_libcpp) { + if (is_linking_libcpp) { try zig_args.append(gpa, "-lc++"); } - if (compile.is_linking_libc) { + if (is_linking_libc) { try zig_args.append(gpa, "-lc"); } } @@ -500,14 +499,14 @@ fn lowerZigArgs( try zig_args.appendSlice(gpa, &.{ "--debug-log", log_scope }); } - try addBool(gpa, zig_args, graph.debug_compile_errors, "--debug-compile-errors"); - try addBool(gpa, zig_args, graph.debug_incremental, "--debug-incremental"); - try addBool(gpa, zig_args, graph.verbose_air, "--verbose-air"); - try addBool(gpa, zig_args, graph.verbose_llvm_ir, "--verbose-llvm-ir"); - try addBool(gpa, zig_args, graph.verbose_link or compile.verbose_link, "--verbose-link"); - try addBool(gpa, zig_args, graph.verbose_cc or compile.verbose_cc, "--verbose-cc"); - try addBool(gpa, zig_args, graph.verbose_llvm_cpu_features, "--verbose-llvm-cpu-features"); - try addBool(gpa, zig_args, graph.time_report, "--time-report"); + try addBool(gpa, zig_args, "--debug-compile-errors", graph.debug_compile_errors); + try addBool(gpa, zig_args, "--debug-incremental", graph.debug_incremental); + try addBool(gpa, zig_args, "--verbose-air", graph.verbose_air); + try addBool(gpa, zig_args, "--verbose-llvm-ir", graph.verbose_llvm_ir); + try addBool(gpa, zig_args, "--verbose-link", graph.verbose_link or compile.verbose_link); + try addBool(gpa, zig_args, "--verbose-cc", graph.verbose_cc or compile.verbose_cc); + try addBool(gpa, zig_args, "--verbose-llvm-cpu-features", graph.verbose_llvm_cpu_features); + try addBool(gpa, zig_args, "--time-report", graph.time_report); if (compile.generated_asm != null) try zig_args.append(gpa, "-femit-asm"); if (compile.generated_bin == null) try zig_args.append(gpa, "-fno-emit-bin"); diff --git a/lib/compiler/configurer.zig b/lib/compiler/configurer.zig @@ -606,7 +606,7 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void { .max_memory = c.max_memory != null, .kind = c.kind, .global_base = c.global_base != null, - .test_runner_mode = if (c.test_runner) |tr| switch (tr.mode) { + .test_runner = if (c.test_runner) |tr| switch (tr.mode) { .simple => .simple, .server => .server, } else .default, @@ -678,10 +678,18 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void { .exec_cmd_args = .{ .slice = try s.initOptionalStringList(exec_cmd_args) }, .installed_headers = .initErased(installed_headers), .force_undefined_symbols = .{ .slice = try s.initStringList(c.force_undefined_symbols.keys()) }, + .expect_errors = .{ .u = if (c.expect_errors) |x| switch (x) { + .contains => |slice| .{ .contains = try wc.addString(slice) }, + .exact => |exact| .{ .exact = .{ .slice = try s.initStringList(exact) } }, + .starts_with => |slice| .{ .starts_with = try wc.addString(slice) }, + .stderr_contains => |slice| .{ .stderr_contains = try wc.addString(slice) }, + } else .none }, + .test_runner = .{ .u = if (c.test_runner) |tr| switch (tr.mode) { + .simple => .{ .simple = try s.addLazyPath(tr.path) }, + .server => .{ .server = try s.addLazyPath(tr.path) }, + } else .default }, })); - log.err("TODO serialize the trailing Compile step data", .{}); - break :e @enumFromInt(extra_index); }, .install_artifact => e: { diff --git a/lib/std/zig/Configuration.zig b/lib/std/zig/Configuration.zig @@ -584,9 +584,6 @@ pub const Step = extern struct { }; }; - /// Trailing: - /// * exact_match: String, // if expect_errors is contains, starts_with, or stderr_contains - /// * test_runner: LazyPath, // if test_runner_mode is not default pub const Compile = struct { flags: @This().Flags, flags2: Flags2, @@ -600,7 +597,7 @@ pub const Step = extern struct { exec_cmd_args: Storage.FlagLengthPrefixedList(.flags, .exec_cmd_args_len, OptionalString), installed_headers: Storage.FlagLengthPrefixedList(.flags, .installed_headers_len, Storage.Extended(InstalledHeader.Flags, InstalledHeader)), force_undefined_symbols: Storage.FlagLengthPrefixedList(.flags, .force_undefined_symbols_len, String), - //exacts: EnumConditionalPrefixedList(.flags4, .expect_errors, .exact, String), + expect_errors: Storage.FlagUnion(.flags4, .expect_errors, ExpectErrors), linker_script: Storage.FlagOptional(.flags4, .linker_script, LazyPath), version_script: Storage.FlagOptional(.flags4, .version_script, LazyPath), zig_lib_dir: Storage.FlagOptional(.flags3, .zig_lib_dir, LazyPath), @@ -622,6 +619,7 @@ pub const Step = extern struct { headerpad_size: Storage.FlagOptional(.flags4, .headerpad_size, u32), error_limit: Storage.FlagOptional(.flags4, .error_limit, u32), build_id: Storage.EnumOptional(.flags3, .build_id, .hexstring, String), + test_runner: Storage.FlagUnion(.flags3, .test_runner, TestRunner), pub const InstalledHeader = union(@This().Tag) { file: File, @@ -663,8 +661,22 @@ pub const Step = extern struct { }; }; }; - pub const ExpectErrors = enum(u3) { contains, exact, starts_with, stderr_contains, none }; - pub const TestRunnerMode = enum(u2) { default, simple, server }; + pub const ExpectErrors = union(@This().Tag) { + pub const Tag = enum(u3) { contains, exact, starts_with, stderr_contains, none }; + + contains: String, + exact: Storage.LengthPrefixedList(String), + starts_with: String, + stderr_contains: String, + none: void, + }; + pub const TestRunner = union(@This().Tag) { + pub const Tag = enum(u2) { default, simple, server }; + + default: void, + simple: LazyPath, + server: LazyPath, + }; pub const Entry = enum(u2) { default, disabled, enabled, symbol_name }; pub const Lto = enum(u2) { @@ -826,7 +838,7 @@ pub const Step = extern struct { kind: Kind, compress_debug_sections: std.zig.CompressDebugSections, global_base: bool, - test_runner_mode: TestRunnerMode, + test_runner: TestRunner.Tag, wasi_exec_model: WasiExecModel, win32_manifest: bool, win32_module_definition: bool, @@ -849,7 +861,7 @@ pub const Step = extern struct { error_limit: bool, install_name: bool, entitlements: bool, - expect_errors: ExpectErrors, + expect_errors: ExpectErrors.Tag, linker_script: bool, version_script: bool, _: u18 = 0, @@ -1756,8 +1768,10 @@ pub const Storage = enum { flag_optional, enum_optional, extended, + length_prefixed_list, flag_length_prefixed_list, union_list, + flag_union, /// The presence of the field is determined by a boolean within a packed /// struct. @@ -1776,6 +1790,24 @@ pub const Storage = enum { }; } + /// The type of the field is determined by an enum within a packed struct. + pub fn FlagUnion( + comptime flags_arg: @EnumLiteral(), + comptime flag_arg: @EnumLiteral(), + comptime UnionArg: type, + ) type { + return struct { + u: Union, + + pub const storage: Storage = .flag_union; + pub const flags = flags_arg; + pub const flag = flag_arg; + pub const Union = UnionArg; + + pub const Tag = @typeInfo(Union).@"union".tag_type.?; + }; + } + /// The field is present if an enum tag from flags matches a specific value. pub fn EnumOptional( comptime flags_arg: @EnumLiteral(), @@ -1814,21 +1846,32 @@ pub const Storage = enum { /// A field in flags determines whether the length is zero or nonzero. If the length is /// nonzero, then there is a length field followed by the list. - /// - /// When deserializing, the slice field is set. When serializing, the index - /// field must be set. pub fn FlagLengthPrefixedList( comptime flags_arg: @EnumLiteral(), comptime flag_arg: @EnumLiteral(), - comptime ValueArg: type, + comptime ElemArg: type, ) type { return struct { - slice: []const Value, + slice: []const Elem, pub const storage: Storage = .flag_length_prefixed_list; pub const flags = flags_arg; pub const flag = flag_arg; - pub const Value = ValueArg; + pub const Elem = ElemArg; + + pub fn initErased(s: []const u32) @This() { + return .{ .slice = @ptrCast(s) }; + } + }; + } + + /// The field contains a u32 length followed by that many items. + pub fn LengthPrefixedList(comptime ElemArg: type) type { + return struct { + slice: []const Elem, + + pub const storage: Storage = .length_prefixed_list; + pub const Elem = ElemArg; pub fn initErased(s: []const u32) @This() { return .{ .slice = @ptrCast(s) }; @@ -1910,6 +1953,7 @@ pub const Storage = enum { fn dataField(buffer: []const u32, i: *usize, container: anytype, comptime Field: type) Field { switch (@typeInfo(Field)) { + .void => return {}, .int => |info| switch (info.bits) { 32 => { defer i.* += 1; @@ -1954,6 +1998,24 @@ pub const Storage = enum { .value = if (flag) dataField(buffer, i, container, Field.Value) else null, }; }, + .flag_union => { + const flags = @field(container, @tagName(Field.flags)); + const tag: Field.Tag = @field(flags, @tagName(Field.flag)); + return .{ + .u = switch (tag) { + inline else => |comptime_tag| @unionInit( + Field.Union, + @tagName(comptime_tag), + dataField( + buffer, + i, + container, + @typeInfo(Field.Union).@"union".fields[@intFromEnum(comptime_tag)].type, + ), + ), + }, + }; + }, .enum_optional => { const flags = @field(container, @tagName(Field.flags)); const tag = @field(flags, @tagName(Field.flag)); @@ -1963,6 +2025,12 @@ pub const Storage = enum { }; }, .extended => @compileError("TODO"), + .length_prefixed_list => { + const data_start = i.* + 1; + const len = buffer[data_start - 1]; + defer i.* = data_start + len; + return .{ .slice = @ptrCast(buffer[data_start..][0..len]) }; + }, .flag_length_prefixed_list => { const flags = @field(container, @tagName(Field.flags)); const flag = @field(flags, @tagName(Field.flag)); @@ -2010,6 +2078,7 @@ pub const Storage = enum { fn extraFieldLen(field: anytype) usize { const Field = @TypeOf(field); return switch (@typeInfo(Field)) { + .void => 0, .int => |info| switch (info.bits) { 32 => 1, 64 => 2, @@ -2024,8 +2093,11 @@ pub const Storage = enum { }, .auto => switch (Field.storage) { .flag_optional, .enum_optional, .extended => 1, - .flag_length_prefixed_list => field.slice.len + 1, + .length_prefixed_list, .flag_length_prefixed_list => field.slice.len + 1, .union_list => Field.extraLen(field.len), + .flag_union => switch (field.u) { + inline else => |v| extraFieldLen(v), + }, }, .@"extern" => comptime unreachable, }, @@ -2044,6 +2116,7 @@ pub const Storage = enum { inline fn setExtraField(buffer: []u32, i: usize, comptime Field: type, value: anytype) usize { switch (@typeInfo(Field)) { + .void => return 0, .int => |info| switch (info.bits) { 32 => { buffer[i] = value; @@ -2081,8 +2154,11 @@ pub const Storage = enum { .flag_optional, .enum_optional => { return if (value.value) |v| setExtraField(buffer, i, Field.Value, v) else 0; }, + .flag_union => return switch (value.u) { + inline else => |x| setExtraField(buffer, i, @TypeOf(x), x), + }, .extended => @compileError("TODO"), - .flag_length_prefixed_list => { + .flag_length_prefixed_list, .length_prefixed_list => { const len: u32 = @intCast(value.slice.len); if (len == 0) return 0; buffer[i] = len;