authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-02-27 18:48:27-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-05-25 18:54:34-07:00
log4381a387bfa73c523a49d6b5c4d8ea336c7d4275
tree9dc779fffedefbb11f61ee26c8169eab7e507a7e
parentd3d3fb8473e25273ddca2e0da8d9c76cc43c794b

Configuration: complete serialization of Compile steps


4 files changed, 144 insertions(+), 44 deletions(-)

lib/compiler/Maker/ScannedConfig.zig+18-1
......@@ -85,6 +85,8 @@ fn printValue(sc: *const ScannedConfig, s: *Serializer, comptime Field: type, fi
8585 .flag_length_prefixed_list => comptime unreachable,
8686 .enum_optional => comptime unreachable,
8787 .union_list => comptime unreachable,
88 .length_prefixed_list => comptime unreachable,
89 .flag_union => comptime unreachable,
8890 } else if (std.enums.tagName(Field, field_value)) |name| {
8991 try s.ident(name);
9092 } else {
......@@ -103,14 +105,29 @@ fn printValue(sc: *const ScannedConfig, s: *Serializer, comptime Field: type, fi
103105 try s.value(null, .{});
104106 }
105107 },
106 .flag_length_prefixed_list => {
108 .length_prefixed_list, .flag_length_prefixed_list => {
107109 try printValue(sc, s, @TypeOf(field_value.slice), field_value.slice);
108110 },
109111 .extended => @compileError("TODO"),
110112 .union_list => @compileError("TODO"),
113 .flag_union => try printValue(sc, s, Field.Union, field_value.u),
111114 },
112115 else => @compileError("not implemented: " ++ @typeName(Field)),
113116 },
117 .@"union" => {
118 switch (field_value) {
119 inline else => |u, tag| {
120 if (@TypeOf(u) == void) {
121 try s.ident(@tagName(tag));
122 } else {
123 var sub_struct = try s.beginStruct(.{});
124 try sub_struct.fieldPrefix(@tagName(tag));
125 try printValue(sc, s, @TypeOf(u), u);
126 try sub_struct.end();
127 }
128 },
129 }
130 },
114131 else => @compileError("not implemented: " ++ @typeName(Field)),
115132 },
116133 }
lib/compiler/Maker/Step/Compile.zig+23-24
......@@ -134,21 +134,20 @@ fn lowerZigArgs(
134134 },
135135 }
136136
137 if (true) @panic("TODO");
138
139 {
140 for (compile.force_undefined_symbols.keys()) |symbol_name| {
141 try zig_args.append(gpa, "--force_undefined");
142 try zig_args.append(gpa, symbol_name.*);
143 }
137 for (conf_comp.force_undefined_symbols.slice) |symbol_name| {
138 try zig_args.appendSlice(gpa, &.{ "--force_undefined", symbol_name.slice(conf) });
144139 }
145140
146 if (compile.stack_size) |stack_size| {
147 try zig_args.append(gpa, "--stack");
148 try zig_args.append(gpa, try allocPrint(arena, "{}", .{stack_size}));
141 if (conf_comp.stack_size.value) |stack_size| {
142 try zig_args.appendSlice(gpa, &.{ "--stack", try allocPrint(arena, "{d}", .{stack_size}) });
149143 }
150144
151 try addBool(gpa, zig_args, fuzz, "-ffuzz");
145 try addBool(gpa, zig_args, "-ffuzz", fuzz);
146
147 if (true) @panic("TODO");
148
149 var is_linking_libc = conf_comp.flags3.is_linking_libc;
150 var is_linking_libcpp = conf_comp.flags3.is_linking_libcpp;
152151
153152 {
154153 // Stores system libraries that have already been seen for at least one
......@@ -163,14 +162,14 @@ fn lowerZigArgs(
163162 var prev_preferred_link_mode: std.builtin.LinkMode = .dynamic;
164163 // Track the number of positional arguments so that a nice error can be
165164 // emitted if there is nothing to link.
166 var total_linker_objects: usize = @intFromBool(compile.root_module.root_source_file != null);
165 var total_linker_objects: usize = @intFromBool(root_module.root_source_file != .none);
167166
168167 // Fully recursive iteration including dynamic libraries to detect
169168 // libc and libc++ linkage.
170169 for (getCompileDependencies(true)) |some_compile| {
171170 for (some_compile.root_module.getGraph().modules) |mod| {
172 if (mod.link_libc == true) compile.is_linking_libc = true;
173 if (mod.link_libcpp == true) compile.is_linking_libcpp = true;
171 if (mod.link_libc == true) is_linking_libc = true;
172 if (mod.link_libcpp == true) is_linking_libcpp = true;
174173 }
175174 }
176175
......@@ -465,11 +464,11 @@ fn lowerZigArgs(
465464 try zig_args.append(gpa, name);
466465 }
467466
468 if (compile.is_linking_libcpp) {
467 if (is_linking_libcpp) {
469468 try zig_args.append(gpa, "-lc++");
470469 }
471470
472 if (compile.is_linking_libc) {
471 if (is_linking_libc) {
473472 try zig_args.append(gpa, "-lc");
474473 }
475474 }
......@@ -500,14 +499,14 @@ fn lowerZigArgs(
500499 try zig_args.appendSlice(gpa, &.{ "--debug-log", log_scope });
501500 }
502501
503 try addBool(gpa, zig_args, graph.debug_compile_errors, "--debug-compile-errors");
504 try addBool(gpa, zig_args, graph.debug_incremental, "--debug-incremental");
505 try addBool(gpa, zig_args, graph.verbose_air, "--verbose-air");
506 try addBool(gpa, zig_args, graph.verbose_llvm_ir, "--verbose-llvm-ir");
507 try addBool(gpa, zig_args, graph.verbose_link or compile.verbose_link, "--verbose-link");
508 try addBool(gpa, zig_args, graph.verbose_cc or compile.verbose_cc, "--verbose-cc");
509 try addBool(gpa, zig_args, graph.verbose_llvm_cpu_features, "--verbose-llvm-cpu-features");
510 try addBool(gpa, zig_args, graph.time_report, "--time-report");
502 try addBool(gpa, zig_args, "--debug-compile-errors", graph.debug_compile_errors);
503 try addBool(gpa, zig_args, "--debug-incremental", graph.debug_incremental);
504 try addBool(gpa, zig_args, "--verbose-air", graph.verbose_air);
505 try addBool(gpa, zig_args, "--verbose-llvm-ir", graph.verbose_llvm_ir);
506 try addBool(gpa, zig_args, "--verbose-link", graph.verbose_link or compile.verbose_link);
507 try addBool(gpa, zig_args, "--verbose-cc", graph.verbose_cc or compile.verbose_cc);
508 try addBool(gpa, zig_args, "--verbose-llvm-cpu-features", graph.verbose_llvm_cpu_features);
509 try addBool(gpa, zig_args, "--time-report", graph.time_report);
511510
512511 if (compile.generated_asm != null) try zig_args.append(gpa, "-femit-asm");
513512 if (compile.generated_bin == null) try zig_args.append(gpa, "-fno-emit-bin");
lib/compiler/configurer.zig+11-3
......@@ -606,7 +606,7 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
606606 .max_memory = c.max_memory != null,
607607 .kind = c.kind,
608608 .global_base = c.global_base != null,
609 .test_runner_mode = if (c.test_runner) |tr| switch (tr.mode) {
609 .test_runner = if (c.test_runner) |tr| switch (tr.mode) {
610610 .simple => .simple,
611611 .server => .server,
612612 } else .default,
......@@ -678,10 +678,18 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
678678 .exec_cmd_args = .{ .slice = try s.initOptionalStringList(exec_cmd_args) },
679679 .installed_headers = .initErased(installed_headers),
680680 .force_undefined_symbols = .{ .slice = try s.initStringList(c.force_undefined_symbols.keys()) },
681 .expect_errors = .{ .u = if (c.expect_errors) |x| switch (x) {
682 .contains => |slice| .{ .contains = try wc.addString(slice) },
683 .exact => |exact| .{ .exact = .{ .slice = try s.initStringList(exact) } },
684 .starts_with => |slice| .{ .starts_with = try wc.addString(slice) },
685 .stderr_contains => |slice| .{ .stderr_contains = try wc.addString(slice) },
686 } else .none },
687 .test_runner = .{ .u = if (c.test_runner) |tr| switch (tr.mode) {
688 .simple => .{ .simple = try s.addLazyPath(tr.path) },
689 .server => .{ .server = try s.addLazyPath(tr.path) },
690 } else .default },
681691 }));
682692
683 log.err("TODO serialize the trailing Compile step data", .{});
684
685693 break :e @enumFromInt(extra_index);
686694 },
687695 .install_artifact => e: {
lib/std/zig/Configuration.zig+92-16
......@@ -584,9 +584,6 @@ pub const Step = extern struct {
584584 };
585585 };
586586
587 /// Trailing:
588 /// * exact_match: String, // if expect_errors is contains, starts_with, or stderr_contains
589 /// * test_runner: LazyPath, // if test_runner_mode is not default
590587 pub const Compile = struct {
591588 flags: @This().Flags,
592589 flags2: Flags2,
......@@ -600,7 +597,7 @@ pub const Step = extern struct {
600597 exec_cmd_args: Storage.FlagLengthPrefixedList(.flags, .exec_cmd_args_len, OptionalString),
601598 installed_headers: Storage.FlagLengthPrefixedList(.flags, .installed_headers_len, Storage.Extended(InstalledHeader.Flags, InstalledHeader)),
602599 force_undefined_symbols: Storage.FlagLengthPrefixedList(.flags, .force_undefined_symbols_len, String),
603 //exacts: EnumConditionalPrefixedList(.flags4, .expect_errors, .exact, String),
600 expect_errors: Storage.FlagUnion(.flags4, .expect_errors, ExpectErrors),
604601 linker_script: Storage.FlagOptional(.flags4, .linker_script, LazyPath),
605602 version_script: Storage.FlagOptional(.flags4, .version_script, LazyPath),
606603 zig_lib_dir: Storage.FlagOptional(.flags3, .zig_lib_dir, LazyPath),
......@@ -622,6 +619,7 @@ pub const Step = extern struct {
622619 headerpad_size: Storage.FlagOptional(.flags4, .headerpad_size, u32),
623620 error_limit: Storage.FlagOptional(.flags4, .error_limit, u32),
624621 build_id: Storage.EnumOptional(.flags3, .build_id, .hexstring, String),
622 test_runner: Storage.FlagUnion(.flags3, .test_runner, TestRunner),
625623
626624 pub const InstalledHeader = union(@This().Tag) {
627625 file: File,
......@@ -663,8 +661,22 @@ pub const Step = extern struct {
663661 };
664662 };
665663 };
666 pub const ExpectErrors = enum(u3) { contains, exact, starts_with, stderr_contains, none };
667 pub const TestRunnerMode = enum(u2) { default, simple, server };
664 pub const ExpectErrors = union(@This().Tag) {
665 pub const Tag = enum(u3) { contains, exact, starts_with, stderr_contains, none };
666
667 contains: String,
668 exact: Storage.LengthPrefixedList(String),
669 starts_with: String,
670 stderr_contains: String,
671 none: void,
672 };
673 pub const TestRunner = union(@This().Tag) {
674 pub const Tag = enum(u2) { default, simple, server };
675
676 default: void,
677 simple: LazyPath,
678 server: LazyPath,
679 };
668680 pub const Entry = enum(u2) { default, disabled, enabled, symbol_name };
669681
670682 pub const Lto = enum(u2) {
......@@ -826,7 +838,7 @@ pub const Step = extern struct {
826838 kind: Kind,
827839 compress_debug_sections: std.zig.CompressDebugSections,
828840 global_base: bool,
829 test_runner_mode: TestRunnerMode,
841 test_runner: TestRunner.Tag,
830842 wasi_exec_model: WasiExecModel,
831843 win32_manifest: bool,
832844 win32_module_definition: bool,
......@@ -849,7 +861,7 @@ pub const Step = extern struct {
849861 error_limit: bool,
850862 install_name: bool,
851863 entitlements: bool,
852 expect_errors: ExpectErrors,
864 expect_errors: ExpectErrors.Tag,
853865 linker_script: bool,
854866 version_script: bool,
855867 _: u18 = 0,
......@@ -1756,8 +1768,10 @@ pub const Storage = enum {
17561768 flag_optional,
17571769 enum_optional,
17581770 extended,
1771 length_prefixed_list,
17591772 flag_length_prefixed_list,
17601773 union_list,
1774 flag_union,
17611775
17621776 /// The presence of the field is determined by a boolean within a packed
17631777 /// struct.
......@@ -1776,6 +1790,24 @@ pub const Storage = enum {
17761790 };
17771791 }
17781792
1793 /// The type of the field is determined by an enum within a packed struct.
1794 pub fn FlagUnion(
1795 comptime flags_arg: @EnumLiteral(),
1796 comptime flag_arg: @EnumLiteral(),
1797 comptime UnionArg: type,
1798 ) type {
1799 return struct {
1800 u: Union,
1801
1802 pub const storage: Storage = .flag_union;
1803 pub const flags = flags_arg;
1804 pub const flag = flag_arg;
1805 pub const Union = UnionArg;
1806
1807 pub const Tag = @typeInfo(Union).@"union".tag_type.?;
1808 };
1809 }
1810
17791811 /// The field is present if an enum tag from flags matches a specific value.
17801812 pub fn EnumOptional(
17811813 comptime flags_arg: @EnumLiteral(),
......@@ -1814,21 +1846,32 @@ pub const Storage = enum {
18141846
18151847 /// A field in flags determines whether the length is zero or nonzero. If the length is
18161848 /// nonzero, then there is a length field followed by the list.
1817 ///
1818 /// When deserializing, the slice field is set. When serializing, the index
1819 /// field must be set.
18201849 pub fn FlagLengthPrefixedList(
18211850 comptime flags_arg: @EnumLiteral(),
18221851 comptime flag_arg: @EnumLiteral(),
1823 comptime ValueArg: type,
1852 comptime ElemArg: type,
18241853 ) type {
18251854 return struct {
1826 slice: []const Value,
1855 slice: []const Elem,
18271856
18281857 pub const storage: Storage = .flag_length_prefixed_list;
18291858 pub const flags = flags_arg;
18301859 pub const flag = flag_arg;
1831 pub const Value = ValueArg;
1860 pub const Elem = ElemArg;
1861
1862 pub fn initErased(s: []const u32) @This() {
1863 return .{ .slice = @ptrCast(s) };
1864 }
1865 };
1866 }
1867
1868 /// The field contains a u32 length followed by that many items.
1869 pub fn LengthPrefixedList(comptime ElemArg: type) type {
1870 return struct {
1871 slice: []const Elem,
1872
1873 pub const storage: Storage = .length_prefixed_list;
1874 pub const Elem = ElemArg;
18321875
18331876 pub fn initErased(s: []const u32) @This() {
18341877 return .{ .slice = @ptrCast(s) };
......@@ -1910,6 +1953,7 @@ pub const Storage = enum {
19101953
19111954 fn dataField(buffer: []const u32, i: *usize, container: anytype, comptime Field: type) Field {
19121955 switch (@typeInfo(Field)) {
1956 .void => return {},
19131957 .int => |info| switch (info.bits) {
19141958 32 => {
19151959 defer i.* += 1;
......@@ -1954,6 +1998,24 @@ pub const Storage = enum {
19541998 .value = if (flag) dataField(buffer, i, container, Field.Value) else null,
19551999 };
19562000 },
2001 .flag_union => {
2002 const flags = @field(container, @tagName(Field.flags));
2003 const tag: Field.Tag = @field(flags, @tagName(Field.flag));
2004 return .{
2005 .u = switch (tag) {
2006 inline else => |comptime_tag| @unionInit(
2007 Field.Union,
2008 @tagName(comptime_tag),
2009 dataField(
2010 buffer,
2011 i,
2012 container,
2013 @typeInfo(Field.Union).@"union".fields[@intFromEnum(comptime_tag)].type,
2014 ),
2015 ),
2016 },
2017 };
2018 },
19572019 .enum_optional => {
19582020 const flags = @field(container, @tagName(Field.flags));
19592021 const tag = @field(flags, @tagName(Field.flag));
......@@ -1963,6 +2025,12 @@ pub const Storage = enum {
19632025 };
19642026 },
19652027 .extended => @compileError("TODO"),
2028 .length_prefixed_list => {
2029 const data_start = i.* + 1;
2030 const len = buffer[data_start - 1];
2031 defer i.* = data_start + len;
2032 return .{ .slice = @ptrCast(buffer[data_start..][0..len]) };
2033 },
19662034 .flag_length_prefixed_list => {
19672035 const flags = @field(container, @tagName(Field.flags));
19682036 const flag = @field(flags, @tagName(Field.flag));
......@@ -2010,6 +2078,7 @@ pub const Storage = enum {
20102078 fn extraFieldLen(field: anytype) usize {
20112079 const Field = @TypeOf(field);
20122080 return switch (@typeInfo(Field)) {
2081 .void => 0,
20132082 .int => |info| switch (info.bits) {
20142083 32 => 1,
20152084 64 => 2,
......@@ -2024,8 +2093,11 @@ pub const Storage = enum {
20242093 },
20252094 .auto => switch (Field.storage) {
20262095 .flag_optional, .enum_optional, .extended => 1,
2027 .flag_length_prefixed_list => field.slice.len + 1,
2096 .length_prefixed_list, .flag_length_prefixed_list => field.slice.len + 1,
20282097 .union_list => Field.extraLen(field.len),
2098 .flag_union => switch (field.u) {
2099 inline else => |v| extraFieldLen(v),
2100 },
20292101 },
20302102 .@"extern" => comptime unreachable,
20312103 },
......@@ -2044,6 +2116,7 @@ pub const Storage = enum {
20442116
20452117 inline fn setExtraField(buffer: []u32, i: usize, comptime Field: type, value: anytype) usize {
20462118 switch (@typeInfo(Field)) {
2119 .void => return 0,
20472120 .int => |info| switch (info.bits) {
20482121 32 => {
20492122 buffer[i] = value;
......@@ -2081,8 +2154,11 @@ pub const Storage = enum {
20812154 .flag_optional, .enum_optional => {
20822155 return if (value.value) |v| setExtraField(buffer, i, Field.Value, v) else 0;
20832156 },
2157 .flag_union => return switch (value.u) {
2158 inline else => |x| setExtraField(buffer, i, @TypeOf(x), x),
2159 },
20842160 .extended => @compileError("TODO"),
2085 .flag_length_prefixed_list => {
2161 .flag_length_prefixed_list, .length_prefixed_list => {
20862162 const len: u32 = @intCast(value.slice.len);
20872163 if (len == 0) return 0;
20882164 buffer[i] = len;