╭─────────────╮╭────────────╮ │scroll to top││next lines →│ ╰─────────────╯╰────────────╯ ╭ InternPool.zig ───────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭ find file ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ ╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │ │ │http│ ssh │ │ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
3042 inline else => |val, tag| { 3043 const Bits = @Int(.unsigned, @bitSizeOf(@TypeOf(val))); 3044 const a_bits: Bits = @bitCast(val); 3045 const b_bits: Bits = @bitCast(@field(b_info.storage, @tagName(tag))); 3046 return a_bits == b_bits; 3047 }, 3048 } 3049 }, 3050 3051 inline .opaque_type, .enum_type, .union_type, .struct_type => |a_info, a_tag_ct| { 3052 const b_info = @field(b, @tagName(a_tag_ct)); 3053 if (std.meta.activeTag(a_info) != b_info) return false; 3054 switch (a_info) { 3055 .declared => |a_d| { 3056 const b_d = b_info.declared; 3057 if (a_d.zir_index != b_d.zir_index) return false; 3058 const a_captures = switch (a_d.captures) { 3059 .owned => |s| s.get(ip), 3060 .external => |cvs| cvs, 3061 }; 3062 const b_captures = switch (b_d.captures) { 3063 .owned => |s| s.get(ip), 3064 .external => |cvs| cvs, 3065 }; 3066 return std.mem.eql(u32, @ptrCast(a_captures), @ptrCast(b_captures)); 3067 }, 3068 .reified => |a_r| { 3069 const b_r = b_info.reified; 3070 return a_r.zir_index == b_r.zir_index and 3071 a_r.type_hash == b_r.type_hash; 3072 }, 3073 .generated_union_tag => |a_union_ty| return a_union_ty == b_info.generated_union_tag, 3074 } 3075 }, 3076 .aggregate => |a_info| { 3077 const b_info = b.aggregate; 3078 if (a_info.ty != b_info.ty) return false; 3079 3080 const len = ip.aggregateTypeLen(a_info.ty); 3081 const StorageTag = @typeInfo(Key.Aggregate.Storage).@"union".tag_type.?; 3082 if (@as(StorageTag, a_info.storage) != @as(StorageTag, b_info.storage)) { 3083 for (0..@intCast(len)) |elem_index| { 3084 const a_elem = switch (a_info.storage) { 3085 .bytes => |bytes| ip.getIfExists(.{ .int = .{ 3086 .ty = .u8_type, 3087 .storage = .{ .u64 = bytes.at(elem_index, ip) }, 3088 } }) orelse return false, 3089 .elems => |elems| elems[elem_index], 3090 .repeated_elem => |elem| elem, 3091 }; 3092 const b_elem = switch (b_info.storage) { 3093 .bytes => |bytes| ip.getIfExists(.{ .int = .{ 3094 .ty = .u8_type, 3095 .storage = .{ .u64 = bytes.at(elem_index, ip) }, 3096 } }) orelse return false, 3097 .elems => |elems| elems[elem_index], 3098 .repeated_elem => |elem| elem, 3099 }; 3100 if (a_elem != b_elem) return false; 3101 } 3102 return true; 3103 } 3104 3105 switch (a_info.storage) { 3106 .bytes => |a_bytes| { 3107 const b_bytes = b_info.storage.bytes; 3108 return a_bytes == b_bytes or 3109 std.mem.eql(u8, a_bytes.toSlice(len, ip), b_bytes.toSlice(len, ip)); 3110 }, 3111 .elems => |a_elems| { 3112 const b_elems = b_info.storage.elems; 3113 return std.mem.eql( 3114 Index, 3115 a_elems[0..@intCast(len)], 3116 b_elems[0..@intCast(len)], 3117 ); 3118 }, 3119 .repeated_elem => |a_elem| { 3120 const b_elem = b_info.storage.repeated_elem; 3121 return a_elem == b_elem; 3122 }, 3123 } 3124 }, 3125 .tuple_type => |a_info| { 3126 const b_info = b.tuple_type; 3127 return std.mem.eql(Index, a_info.types.get(ip), b_info.types.get(ip)) and 3128 std.mem.eql(Index, a_info.values.get(ip), b_info.values.get(ip)); 3129 }, 3130 .error_set_type => |a_info| { 3131 const b_info = b.error_set_type; 3132 return std.mem.eql(NullTerminatedString, a_info.names.get(ip), b_info.names.get(ip)); 3133 }, 3134 .inferred_error_set_type => |a_info| { 3135 const b_info = b.inferred_error_set_type; 3136 return a_info == b_info; 3137 }, 3138 3139 .func_type => |a_info| { 3140 const b_info = b.func_type; 3141 return Key.FuncType.eql(a_info, b_info, ip); 3142 }, 3143 3144 .memoized_call => |a_info| { 3145 const b_info = b.memoized_call; 3146 return a_info.func == b_info.func and 3147 std.mem.eql(Index, a_info.arg_values, b_info.arg_values); 3148 }, 3149 } 3150 } 3151 3152 pub fn typeOf(key: Key) Index { 3153 return switch (key) { 3154 .int_type, 3155 .ptr_type, 3156 .array_type, 3157 .vector_type, 3158 .opt_type, 3159 .anyframe_type, 3160 .error_union_type, 3161 .error_set_type, 3162 .inferred_error_set_type, 3163 .simple_type, 3164 .struct_type, 3165 .union_type, 3166 .spirv_type, 3167 .opaque_type, 3168 .enum_type, 3169 .tuple_type, 3170 .func_type, 3171 => .type_type, 3172 3173 inline .ptr, 3174 .slice, 3175 .int, 3176 .float, 3177 .opt, 3178 .@"extern", 3179 .func, 3180 .err, 3181 .error_union, 3182 .enum_tag, 3183 .aggregate, 3184 .un, 3185 .bitpack, 3186 => |x| x.ty, 3187 3188 .enum_literal => .enum_literal_type, 3189 3190 .undef => |x| x, 3191 3192 .simple_value => |s| switch (s) { 3193 .void => .void_type, 3194 .null => .null_type, 3195 .false, .true => .bool_type, 3196 .@"unreachable" => .noreturn_type, 3197 }, 3198 3199 .memoized_call => unreachable, 3200 }; 3201 } 3202 }; 3203 3204 pub const LoadedStructType = struct { 3205 /// Index of the `struct_decl` or `reify` ZIR instruction. 3206 zir_index: TrackedInst.Index, 3207 captures: CaptureValue.Slice, 3208 is_reified: bool, 3209 3210 /// The name of this struct type. 3211 name: NullTerminatedString, 3212 /// The fully-qualified name of this struct type. 3213 fqn: NullTerminatedString, 3214 /// If this is a declared type with the `.parent` name strategy, this is the `Nav` it was named after. 3215 /// Otherwise, or if this is a file's root struct type, this is `.none`. 3216 name_nav: Nav.Index.Optional, 3217 namespace: NamespaceIndex, 3218 3219 layout: std.lang.Type.ContainerLayout, 3220 /// May be `undefined` if `layout != .@"packed"`. 3221 packed_backing_mode: BackingTypeMode, 3222 3223 /// Initially `false`, and set to `true` once any dependency on or reference to the struct's 3224 /// layout is encountered, after which it is never reset to `false`, even across incremental 3225 /// updates. 3226 /// 3227 /// This field is purely an optimization to avoid resolving the layout of types whose layouts 3228 /// are never demanded. If this field is `true` but the layout is not actually needed, the 3229 /// compiler frontend resolves this by traversing the reference graph at the end of each update 3230 /// with `Zcu.resolveReferences` and hiding compile errors which arise from this analysis. 3231 want_layout: bool, 3232 3233 // The remaining fields are only valid once the struct's layout is resolved. 3234 field_name_map: MapIndex, 3235 field_names: NullTerminatedString.Slice, 3236 field_types: Index.Slice, 3237 field_defaults: Index.Slice, 3238 field_aligns: Alignment.Slice, 3239 field_is_comptime_bits: ComptimeBits, 3240 /// If `layout` is `.@"packed"`, this is `.empty`. 3241 field_runtime_order: RuntimeOrder.Slice, 3242 /// If `layout` is `.@"packed"`, this is `.empty`. 3243 field_offsets: Offsets, 3244 /// Only valid if `layout` is `.@"packed"`. 3245 packed_backing_int_type: Index, 3246 /// Only valid if `layout` is *not* `.@"packed"`. 3247 class: TypeClass, 3248 /// Only valid if `layout` is *not* `.@"packed"`. 3249 size: u32, 3250 /// Only valid if `layout` is *not* `.@"packed"`. 3251 alignment: Alignment, 3252 3253 pub const ComptimeBits = struct { 3254 tid: Zcu.PerThread.Id, 3255 start: u32, 3256 /// This is the number of u32 elements, not the number of struct fields. 3257 len: u32, 3258 3259 pub const empty: ComptimeBits = .{ .tid = .main, .start = 0, .len = 0 }; 3260 3261 pub fn getAll(this: ComptimeBits, ip: *const InternPool) []u32 { 3262 const extra = ip.getLocalShared(this.tid).extra.acquire(); 3263 return extra.view().items(.@"0")[this.start..][0..this.len]; 3264 } 3265 3266 pub fn get(this: ComptimeBits, ip: *const InternPool, i: usize) bool { 3267 if (this.len == 0) return false; 3268 return @as(u1, @truncate(this.getAll(ip)[i / 32] >> @intCast(i % 32))) != 0; 3269 } 3270 }; 3271 3272 pub const Offsets = struct { 3273 tid: Zcu.PerThread.Id, 3274 start: u32, 3275 len: u32, 3276 3277 pub const empty: Offsets = .{ .tid = .main, .start = 0, .len = 0 }; 3278 3279 pub fn get(this: Offsets, ip: *const InternPool) []u32 { 3280 const extra = ip.getLocalShared(this.tid).extra.acquire(); 3281 return @ptrCast(extra.view().items(.@"0")[this.start..][0..this.len]); 3282 } 3283 }; 3284 3285 pub const RuntimeOrder = enum(u32) { 3286 /// Placeholder until layout is resolved. 3287 unresolved = std.math.maxInt(u32) - 0, 3288 /// Field not present at runtime 3289 omitted = std.math.maxInt(u32) - 1, 3290 _, 3291 3292 pub const Slice = struct { 3293 tid: Zcu.PerThread.Id, 3294 start: u32, 3295 len: u32, 3296 3297 pub const empty: Slice = .{ .tid = .main, .start = 0, .len = 0 }; 3298 3299 pub fn get(slice: RuntimeOrder.Slice, ip: *const InternPool) []RuntimeOrder { 3300 const extra = ip.getLocalShared(slice.tid).extra.acquire(); 3301 return @ptrCast(extra.view().items(.@"0")[slice.start..][0..slice.len]); 3302 } 3303 }; 3304 3305 pub fn toInt(i: RuntimeOrder) ?u32 { 3306 return switch (i) { 3307 .omitted => null, 3308 .unresolved => unreachable, 3309 else => @backingInt(i), 3310 }; 3311 } 3312 }; 3313 3314 /// Look up field index based on field name. 3315 pub fn nameIndex(s: LoadedStructType, ip: *const InternPool, name: NullTerminatedString) ?u32 { 3316 const map = s.field_name_map.get(ip); 3317 const adapter: NullTerminatedString.Adapter = .{ .strings = s.field_names.get(ip) }; 3318 const field_index = map.getIndexAdapted(name, adapter) orelse return null; 3319 return @intCast(field_index); 3320 } 3321 3322 /// Iterates over non-comptime fields in the order they are laid out in memory at runtime. 3323 /// May or may not include zero-bit fields. 3324 /// Asserts the struct is not packed. 3325 pub fn iterateRuntimeOrder(s: *const LoadedStructType, ip: *const InternPool) RuntimeOrderIterator { 3326 switch (s.layout) { 3327 .auto => { 3328 const ro = std.mem.sliceTo(s.field_runtime_order.get(ip), .omitted); 3329 return .{ 3330 .runtime_order = ro, 3331 .fields_len = @intCast(ro.len), 3332 .next_index = 0, 3333 }; 3334 }, 3335 .@"extern" => return .{ 3336 .runtime_order = null, 3337 .fields_len = s.field_names.len, 3338 .next_index = 0, 3339 }, 3340 .@"packed" => unreachable, 3341 } 3342 } 3343 pub const RuntimeOrderIterator = struct { 3344 runtime_order: ?[]const RuntimeOrder, 3345 fields_len: u32, 3346 next_index: u32, 3347 pub fn next(it: *RuntimeOrderIterator) ?u32 { 3348 const i = it.next_index; 3349 if (i == it.fields_len) return null; 3350 it.next_index = i + 1; 3351 const ro = it.runtime_order orelse return i; 3352 return ro[i].toInt().?; 3353 } 3354 }; 3355 3356 pub fn iterateRuntimeOrderReverse(s: *const LoadedStructType, ip: *InternPool) ReverseRuntimeOrderIterator { 3357 switch (s.layout) { 3358 .auto => { 3359 const ro = std.mem.sliceTo(s.field_runtime_order.get(ip), .omitted); 3360 return .{ 3361 .runtime_order = ro, 3362 .last_index = @intCast(ro.len), 3363 }; 3364 }, 3365 .@"extern" => return .{ 3366 .runtime_order = null, 3367 .last_index = s.field_names.len, 3368 }, 3369 .@"packed" => unreachable, 3370 } 3371 } 3372 pub const ReverseRuntimeOrderIterator = struct { 3373 runtime_order: ?[]const RuntimeOrder, 3374 last_index: u32, 3375 pub fn next(it: *ReverseRuntimeOrderIterator) ?u32 { 3376 if (it.last_index == 0) return null; 3377 const i = it.last_index - 1; 3378 it.last_index = i; 3379 const ro = it.runtime_order orelse return i; 3380 return ro[i].toInt().?; 3381 } 3382 }; 3383 }; 3384 3385 /// Unlike `Tag.TypeUnion` which is an encoding, and `Key.UnionType` which is a 3386 /// minimal hashmap key, this type is a convenience type that contains info 3387 /// needed by semantic analysis. 3388 pub const LoadedUnionType = struct { 3389 /// Index of the `union_decl` or `reify` ZIR instruction. 3390 zir_index: TrackedInst.Index, 3391 captures: CaptureValue.Slice, 3392 is_reified: bool, 3393 3394 /// The name of this union type. 3395 name: NullTerminatedString, 3396 /// The fully-qualified name of this union type. 3397 fqn: NullTerminatedString, 3398 /// If this is a declared type with the `.parent` name strategy, this is the `Nav` it was named after. 3399 /// Otherwise, this is `.none`. 3400 name_nav: Nav.Index.Optional, 3401 namespace: NamespaceIndex, 3402 3403 layout: std.lang.Type.ContainerLayout, 3404 enum_tag_mode: BackingTypeMode, 3405 /// May be `undefined` if `layout != .@"packed"`. 3406 packed_backing_mode: BackingTypeMode, 3407 3408 /// Only reified unions store field names; typically they should be loaded from `enum_tag_type` 3409 /// instead. Reified unions store them because type resolution needs them in order to validate 3410 /// or populate `enum_tag_type`. 3411 reified_field_names: NullTerminatedString.Slice, 3412 3413 /// Initially `false`, and set to `true` once any dependency on or reference to the struct's 3414 /// layout is encountered, after which it is never reset to `false`, even across incremental 3415 /// updates. 3416 /// 3417 /// This field is purely an optimization to avoid resolving the layout of types whose layouts 3418 /// are never demanded. If this field is `true` but the layout is not actually needed, the 3419 /// compiler frontend resolves this by traversing the reference graph at the end of each update 3420 /// with `Zcu.resolveReferences` and hiding compile errors which arise from this analysis. 3421 want_layout: bool, 3422 3423 // The remaining fields are only valid once the union's layout is resolved. 3424 field_types: Index.Slice, 3425 field_aligns: Alignment.Slice, 3426 tag_usage: TagUsage, 3427 /// While `tag_usage` indicates whether the union should logically contain a tag, it may be 3428 /// omitted if the union layout is resolved as OPV or NPV. This field is `true` iff there is an 3429 /// actual runtime tag, with one or more runtime bits, in the union layout. It is always `false` 3430 /// if `layout` is not `.auto`. 3431 has_runtime_tag: bool, 3432 /// Even if `tag_usage == .none` and `has_runtime_tag == false`, this is still populated with 3433 /// the union's "hypothetical" tag type. 3434 enum_tag_type: Index, 3435 /// Only valid if `layout` is `.@"packed"`. 3436 packed_backing_int_type: Index, 3437 /// Not valid if `layout` is `.@"packed"`. 3438 class: TypeClass, 3439 /// Not valid if `layout` is `.@"packed"`. 3440 size: u32, 3441 /// Not valid if `layout` is `.@"packed"`. 3442 padding: u32, 3443 /// Not valid if `layout` is `.@"packed"`. 3444 alignment: Alignment, 3445 3446 pub const TagUsage = enum(u2) { 3447 none, 3448 safety, 3449 tagged, 3450 }; 3451 }; 3452 3453 pub const LoadedEnumType = struct { 3454 /// This is `none` iff this is a generated tag type. 3455 /// Otherwise, index of the `enum_decl` or `reify` ZIR instruction. 3456 zir_index: TrackedInst.Index.Optional, 3457 captures: CaptureValue.Slice, 3458 /// If `zir_index` is `.none`, this is the union type for which this enum is the tag type. 3459 owner_union: Index, 3460 is_reified: bool, 3461 3462 /// The name of this enum type. 3463 name: NullTerminatedString, 3464 /// The fully-qualified name of this enum type. 3465 fqn: NullTerminatedString, 3466 /// If this is a declared type with the `.parent` name strategy, this is the `Nav` it was named after. 3467 /// Otherwise, this is `.none`. 3468 name_nav: Nav.Index.Optional, 3469 namespace: NamespaceIndex, 3470 3471 int_tag_mode: BackingTypeMode, 3472 nonexhaustive: bool, 3473 3474 /// Initially `false`, and set to `true` once any dependency on or reference to the struct's 3475 /// layout is encountered, after which it is never reset to `false`, even across incremental 3476 /// updates. 3477 /// 3478 /// This field is purely an optimization to avoid resolving the layout of types whose layouts 3479 /// are never demanded. If this field is `true` but the layout is not actually needed, the 3480 /// compiler frontend resolves this by traversing the reference graph at the end of each update 3481 /// with `Zcu.resolveReferences` and hiding compile errors which arise from this analysis. 3482 want_layout: bool, 3483 3484 // The remaining fields are only valid once the enum's layout is resolved. 3485 int_tag_type: Index, 3486 field_name_map: MapIndex, 3487 field_names: NullTerminatedString.Slice, 3488 field_value_map: OptionalMapIndex, 3489 field_values: Index.Slice, 3490 3491 /// Look up field index based on field name. 3492 pub fn nameIndex(e: LoadedEnumType, ip: *const InternPool, name: NullTerminatedString) ?u32 { 3493 const map = e.field_name_map.get(ip); 3494 const adapter: NullTerminatedString.Adapter = .{ .strings = e.field_names.get(ip) }; 3495 const field_index = map.getIndexAdapted(name, adapter) orelse return null; 3496 return @intCast(field_index); 3497 } 3498 3499 /// Look up field index based on integer tag value. 3500 /// Asserts that the type of `tag_val` is `enum_obj.int_tag_type`. 3501 /// Asserts that `tag_val` is not `undefined`. 3502 pub fn tagValueIndex(e: LoadedEnumType, ip: *const InternPool, tag_val: Index) ?u32 { 3503 assert(ip.typeOf(tag_val) == e.int_tag_type); 3504 assert(ip.indexToKey(tag_val) == .int); 3505 if (e.field_value_map.unwrap()) |field_value_map| { 3506 const map = field_value_map.get(ip); 3507 const adapter: Index.Adapter = .{ .indexes = e.field_values.get(ip) }; 3508 const field_index = map.getIndexAdapted(tag_val, adapter) orelse return null; 3509 return @intCast(field_index); 3510 } 3511 // Auto-numbered enum, so convert `tag_val` to field index 3512 const field_index = switch (ip.indexToKey(tag_val).int.storage) { 3513 inline .u64, .i64 => |x| std.math.cast(u32, x) orelse return null, 3514 .big_int => |x| x.toInt(u32) catch return null, 3515 }; 3516 return if (field_index < e.field_names.len) field_index else null; 3517 } 3518 }; 3519 3520 pub const LoadedOpaqueType = struct { 3521 /// Index of the `opaque_decl` instruction. 3522 zir_index: TrackedInst.Index, 3523 captures: CaptureValue.Slice, 3524 3525 /// The name of this opaque type. 3526 name: NullTerminatedString, 3527 /// The fully-qualified name of this opaque type. 3528 fqn: NullTerminatedString, 3529 /// If this is a declared type with the `.parent` name strategy, this is the `Nav` it was named after. 3530 /// Otherwise, this is `.none`. 3531 name_nav: Nav.Index.Optional, 3532 namespace: NamespaceIndex, 3533 }; 3534 3535 pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType { 3536 const unwrapped_index = index.unwrap(ip); 3537 const extra_list = unwrapped_index.getExtra(ip); 3538 const extra_items = extra_list.view().items(.@"0"); 3539 const item = unwrapped_index.getItem(ip); 3540 // Exiting this `switch` means this is a `packed struct`. 3541 const backing_mode: BackingTypeMode, const any_defaults: bool = switch (item.tag) { 3542 .type_struct_packed_auto => .{ .auto, false }, 3543 .type_struct_packed_explicit => .{ .explicit, false }, 3544 .type_struct_packed_auto_defaults => .{ .auto, true }, 3545 .type_struct_packed_explicit_defaults => .{ .explicit, true }, 3546 .type_struct => { 3547 const extra = extraDataTrail(extra_list, Tag.TypeStruct, item.data); 3548 var extra_index = extra.end; 3549 const captures: CaptureValue.Slice = switch (extra.data.flags.any_captures) { 3550 .reified => captures: { 3551 extra_index += 2; // type_hash: PackedU64 3552 break :captures .empty; 3553 }, 3554 .false => .empty, 3555 .true => captures: { 3556 const len = extra_items[extra_index]; 3557 extra_index += 1; 3558 break :captures .{ 3559 .tid = unwrapped_index.tid, 3560 .start = extra_index, 3561 .len = len, 3562 }; 3563 }, 3564 }; 3565 extra_index += captures.len; 3566 const field_names: NullTerminatedString.Slice = .{ 3567 .tid = unwrapped_index.tid, 3568 .start = extra_index, 3569 .len = extra.data.fields_len, 3570 }; 3571 extra_index += field_names.len; 3572 const field_types: Index.Slice = .{ 3573 .tid = unwrapped_index.tid, 3574 .start = extra_index, 3575 .len = extra.data.fields_len, 3576 }; 3577 extra_index += field_types.len; 3578 const field_defaults: Index.Slice = if (extra.data.flags.any_field_defaults) .{ 3579 .tid = unwrapped_index.tid, 3580 .start = extra_index, 3581 .len = extra.data.fields_len, 3582 } else .empty; 3583 extra_index += field_defaults.len; 3584 const field_aligns: Alignment.Slice = if (extra.data.flags.any_field_aligns) .{ 3585 .tid = unwrapped_index.tid, 3586 .start = extra_index, 3587 .len = extra.data.fields_len, 3588 } else .empty; 3589 extra_index += @divCeil(field_aligns.len, 4); 3590 const field_is_comptime_bits: LoadedStructType.ComptimeBits = if (extra.data.flags.any_comptime_fields) .{ 3591 .tid = unwrapped_index.tid, 3592 .start = extra_index, 3593 .len = @divCeil(extra.data.fields_len, 32), 3594 } else .empty; 3595 extra_index += field_is_comptime_bits.len; 3596 const field_runtime_order: LoadedStructType.RuntimeOrder.Slice = if (extra.data.flags.layout == .auto) .{ 3597 .tid = unwrapped_index.tid, 3598 .start = extra_index, 3599 .len = extra.data.fields_len, 3600 } else .empty; 3601 extra_index += field_runtime_order.len; 3602 const field_offsets: LoadedStructType.Offsets = .{ 3603 .tid = unwrapped_index.tid, 3604 .start = extra_index, 3605 .len = extra.data.fields_len, 3606 }; 3607 extra_index += field_offsets.len; 3608 3609 return .{ 3610 .zir_index = extra.data.zir_index, 3611 .captures = captures, 3612 .is_reified = extra.data.flags.any_captures == .reified, 3613 .name = extra.data.name, 3614 .fqn = extra.data.fqn, 3615 .name_nav = extra.data.name_nav, 3616 .namespace = extra.data.namespace, 3617 .layout = switch (extra.data.flags.layout) { 3618 .auto => .auto, 3619 .@"extern" => .@"extern", 3620 }, 3621 .packed_backing_mode = undefined, 3622 3623 .want_layout = extra.data.flags.want_layout, 3624 3625 .field_name_map = extra.data.field_name_map, 3626 .field_names = field_names, 3627 .field_types = field_types, 3628 .field_defaults = field_defaults, 3629 .field_aligns = field_aligns, 3630 .field_is_comptime_bits = field_is_comptime_bits, 3631 .field_runtime_order = field_runtime_order, 3632 .field_offsets = field_offsets, 3633 .packed_backing_int_type = .none, 3634 .class = extra.data.flags.class, 3635 .size = extra.data.size, 3636 .alignment = extra.data.flags.alignment, 3637 }; 3638 }, 3639 else => unreachable, 3640 }; 3641 const extra = extraDataTrail(extra_list, Tag.TypeStructPacked, item.data); 3642 var extra_index = extra.end; 3643 const captures: CaptureValue.Slice = switch (extra.data.bits.captures_len) { 3644 .reified => captures: { 3645 extra_index += 2; // type_hash: PackedU64 3646 break :captures .empty; 3647 }, 3648 _ => |n| .{ 3649 .tid = unwrapped_index.tid, 3650 .start = extra_index, 3651 .len = @backingInt(n), 3652 }, 3653 }; 3654 extra_index += captures.len; 3655 const field_names: NullTerminatedString.Slice = .{ 3656 .tid = unwrapped_index.tid, 3657 .start = extra_index, 3658 .len = extra.data.fields_len, 3659 }; 3660 extra_index += field_names.len; 3661 const field_types: Index.Slice = .{ 3662 .tid = unwrapped_index.tid, 3663 .start = extra_index, 3664 .len = extra.data.fields_len, 3665 }; 3666 extra_index += field_types.len; 3667 const field_defaults: Index.Slice = if (any_defaults) .{ 3668 .tid = unwrapped_index.tid, 3669 .start = extra_index, 3670 .len = extra.data.fields_len, 3671 } else .empty; 3672 extra_index += field_defaults.len; 3673 return .{ 3674 .zir_index = extra.data.zir_index, 3675 .captures = captures, 3676 .is_reified = extra.data.bits.captures_len == .reified, 3677 .name = extra.data.name, 3678 .fqn = extra.data.fqn, 3679 .name_nav = extra.data.name_nav, 3680 .namespace = extra.data.namespace, 3681 .layout = .@"packed", 3682 .packed_backing_mode = backing_mode, 3683 3684 .want_layout = extra.data.bits.want_layout, 3685 3686 .field_name_map = extra.data.field_name_map, 3687 .field_names = field_names, 3688 .field_types = field_types, 3689 .field_defaults = field_defaults, 3690 .field_aligns = .empty, 3691 .field_is_comptime_bits = .empty, 3692 .field_runtime_order = .empty, 3693 .field_offsets = .empty, 3694 .packed_backing_int_type = extra.data.backing_int_type, 3695 .class = undefined, 3696 .size = undefined, 3697 .alignment = undefined, 3698 }; 3699 } 3700 3701 pub fn loadUnionType(ip: *const InternPool, index: Index) LoadedUnionType { 3702 const unwrapped_index = index.unwrap(ip); 3703 const extra_list = unwrapped_index.getExtra(ip); 3704 const extra_items = extra_list.view().items(.@"0"); 3705 const item = unwrapped_index.getItem(ip); 3706 // Exiting this `switch` means this is a `packed union`. 3707 const backing_mode: BackingTypeMode = switch (item.tag) { 3708 .type_union_packed_auto => .auto, 3709 .type_union_packed_explicit => .explicit, 3710 .type_union => { 3711 const extra = extraDataTrail(extra_list, Tag.TypeUnion, item.data); 3712 var extra_index = extra.end; 3713 const captures: CaptureValue.Slice = switch (extra.data.flags.any_captures) { 3714 .reified => captures: { 3715 extra_index += 2; // type_hash: PackedU64 3716 break :captures .empty; 3717 }, 3718 .false => .empty, 3719 .true => captures: { 3720 const len = extra_items[extra_index]; 3721 extra_index += 1; 3722 break :captures .{ 3723 .tid = unwrapped_index.tid, 3724 .start = extra_index, 3725 .len = len, 3726 }; 3727 }, 3728 }; 3729 extra_index += captures.len; 3730 const reified_field_names: NullTerminatedString.Slice = if (extra.data.flags.any_captures == .reified) .{ 3731 .tid = unwrapped_index.tid, 3732 .start = extra_index, 3733 .len = extra.data.fields_len, 3734 } else .empty; 3735 extra_index += reified_field_names.len; 3736 const field_types: Index.Slice = .{ 3737 .tid = unwrapped_index.tid, 3738 .start = extra_index, 3739 .len = extra.data.fields_len, 3740 }; 3741 extra_index += field_types.len; 3742 const field_aligns: Alignment.Slice = if (extra.data.flags.any_field_aligns) .{ 3743 .tid = unwrapped_index.tid, 3744 .start = extra_index, 3745 .len = extra.data.fields_len, 3746 } else .empty; 3747 extra_index += @divCeil(field_aligns.len, 4); 3748 3749 return .{ 3750 .zir_index = extra.data.zir_index, 3751 .captures = captures, 3752 .is_reified = extra.data.flags.any_captures == .reified, 3753 .name = extra.data.name, 3754 .fqn = extra.data.fqn, 3755 .name_nav = extra.data.name_nav, 3756 .namespace = extra.data.namespace, 3757 .layout = switch (extra.data.flags.layout) { 3758 .auto => .auto, 3759 .@"extern" => .@"extern", 3760 }, 3761 .tag_usage = extra.data.flags.tag_usage, 3762 .enum_tag_mode = extra.data.flags.enum_tag_mode, 3763 .enum_tag_type = extra.data.enum_tag_type, 3764 .packed_backing_mode = undefined, 3765 .packed_backing_int_type = undefined, 3766 .reified_field_names = reified_field_names, 3767 .want_layout = extra.data.flags.want_layout, 3768 .field_types = field_types, 3769 .field_aligns = field_aligns, 3770 .has_runtime_tag = extra.data.flags.has_runtime_tag, 3771 .class = extra.data.flags.class, 3772 .size = extra.data.size, 3773 .padding = extra.data.padding, 3774 .alignment = extra.data.flags.alignment, 3775 }; 3776 }, 3777 else => unreachable, 3778 }; 3779 const extra = extraDataTrail(extra_list, Tag.TypeUnionPacked, item.data); 3780 var extra_index = extra.end; 3781 const captures: CaptureValue.Slice = switch (extra.data.bits.captures_len) { 3782 .reified => captures: { 3783 extra_index += 2; // type_hash: PackedU64 3784 break :captures .empty; 3785 }, 3786 _ => |n| .{ 3787 .tid = unwrapped_index.tid, 3788 .start = extra_index, 3789 .len = @backingInt(n), 3790 }, 3791 }; 3792 extra_index += captures.len; 3793 const reified_field_names: NullTerminatedString.Slice = if (extra.data.bits.captures_len == .reified) .{ 3794 .tid = unwrapped_index.tid, 3795 .start = extra_index, 3796 .len = extra.data.fields_len, 3797 } else .empty; 3798 extra_index += reified_field_names.len; 3799 const field_types: Index.Slice = .{ 3800 .tid = unwrapped_index.tid, 3801 .start = extra_index, 3802 .len = extra.data.fields_len, 3803 }; 3804 extra_index += field_types.len; 3805 return .{ 3806 .zir_index = extra.data.zir_index, 3807 .captures = captures, 3808 .is_reified = extra.data.bits.captures_len == .reified, 3809 .name = extra.data.name, 3810 .fqn = extra.data.fqn, 3811 .name_nav = extra.data.name_nav, 3812 .namespace = extra.data.namespace, 3813 .layout = .@"packed", 3814 .tag_usage = .none, 3815 .enum_tag_mode = .auto, 3816 .enum_tag_type = extra.data.enum_tag_type, 3817 .packed_backing_mode = backing_mode, 3818 .packed_backing_int_type = extra.data.backing_int_type, 3819 .reified_field_names = reified_field_names, 3820 .want_layout = extra.data.bits.want_layout, 3821 .field_types = field_types, 3822 .field_aligns = .empty, 3823 .has_runtime_tag = false, 3824 .class = undefined, 3825 .size = undefined, 3826 .padding = undefined, 3827 .alignment = undefined, 3828 }; 3829 } 3830 3831 pub fn loadEnumType(ip: *const InternPool, index: Index) LoadedEnumType { 3832 const unwrapped_index = index.unwrap(ip); 3833 const extra_list = unwrapped_index.getExtra(ip); 3834 const extra_items = extra_list.view().items(.@"0"); 3835 const item = unwrapped_index.getItem(ip); 3836 const explicit_int_tag: bool, const nonexhaustive: bool = switch (item.tag) { 3837 .type_enum_auto => .{ false, false }, 3838 .type_enum_explicit => .{ true, false }, 3839 .type_enum_nonexhaustive => .{ true, true }, 3840 else => unreachable, 3841 }; 3842 const extra = extraDataTrail(extra_list, Tag.TypeEnum, item.data); 3843 var extra_index: u32 = @intCast(extra.end); 3844 const zir_index: TrackedInst.Index.Optional, const captures: CaptureValue.Slice, const owner_union: Index = switch (extra.data.bits.captures_len) { 3845 .reified => info: { 3846 const zir_index: TrackedInst.Index = @fromBackingInt(@intCast(extra_items[extra_index])); 3847 extra_index += 1; 3848 extra_index += 2; // type_hash: PackedU64 3849 break :info .{ zir_index.toOptional(), .empty, .none }; 3850 }, 3851 .generated_union_tag => info: { 3852 const owner_union: Index = @fromBackingInt(@intCast(extra_items[extra_index])); 3853 extra_index += 1; 3854 break :info .{ .none, .empty, owner_union }; 3855 }, 3856 _ => |n| info: { 3857 const zir_index: TrackedInst.Index = @fromBackingInt(@intCast(extra_items[extra_index])); 3858 extra_index += 1; 3859 const captures: CaptureValue.Slice = .{ 3860 .tid = unwrapped_index.tid, 3861 .start = extra_index, 3862 .len = @backingInt(n), 3863 }; 3864 extra_index += captures.len; 3865 break :info .{ zir_index.toOptional(), captures, .none }; 3866 }, 3867 }; 3868 const field_value_map: OptionalMapIndex = if (explicit_int_tag) m: { 3869 const map: MapIndex = @fromBackingInt(@intCast(extra_items[extra_index])); 3870 extra_index += 1; 3871 break :m map.toOptional(); 3872 } else .none; 3873 const field_names: NullTerminatedString.Slice = .{ 3874 .tid = unwrapped_index.tid, 3875 .start = extra_index, 3876 .len = extra.data.fields_len, 3877 }; 3878 extra_index += field_names.len; 3879 const field_values: Index.Slice = if (explicit_int_tag) .{ 3880 .tid = unwrapped_index.tid, 3881 .start = extra_index, 3882 .len = extra.data.fields_len, 3883 } else .empty; 3884 extra_index += field_values.len; 3885 return .{ 3886 .zir_index = zir_index, 3887 .captures = captures, 3888 .is_reified = extra.data.bits.captures_len == .reified, 3889 .owner_union = owner_union, 3890 .name = extra.data.name, 3891 .fqn = extra.data.fqn, 3892 .name_nav = extra.data.name_nav, 3893 .namespace = extra.data.namespace, 3894 .int_tag_type = extra.data.int_tag_type, 3895 .int_tag_mode = if (explicit_int_tag) .explicit else .auto, 3896 .nonexhaustive = nonexhaustive, 3897 .want_layout = extra.data.bits.want_layout, 3898 .field_name_map = extra.data.field_name_map, 3899 .field_value_map = field_value_map, 3900 .field_names = field_names, 3901 .field_values = field_values, 3902 }; 3903 } 3904 3905 pub fn loadOpaqueType(ip: *const InternPool, index: Index) LoadedOpaqueType { 3906 const unwrapped_index = index.unwrap(ip); 3907 const item = unwrapped_index.getItem(ip); 3908 assert(item.tag == .type_opaque); 3909 const extra = extraDataTrail(unwrapped_index.getExtra(ip), Tag.TypeOpaque, item.data); 3910 return .{ 3911 .zir_index = extra.data.zir_index, 3912 .captures = .{ 3913 .tid = unwrapped_index.tid, 3914 .start = extra.end, 3915 .len = extra.data.captures_len, 3916 }, 3917 .name = extra.data.name, 3918 .fqn = extra.data.fqn, 3919 .name_nav = extra.data.name_nav, 3920 .namespace = extra.data.namespace, 3921 }; 3922 } 3923 3924 pub fn loadSpirvType(ip: *const InternPool, index: Index) Tag.TypeSpirv { 3925 const unwrapped_index = index.unwrap(ip); 3926 const item = unwrapped_index.getItem(ip); 3927 assert(item.tag == .type_spirv); 3928 const extra = extraData(unwrapped_index.getExtra(ip), Tag.TypeSpirv, item.data); 3929 return extra; 3930 } 3931 3932 pub const Item = struct { 3933 tag: Tag, 3934 /// The doc comments on the respective Tag explain how to interpret this. 3935 data: u32, 3936 }; 3937 3938 /// Represents an index into `map`. It represents the canonical index 3939 /// of a `Value` within this `InternPool`. The values are typed. 3940 /// Two values which have the same type can be equality compared simply 3941 /// by checking if their indexes are equal, provided they are both in 3942 /// the same `InternPool`. 3943 /// When adding a tag to this enum, consider adding a corresponding entry to 3944 /// `primitives` in AstGen.zig. 3945 pub const Index = enum(u32) { 3946 pub const first_type: Index = .u0_type; 3947 pub const last_type: Index = .empty_tuple_type; 3948 pub const first_value: Index = .undef; 3949 pub const last_value: Index = .empty_tuple; 3950 3951 u0_type, 3952 u1_type, 3953 u8_type, 3954 i8_type, 3955 u16_type, 3956 i16_type, 3957 u29_type, 3958 u32_type, 3959 i32_type, 3960 u64_type, 3961 i64_type, 3962 u80_type, 3963 u128_type, 3964 i128_type, 3965 u256_type, 3966 usize_type, 3967 isize_type, 3968 c_char_type, 3969 c_short_type, 3970 c_ushort_type, 3971 c_int_type, 3972 c_uint_type, 3973 c_long_type, 3974 c_ulong_type, 3975 c_longlong_type, 3976 c_ulonglong_type, 3977 c_longdouble_type, 3978 f16_type, 3979 f32_type, 3980 f64_type, 3981 f80_type, 3982 f128_type, 3983 anyopaque_type, 3984 bool_type, 3985 void_type, 3986 type_type, 3987 anyerror_type, 3988 comptime_int_type, 3989 comptime_float_type, 3990 noreturn_type, 3991 anyframe_type, 3992 null_type, 3993 undefined_type, 3994 enum_literal_type, 3995 3996 ptr_usize_type, 3997 ptr_const_comptime_int_type, 3998 manyptr_u8_type, 3999 manyptr_const_u8_type, 4000 manyptr_const_u8_sentinel_0_type, 4001 slice_const_u8_type, 4002 slice_const_u8_sentinel_0_type, 4003 4004 manyptr_const_slice_const_u8_type, 4005 slice_const_slice_const_u8_type, 4006 4007 optional_type_type, 4008 manyptr_const_type_type, 4009 slice_const_type_type, 4010 4011 vector_8_i8_type, 4012 vector_16_i8_type, 4013 vector_32_i8_type, 4014 vector_64_i8_type, 4015 vector_1_u8_type, 4016 vector_2_u8_type, 4017 vector_4_u8_type, 4018 vector_8_u8_type, 4019 vector_16_u8_type, 4020 vector_32_u8_type, 4021 vector_64_u8_type, 4022 vector_2_i16_type, 4023 vector_4_i16_type, 4024 vector_8_i16_type, 4025 vector_16_i16_type, 4026 vector_32_i16_type, 4027 vector_4_u16_type, 4028 vector_8_u16_type, 4029 vector_16_u16_type, 4030 vector_32_u16_type, 4031 vector_2_i32_type, 4032 vector_4_i32_type, 4033 vector_8_i32_type, 4034 vector_16_i32_type, 4035 vector_4_u32_type, 4036 vector_8_u32_type, 4037 vector_16_u32_type, 4038 vector_2_i64_type, 4039 vector_4_i64_type, 4040 vector_8_i64_type, 4041 vector_2_u64_type, 4042 vector_4_u64_type, 4043 vector_8_u64_type, 4044 vector_1_u128_type, 4045 vector_2_u128_type, 4046 vector_1_u256_type, 4047 vector_4_f16_type, 4048 vector_8_f16_type, 4049 vector_16_f16_type, 4050 vector_32_f16_type, 4051 vector_2_f32_type, 4052 vector_4_f32_type, 4053 vector_8_f32_type, 4054 vector_16_f32_type, 4055 vector_2_f64_type, 4056 vector_4_f64_type, 4057 vector_8_f64_type, 4058 4059 optional_noreturn_type, 4060 anyerror_void_error_union_type, 4061 /// Used for the inferred error set of inline/comptime function calls. 4062 adhoc_inferred_error_set_type, 4063 /// Represents a type which is unknown. 4064 /// This is used in functions to represent generic parameter/return types, and 4065 /// during semantic analysis to represent unknown result types (i.e. where AstGen 4066 /// thought we would have a result type, but we do not). 4067 generic_poison_type, 4068 /// `@TypeOf(.{})`; a tuple with zero elements. 4069 /// This is not the same as `struct {}`, since that is a struct rather than a tuple. 4070 empty_tuple_type, 4071 4072 /// `undefined` (untyped) 4073 undef, 4074 /// `@as(bool, undefined)` 4075 undef_bool, 4076 /// `@as(usize, undefined)` 4077 undef_usize, 4078 /// `@as(u1, undefined)` 4079 undef_u1, 4080 /// `0` (comptime_int) 4081 zero, 4082 /// `@as(usize, 0)` 4083 zero_usize, 4084 /// `@as(u1, 0)` 4085 zero_u1, 4086 /// `@as(u8, 0)` 4087 zero_u8, 4088 /// `1` (comptime_int) 4089 one, 4090 /// `@as(usize, 1)` 4091 one_usize, 4092 /// `@as(u1, 1)` 4093 one_u1, 4094 /// `@as(u8, 1)` 4095 one_u8, 4096 /// `@as(u8, 4)` 4097 four_u8, 4098 /// `-1` (comptime_int) 4099 negative_one, 4100 /// `{}` 4101 void_value, 4102 /// `unreachable` (noreturn type) 4103 unreachable_value, 4104 /// `null` (untyped) 4105 null_value, 4106 /// `true` 4107 bool_true, 4108 /// `false` 4109 bool_false, 4110 /// `.{}` 4111 empty_tuple, 4112 4113 /// Used by Air/Sema only. 4114 none = std.math.maxInt(u32), 4115 4116 _, 4117 4118 /// An array of `Index` existing within the `extra` array. 4119 /// This type exists to provide a struct with lifetime that is 4120 /// not invalidated when items are added to the `InternPool`. 4121 pub const Slice = struct { 4122 tid: Zcu.PerThread.Id, 4123 start: u32, 4124 len: u32, 4125 4126 pub const empty: Slice = .{ .tid = .main, .start = 0, .len = 0 }; 4127 4128 pub fn get(slice: Slice, ip: *const InternPool) []Index { 4129 const extra = ip.getLocalShared(slice.tid).extra.acquire(); 4130 return @ptrCast(extra.view().items(.@"0")[slice.start..][0..slice.len]); 4131 } 4132 4133 /// If `slice` is empty (`slice.len == 0`), returns `.none`. 4134 /// Otherwise, asserts that `index < slice.len`, and returns the value at `index`. 4135 pub fn getOrNone(slice: Slice, ip: *const InternPool, index: usize) Index { 4136 if (slice.len == 0) return .none; 4137 return slice.get(ip)[index]; 4138 } 4139 }; 4140 4141 /// Used for a map of `Index` values to the index within a list of `Index` values. 4142 const Adapter = struct { 4143 indexes: []const Index, 4144 4145 pub fn eql(ctx: @This(), a: Index, b_void: void, b_map_index: usize) bool { 4146 _ = b_void; 4147 return a == ctx.indexes[b_map_index]; 4148 } 4149 4150 pub fn hash(ctx: @This(), a: Index) u32 { 4151 _ = ctx; 4152 return std.hash.int(@backingInt(a)); 4153 } 4154 }; 4155 4156 const Unwrapped = struct { 4157 tid: Zcu.PerThread.Id, 4158 index: u32, 4159 4160 fn wrap(unwrapped: Unwrapped, ip: *const InternPool) Index { 4161 assert(@backingInt(unwrapped.tid) <= ip.getTidMask()); 4162 assert(unwrapped.index <= ip.getIndexMask(u30)); 4163 return @fromBackingInt(@intCast(@shlExact(@as(u32, @backingInt(unwrapped.tid)), ip.tid_shift_30) | 4164 unwrapped.index)); 4165 } 4166 4167 pub fn getExtra(unwrapped: Unwrapped, ip: *const InternPool) Local.Extra { 4168 return ip.getLocalShared(unwrapped.tid).extra.acquire(); 4169 } 4170 4171 pub fn getItem(unwrapped: Unwrapped, ip: *const InternPool) Item { 4172 const item_ptr = unwrapped.itemPtr(ip); 4173 const tag = @atomicLoad(Tag, item_ptr.tag_ptr, .acquire); 4174 return .{ .tag = tag, .data = item_ptr.data_ptr.* }; 4175 } 4176 4177 pub fn getTag(unwrapped: Unwrapped, ip: *const InternPool) Tag { 4178 const item_ptr = unwrapped.itemPtr(ip); 4179 return @atomicLoad(Tag, item_ptr.tag_ptr, .acquire); 4180 } 4181 4182 pub fn getData(unwrapped: Unwrapped, ip: *const InternPool) u32 { 4183 return unwrapped.getItem(ip).data; 4184 } 4185 4186 const ItemPtr = struct { 4187 tag_ptr: *Tag, 4188 data_ptr: *u32, 4189 }; 4190 fn itemPtr(unwrapped: Unwrapped, ip: *const InternPool) ItemPtr { 4191 const slice = ip.getLocalShared(unwrapped.tid).items.acquire().view().slice(); 4192 return .{ 4193 .tag_ptr = &slice.items(.tag)[unwrapped.index], 4194 .data_ptr = &slice.items(.data)[unwrapped.index], 4195 }; 4196 } 4197 4198 const debug_state = InternPool.debug_state; 4199 }; 4200 pub fn unwrap(index: Index, ip: *const InternPool) Unwrapped { 4201 return .{ 4202 .tid = @fromBackingInt(@intCast(@backingInt(index) >> ip.tid_shift_30 & ip.getTidMask())), 4203 .index = @backingInt(index) & ip.getIndexMask(u30), 4204 }; 4205 } 4206 4207 /// This function is used in the debugger pretty formatters in lib/lldb/ to fetch the 4208 /// Tag to encoding mapping to facilitate fancy debug printing for this type. 4209 fn dbHelper(self: *Index, tag_to_encoding_map: *struct { 4210 const DataIsIndex = struct { data: Index }; 4211 4212 removed: void, 4213 type_int_signed: struct { data: u32 }, 4214 type_int_unsigned: struct { data: u32 }, 4215 type_array_big: struct { data: *Array }, 4216 type_array_small: struct { data: *Vector }, 4217 type_vector: struct { data: *Vector }, 4218 type_pointer: struct { data: *Tag.TypePointer }, 4219 type_slice: DataIsIndex, 4220 type_optional: DataIsIndex, 4221 type_anyframe: DataIsIndex, 4222 type_error_union: struct { data: *Key.ErrorUnionType }, 4223 type_anyerror_union: DataIsIndex, 4224 type_error_set: struct { 4225 const @"data.names_len" = opaque {}; 4226 data: *Tag.ErrorSet, 4227 @"trailing.names.len": *@"data.names_len", 4228 trailing: struct { names: []NullTerminatedString }, 4229 }, 4230 type_inferred_error_set: DataIsIndex, 4231 simple_type: void, 4232 type_function: struct { 4233 const @"data.params_len" = opaque {}; 4234 data: *Tag.TypeFunction, 4235 @"trailing.param_types.len": *@"data.params_len", 4236 trailing: struct { param_types: []Index }, 4237 }, 4238 type_tuple: struct { 4239 const @"data.fields_len" = opaque {}; 4240 data: *TypeTuple, 4241 @"trailing.types.len": *@"data.fields_len", 4242 @"trailing.values.len": *@"data.fields_len", 4243 trailing: struct { types: []Index, values: []Index }, 4244 }, 4245 4246 type_struct: struct { data: *Tag.TypeStruct }, 4247 type_struct_packed_auto: struct { data: *Tag.TypeStructPacked }, 4248 type_struct_packed_explicit: struct { data: *Tag.TypeStructPacked }, 4249 type_struct_packed_auto_defaults: struct { data: *Tag.TypeStructPacked }, 4250 type_struct_packed_explicit_defaults: struct { data: *Tag.TypeStructPacked }, 4251 type_union: struct { data: *Tag.TypeUnion }, 4252 type_union_packed_auto: struct { data: *Tag.TypeUnionPacked }, 4253 type_union_packed_explicit: struct { data: *Tag.TypeUnionPacked }, 4254 type_enum_auto: struct { data: *Tag.TypeEnum }, 4255 type_enum_explicit: struct { data: *Tag.TypeEnum }, 4256 type_enum_nonexhaustive: struct { data: *Tag.TypeEnum }, 4257 type_opaque: struct { data: *Tag.TypeOpaque }, 4258 4259 type_spirv: struct { data: *Tag.TypeSpirv }, 4260 4261 undef: DataIsIndex, 4262 simple_value: void, 4263 ptr_nav: struct { data: *PtrNav }, 4264 ptr_comptime_alloc: struct { data: *PtrComptimeAlloc }, 4265 ptr_uav: struct { data: *PtrUav }, 4266 ptr_uav_aligned: struct { data: *PtrUavAligned }, 4267 ptr_comptime_field: struct { data: *PtrComptimeField }, 4268 ptr_int: struct { data: *PtrInt }, 4269 ptr_eu_payload: struct { data: *PtrBase }, 4270 ptr_opt_payload: struct { data: *PtrBase }, 4271 ptr_elem: struct { data: *PtrBaseIndex }, 4272 ptr_field: struct { data: *PtrBaseIndex }, 4273 ptr_slice: struct { data: *PtrSlice }, 4274 opt_payload: struct { data: *Tag.TypeValue }, 4275 opt_null: DataIsIndex, 4276 int_u8: struct { data: u8 }, 4277 int_u16: struct { data: u16 }, 4278 int_u32: struct { data: u32 }, 4279 int_i32: struct { data: i32 }, 4280 int_usize: struct { data: u32 }, 4281 int_comptime_int_u32: struct { data: u32 }, 4282 int_comptime_int_i32: struct { data: i32 }, 4283 int_small: struct { data: *IntSmall }, 4284 int_positive: struct { data: u32 }, 4285 int_negative: struct { data: u32 }, 4286 error_set_error: struct { data: *Key.Error }, 4287 error_union_error: struct { data: *Key.Error }, 4288 error_union_payload: struct { data: *Tag.TypeValue }, 4289 enum_literal: struct { data: NullTerminatedString }, 4290 enum_tag: struct { data: *Tag.EnumTag }, 4291 float_f16: struct { data: f16 }, 4292 float_f32: struct { data: f32 }, 4293 float_f64: struct { data: *Float64 }, 4294 float_f80: struct { data: *Float80 }, 4295 float_f128: struct { data: *Float128 }, 4296 float_c_longdouble_f80: struct { data: *Float80 }, 4297 float_c_longdouble_f128: struct { data: *Float128 }, 4298 float_comptime_float: struct { data: *Float128 }, 4299 @"extern": struct { data: *Tag.Extern }, 4300 func_decl: struct { 4301 const @"data.analysis.inferred_error_set" = opaque {}; 4302 data: *Tag.FuncDecl, 4303 @"trailing.resolved_error_set.len": *@"data.analysis.inferred_error_set", 4304 trailing: struct { resolved_error_set: []Index }, 4305 }, 4306 func_instance: struct { 4307 const @"data.analysis.inferred_error_set" = opaque {}; 4308 const @"data.generic_owner.data.ty.data.params_len" = opaque {}; 4309 data: *Tag.FuncInstance, 4310 @"trailing.resolved_error_set.len": *@"data.analysis.inferred_error_set", 4311 @"trailing.comptime_args.len": *@"data.generic_owner.data.ty.data.params_len", 4312 trailing: struct { resolved_error_set: []Index, comptime_args: []Index }, 4313 }, 4314 func_coerced: struct { 4315 data: *Tag.FuncCoerced, 4316 }, 4317 only_possible_value: DataIsIndex, 4318 union_value: struct { data: *Key.Union }, 4319 bytes: struct { data: *Bytes }, 4320 aggregate: struct { 4321 const @"data.ty.data.len orelse data.ty.data.fields_len" = opaque {}; 4322 data: *Tag.Aggregate, 4323 @"trailing.element_values.len": *@"data.ty.data.len orelse data.ty.data.fields_len", 4324 trailing: struct { element_values: []Index }, 4325 }, 4326 repeated: struct { data: *Repeated }, 4327 bitpack: struct { data: *Key.Bitpack }, 4328 4329 memoized_call: struct { 4330 const @"data.args_len" = opaque {}; 4331 data: *MemoizedCall, 4332 @"trailing.arg_values.len": *@"data.args_len", 4333 trailing: struct { arg_values: []Index }, 4334 }, 4335 }) void { 4336 _ = self; 4337 const map_info = @typeInfo(@typeInfo(@TypeOf(tag_to_encoding_map)).pointer.child).@"struct"; 4338 @setEvalBranchQuota(3_000); 4339 inline for (@typeInfo(Tag).@"enum".field_names, 0..) |tag_name, start| { 4340 inline for (0..map_info.field_names.len) |offset| { 4341 if (comptime std.mem.eql(u8, tag_name, map_info.field_names[(start + offset) % map_info.field_names.len])) break; 4342 } else { 4343 @compileError(@typeName(Tag) ++ "." ++ tag_name ++ " missing dbHelper tag_to_encoding_map entry"); 4344 } 4345 } 4346 } 4347 comptime { 4348 if (!builtin.strip_debug_info) switch (builtin.zig_backend) { 4349 .stage2_llvm => _ = &dbHelper, 4350 .stage2_x86_64 => for (@typeInfo(Tag).@"enum".field_names) |tag_name| { 4351 if (!@hasField(@TypeOf(Tag.encodings), tag_name)) @compileLog("missing: " ++ @typeName(Tag) ++ ".encodings." ++ tag_name); 4352 const encoding = @field(Tag.encodings, tag_name); 4353 if (@hasField(@TypeOf(encoding), "trailing")) { 4354 const trailing_info = @typeInfo(encoding.trailing).@"struct"; 4355 for (trailing_info.field_names, trailing_info.field_types) |trailing_field_name, trailing_field_type| { 4356 struct { 4357 fn checkConfig(name: []const u8) void { 4358 if (!@hasField(@TypeOf(encoding.config), name)) @compileError("missing field: " ++ @typeName(Tag) ++ ".encodings." ++ tag_name ++ ".config.@\"" ++ name ++ "\""); 4359 const FieldType = @TypeOf(@field(encoding.config, name)); 4360 if (@typeInfo(FieldType) != .enum_literal) @compileError("expected enum literal: " ++ @typeName(Tag) ++ ".encodings." ++ tag_name ++ ".config.@\"" ++ name ++ "\": " ++ @typeName(FieldType)); 4361 } 4362 fn checkField(name: []const u8, Type: type) void { 4363 switch (@typeInfo(Type)) { 4364 .int, .@"enum" => return, 4365 .@"struct" => |info| switch (info.layout) { 4366 .auto => unreachable, 4367 .@"extern" => { 4368 for (info.field_names, info.field_types) |field_name, field_type| checkField(name ++ "." ++ field_name, field_type); 4369 return; 4370 }, 4371 .@"packed" => return, 4372 }, 4373 .optional => |info| { 4374 checkConfig(name ++ ".?"); 4375 checkField(name ++ ".?", info.child); 4376 return; 4377 }, 4378 .pointer => |info| if (info.size == .slice) { 4379 checkConfig(name ++ ".len"); 4380 checkField(name ++ "[0]", info.child); 4381 return; 4382 }, 4383 else => {}, 4384 } 4385 @compileError("unsupported type: " ++ @typeName(Tag) ++ ".encodings." ++ tag_name ++ "." ++ name ++ ": " ++ @typeName(Type)); 4386 } 4387 }.checkField("trailing." ++ trailing_field_name, trailing_field_type); 4388 } 4389 } 4390 }, 4391 else => {}, 4392 }; 4393 } 4394 }; 4395 4396 pub const static_keys: [static_len]Key = .{ 4397 .{ .int_type = .{ 4398 .signedness = .unsigned, 4399 .bits = 0, 4400 } }, 4401 4402 .{ .int_type = .{ 4403 .signedness = .unsigned, 4404 .bits = 1, 4405 } }, 4406 4407 .{ .int_type = .{ 4408 .signedness = .unsigned, 4409 .bits = 8, 4410 } }, 4411 4412 .{ .int_type = .{ 4413 .signedness = .signed, 4414 .bits = 8, 4415 } }, 4416 4417 .{ .int_type = .{ 4418 .signedness = .unsigned, 4419 .bits = 16, 4420 } }, 4421 4422 .{ .int_type = .{ 4423 .signedness = .signed, 4424 .bits = 16, 4425 } }, 4426 4427 .{ .int_type = .{ 4428 .signedness = .unsigned, 4429 .bits = 29, 4430 } }, 4431 4432 .{ .int_type = .{ 4433 .signedness = .unsigned, 4434 .bits = 32, 4435 } }, 4436 4437 .{ .int_type = .{ 4438 .signedness = .signed, 4439 .bits = 32, 4440 } }, 4441 4442 .{ .int_type = .{ 4443 .signedness = .unsigned, 4444 .bits = 64, 4445 } }, 4446 4447 .{ .int_type = .{ 4448 .signedness = .signed, 4449 .bits = 64, 4450 } }, 4451 4452 .{ .int_type = .{ 4453 .signedness = .unsigned, 4454 .bits = 80, 4455 } }, 4456 4457 .{ .int_type = .{ 4458 .signedness = .unsigned, 4459 .bits = 128, 4460 } }, 4461 4462 .{ .int_type = .{ 4463 .signedness = .signed, 4464 .bits = 128, 4465 } }, 4466 4467 .{ .int_type = .{ 4468 .signedness = .unsigned, 4469 .bits = 256, 4470 } }, 4471 4472 .{ .simple_type = .usize }, 4473 .{ .simple_type = .isize }, 4474 .{ .simple_type = .c_char }, 4475 .{ .simple_type = .c_short }, 4476 .{ .simple_type = .c_ushort }, 4477 .{ .simple_type = .c_int }, 4478 .{ .simple_type = .c_uint }, 4479 .{ .simple_type = .c_long }, 4480 .{ .simple_type = .c_ulong }, 4481 .{ .simple_type = .c_longlong }, 4482 .{ .simple_type = .c_ulonglong }, 4483 .{ .simple_type = .c_longdouble }, 4484 .{ .simple_type = .f16 }, 4485 .{ .simple_type = .f32 }, 4486 .{ .simple_type = .f64 }, 4487 .{ .simple_type = .f80 }, 4488 .{ .simple_type = .f128 }, 4489 .{ .simple_type = .anyopaque }, 4490 .{ .simple_type = .bool }, 4491 .{ .simple_type = .void }, 4492 .{ .simple_type = .type }, 4493 .{ .simple_type = .anyerror }, 4494 .{ .simple_type = .comptime_int }, 4495 .{ .simple_type = .comptime_float }, 4496 .{ .simple_type = .noreturn }, 4497 .{ .anyframe_type = .none }, 4498 .{ .simple_type = .null }, 4499 .{ .simple_type = .undefined }, 4500 .{ .simple_type = .enum_literal }, 4501 4502 // *usize 4503 .{ .ptr_type = .{ 4504 .child = .usize_type, 4505 .flags = .{}, 4506 } }, 4507 4508 // *const comptime_int 4509 .{ .ptr_type = .{ 4510 .child = .comptime_int_type, 4511 .flags = .{ 4512 .is_const = true, 4513 }, 4514 } }, 4515 4516 // [*]u8 4517 .{ .ptr_type = .{ 4518 .child = .u8_type, 4519 .flags = .{ 4520 .size = .many, 4521 }, 4522 } }, 4523 4524 // [*]const u8 4525 .{ .ptr_type = .{ 4526 .child = .u8_type, 4527 .flags = .{ 4528 .size = .many, 4529 .is_const = true, 4530 }, 4531 } }, 4532 4533 // [*:0]const u8 4534 .{ .ptr_type = .{ 4535 .child = .u8_type, 4536 .sentinel = .zero_u8, 4537 .flags = .{ 4538 .size = .many, 4539 .is_const = true, 4540 }, 4541 } }, 4542 4543 // []const u8 4544 .{ .ptr_type = .{ 4545 .child = .u8_type, 4546 .flags = .{ 4547 .size = .slice, 4548 .is_const = true, 4549 }, 4550 } }, 4551 4552 // [:0]const u8 4553 .{ .ptr_type = .{ 4554 .child = .u8_type, 4555 .sentinel = .zero_u8, 4556 .flags = .{ 4557 .size = .slice, 4558 .is_const = true, 4559 }, 4560 } }, 4561 4562 // [*]const []const u8 4563 .{ .ptr_type = .{ 4564 .child = .slice_const_u8_type, 4565 .flags = .{ 4566 .size = .many, 4567 .is_const = true, 4568 }, 4569 } }, 4570 4571 // []const []const u8 4572 .{ .ptr_type = .{ 4573 .child = .slice_const_u8_type, 4574 .flags = .{ 4575 .size = .slice, 4576 .is_const = true, 4577 }, 4578 } }, 4579 4580 // ?type 4581 .{ .opt_type = .type_type }, 4582 4583 // [*]const type 4584 .{ .ptr_type = .{ 4585 .child = .type_type, 4586 .flags = .{ 4587 .size = .many, 4588 .is_const = true, 4589 }, 4590 } }, 4591 4592 // []const type 4593 .{ .ptr_type = .{ 4594 .child = .type_type, 4595 .flags = .{ 4596 .size = .slice, 4597 .is_const = true, 4598 }, 4599 } }, 4600 4601 // @Vector(8, i8) 4602 .{ .vector_type = .{ .len = 8, .child = .i8_type } }, 4603 // @Vector(16, i8) 4604 .{ .vector_type = .{ .len = 16, .child = .i8_type } }, 4605 // @Vector(32, i8) 4606 .{ .vector_type = .{ .len = 32, .child = .i8_type } }, 4607 // @Vector(64, i8) 4608 .{ .vector_type = .{ .len = 64, .child = .i8_type } }, 4609 // @Vector(1, u8) 4610 .{ .vector_type = .{ .len = 1, .child = .u8_type } }, 4611 // @Vector(2, u8) 4612 .{ .vector_type = .{ .len = 2, .child = .u8_type } }, 4613 // @Vector(4, u8) 4614 .{ .vector_type = .{ .len = 4, .child = .u8_type } }, 4615 // @Vector(8, u8) 4616 .{ .vector_type = .{ .len = 8, .child = .u8_type } }, 4617 // @Vector(16, u8) 4618 .{ .vector_type = .{ .len = 16, .child = .u8_type } }, 4619 // @Vector(32, u8) 4620 .{ .vector_type = .{ .len = 32, .child = .u8_type } }, 4621 // @Vector(64, u8) 4622 .{ .vector_type = .{ .len = 64, .child = .u8_type } }, 4623 // @Vector(2, i16) 4624 .{ .vector_type = .{ .len = 2, .child = .i16_type } }, 4625 // @Vector(4, i16) 4626 .{ .vector_type = .{ .len = 4, .child = .i16_type } }, 4627 // @Vector(8, i16) 4628 .{ .vector_type = .{ .len = 8, .child = .i16_type } }, 4629 // @Vector(16, i16) 4630 .{ .vector_type = .{ .len = 16, .child = .i16_type } }, 4631 // @Vector(32, i16) 4632 .{ .vector_type = .{ .len = 32, .child = .i16_type } }, 4633 // @Vector(4, u16) 4634 .{ .vector_type = .{ .len = 4, .child = .u16_type } }, 4635 // @Vector(8, u16) 4636 .{ .vector_type = .{ .len = 8, .child = .u16_type } }, 4637 // @Vector(16, u16) 4638 .{ .vector_type = .{ .len = 16, .child = .u16_type } }, 4639 // @Vector(32, u16) 4640 .{ .vector_type = .{ .len = 32, .child = .u16_type } }, 4641 // @Vector(2, i32) 4642 .{ .vector_type = .{ .len = 2, .child = .i32_type } }, 4643 // @Vector(4, i32) 4644 .{ .vector_type = .{ .len = 4, .child = .i32_type } }, 4645 // @Vector(8, i32) 4646 .{ .vector_type = .{ .len = 8, .child = .i32_type } }, 4647 // @Vector(16, i32) 4648 .{ .vector_type = .{ .len = 16, .child = .i32_type } }, 4649 // @Vector(4, u32) 4650 .{ .vector_type = .{ .len = 4, .child = .u32_type } }, 4651 // @Vector(8, u32) 4652 .{ .vector_type = .{ .len = 8, .child = .u32_type } }, 4653 // @Vector(16, u32) 4654 .{ .vector_type = .{ .len = 16, .child = .u32_type } }, 4655 // @Vector(2, i64) 4656 .{ .vector_type = .{ .len = 2, .child = .i64_type } }, 4657 // @Vector(4, i64) 4658 .{ .vector_type = .{ .len = 4, .child = .i64_type } }, 4659 // @Vector(8, i64) 4660 .{ .vector_type = .{ .len = 8, .child = .i64_type } }, 4661 // @Vector(2, u64) 4662 .{ .vector_type = .{ .len = 2, .child = .u64_type } }, 4663 // @Vector(4, u64) 4664 .{ .vector_type = .{ .len = 4, .child = .u64_type } }, 4665 // @Vector(8, u64) 4666 .{ .vector_type = .{ .len = 8, .child = .u64_type } }, 4667 // @Vector(1, u128) 4668 .{ .vector_type = .{ .len = 1, .child = .u128_type } }, 4669 // @Vector(2, u128) 4670 .{ .vector_type = .{ .len = 2, .child = .u128_type } }, 4671 // @Vector(1, u256) 4672 .{ .vector_type = .{ .len = 1, .child = .u256_type } }, 4673 // @Vector(4, f16) 4674 .{ .vector_type = .{ .len = 4, .child = .f16_type } }, 4675 // @Vector(8, f16) 4676 .{ .vector_type = .{ .len = 8, .child = .f16_type } }, 4677 // @Vector(16, f16) 4678 .{ .vector_type = .{ .len = 16, .child = .f16_type } }, 4679 // @Vector(32, f16) 4680 .{ .vector_type = .{ .len = 32, .child = .f16_type } }, 4681 // @Vector(2, f32) 4682 .{ .vector_type = .{ .len = 2, .child = .f32_type } }, 4683 // @Vector(4, f32) 4684 .{ .vector_type = .{ .len = 4, .child = .f32_type } }, 4685 // @Vector(8, f32) 4686 .{ .vector_type = .{ .len = 8, .child = .f32_type } }, 4687 // @Vector(16, f32) 4688 .{ .vector_type = .{ .len = 16, .child = .f32_type } }, 4689 // @Vector(2, f64) 4690 .{ .vector_type = .{ .len = 2, .child = .f64_type } }, 4691 // @Vector(4, f64) 4692 .{ .vector_type = .{ .len = 4, .child = .f64_type } }, 4693 // @Vector(8, f64) 4694 .{ .vector_type = .{ .len = 8, .child = .f64_type } }, 4695 4696 // ?noreturn 4697 .{ .opt_type = .noreturn_type }, 4698 4699 // anyerror!void 4700 .{ .error_union_type = .{ 4701 .error_set_type = .anyerror_type, 4702 .payload_type = .void_type, 4703 } }, 4704 4705 // adhoc_inferred_error_set_type 4706 .{ .simple_type = .adhoc_inferred_error_set }, 4707 // generic_poison_type 4708 .{ .simple_type = .generic_poison }, 4709 4710 // empty_tuple_type 4711 .{ .tuple_type = .{ 4712 .types = .empty, 4713 .values = .empty, 4714 } }, 4715 4716 .{ .undef = .undefined_type }, 4717 .{ .undef = .bool_type }, 4718 .{ .undef = .usize_type }, 4719 .{ .undef = .u1_type }, 4720 4721 .{ .int = .{ 4722 .ty = .comptime_int_type, 4723 .storage = .{ .u64 = 0 }, 4724 } }, 4725 4726 .{ .int = .{ 4727 .ty = .usize_type, 4728 .storage = .{ .u64 = 0 }, 4729 } }, 4730 4731 .{ .int = .{ 4732 .ty = .u1_type, 4733 .storage = .{ .u64 = 0 }, 4734 } }, 4735 4736 .{ .int = .{ 4737 .ty = .u8_type, 4738 .storage = .{ .u64 = 0 }, 4739 } }, 4740 4741 .{ .int = .{ 4742 .ty = .comptime_int_type, 4743 .storage = .{ .u64 = 1 }, 4744 } }, 4745 4746 .{ .int = .{ 4747 .ty = .usize_type, 4748 .storage = .{ .u64 = 1 }, 4749 } }, 4750 4751 .{ .int = .{ 4752 .ty = .u1_type, 4753 .storage = .{ .u64 = 1 }, 4754 } }, 4755 4756 .{ .int = .{ 4757 .ty = .u8_type, 4758 .storage = .{ .u64 = 1 }, 4759 } }, 4760 4761 .{ .int = .{ 4762 .ty = .u8_type, 4763 .storage = .{ .u64 = 4 }, 4764 } }, 4765 4766 .{ .int = .{ 4767 .ty = .comptime_int_type, 4768 .storage = .{ .i64 = -1 }, 4769 } }, 4770 4771 .{ .simple_value = .void }, 4772 .{ .simple_value = .@"unreachable" }, 4773 .{ .simple_value = .null }, 4774 .{ .simple_value = .true }, 4775 .{ .simple_value = .false }, 4776 4777 .{ .aggregate = .{ 4778 .ty = .empty_tuple_type, 4779 .storage = .{ .elems = &.{} }, 4780 } }, 4781 }; 4782 4783 /// How many items in the InternPool are statically known. 4784 /// This is specified with an integer literal and a corresponding comptime 4785 /// assert below to break an unfortunate and arguably incorrect dependency loop 4786 /// when compiling. 4787 pub const static_len = Zir.Inst.Ref.static_len; 4788 4789 pub const Tag = enum(u8) { 4790 /// This special tag represents a value which was removed from this pool via 4791 /// `InternPool.remove`. The item remains allocated to preserve indices, but 4792 /// lookups will consider it not equal to any other item, and all queries 4793 /// assert not this tag. `data` is unused. 4794 removed, 4795 4796 /// A type that can be represented with only an enum tag. 4797 simple_type, 4798 /// An integer type. 4799 /// data is number of bits 4800 type_int_signed, 4801 /// An integer type. 4802 /// data is number of bits 4803 type_int_unsigned, 4804 /// An array type whose length requires 64 bits or which has a sentinel. 4805 /// data is payload to Array. 4806 type_array_big, 4807 /// An array type that has no sentinel and whose length fits in 32 bits. 4808 /// data is payload to Vector. 4809 type_array_small, 4810 /// A vector type. 4811 /// data is payload to Vector. 4812 type_vector, 4813 /// A fully explicitly specified pointer type. 4814 type_pointer, 4815 /// A slice type. 4816 /// data is Index of underlying pointer type. 4817 type_slice, 4818 /// An optional type. 4819 /// data is the child type. 4820 type_optional, 4821 /// The type `anyframe->T`. 4822 /// data is the child type. 4823 /// If the child type is `none`, the type is `anyframe`. 4824 type_anyframe, 4825 /// An error union type. 4826 /// data is payload to `Key.ErrorUnionType`. 4827 type_error_union, 4828 /// An error union type of the form `anyerror!T`. 4829 /// data is `Index` of payload type. 4830 type_anyerror_union, 4831 /// An error set type. 4832 /// data is payload to `ErrorSet`. 4833 type_error_set, 4834 /// The inferred error set type of a function. 4835 /// data is `Index` of a `func_decl` or `func_instance`. 4836 type_inferred_error_set, 4837 /// A function body type. 4838 /// `data` is extra index to `TypeFunction`. 4839 type_function, 4840 /// A `TupleType`. 4841 /// data is extra index of `TypeTuple`. 4842 type_tuple, 4843 4844 /// A non-packed struct type. 4845 /// data is extra index of `TypeStruct`. 4846 type_struct, 4847 /// `packed struct { ... }` with no default field values. 4848 /// data is extra index of `TypeStructPacked`. 4849 type_struct_packed_auto, 4850 /// `packed struct(T) { ... }` with no default field values. 4851 /// data is extra index of `TypeStructPacked`. 4852 type_struct_packed_explicit, 4853 /// `packed struct { ... }` with one or more default field values. 4854 /// data is extra index of `TypeStructPacked`. 4855 type_struct_packed_auto_defaults, 4856 /// `packed struct(T) { ... }` with one or more default field values. 4857 /// data is extra index of `TypeStructPacked`. 4858 type_struct_packed_explicit_defaults, 4859 4860 /// A non-packed union type. 4861 /// data is extra index of `TypeUnion`. 4862 type_union, 4863 /// `packed union { ... }`. 4864 /// data is extra index of `TypeUnionPacked`. 4865 type_union_packed_auto, 4866 /// `packed union(T) { ... }`. 4867 /// data is extra index of `TypeUnionPacked`. 4868 type_union_packed_explicit, 4869 4870 /// An exhaustive enum type *without* an explicit integer tag type. The tag type is inferred. 4871 /// 4872 /// Because the tag type is inferred, there are no explicit field values. 4873 /// 4874 /// May be the generated tag type for a `union(enum)`. 4875 /// 4876 /// data is extra index of `TypeEnum`. 4877 type_enum_auto, 4878 /// An exhaustive enum type *with* an explicit integer tag type. 4879 /// 4880 /// May have explicit field values. 4881 /// 4882 /// May be the generated tag type for a `union(enum(T))`. 4883 /// 4884 /// data is extra index of `TypeEnum`. 4885 type_enum_explicit, 4886 /// An non-exhaustive enum type (with an explicit integer tag type, since it is required for 4887 /// non-exhaustive enums). 4888 /// 4889 /// May have explicit field values. 4890 /// 4891 /// This is *not* a union's generated tag type, because such types are always exhaustive. 4892 /// 4893 /// data is extra index of `TypeEnum`. 4894 type_enum_nonexhaustive, 4895 4896 /// An spirv type. 4897 /// data is index of `TypeSpirv` in extra. 4898 type_spirv, 4899 4900 /// An opaque type. 4901 /// data is extra index of `TypeOpaque`. 4902 type_opaque, 4903 4904 /// Typed `undefined`. 4905 /// `data` is `Index` of the type. 4906 /// Untyped `undefined` is stored instead via `simple_value`. 4907 undef, 4908 /// A value that can be represented with only an enum tag. 4909 simple_value, 4910 /// A pointer to a `Nav`. 4911 /// data is extra index of `PtrNav`, which contains the type and address. 4912 ptr_nav, 4913 /// A pointer to a decl that can be mutated at comptime. 4914 /// data is extra index of `PtrComptimeAlloc`, which contains the type and address. 4915 ptr_comptime_alloc, 4916 /// A pointer to an anonymous addressable value. 4917 /// data is extra index of `PtrUav`, which contains the pointer type and decl value. 4918 /// The alignment of the uav is communicated via the pointer type. 4919 ptr_uav, 4920 /// A pointer to an unnamed addressable value. 4921 /// data is extra index of `PtrUavAligned`, which contains the pointer 4922 /// type and decl value. 4923 /// The original pointer type is also provided, which will be different than `ty`. 4924 /// This encoding is only used when a pointer to a Uav is 4925 /// coerced to a different pointer type with a different alignment. 4926 ptr_uav_aligned, 4927 /// data is extra index of `PtrComptimeField`, which contains the pointer type and field value. 4928 ptr_comptime_field, 4929 /// A pointer with an integer value. 4930 /// data is extra index of `PtrInt`, which contains the type and address (byte offset from 0). 4931 /// Only pointer types are allowed to have this encoding. Optional types must use 4932 /// `opt_payload` or `opt_null`. 4933 ptr_int, 4934 /// A pointer to the payload of an error union. 4935 /// data is extra index of `PtrBase`, which contains the type and base pointer. 4936 ptr_eu_payload, 4937 /// A pointer to the payload of an optional. 4938 /// data is extra index of `PtrBase`, which contains the type and base pointer. 4939 ptr_opt_payload, 4940 /// A pointer to an array element. 4941 /// data is extra index of PtrBaseIndex, which contains the base array and element index. 4942 /// In order to use this encoding, one must ensure that the `InternPool` 4943 /// already contains the elem pointer type corresponding to this payload. 4944 ptr_elem, 4945 /// A pointer to a container field. 4946 /// data is extra index of PtrBaseIndex, which contains the base container and field index. 4947 ptr_field, 4948 /// A slice. 4949 /// data is extra index of PtrSlice, which contains the ptr and len values 4950 ptr_slice, 4951 /// An optional value that is non-null. 4952 /// data is extra index of `TypeValue`. 4953 /// The type is the optional type (not the payload type). 4954 opt_payload, 4955 /// An optional value that is null. 4956 /// data is Index of the optional type. 4957 opt_null, 4958 /// Type: u8 4959 /// data is integer value 4960 int_u8, 4961 /// Type: u16 4962 /// data is integer value 4963 int_u16, 4964 /// Type: u32 4965 /// data is integer value 4966 int_u32, 4967 /// Type: i32 4968 /// data is integer value bitcasted to u32. 4969 int_i32, 4970 /// A usize that fits in 32 bits. 4971 /// data is integer value. 4972 int_usize, 4973 /// A comptime_int that fits in a u32. 4974 /// data is integer value. 4975 int_comptime_int_u32, 4976 /// A comptime_int that fits in an i32. 4977 /// data is integer value bitcasted to u32. 4978 int_comptime_int_i32, 4979 /// An integer value that fits in 32 bits with an explicitly provided type. 4980 /// data is extra index of `IntSmall`. 4981 int_small, 4982 /// A positive integer value. 4983 /// data is a limbs index to `Int`. 4984 int_positive, 4985 /// A negative integer value. 4986 /// data is a limbs index to `Int`. 4987 int_negative, 4988 /// An error value. 4989 /// data is extra index of `Key.Error`. 4990 error_set_error, 4991 /// An error union error. 4992 /// data is extra index of `Key.Error`. 4993 error_union_error, 4994 /// An error union payload. 4995 /// data is extra index of `TypeValue`. 4996 error_union_payload, 4997 /// An enum literal value. 4998 /// data is `NullTerminatedString` of the error name. 4999 enum_literal, 5000 /// An enum tag value. 5001 /// data is extra index of `EnumTag`. 5002 enum_tag, 5003 /// An f16 value. 5004 /// data is float value bitcasted to u16 and zero-extended. 5005 float_f16, 5006 /// An f32 value. 5007 /// data is float value bitcasted to u32. 5008 float_f32, 5009 /// An f64 value. 5010 /// data is extra index to Float64. 5011 float_f64, 5012 /// An f80 value. 5013 /// data is extra index to Float80. 5014 float_f80, 5015 /// An f128 value. 5016 /// data is extra index to Float128. 5017 float_f128, 5018 /// A c_longdouble value of 80 bits. 5019 /// data is extra index to Float80. 5020 /// This is used when a c_longdouble value is provided as an f80, because f80 has unnormalized 5021 /// values which cannot be losslessly represented as f128. It should only be used when the type 5022 /// underlying c_longdouble for the target is 80 bits. 5023 float_c_longdouble_f80, 5024 /// A c_longdouble value of 128 bits. 5025 /// data is extra index to Float128. 5026 /// This is used when a c_longdouble value is provided as any type other than an f80, since all 5027 /// other float types can be losslessly converted to and from f128. 5028 float_c_longdouble_f128, 5029 /// A comptime_float value. 5030 /// data is extra index to Float128. 5031 float_comptime_float, 5032 /// An extern function or variable. 5033 /// data is extra index to Extern. 5034 /// Some parts of the key are stored in `owner_nav`. 5035 @"extern", 5036 /// A non-extern function corresponding directly to the AST node from whence it originated. 5037 /// data is extra index to `FuncDecl`. 5038 /// Only the owner Decl is used for hashing and equality because the other 5039 /// fields can get patched up during incremental compilation. 5040 func_decl, 5041 /// A generic function instantiation. 5042 /// data is extra index to `FuncInstance`. 5043 func_instance, 5044 /// A `func_decl` or a `func_instance` that has been coerced to a different type. 5045 /// data is extra index to `FuncCoerced`. 5046 func_coerced, 5047 /// This represents the only possible value for *some* types which have 5048 /// only one possible value. Not all only-possible-values are encoded this way; 5049 /// for example structs which have all comptime fields are not encoded this way. 5050 /// The set of values that are encoded this way is: 5051 /// * An array or vector which has length 0. 5052 /// * A struct which has all fields comptime-known. 5053 /// data is Index of the type, which is known to be zero bits at runtime. 5054 only_possible_value, 5055 /// data is extra index to Key.Union. 5056 union_value, 5057 /// An array of bytes. 5058 /// data is extra index to `Bytes`. 5059 bytes, 5060 /// An instance of a struct, array, or vector. 5061 /// data is extra index to `Aggregate`. 5062 aggregate, 5063 /// An instance of an array or vector with every element being the same value. 5064 /// data is extra index to `Repeated`. 5065 repeated, 5066 /// An instance of a `packed struct` or `packed union`. 5067 /// data is extra index to `Key.Bitpack`. 5068 bitpack, 5069 5070 /// A memoized comptime function call result. 5071 /// data is extra index to `MemoizedCall` 5072 memoized_call, 5073 5074 const ErrorUnionType = Key.ErrorUnionType; 5075 const TypeValue = Key.TypeValue; 5076 const Error = Key.Error; 5077 const EnumTag = Key.EnumTag; 5078 const Union = Key.Union; 5079 const TypePointer = Key.PtrType; 5080 const TypeSpirv = Key.SpirvType; 5081 5082 const struct_packed_encoding = .{ 5083 .summary = .@"{.payload.name%summary#\"}", 5084 .payload = TypeStructPacked, 5085 .trailing = struct { 5086 type_hash: ?u64, 5087 captures: ?[]CaptureValue, 5088 field_names: []NullTerminatedString, 5089 field_types: []Index, 5090 }, 5091 .config = .{ 5092 .@"trailing.type_hash.?" = .@"payload.bits.captures_len == .reified", 5093 .@"trailing.captures.?" = .@"payload.bits.captures_len != .reified", 5094 .@"trailing.captures.?.len" = .@"@intFromEnum(payload.bits.captures_len)", 5095 .@"trailing.field_names.len" = .@"payload.fields_len", 5096 .@"trailing.field_types.len" = .@"payload.fields_len", 5097 }, 5098 }; 5099 const struct_packed_defaults_encoding = .{ 5100 .summary = .@"{.payload.name%summary#\"}", 5101 .payload = TypeStructPacked, 5102 .trailing = struct { 5103 type_hash: ?u64, 5104 captures: ?[]CaptureValue, 5105 field_names: []NullTerminatedString, 5106 field_types: []Index, 5107 field_defaults: []Index, 5108 }, 5109 .config = .{ 5110 .@"trailing.type_hash.?" = .@"payload.bits.captures_len == .reified", 5111 .@"trailing.captures.?" = .@"payload.bits.captures_len != .reified", 5112 .@"trailing.captures.?.len" = .@"@intFromEnum(payload.bits.captures_len)", 5113 .@"trailing.field_names.len" = .@"payload.fields_len", 5114 .@"trailing.field_types.len" = .@"payload.fields_len", 5115 .@"trailing.field_defaults.len" = .@"payload.fields_len", 5116 }, 5117 }; 5118 const union_packed_encoding = .{ 5119 .summary = .@"{.payload.name%summary#\"}", 5120 .payload = TypeUnionPacked, 5121 .trailing = struct { 5122 type_hash: ?u64, 5123 captures: ?[]CaptureValue, 5124 field_types: []Index, 5125 }, 5126 .config = .{ 5127 .@"trailing.type_hash.?" = .@"payload.bits.captures_len == .reified", 5128 .@"trailing.captures.?" = .@"payload.bits.captures_len != .reified", 5129 .@"trailing.captures.?.len" = .@"@intFromEnum(payload.bits.captures_len)", 5130 .@"trailing.field_types.len" = .@"payload.fields_len", 5131 }, 5132 }; 5133 const enum_explicit_encoding = .{ 5134 .summary = .@"{.payload.name%summary#\"}", 5135 .payload = TypeEnum, 5136 .trailing = struct { 5137 owner_union: ?Index, 5138 zir_index: ?TrackedInst.Index, 5139 type_hash: ?u64, 5140 captures: ?[]CaptureValue, 5141 field_value_map: MapIndex, 5142 field_names: []NullTerminatedString, 5143 field_values: []Index, 5144 }, 5145 .config = .{ 5146 .@"trailing.owner_union.?" = .@"payload.bits.captures_len == .generated_union_tag", 5147 .@"trailing.zir_index.?" = .@"payload.bits.captures_len != .generated_union_tag", 5148 .@"trailing.type_hash.?" = .@"payload.bits.captures_len == .reified", 5149 .@"trailing.captures.?" = .@"payload.bits.captures_len != .reified and payload.bits.captures_len != .generated_union_tag", 5150 .@"trailing.captures.?.len" = .@"@intFromEnum(payload.bits.captures_len)", 5151 .@"trailing.field_names.len" = .@"payload.fields_len", 5152 .@"trailing.field_values.len" = .@"payload.fields_len", 5153 }, 5154 }; 5155 const encodings = .{ 5156 .removed = .{}, 5157 5158 .type_int_signed = .{ .summary = .@"i{.data%value}", .data = u32 }, 5159 .type_int_unsigned = .{ .summary = .@"u{.data%value}", .data = u32 }, 5160 .type_array_big = .{ 5161 .summary = .@"[{.payload.len1%value} << 32 | {.payload.len0%value}:{.payload.sentinel%summary}]{.payload.child%summary}", 5162 .payload = Array, 5163 }, 5164 .type_array_small = .{ .summary = .@"[{.payload.len%value}]{.payload.child%summary}", .payload = Vector }, 5165 .type_vector = .{ .summary = .@"@Vector({.payload.len%value}, {.payload.child%summary})", .payload = Vector }, 5166 .type_pointer = .{ .summary = .@"*... {.payload.child%summary}", .payload = TypePointer }, 5167 .type_slice = .{ .summary = .@"[]... {.data.unwrapped.payload.child%summary}", .data = Index }, 5168 .type_optional = .{ .summary = .@"?{.data%summary}", .data = Index }, 5169 .type_anyframe = .{ .summary = .@"anyframe->{.data%summary}", .data = Index }, 5170 .type_error_union = .{ 5171 .summary = .@"{.payload.error_set_type%summary}!{.payload.payload_type%summary}", 5172 .payload = ErrorUnionType, 5173 }, 5174 .type_anyerror_union = .{ .summary = .@"anyerror!{.data%summary}", .data = Index }, 5175 .type_error_set = .{ .summary = .@"error{...}", .payload = ErrorSet }, 5176 .type_inferred_error_set = .{ 5177 .summary = .@"@typeInfo(@typeInfo(@TypeOf({.data%summary})).@\"fn\".return_type.?).error_union.error_set", 5178 .data = Index, 5179 }, 5180 .simple_type = .{ .summary = .@"{.index%value#.}", .index = SimpleType }, 5181 .type_tuple = .{ 5182 .summary = .@"struct {...}", 5183 .payload = TypeTuple, 5184 .trailing = struct { 5185 field_types: []Index, 5186 field_values: []Index, 5187 }, 5188 .config = .{ 5189 .@"trailing.field_types.len" = .@"payload.fields_len", 5190 .@"trailing.field_values.len" = .@"payload.fields_len", 5191 }, 5192 }, 5193 .type_function = .{ 5194 .summary = .@"fn (...) ... {.payload.return_type%summary}", 5195 .payload = TypeFunction, 5196 .trailing = struct { 5197 param_comptime_bits: ?[]u32, 5198 param_noalias_bits: ?[]u32, 5199 spirv_kernel_options: ?extern struct { x: u32, y: u32, z: u32 }, 5200 spirv_mesh_options: ?extern struct { max_primitives: u32, max_vertices: u32, x: u32, y: u32, z: u32 }, 5201 param_types: []Index, 5202 }, 5203 .config = .{ 5204 .@"trailing.param_comptime_bits.?" = .@"payload.flags.has_comptime_bits", 5205 .@"trailing.param_comptime_bits.?.len" = .@"(payload.params_len + 31) / 32", 5206 .@"trailing.param_noalias_bits.?" = .@"payload.flags.has_noalias_bits", 5207 .@"trailing.param_noalias_bits.?.len" = .@"(payload.params_len + 31) / 32", 5208 .@"trailing.spirv_kernel_options.?" = .@"payload.flags.cc.tag == .spirv_kernel or payload.flags.cc.tag == .spirv_task", 5209 .@"trailing.spirv_mesh_options.?" = .@"payload.flags.cc.tag == .spirv_mesh", 5210 .@"trailing.param_types.len" = .@"payload.params_len", 5211 }, 5212 }, 5213 5214 .type_struct = .{ 5215 .summary = .@"{.payload.name%summary#\"}", 5216 .payload = TypeStruct, 5217 .trailing = struct { 5218 type_hash: ?u64, 5219 captures_len: ?u32, 5220 captures: ?[]CaptureValue, 5221 field_names: []NullTerminatedString, 5222 field_types: []Index, 5223 field_defaults: ?[]Index, 5224 field_aligns: ?[]Alignment, 5225 field_is_comptime_bits: ?[]u32, 5226 field_runtime_order: ?[]u32, 5227 field_offsets: []u32, 5228 }, 5229 .config = .{ 5230 .@"trailing.type_hash.?" = .@"payload.flags.any_captures == .reified", 5231 .@"trailing.captures_len.?" = .@"payload.flags.any_captures == .true", 5232 .@"trailing.captures.?" = .@"payload.flags.any_captures == .true", 5233 .@"trailing.captures.?.len" = .@"trailing.captures_len.?", 5234 .@"trailing.field_names.len" = .@"payload.fields_len", 5235 .@"trailing.field_types.len" = .@"payload.fields_len", 5236 .@"trailing.field_defaults.?" = .@"payload.flags.any_field_defaults", 5237 .@"trailing.field_defaults.?.len" = .@"payload.fields_len", 5238 .@"trailing.field_aligns.?" = .@"payload.flags.any_field_aligns", 5239 .@"trailing.field_aligns.?.len" = .@"(payload.fields_len + 3) / 4", 5240 .@"trailing.field_is_comptime_bits.?" = .@"payload.flags.any_comptime_fields", 5241 .@"trailing.field_is_comptime_bits.?.len" = .@"(payload.fields_len + 31) / 32", 5242 .@"trailing.field_runtime_order.?" = .@"payload.flags.layout == .auto", 5243 .@"trailing.field_runtime_order.?.len" = .@"payload.fields_len", 5244 .@"trailing.field_offsets.len" = .@"payload.fields_len", 5245 }, 5246 }, 5247 .type_struct_packed_auto = struct_packed_encoding, 5248 .type_struct_packed_explicit = struct_packed_encoding, 5249 .type_struct_packed_auto_defaults = struct_packed_defaults_encoding, 5250 .type_struct_packed_explicit_defaults = struct_packed_defaults_encoding, 5251 .type_union = .{ 5252 .summary = .@"{.payload.name%summary#\"}", 5253 .payload = TypeUnion, 5254 .trailing = struct { 5255 type_hash: ?u64, 5256 captures_len: ?u32, 5257 captures: ?[]CaptureValue, 5258 field_types: []Index, 5259 field_aligns: ?[]Alignment, 5260 }, 5261 .config = .{ 5262 .@"trailing.type_hash.?" = .@"payload.flags.any_captures == .reified", 5263 .@"trailing.captures_len.?" = .@"payload.flags.any_captures == .true", 5264 .@"trailing.captures.?" = .@"payload.flags.any_captures == .true", 5265 .@"trailing.captures.?.len" = .@"trailing.captures_len.?", 5266 .@"trailing.field_types.len" = .@"payload.fields_len", 5267 .@"trailing.field_aligns.?" = .@"payloads.flags.any_field_aligns", 5268 .@"trailing.field_aligns.?.len" = .@"(payload.fields_len + 3) / 4", 5269 }, 5270 }, 5271 .type_union_packed_auto = union_packed_encoding, 5272 .type_union_packed_explicit = union_packed_encoding, 5273 .type_enum_auto = .{ 5274 .summary = .@"{.payload.name%summary#\"}", 5275 .payload = TypeEnum, 5276 .trailing = struct { 5277 owner_union: ?Index, 5278 zir_index: ?TrackedInst.Index, 5279 type_hash: ?u64, 5280 captures: ?[]CaptureValue, 5281 field_names: []NullTerminatedString, 5282 }, 5283 .config = .{ 5284 .@"trailing.owner_union.?" = .@"payload.bits.captures_len == .generated_union_tag", 5285 .@"trailing.zir_index.?" = .@"payload.bits.captures_len != .generated_union_tag", 5286 .@"trailing.type_hash.?" = .@"payload.bits.captures_len == .reified", 5287 .@"trailing.captures.?" = .@"payload.bits.captures_len != .reified and payload.bits.captures_len != .generated_union_tag", 5288 .@"trailing.captures.?.len" = .@"@intFromEnum(payload.bits.captures_len)", 5289 .@"trailing.field_names.len" = .@"payload.fields_len", 5290 }, 5291 }, 5292 .type_enum_explicit = enum_explicit_encoding, 5293 .type_enum_nonexhaustive = enum_explicit_encoding, 5294 .type_spirv = .{ .payload = Tag.TypeSpirv }, 5295 .type_opaque = .{ 5296 .summary = .@"{.payload.name%summary#\"}", 5297 .payload = TypeOpaque, 5298 .trailing = struct { captures: []CaptureValue }, 5299 .config = .{ .@"trailing.captures.len" = .@"payload.captures_len" }, 5300 }, 5301 5302 .undef = .{ .summary = .@"@as({.data%summary}, undefined)", .data = Index }, 5303 .simple_value = .{ .summary = .@"{.index%value#.}", .index = SimpleValue }, 5304 .ptr_nav = .{ 5305 .summary = .@"@as({.payload.ty%summary}, @ptrFromInt(@intFromPtr(&{.payload.nav.fqn%summary#\"}) + ({.payload.byte_offset_a%value} << 32 | {.payload.byte_offset_b%value})))", 5306 .payload = PtrNav, 5307 }, 5308 .ptr_comptime_alloc = .{ 5309 .summary = .@"@as({.payload.ty%summary}, @ptrFromInt(@intFromPtr(&comptime_allocs[{.payload.index%summary}]) + ({.payload.byte_offset_a%value} << 32 | {.payload.byte_offset_b%value})))", 5310 .payload = PtrComptimeAlloc, 5311 }, 5312 .ptr_uav = .{ 5313 .summary = .@"@as({.payload.ty%summary}, @ptrFromInt(@intFromPtr(&{.payload.val%summary}) + ({.payload.byte_offset_a%value} << 32 | {.payload.byte_offset_b%value})))", 5314 .payload = PtrUav, 5315 }, 5316 .ptr_uav_aligned = .{ 5317 .summary = .@"@as({.payload.ty%summary}, @ptrFromInt(@intFromPtr(@as({.payload.orig_ty%summary}, &{.payload.val%summary})) + ({.payload.byte_offset_a%value} << 32 | {.payload.byte_offset_b%value})))", 5318 .payload = PtrUavAligned, 5319 }, 5320 .ptr_comptime_field = .{ 5321 .summary = .@"@as({.payload.ty%summary}, @ptrFromInt(@intFromPtr(&{.payload.field_val%summary}) + ({.payload.byte_offset_a%value} << 32 | {.payload.byte_offset_b%value})))", 5322 .payload = PtrComptimeField, 5323 }, 5324 .ptr_int = .{ 5325 .summary = .@"@as({.payload.ty%summary}, @ptrFromInt({.payload.byte_offset_a%value} << 32 | {.payload.byte_offset_b%value}))", 5326 .payload = PtrInt, 5327 }, 5328 .ptr_eu_payload = .{ 5329 .summary = .@"@as({.payload.ty%summary}, @ptrFromInt(@intFromPtr(&({.payload.base%summary} catch unreachable)) + ({.payload.byte_offset_a%value} << 32 | {.payload.byte_offset_b%value})))", 5330 .payload = PtrBase, 5331 }, 5332 .ptr_opt_payload = .{ 5333 .summary = .@"@as({.payload.ty%summary}, @ptrFromInt(@intFromPtr(&{.payload.base%summary}.?) + ({.payload.byte_offset_a%value} << 32 | {.payload.byte_offset_b%value})))", 5334 .payload = PtrBase, 5335 }, 5336 .ptr_elem = .{ 5337 .summary = .@"@as({.payload.ty%summary}, @ptrFromInt(@intFromPtr(&{.payload.base%summary}[{.payload.index%summary}]) + ({.payload.byte_offset_a%value} << 32 | {.payload.byte_offset_b%value})))", 5338 .payload = PtrBaseIndex, 5339 }, 5340 .ptr_field = .{ 5341 .summary = .@"@as({.payload.ty%summary}, @ptrFromInt(@intFromPtr(&{.payload.base%summary}[{.payload.index%summary}]) + ({.payload.byte_offset_a%value} << 32 | {.payload.byte_offset_b%value})))", 5342 .payload = PtrBaseIndex, 5343 }, 5344 .ptr_slice = .{ 5345 .summary = .@"{.payload.ptr%summary}[0..{.payload.len%summary}]", 5346 .payload = PtrSlice, 5347 }, 5348 .opt_payload = .{ .summary = .@"@as({.payload.ty%summary}, {.payload.val%summary})", .payload = TypeValue }, 5349 .opt_null = .{ .summary = .@"@as({.data%summary}, null)", .data = Index }, 5350 .int_u8 = .{ .summary = .@"@as(u8, {.data%value})", .data = u8 }, 5351 .int_u16 = .{ .summary = .@"@as(u16, {.data%value})", .data = u16 }, 5352 .int_u32 = .{ .summary = .@"@as(u32, {.data%value})", .data = u32 }, 5353 .int_i32 = .{ .summary = .@"@as(i32, {.data%value})", .data = i32 }, 5354 .int_usize = .{ .summary = .@"@as(usize, {.data%value})", .data = u32 }, 5355 .int_comptime_int_u32 = .{ .summary = .@"{.data%value}", .data = u32 }, 5356 .int_comptime_int_i32 = .{ .summary = .@"{.data%value}", .data = i32 }, 5357 .int_small = .{ .summary = .@"@as({.payload.ty%summary}, {.payload.value%value})", .payload = IntSmall }, 5358 .int_positive = .{}, 5359 .int_negative = .{}, 5360 .error_set_error = .{ .summary = .@"@as({.payload.ty%summary}, error.@{.payload.name%summary})", .payload = Error }, 5361 .error_union_error = .{ .summary = .@"@as({.payload.ty%summary}, error.@{.payload.name%summary})", .payload = Error }, 5362 .error_union_payload = .{ .summary = .@"@as({.payload.ty%summary}, {.payload.val%summary})", .payload = TypeValue }, 5363 .enum_literal = .{ .summary = .@".@{.data%summary}", .data = NullTerminatedString }, 5364 .enum_tag = .{ .summary = .@"@as({.payload.ty%summary}, @enumFromInt({.payload.int%summary}))", .payload = EnumTag }, 5365 .float_f16 = .{ .summary = .@"@as(f16, {.data%value})", .data = f16 }, 5366 .float_f32 = .{ .summary = .@"@as(f32, {.data%value})", .data = f32 }, 5367 .float_f64 = .{ .summary = .@"@as(f64, {.payload%value})", .payload = f64 }, 5368 .float_f80 = .{ .summary = .@"@as(f80, {.payload%value})", .payload = f80 }, 5369 .float_f128 = .{ .summary = .@"@as(f128, {.payload%value})", .payload = f128 }, 5370 .float_c_longdouble_f80 = .{ .summary = .@"@as(c_longdouble, {.payload%value})", .payload = f80 }, 5371 .float_c_longdouble_f128 = .{ .summary = .@"@as(c_longdouble, {.payload%value})", .payload = f128 }, 5372 .float_comptime_float = .{ .summary = .@"{.payload%value}", .payload = f128 }, 5373 .@"extern" = .{ .summary = .@"{.payload.owner_nav.fqn%summary#\"}", .payload = Extern }, 5374 .func_decl = .{ 5375 .summary = .@"{.payload.owner_nav.fqn%summary#\"}", 5376 .payload = FuncDecl, 5377 .trailing = struct { inferred_error_set: ?Index }, 5378 .config = .{ .@"trailing.inferred_error_set.?" = .@"payload.analysis.inferred_error_set" }, 5379 }, 5380 .func_instance = .{ 5381 .summary = .@"{.payload.owner_nav.fqn%summary#\"}", 5382 .payload = FuncInstance, 5383 .trailing = struct { 5384 inferred_error_set: ?Index, 5385 param_values: []Index, 5386 }, 5387 .config = .{ 5388 .@"trailing.inferred_error_set.?" = .@"payload.analysis.inferred_error_set", 5389 .@"trailing.param_values.len" = .@"payload.ty.payload.params_len", 5390 }, 5391 }, 5392 .func_coerced = .{ 5393 .summary = .@"@as(*const {.payload.ty%summary}, @ptrCast(&{.payload.func%summary})).*", 5394 .payload = FuncCoerced, 5395 }, 5396 .only_possible_value = .{ .summary = .@"@as({.data%summary}, undefined)", .data = Index }, 5397 .union_value = .{ .summary = .@"@as({.payload.ty%summary}, {})", .payload = Union }, 5398 .bytes = .{ .summary = .@"@as({.payload.ty%summary}, {.payload.bytes%summary}.*)", .payload = Bytes }, 5399 .aggregate = .{ 5400 .summary = .@"@as({.payload.ty%summary}, .{...})", 5401 .payload = Aggregate, 5402 .trailing = struct { elements: []Index }, 5403 .config = .{ .@"trailing.elements.len" = .@"payload.ty.payload.fields_len" }, 5404 }, 5405 .repeated = .{ .summary = .@"@as({.payload.ty%summary}, @splat({.payload.elem_val%summary}))", .payload = Repeated }, 5406 .bitpack = .{ .summary = .@"@as({.payload.ty%summary}, {})", .payload = Key.Bitpack }, 5407 5408 .memoized_call = .{ 5409 .summary = .@"@memoize({.payload.func%summary})", 5410 .payload = MemoizedCall, 5411 .trailing = struct { arg_values: []Index }, 5412 .config = .{ .@"trailing.arg_values.len" = .@"payload.args_len" }, 5413 }, 5414 }; 5415 fn Payload(comptime tag: Tag) type { 5416 return @field(encodings, @tagName(tag)).payload; 5417 } 5418 5419 pub const Extern = struct { 5420 // name, is_const, alignment, addrspace come from `owner_nav`. 5421 ty: Index, 5422 lib_name: OptionalNullTerminatedString, 5423 flags: Flags, 5424 owner_nav: Nav.Index, 5425 zir_index: TrackedInst.Index, 5426 location_or_descriptor_set: u32, 5427 descriptor_binding: u32, 5428 5429 pub const Flags = packed struct(u32) { 5430 linkage: std.lang.GlobalLinkage, 5431 visibility: std.lang.SymbolVisibility, 5432 is_dll_import: bool, 5433 relocation: std.lang.ExternOptions.Relocation, 5434 source: Source, 5435 decoration_type: DecorationType, 5436 _: u23 = 0, 5437 5438 pub const Source = enum(u1) { builtin, syntax }; 5439 pub const DecorationType = enum(u2) { none, location, descriptor, flat }; 5440 }; 5441 5442 pub fn decoration(self: Extern) ?std.lang.ExternOptions.Decoration { 5443 return switch (self.flags.decoration_type) { 5444 .none => null, 5445 .location => std.lang.ExternOptions.Decoration{ .location = self.location_or_descriptor_set }, 5446 .descriptor => std.lang.ExternOptions.Decoration{ .descriptor = .{ .set = self.location_or_descriptor_set, .binding = self.descriptor_binding } }, 5447 .flat => std.lang.ExternOptions.Decoration{ .flat = self.location_or_descriptor_set }, 5448 }; 5449 } 5450 }; 5451 5452 /// Trailing: 5453 /// 0. element: Index for each len 5454 /// len is determined by the aggregate type. 5455 pub const Aggregate = struct { 5456 /// The type of the aggregate. 5457 ty: Index, 5458 }; 5459 5460 /// Trailing: 5461 /// 0. If `analysis.inferred_error_set` is `true`, `Index` of an `error_set` which 5462 /// is a regular error set corresponding to the finished inferred error set. 5463 /// A `none` value marks that the inferred error set is not resolved yet. 5464 pub const FuncDecl = struct { 5465 analysis: FuncAnalysis, 5466 owner_nav: Nav.Index, 5467 ty: Index, 5468 zir_body_inst: TrackedInst.Index, 5469 lbrace_line: u32, 5470 rbrace_line: u32, 5471 lbrace_column: u32, 5472 rbrace_column: u32, 5473 }; 5474 5475 /// Trailing: 5476 /// 0. If `analysis.inferred_error_set` is `true`, `Index` of an `error_set` which 5477 /// is a regular error set corresponding to the finished inferred error set. 5478 /// A `none` value marks that the inferred error set is not resolved yet. 5479 /// 1. For each parameter of generic_owner: `Index` if comptime, otherwise `none` 5480 pub const FuncInstance = struct { 5481 analysis: FuncAnalysis, 5482 // Needed by the linker for codegen. Not part of hashing or equality. 5483 owner_nav: Nav.Index, 5484 ty: Index, 5485 branch_quota: u32, 5486 /// Points to a `FuncDecl`. 5487 generic_owner: Index, 5488 }; 5489 5490 pub const FuncCoerced = struct { 5491 ty: Index, 5492 func: Index, 5493 }; 5494 5495 /// Trailing: 5496 /// 0. name: NullTerminatedString for each names_len 5497 pub const ErrorSet = struct { 5498 names_len: u32, 5499 /// Maps error names to declaration index. 5500 names_map: MapIndex, 5501 }; 5502 5503 /// Trailing: 5504 /// 0. comptime_bits: u32, // if has_comptime_bits 5505 /// 1. noalias_bits: u32, // if has_noalias_bits 5506 /// 2. param_type: Index for each params_len 5507 pub const TypeFunction = struct { 5508 params_len: u32, 5509 return_type: Index, 5510 flags: Flags, 5511 5512 pub const Flags = packed struct(u32) { 5513 cc: PackedCallingConvention, 5514 is_var_args: bool, 5515 has_comptime_bits: bool, 5516 has_noalias_bits: bool, 5517 is_noinline: bool, 5518 _: u10 = 0, 5519 }; 5520 }; 5521 5522 /// At first I thought of storing the denormalized data externally, such as... 5523 /// 5524 /// * runtime field order 5525 /// * calculated field offsets 5526 /// * size and alignment of the struct 5527 /// 5528 /// ...since these can be computed based on the other data here. However, 5529 /// this data does need to be memoized, and therefore stored in memory 5530 /// while the compiler is running, in order to avoid O(N^2) logic in many 5531 /// places. Since the data can be stored compactly in the InternPool 5532 /// representation, it is better for memory usage to store denormalized data 5533 /// here, and potentially also better for performance as well. It's also simpler 5534 /// than coming up with some other scheme for the data. 5535 /// 5536 /// Trailing: 5537 /// 0. type_hash: PackedU64 // if `any_captures == .reified` 5538 /// 1. captures_len: u32 // if `any_captures == .true` 5539 /// 2. capture: CaptureValue // for each `captures_len` 5540 /// 3. field_name: NullTerminatedString // for each `fields_len` 5541 /// 4. field_type: Index // for each `fields_len` 5542 /// 5. field_default: Index // if `any_field_defaults`; for each `fields_len` 5543 /// 6. field_align: Alignment // if `any_field_aligns`; for each `fields_len` 5544 /// 7. field_is_comptime_bits: u32 // if `any_comptime_fields`; minimum `u32` for `fields_len`; LSB is field 0 5545 /// 8. field_runtime_order: RuntimeOrder // if `layout == .auto`; for each `fields_len` 5546 /// 9. field_offset: u32 // for each `fields_len` 5547 pub const TypeStruct = struct { 5548 zir_index: TrackedInst.Index, 5549 5550 name: NullTerminatedString, 5551 fqn: NullTerminatedString, 5552 name_nav: Nav.Index.Optional, 5553 namespace: NamespaceIndex, 5554 5555 fields_len: u32, 5556 field_name_map: MapIndex, 5557 5558 /// Size in bytes of the whole struct. Always 0 until layout resolved. 5559 size: u32, 5560 5561 flags: Flags, 5562 5563 pub const Flags = packed struct(u32) { 5564 any_captures: enum(u2) { true, false, reified }, 5565 5566 /// `packed` layout is represented separately by `TypeStructPacked`. 5567 layout: enum(u1) { auto, @"extern" }, 5568 5569 any_comptime_fields: bool, 5570 any_field_defaults: bool, 5571 any_field_aligns: bool, 5572 5573 class: TypeClass, 5574 /// Alignment of the whole struct. Always `.none` until layout resolved. 5575 alignment: Alignment, 5576 5577 want_layout: bool, 5578 5579 _: u16 = 0, 5580 }; 5581 }; 5582 5583 /// Trailing: 5584 /// 0. type_hash: PackedU64 // if `captures_len == .reified` 5585 /// 1. capture: CaptureValue // if `captures_len != .reified`; for each `captures_len` 5586 /// 2. field_name: NullTerminatedString // for each `fields_len` 5587 /// 3. field_type: Index // for each `fields_len` 5588 /// 4. field_default: Index // if item tag implies field defaults; for each `fields_len` 5589 pub const TypeStructPacked = struct { 5590 zir_index: TrackedInst.Index, 5591 bits: Bits, 5592 5593 name: NullTerminatedString, 5594 fqn: NullTerminatedString, 5595 name_nav: Nav.Index.Optional, 5596 namespace: NamespaceIndex, 5597 5598 /// The corresponding `BackingTypeMode` depends on the item's `Tag`. 5599 backing_int_type: Index, 5600 5601 fields_len: u32, 5602 field_name_map: MapIndex, 5603 5604 const Bits = packed struct(u32) { 5605 captures_len: enum(u31) { 5606 reified = std.math.maxInt(u31), 5607 _, 5608 }, 5609 want_layout: bool, 5610 }; 5611 }; 5612 5613 /// For declared unions, field names are intentionally omitted because they are available in 5614 /// `enum_tag_type`. However, reified unions do store field names, because they are needed by 5615 /// type resolution to create or validate the enum tag type (type resolution for declared unions 5616 /// instead fetches field names from ZIR). 5617 /// 5618 /// Trailing: 5619 /// 0. type_hash: PackedU64 // if `any_captures == .reified` 5620 /// 1. captures_len: u32 // if `any_captures == .true` 5621 /// 2. capture: CaptureValue // if `any_captures == .true`; for each `captures_len` 5622 /// 3. reified_field_name: NullTerminatedString // if `any_captures == .reified`; for each `fields_len` 5623 /// 4. field_type: Index // for each `fields_len` 5624 /// 5. field_align: Alignment // for each `fields_len` if `any_field_aligns` 5625 pub const TypeUnion = struct { 5626 zir_index: TrackedInst.Index, 5627 5628 name: NullTerminatedString, 5629 fqn: NullTerminatedString, 5630 name_nav: Nav.Index.Optional, 5631 namespace: NamespaceIndex, 5632 /// The enum that provides the list of field names and values. 5633 enum_tag_type: Index, 5634 5635 /// This could be provided through the tag type, but it is more convenient 5636 /// to store it directly. This is also necessary for `dumpStatsFallible` to 5637 /// work on unresolved types. 5638 fields_len: u32, 5639 5640 /// Always 0 until layout resolved. 5641 size: u32, 5642 /// Always 0 until layout resolved. 5643 padding: u32, 5644 5645 flags: Flags, 5646 5647 pub const Flags = packed struct(u32) { 5648 any_captures: enum(u2) { true, false, reified }, 5649 5650 /// Whether `enum_tag_type` was explicitly specified with `union(E)` syntax. 5651 /// 5652 /// For `union(enum(E))` syntax, this is `false`, but the generated enum tag type is 5653 /// considered to have an explicitly specified integer tag type. 5654 enum_tag_mode: BackingTypeMode, 5655 5656 /// `packed` layout is represented separately by `TypeStructPacked`. 5657 layout: enum(u1) { auto, @"extern" }, 5658 5659 any_field_aligns: bool, 5660 tag_usage: LoadedUnionType.TagUsage, 5661 5662 class: TypeClass, 5663 has_runtime_tag: bool, 5664 5665 /// Alignment of the whole union. Always `.none` until layout resolved. 5666 alignment: Alignment, 5667 5668 want_layout: bool, 5669 5670 _: u14 = 0, 5671 }; 5672 }; 5673 5674 /// For declared unions, field names are intentionally omitted because they are available in 5675 /// `enum_tag_type`. However, reified unions do store field names, because they are needed by 5676 /// type resolution to create or validate the enum tag type (type resolution for declared unions 5677 /// instead fetches field names from ZIR). 5678 /// 5679 /// Trailing: 5680 /// 0. type_hash: PackedU64 // if `captures_len == .reified` 5681 /// 1. capture: CaptureValue // if `captures_len != .reified`; for each `captures_len` 5682 /// 2. reified_field_name: NullTerminatedString // if `captures_len == .reified`; for each `fields_len` 5683 /// 3. field_type: Index // for each `fields_len` 5684 pub const TypeUnionPacked = struct { 5685 zir_index: TrackedInst.Index, 5686 bits: Bits, 5687 5688 name: NullTerminatedString, 5689 fqn: NullTerminatedString, 5690 name_nav: Nav.Index.Optional, 5691 namespace: NamespaceIndex, 5692 5693 /// The corresponding `BackingTypeMode` depends on the item's `Tag`. 5694 backing_int_type: Index, 5695 /// Although packed unions do not semantically have a tag type, the compiler still assigns 5696 /// them a "hypothetical" tag type. 5697 enum_tag_type: Index, 5698 5699 /// This could be provided through the tag type, but it is more convenient 5700 /// to store it directly. This is also necessary for `dumpStatsFallible` to 5701 /// work on unresolved types. 5702 fields_len: u32, 5703 5704 const Bits = packed struct(u32) { 5705 captures_len: enum(u31) { 5706 reified = std.math.maxInt(u31), 5707 _, 5708 }, 5709 want_layout: bool, 5710 }; 5711 }; 5712 5713 /// Trailing: 5714 /// 0. owner_union: Index // if `captures_len == .generated_union_tag` 5715 /// 1. zir_index: TrackedInst.Index // if `captures_len != .generated_union_tag` 5716 /// 2. type_hash: PackedU64 // if `captures_len == .reified` 5717 /// 3. capture: CaptureValue // if `captures_len` is not a named tag; for each `captures_len` 5718 /// 4. field_value_map: MapIndex // if tag is not `.type_enum_auto` 5719 /// 5. field_name: NullTerminatedString // for each `fields_len` 5720 /// 6. field_value: Index // if tag is not `.type_enum_auto`; for each `fields_len` 5721 pub const TypeEnum = struct { 5722 bits: Bits, 5723 5724 name: NullTerminatedString, 5725 fqn: NullTerminatedString, 5726 name_nav: Nav.Index.Optional, 5727 namespace: NamespaceIndex, 5728 5729 /// An integer type which is used for the numerical value of the enum. Whether this was 5730 /// user-provided or inferred by the compiler depends on the tag. 5731 int_tag_type: Index, 5732 5733 fields_len: u32, 5734 field_name_map: MapIndex, 5735 5736 const Bits = packed struct(u32) { 5737 captures_len: enum(u31) { 5738 reified = std.math.maxInt(u31), 5739 generated_union_tag = std.math.maxInt(u31) - 1, 5740 _, 5741 }, 5742 want_layout: bool, 5743 }; 5744 }; 5745 5746 /// Trailing: 5747 /// 0. capture: CaptureValue // for each `captures_len` 5748 pub const TypeOpaque = struct { 5749 zir_index: TrackedInst.Index, 5750 captures_len: u32, 5751 5752 name: NullTerminatedString, 5753 fqn: NullTerminatedString, 5754 name_nav: Nav.Index.Optional, 5755 namespace: NamespaceIndex, 5756 }; 5757 }; 5758 5759 /// Differentiates between user-provided and compiler-generated backing types for packed and tagged types. 5760 pub const BackingTypeMode = enum(u1) { 5761 /// The backing type was explicitly provided by the user. For instance: 5762 /// union(T) 5763 /// enum(T) 5764 /// packed struct(T) 5765 /// packed union(T) 5766 /// Type layout resolution will evaluate the user-provided expression and validate that type. 5767 explicit, 5768 /// No backing type was explicitly provided by the user. Type layout resolution will populate 5769 /// an inferred/generated type. 5770 auto, 5771 }; 5772 5773 /// State that is mutable during semantic analysis. This data is not used for 5774 /// equality or hashing, except for `inferred_error_set` which is considered 5775 /// to be part of the type of the function. 5776 pub const FuncAnalysis = packed struct(u32) { 5777 want_runtime_analysis: bool, 5778 branch_hint: std.lang.BranchHint, 5779 is_noinline: bool, 5780 has_error_trace: bool, 5781 /// True if this function has an inferred error set. 5782 inferred_error_set: bool, 5783 disable_instrumentation: bool, 5784 disable_intrinsics: bool, 5785 5786 _: u23 = 0, 5787 }; 5788 5789 pub const Bytes = struct { 5790 /// The type of the aggregate 5791 ty: Index, 5792 /// Index into strings, of len ip.aggregateTypeLen(ty) 5793 bytes: String, 5794 }; 5795 5796 pub const Repeated = struct { 5797 /// The type of the aggregate. 5798 ty: Index, 5799 /// The value of every element. 5800 elem_val: Index, 5801 }; 5802 5803 /// Trailing: 5804 /// 0. type: Index for each fields_len 5805 /// 1. value: Index for each fields_len 5806 pub const TypeTuple = struct { 5807 fields_len: u32, 5808 }; 5809 5810 /// Having `SimpleType` and `SimpleValue` in separate enums makes it easier to 5811 /// implement logic that only wants to deal with types because the logic can 5812 /// ignore all simple values. Note that technically, types are values. 5813 pub const SimpleType = enum(u32) { 5814 f16 = @backingInt(Index.f16_type), 5815 f32 = @backingInt(Index.f32_type), 5816 f64 = @backingInt(Index.f64_type), 5817 f80 = @backingInt(Index.f80_type), 5818 f128 = @backingInt(Index.f128_type), 5819 usize = @backingInt(Index.usize_type), 5820 isize = @backingInt(Index.isize_type), 5821 c_char = @backingInt(Index.c_char_type), 5822 c_short = @backingInt(Index.c_short_type), 5823 c_ushort = @backingInt(Index.c_ushort_type), 5824 c_int = @backingInt(Index.c_int_type), 5825 c_uint = @backingInt(Index.c_uint_type), 5826 c_long = @backingInt(Index.c_long_type), 5827 c_ulong = @backingInt(Index.c_ulong_type), 5828 c_longlong = @backingInt(Index.c_longlong_type), 5829 c_ulonglong = @backingInt(Index.c_ulonglong_type), 5830 c_longdouble = @backingInt(Index.c_longdouble_type), 5831 anyopaque = @backingInt(Index.anyopaque_type), 5832 bool = @backingInt(Index.bool_type), 5833 void = @backingInt(Index.void_type), 5834 type = @backingInt(Index.type_type), 5835 anyerror = @backingInt(Index.anyerror_type), 5836 comptime_int = @backingInt(Index.comptime_int_type), 5837 comptime_float = @backingInt(Index.comptime_float_type), 5838 noreturn = @backingInt(Index.noreturn_type), 5839 null = @backingInt(Index.null_type), 5840 undefined = @backingInt(Index.undefined_type), 5841 enum_literal = @backingInt(Index.enum_literal_type), 5842 5843 adhoc_inferred_error_set = @backingInt(Index.adhoc_inferred_error_set_type), 5844 generic_poison = @backingInt(Index.generic_poison_type), 5845 }; 5846 5847 pub const SimpleValue = enum(u32) { 5848 void = @backingInt(Index.void_value), 5849 /// This is untyped `null`. 5850 null = @backingInt(Index.null_value), 5851 true = @backingInt(Index.bool_true), 5852 false = @backingInt(Index.bool_false), 5853 @"unreachable" = @backingInt(Index.unreachable_value), 5854 }; 5855 5856 /// Stored as a power-of-two, with one special value to indicate none. 5857 pub const Alignment = enum(u6) { 5858 @"1" = 0, 5859 @"2" = 1, 5860 @"4" = 2, 5861 @"8" = 3, 5862 @"16" = 4, 5863 @"32" = 5, 5864 @"64" = 6, 5865 none = std.math.maxInt(u6), 5866 _, 5867 5868 pub fn toByteUnits(a: Alignment) ?u64 { 5869 return switch (a) { 5870 .none => null, 5871 else => @as(u64, 1) << @backingInt(a), 5872 }; 5873 } 5874 5875 pub fn fromByteUnits(n: u64) Alignment { 5876 if (n == 0) return .none; 5877 assert(std.math.isPowerOfTwo(n)); 5878 return @fromBackingInt(@intCast(@ctz(n))); 5879 } 5880 5881 pub fn fromNonzeroByteUnits(n: u64) Alignment { 5882 assert(n != 0); 5883 return fromByteUnits(n); 5884 } 5885 5886 pub fn toLog2Units(a: Alignment) u6 { 5887 assert(a != .none); 5888 return @backingInt(a); 5889 } 5890 5891 /// This is just a glorified `@enumFromInt` but using it can help 5892 /// document the intended conversion. 5893 /// The parameter uses a u32 for convenience at the callsite. 5894 pub fn fromLog2Units(a: u32) Alignment { 5895 assert(a != @backingInt(Alignment.none)); 5896 return @fromBackingInt(@intCast(a)); 5897 } 5898 5899 pub fn order(lhs: Alignment, rhs: Alignment) std.math.Order { 5900 assert(lhs != .none); 5901 assert(rhs != .none); 5902 return std.math.order(@backingInt(lhs), @backingInt(rhs)); 5903 } 5904 5905 /// Relaxed comparison. We have this as default because a lot of callsites 5906 /// were upgraded from directly using comparison operators on byte units, 5907 /// with the `none` value represented by zero. 5908 /// Prefer `compareStrict` if possible. 5909 pub fn compare(lhs: Alignment, op: std.math.CompareOperator, rhs: Alignment) bool { 5910 return std.math.compare(lhs.toRelaxedCompareUnits(), op, rhs.toRelaxedCompareUnits()); 5911 } 5912 5913 pub fn compareStrict(lhs: Alignment, op: std.math.CompareOperator, rhs: Alignment) bool { 5914 assert(lhs != .none); 5915 assert(rhs != .none); 5916 return std.math.compare(@backingInt(lhs), op, @backingInt(rhs)); 5917 } 5918 5919 /// Treats `none` as zero. 5920 /// This matches previous behavior of using `@max` directly on byte units. 5921 /// Prefer `maxStrict` if possible. 5922 pub fn max(lhs: Alignment, rhs: Alignment) Alignment { 5923 if (lhs == .none) return rhs; 5924 if (rhs == .none) return lhs; 5925 return maxStrict(lhs, rhs); 5926 } 5927 5928 pub fn maxStrict(lhs: Alignment, rhs: Alignment) Alignment { 5929 assert(lhs != .none); 5930 assert(rhs != .none); 5931 return @fromBackingInt(@intCast(@max(@backingInt(lhs), @backingInt(rhs)))); 5932 } 5933 5934 /// Treats `none` as zero. 5935 /// This matches previous behavior of using `@min` directly on byte units. 5936 /// Prefer `minStrict` if possible. 5937 pub fn min(lhs: Alignment, rhs: Alignment) Alignment { 5938 if (lhs == .none) return lhs; 5939 if (rhs == .none) return rhs; 5940 return minStrict(lhs, rhs); 5941 } 5942 5943 pub fn minStrict(lhs: Alignment, rhs: Alignment) Alignment { 5944 assert(lhs != .none); 5945 assert(rhs != .none); 5946 return @fromBackingInt(@intCast(@min(@backingInt(lhs), @backingInt(rhs)))); 5947 } 5948 5949 /// Given a base address known to be aligned to `a`, 5950 /// computes the known alignment of base address plus `off`. 5951 pub fn offset(a: Alignment, off: u64) Alignment { 5952 return .fromLog2Units(@min(a.toLog2Units(), @ctz(off))); 5953 } 5954 5955 /// Align an address forwards to this alignment. 5956 pub fn forward(a: Alignment, addr: u64) u64 { 5957 assert(a != .none); 5958 const x = (@as(u64, 1) << @backingInt(a)) - 1; 5959 return (addr + x) & ~x; 5960 } 5961 5962 /// Align an address backwards to this alignment. 5963 pub fn backward(a: Alignment, addr: u64) u64 { 5964 assert(a != .none); 5965 const x = (@as(u64, 1) << @backingInt(a)) - 1; 5966 return addr & ~x; 5967 } 5968 5969 /// Check if an address is aligned to this amount. 5970 pub fn check(a: Alignment, addr: u64) bool { 5971 assert(a != .none); 5972 return @ctz(addr) >= @backingInt(a); 5973 } 5974 5975 /// An array of `Alignment` objects existing within the `extra` array. 5976 /// This type exists to provide a struct with lifetime that is 5977 /// not invalidated when items are added to the `InternPool`. 5978 pub const Slice = struct { 5979 tid: Zcu.PerThread.Id, 5980 start: u32, 5981 /// This is the number of alignment values, not the number of u32 elements. 5982 len: u32, 5983 5984 pub const empty: Slice = .{ .tid = .main, .start = 0, .len = 0 }; 5985 5986 pub fn get(slice: Slice, ip: *const InternPool) []Alignment { 5987 const extra = ip.getLocalShared(slice.tid).extra.acquire(); 5988 const bytes: []u8 = @ptrCast(extra.view().items(.@"0")[slice.start..]); 5989 return @ptrCast(bytes[0..slice.len]); 5990 } 5991 5992 /// If `slice` is empty (`slice.len == 0`), returns `.none`. 5993 /// Otherwise, asserts that `index < slice.len`, and returns the value at `index`. 5994 pub fn getOrNone(slice: Slice, ip: *const InternPool, index: usize) Alignment { 5995 if (slice.len == 0) return .none; 5996 return slice.get(ip)[index]; 5997 } 5998 }; 5999 6000 pub fn toRelaxedCompareUnits(a: Alignment) u8 { 6001 const n: u8 = @backingInt(a); 6002 assert(n <= @backingInt(Alignment.none)); 6003 if (n == @backingInt(Alignment.none)) return 0; 6004 return n + 1; 6005 } 6006 6007 pub fn toLlvm(a: Alignment) std.zig.llvm.Builder.Alignment { 6008 return @fromBackingInt(@intCast(@backingInt(a))); 6009 } 6010 }; 6011 6012 /// Used for non-sentineled arrays that have length fitting in u32, as well as 6013 /// vectors. 6014 pub const Vector = struct { 6015 len: u32, 6016 child: Index, 6017 }; 6018 6019 pub const Array = struct { 6020 len0: u32, 6021 len1: u32, 6022 child: Index, 6023 sentinel: Index, 6024 6025 pub const Length = PackedU64; 6026 6027 pub fn getLength(a: Array) u64 { 6028 return (PackedU64{ 6029 .a = a.len0, 6030 .b = a.len1, 6031 }).get(); 6032 } 6033 }; 6034 6035 pub const PackedU64 = packed struct(u64) { 6036 a: u32, 6037 b: u32, 6038 6039 pub fn get(x: PackedU64) u64 { 6040 return @bitCast(x); 6041 } 6042 6043 pub fn init(x: u64) PackedU64 { 6044 return @bitCast(x); 6045 } 6046 }; 6047 6048 pub const PtrNav = struct { 6049 ty: Index, 6050 nav: Nav.Index, 6051 byte_offset_a: u32, 6052 byte_offset_b: u32, 6053 fn init(ty: Index, nav: Nav.Index, byte_offset: u64) @This() { 6054 return .{ 6055 .ty = ty, 6056 .nav = nav, 6057 .byte_offset_a = @intCast(byte_offset >> 32), 6058 .byte_offset_b = @truncate(byte_offset), 6059 }; 6060 } 6061 fn byteOffset(data: @This()) u64 { 6062 return @as(u64, data.byte_offset_a) << 32 | data.byte_offset_b; 6063 } 6064 }; 6065 6066 pub const PtrUav = struct { 6067 ty: Index, 6068 val: Index, 6069 byte_offset_a: u32, 6070 byte_offset_b: u32, 6071 fn init(ty: Index, val: Index, byte_offset: u64) @This() { 6072 return .{ 6073 .ty = ty, 6074 .val = val, 6075 .byte_offset_a = @intCast(byte_offset >> 32), 6076 .byte_offset_b = @truncate(byte_offset), 6077 }; 6078 } 6079 fn byteOffset(data: @This()) u64 { 6080 return @as(u64, data.byte_offset_a) << 32 | data.byte_offset_b; 6081 } 6082 }; 6083 6084 pub const PtrUavAligned = struct { 6085 ty: Index, 6086 val: Index, 6087 /// Must be nonequal to `ty`. Only the alignment from this value is important. 6088 orig_ty: Index, 6089 byte_offset_a: u32, 6090 byte_offset_b: u32, 6091 fn init(ty: Index, val: Index, orig_ty: Index, byte_offset: u64) @This() { 6092 return .{ 6093 .ty = ty, 6094 .val = val, 6095 .orig_ty = orig_ty, 6096 .byte_offset_a = @intCast(byte_offset >> 32), 6097 .byte_offset_b = @truncate(byte_offset), 6098 }; 6099 } 6100 fn byteOffset(data: @This()) u64 { 6101 return @as(u64, data.byte_offset_a) << 32 | data.byte_offset_b; 6102 } 6103 }; 6104 6105 pub const PtrComptimeAlloc = struct { 6106 ty: Index, 6107 index: ComptimeAllocIndex, 6108 byte_offset_a: u32, 6109 byte_offset_b: u32, 6110 fn init(ty: Index, index: ComptimeAllocIndex, byte_offset: u64) @This() { 6111 return .{ 6112 .ty = ty, 6113 .index = index, 6114 .byte_offset_a = @intCast(byte_offset >> 32), 6115 .byte_offset_b = @truncate(byte_offset), 6116 }; 6117 } 6118 fn byteOffset(data: @This()) u64 { 6119 return @as(u64, data.byte_offset_a) << 32 | data.byte_offset_b; 6120 } 6121 }; 6122 6123 pub const PtrComptimeField = struct { 6124 ty: Index, 6125 field_val: Index, 6126 byte_offset_a: u32, 6127 byte_offset_b: u32, 6128 fn init(ty: Index, field_val: Index, byte_offset: u64) @This() { 6129 return .{ 6130 .ty = ty, 6131 .field_val = field_val, 6132 .byte_offset_a = @intCast(byte_offset >> 32), 6133 .byte_offset_b = @truncate(byte_offset), 6134 }; 6135 } 6136 fn byteOffset(data: @This()) u64 { 6137 return @as(u64, data.byte_offset_a) << 32 | data.byte_offset_b; 6138 } 6139 }; 6140 6141 pub const PtrBase = struct { 6142 ty: Index, 6143 base: Index, 6144 byte_offset_a: u32, 6145 byte_offset_b: u32, 6146 fn init(ty: Index, base: Index, byte_offset: u64) @This() { 6147 return .{ 6148 .ty = ty, 6149 .base = base, 6150 .byte_offset_a = @intCast(byte_offset >> 32), 6151 .byte_offset_b = @truncate(byte_offset), 6152 }; 6153 } 6154 fn byteOffset(data: @This()) u64 { 6155 return @as(u64, data.byte_offset_a) << 32 | data.byte_offset_b; 6156 } 6157 }; 6158 6159 pub const PtrBaseIndex = struct { 6160 ty: Index, 6161 base: Index, 6162 index: Index, 6163 byte_offset_a: u32, 6164 byte_offset_b: u32, 6165 fn init(ty: Index, base: Index, index: Index, byte_offset: u64) @This() { 6166 return .{ 6167 .ty = ty, 6168 .base = base, 6169 .index = index, 6170 .byte_offset_a = @intCast(byte_offset >> 32), 6171 .byte_offset_b = @truncate(byte_offset), 6172 }; 6173 } 6174 fn byteOffset(data: @This()) u64 { 6175 return @as(u64, data.byte_offset_a) << 32 | data.byte_offset_b; 6176 } 6177 }; 6178 6179 pub const PtrInt = struct { 6180 ty: Index, 6181 byte_offset_a: u32, 6182 byte_offset_b: u32, 6183 fn init(ty: Index, byte_offset: u64) @This() { 6184 return .{ 6185 .ty = ty, 6186 .byte_offset_a = @intCast(byte_offset >> 32), 6187 .byte_offset_b = @truncate(byte_offset), 6188 }; 6189 } 6190 fn byteOffset(data: @This()) u64 { 6191 return @as(u64, data.byte_offset_a) << 32 | data.byte_offset_b; 6192 } 6193 }; 6194 6195 pub const PtrSlice = struct { 6196 /// The slice type. 6197 ty: Index, 6198 /// A many pointer value. 6199 ptr: Index, 6200 /// A usize value. 6201 len: Index, 6202 }; 6203 6204 /// Trailing: Limb for every limbs_len 6205 pub const Int = packed struct { 6206 ty: Index, 6207 limbs_len: u32, 6208 6209 const limbs_items_len = @divExact(@sizeOf(Int), @sizeOf(Limb)); 6210 }; 6211 6212 pub const IntSmall = struct { 6213 ty: Index, 6214 value: u32, 6215 }; 6216 6217 /// A f64 value, broken up into 2 u32 parts. 6218 pub const Float64 = struct { 6219 piece0: u32, 6220 piece1: u32, 6221 6222 pub fn get(self: Float64) f64 { 6223 const int_bits = @as(u64, self.piece0) | (@as(u64, self.piece1) << 32); 6224 return @bitCast(int_bits); 6225 } 6226 6227 fn pack(val: f64) Float64 { 6228 const bits: u64 = @bitCast(val); 6229 return .{ 6230 .piece0 = @truncate(bits), 6231 .piece1 = @truncate(bits >> 32), 6232 }; 6233 } 6234 }; 6235 6236 /// A f80 value, broken up into 2 u32 parts and a u16 part zero-padded to a u32. 6237 pub const Float80 = struct { 6238 piece0: u32, 6239 piece1: u32, 6240 piece2: u32, // u16 part, top bits 6241 6242 pub fn get(self: Float80) f80 { 6243 const int_bits = @as(u80, self.piece0) | 6244 (@as(u80, self.piece1) << 32) | 6245 (@as(u80, self.piece2) << 64); 6246 return @bitCast(int_bits); 6247 } 6248 6249 fn pack(val: f80) Float80 { 6250 const bits: u80 = @bitCast(val); 6251 return .{ 6252 .piece0 = @truncate(bits), 6253 .piece1 = @truncate(bits >> 32), 6254 .piece2 = @truncate(bits >> 64), 6255 }; 6256 } 6257 }; 6258 6259 /// A f128 value, broken up into 4 u32 parts. 6260 pub const Float128 = struct { 6261 piece0: u32, 6262 piece1: u32, 6263 piece2: u32, 6264 piece3: u32, 6265 6266 pub fn get(self: Float128) f128 { 6267 const int_bits = @as(u128, self.piece0) | 6268 (@as(u128, self.piece1) << 32) | 6269 (@as(u128, self.piece2) << 64) | 6270 (@as(u128, self.piece3) << 96); 6271 return @bitCast(int_bits); 6272 } 6273 6274 fn pack(val: f128) Float128 { 6275 const bits: u128 = @bitCast(val); 6276 return .{ 6277 .piece0 = @truncate(bits), 6278 .piece1 = @truncate(bits >> 32), 6279 .piece2 = @truncate(bits >> 64), 6280 .piece3 = @truncate(bits >> 96), 6281 }; 6282 } 6283 }; 6284 6285 /// Trailing: 6286 /// 0. arg value: Index for each args_len 6287 pub const MemoizedCall = struct { 6288 func: Index, 6289 args_len: u32, 6290 result: Index, 6291 branch_count: u32, 6292 branch_quota: u32, 6293 }; 6294 6295 pub fn init(ip: *InternPool, gpa: Allocator, io: Io, available_threads: usize) !void { 6296 errdefer ip.deinit(gpa, io); 6297 assert(ip.locals.len == 0 and ip.shards.len == 0); 6298 assert(available_threads > 0 and available_threads <= std.math.maxInt(u8)); 6299 6300 const used_threads = if (single_threaded) 1 else @max(available_threads, 2); 6301 ip.locals = try gpa.alloc(Local, used_threads); 6302 @memset(ip.locals, .{ 6303 .shared = .{ 6304 .items = .empty, 6305 .extra = .empty, 6306 .limbs = .empty, 6307 .strings = .empty, 6308 .string_bytes = .empty, 6309 .tracked_insts = .empty, 6310 .files = .empty, 6311 .maps = .empty, 6312 .navs = .empty, 6313 .comptime_units = .empty, 6314 6315 .namespaces = .empty, 6316 }, 6317 .mutate = .{ 6318 .arena = .{}, 6319 6320 .items = .empty, 6321 .extra = .empty, 6322 .limbs = .empty, 6323 .strings = .empty, 6324 .string_bytes = .empty, 6325 .tracked_insts = .empty, 6326 .files = .empty, 6327 .maps = .empty, 6328 .navs = .empty, 6329 .comptime_units = .empty, 6330 6331 .namespaces = .empty, 6332 }, 6333 }); 6334 for (ip.locals) |*local| try local.getMutableStrings(gpa, io).append(.{0}); 6335 6336 ip.tid_width = @intCast(std.math.log2_int_ceil(usize, used_threads)); 6337 ip.tid_shift_30 = if (single_threaded) 0 else 30 - ip.tid_width; 6338 ip.tid_shift_31 = if (single_threaded) 0 else 31 - ip.tid_width; 6339 ip.tid_shift_32 = if (single_threaded) 0 else ip.tid_shift_31 +| 1; 6340 ip.shards = try gpa.alloc(Shard, @as(usize, 1) << ip.tid_width); 6341 @memset(ip.shards, .{ 6342 .shared = .{ 6343 .map = .empty, 6344 .string_map = .empty, 6345 .tracked_inst_map = .empty, 6346 }, 6347 .mutate = .{ 6348 .map = .empty, 6349 .string_map = .empty, 6350 .tracked_inst_map = .empty, 6351 }, 6352 }); 6353 6354 // Reserve string index 0 for an empty string. 6355 assert((try ip.getOrPutString(gpa, io, .main, "", .no_embedded_nulls)) == .empty); 6356 6357 // This inserts all the statically-known values into the intern pool in the 6358 // order expected. 6359 for (&static_keys, 0..) |key, key_index| switch (@as(Index, @fromBackingInt(@intCast(key_index)))) { 6360 .empty_tuple_type => assert(try ip.getTupleType(gpa, io, .main, .{ 6361 .types = &.{}, 6362 .values = &.{}, 6363 }) == .empty_tuple_type), 6364 else => |expected_index| assert(try ip.get(gpa, io, .main, key) == expected_index), 6365 }; 6366 6367 if (std.debug.runtime_safety) { 6368 // Sanity check. 6369 assert(ip.indexToKey(.bool_true).simple_value == .true); 6370 assert(ip.indexToKey(.bool_false).simple_value == .false); 6371 } 6372 } 6373 6374 pub fn deinit(ip: *InternPool, gpa: Allocator, io: Io) void { 6375 std.debug.assert(debug_state.intern_pool == null); 6376 6377 ip.src_hash_deps.deinit(gpa); 6378 ip.nav_val_deps.deinit(gpa); 6379 ip.nav_ty_deps.deinit(gpa); 6380 ip.func_ies_deps.deinit(gpa); 6381 ip.type_layout_deps.deinit(gpa); 6382 ip.struct_defaults_deps.deinit(gpa); 6383 ip.source_file_deps.deinit(gpa); 6384 ip.embed_file_deps.deinit(gpa); 6385 ip.namespace_deps.deinit(gpa); 6386 ip.namespace_name_deps.deinit(gpa); 6387 6388 ip.first_dependency.deinit(gpa); 6389 6390 ip.dep_entries.deinit(gpa); 6391 ip.free_dep_entries.deinit(gpa); 6392 6393 gpa.free(ip.shards); 6394 for (ip.locals) |*local| { 6395 const buckets_len = local.mutate.namespaces.buckets_list.len; 6396 if (buckets_len > 0) for ( 6397 local.shared.namespaces.view().items(.@"0")[0..buckets_len], 6398 0.., 6399 ) |namespace_bucket, buckets_index| { 6400 for (namespace_bucket[0..if (buckets_index < buckets_len - 1) 6401 namespace_bucket.len 6402 else 6403 local.mutate.namespaces.last_bucket_len]) |*namespace| 6404 { 6405 namespace.pub_decls.deinit(gpa); 6406 namespace.priv_decls.deinit(gpa); 6407 namespace.comptime_decls.deinit(gpa); 6408 namespace.test_decls.deinit(gpa); 6409 } 6410 }; 6411 const maps = local.getMutableMaps(gpa, io); 6412 if (maps.mutate.len > 0) for (maps.view().items(.@"0")) |*map| map.deinit(gpa); 6413 local.mutate.arena.promote(gpa).deinit(); 6414 } 6415 gpa.free(ip.locals); 6416 6417 ip.* = undefined; 6418 } 6419 6420 pub const Active = struct { 6421 prev_ip: if (debug_state.enable) ?*const InternPool else void, 6422 pub fn deactivate(active: Active) void { 6423 if (!debug_state.enable) return; 6424 debug_state.intern_pool = active.prev_ip; 6425 } 6426 }; 6427 pub fn activate(ip: *const InternPool) Active { 6428 if (!debug_state.enable) return .{ .prev_ip = {} }; 6429 _ = Index.Unwrapped.debug_state; 6430 _ = String.debug_state; 6431 _ = OptionalString.debug_state; 6432 _ = NullTerminatedString.debug_state; 6433 _ = OptionalNullTerminatedString.debug_state; 6434 _ = TrackedInst.Index.debug_state; 6435 _ = TrackedInst.Index.Optional.debug_state; 6436 _ = Nav.Index.debug_state; 6437 _ = Nav.Index.Optional.debug_state; 6438 defer debug_state.intern_pool = ip; 6439 return .{ .prev_ip = debug_state.intern_pool }; 6440 } 6441 6442 /// For debugger access only. 6443 const debug_state = struct { 6444 const enable = switch (builtin.zig_backend) { 6445 else => false, 6446 .stage2_x86_64 => !builtin.strip_debug_info and build_options.io_mode == .threaded, 6447 }; 6448 threadlocal var intern_pool: ?*const InternPool = null; 6449 }; 6450 6451 pub fn indexToKey(ip: *const InternPool, index: Index) Key { 6452 assert(index != .none); 6453 const unwrapped_index = index.unwrap(ip); 6454 const item = unwrapped_index.getItem(ip); 6455 const data = item.data; 6456 return switch (item.tag) { 6457 .removed => unreachable, 6458 .type_int_signed => .{ 6459 .int_type = .{ 6460 .signedness = .signed, 6461 .bits = @intCast(data), 6462 }, 6463 }, 6464 .type_int_unsigned => .{ 6465 .int_type = .{ 6466 .signedness = .unsigned, 6467 .bits = @intCast(data), 6468 }, 6469 }, 6470 .type_array_big => { 6471 const array_info = extraData(unwrapped_index.getExtra(ip), Array, data); 6472 return .{ .array_type = .{ 6473 .len = array_info.getLength(), 6474 .child = array_info.child, 6475 .sentinel = array_info.sentinel, 6476 } }; 6477 }, 6478 .type_array_small => { 6479 const array_info = extraData(unwrapped_index.getExtra(ip), Vector, data); 6480 return .{ .array_type = .{ 6481 .len = array_info.len, 6482 .child = array_info.child, 6483 .sentinel = .none, 6484 } }; 6485 }, 6486 .simple_type => .{ .simple_type = @fromBackingInt(@intCast(@backingInt(index))) }, 6487 .simple_value => .{ .simple_value = @fromBackingInt(@intCast(@backingInt(index))) }, 6488 6489 .type_vector => { 6490 const vector_info = extraData(unwrapped_index.getExtra(ip), Vector, data); 6491 return .{ .vector_type = .{ 6492 .len = vector_info.len, 6493 .child = vector_info.child, 6494 } }; 6495 }, 6496 6497 .type_pointer => .{ .ptr_type = extraData(unwrapped_index.getExtra(ip), Tag.TypePointer, data) }, 6498 6499 .type_slice => { 6500 const many_ptr_index: Index = @fromBackingInt(@intCast(data)); 6501 const many_ptr_unwrapped = many_ptr_index.unwrap(ip); 6502 const many_ptr_item = many_ptr_unwrapped.getItem(ip); 6503 assert(many_ptr_item.tag == .type_pointer); 6504 var ptr_info = extraData(many_ptr_unwrapped.getExtra(ip), Tag.TypePointer, many_ptr_item.data); 6505 ptr_info.flags.size = .slice; 6506 return .{ .ptr_type = ptr_info }; 6507 }, 6508 6509 .type_optional => .{ .opt_type = @fromBackingInt(@intCast(data)) }, 6510 .type_anyframe => .{ .anyframe_type = @fromBackingInt(@intCast(data)) }, 6511 6512 .type_error_union => .{ .error_union_type = extraData(unwrapped_index.getExtra(ip), Key.ErrorUnionType, data) }, 6513 .type_anyerror_union => .{ .error_union_type = .{ 6514 .error_set_type = .anyerror_type, 6515 .payload_type = @fromBackingInt(@intCast(data)), 6516 } }, 6517 .type_error_set => .{ .error_set_type = extraErrorSet(unwrapped_index.tid, unwrapped_index.getExtra(ip), data) }, 6518 .type_inferred_error_set => .{ 6519 .inferred_error_set_type = @fromBackingInt(@intCast(data)), 6520 }, 6521 .type_function => .{ .func_type = extraFuncType(unwrapped_index.tid, unwrapped_index.getExtra(ip), data) }, 6522 .type_tuple => .{ .tuple_type = extraTypeTuple(unwrapped_index.tid, unwrapped_index.getExtra(ip), data) }, 6523 6524 .type_struct => .{ .struct_type = ns: { 6525 const extra_list = unwrapped_index.getExtra(ip); 6526 const extra = extraDataTrail(extra_list, Tag.TypeStruct, data); 6527 break :ns switch (extra.data.flags.any_captures) { 6528 .reified => .{ .reified = .{ 6529 .zir_index = extra.data.zir_index, 6530 .type_hash = extraData(extra_list, PackedU64, extra.end).get(), 6531 } }, 6532 .false => .{ .declared = .{ 6533 .zir_index = extra.data.zir_index, 6534 .captures = .{ .owned = .empty }, 6535 } }, 6536 .true => .{ .declared = .{ 6537 .zir_index = extra.data.zir_index, 6538 .captures = .{ .owned = .{ 6539 .tid = unwrapped_index.tid, 6540 .start = extra.end + 1, 6541 .len = extra_list.view().items(.@"0")[extra.end], 6542 } }, 6543 } }, 6544 }; 6545 } }, 6546 .type_struct_packed_auto, 6547 .type_struct_packed_explicit, 6548 .type_struct_packed_auto_defaults, 6549 .type_struct_packed_explicit_defaults, 6550 => .{ .struct_type = ns: { 6551 const extra_list = unwrapped_index.getExtra(ip); 6552 const extra = extraDataTrail(extra_list, Tag.TypeStructPacked, data); 6553 break :ns switch (extra.data.bits.captures_len) { 6554 .reified => .{ .reified = .{ 6555 .zir_index = extra.data.zir_index, 6556 .type_hash = extraData(extra_list, PackedU64, extra.end).get(), 6557 } }, 6558 _ => |len| .{ .declared = .{ 6559 .zir_index = extra.data.zir_index, 6560 .captures = .{ .owned = .{ 6561 .tid = unwrapped_index.tid, 6562 .start = extra.end, 6563 .len = @backingInt(len), 6564 } }, 6565 } }, 6566 }; 6567 } }, 6568 .type_union => .{ .union_type = ns: { 6569 const extra_list = unwrapped_index.getExtra(ip); 6570 const extra = extraDataTrail(extra_list, Tag.TypeUnion, data); 6571 break :ns switch (extra.data.flags.any_captures) { 6572 .reified => .{ .reified = .{ 6573 .zir_index = extra.data.zir_index, 6574 .type_hash = extraData(extra_list, PackedU64, extra.end).get(), 6575 } }, 6576 .false => .{ .declared = .{ 6577 .zir_index = extra.data.zir_index, 6578 .captures = .{ .owned = .empty }, 6579 } }, 6580 .true => .{ .declared = .{ 6581 .zir_index = extra.data.zir_index, 6582 .captures = .{ .owned = .{ 6583 .tid = unwrapped_index.tid, 6584 .start = extra.end + 1, 6585 .len = extra_list.view().items(.@"0")[extra.end], 6586 } }, 6587 } }, 6588 }; 6589 } }, 6590 .type_union_packed_auto, .type_union_packed_explicit => .{ .union_type = ns: { 6591 const extra_list = unwrapped_index.getExtra(ip); 6592 const extra = extraDataTrail(extra_list, Tag.TypeUnionPacked, data); 6593 break :ns switch (extra.data.bits.captures_len) { 6594 .reified => .{ .reified = .{ 6595 .zir_index = extra.data.zir_index, 6596 .type_hash = extraData(extra_list, PackedU64, extra.end).get(), 6597 } }, 6598 _ => |len| .{ .declared = .{ 6599 .zir_index = extra.data.zir_index, 6600 .captures = .{ .owned = .{ 6601 .tid = unwrapped_index.tid, 6602 .start = extra.end, 6603 .len = @backingInt(len), 6604 } }, 6605 } }, 6606 }; 6607 } }, 6608 .type_enum_auto, .type_enum_explicit, .type_enum_nonexhaustive => .{ .enum_type = ns: { 6609 const extra_list = unwrapped_index.getExtra(ip); 6610 const extra = extraDataTrail(extra_list, Tag.TypeEnum, data); 6611 break :ns switch (extra.data.bits.captures_len) { 6612 .reified => .{ .reified = .{ 6613 .zir_index = @fromBackingInt(@intCast(extra_list.view().items(.@"0")[extra.end])), 6614 .type_hash = extraData(extra_list, PackedU64, extra.end + 1).get(), 6615 } }, 6616 .generated_union_tag => .{ .generated_union_tag = owner_union: { 6617 break :owner_union @fromBackingInt(@intCast(extra_list.view().items(.@"0")[extra.end])); 6618 } }, 6619 _ => |len| .{ .declared = .{ 6620 .zir_index = @fromBackingInt(@intCast(extra_list.view().items(.@"0")[extra.end])), 6621 .captures = .{ .owned = .{ 6622 .tid = unwrapped_index.tid, 6623 .start = extra.end + 1, 6624 .len = @backingInt(len), 6625 } }, 6626 } }, 6627 }; 6628 } }, 6629 .type_spirv => .{ .spirv_type = ns: { 6630 const extra = extraData(unwrapped_index.getExtra(ip), Tag.TypeSpirv, data); 6631 break :ns .{ 6632 .ty = extra.ty, 6633 .flags = extra.flags, 6634 }; 6635 } }, 6636 .type_opaque => .{ .opaque_type = ns: { 6637 const extra = extraDataTrail(unwrapped_index.getExtra(ip), Tag.TypeOpaque, data); 6638 break :ns .{ .declared = .{ 6639 .zir_index = extra.data.zir_index, 6640 .captures = .{ .owned = .{ 6641 .tid = unwrapped_index.tid, 6642 .start = extra.end, 6643 .len = extra.data.captures_len, 6644 } }, 6645 } }; 6646 } }, 6647 6648 .undef => .{ .undef = @fromBackingInt(@intCast(data)) }, 6649 .opt_null => .{ .opt = .{ 6650 .ty = @fromBackingInt(@intCast(data)), 6651 .val = .none, 6652 } }, 6653 .opt_payload => { 6654 const extra = extraData(unwrapped_index.getExtra(ip), Tag.TypeValue, data); 6655 return .{ .opt = .{ 6656 .ty = extra.ty, 6657 .val = extra.val, 6658 } }; 6659 }, 6660 .ptr_nav => { 6661 const info = extraData(unwrapped_index.getExtra(ip), PtrNav, data); 6662 return .{ .ptr = .{ .ty = info.ty, .base_addr = .{ .nav = info.nav }, .byte_offset = info.byteOffset() } }; 6663 }, 6664 .ptr_comptime_alloc => { 6665 const info = extraData(unwrapped_index.getExtra(ip), PtrComptimeAlloc, data); 6666 return .{ .ptr = .{ .ty = info.ty, .base_addr = .{ .comptime_alloc = info.index }, .byte_offset = info.byteOffset() } }; 6667 }, 6668 .ptr_uav => { 6669 const info = extraData(unwrapped_index.getExtra(ip), PtrUav, data); 6670 return .{ .ptr = .{ .ty = info.ty, .base_addr = .{ .uav = .{ 6671 .val = info.val, 6672 .orig_ty = info.ty, 6673 } }, .byte_offset = info.byteOffset() } }; 6674 }, 6675 .ptr_uav_aligned => { 6676 const info = extraData(unwrapped_index.getExtra(ip), PtrUavAligned, data); 6677 return .{ .ptr = .{ .ty = info.ty, .base_addr = .{ .uav = .{ 6678 .val = info.val, 6679 .orig_ty = info.orig_ty, 6680 } }, .byte_offset = info.byteOffset() } }; 6681 }, 6682 .ptr_comptime_field => { 6683 const info = extraData(unwrapped_index.getExtra(ip), PtrComptimeField, data); 6684 return .{ .ptr = .{ .ty = info.ty, .base_addr = .{ .comptime_field = info.field_val }, .byte_offset = info.byteOffset() } }; 6685 }, 6686 .ptr_int => { 6687 const info = extraData(unwrapped_index.getExtra(ip), PtrInt, data); 6688 return .{ .ptr = .{ 6689 .ty = info.ty, 6690 .base_addr = .int, 6691 .byte_offset = info.byteOffset(), 6692 } }; 6693 }, 6694 .ptr_eu_payload => { 6695 const info = extraData(unwrapped_index.getExtra(ip), PtrBase, data); 6696 return .{ .ptr = .{ .ty = info.ty, .base_addr = .{ .eu_payload = info.base }, .byte_offset = info.byteOffset() } }; 6697 }, 6698 .ptr_opt_payload => { 6699 const info = extraData(unwrapped_index.getExtra(ip), PtrBase, data); 6700 return .{ .ptr = .{ .ty = info.ty, .base_addr = .{ .opt_payload = info.base }, .byte_offset = info.byteOffset() } }; 6701 }, 6702 .ptr_elem => { 6703 // Avoid `indexToKey` recursion by asserting the tag encoding. 6704 const info = extraData(unwrapped_index.getExtra(ip), PtrBaseIndex, data); 6705 const index_item = info.index.unwrap(ip).getItem(ip); 6706 return switch (index_item.tag) { 6707 .int_usize => .{ .ptr = .{ .ty = info.ty, .base_addr = .{ .arr_elem = .{ 6708 .base = info.base, 6709 .index = index_item.data, 6710 } }, .byte_offset = info.byteOffset() } }, 6711 .int_positive => @panic("TODO"), // implement along with behavior test coverage 6712 else => unreachable, 6713 }; 6714 }, 6715 .ptr_field => { 6716 // Avoid `indexToKey` recursion by asserting the tag encoding. 6717 const info = extraData(unwrapped_index.getExtra(ip), PtrBaseIndex, data); 6718 const index_item = info.index.unwrap(ip).getItem(ip); 6719 return switch (index_item.tag) { 6720 .int_usize => .{ .ptr = .{ .ty = info.ty, .base_addr = .{ .field = .{ 6721 .base = info.base, 6722 .index = index_item.data, 6723 } }, .byte_offset = info.byteOffset() } }, 6724 .int_positive => @panic("TODO"), // implement along with behavior test coverage 6725 else => unreachable, 6726 }; 6727 }, 6728 .ptr_slice => { 6729 const info = extraData(unwrapped_index.getExtra(ip), PtrSlice, data); 6730 return .{ .slice = .{ 6731 .ty = info.ty, 6732 .ptr = info.ptr, 6733 .len = info.len, 6734 } }; 6735 }, 6736 .int_u8 => .{ .int = .{ 6737 .ty = .u8_type, 6738 .storage = .{ .u64 = data }, 6739 } }, 6740 .int_u16 => .{ .int = .{ 6741 .ty = .u16_type, 6742 .storage = .{ .u64 = data }, 6743 } }, 6744 .int_u32 => .{ .int = .{ 6745 .ty = .u32_type, 6746 .storage = .{ .u64 = data }, 6747 } }, 6748 .int_i32 => .{ .int = .{ 6749 .ty = .i32_type, 6750 .storage = .{ .i64 = @as(i32, @bitCast(data)) }, 6751 } }, 6752 .int_usize => .{ .int = .{ 6753 .ty = .usize_type, 6754 .storage = .{ .u64 = data }, 6755 } }, 6756 .int_comptime_int_u32 => .{ .int = .{ 6757 .ty = .comptime_int_type, 6758 .storage = .{ .u64 = data }, 6759 } }, 6760 .int_comptime_int_i32 => .{ .int = .{ 6761 .ty = .comptime_int_type, 6762 .storage = .{ .i64 = @as(i32, @bitCast(data)) }, 6763 } }, 6764 .int_positive => ip.indexToKeyBigInt(unwrapped_index.tid, data, true), 6765 .int_negative => ip.indexToKeyBigInt(unwrapped_index.tid, data, false), 6766 .int_small => { 6767 const info = extraData(unwrapped_index.getExtra(ip), IntSmall, data); 6768 return .{ .int = .{ 6769 .ty = info.ty, 6770 .storage = .{ .u64 = info.value }, 6771 } }; 6772 }, 6773 .float_f16 => .{ .float = .{ 6774 .ty = .f16_type, 6775 .storage = .{ .f16 = @bitCast(@as(u16, @intCast(data))) }, 6776 } }, 6777 .float_f32 => .{ .float = .{ 6778 .ty = .f32_type, 6779 .storage = .{ .f32 = @bitCast(data) }, 6780 } }, 6781 .float_f64 => .{ .float = .{ 6782 .ty = .f64_type, 6783 .storage = .{ .f64 = extraData(unwrapped_index.getExtra(ip), Float64, data).get() }, 6784 } }, 6785 .float_f80 => .{ .float = .{ 6786 .ty = .f80_type, 6787 .storage = .{ .f80 = extraData(unwrapped_index.getExtra(ip), Float80, data).get() }, 6788 } }, 6789 .float_f128 => .{ .float = .{ 6790 .ty = .f128_type, 6791 .storage = .{ .f128 = extraData(unwrapped_index.getExtra(ip), Float128, data).get() }, 6792 } }, 6793 .float_c_longdouble_f80 => .{ .float = .{ 6794 .ty = .c_longdouble_type, 6795 .storage = .{ .f80 = extraData(unwrapped_index.getExtra(ip), Float80, data).get() }, 6796 } }, 6797 .float_c_longdouble_f128 => .{ .float = .{ 6798 .ty = .c_longdouble_type, 6799 .storage = .{ .f128 = extraData(unwrapped_index.getExtra(ip), Float128, data).get() }, 6800 } }, 6801 .float_comptime_float => .{ .float = .{ 6802 .ty = .comptime_float_type, 6803 .storage = .{ .f128 = extraData(unwrapped_index.getExtra(ip), Float128, data).get() }, 6804 } }, 6805 .@"extern" => { 6806 const extra = extraData(unwrapped_index.getExtra(ip), Tag.Extern, data); 6807 const nav = ip.getNav(extra.owner_nav); 6808 return .{ .@"extern" = .{ 6809 .name = nav.name, 6810 .ty = extra.ty, 6811 .lib_name = extra.lib_name, 6812 .linkage = extra.flags.linkage, 6813 .visibility = extra.flags.visibility, 6814 .is_threadlocal = nav.resolved.?.@"threadlocal", 6815 .is_dll_import = extra.flags.is_dll_import, 6816 .relocation = extra.flags.relocation, 6817 .decoration = extra.decoration(), 6818 .is_const = nav.resolved.?.@"const", 6819 .alignment = nav.resolved.?.@"align", 6820 .@"addrspace" = nav.resolved.?.@"addrspace", 6821 .zir_index = extra.zir_index, 6822 .owner_nav = extra.owner_nav, 6823 .source = extra.flags.source, 6824 } }; 6825 }, 6826 .func_instance => .{ .func = ip.extraFuncInstance(unwrapped_index.tid, unwrapped_index.getExtra(ip), data) }, 6827 .func_decl => .{ .func = extraFuncDecl(unwrapped_index.tid, unwrapped_index.getExtra(ip), data) }, 6828 .func_coerced => .{ .func = ip.extraFuncCoerced(unwrapped_index.getExtra(ip), data) }, 6829 .only_possible_value => { 6830 const ty: Index = @fromBackingInt(@intCast(data)); 6831 const ty_unwrapped = ty.unwrap(ip); 6832 const ty_extra = ty_unwrapped.getExtra(ip); 6833 const ty_item = ty_unwrapped.getItem(ip); 6834 return switch (ty_item.tag) { 6835 .type_array_big => { 6836 const sentinel = @as( 6837 *const [1]Index, 6838 @ptrCast(&ty_extra.view().items(.@"0")[ty_item.data + std.meta.fieldIndex(Array, "sentinel").?]), 6839 ); 6840 return .{ .aggregate = .{ 6841 .ty = ty, 6842 .storage = .{ .elems = sentinel[0..@intFromBool(sentinel[0] != .none)] }, 6843 } }; 6844 }, 6845 .type_array_small, 6846 .type_vector, 6847 .type_struct_packed_auto, 6848 .type_struct_packed_explicit, 6849 => .{ .aggregate = .{ 6850 .ty = ty, 6851 .storage = .{ .elems = &.{} }, 6852 } }, 6853 6854 // There is only one possible value precisely due to the 6855 // fact that this values slice is fully populated! 6856 .type_struct, 6857 .type_struct_packed_auto_defaults, 6858 .type_struct_packed_explicit_defaults, 6859 => { 6860 const info = loadStructType(ip, ty); 6861 return .{ .aggregate = .{ 6862 .ty = ty, 6863 .storage = .{ .elems = @ptrCast(info.field_defaults.get(ip)) }, 6864 } }; 6865 }, 6866 6867 // There is only one possible value precisely due to the 6868 // fact that this values slice is fully populated! 6869 .type_tuple => { 6870 const type_tuple = extraDataTrail(ty_extra, TypeTuple, ty_item.data); 6871 const fields_len = type_tuple.data.fields_len; 6872 const values = ty_extra.view().items(.@"0")[type_tuple.end + fields_len ..][0..fields_len]; 6873 return .{ .aggregate = .{ 6874 .ty = ty, 6875 .storage = .{ .elems = @ptrCast(values) }, 6876 } }; 6877 }, 6878 6879 else => unreachable, 6880 }; 6881 }, 6882 .bytes => { 6883 const extra = extraData(unwrapped_index.getExtra(ip), Bytes, data); 6884 return .{ .aggregate = .{ 6885 .ty = extra.ty, 6886 .storage = .{ .bytes = extra.bytes }, 6887 } }; 6888 }, 6889 .aggregate => { 6890 const extra_list = unwrapped_index.getExtra(ip); 6891 const extra = extraDataTrail(extra_list, Tag.Aggregate, data); 6892 const len: u32 = @intCast(ip.aggregateTypeLenIncludingSentinel(extra.data.ty)); 6893 const fields: []const Index = @ptrCast(extra_list.view().items(.@"0")[extra.end..][0..len]); 6894 return .{ .aggregate = .{ 6895 .ty = extra.data.ty, 6896 .storage = .{ .elems = fields }, 6897 } }; 6898 }, 6899 .repeated => { 6900 const extra = extraData(unwrapped_index.getExtra(ip), Repeated, data); 6901 return .{ .aggregate = .{ 6902 .ty = extra.ty, 6903 .storage = .{ .repeated_elem = extra.elem_val }, 6904 } }; 6905 }, 6906 .union_value => .{ .un = extraData(unwrapped_index.getExtra(ip), Key.Union, data) }, 6907 .error_set_error => .{ .err = extraData(unwrapped_index.getExtra(ip), Key.Error, data) }, 6908 .error_union_error => { 6909 const extra = extraData(unwrapped_index.getExtra(ip), Key.Error, data); 6910 return .{ .error_union = .{ 6911 .ty = extra.ty, 6912 .val = .{ .err_name = extra.name }, 6913 } }; 6914 }, 6915 .error_union_payload => { 6916 const extra = extraData(unwrapped_index.getExtra(ip), Tag.TypeValue, data); 6917 return .{ .error_union = .{ 6918 .ty = extra.ty, 6919 .val = .{ .payload = extra.val }, 6920 } }; 6921 }, 6922 .enum_literal => .{ .enum_literal = @fromBackingInt(@intCast(data)) }, 6923 .enum_tag => .{ .enum_tag = extraData(unwrapped_index.getExtra(ip), Tag.EnumTag, data) }, 6924 .bitpack => .{ .bitpack = extraData(unwrapped_index.getExtra(ip), Key.Bitpack, data) }, 6925 6926 .memoized_call => { 6927 const extra_list = unwrapped_index.getExtra(ip); 6928 const extra = extraDataTrail(extra_list, MemoizedCall, data); 6929 return .{ .memoized_call = .{ 6930 .func = extra.data.func, 6931 .arg_values = @ptrCast(extra_list.view().items(.@"0")[extra.end..][0..extra.data.args_len]), 6932 .result = extra.data.result, 6933 .branch_count = extra.data.branch_count, 6934 .branch_quota = extra.data.branch_quota, 6935 } }; 6936 }, 6937 }; 6938 } 6939 6940 fn extraErrorSet(tid: Zcu.PerThread.Id, extra: Local.Extra, extra_index: u32) Key.ErrorSetType { 6941 const error_set = extraDataTrail(extra, Tag.ErrorSet, extra_index); 6942 return .{ 6943 .names = .{ 6944 .tid = tid, 6945 .start = @intCast(error_set.end), 6946 .len = error_set.data.names_len, 6947 }, 6948 .names_map = error_set.data.names_map.toOptional(), 6949 }; 6950 } 6951 6952 fn extraTypeTuple(tid: Zcu.PerThread.Id, extra: Local.Extra, extra_index: u32) Key.TupleType { 6953 const type_tuple = extraDataTrail(extra, TypeTuple, extra_index); 6954 const fields_len = type_tuple.data.fields_len; 6955 return .{ 6956 .types = .{ 6957 .tid = tid, 6958 .start = type_tuple.end, 6959 .len = fields_len, 6960 }, 6961 .values = .{ 6962 .tid = tid, 6963 .start = type_tuple.end + fields_len, 6964 .len = fields_len, 6965 }, 6966 }; 6967 } 6968 6969 fn extraFuncType(tid: Zcu.PerThread.Id, extra: Local.Extra, extra_index: u32) Key.FuncType { 6970 const type_function = extraDataTrail(extra, Tag.TypeFunction, extra_index); 6971 var trail_index: usize = type_function.end; 6972 const comptime_bits: u32 = if (!type_function.data.flags.has_comptime_bits) 0 else b: { 6973 const x = extra.view().items(.@"0")[trail_index]; 6974 trail_index += 1; 6975 break :b x; 6976 }; 6977 const noalias_bits: u32 = if (!type_function.data.flags.has_noalias_bits) 0 else b: { 6978 const x = extra.view().items(.@"0")[trail_index]; 6979 trail_index += 1; 6980 break :b x; 6981 }; 6982 const cc_extra_len = type_function.data.flags.cc.extraLen(); 6983 const cc = type_function.data.flags.cc.unpack(extra.view().items(.@"0")[trail_index..][0..cc_extra_len]); 6984 trail_index += cc_extra_len; 6985 return .{ 6986 .param_types = .{ 6987 .tid = tid, 6988 .start = @intCast(trail_index), 6989 .len = type_function.data.params_len, 6990 }, 6991 .return_type = type_function.data.return_type, 6992 .comptime_bits = comptime_bits, 6993 .noalias_bits = noalias_bits, 6994 .cc = cc, 6995 .is_var_args = type_function.data.flags.is_var_args, 6996 .is_noinline = type_function.data.flags.is_noinline, 6997 }; 6998 } 6999 7000 fn extraFuncDecl(tid: Zcu.PerThread.Id, extra: Local.Extra, extra_index: u32) Key.Func { 7001 const P = Tag.FuncDecl; 7002 const func_decl = extraDataTrail(extra, P, extra_index); 7003 return .{ 7004 .tid = tid, 7005 .ty = func_decl.data.ty, 7006 .uncoerced_ty = func_decl.data.ty, 7007 .analysis_extra_index = extra_index + std.meta.fieldIndex(P, "analysis").?, 7008 .zir_body_inst_extra_index = extra_index + std.meta.fieldIndex(P, "zir_body_inst").?, 7009 .resolved_error_set_extra_index = if (func_decl.data.analysis.inferred_error_set) func_decl.end else 0, 7010 .branch_quota_extra_index = 0, 7011 .owner_nav = func_decl.data.owner_nav, 7012 .zir_body_inst = func_decl.data.zir_body_inst, 7013 .lbrace_line = func_decl.data.lbrace_line, 7014 .rbrace_line = func_decl.data.rbrace_line, 7015 .lbrace_column = func_decl.data.lbrace_column, 7016 .rbrace_column = func_decl.data.rbrace_column, 7017 .generic_owner = .none, 7018 .comptime_args = Index.Slice.empty, 7019 }; 7020 } 7021 7022 fn extraFuncInstance(ip: *const InternPool, tid: Zcu.PerThread.Id, extra: Local.Extra, extra_index: u32) Key.Func { 7023 const extra_items = extra.view().items(.@"0"); 7024 const analysis_extra_index = extra_index + std.meta.fieldIndex(Tag.FuncInstance, "analysis").?; 7025 const analysis: FuncAnalysis = @bitCast(@atomicLoad(u32, &extra_items[analysis_extra_index], .unordered)); 7026 const owner_nav: Nav.Index = @fromBackingInt(@intCast(extra_items[extra_index + std.meta.fieldIndex(Tag.FuncInstance, "owner_nav").?])); 7027 const ty: Index = @fromBackingInt(@intCast(extra_items[extra_index + std.meta.fieldIndex(Tag.FuncInstance, "ty").?])); 7028 const generic_owner: Index = @fromBackingInt(@intCast(extra_items[extra_index + std.meta.fieldIndex(Tag.FuncInstance, "generic_owner").?])); 7029 const func_decl = ip.funcDeclInfo(generic_owner); 7030 const end_extra_index = extra_index + @as(u32, @typeInfo(Tag.FuncInstance).@"struct".field_names.len); 7031 return .{ 7032 .tid = tid, 7033 .ty = ty, 7034 .uncoerced_ty = ty, 7035 .analysis_extra_index = analysis_extra_index, 7036 .zir_body_inst_extra_index = func_decl.zir_body_inst_extra_index, 7037 .resolved_error_set_extra_index = if (analysis.inferred_error_set) end_extra_index else 0, 7038 .branch_quota_extra_index = extra_index + std.meta.fieldIndex(Tag.FuncInstance, "branch_quota").?, 7039 .owner_nav = owner_nav, 7040 .zir_body_inst = func_decl.zir_body_inst, 7041 .lbrace_line = func_decl.lbrace_line, 7042 .rbrace_line = func_decl.rbrace_line, 7043 .lbrace_column = func_decl.lbrace_column, 7044 .rbrace_column = func_decl.rbrace_column, 7045 .generic_owner = generic_owner, 7046 .comptime_args = .{ 7047 .tid = tid, 7048 .start = end_extra_index + @intFromBool(analysis.inferred_error_set), 7049 .len = ip.funcTypeParamsLen(func_decl.ty), 7050 }, 7051 }; 7052 } 7053 7054 fn extraFuncCoerced(ip: *const InternPool, extra: Local.Extra, extra_index: u32) Key.Func { 7055 const func_coerced = extraData(extra, Tag.FuncCoerced, extra_index); 7056 const func_unwrapped = func_coerced.func.unwrap(ip); 7057 const sub_item = func_unwrapped.getItem(ip); 7058 const func_extra = func_unwrapped.getExtra(ip); 7059 var func: Key.Func = switch (sub_item.tag) { 7060 .func_instance => ip.extraFuncInstance(func_unwrapped.tid, func_extra, sub_item.data), 7061 .func_decl => extraFuncDecl(func_unwrapped.tid, func_extra, sub_item.data), 7062 else => unreachable, 7063 }; 7064 func.ty = func_coerced.ty; 7065 return func; 7066 } 7067 7068 fn indexToKeyBigInt(ip: *const InternPool, tid: Zcu.PerThread.Id, limb_index: u32, positive: bool) Key { 7069 const limbs_items = ip.getLocalShared(tid).getLimbs().view().items(.@"0"); 7070 const int: Int = @bitCast(limbs_items[limb_index..][0..Int.limbs_items_len].*); 7071 const big_int: BigIntConst = .{ 7072 .limbs = limbs_items[limb_index + Int.limbs_items_len ..][0..int.limbs_len], 7073 .positive = positive, 7074 }; 7075 return .{ .int = .{ 7076 .ty = int.ty, 7077 .storage = if (big_int.toInt(u64)) |x| 7078 .{ .u64 = x } 7079 else |_| if (big_int.toInt(i64)) |x| 7080 .{ .i64 = x } 7081 else |_| 7082 .{ .big_int = big_int }, 7083 } }; 7084 } 7085 7086 const GetOrPutKey = union(enum) { 7087 existing: Index, 7088 new: struct { 7089 ip: *InternPool, 7090 tid: Zcu.PerThread.Id, 7091 io: Io, 7092 shard: *Shard, 7093 map_index: u32, 7094 }, 7095 7096 fn put(gop: *GetOrPutKey) Index { 7097 switch (gop.*) { 7098 .existing => unreachable, 7099 .new => |*info| { 7100 const index = Index.Unwrapped.wrap(.{ 7101 .tid = info.tid, 7102 .index = info.ip.getLocal(info.tid).mutate.items.len - 1, 7103 }, info.ip); 7104 gop.putTentative(index); 7105 gop.putFinal(index); 7106 return index; 7107 }, 7108 } 7109 } 7110 7111 fn putTentative(gop: *GetOrPutKey, index: Index) void { 7112 assert(index != .none); 7113 switch (gop.*) { 7114 .existing => unreachable, 7115 .new => |*info| gop.new.shard.shared.map.entries[info.map_index].release(index), 7116 } 7117 } 7118 7119 fn putFinal(gop: *GetOrPutKey, index: Index) void { 7120 assert(index != .none); 7121 switch (gop.*) { 7122 .existing => unreachable, 7123 .new => |info| { 7124 assert(info.shard.shared.map.entries[info.map_index].value == index); 7125 info.shard.mutate.map.len += 1; 7126 info.shard.mutate.map.mutex.unlock(info.io); 7127 gop.* = .{ .existing = index }; 7128 }, 7129 } 7130 } 7131 7132 fn cancel(gop: *GetOrPutKey) void { 7133 switch (gop.*) { 7134 .existing => {}, 7135 .new => |info| info.shard.mutate.map.mutex.unlock(info.io), 7136 } 7137 gop.* = .{ .existing = undefined }; 7138 } 7139 7140 fn deinit(gop: *GetOrPutKey) void { 7141 switch (gop.*) { 7142 .existing => {}, 7143 .new => |info| info.shard.shared.map.entries[info.map_index].resetUnordered(), 7144 } 7145 gop.cancel(); 7146 gop.* = undefined; 7147 } 7148 }; 7149 fn getOrPutKey( 7150 ip: *InternPool, 7151 gpa: Allocator, 7152 io: Io, 7153 tid: Zcu.PerThread.Id, 7154 key: Key, 7155 ) Allocator.Error!GetOrPutKey { 7156 return ip.getOrPutKeyEnsuringAdditionalCapacity(gpa, io, tid, key, 0); 7157 } 7158 fn getOrPutKeyEnsuringAdditionalCapacity( 7159 ip: *InternPool, 7160 gpa: Allocator, 7161 io: Io, 7162 tid: Zcu.PerThread.Id, 7163 key: Key, 7164 additional_capacity: u32, 7165 ) Allocator.Error!GetOrPutKey { 7166 const full_hash = key.hash64(ip); 7167 const hash: u32 = @truncate(full_hash >> 32); 7168 const shard = &ip.shards[@intCast(full_hash & (ip.shards.len - 1))]; 7169 var map = shard.shared.map.acquire(); 7170 const Map = @TypeOf(map); 7171 var map_mask = map.header().mask(); 7172 var map_index = hash; 7173 while (true) : (map_index += 1) { 7174 map_index &= map_mask; 7175 const entry = &map.entries[map_index]; 7176 const index = entry.acquire(); 7177 if (index == .none) break; 7178 if (entry.hash != hash) continue; 7179 if (index.unwrap(ip).getTag(ip) == .removed) continue; 7180 if (ip.indexToKey(index).eql(key, ip)) return .{ .existing = index }; 7181 } 7182 shard.mutate.map.mutex.lock(io, tid); 7183 errdefer shard.mutate.map.mutex.unlock(io); 7184 if (map.entries != shard.shared.map.entries) { 7185 map = shard.shared.map; 7186 map_mask = map.header().mask(); 7187 map_index = hash; 7188 } 7189 while (true) : (map_index += 1) { 7190 map_index &= map_mask; 7191 const entry = &map.entries[map_index]; 7192 const index = entry.value; 7193 if (index == .none) break; 7194 if (entry.hash != hash) continue; 7195 if (ip.indexToKey(index).eql(key, ip)) { 7196 defer shard.mutate.map.mutex.unlock(io); 7197 return .{ .existing = index }; 7198 } 7199 } 7200 const map_header = map.header().*; 7201 const required = shard.mutate.map.len + additional_capacity; 7202 if (required >= map_header.capacity * 3 / 5) { 7203 const arena_state = &ip.getLocal(tid).mutate.arena; 7204 var arena = arena_state.promote(gpa); 7205 defer arena_state.* = arena.state; 7206 var new_map_capacity = map_header.capacity; 7207 while (true) { 7208 new_map_capacity *= 2; 7209 if (required < new_map_capacity * 3 / 5) break; 7210 } 7211 const new_map_buf = try arena.allocator().alignedAlloc( 7212 u8, 7213 .fromByteUnits(Map.alignment), 7214 Map.entries_offset + new_map_capacity * @sizeOf(Map.Entry), 7215 ); 7216 const new_map: Map = .{ .entries = @ptrCast(new_map_buf[Map.entries_offset..].ptr) }; 7217 new_map.header().* = .{ .capacity = new_map_capacity }; 7218 @memset(new_map.entries[0..new_map_capacity], .{ .value = .none, .hash = undefined }); 7219 const new_map_mask = new_map.header().mask(); 7220 map_index = 0; 7221 while (map_index < map_header.capacity) : (map_index += 1) { 7222 const entry = &map.entries[map_index]; 7223 const index = entry.value; 7224 if (index == .none) continue; 7225 const item_hash = entry.hash; 7226 var new_map_index = item_hash; 7227 while (true) : (new_map_index += 1) { 7228 new_map_index &= new_map_mask; 7229 const new_entry = &new_map.entries[new_map_index]; 7230 if (new_entry.value != .none) continue; 7231 new_entry.* = .{ 7232 .value = index, 7233 .hash = item_hash, 7234 }; 7235 break; 7236 } 7237 } 7238 map = new_map; 7239 map_index = hash; 7240 while (true) : (map_index += 1) { 7241 map_index &= new_map_mask; 7242 if (map.entries[map_index].value == .none) break; 7243 } 7244 shard.shared.map.release(new_map); 7245 } 7246 map.entries[map_index].hash = hash; 7247 return .{ .new = .{ 7248 .ip = ip, 7249 .tid = tid, 7250 .io = io, 7251 .shard = shard, 7252 .map_index = map_index, 7253 } }; 7254 } 7255 7256 pub fn get(ip: *InternPool, gpa: Allocator, io: Io, tid: Zcu.PerThread.Id, key: Key) Allocator.Error!Index { 7257 var gop = try ip.getOrPutKey(gpa, io, tid, key); 7258 defer gop.deinit(); 7259 if (gop == .existing) return gop.existing; 7260 const local = ip.getLocal(tid); 7261 const items = local.getMutableItems(gpa, io); 7262 const extra = local.getMutableExtra(gpa, io); 7263 try items.ensureUnusedCapacity(1); 7264 switch (key) { 7265 .int_type => |int_type| { 7266 if (int_type.signedness == .signed) assert(int_type.bits > 0); 7267 const t: Tag = switch (int_type.signedness) { 7268 .signed => .type_int_signed, 7269 .unsigned => .type_int_unsigned, 7270 }; 7271 items.appendAssumeCapacity(.{ 7272 .tag = t, 7273 .data = int_type.bits, 7274 }); 7275 }, 7276 .ptr_type => |ptr_type| { 7277 assert(ptr_type.child != .none); 7278 assert(ptr_type.sentinel == .none or ip.typeOf(ptr_type.sentinel) == ptr_type.child); 7279 7280 if (ptr_type.flags.size == .slice) { 7281 gop.cancel(); 7282 var new_key = key; 7283 new_key.ptr_type.flags.size = .many; 7284 const ptr_type_index = try ip.get(gpa, io, tid, new_key); 7285 gop = try ip.getOrPutKey(gpa, io, tid, key); 7286 7287 try items.ensureUnusedCapacity(1); 7288 items.appendAssumeCapacity(.{ 7289 .tag = .type_slice, 7290 .data = @backingInt(ptr_type_index), 7291 }); 7292 return gop.put(); 7293 } 7294 7295 var ptr_type_adjusted = ptr_type; 7296 if (ptr_type.flags.size == .c) ptr_type_adjusted.flags.is_allowzero = true; 7297 7298 items.appendAssumeCapacity(.{ 7299 .tag = .type_pointer, 7300 .data = try addExtra(extra, ptr_type_adjusted), 7301 }); 7302 }, 7303 .array_type => |array_type| { 7304 assert(array_type.child != .none); 7305 assert(array_type.sentinel == .none or ip.typeOf(array_type.sentinel) == array_type.child); 7306 7307 if (std.math.cast(u32, array_type.len)) |len| { 7308 if (array_type.sentinel == .none) { 7309 items.appendAssumeCapacity(.{ 7310 .tag = .type_array_small, 7311 .data = try addExtra(extra, Vector{ 7312 .len = len, 7313 .child = array_type.child, 7314 }), 7315 }); 7316 return gop.put(); 7317 } 7318 } 7319 7320 const length = Array.Length.init(array_type.len); 7321 items.appendAssumeCapacity(.{ 7322 .tag = .type_array_big, 7323 .data = try addExtra(extra, Array{ 7324 .len0 = length.a, 7325 .len1 = length.b, 7326 .child = array_type.child, 7327 .sentinel = array_type.sentinel, 7328 }), 7329 }); 7330 }, 7331 .vector_type => |vector_type| { 7332 items.appendAssumeCapacity(.{ 7333 .tag = .type_vector, 7334 .data = try addExtra(extra, Vector{ 7335 .len = vector_type.len, 7336 .child = vector_type.child, 7337 }), 7338 }); 7339 }, 7340 .opt_type => |payload_type| { 7341 assert(payload_type != .none); 7342 items.appendAssumeCapacity(.{ 7343 .tag = .type_optional, 7344 .data = @backingInt(payload_type), 7345 }); 7346 }, 7347 .anyframe_type => |payload_type| { 7348 // payload_type might be none, indicating the type is `anyframe`. 7349 items.appendAssumeCapacity(.{ 7350 .tag = .type_anyframe, 7351 .data = @backingInt(payload_type), 7352 }); 7353 }, 7354 .error_union_type => |error_union_type| { 7355 items.appendAssumeCapacity(if (error_union_type.error_set_type == .anyerror_type) .{ 7356 .tag = .type_anyerror_union, 7357 .data = @backingInt(error_union_type.payload_type), 7358 } else .{ 7359 .tag = .type_error_union, 7360 .data = try addExtra(extra, error_union_type), 7361 }); 7362 }, 7363 .error_set_type => |error_set_type| { 7364 assert(error_set_type.names_map == .none); 7365 assert(std.sort.isSorted(NullTerminatedString, error_set_type.names.get(ip), {}, NullTerminatedString.indexLessThan)); 7366 const names = error_set_type.names.get(ip); 7367 const names_map = try ip.addMap(gpa, io, tid, names.len); 7368 ip.addStringsToMap(names_map, names); 7369 const names_len = error_set_type.names.len; 7370 try extra.ensureUnusedCapacity(@typeInfo(Tag.ErrorSet).@"struct".field_names.len + names_len); 7371 items.appendAssumeCapacity(.{ 7372 .tag = .type_error_set, 7373 .data = addExtraAssumeCapacity(extra, Tag.ErrorSet{ 7374 .names_len = names_len, 7375 .names_map = names_map, 7376 }), 7377 }); 7378 extra.appendSliceAssumeCapacity(.{@ptrCast(error_set_type.names.get(ip))}); 7379 }, 7380 .inferred_error_set_type => |ies_index| { 7381 items.appendAssumeCapacity(.{ 7382 .tag = .type_inferred_error_set, 7383 .data = @backingInt(ies_index), 7384 }); 7385 }, 7386 .simple_type => |simple_type| { 7387 assert(@backingInt(simple_type) == items.mutate.len); 7388 items.appendAssumeCapacity(.{ 7389 .tag = .simple_type, 7390 .data = 0, // avoid writing `undefined` bits to a file 7391 }); 7392 }, 7393 .simple_value => |simple_value| { 7394 assert(@backingInt(simple_value) == items.mutate.len); 7395 items.appendAssumeCapacity(.{ 7396 .tag = .simple_value, 7397 .data = 0, // avoid writing `undefined` bits to a file 7398 }); 7399 }, 7400 .undef => |ty| { 7401 assert(ty != .none); 7402 items.appendAssumeCapacity(.{ 7403 .tag = .undef, 7404 .data = @backingInt(ty), 7405 }); 7406 }, 7407 7408 .struct_type => unreachable, // instead use: getDeclaredStructType, getReifiedStructType 7409 .union_type => unreachable, // instead use: getDeclaredUnionType, getReifiedUnionType 7410 .enum_type => unreachable, // instead use: getDeclaredEnumType, getReifiedEnumType, getGeneratedEnumTagType 7411 .opaque_type => unreachable, // instead use: getDeclaredOpaqueType 7412 .spirv_type => unreachable, // instead use: getSpirvType 7413 7414 .tuple_type => unreachable, // use getTupleType() instead 7415 .func_type => unreachable, // use getFuncType() instead 7416 .@"extern" => unreachable, // use getExtern() instead 7417 .func => unreachable, // use getFuncInstance() or getFuncDecl() instead 7418 .un => unreachable, // use getUnion instead 7419 7420 .slice => |slice| { 7421 assert(ip.indexToKey(slice.ty).ptr_type.flags.size == .slice); 7422 assert(ip.indexToKey(ip.typeOf(slice.ptr)).ptr_type.flags.size == .many); 7423 items.appendAssumeCapacity(.{ 7424 .tag = .ptr_slice, 7425 .data = try addExtra(extra, PtrSlice{ 7426 .ty = slice.ty, 7427 .ptr = slice.ptr, 7428 .len = slice.len, 7429 }), 7430 }); 7431 }, 7432 7433 .ptr => |ptr| { 7434 const ptr_type = ip.indexToKey(ptr.ty).ptr_type; 7435 assert(ptr_type.flags.size != .slice); 7436 items.appendAssumeCapacity(switch (ptr.base_addr) { 7437 .nav => |nav| .{ 7438 .tag = .ptr_nav, 7439 .data = try addExtra(extra, PtrNav.init(ptr.ty, nav, ptr.byte_offset)), 7440 }, 7441 .comptime_alloc => |alloc_index| .{ 7442 .tag = .ptr_comptime_alloc, 7443 .data = try addExtra(extra, PtrComptimeAlloc.init(ptr.ty, alloc_index, ptr.byte_offset)), 7444 }, 7445 .uav => |uav| if (ptrsHaveSameAlignment(ip, ptr.ty, ptr_type, uav.orig_ty)) item: { 7446 if (ptr.ty != uav.orig_ty) { 7447 gop.cancel(); 7448 var new_key = key; 7449 new_key.ptr.base_addr.uav.orig_ty = ptr.ty; 7450 gop = try ip.getOrPutKey(gpa, io, tid, new_key); 7451 if (gop == .existing) return gop.existing; 7452 } 7453 break :item .{ 7454 .tag = .ptr_uav, 7455 .data = try addExtra(extra, PtrUav.init(ptr.ty, uav.val, ptr.byte_offset)), 7456 }; 7457 } else .{ 7458 .tag = .ptr_uav_aligned, 7459 .data = try addExtra(extra, PtrUavAligned.init(ptr.ty, uav.val, uav.orig_ty, ptr.byte_offset)), 7460 }, 7461 .comptime_field => |field_val| item: { 7462 assert(field_val != .none); 7463 break :item .{ 7464 .tag = .ptr_comptime_field, 7465 .data = try addExtra(extra, PtrComptimeField.init(ptr.ty, field_val, ptr.byte_offset)), 7466 }; 7467 }, 7468 .eu_payload, .opt_payload => |base| item: { 7469 switch (ptr.base_addr) { 7470 .eu_payload => assert(ip.indexToKey( 7471 ip.indexToKey(ip.typeOf(base)).ptr_type.child, 7472 ) == .error_union_type), 7473 .opt_payload => assert(ip.indexToKey( 7474 ip.indexToKey(ip.typeOf(base)).ptr_type.child, 7475 ) == .opt_type), 7476 else => unreachable, 7477 } 7478 break :item .{ 7479 .tag = switch (ptr.base_addr) { 7480 .eu_payload => .ptr_eu_payload, 7481 .opt_payload => .ptr_opt_payload, 7482 else => unreachable, 7483 }, 7484 .data = try addExtra(extra, PtrBase.init(ptr.ty, base, ptr.byte_offset)), 7485 }; 7486 }, 7487 .int => .{ 7488 .tag = .ptr_int, 7489 .data = try addExtra(extra, PtrInt.init(ptr.ty, ptr.byte_offset)), 7490 }, 7491 .arr_elem, .field => |base_index| { 7492 const base_ptr_type = ip.indexToKey(ip.typeOf(base_index.base)).ptr_type; 7493 switch (ptr.base_addr) { 7494 .arr_elem => assert(base_ptr_type.flags.size == .many), 7495 .field => { 7496 assert(base_ptr_type.flags.size == .one); 7497 switch (ip.indexToKey(base_ptr_type.child)) { 7498 .tuple_type => |tuple_type| { 7499 assert(ptr.base_addr == .field); 7500 assert(base_index.index < tuple_type.types.len); 7501 }, 7502 .struct_type => { 7503 assert(ptr.base_addr == .field); 7504 assert(base_index.index < ip.loadStructType(base_ptr_type.child).field_types.len); 7505 }, 7506 .union_type => { 7507 const union_type = ip.loadUnionType(base_ptr_type.child); 7508 assert(ptr.base_addr == .field); 7509 assert(base_index.index < union_type.field_types.len); 7510 }, 7511 .ptr_type => |slice_type| { 7512 assert(ptr.base_addr == .field); 7513 assert(slice_type.flags.size == .slice); 7514 assert(base_index.index < 2); 7515 }, 7516 else => unreachable, 7517 } 7518 }, 7519 else => unreachable, 7520 } 7521 gop.cancel(); 7522 const index_index = try ip.get(gpa, io, tid, .{ .int = .{ 7523 .ty = .usize_type, 7524 .storage = .{ .u64 = base_index.index }, 7525 } }); 7526 gop = try ip.getOrPutKey(gpa, io, tid, key); 7527 try items.ensureUnusedCapacity(1); 7528 items.appendAssumeCapacity(.{ 7529 .tag = switch (ptr.base_addr) { 7530 .arr_elem => .ptr_elem, 7531 .field => .ptr_field, 7532 else => unreachable, 7533 }, 7534 .data = try addExtra(extra, PtrBaseIndex.init(ptr.ty, base_index.base, index_index, ptr.byte_offset)), 7535 }); 7536 return gop.put(); 7537 }, 7538 }); 7539 }, 7540 7541 .opt => |opt| { 7542 assert(ip.isOptionalType(opt.ty)); 7543 assert(opt.val == .none or ip.indexToKey(opt.ty).opt_type == ip.typeOf(opt.val)); 7544 items.appendAssumeCapacity(if (opt.val == .none) .{ 7545 .tag = .opt_null, 7546 .data = @backingInt(opt.ty), 7547 } else .{ 7548 .tag = .opt_payload, 7549 .data = try addExtra(extra, Tag.TypeValue{ 7550 .ty = opt.ty, 7551 .val = opt.val, 7552 }), 7553 }); 7554 }, 7555 7556 .int => |int| b: { 7557 assert(ip.isIntegerType(int.ty)); 7558 switch (int.ty) { 7559 .u8_type => switch (int.storage) { 7560 .big_int => |big_int| { 7561 items.appendAssumeCapacity(.{ 7562 .tag = .int_u8, 7563 .data = big_int.toInt(u8) catch unreachable, 7564 }); 7565 break :b; 7566 }, 7567 inline .u64, .i64 => |x| { 7568 items.appendAssumeCapacity(.{ 7569 .tag = .int_u8, 7570 .data = @as(u8, @intCast(x)), 7571 }); 7572 break :b; 7573 }, 7574 }, 7575 .u16_type => switch (int.storage) { 7576 .big_int => |big_int| { 7577 items.appendAssumeCapacity(.{ 7578 .tag = .int_u16, 7579 .data = big_int.toInt(u16) catch unreachable, 7580 }); 7581 break :b; 7582 }, 7583 inline .u64, .i64 => |x| { 7584 items.appendAssumeCapacity(.{ 7585 .tag = .int_u16, 7586 .data = @as(u16, @intCast(x)), 7587 }); 7588 break :b; 7589 }, 7590 }, 7591 .u32_type => switch (int.storage) { 7592 .big_int => |big_int| { 7593 items.appendAssumeCapacity(.{ 7594 .tag = .int_u32, 7595 .data = big_int.toInt(u32) catch unreachable, 7596 }); 7597 break :b; 7598 }, 7599 inline .u64, .i64 => |x| { 7600 items.appendAssumeCapacity(.{ 7601 .tag = .int_u32, 7602 .data = @as(u32, @intCast(x)), 7603 }); 7604 break :b; 7605 }, 7606 }, 7607 .i32_type => switch (int.storage) { 7608 .big_int => |big_int| { 7609 const casted = big_int.toInt(i32) catch unreachable; 7610 items.appendAssumeCapacity(.{ 7611 .tag = .int_i32, 7612 .data = @as(u32, @bitCast(casted)), 7613 }); 7614 break :b; 7615 }, 7616 inline .u64, .i64 => |x| { 7617 items.appendAssumeCapacity(.{ 7618 .tag = .int_i32, 7619 .data = @as(u32, @bitCast(@as(i32, @intCast(x)))), 7620 }); 7621 break :b; 7622 }, 7623 }, 7624 .usize_type => switch (int.storage) { 7625 .big_int => |big_int| { 7626 if (big_int.toInt(u32)) |casted| { 7627 items.appendAssumeCapacity(.{ 7628 .tag = .int_usize, 7629 .data = casted, 7630 }); 7631 break :b; 7632 } else |_| {} 7633 }, 7634 inline .u64, .i64 => |x| { 7635 if (std.math.cast(u32, x)) |casted| { 7636 items.appendAssumeCapacity(.{ 7637 .tag = .int_usize, 7638 .data = casted, 7639 }); 7640 break :b; 7641 } 7642 }, 7643 }, 7644 .comptime_int_type => switch (int.storage) { 7645 .big_int => |big_int| { 7646 if (big_int.toInt(u32)) |casted| { 7647 items.appendAssumeCapacity(.{ 7648 .tag = .int_comptime_int_u32, 7649 .data = casted, 7650 }); 7651 break :b; 7652 } else |_| {} 7653 if (big_int.toInt(i32)) |casted| { 7654 items.appendAssumeCapacity(.{ 7655 .tag = .int_comptime_int_i32, 7656 .data = @as(u32, @bitCast(casted)), 7657 }); 7658 break :b; 7659 } else |_| {} 7660 }, 7661 inline .u64, .i64 => |x| { 7662 if (std.math.cast(u32, x)) |casted| { 7663 items.appendAssumeCapacity(.{ 7664 .tag = .int_comptime_int_u32, 7665 .data = casted, 7666 }); 7667 break :b; 7668 } 7669 if (std.math.cast(i32, x)) |casted| { 7670 items.appendAssumeCapacity(.{ 7671 .tag = .int_comptime_int_i32, 7672 .data = @as(u32, @bitCast(casted)), 7673 }); 7674 break :b; 7675 } 7676 }, 7677 }, 7678 else => {}, 7679 } 7680 switch (int.storage) { 7681 .big_int => |big_int| { 7682 if (big_int.toInt(u32)) |casted| { 7683 items.appendAssumeCapacity(.{ 7684 .tag = .int_small, 7685 .data = try addExtra(extra, IntSmall{ 7686 .ty = int.ty, 7687 .value = casted, 7688 }), 7689 }); 7690 return gop.put(); 7691 } else |_| {} 7692 7693 const tag: Tag = if (big_int.positive or big_int.eqlZero()) .int_positive else .int_negative; 7694 try addInt(ip, gpa, io, tid, int.ty, tag, big_int.limbs); 7695 }, 7696 inline .u64, .i64 => |x| { 7697 if (std.math.cast(u32, x)) |casted| { 7698 items.appendAssumeCapacity(.{ 7699 .tag = .int_small, 7700 .data = try addExtra(extra, IntSmall{ 7701 .ty = int.ty, 7702 .value = casted, 7703 }), 7704 }); 7705 return gop.put(); 7706 } 7707 7708 var buf: [2]Limb = undefined; 7709 const big_int = BigIntMutable.init(&buf, x).toConst(); 7710 const tag: Tag = if (big_int.positive or big_int.eqlZero()) .int_positive else .int_negative; 7711 try addInt(ip, gpa, io, tid, int.ty, tag, big_int.limbs); 7712 }, 7713 } 7714 }, 7715 7716 .err => |err| { 7717 assert(ip.isErrorSetType(err.ty)); 7718 items.appendAssumeCapacity(.{ 7719 .tag = .error_set_error, 7720 .data = try addExtra(extra, err), 7721 }); 7722 }, 7723 7724 .error_union => |error_union| { 7725 assert(ip.isErrorUnionType(error_union.ty)); 7726 items.appendAssumeCapacity(switch (error_union.val) { 7727 .err_name => |err_name| .{ 7728 .tag = .error_union_error, 7729 .data = try addExtra(extra, Key.Error{ 7730 .ty = error_union.ty, 7731 .name = err_name, 7732 }), 7733 }, 7734 .payload => |payload| .{ 7735 .tag = .error_union_payload, 7736 .data = try addExtra(extra, Tag.TypeValue{ 7737 .ty = error_union.ty, 7738 .val = payload, 7739 }), 7740 }, 7741 }); 7742 }, 7743 7744 .enum_literal => |enum_literal| items.appendAssumeCapacity(.{ 7745 .tag = .enum_literal, 7746 .data = @backingInt(enum_literal), 7747 }), 7748 7749 .enum_tag => |enum_tag| { 7750 const enum_obj = ip.loadEnumType(enum_tag.ty); 7751 assert(ip.typeOf(enum_tag.int) == enum_obj.int_tag_type); 7752 items.appendAssumeCapacity(.{ 7753 .tag = .enum_tag, 7754 .data = try addExtra(extra, enum_tag), 7755 }); 7756 }, 7757 7758 .float => |float| { 7759 switch (float.ty) { 7760 .f16_type => items.appendAssumeCapacity(.{ 7761 .tag = .float_f16, 7762 .data = @as(u16, @bitCast(float.storage.f16)), 7763 }), 7764 .f32_type => items.appendAssumeCapacity(.{ 7765 .tag = .float_f32, 7766 .data = @as(u32, @bitCast(float.storage.f32)), 7767 }), 7768 .f64_type => items.appendAssumeCapacity(.{ 7769 .tag = .float_f64, 7770 .data = try addExtra(extra, Float64.pack(float.storage.f64)), 7771 }), 7772 .f80_type => items.appendAssumeCapacity(.{ 7773 .tag = .float_f80, 7774 .data = try addExtra(extra, Float80.pack(float.storage.f80)), 7775 }), 7776 .f128_type => items.appendAssumeCapacity(.{ 7777 .tag = .float_f128, 7778 .data = try addExtra(extra, Float128.pack(float.storage.f128)), 7779 }), 7780 .c_longdouble_type => switch (float.storage) { 7781 .f80 => |x| items.appendAssumeCapacity(.{ 7782 .tag = .float_c_longdouble_f80, 7783 .data = try addExtra(extra, Float80.pack(x)), 7784 }), 7785 inline .f16, .f32, .f64, .f128 => |x| items.appendAssumeCapacity(.{ 7786 .tag = .float_c_longdouble_f128, 7787 .data = try addExtra(extra, Float128.pack(x)), 7788 }), 7789 }, 7790 .comptime_float_type => items.appendAssumeCapacity(.{ 7791 .tag = .float_comptime_float, 7792 .data = try addExtra(extra, Float128.pack(float.storage.f128)), 7793 }), 7794 else => unreachable, 7795 } 7796 }, 7797 7798 .aggregate => |aggregate| { 7799 const ty_key = ip.indexToKey(aggregate.ty); 7800 const len = ip.aggregateTypeLen(aggregate.ty); 7801 const child: Index, const sentinel: Index = switch (ty_key) { 7802 .array_type => |array_type| .{ array_type.child, array_type.sentinel }, 7803 .vector_type => |vector_type| .{ vector_type.child, .none }, 7804 .tuple_type => .{ .none, .none }, 7805 .struct_type => child: { 7806 assert(ip.loadStructType(aggregate.ty).layout != .@"packed"); 7807 break :child .{ .none, .none }; 7808 }, 7809 else => unreachable, 7810 }; 7811 const len_including_sentinel = len + @intFromBool(sentinel != .none); 7812 switch (aggregate.storage) { 7813 .bytes => |bytes| { 7814 assert(child == .u8_type); 7815 if (sentinel != .none) { 7816 assert(bytes.at(@intCast(len), ip) == ip.indexToKey(sentinel).int.storage.u64); 7817 } 7818 }, 7819 .elems => |elems| { 7820 if (elems.len != len) { 7821 assert(elems.len == len_including_sentinel); 7822 assert(elems[@intCast(len)] == sentinel); 7823 } 7824 }, 7825 .repeated_elem => |elem| { 7826 assert(sentinel == .none or elem == sentinel); 7827 }, 7828 } 7829 if (aggregate.storage.values().len > 0) switch (ty_key) { 7830 .array_type, .vector_type => { 7831 var any_defined = false; 7832 for (aggregate.storage.values()) |elem| { 7833 if (!ip.isUndef(elem)) any_defined = true; 7834 assert(ip.typeOf(elem) == child); 7835 } 7836 assert(any_defined); // aggregate fields must not be all undefined 7837 }, 7838 .struct_type => { 7839 var any_defined = false; 7840 for (aggregate.storage.values(), ip.loadStructType(aggregate.ty).field_types.get(ip)) |elem, field_ty| { 7841 if (!ip.isUndef(elem)) any_defined = true; 7842 assert(ip.typeOf(elem) == field_ty); 7843 } 7844 assert(any_defined); // aggregate fields must not be all undefined 7845 }, 7846 .tuple_type => |tuple_type| { 7847 var any_defined = false; 7848 for (aggregate.storage.values(), tuple_type.types.get(ip)) |elem, ty| { 7849 if (!ip.isUndef(elem)) any_defined = true; 7850 assert(ip.typeOf(elem) == ty); 7851 } 7852 assert(any_defined); // aggregate fields must not be all undefined 7853 }, 7854 else => unreachable, 7855 }; 7856 7857 if (len == 0) { 7858 items.appendAssumeCapacity(.{ 7859 .tag = .only_possible_value, 7860 .data = @backingInt(aggregate.ty), 7861 }); 7862 return gop.put(); 7863 } 7864 7865 switch (ty_key) { 7866 .tuple_type => |tuple_type| opv: { 7867 switch (aggregate.storage) { 7868 .bytes => |bytes| for (tuple_type.values.get(ip), bytes.at(0, ip)..) |value, byte| { 7869 if (value == .none) break :opv; 7870 switch (ip.indexToKey(value)) { 7871 .undef => break :opv, 7872 .int => |int| switch (int.storage) { 7873 .u64 => |x| if (x != byte) break :opv, 7874 else => break :opv, 7875 }, 7876 else => unreachable, 7877 } 7878 }, 7879 .elems => |elems| if (!std.mem.eql( 7880 Index, 7881 tuple_type.values.get(ip), 7882 elems, 7883 )) break :opv, 7884 .repeated_elem => |elem| for (tuple_type.values.get(ip)) |value| { 7885 if (value != elem) break :opv; 7886 }, 7887 } 7888 // This encoding works thanks to the fact that, as we just verified, 7889 // the type itself contains a slice of values that can be provided 7890 // in the aggregate fields. 7891 items.appendAssumeCapacity(.{ 7892 .tag = .only_possible_value, 7893 .data = @backingInt(aggregate.ty), 7894 }); 7895 return gop.put(); 7896 }, 7897 else => {}, 7898 } 7899 7900 repeated: { 7901 switch (aggregate.storage) { 7902 .bytes => |bytes| for (bytes.toSlice(len, ip)[1..]) |byte| 7903 if (byte != bytes.at(0, ip)) break :repeated, 7904 .elems => |elems| for (elems[1..@intCast(len)]) |elem| 7905 if (elem != elems[0]) break :repeated, 7906 .repeated_elem => {}, 7907 } 7908 const elem = switch (aggregate.storage) { 7909 .bytes => |bytes| elem: { 7910 gop.cancel(); 7911 const elem = try ip.get(gpa, io, tid, .{ .int = .{ 7912 .ty = .u8_type, 7913 .storage = .{ .u64 = bytes.at(0, ip) }, 7914 } }); 7915 gop = try ip.getOrPutKey(gpa, io, tid, key); 7916 try items.ensureUnusedCapacity(1); 7917 break :elem elem; 7918 }, 7919 .elems => |elems| elems[0], 7920 .repeated_elem => |elem| elem, 7921 }; 7922 7923 try extra.ensureUnusedCapacity(@typeInfo(Repeated).@"struct".field_names.len); 7924 items.appendAssumeCapacity(.{ 7925 .tag = .repeated, 7926 .data = addExtraAssumeCapacity(extra, Repeated{ 7927 .ty = aggregate.ty, 7928 .elem_val = elem, 7929 }), 7930 }); 7931 return gop.put(); 7932 } 7933 7934 if (child == .u8_type) bytes: { 7935 const string_bytes = ip.getLocal(tid).getMutableStringBytes(gpa, io); 7936 const start = string_bytes.mutate.len; 7937 try string_bytes.ensureUnusedCapacity(@intCast(len_including_sentinel + 1)); 7938 try extra.ensureUnusedCapacity(@typeInfo(Bytes).@"struct".field_names.len); 7939 switch (aggregate.storage) { 7940 .bytes => |bytes| string_bytes.appendSliceAssumeCapacity(.{bytes.toSlice(len, ip)}), 7941 .elems => |elems| for (elems[0..@intCast(len)]) |elem| switch (ip.indexToKey(elem)) { 7942 .undef => { 7943 string_bytes.shrinkRetainingCapacity(start); 7944 break :bytes; 7945 }, 7946 .int => |int| string_bytes.appendAssumeCapacity(.{@intCast(int.storage.u64)}), 7947 else => unreachable, 7948 }, 7949 .repeated_elem => |elem| switch (ip.indexToKey(elem)) { 7950 .undef => break :bytes, 7951 .int => |int| @memset( 7952 string_bytes.addManyAsSliceAssumeCapacity(@intCast(len))[0], 7953 @intCast(int.storage.u64), 7954 ), 7955 else => unreachable, 7956 }, 7957 } 7958 if (sentinel != .none) string_bytes.appendAssumeCapacity(.{ 7959 @intCast(ip.indexToKey(sentinel).int.storage.u64), 7960 }); 7961 const string = try ip.getOrPutTrailingString( 7962 gpa, 7963 io, 7964 tid, 7965 @intCast(len_including_sentinel), 7966 .maybe_embedded_nulls, 7967 ); 7968 items.appendAssumeCapacity(.{ 7969 .tag = .bytes, 7970 .data = addExtraAssumeCapacity(extra, Bytes{ 7971 .ty = aggregate.ty, 7972 .bytes = string, 7973 }), 7974 }); 7975 return gop.put(); 7976 } 7977 7978 try extra.ensureUnusedCapacity( 7979 @typeInfo(Tag.Aggregate).@"struct".field_names.len + @as(usize, @intCast(len_including_sentinel + 1)), 7980 ); 7981 items.appendAssumeCapacity(.{ 7982 .tag = .aggregate, 7983 .data = addExtraAssumeCapacity(extra, Tag.Aggregate{ 7984 .ty = aggregate.ty, 7985 }), 7986 }); 7987 extra.appendSliceAssumeCapacity(.{@ptrCast(aggregate.storage.elems)}); 7988 if (sentinel != .none) extra.appendAssumeCapacity(.{@backingInt(sentinel)}); 7989 }, 7990 .bitpack => |bitpack| { 7991 switch (ip.zigTypeTag(bitpack.ty)) { 7992 .@"struct" => assert(ip.typeOf(bitpack.backing_int_val) == ip.loadStructType(bitpack.ty).packed_backing_int_type), 7993 .@"union" => assert(ip.typeOf(bitpack.backing_int_val) == ip.loadUnionType(bitpack.ty).packed_backing_int_type), 7994 else => unreachable, 7995 } 7996 assert(!ip.isUndef(bitpack.backing_int_val)); 7997 items.appendAssumeCapacity(.{ 7998 .tag = .bitpack, 7999 .data = try addExtra(extra, bitpack), 8000 }); 8001 }, 8002 8003 .memoized_call => |memoized_call| { 8004 for (memoized_call.arg_values) |arg| assert(arg != .none); 8005 try extra.ensureUnusedCapacity(@typeInfo(MemoizedCall).@"struct".field_names.len + 8006 memoized_call.arg_values.len); 8007 items.appendAssumeCapacity(.{ 8008 .tag = .memoized_call, 8009 .data = addExtraAssumeCapacity(extra, MemoizedCall{ 8010 .func = memoized_call.func, 8011 .args_len = @intCast(memoized_call.arg_values.len), 8012 .result = memoized_call.result, 8013 .branch_count = memoized_call.branch_count, 8014 .branch_quota = memoized_call.branch_quota, 8015 }), 8016 }); 8017 extra.appendSliceAssumeCapacity(.{@ptrCast(memoized_call.arg_values)}); 8018 }, 8019 } 8020 return gop.put(); 8021 } 8022 8023 pub fn getDeclaredStructType( 8024 ip: *InternPool, 8025 gpa: Allocator, 8026 io: Io, 8027 tid: Zcu.PerThread.Id, 8028 ini: struct { 8029 zir_index: TrackedInst.Index, 8030 captures: []const CaptureValue, 8031 8032 // If the value of any of the following fields would change on an incremental update, then logic 8033 // in `Zcu.mapOldZirToNew` must detect that (these properties are all trivially known from ZIR) 8034 // and refuse to map the type declaration. This causes `zir_index` to change so that a new type 8035 // will be interned at a fresh index. 8036 // 8037 // In the future, it would be good to remove all of those fields from `ini`, and in fact just 8038 // have a single function `getDeclaredContainer` which is suitable for all container types. 8039 // However, this requires some major changes to how container types are represented in the 8040 // InternPool, so that it is possible for their backing storage to be "reallocated" as needed 8041 // during type resolution.