╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭ Type.zig ─────────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭ find file ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ ╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │ │ │http│ ssh │ │ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
3379 } 3380 }, 3381 .tuple_type => |tuple| { 3382 for (tuple.types.get(ip)) |field_ty| { 3383 try collectSubtypes(Type.fromInterned(field_ty), pt, visited); 3384 } 3385 }, 3386 .func_type => |fn_info| { 3387 const param_types = fn_info.param_types.get(&zcu.intern_pool); 3388 for (param_types) |param_ty| { 3389 if (param_ty != .generic_poison_type) { 3390 try collectSubtypes(Type.fromInterned(param_ty), pt, visited); 3391 } 3392 } 3393 3394 if (fn_info.return_type != .generic_poison_type) { 3395 try collectSubtypes(Type.fromInterned(fn_info.return_type), pt, visited); 3396 } 3397 }, 3398 .anyframe_type => |child| try collectSubtypes(Type.fromInterned(child), pt, visited), 3399 3400 // leaf types 3401 .undef, 3402 .inferred_error_set_type, 3403 .error_set_type, 3404 .struct_type, 3405 .union_type, 3406 .opaque_type, 3407 .enum_type, 3408 .spirv_type, 3409 .simple_type, 3410 .int_type, 3411 => {}, 3412 3413 // values, not types 3414 .simple_value, 3415 .@"extern", 3416 .func, 3417 .int, 3418 .err, 3419 .error_union, 3420 .enum_literal, 3421 .enum_tag, 3422 .float, 3423 .ptr, 3424 .slice, 3425 .opt, 3426 .aggregate, 3427 .un, 3428 .bitpack, 3429 // memoization, not types 3430 .memoized_call, 3431 => unreachable, 3432 } 3433 } 3434 3435 fn shouldDedupeType(ty: Type, ctx: *Comparison, pt: Zcu.PerThread) error{OutOfMemory}!Comparison.DedupeEntry { 3436 if (ctx.type_occurrences.get(ty)) |occ| { 3437 if (ctx.type_dedupe_cache.get(ty)) |cached| { 3438 return cached; 3439 } 3440 3441 var discarding: std.Io.Writer.Discarding = .init(&.{}); 3442 3443 print(ty, &discarding.writer, pt, null) catch 3444 unreachable; // we are writing into a discarding writer, it should never fail 3445 3446 const type_len: i32 = @intCast(discarding.count); 3447 3448 const placeholder_len: i32 = 1; 3449 const min_saved_bytes: i32 = 20; 3450 3451 const saved_bytes = (type_len - placeholder_len) * (occ - 1); 3452 const max_placeholders = 7; // T to Z 3453 const should_dedupe = saved_bytes >= min_saved_bytes and ctx.placeholder_index < max_placeholders; 3454 3455 const entry: Comparison.DedupeEntry = if (should_dedupe) b: { 3456 ctx.placeholder_index += 1; 3457 break :b .{ .dedupe = .{ .index = ctx.placeholder_index - 1 } }; 3458 } else .dont_dedupe; 3459 3460 try ctx.type_dedupe_cache.put(pt.zcu.gpa, ty, entry); 3461 3462 return entry; 3463 } else { 3464 return .{ .dont_dedupe = {} }; 3465 } 3466 } 3467 3468 /// The comparison recursively walks all types given and notes how many times 3469 /// each subtype occurs. It then while recursively printing decides for each 3470 /// subtype whether to print the type inline or create a placeholder based on 3471 /// the subtype length and number of occurences. Placeholders are then found by 3472 /// iterating `type_dedupe_cache` which caches the inline/placeholder decisions. 3473 pub const Comparison = struct { 3474 type_occurrences: std.array_hash_map.Auto(Type, u16), 3475 type_dedupe_cache: std.array_hash_map.Auto(Type, DedupeEntry), 3476 placeholder_index: u8, 3477 3478 pub const Placeholder = struct { 3479 index: u8, 3480 3481 pub fn format(p: Placeholder, writer: *std.Io.Writer) error{WriteFailed}!void { 3482 return writer.print("{c}", .{p.index + 'T'}); 3483 } 3484 }; 3485 3486 pub const DedupeEntry = union(enum) { 3487 dont_dedupe: void, 3488 dedupe: Placeholder, 3489 }; 3490 3491 pub fn init(types: []const Type, pt: Zcu.PerThread) error{OutOfMemory}!Comparison { 3492 var cmp: Comparison = .{ 3493 .type_occurrences = .empty, 3494 .type_dedupe_cache = .empty, 3495 .placeholder_index = 0, 3496 }; 3497 3498 errdefer cmp.deinit(pt); 3499 3500 for (types) |ty| { 3501 try collectSubtypes(ty, pt, &cmp.type_occurrences); 3502 } 3503 3504 return cmp; 3505 } 3506 3507 pub fn deinit(cmp: *Comparison, pt: Zcu.PerThread) void { 3508 const gpa = pt.zcu.gpa; 3509 cmp.type_occurrences.deinit(gpa); 3510 cmp.type_dedupe_cache.deinit(gpa); 3511 } 3512 3513 pub fn fmtType(ctx: *Comparison, ty: Type, pt: Zcu.PerThread) Comparison.Formatter { 3514 return .{ .ty = ty, .ctx = ctx, .pt = pt }; 3515 } 3516 pub const Formatter = struct { 3517 ty: Type, 3518 ctx: *Comparison, 3519 pt: Zcu.PerThread, 3520 3521 pub fn format(self: Comparison.Formatter, writer: anytype) error{WriteFailed}!void { 3522 print(self.ty, writer, self.pt, self.ctx) catch return error.WriteFailed; 3523 } 3524 }; 3525 }; 3526 3527 pub const @"u0": Type = .{ .ip_index = .u0_type }; 3528 pub const @"u1": Type = .{ .ip_index = .u1_type }; 3529 pub const @"u8": Type = .{ .ip_index = .u8_type }; 3530 pub const @"u16": Type = .{ .ip_index = .u16_type }; 3531 pub const @"u29": Type = .{ .ip_index = .u29_type }; 3532 pub const @"u32": Type = .{ .ip_index = .u32_type }; 3533 pub const @"u64": Type = .{ .ip_index = .u64_type }; 3534 pub const @"u80": Type = .{ .ip_index = .u80_type }; 3535 pub const @"u128": Type = .{ .ip_index = .u128_type }; 3536 pub const @"u256": Type = .{ .ip_index = .u256_type }; 3537 3538 pub const @"i8": Type = .{ .ip_index = .i8_type }; 3539 pub const @"i16": Type = .{ .ip_index = .i16_type }; 3540 pub const @"i32": Type = .{ .ip_index = .i32_type }; 3541 pub const @"i64": Type = .{ .ip_index = .i64_type }; 3542 pub const @"i128": Type = .{ .ip_index = .i128_type }; 3543 3544 pub const @"f16": Type = .{ .ip_index = .f16_type }; 3545 pub const @"f32": Type = .{ .ip_index = .f32_type }; 3546 pub const @"f64": Type = .{ .ip_index = .f64_type }; 3547 pub const @"f80": Type = .{ .ip_index = .f80_type }; 3548 pub const @"f128": Type = .{ .ip_index = .f128_type }; 3549 3550 pub const @"bool": Type = .{ .ip_index = .bool_type }; 3551 pub const @"usize": Type = .{ .ip_index = .usize_type }; 3552 pub const @"isize": Type = .{ .ip_index = .isize_type }; 3553 pub const @"comptime_int": Type = .{ .ip_index = .comptime_int_type }; 3554 pub const @"comptime_float": Type = .{ .ip_index = .comptime_float_type }; 3555 pub const @"void": Type = .{ .ip_index = .void_type }; 3556 pub const @"type": Type = .{ .ip_index = .type_type }; 3557 pub const @"anyerror": Type = .{ .ip_index = .anyerror_type }; 3558 pub const @"anyopaque": Type = .{ .ip_index = .anyopaque_type }; 3559 pub const @"anyframe": Type = .{ .ip_index = .anyframe_type }; 3560 pub const @"null": Type = .{ .ip_index = .null_type }; 3561 pub const @"undefined": Type = .{ .ip_index = .undefined_type }; 3562 pub const @"noreturn": Type = .{ .ip_index = .noreturn_type }; 3563 pub const enum_literal: Type = .{ .ip_index = .enum_literal_type }; 3564 3565 pub const @"c_char": Type = .{ .ip_index = .c_char_type }; 3566 pub const @"c_short": Type = .{ .ip_index = .c_short_type }; 3567 pub const @"c_ushort": Type = .{ .ip_index = .c_ushort_type }; 3568 pub const @"c_int": Type = .{ .ip_index = .c_int_type }; 3569 pub const @"c_uint": Type = .{ .ip_index = .c_uint_type }; 3570 pub const @"c_long": Type = .{ .ip_index = .c_long_type }; 3571 pub const @"c_ulong": Type = .{ .ip_index = .c_ulong_type }; 3572 pub const @"c_longlong": Type = .{ .ip_index = .c_longlong_type }; 3573 pub const @"c_ulonglong": Type = .{ .ip_index = .c_ulonglong_type }; 3574 pub const @"c_longdouble": Type = .{ .ip_index = .c_longdouble_type }; 3575 3576 pub const ptr_usize: Type = .{ .ip_index = .ptr_usize_type }; 3577 pub const ptr_const_comptime_int: Type = .{ .ip_index = .ptr_const_comptime_int_type }; 3578 pub const manyptr_u8: Type = .{ .ip_index = .manyptr_u8_type }; 3579 pub const manyptr_const_u8: Type = .{ .ip_index = .manyptr_const_u8_type }; 3580 pub const manyptr_const_u8_sentinel_0: Type = .{ .ip_index = .manyptr_const_u8_sentinel_0_type }; 3581 pub const slice_const_u8: Type = .{ .ip_index = .slice_const_u8_type }; 3582 pub const slice_const_u8_sentinel_0: Type = .{ .ip_index = .slice_const_u8_sentinel_0_type }; 3583 pub const slice_const_slice_const_u8: Type = .{ .ip_index = .slice_const_slice_const_u8_type }; 3584 pub const slice_const_type: Type = .{ .ip_index = .slice_const_type_type }; 3585 pub const optional_type: Type = .{ .ip_index = .optional_type_type }; 3586 pub const optional_noreturn: Type = .{ .ip_index = .optional_noreturn_type }; 3587 3588 pub const vector_8_i8: Type = .{ .ip_index = .vector_8_i8_type }; 3589 pub const vector_16_i8: Type = .{ .ip_index = .vector_16_i8_type }; 3590 pub const vector_32_i8: Type = .{ .ip_index = .vector_32_i8_type }; 3591 pub const vector_64_i8: Type = .{ .ip_index = .vector_64_i8_type }; 3592 pub const vector_1_u8: Type = .{ .ip_index = .vector_1_u8_type }; 3593 pub const vector_2_u8: Type = .{ .ip_index = .vector_2_u8_type }; 3594 pub const vector_4_u8: Type = .{ .ip_index = .vector_4_u8_type }; 3595 pub const vector_8_u8: Type = .{ .ip_index = .vector_8_u8_type }; 3596 pub const vector_16_u8: Type = .{ .ip_index = .vector_16_u8_type }; 3597 pub const vector_32_u8: Type = .{ .ip_index = .vector_32_u8_type }; 3598 pub const vector_64_u8: Type = .{ .ip_index = .vector_64_u8_type }; 3599 pub const vector_2_i16: Type = .{ .ip_index = .vector_2_i16_type }; 3600 pub const vector_4_i16: Type = .{ .ip_index = .vector_4_i16_type }; 3601 pub const vector_8_i16: Type = .{ .ip_index = .vector_8_i16_type }; 3602 pub const vector_16_i16: Type = .{ .ip_index = .vector_16_i16_type }; 3603 pub const vector_32_i16: Type = .{ .ip_index = .vector_32_i16_type }; 3604 pub const vector_4_u16: Type = .{ .ip_index = .vector_4_u16_type }; 3605 pub const vector_8_u16: Type = .{ .ip_index = .vector_8_u16_type }; 3606 pub const vector_16_u16: Type = .{ .ip_index = .vector_16_u16_type }; 3607 pub const vector_32_u16: Type = .{ .ip_index = .vector_32_u16_type }; 3608 pub const vector_2_i32: Type = .{ .ip_index = .vector_2_i32_type }; 3609 pub const vector_4_i32: Type = .{ .ip_index = .vector_4_i32_type }; 3610 pub const vector_8_i32: Type = .{ .ip_index = .vector_8_i32_type }; 3611 pub const vector_16_i32: Type = .{ .ip_index = .vector_16_i32_type }; 3612 pub const vector_4_u32: Type = .{ .ip_index = .vector_4_u32_type }; 3613 pub const vector_8_u32: Type = .{ .ip_index = .vector_8_u32_type }; 3614 pub const vector_16_u32: Type = .{ .ip_index = .vector_16_u32_type }; 3615 pub const vector_2_i64: Type = .{ .ip_index = .vector_2_i64_type }; 3616 pub const vector_4_i64: Type = .{ .ip_index = .vector_4_i64_type }; 3617 pub const vector_8_i64: Type = .{ .ip_index = .vector_8_i64_type }; 3618 pub const vector_2_u64: Type = .{ .ip_index = .vector_2_u64_type }; 3619 pub const vector_4_u64: Type = .{ .ip_index = .vector_4_u64_type }; 3620 pub const vector_8_u64: Type = .{ .ip_index = .vector_8_u64_type }; 3621 pub const vector_1_u128: Type = .{ .ip_index = .vector_1_u128_type }; 3622 pub const vector_2_u128: Type = .{ .ip_index = .vector_2_u128_type }; 3623 pub const vector_1_u256: Type = .{ .ip_index = .vector_1_u256_type }; 3624 pub const vector_4_f16: Type = .{ .ip_index = .vector_4_f16_type }; 3625 pub const vector_8_f16: Type = .{ .ip_index = .vector_8_f16_type }; 3626 pub const vector_16_f16: Type = .{ .ip_index = .vector_16_f16_type }; 3627 pub const vector_32_f16: Type = .{ .ip_index = .vector_32_f16_type }; 3628 pub const vector_2_f32: Type = .{ .ip_index = .vector_2_f32_type }; 3629 pub const vector_4_f32: Type = .{ .ip_index = .vector_4_f32_type }; 3630 pub const vector_8_f32: Type = .{ .ip_index = .vector_8_f32_type }; 3631 pub const vector_16_f32: Type = .{ .ip_index = .vector_16_f32_type }; 3632 pub const vector_2_f64: Type = .{ .ip_index = .vector_2_f64_type }; 3633 pub const vector_4_f64: Type = .{ .ip_index = .vector_4_f64_type }; 3634 pub const vector_8_f64: Type = .{ .ip_index = .vector_8_f64_type }; 3635 3636 pub const empty_tuple: Type = .{ .ip_index = .empty_tuple_type }; 3637 3638 pub const generic_poison: Type = .{ .ip_index = .generic_poison_type }; 3639 3640 pub fn smallestUnsignedBits(max: u64) u16 { 3641 return switch (max) { 3642 0 => 0, 3643 else => @as(u16, 1) + std.math.log2_int(u64, max), 3644 }; 3645 } 3646 3647 /// This is only used for comptime asserts. Bump this number when you make a change 3648 /// to packed struct layout to find out all the places in the codebase you need to edit! 3649 pub const packed_struct_layout_version = 2; 3650 3651 fn cTypeAlign(target: *const Target, c_type: Target.CType) Alignment { 3652 return .fromByteUnits(target.cTypeAlignment(c_type).?); 3653 } 3654