| ... | ... | @@ -205,9 +205,7 @@ pub const Wip = struct { |
| 205 | 205 | null; |
| 206 | 206 | const cpu_features_add_empty = q.cpu_features_add.isEmpty(); |
| 207 | 207 | 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, .{ |
| 211 | 209 | .flags = .{ |
| 212 | 210 | .cpu_arch = .init(q.cpu_arch), |
| 213 | 211 | .cpu_model = .init(q.cpu_model), |
| ... | ... | @@ -218,19 +216,20 @@ pub const Wip = struct { |
| 218 | 216 | .object_format = .init(q.ofmt), |
| 219 | 217 | .os_version_min = .init(q.os_version_min), |
| 220 | 218 | .os_version_max = .init(q.os_version_max), |
| 221 | | .glibc_version = q.glibc_version != null, |
| 219 | .glibc_version = glibc_version != null, |
| 222 | 220 | .android_api_level = q.android_api_level != null, |
| 223 | | .dynamic_linker = q.dynamic_linker != null, |
| 221 | .dynamic_linker = dynamic_linker != null, |
| 224 | 222 | }, |
| 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 }, |
| 225 | 228 | }))); |
| 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; |
| 234 | 233 | |
| 235 | 234 | // Deduplicate. |
| 236 | 235 | const gop = try wip.targets_table.getOrPutContext(gpa, result_index, @as(TargetsTableContext, .{ |
| ... | ... | @@ -287,9 +286,7 @@ pub const Wip = struct { |
| 287 | 286 | .semver, .linux, .hurd => .semver, |
| 288 | 287 | .windows => .windows, |
| 289 | 288 | }; |
| 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, .{ |
| 293 | 290 | .flags = .{ |
| 294 | 291 | .cpu_arch = .init(t.cpu.arch), |
| 295 | 292 | .cpu_model = .explicit, |
| ... | ... | @@ -304,14 +301,16 @@ pub const Wip = struct { |
| 304 | 301 | .android_api_level = android_api_level != null, |
| 305 | 302 | .dynamic_linker = dynamic_linker != null, |
| 306 | 303 | }, |
| 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 }, |
| 307 | 309 | }))); |
| 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; |
| 315 | 314 | |
| 316 | 315 | // Deduplicate. |
| 317 | 316 | const gop = try wip.targets_table.getOrPutContext(gpa, result_index, @as(TargetsTableContext, .{ |
| ... | ... | @@ -345,17 +344,14 @@ pub const Wip = struct { |
| 345 | 344 | } |
| 346 | 345 | |
| 347 | 346 | 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); |
| 351 | 349 | return addExtraAssumeCapacity(wip, extra); |
| 352 | 350 | } |
| 353 | 351 | |
| 354 | 352 | pub fn addExtraAssumeCapacity(wip: *Wip, extra: anytype) u32 { |
| 355 | | const fields = @typeInfo(@TypeOf(extra)).@"struct".fields; |
| 356 | 353 | 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); |
| 359 | 355 | return result; |
| 360 | 356 | } |
| 361 | 357 | |
| ... | ... | @@ -363,21 +359,6 @@ pub const Wip = struct { |
| 363 | 359 | const string = optional_string orelse return; |
| 364 | 360 | wip.extra.appendAssumeCapacity(@intFromEnum(string)); |
| 365 | 361 | } |
| 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 | | } |
| 381 | 362 | }; |
| 382 | 363 | |
| 383 | 364 | pub const SystemIntegration = extern struct { |
| ... | ... | @@ -577,7 +558,7 @@ pub const Step = extern struct { |
| 577 | 558 | }; |
| 578 | 559 | |
| 579 | 560 | /// 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 |
| 581 | 562 | /// * test_runner: LazyPath, // if test_runner_mode is not default |
| 582 | 563 | pub const Compile = struct { |
| 583 | 564 | flags: @This().Flags, |
| ... | ... | @@ -588,36 +569,34 @@ pub const Step = extern struct { |
| 588 | 569 | root_module: Module.Index, |
| 589 | 570 | root_name: String, |
| 590 | 571 | |
| 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 }; |
| 621 | 600 | pub const TestRunnerMode = enum(u2) { default, simple, server }; |
| 622 | 601 | pub const Entry = enum(u2) { default, disabled, enabled, symbol_name }; |
| 623 | 602 | |
| ... | ... | @@ -803,7 +782,7 @@ pub const Step = extern struct { |
| 803 | 782 | error_limit: bool, |
| 804 | 783 | install_name: bool, |
| 805 | 784 | entitlements: bool, |
| 806 | | expected_compile_errors: ExpectedCompileErrors, |
| 785 | expect_errors: ExpectErrors, |
| 807 | 786 | linker_script: bool, |
| 808 | 787 | version_script: bool, |
| 809 | 788 | _: u18 = 0, |
| ... | ... | @@ -833,6 +812,13 @@ pub const MaxRss = enum(u32) { |
| 833 | 812 | pub const OptionalLazyPath = enum(u32) { |
| 834 | 813 | none = maxInt(u32), |
| 835 | 814 | _, |
| 815 | |
| 816 | pub fn unwrap(this: @This()) ?LazyPath { |
| 817 | return switch (this) { |
| 818 | .none => null, |
| 819 | else => @enumFromInt(@intFromEnum(this)), |
| 820 | }; |
| 821 | } |
| 836 | 822 | }; |
| 837 | 823 | |
| 838 | 824 | /// An index into `extra`. |
| ... | ... | @@ -909,7 +895,6 @@ pub const Package = struct { |
| 909 | 895 | /// * link_objects: UnionList(LinkObject), // if flag is set |
| 910 | 896 | pub const Module = struct { |
| 911 | 897 | flags: Flags, |
| 912 | | flags2: Flags2, |
| 913 | 898 | owner: Package.Index, |
| 914 | 899 | root_source_file: OptionalLazyPath, |
| 915 | 900 | import_table: ImportTable, |
| ... | ... | @@ -979,7 +964,7 @@ pub const Module = struct { |
| 979 | 964 | _, |
| 980 | 965 | }; |
| 981 | 966 | |
| 982 | | pub const Flags = packed struct(u32) { |
| 967 | pub const Flags = packed struct(u64) { |
| 983 | 968 | optimize: Optimize, |
| 984 | 969 | strip: DefaultingBool, |
| 985 | 970 | unwind_tables: UnwindTables, |
| ... | ... | @@ -998,9 +983,7 @@ pub const Module = struct { |
| 998 | 983 | frameworks: bool, |
| 999 | 984 | link_objects: bool, |
| 1000 | 985 | export_symbol_names: bool, |
| 1001 | | }; |
| 1002 | 986 | |
| 1003 | | pub const Flags2 = packed struct(u32) { |
| 1004 | 987 | valgrind: DefaultingBool, |
| 1005 | 988 | pic: DefaultingBool, |
| 1006 | 989 | red_zone: DefaultingBool, |
| ... | ... | @@ -1257,20 +1240,20 @@ pub const ResolvedTarget = struct { |
| 1257 | 1240 | }; |
| 1258 | 1241 | }; |
| 1259 | 1242 | |
| 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 |
| 1271 | 1243 | pub const TargetQuery = struct { |
| 1272 | 1244 | flags: Flags, |
| 1273 | 1245 | |
| 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 | |
| 1274 | 1257 | pub const Index = enum(u32) { |
| 1275 | 1258 | _, |
| 1276 | 1259 | |
| ... | ... | @@ -1279,24 +1262,7 @@ pub const TargetQuery = struct { |
| 1279 | 1262 | } |
| 1280 | 1263 | |
| 1281 | 1264 | 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); |
| 1300 | 1266 | } |
| 1301 | 1267 | }; |
| 1302 | 1268 | |
| ... | ... | @@ -1528,21 +1494,186 @@ pub const TargetQuery = struct { |
| 1528 | 1494 | }; |
| 1529 | 1495 | }; |
| 1530 | 1496 | |
| 1531 | | pub 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]), |
| 1497 | pub 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 | }, |
| 1541 | 1669 | else => comptime unreachable, |
| 1542 | 1670 | }; |
| 1543 | | i += 1; |
| 1544 | 1671 | } |
| 1545 | | return result; |
| 1672 | }; |
| 1673 | |
| 1674 | pub fn extraData(c: *const Configuration, comptime T: type, index: usize) T { |
| 1675 | var i: usize = index; |
| 1676 | return Storage.data(c.extra, &i, T); |
| 1546 | 1677 | } |
| 1547 | 1678 | |
| 1548 | 1679 | pub const LoadFileError = Io.File.Reader.Error || Allocator.Error || error{EndOfStream}; |