authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-02-19 18:35:53-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-05-25 18:54:34-07:00
log612560d0198ab9a6b471e36770eb3718ccc5b57f
treebb452147295f247401c9f9378f6c0862b916aab2
parent74b018ceb3822e0810ddfe434605bee69aba8b73

std.Build.Configure: implement FlagOptional serialization


3 files changed, 308 insertions(+), 132 deletions(-)

lib/compiler/configure_runner.zig+47-9
......@@ -239,7 +239,7 @@ const Serialize = struct {
239239 return gop.value_ptr.*;
240240 }
241241
242 fn addOptionalLazyPath(s: *Serialize, lp: ?std.Build.LazyPath) !Configuration.OptionalLazyPath {
242 fn addOptionalLazyPathEnum(s: *Serialize, lp: ?std.Build.LazyPath) !Configuration.OptionalLazyPath {
243243 const wc = s.wc;
244244 return @enumFromInt(switch (lp orelse return .none) {
245245 .src_path => |src_path| i: {
......@@ -274,6 +274,18 @@ const Serialize = struct {
274274 },
275275 });
276276 }
277
278 fn addOptionalLazyPath(s: *Serialize, lp: ?std.Build.LazyPath) !?Configuration.LazyPath {
279 return (try addOptionalLazyPathEnum(s, lp)).unwrap();
280 }
281
282 fn addOptionalSemVer(s: *Serialize, sem_ver: ?std.SemanticVersion) !?Configuration.String {
283 return if (sem_ver) |sv| try s.wc.addSemVer(sv) else null;
284 }
285
286 fn addOptionalString(s: *Serialize, opt_slice: ?[]const u8) !?Configuration.String {
287 return if (opt_slice) |slice| try s.wc.addString(slice) else null;
288 }
277289};
278290
279291fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
......@@ -416,9 +428,36 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
416428 .error_limit = c.error_limit != null,
417429 .install_name = c.install_name != null,
418430 .entitlements = c.entitlements != null,
431 .expect_errors = if (c.expect_errors) |x| switch (x) {
432 .contains => .contains,
433 .exact => .exact,
434 .starts_with => .starts_with,
435 .stderr_contains => .stderr_contains,
436 } else .none,
437 .linker_script = c.linker_script != null,
438 .version_script = c.version_script != null,
419439 },
420440 .root_module = try addModule(&s, c.root_module),
421441 .root_name = try wc.addString(c.name),
442 .linker_script = .{ .value = try s.addOptionalLazyPath(c.linker_script) },
443 .version_script = .{ .value = try s.addOptionalLazyPath(c.version_script) },
444 .zig_lib_dir = .{ .value = try s.addOptionalLazyPath(c.zig_lib_dir) },
445 .libc_file = .{ .value = try s.addOptionalLazyPath(c.libc_file) },
446 .win32_manifest = .{ .value = try s.addOptionalLazyPath(c.win32_manifest) },
447 .win32_module_definition = .{ .value = try s.addOptionalLazyPath(c.win32_module_definition) },
448 .entitlements = .{ .value = try s.addOptionalLazyPath(c.entitlements) },
449 .version = .{ .value = try s.addOptionalSemVer(c.version) },
450 .install_name = .{ .value = try s.addOptionalString(c.install_name) },
451 .initial_memory = .{ .value = c.initial_memory },
452 .max_memory = .{ .value = c.max_memory },
453 .global_base = .{ .value = c.global_base },
454 .image_base = .{ .value = c.image_base },
455 .link_z_common_page_size = .{ .value = c.link_z_common_page_size },
456 .link_z_max_page_size = .{ .value = c.link_z_max_page_size },
457 .pagezero_size = .{ .value = c.pagezero_size },
458 .stack_size = .{ .value = c.stack_size },
459 .headerpad_size = .{ .value = c.headerpad_size },
460 .error_limit = .{ .value = c.error_limit },
422461 }));
423462
424463 log.err("TODO serialize the trailing Compile step data", .{});
......@@ -433,13 +472,13 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
433472 },
434473 .dest_dir = try addInstallDir(wc, ia.dest_dir),
435474 .dest_sub_path = try wc.addString(ia.dest_sub_path),
436 .emitted_bin = try s.addOptionalLazyPath(ia.emitted_bin),
475 .emitted_bin = try s.addOptionalLazyPathEnum(ia.emitted_bin),
437476 .implib_dir = try addInstallDir(wc, ia.implib_dir),
438 .emitted_implib = try s.addOptionalLazyPath(ia.emitted_implib),
477 .emitted_implib = try s.addOptionalLazyPathEnum(ia.emitted_implib),
439478 .pdb_dir = try addInstallDir(wc, ia.pdb_dir),
440 .emitted_pdb = try s.addOptionalLazyPath(ia.emitted_pdb),
479 .emitted_pdb = try s.addOptionalLazyPathEnum(ia.emitted_pdb),
441480 .h_dir = try addInstallDir(wc, ia.h_dir),
442 .emitted_h = try s.addOptionalLazyPath(ia.emitted_h),
481 .emitted_h = try s.addOptionalLazyPathEnum(ia.emitted_h),
443482 .artifact = stepIndex(&step_map, &ia.artifact.step),
444483 }));
445484 },
......@@ -490,7 +529,7 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
490529 },
491530 .file_inputs_len = @intCast(run.file_inputs.items.len),
492531 .args_len = @intCast(run.argv.items.len),
493 .cwd = try s.addOptionalLazyPath(run.cwd),
532 .cwd = try s.addOptionalLazyPathEnum(run.cwd),
494533 .captured_stdout = captured_stdout,
495534 .captured_stderr = captured_stderr,
496535 }));
......@@ -565,8 +604,7 @@ fn addModule(s: *Serialize, m: *std.Build.Module) !Configuration.Module.Index {
565604 .frameworks = m.frameworks.entries.len != 0,
566605 .link_objects = m.link_objects.items.len != 0,
567606 .export_symbol_names = m.export_symbol_names.len != 0,
568 },
569 .flags2 = .{
607
570608 .valgrind = .init(m.strip),
571609 .pic = .init(m.strip),
572610 .red_zone = .init(m.strip),
......@@ -577,7 +615,7 @@ fn addModule(s: *Serialize, m: *std.Build.Module) !Configuration.Module.Index {
577615 .no_builtin = .init(m.strip),
578616 },
579617 .owner = try s.builderToPackage(m.owner),
580 .root_source_file = try s.addOptionalLazyPath(m.root_source_file),
618 .root_source_file = try s.addOptionalLazyPathEnum(m.root_source_file),
581619 .import_table = import_table,
582620 .resolved_target = try addOptionalResolvedTarget(wc, m.resolved_target),
583621 })));
lib/std/Build/Step/Compile.zig+9-2
......@@ -145,8 +145,8 @@ link_z_defs: bool = false,
145145/// (Darwin) Install name for the dylib
146146install_name: ?[]const u8 = null,
147147
148/// (Darwin) Path to entitlements file
149entitlements: ?[]const u8 = null,
148/// Must be passed in via `Options`.
149entitlements: ?LazyPath = null,
150150
151151/// (Darwin) Size of the pagezero segment.
152152pagezero_size: ?u64 = null,
......@@ -286,6 +286,8 @@ pub const Options = struct {
286286 win32_manifest: ?LazyPath = null,
287287 /// Win32 module definition file.
288288 win32_module_definition: ?LazyPath = null,
289 /// (Darwin) Path to entitlements file
290 entitlements: ?LazyPath = null,
289291};
290292
291293pub const Kind = std.Build.Configuration.Step.Compile.Kind;
......@@ -462,6 +464,11 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
462464 }
463465 }
464466
467 if (options.entitlements) |lp| {
468 compile.entitlements = lp.dupe(compile.step.owner);
469 lp.addStepDependencies(&compile.step);
470 }
471
465472 if (compile.kind == .lib) {
466473 if (compile.linkage != null and compile.linkage.? == .static) {
467474 compile.out_lib_filename = compile.out_filename;
lib/std/zig/Configuration.zig+252-121
......@@ -205,9 +205,7 @@ pub const Wip = struct {
205205 null;
206206 const cpu_features_add_empty = q.cpu_features_add.isEmpty();
207207 const cpu_features_sub_empty = q.cpu_features_sub.isEmpty();
208 try wip.extra.ensureUnusedCapacity(gpa, @typeInfo(TargetQuery).@"struct".fields.len + 6 +
209 2 * ((@sizeOf(std.Target.Cpu.Feature.Set) + 3) / 4));
210 const result_index: TargetQuery.Index = @enumFromInt(wip.addExtraAssumeCapacity(@as(TargetQuery, .{
208 const result_index: TargetQuery.Index = @enumFromInt(try wip.addExtra(@as(TargetQuery, .{
211209 .flags = .{
212210 .cpu_arch = .init(q.cpu_arch),
213211 .cpu_model = .init(q.cpu_model),
......@@ -218,19 +216,20 @@ pub const Wip = struct {
218216 .object_format = .init(q.ofmt),
219217 .os_version_min = .init(q.os_version_min),
220218 .os_version_max = .init(q.os_version_max),
221 .glibc_version = q.glibc_version != null,
219 .glibc_version = glibc_version != null,
222220 .android_api_level = q.android_api_level != null,
223 .dynamic_linker = q.dynamic_linker != null,
221 .dynamic_linker = dynamic_linker != null,
224222 },
223 .cpu_features_add = .{ .value = if (cpu_features_add_empty) null else q.cpu_features_add },
224 .cpu_features_sub = .{ .value = if (cpu_features_sub_empty) null else q.cpu_features_sub },
225 .glibc_version = .{ .value = glibc_version },
226 .android_api_level = .{ .value = q.android_api_level },
227 .dynamic_linker = .{ .value = dynamic_linker },
225228 })));
226 if (!cpu_features_add_empty) wip.extra.appendSliceAssumeCapacity(@ptrCast(&q.cpu_features_add.ints));
227 if (!cpu_features_sub_empty) wip.extra.appendSliceAssumeCapacity(@ptrCast(&q.cpu_features_sub.ints));
228 wip.addExtraOptionalStringAssumeCapacity(cpu_name);
229 if (os_version_min) |v| wip.extra.appendAssumeCapacity(v);
230 if (os_version_max) |v| wip.extra.appendAssumeCapacity(v);
231 wip.addExtraOptionalStringAssumeCapacity(glibc_version);
232 if (q.android_api_level) |x| wip.extra.appendAssumeCapacity(x);
233 wip.addExtraOptionalStringAssumeCapacity(dynamic_linker);
229 std.log.err("TODO serialize more target query stuff", .{});
230 _ = os_version_min;
231 _ = os_version_max;
232 _ = cpu_name;
234233
235234 // Deduplicate.
236235 const gop = try wip.targets_table.getOrPutContext(gpa, result_index, @as(TargetsTableContext, .{
......@@ -287,9 +286,7 @@ pub const Wip = struct {
287286 .semver, .linux, .hurd => .semver,
288287 .windows => .windows,
289288 };
290 try wip.extra.ensureUnusedCapacity(gpa, @typeInfo(TargetQuery).@"struct".fields.len + 6 +
291 2 * ((@sizeOf(std.Target.Cpu.Feature.Set) + 3) / 4));
292 const result_index: TargetQuery.Index = @enumFromInt(wip.addExtraAssumeCapacity(@as(TargetQuery, .{
289 const result_index: TargetQuery.Index = @enumFromInt(try wip.addExtra(@as(TargetQuery, .{
293290 .flags = .{
294291 .cpu_arch = .init(t.cpu.arch),
295292 .cpu_model = .explicit,
......@@ -304,14 +301,16 @@ pub const Wip = struct {
304301 .android_api_level = android_api_level != null,
305302 .dynamic_linker = dynamic_linker != null,
306303 },
304 .cpu_features_add = .{ .value = if (cpu_features_add_empty) null else t.cpu.features },
305 .cpu_features_sub = .{ .value = null },
306 .glibc_version = .{ .value = glibc_version },
307 .android_api_level = .{ .value = android_api_level },
308 .dynamic_linker = .{ .value = dynamic_linker },
307309 })));
308 if (!cpu_features_add_empty) wip.extra.appendSliceAssumeCapacity(@ptrCast(&t.cpu.features.ints));
309 wip.addExtraOptionalStringAssumeCapacity(cpu_name);
310 if (os_version_min) |v| wip.extra.appendAssumeCapacity(v);
311 if (os_version_max) |v| wip.extra.appendAssumeCapacity(v);
312 wip.addExtraOptionalStringAssumeCapacity(glibc_version);
313 if (android_api_level) |x| wip.extra.appendAssumeCapacity(x);
314 wip.addExtraOptionalStringAssumeCapacity(dynamic_linker);
310 std.log.err("TODO serialize more target stuff", .{});
311 _ = cpu_name;
312 _ = os_version_min;
313 _ = os_version_max;
315314
316315 // Deduplicate.
317316 const gop = try wip.targets_table.getOrPutContext(gpa, result_index, @as(TargetsTableContext, .{
......@@ -345,17 +344,14 @@ pub const Wip = struct {
345344 }
346345
347346 pub fn addExtra(wip: *Wip, extra: anytype) Allocator.Error!u32 {
348 const gpa = wip.gpa;
349 const fields = @typeInfo(@TypeOf(extra)).@"struct".fields;
350 try wip.extra.ensureUnusedCapacity(gpa, fields.len);
347 const extra_len = Storage.calculateExtraLenUpperBound(@TypeOf(extra));
348 try wip.extra.ensureUnusedCapacity(wip.gpa, extra_len);
351349 return addExtraAssumeCapacity(wip, extra);
352350 }
353351
354352 pub fn addExtraAssumeCapacity(wip: *Wip, extra: anytype) u32 {
355 const fields = @typeInfo(@TypeOf(extra)).@"struct".fields;
356353 const result: u32 = @intCast(wip.extra.items.len);
357 wip.extra.items.len += fields.len;
358 setExtra(wip, result, extra);
354 wip.extra.items.len = Storage.setExtra(wip.extra.allocatedSlice(), result, extra);
359355 return result;
360356 }
361357
......@@ -363,21 +359,6 @@ pub const Wip = struct {
363359 const string = optional_string orelse return;
364360 wip.extra.appendAssumeCapacity(@intFromEnum(string));
365361 }
366
367 fn setExtra(wip: *Wip, index: usize, extra: anytype) void {
368 const fields = @typeInfo(@TypeOf(extra)).@"struct".fields;
369 var i = index;
370 inline for (fields) |field| {
371 comptime assert(@sizeOf(field.type) == @sizeOf(u32));
372 wip.extra.items[i] = switch (@typeInfo(field.type)) {
373 .int => @field(extra, field.name),
374 .@"enum" => @intFromEnum(@field(extra, field.name)),
375 .@"struct" => @bitCast(@field(extra, field.name)),
376 else => @compileError("bad field type: " ++ @typeName(field.type)),
377 };
378 i += 1;
379 }
380 }
381362};
382363
383364pub const SystemIntegration = extern struct {
......@@ -577,7 +558,7 @@ pub const Step = extern struct {
577558 };
578559
579560 /// Trailing:
580 /// * exact_match: String, // if expected_compile_errors is contains, starts_with, or stderr_contains
561 /// * exact_match: String, // if expect_errors is contains, starts_with, or stderr_contains
581562 /// * test_runner: LazyPath, // if test_runner_mode is not default
582563 pub const Compile = struct {
583564 flags: @This().Flags,
......@@ -588,36 +569,34 @@ pub const Step = extern struct {
588569 root_module: Module.Index,
589570 root_name: String,
590571
591 trailing: Trailing(struct {
592 filters: FlagLengthPrefixedList(.flags, .filters_len, String),
593 exec_cmd_args: FlagLengthPrefixedList(.flags, .exec_cmd_args_len, u32),
594 installed_headers: FlagLengthPrefixedList(.flags, .installed_headers_len, InstalledHeader),
595 force_undefined_symbols: FlagLengthPrefixedList(.flags, .force_undefined_symbols_len, String),
596 exacts: EnumConditionalPrefixedList(.flags4, .expected_compile_errors, .exact, String),
597 linker_script: FlagOptional(.flags4, .linker_script, LazyPath),
598 version_script: FlagOptional(.flags4, .version_script, LazyPath),
599 zig_lib_dir: FlagOptional(.flags3, .zig_lib_dir, LazyPath),
600 libc_file: FlagOptional(.flags4, .libc_file, LazyPath),
601 win32_manifest: FlagOptional(.flags3, .win32_manifest, LazyPath),
602 win32_module_definition: FlagOptional(.flags3, .win32_module_definition, LazyPath),
603 entitlements: FlagOptional(.flags4, .entitlements, LazyPath),
604 version: FlagOptional(.flags3, .version, String), // semantic version string
605 entry: EnumOptional(.flags3, .entry, .symbol, String),
606 install_name: FlagOptional(.flags4, .install_name, String),
607 initial_memory: FlagOptional(.flags3, .initial_memory, u64),
608 max_memory: FlagOptional(.flags3, .max_memory, u64),
609 global_base: FlagOptional(.flags3, .global_base, u64),
610 image_base: FlagOptional(.flags3, .image_base, u64),
611 link_z_common_page_size: FlagOptional(.flags4, .link_z_common_page_size, u64),
612 link_z_max_page_size: FlagOptional(.flags4, .link_z_max_page_size, u64),
613 pagezero_size: FlagOptional(.flags4, .pagezero_size, u64),
614 stack_size: FlagOptional(.flags4, .stack_size, u64),
615 headerpad_size: FlagOptional(.flags4, .headerpad_size, u32),
616 error_limit: FlagOptional(.flags4, .error_limit, u32),
617 build_id: EnumOptional(.flags3, .build_id, .hexstring, Hexstring),
618 }),
619
620 pub const ExpectedCompileErrors = enum(u3) { contains, exact, starts_with, stderr_contains, none };
572 //filters: FlagLengthPrefixedList(.flags, .filters_len, String),
573 //exec_cmd_args: FlagLengthPrefixedList(.flags, .exec_cmd_args_len, u32),
574 //installed_headers: FlagLengthPrefixedList(.flags, .installed_headers_len, InstalledHeader),
575 //force_undefined_symbols: FlagLengthPrefixedList(.flags, .force_undefined_symbols_len, String),
576 //exacts: EnumConditionalPrefixedList(.flags4, .expect_errors, .exact, String),
577 linker_script: Storage.FlagOptional(.flags4, .linker_script, LazyPath),
578 version_script: Storage.FlagOptional(.flags4, .version_script, LazyPath),
579 zig_lib_dir: Storage.FlagOptional(.flags3, .zig_lib_dir, LazyPath),
580 libc_file: Storage.FlagOptional(.flags4, .libc_file, LazyPath),
581 win32_manifest: Storage.FlagOptional(.flags3, .win32_manifest, LazyPath),
582 win32_module_definition: Storage.FlagOptional(.flags3, .win32_module_definition, LazyPath),
583 entitlements: Storage.FlagOptional(.flags4, .entitlements, LazyPath),
584 version: Storage.FlagOptional(.flags3, .version, String), // semantic version string
585 //entry: EnumOptional(.flags3, .entry, .symbol, String),
586 install_name: Storage.FlagOptional(.flags4, .install_name, String),
587 initial_memory: Storage.FlagOptional(.flags3, .initial_memory, u64),
588 max_memory: Storage.FlagOptional(.flags3, .max_memory, u64),
589 global_base: Storage.FlagOptional(.flags3, .global_base, u64),
590 image_base: Storage.FlagOptional(.flags3, .image_base, u64),
591 link_z_common_page_size: Storage.FlagOptional(.flags4, .link_z_common_page_size, u64),
592 link_z_max_page_size: Storage.FlagOptional(.flags4, .link_z_max_page_size, u64),
593 pagezero_size: Storage.FlagOptional(.flags4, .pagezero_size, u64),
594 stack_size: Storage.FlagOptional(.flags4, .stack_size, u64),
595 headerpad_size: Storage.FlagOptional(.flags4, .headerpad_size, u32),
596 error_limit: Storage.FlagOptional(.flags4, .error_limit, u32),
597 //build_id: EnumOptional(.flags3, .build_id, .hexstring, Hexstring),
598
599 pub const ExpectErrors = enum(u3) { contains, exact, starts_with, stderr_contains, none };
621600 pub const TestRunnerMode = enum(u2) { default, simple, server };
622601 pub const Entry = enum(u2) { default, disabled, enabled, symbol_name };
623602
......@@ -803,7 +782,7 @@ pub const Step = extern struct {
803782 error_limit: bool,
804783 install_name: bool,
805784 entitlements: bool,
806 expected_compile_errors: ExpectedCompileErrors,
785 expect_errors: ExpectErrors,
807786 linker_script: bool,
808787 version_script: bool,
809788 _: u18 = 0,
......@@ -833,6 +812,13 @@ pub const MaxRss = enum(u32) {
833812pub const OptionalLazyPath = enum(u32) {
834813 none = maxInt(u32),
835814 _,
815
816 pub fn unwrap(this: @This()) ?LazyPath {
817 return switch (this) {
818 .none => null,
819 else => @enumFromInt(@intFromEnum(this)),
820 };
821 }
836822};
837823
838824/// An index into `extra`.
......@@ -909,7 +895,6 @@ pub const Package = struct {
909895/// * link_objects: UnionList(LinkObject), // if flag is set
910896pub const Module = struct {
911897 flags: Flags,
912 flags2: Flags2,
913898 owner: Package.Index,
914899 root_source_file: OptionalLazyPath,
915900 import_table: ImportTable,
......@@ -979,7 +964,7 @@ pub const Module = struct {
979964 _,
980965 };
981966
982 pub const Flags = packed struct(u32) {
967 pub const Flags = packed struct(u64) {
983968 optimize: Optimize,
984969 strip: DefaultingBool,
985970 unwind_tables: UnwindTables,
......@@ -998,9 +983,7 @@ pub const Module = struct {
998983 frameworks: bool,
999984 link_objects: bool,
1000985 export_symbol_names: bool,
1001 };
1002986
1003 pub const Flags2 = packed struct(u32) {
1004987 valgrind: DefaultingBool,
1005988 pic: DefaultingBool,
1006989 red_zone: DefaultingBool,
......@@ -1257,20 +1240,20 @@ pub const ResolvedTarget = struct {
12571240 };
12581241};
12591242
1260/// Trailing:
1261/// * cpu_features_add: std.Target.Feature.Set, // if flag set
1262/// * cpu_features_sub: std.Target.Feature.Set, // if flag set
1263/// * cpu_name: String, // if cpu_model is explicit
1264/// * os_version_min: WindowsVersion // if os_version_min is windows
1265/// * os_version_min: String // if os_version_min is semver
1266/// * os_version_max: WindowsVersion // if os_version_max is windows
1267/// * os_version_max: String // if os_version_max is semver
1268/// * glibc_version: String, // if flag is set
1269/// * android_api_level: u32, // if flag is set
1270/// * dynamic_linker: String, // if flag is set
12711243pub const TargetQuery = struct {
12721244 flags: Flags,
12731245
1246 cpu_features_add: Storage.FlagOptional(.flags, .cpu_features_add, std.Target.Cpu.Feature.Set),
1247 cpu_features_sub: Storage.FlagOptional(.flags, .cpu_features_sub, std.Target.Cpu.Feature.Set),
1248 //cpu_name: Storage.EnumOptional(.flags, .cpu_name, .explicit, String),
1249 //os_version_min: Storage.EnumOptional(.flags, .os_version_min, .windows, WindowsVersion),
1250 //os_version_min: Storage.EnumOptional(.flags, .os_version_min, .semver, String),
1251 //os_version_max: Storage.EnumOptional(.flags, .os_version_max, .windows, WindowsVersion),
1252 //os_version_max: Storage.EnumOptional(.flags, .os_version_max, .semver, String),
1253 glibc_version: Storage.FlagOptional(.flags, .glibc_version, String),
1254 android_api_level: Storage.FlagOptional(.flags, .android_api_level, u32),
1255 dynamic_linker: Storage.FlagOptional(.flags, .dynamic_linker, String),
1256
12741257 pub const Index = enum(u32) {
12751258 _,
12761259
......@@ -1279,24 +1262,7 @@ pub const TargetQuery = struct {
12791262 }
12801263
12811264 pub fn length(i: Index, extra: []const u32) usize {
1282 //const flags = getExtra(extra, @intFromEnum(i), TargetQuery).flags;
1283 const flags: Flags = @bitCast(extra[@intFromEnum(i)]);
1284 const feature_set_size: usize = (@sizeOf(std.Target.Cpu.Feature.Set) + 3) / 4;
1285 return @typeInfo(TargetQuery).@"struct".fields.len +
1286 (if (flags.cpu_features_add) feature_set_size else 0) +
1287 (if (flags.cpu_features_sub) feature_set_size else 0) +
1288 @intFromBool(flags.cpu_model == .explicit) +
1289 @as(usize, switch (flags.os_version_min) {
1290 .semver, .windows => 1,
1291 else => 0,
1292 }) +
1293 @as(usize, switch (flags.os_version_max) {
1294 .semver, .windows => 1,
1295 else => 0,
1296 }) +
1297 @intFromBool(flags.glibc_version) +
1298 @intFromBool(flags.android_api_level) +
1299 @intFromBool(flags.dynamic_linker);
1265 return Storage.dataLength(extra, @intFromEnum(i), TargetQuery);
13001266 }
13011267 };
13021268
......@@ -1528,21 +1494,186 @@ pub const TargetQuery = struct {
15281494 };
15291495};
15301496
1531pub fn extraData(c: *const Configuration, comptime T: type, index: usize) T {
1532 const extra = c.extra;
1533 var i: usize = index;
1534 var result: T = undefined;
1535 inline for (@typeInfo(T).@"struct".fields) |field| {
1536 comptime assert(@sizeOf(field.type) == @sizeOf(u32));
1537 @field(result, field.name) = switch (@typeInfo(field.type)) {
1538 .int => extra[i],
1539 .@"enum" => @enumFromInt(extra[i]),
1540 .@"struct" => @bitCast(extra[i]),
1497pub const Storage = enum {
1498 flag_optional,
1499
1500 pub fn FlagOptional(
1501 comptime flags_arg: @EnumLiteral(),
1502 comptime flag_arg: @EnumLiteral(),
1503 comptime ValueArg: type,
1504 ) type {
1505 return struct {
1506 value: ?Value,
1507
1508 pub const flags = flags_arg;
1509 pub const flag = flag_arg;
1510 pub const storage: Storage = .flag_optional;
1511 pub const Value = ValueArg;
1512 };
1513 }
1514
1515 pub fn dataLength(buffer: []const u32, i: usize, comptime S: type) usize {
1516 var end = i;
1517 _ = data(buffer, &end, S);
1518 return end - i;
1519 }
1520
1521 pub fn data(buffer: []const u32, i: *usize, comptime S: type) S {
1522 var result: S = undefined;
1523 const fields = @typeInfo(S).@"struct".fields;
1524 inline for (fields) |field| {
1525 @field(result, field.name) = dataField(buffer, i, &result, field.type);
1526 }
1527 return result;
1528 }
1529
1530 fn dataField(buffer: []const u32, i: *usize, container: anytype, comptime Field: type) Field {
1531 switch (@typeInfo(Field)) {
1532 .int => |info| switch (info.bits) {
1533 32 => {
1534 defer i.* += 1;
1535 return buffer[i.*];
1536 },
1537 64 => {
1538 defer i.* += 2;
1539 return buffer[i.*..][0..2].*;
1540 },
1541 else => comptime unreachable,
1542 },
1543 .@"enum" => {
1544 defer i.* += 1;
1545 return @enumFromInt(buffer[i.*]);
1546 },
1547 .@"struct" => |info| switch (info.layout) {
1548 .@"packed" => switch (info.backing_integer.?) {
1549 u32 => {
1550 defer i.* += 1;
1551 return @bitCast(buffer[i.*]);
1552 },
1553 u64 => {
1554 defer i.* += 2;
1555 return @bitCast(buffer[i.*..][0..2].*);
1556 },
1557 else => comptime unreachable,
1558 },
1559 .auto => switch (Field) {
1560 std.Target.Cpu.Feature.Set => {
1561 const u32_count = (Field.usize_count * @sizeOf(usize)) / @sizeOf(u32);
1562 defer i.* += u32_count;
1563 return .{ .ints = @as(
1564 *align(@alignOf(u32)) const [Field.usize_count]usize,
1565 @ptrCast(buffer[i.*..][0..u32_count]),
1566 ).* };
1567 },
1568 else => switch (Field.storage) {
1569 .flag_optional => {
1570 const flags = @field(container, @tagName(Field.flags));
1571 const flag = @field(flags, @tagName(Field.flag));
1572 return .{
1573 .value = if (flag) dataField(buffer, i, container, Field.Value) else null,
1574 };
1575 },
1576 },
1577 },
1578 .@"extern" => comptime unreachable,
1579 },
1580 else => comptime unreachable,
1581 }
1582 }
1583
1584 /// Returns new end index.
1585 fn setExtra(buffer: []u32, index: usize, extra: anytype) usize {
1586 const fields = @typeInfo(@TypeOf(extra)).@"struct".fields;
1587 var i = index;
1588 inline for (fields) |field| {
1589 i += setExtraField(buffer, i, field.type, @field(extra, field.name));
1590 }
1591 return i;
1592 }
1593
1594 fn calculateExtraLenUpperBound(comptime Extra: type) comptime_int {
1595 var i = 0;
1596 const fields = @typeInfo(Extra).@"struct".fields;
1597 inline for (fields) |field| {
1598 i += calculateExtraFieldLenUpperBound(field.type);
1599 }
1600 return i;
1601 }
1602
1603 inline fn setExtraField(buffer: []u32, i: usize, comptime Field: type, value: anytype) usize {
1604 switch (@typeInfo(Field)) {
1605 .int => |info| switch (info.bits) {
1606 32 => {
1607 buffer[i] = value;
1608 return 1;
1609 },
1610 64 => {
1611 buffer[i..][0..2].* = @bitCast(value);
1612 return 2;
1613 },
1614 else => comptime unreachable,
1615 },
1616 .@"enum" => {
1617 buffer[i] = @intFromEnum(value);
1618 return 1;
1619 },
1620 .@"struct" => |info| switch (info.layout) {
1621 .@"packed" => switch (info.backing_integer.?) {
1622 u32 => {
1623 buffer[i] = @bitCast(value);
1624 return 1;
1625 },
1626 u64 => {
1627 buffer[i..][0..2].* = @bitCast(value);
1628 return 2;
1629 },
1630 else => comptime unreachable,
1631 },
1632 .auto => switch (Field) {
1633 std.Target.Cpu.Feature.Set => {
1634 const casted: []const u32 = @ptrCast(&value.ints);
1635 @memcpy(buffer[i..][0..casted.len], casted);
1636 return casted.len;
1637 },
1638 else => switch (Field.storage) {
1639 .flag_optional => {
1640 return if (value.value) |v| setExtraField(buffer, i, Field.Value, v) else 0;
1641 },
1642 },
1643 },
1644 .@"extern" => comptime unreachable,
1645 },
1646 else => @compileError("bad field type: " ++ @typeName(Field)),
1647 }
1648 }
1649
1650 fn calculateExtraFieldLenUpperBound(comptime Field: type) comptime_int {
1651 return switch (@typeInfo(Field)) {
1652 .int => |info| switch (info.bits) {
1653 32 => 1,
1654 64 => 2,
1655 else => comptime unreachable,
1656 },
1657 .@"enum" => 1,
1658 .@"struct" => |info| switch (info.layout) {
1659 .@"packed" => switch (info.backing_integer.?) {
1660 u32 => 1,
1661 u64 => 2,
1662 else => comptime unreachable,
1663 },
1664 .auto => switch (Field.storage) {
1665 .flag_optional => 1,
1666 },
1667 .@"extern" => comptime unreachable,
1668 },
15411669 else => comptime unreachable,
15421670 };
1543 i += 1;
15441671 }
1545 return result;
1672};
1673
1674pub fn extraData(c: *const Configuration, comptime T: type, index: usize) T {
1675 var i: usize = index;
1676 return Storage.data(c.extra, &i, T);
15461677}
15471678
15481679pub const LoadFileError = Io.File.Reader.Error || Allocator.Error || error{EndOfStream};