╭─────────────╮╭────────────╮ │scroll to top││next lines →│ ╰─────────────╯╰────────────╯ ╭ InternPool.zig ───────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭ find file ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ ╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │ │ │http│ ssh │ │ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
520 .tid = @fromBackingInt(@intCast(@backingInt(id) >> ip.tid_shift_32 & ip.getTidMask())), 521 .index = @backingInt(id) & ip.getIndexMask(u31), 522 }; 523 } 524 525 const debug_state = InternPool.debug_state; 526 }; 527 }; 528 529 /// Named Addressable Value. Represents a global value with a name and address. This name may be 530 /// generated, and the type (and hence address) may be comptime-only. A `Nav` whose type has runtime 531 /// bits is sent to the linker to be emitted to the binary. 532 /// 533 /// * Every ZIR `declaration` which is not a `comptime` declaration has a `Nav` (post-instantiation) 534 /// which stores the declaration's resolved value. 535 /// * Generic instances have a `Nav` corresponding to the instantiated function. 536 /// * `@extern` calls create a `Nav` whose value is a `.@"extern"`. 537 /// 538 /// This data structure is optimized for the `analysis_info != null` case, because this is much more 539 /// common in practice; the other case is used only for externs and for generic instances. At the time 540 /// of writing, in the compiler itself, around 74% of all `Nav`s have `analysis_info != null`. 541 /// (Specifically, 104225 / 140923) 542 /// 543 /// `Nav.Repr` is the in-memory representation. 544 pub const Nav = struct { 545 /// The unqualified name of this `Nav`. Namespace lookups use this name, and error messages may use it. 546 /// Additionally, extern `Nav`s (i.e. those whose value is an `extern`) use this name. 547 name: NullTerminatedString, 548 /// The fully-qualified name of this `Nav`. 549 fqn: NullTerminatedString, 550 /// This field is populated iff this `Nav` is resolved by semantic analysis. 551 /// If this is `null`, then `resolved` is *not* `null`. 552 analysis: ?struct { 553 namespace: NamespaceIndex, 554 zir_index: TrackedInst.Index, 555 /// Initially `false`. Set to `true` by `setWantNavAnalysis`. 556 wanted: bool, 557 }, 558 /// If this is `null`, then `analysis` is *not* `null`, and semantic analysis is required to 559 /// resolve the type and value of this `Nav`. Otherwise, the type is resolved---therefore, 560 /// `Nav.resolved.?.type` is never `.none`. However, the *value* may not be resolved yet even 561 /// if this field is not `null`---see `Resolved.value` for details. 562 resolved: ?Resolved, 563 564 pub const Resolved = struct { 565 /// This is never `.none` 566 type: InternPool.Index, 567 @"align": Alignment, 568 @"linksection": OptionalNullTerminatedString, 569 @"addrspace": std.lang.AddressSpace, 570 @"const": bool, 571 @"threadlocal": bool, 572 /// This field is whether this `Nav` is a literal `extern` definition. 573 /// It does *not* tell you whether this might alias an extern fn (see #21027). 574 is_extern_decl: bool, 575 /// If the type is resolved but not the value, this is `.none`. In that case, the value will 576 /// be resolved by semantic analysis, so `Nav.analysis` is definitely not `null`. 577 /// 578 /// If this is an extern, the special key `Key.@"extern"` is used. 579 /// 580 /// If this is a variable (`Resolved.@"const" == false`) and not an extern, then this value 581 /// is the global variable's initializer; the value loaded from the variable at runtime may 582 /// of course be different. 583 value: InternPool.Index, 584 }; 585 586 /// If the value of this `Nav` is resolved and is an extern, returns the `Key.Extern`. If the 587 /// value is *not* an extern, *or* if the value is not yet resolved (only the type is), returns 588 /// `null`. 589 /// 590 /// This logic works because the frontend ensures that if a `Nav` *might* be extern, its value 591 /// is resolved more eagerly (see logic in `Sema.analyzeNavRefInner`). Therefore, if we see that 592 /// the value is not yet resolved, we know the frontend determined that the `Nav` is definitely 593 /// *not* extern. 594 /// 595 /// This function is only intended be used by the compiler backend (codegen/link). The guarantee 596 /// mentioned above does not necessarily hold in the compiler frontend (if we haven't reached 597 /// `Sema.analyzeNavRefInner` yet). 598 /// 599 /// Asserts that `nav.resolved != null`. 600 pub fn getExtern(nav: Nav, ip: *const InternPool) ?Key.Extern { 601 const r = nav.resolved.?; 602 if (r.value == .none) return null; 603 return switch (ip.indexToKey(r.value)) { 604 .@"extern" => |e| e, 605 else => null, 606 }; 607 } 608 609 /// Get the ZIR instruction corresponding to this `Nav`, used to resolve source locations. 610 /// This is a `declaration`. 611 pub fn srcInst(nav: Nav, ip: *const InternPool) TrackedInst.Index { 612 if (nav.analysis) |a| { 613 return a.zir_index; 614 } 615 // A `Nav` which does not undergo analysis always has a resolved value. 616 return switch (ip.indexToKey(nav.resolved.?.value)) { 617 .func => |func| { 618 // Since `analysis` was not populated, this must be an instantiation. 619 // Go up to the generic owner and consult *its* `analysis` field. 620 const go_nav = ip.getNav(ip.indexToKey(func.generic_owner).func.owner_nav); 621 return go_nav.analysis.?.zir_index; 622 }, 623 .@"extern" => |@"extern"| @"extern".zir_index, // extern / @extern 624 else => unreachable, 625 }; 626 } 627 628 pub const Index = enum(u32) { 629 _, 630 pub const Optional = enum(u32) { 631 none = std.math.maxInt(u32), 632 _, 633 pub fn unwrap(opt: Optional) ?Nav.Index { 634 return switch (opt) { 635 .none => null, 636 _ => @fromBackingInt(@intCast(@backingInt(opt))), 637 }; 638 } 639 640 const debug_state = InternPool.debug_state; 641 }; 642 pub fn toOptional(i: Nav.Index) Optional { 643 return @fromBackingInt(@intCast(@backingInt(i))); 644 } 645 const Unwrapped = struct { 646 tid: Zcu.PerThread.Id, 647 index: u32, 648 649 fn wrap(unwrapped: Unwrapped, ip: *const InternPool) Nav.Index { 650 assert(@backingInt(unwrapped.tid) <= ip.getTidMask()); 651 assert(unwrapped.index <= ip.getIndexMask(u30)); 652 return @fromBackingInt(@intCast(@shlExact(@as(u32, @backingInt(unwrapped.tid)), ip.tid_shift_30) | 653 unwrapped.index)); 654 } 655 }; 656 fn unwrap(nav_index: Nav.Index, ip: *const InternPool) Unwrapped { 657 return .{ 658 .tid = @fromBackingInt(@intCast(@backingInt(nav_index) >> ip.tid_shift_30 & ip.getTidMask())), 659 .index = @backingInt(nav_index) & ip.getIndexMask(u30), 660 }; 661 } 662 663 const debug_state = InternPool.debug_state; 664 }; 665 666 /// The compact in-memory representation of a `Nav`. 667 /// 30 bytes. 668 const Repr = struct { 669 name: NullTerminatedString, 670 fqn: NullTerminatedString, 671 // The following 2 fields are either both populated, or both `.none`. 672 analysis_namespace: OptionalNamespaceIndex, 673 analysis_zir_index: TrackedInst.Index.Optional, 674 type: InternPool.Index, 675 value: InternPool.Index, 676 @"linksection": OptionalNullTerminatedString, 677 bits: Bits, 678 679 const Bits = packed struct(u16) { 680 @"align": Alignment, 681 @"addrspace": std.lang.AddressSpace, 682 @"const": bool, 683 @"threadlocal": bool, 684 is_extern_decl: bool, 685 want_analysis: bool, 686 _: u1 = 0, 687 }; 688 689 fn unpack(repr: Repr) Nav { 690 return .{ 691 .name = repr.name, 692 .fqn = repr.fqn, 693 .analysis = if (repr.analysis_namespace.unwrap()) |namespace| .{ 694 .namespace = namespace, 695 .zir_index = repr.analysis_zir_index.unwrap().?, 696 .wanted = repr.bits.want_analysis, 697 } else a: { 698 assert(repr.analysis_zir_index == .none); 699 break :a null; 700 }, 701 .resolved = if (repr.type == .none) null else .{ 702 .type = repr.type, 703 .@"align" = repr.bits.@"align", 704 .@"linksection" = repr.@"linksection", 705 .@"addrspace" = repr.bits.@"addrspace", 706 .@"const" = repr.bits.@"const", 707 .@"threadlocal" = repr.bits.@"threadlocal", 708 .is_extern_decl = repr.bits.is_extern_decl, 709 .value = repr.value, 710 }, 711 }; 712 } 713 }; 714 715 fn pack(nav: Nav) Repr { 716 // Note that even if `nav.resolved == null`, we do not set any fields to `undefined`, even 717 // though they should not be used. This is to avoid writing undefined bytes to disk when 718 // serializing buffers. 719 return .{ 720 .name = nav.name, 721 .fqn = nav.fqn, 722 .analysis_namespace = if (nav.analysis) |a| a.namespace.toOptional() else .none, 723 .analysis_zir_index = if (nav.analysis) |a| a.zir_index.toOptional() else .none, 724 .type = if (nav.resolved) |r| r.type else .none, 725 .value = if (nav.resolved) |r| r.value else .none, 726 .@"linksection" = if (nav.resolved) |r| r.@"linksection" else .none, 727 .bits = if (nav.resolved) |r| .{ 728 .@"align" = r.@"align", 729 .@"addrspace" = r.@"addrspace", 730 .@"const" = r.@"const", 731 .@"threadlocal" = r.@"threadlocal", 732 .is_extern_decl = r.is_extern_decl, 733 .want_analysis = if (nav.analysis) |a| a.wanted else false, 734 } else .{ 735 .@"align" = .none, 736 .@"addrspace" = .generic, 737 .@"const" = false, 738 .@"threadlocal" = false, 739 .is_extern_decl = false, 740 .want_analysis = if (nav.analysis) |a| a.wanted else false, 741 }, 742 }; 743 } 744 }; 745 746 pub const Dependee = union(enum) { 747 src_hash: TrackedInst.Index, 748 nav_val: Nav.Index, 749 nav_ty: Nav.Index, 750 /// Index is the function, not its IES. 751 func_ies: Index, 752 type_layout: Index, 753 struct_defaults: Index, 754 source_file: FileIndex, 755 embed_file: Zcu.EmbedFile.Index, 756 namespace: TrackedInst.Index, 757 namespace_name: NamespaceNameKey, 758 memoized_state: MemoizedStateStage, 759 }; 760 761 pub fn removeDependenciesForDepender(ip: *InternPool, gpa: Allocator, depender: AnalUnit) void { 762 var opt_idx = (ip.first_dependency.fetchSwapRemove(depender) orelse return).value.toOptional(); 763 764 while (opt_idx.unwrap()) |idx| { 765 const dep = ip.dep_entries.items[@backingInt(idx)]; 766 opt_idx = dep.next_dependee; 767 768 const prev_idx = dep.prev.unwrap() orelse { 769 // This entry is the start of a list in some `*_deps`. 770 // We cannot easily remove this mapping, so this must remain as a dummy entry. 771 ip.dep_entries.items[@backingInt(idx)].depender = .none; 772 continue; 773 }; 774 775 ip.dep_entries.items[@backingInt(prev_idx)].next = dep.next; 776 if (dep.next.unwrap()) |next_idx| { 777 ip.dep_entries.items[@backingInt(next_idx)].prev = dep.prev; 778 } 779 780 ip.free_dep_entries.append(gpa, idx) catch { 781 // This memory will be reclaimed on the next garbage collection. 782 // Thus, we do not need to propagate this error. 783 }; 784 } 785 } 786 787 pub const DependencyIterator = struct { 788 ip: *const InternPool, 789 next_entry: DepEntry.Index.Optional, 790 pub fn next(it: *DependencyIterator) ?AnalUnit { 791 while (true) { 792 const idx = it.next_entry.unwrap() orelse return null; 793 const entry = it.ip.dep_entries.items[@backingInt(idx)]; 794 it.next_entry = entry.next; 795 if (entry.depender.unwrap()) |depender| return depender; 796 } 797 } 798 }; 799 800 pub fn dependencyIterator(ip: *const InternPool, dependee: Dependee) DependencyIterator { 801 const first_entry = switch (dependee) { 802 .src_hash => |x| ip.src_hash_deps.get(x), 803 .nav_val => |x| ip.nav_val_deps.get(x), 804 .nav_ty => |x| ip.nav_ty_deps.get(x), 805 .func_ies => |x| ip.func_ies_deps.get(x), 806 .type_layout => |x| ip.type_layout_deps.get(x), 807 .struct_defaults => |x| ip.struct_defaults_deps.get(x), 808 .source_file => |x| ip.source_file_deps.get(x), 809 .embed_file => |x| ip.embed_file_deps.get(x), 810 .namespace => |x| ip.namespace_deps.get(x), 811 .namespace_name => |x| ip.namespace_name_deps.get(x), 812 .memoized_state => |stage| switch (stage) { 813 .main => ip.memoized_state_main_deps.unwrap(), 814 .panic => ip.memoized_state_panic_deps.unwrap(), 815 .va_list => ip.memoized_state_va_list_deps.unwrap(), 816 .assembly => ip.memoized_state_assembly_deps.unwrap(), 817 }, 818 } orelse return .{ 819 .ip = ip, 820 .next_entry = .none, 821 }; 822 return .{ 823 .ip = ip, 824 .next_entry = first_entry.toOptional(), 825 }; 826 } 827 828 pub fn addDependency(ip: *InternPool, gpa: Allocator, depender: AnalUnit, dependee: Dependee) Allocator.Error!void { 829 const first_depender_dep: DepEntry.Index.Optional = if (ip.first_dependency.get(depender)) |idx| dep: { 830 // The entry already exists, so there is capacity to overwrite it later. 831 break :dep idx.toOptional(); 832 } else none: { 833 // Ensure there is capacity available to add this dependency later. 834 try ip.first_dependency.ensureUnusedCapacity(gpa, 1); 835 break :none .none; 836 }; 837 838 // We're very likely to need space for a new entry - reserve it now to avoid 839 // the need for error cleanup logic. 840 if (ip.free_dep_entries.items.len == 0) { 841 try ip.dep_entries.ensureUnusedCapacity(gpa, 1); 842 } 843 844 // This block should allocate an entry and prepend it to the relevant `*_deps` list. 845 // The `next` field should be correctly initialized; all other fields may be undefined. 846 const new_index: DepEntry.Index = switch (dependee) { 847 .memoized_state => |stage| new_index: { 848 const deps = switch (stage) { 849 .main => &ip.memoized_state_main_deps, 850 .panic => &ip.memoized_state_panic_deps, 851 .va_list => &ip.memoized_state_va_list_deps, 852 .assembly => &ip.memoized_state_assembly_deps, 853 }; 854 855 if (deps.unwrap()) |first| { 856 if (ip.dep_entries.items[@backingInt(first)].depender == .none) { 857 // Dummy entry, so we can reuse it rather than allocating a new one! 858 break :new_index first; 859 } 860 } 861 862 // Prepend a new dependency. 863 const new_index: DepEntry.Index, const ptr = if (ip.free_dep_entries.pop()) |new_index| new: { 864 break :new .{ new_index, &ip.dep_entries.items[@backingInt(new_index)] }; 865 } else .{ @fromBackingInt(@intCast(ip.dep_entries.items.len)), ip.dep_entries.addOneAssumeCapacity() }; 866 if (deps.unwrap()) |old_first| { 867 ptr.next = old_first.toOptional(); 868 ip.dep_entries.items[@backingInt(old_first)].prev = new_index.toOptional(); 869 } else { 870 ptr.next = .none; 871 } 872 deps.* = new_index.toOptional(); 873 break :new_index new_index; 874 }, 875 inline else => |dependee_payload, tag| new_index: { 876 const gop = try switch (tag) { 877 .src_hash => ip.src_hash_deps, 878 .nav_val => ip.nav_val_deps, 879 .nav_ty => ip.nav_ty_deps, 880 .func_ies => ip.func_ies_deps, 881 .type_layout => ip.type_layout_deps, 882 .struct_defaults => ip.struct_defaults_deps, 883 .source_file => ip.source_file_deps, 884 .embed_file => ip.embed_file_deps, 885 .namespace => ip.namespace_deps, 886 .namespace_name => ip.namespace_name_deps, 887 .memoized_state => comptime unreachable, 888 }.getOrPut(gpa, dependee_payload); 889 890 if (gop.found_existing and ip.dep_entries.items[@backingInt(gop.value_ptr.*)].depender == .none) { 891 // Dummy entry, so we can reuse it rather than allocating a new one! 892 break :new_index gop.value_ptr.*; 893 } 894 895 // Prepend a new dependency. 896 const new_index: DepEntry.Index, const ptr = if (ip.free_dep_entries.pop()) |new_index| new: { 897 break :new .{ new_index, &ip.dep_entries.items[@backingInt(new_index)] }; 898 } else .{ @fromBackingInt(@intCast(ip.dep_entries.items.len)), ip.dep_entries.addOneAssumeCapacity() }; 899 if (gop.found_existing) { 900 ptr.next = gop.value_ptr.*.toOptional(); 901 ip.dep_entries.items[@backingInt(gop.value_ptr.*)].prev = new_index.toOptional(); 902 } else { 903 ptr.next = .none; 904 } 905 gop.value_ptr.* = new_index; 906 break :new_index new_index; 907 }, 908 }; 909 910 ip.dep_entries.items[@backingInt(new_index)].depender = depender.toOptional(); 911 ip.dep_entries.items[@backingInt(new_index)].prev = .none; 912 ip.dep_entries.items[@backingInt(new_index)].next_dependee = first_depender_dep; 913 ip.first_dependency.putAssumeCapacity(depender, new_index); 914 } 915 916 /// String is the name whose existence the dependency is on. 917 /// DepEntry.Index refers to the first such dependency. 918 pub const NamespaceNameKey = struct { 919 /// The instruction (`struct_decl` etc) which owns the namespace in question. 920 namespace: TrackedInst.Index, 921 /// The name whose existence the dependency is on. 922 name: NullTerminatedString, 923 }; 924 925 pub const DepEntry = extern struct { 926 /// If null, this is a dummy entry. `next_dependee` is undefined. This is the first 927 /// entry in one of `*_deps`, and does not appear in any list by `first_dependency`, 928 /// but is not in `free_dep_entries` since `*_deps` stores a reference to it. 929 depender: AnalUnit.Optional, 930 /// Index into `dep_entries` forming a doubly linked list of all dependencies on this dependee. 931 /// Used to iterate all dependers for a given dependee during an update. 932 /// null if this is the end of the list. 933 next: DepEntry.Index.Optional, 934 /// The other link for `next`. 935 /// null if this is the start of the list. 936 prev: DepEntry.Index.Optional, 937 /// Index into `dep_entries` forming a singly linked list of dependencies *of* `depender`. 938 /// Used to efficiently remove all `DepEntry`s for a single `depender` when it is re-analyzed. 939 /// null if this is the end of the list. 940 next_dependee: DepEntry.Index.Optional, 941 942 pub const Index = enum(u32) { 943 _, 944 pub fn toOptional(dep: DepEntry.Index) Optional { 945 return @fromBackingInt(@intCast(@backingInt(dep))); 946 } 947 pub const Optional = enum(u32) { 948 none = std.math.maxInt(u32), 949 _, 950 pub fn unwrap(opt: Optional) ?DepEntry.Index { 951 return switch (opt) { 952 .none => null, 953 _ => @fromBackingInt(@intCast(@backingInt(opt))), 954 }; 955 } 956 }; 957 }; 958 }; 959 960 const Local = struct { 961 /// These fields can be accessed from any thread by calling `acquire`. 962 /// They are only modified by the owning thread. 963 shared: Shared align(std.atomic.cache_line), 964 /// This state is fully local to the owning thread and does not require any 965 /// atomic access. 966 mutate: struct { 967 /// When we need to allocate any long-lived buffer for mutating the `InternPool`, it is 968 /// allocated into this `arena` (for the `Id` of the thread performing the mutation). An 969 /// arena is used to avoid contention on the GPA, and to ensure that any code which retains 970 /// references to old state remains valid. For instance, when reallocing hashmap metadata, 971 /// a racing lookup on another thread may still retain a handle to the old metadata pointer, 972 /// so it must remain valid. 973 /// This arena's lifetime is tied to that of `Compilation`, although it can be cleared on 974 /// garbage collection (currently vaporware). 975 arena: std.heap.ArenaAllocator.State, 976 977 items: ListMutate, 978 extra: ListMutate, 979 limbs: ListMutate, 980 strings: ListMutate, 981 string_bytes: ListMutate, 982 tracked_insts: ListMutate, 983 files: ListMutate, 984 maps: ListMutate, 985 navs: ListMutate, 986 comptime_units: ListMutate, 987 988 namespaces: BucketListMutate, 989 } align(std.atomic.cache_line), 990 991 const Shared = struct { 992 items: List(Item), 993 extra: Extra, 994 limbs: Limbs, 995 strings: Strings, 996 string_bytes: StringBytes, 997 tracked_insts: TrackedInsts, 998 files: List(File), 999 maps: Maps, 1000 navs: Navs, 1001 comptime_units: ComptimeUnits, 1002 1003 namespaces: Namespaces, 1004 1005 pub fn getLimbs(shared: *const Local.Shared) Limbs { 1006 return switch (@sizeOf(Limb)) { 1007 @sizeOf(u32) => shared.extra, 1008 @sizeOf(u64) => shared.limbs, 1009 else => @compileError("unsupported host"), 1010 }.acquire(); 1011 } 1012 }; 1013 1014 const Extra = List(struct { u32 }); 1015 const Limbs = switch (@sizeOf(Limb)) { 1016 @sizeOf(u32) => Extra, 1017 @sizeOf(u64) => List(struct { u64 }), 1018 else => @compileError("unsupported host"), 1019 }; 1020 const Strings = List(struct { u32 }); 1021 const StringBytes = List(struct { u8 }); 1022 const TrackedInsts = List(struct { TrackedInst.MaybeLost }); 1023 const Maps = List(struct { FieldMap }); 1024 const Navs = List(Nav.Repr); 1025 const ComptimeUnits = List(struct { ComptimeUnit }); 1026 1027 const namespaces_bucket_width = 8; 1028 const namespaces_bucket_mask = (1 << namespaces_bucket_width) - 1; 1029 const namespace_next_free_field = "owner_type"; 1030 const Namespaces = List(struct { *[1 << namespaces_bucket_width]Zcu.Namespace }); 1031 1032 const ListMutate = struct { 1033 mutex: Io.Mutex, 1034 len: u32, 1035 1036 const empty: ListMutate = .{ 1037 .mutex = .init, 1038 .len = 0, 1039 }; 1040 }; 1041 1042 const BucketListMutate = struct { 1043 last_bucket_len: u32, 1044 buckets_list: ListMutate, 1045 free_list: u32, 1046 1047 const free_list_sentinel = std.math.maxInt(u32); 1048 1049 const empty: BucketListMutate = .{ 1050 .last_bucket_len = 0, 1051 .buckets_list = ListMutate.empty, 1052 .free_list = free_list_sentinel, 1053 }; 1054 }; 1055 1056 fn List(comptime Elem: type) type { 1057 assert(@typeInfo(Elem) == .@"struct"); 1058 return struct { 1059 bytes: [*]align(@alignOf(Elem)) u8, 1060 1061 const ListSelf = @This(); 1062 const Mutable = struct { 1063 gpa: Allocator, 1064 io: Io, 1065 arena: *std.heap.ArenaAllocator.State, 1066 mutate: *ListMutate, 1067 list: *ListSelf, 1068 1069 const fields = std.enums.values(std.meta.FieldEnum(Elem)); 1070 1071 fn PtrArrayElem(comptime len: usize) type { 1072 const elem_info = @typeInfo(Elem).@"struct"; 1073 1074 var new_types: [elem_info.field_types.len]type = undefined; 1075 for (&new_types, elem_info.field_types) |*NewType, elem_field_type| { 1076 NewType.* = *[len]elem_field_type; 1077 } 1078 if (elem_info.is_tuple) { 1079 return @Tuple(&new_types); 1080 } else { 1081 return @Struct(.auto, null, elem_info.field_names, &new_types, &@splat(.{})); 1082 } 1083 } 1084 fn PtrElem(comptime opts: struct { 1085 size: std.lang.Type.Pointer.Size, 1086 is_const: bool = false, 1087 }) type { 1088 const elem_info = @typeInfo(Elem).@"struct"; 1089 var new_types: [elem_info.field_types.len]type = undefined; 1090 for (&new_types, elem_info.field_types) |*NewType, elem_field_type| { 1091 NewType.* = @Pointer(opts.size, .{ .@"const" = opts.is_const }, elem_field_type, null); 1092 } 1093 if (elem_info.is_tuple) { 1094 return @Tuple(&new_types); 1095 } else { 1096 return @Struct(.auto, null, elem_info.field_names, &new_types, &@splat(.{})); 1097 } 1098 } 1099 1100 pub fn addOne(mutable: Mutable) Allocator.Error!PtrElem(.{ .size = .one }) { 1101 try mutable.ensureUnusedCapacity(1); 1102 return mutable.addOneAssumeCapacity(); 1103 } 1104 1105 pub fn addOneAssumeCapacity(mutable: Mutable) PtrElem(.{ .size = .one }) { 1106 const index = mutable.mutate.len; 1107 assert(index < mutable.list.header().capacity); 1108 mutable.mutate.len = index + 1; 1109 const mutable_view = mutable.view().slice(); 1110 var ptr: PtrElem(.{ .size = .one }) = undefined; 1111 inline for (fields) |field| { 1112 @field(ptr, @tagName(field)) = &mutable_view.items(field)[index]; 1113 } 1114 return ptr; 1115 } 1116 1117 pub fn append(mutable: Mutable, elem: Elem) Allocator.Error!void { 1118 try mutable.ensureUnusedCapacity(1); 1119 mutable.appendAssumeCapacity(elem); 1120 } 1121 1122 pub fn appendAssumeCapacity(mutable: Mutable, elem: Elem) void { 1123 var mutable_view = mutable.view(); 1124 defer mutable.mutate.len = @intCast(mutable_view.len); 1125 mutable_view.appendAssumeCapacity(elem); 1126 } 1127 1128 pub fn appendSliceAssumeCapacity( 1129 mutable: Mutable, 1130 slice: PtrElem(.{ .size = .slice, .is_const = true }), 1131 ) void { 1132 if (fields.len == 0) return; 1133 const start = mutable.mutate.len; 1134 const slice_len = @field(slice, @tagName(fields[0])).len; 1135 assert(slice_len <= mutable.list.header().capacity - start); 1136 mutable.mutate.len = @intCast(start + slice_len); 1137 const mutable_view = mutable.view().slice(); 1138 inline for (fields) |field| { 1139 const field_slice = @field(slice, @tagName(field)); 1140 assert(field_slice.len == slice_len); 1141 @memcpy(mutable_view.items(field)[start..][0..slice_len], field_slice); 1142 } 1143 } 1144 1145 pub fn appendNTimes(mutable: Mutable, elem: Elem, len: usize) Allocator.Error!void { 1146 try mutable.ensureUnusedCapacity(len); 1147 mutable.appendNTimesAssumeCapacity(elem, len); 1148 } 1149 1150 pub fn appendNTimesAssumeCapacity(mutable: Mutable, elem: Elem, len: usize) void { 1151 const start = mutable.mutate.len; 1152 assert(len <= mutable.list.header().capacity - start); 1153 mutable.mutate.len = @intCast(start + len); 1154 const mutable_view = mutable.view().slice(); 1155 inline for (fields) |field| { 1156 @memset(mutable_view.items(field)[start..][0..len], @field(elem, @tagName(field))); 1157 } 1158 } 1159 1160 pub fn addManyAsArray(mutable: Mutable, comptime len: usize) Allocator.Error!PtrArrayElem(len) { 1161 try mutable.ensureUnusedCapacity(len); 1162 return mutable.addManyAsArrayAssumeCapacity(len); 1163 } 1164 1165 pub fn addManyAsArrayAssumeCapacity(mutable: Mutable, comptime len: usize) PtrArrayElem(len) { 1166 const start = mutable.mutate.len; 1167 assert(len <= mutable.list.header().capacity - start); 1168 mutable.mutate.len = @intCast(start + len); 1169 const mutable_view = mutable.view().slice(); 1170 var ptr_array: PtrArrayElem(len) = undefined; 1171 inline for (fields) |field| { 1172 @field(ptr_array, @tagName(field)) = mutable_view.items(field)[start..][0..len]; 1173 } 1174 return ptr_array; 1175 } 1176 1177 pub fn addManyAsSlice(mutable: Mutable, len: usize) Allocator.Error!PtrElem(.{ .size = .slice }) { 1178 try mutable.ensureUnusedCapacity(len); 1179 return mutable.addManyAsSliceAssumeCapacity(len); 1180 } 1181 1182 pub fn addManyAsSliceAssumeCapacity(mutable: Mutable, len: usize) PtrElem(.{ .size = .slice }) { 1183 const start = mutable.mutate.len; 1184 assert(len <= mutable.list.header().capacity - start); 1185 mutable.mutate.len = @intCast(start + len); 1186 const mutable_view = mutable.view().slice(); 1187 var slice: PtrElem(.{ .size = .slice }) = undefined; 1188 inline for (fields) |field| { 1189 @field(slice, @tagName(field)) = mutable_view.items(field)[start..][0..len]; 1190 } 1191 return slice; 1192 } 1193 1194 pub fn shrinkRetainingCapacity(mutable: Mutable, len: usize) void { 1195 assert(len <= mutable.mutate.len); 1196 mutable.mutate.len = @intCast(len); 1197 } 1198 1199 pub fn ensureUnusedCapacity(mutable: Mutable, unused_capacity: usize) Allocator.Error!void { 1200 try mutable.ensureTotalCapacity(@intCast(mutable.mutate.len + unused_capacity)); 1201 } 1202 1203 pub fn ensureTotalCapacity(mutable: Mutable, total_capacity: usize) Allocator.Error!void { 1204 const old_capacity = mutable.list.header().capacity; 1205 if (old_capacity >= total_capacity) return; 1206 var new_capacity = old_capacity; 1207 while (new_capacity < total_capacity) new_capacity = (new_capacity + 10) * 2; 1208 try mutable.setCapacity(new_capacity); 1209 } 1210 1211 fn setCapacity(mutable: Mutable, capacity: u32) Allocator.Error!void { 1212 const io = mutable.io; 1213 var arena = mutable.arena.promote(mutable.gpa); 1214 defer mutable.arena.* = arena.state; 1215 const buf = try arena.allocator().alignedAlloc( 1216 u8, 1217 .fromByteUnits(alignment), 1218 bytes_offset + View.capacityInBytes(capacity), 1219 ); 1220 var new_list: ListSelf = .{ .bytes = @ptrCast(buf[bytes_offset..].ptr) }; 1221 new_list.header().* = .{ .capacity = capacity }; 1222 const len = mutable.mutate.len; 1223 // this cold, quickly predictable, condition enables 1224 // the `MultiArrayList` optimization in `view` 1225 if (len > 0) { 1226 const old_slice = mutable.list.view().slice(); 1227 const new_slice = new_list.view().slice(); 1228 inline for (fields) |field| @memcpy(new_slice.items(field)[0..len], old_slice.items(field)[0..len]); 1229 } 1230 mutable.mutate.mutex.lockUncancelable(io); 1231 defer mutable.mutate.mutex.unlock(io); 1232 mutable.list.release(new_list); 1233 } 1234 1235 pub fn viewAllowEmpty(mutable: Mutable) View { 1236 const capacity = mutable.list.header().capacity; 1237 return .{ 1238 .bytes = mutable.list.bytes, 1239 .len = mutable.mutate.len, 1240 .capacity = capacity, 1241 }; 1242 } 1243 pub fn view(mutable: Mutable) View { 1244 const capacity = mutable.list.header().capacity; 1245 assert(capacity > 0); // optimizes `MultiArrayList.Slice.items` 1246 return .{ 1247 .bytes = mutable.list.bytes, 1248 .len = mutable.mutate.len, 1249 .capacity = capacity, 1250 }; 1251 } 1252 }; 1253 1254 const empty: ListSelf = .{ .bytes = @constCast(&(extern struct { 1255 header: Header, 1256 bytes: [0]u8 align(@alignOf(Elem)), 1257 }{ 1258 .header = .{ .capacity = 0 }, 1259 .bytes = .{}, 1260 }).bytes) }; 1261 1262 const alignment = @max(@alignOf(Header), @alignOf(Elem)); 1263 const bytes_offset = std.mem.alignForward(usize, @sizeOf(Header), @alignOf(Elem)); 1264 const View = std.MultiArrayList(Elem); 1265 1266 /// Must be called when accessing from another thread. 1267 pub fn acquire(list: *const ListSelf) ListSelf { 1268 return .{ .bytes = @atomicLoad([*]align(@alignOf(Elem)) u8, &list.bytes, .acquire) }; 1269 } 1270 fn release(list: *ListSelf, new_list: ListSelf) void { 1271 @atomicStore([*]align(@alignOf(Elem)) u8, &list.bytes, new_list.bytes, .release); 1272 } 1273 1274 const Header = extern struct { 1275 capacity: u32, 1276 }; 1277 fn header(list: ListSelf) *Header { 1278 return @ptrCast(@alignCast(list.bytes - bytes_offset)); 1279 } 1280 pub fn view(list: ListSelf) View { 1281 const capacity = list.header().capacity; 1282 assert(capacity > 0); // optimizes `MultiArrayList.Slice.items` 1283 return .{ 1284 .bytes = list.bytes, 1285 .len = capacity, 1286 .capacity = capacity, 1287 }; 1288 } 1289 }; 1290 } 1291 1292 pub fn getMutableItems(local: *Local, gpa: Allocator, io: Io) List(Item).Mutable { 1293 return .{ 1294 .gpa = gpa, 1295 .io = io, 1296 .arena = &local.mutate.arena, 1297 .mutate = &local.mutate.items, 1298 .list = &local.shared.items, 1299 }; 1300 } 1301 1302 pub fn getMutableExtra(local: *Local, gpa: Allocator, io: Io) Extra.Mutable { 1303 return .{ 1304 .gpa = gpa, 1305 .io = io, 1306 .arena = &local.mutate.arena, 1307 .mutate = &local.mutate.extra, 1308 .list = &local.shared.extra, 1309 }; 1310 } 1311 1312 /// On 32-bit systems, this array is ignored and extra is used for everything. 1313 /// On 64-bit systems, this array is used for big integers and associated metadata. 1314 /// Use the helper methods instead of accessing this directly in order to not 1315 /// violate the above mechanism. 1316 pub fn getMutableLimbs(local: *Local, gpa: Allocator, io: Io) Limbs.Mutable { 1317 return switch (@sizeOf(Limb)) { 1318 @sizeOf(u32) => local.getMutableExtra(gpa, io), 1319 @sizeOf(u64) => .{ 1320 .gpa = gpa, 1321 .io = io, 1322 .arena = &local.mutate.arena, 1323 .mutate = &local.mutate.limbs, 1324 .list = &local.shared.limbs, 1325 }, 1326 else => @compileError("unsupported host"), 1327 }; 1328 } 1329 1330 /// A list of offsets into `string_bytes` for each string. 1331 pub fn getMutableStrings(local: *Local, gpa: Allocator, io: Io) Strings.Mutable { 1332 return .{ 1333 .gpa = gpa, 1334 .io = io, 1335 .arena = &local.mutate.arena, 1336 .mutate = &local.mutate.strings, 1337 .list = &local.shared.strings, 1338 }; 1339 } 1340 1341 /// In order to store references to strings in fewer bytes, we copy all 1342 /// string bytes into here. String bytes can be null. It is up to whomever 1343 /// is referencing the data here whether they want to store both index and length, 1344 /// thus allowing null bytes, or store only index, and use null-termination. The 1345 /// `strings_bytes` array is agnostic to either usage. 1346 pub fn getMutableStringBytes(local: *Local, gpa: Allocator, io: Io) StringBytes.Mutable { 1347 return .{ 1348 .gpa = gpa, 1349 .io = io, 1350 .arena = &local.mutate.arena, 1351 .mutate = &local.mutate.string_bytes, 1352 .list = &local.shared.string_bytes, 1353 }; 1354 } 1355 1356 /// An index into `tracked_insts` gives a reference to a single ZIR instruction which 1357 /// persists across incremental updates. 1358 pub fn getMutableTrackedInsts(local: *Local, gpa: Allocator, io: Io) TrackedInsts.Mutable { 1359 return .{ 1360 .gpa = gpa, 1361 .io = io, 1362 .arena = &local.mutate.arena, 1363 .mutate = &local.mutate.tracked_insts, 1364 .list = &local.shared.tracked_insts, 1365 }; 1366 } 1367 1368 /// Elements are ordered identically to the `import_table` field of `Zcu`. 1369 /// 1370 /// Unlike `import_table`, this data is serialized as part of incremental 1371 /// compilation state. 1372 /// 1373 /// Key is the hash of the path to this file, used to store 1374 /// `InternPool.TrackedInst`. 1375 pub fn getMutableFiles(local: *Local, gpa: Allocator, io: Io) List(File).Mutable { 1376 return .{ 1377 .gpa = gpa, 1378 .io = io, 1379 .arena = &local.mutate.arena, 1380 .mutate = &local.mutate.files, 1381 .list = &local.shared.files, 1382 }; 1383 } 1384 1385 /// Some types such as enums, structs, and unions need to store mappings from field names 1386 /// to field index, or value to field index. In such cases, they will store the underlying 1387 /// field names and values directly, relying on one of these maps, stored separately, 1388 /// to provide lookup. 1389 /// These are not serialized; it is computed upon deserialization. 1390 pub fn getMutableMaps(local: *Local, gpa: Allocator, io: Io) Maps.Mutable { 1391 return .{ 1392 .gpa = gpa, 1393 .io = io, 1394 .arena = &local.mutate.arena, 1395 .mutate = &local.mutate.maps, 1396 .list = &local.shared.maps, 1397 }; 1398 } 1399 1400 pub fn getMutableNavs(local: *Local, gpa: Allocator, io: Io) Navs.Mutable { 1401 return .{ 1402 .gpa = gpa, 1403 .io = io, 1404 .arena = &local.mutate.arena, 1405 .mutate = &local.mutate.navs, 1406 .list = &local.shared.navs, 1407 }; 1408 } 1409 1410 pub fn getMutableComptimeUnits(local: *Local, gpa: Allocator, io: Io) ComptimeUnits.Mutable { 1411 return .{ 1412 .gpa = gpa, 1413 .io = io, 1414 .arena = &local.mutate.arena, 1415 .mutate = &local.mutate.comptime_units, 1416 .list = &local.shared.comptime_units, 1417 }; 1418 } 1419 1420 /// Rather than allocating Namespace objects with an Allocator, we instead allocate 1421 /// them with this BucketList. This provides four advantages: 1422 /// * Stable memory so that one thread can access a Namespace object while another 1423 /// thread allocates additional Namespace objects from this list. 1424 /// * It allows us to use u32 indexes to reference Namespace objects rather than 1425 /// pointers, saving memory in types. 1426 /// * Using integers to reference Namespace objects rather than pointers makes 1427 /// serialization trivial. 1428 /// * It provides a unique integer to be used for anonymous symbol names, avoiding 1429 /// multi-threaded contention on an atomic counter. 1430 pub fn getMutableNamespaces(local: *Local, gpa: Allocator, io: Io) Namespaces.Mutable { 1431 return .{ 1432 .gpa = gpa, 1433 .io = io, 1434 .arena = &local.mutate.arena, 1435 .mutate = &local.mutate.namespaces.buckets_list, 1436 .list = &local.shared.namespaces, 1437 }; 1438 } 1439 }; 1440 1441 pub fn getLocal(ip: *InternPool, tid: Zcu.PerThread.Id) *Local { 1442 return &ip.locals[@backingInt(tid)]; 1443 } 1444 1445 pub fn getLocalShared(ip: *const InternPool, tid: Zcu.PerThread.Id) *const Local.Shared { 1446 return &ip.locals[@backingInt(tid)].shared; 1447 } 1448 1449 const Shard = struct { 1450 shared: struct { 1451 map: Map(Index), 1452 string_map: Map(OptionalNullTerminatedString), 1453 tracked_inst_map: Map(TrackedInst.Index.Optional), 1454 } align(std.atomic.cache_line), 1455 mutate: struct { 1456 // TODO: measure cost of sharing unrelated mutate state 1457 map: Mutate align(std.atomic.cache_line), 1458 string_map: Mutate align(std.atomic.cache_line), 1459 tracked_inst_map: Mutate align(std.atomic.cache_line), 1460 }, 1461 1462 const Mutate = struct { 1463 /// This mutex needs to be recursive because `getFuncDeclIes` interns multiple things at 1464 /// once (the function, its IES, the corresponding error union, and the resulting function 1465 /// type), so calls `getOrPutKeyEnsuringAdditionalCapacity` multiple times. Each of these 1466 /// calls acquires a lock which will only be released when the whole operation is finalized, 1467 /// and these different items could be in the same shard, in which case that shard's lock 1468 /// will be acquired multiple times. 1469 mutex: RecursiveMutex, 1470 len: u32, 1471 1472 const RecursiveMutex = struct { 1473 const OptionalTid = if (single_threaded) enum(u8) { 1474 null, 1475 main, 1476 fn unwrap(ot: OptionalTid) ?Zcu.PerThread.Id { 1477 return switch (ot) { 1478 .null => null, 1479 .main => .main, 1480 }; 1481 } 1482 fn wrap(tid: Zcu.PerThread.Id) OptionalTid { 1483 comptime assert(tid == .main); 1484 return .main; 1485 } 1486 } else packed struct(u8) { 1487 non_null: bool, 1488 value: Zcu.PerThread.Id, 1489 const @"null": OptionalTid = .{ .non_null = false, .value = .main }; 1490 fn unwrap(ot: OptionalTid) ?Zcu.PerThread.Id { 1491 return if (ot.non_null) ot.value else null; 1492 } 1493 fn wrap(tid: Zcu.PerThread.Id) OptionalTid { 1494 return .{ .non_null = true, .value = tid }; 1495 } 1496 }; 1497 mutex: Io.Mutex, 1498 tid: std.atomic.Value(OptionalTid), 1499 lock_count: u32, 1500 const init: RecursiveMutex = .{ .mutex = .init, .tid = .init(.null), .lock_count = 0 }; 1501 fn lock(r: *RecursiveMutex, io: Io, tid: Zcu.PerThread.Id) void { 1502 if (r.tid.load(.monotonic) != OptionalTid.wrap(tid)) { 1503 r.mutex.lockUncancelable(io); 1504 assert(r.lock_count == 0); 1505 r.tid.store(.wrap(tid), .monotonic); 1506 } 1507 r.lock_count += 1; 1508 } 1509 fn unlock(r: *RecursiveMutex, io: Io) void { 1510 r.lock_count -= 1; 1511 if (r.lock_count == 0) { 1512 r.tid.store(.null, .monotonic); 1513 r.mutex.unlock(io); 1514 } 1515 } 1516 }; 1517 1518 const empty: Mutate = .{ 1519 .mutex = .init, 1520 .len = 0, 1521 }; 1522 }; 1523 1524 fn Map(comptime Value: type) type { 1525 comptime assert(@typeInfo(Value).@"enum".tag_type == u32); 1526 _ = @as(Value, .none); // expected .none key 1527 return struct { 1528 /// header: Header, 1529 /// entries: [header.capacity]Entry, 1530 entries: [*]Entry, 1531 1532 const empty: @This() = .{ .entries = @constCast(&(extern struct { 1533 header: Header, 1534 entries: [1]Entry, 1535 }{ 1536 .header = .{ .capacity = 1 }, 1537 .entries = .{.{ .value = .none, .hash = undefined }}, 1538 }).entries) }; 1539 1540 const alignment = @max(@alignOf(Header), @alignOf(Entry)); 1541 const entries_offset = std.mem.alignForward(usize, @sizeOf(Header), @alignOf(Entry)); 1542 1543 /// Must be called unless the mutate mutex is locked. 1544 fn acquire(map: *const @This()) @This() { 1545 return .{ .entries = @atomicLoad([*]Entry, &map.entries, .acquire) }; 1546 } 1547 fn release(map: *@This(), new_map: @This()) void { 1548 @atomicStore([*]Entry, &map.entries, new_map.entries, .release); 1549 } 1550 1551 const Header = extern struct { 1552 capacity: u32, 1553 1554 fn mask(head: *const Header) u32 { 1555 assert(std.math.isPowerOfTwo(head.capacity)); 1556 return head.capacity - 1; 1557 } 1558 }; 1559 fn header(map: @This()) *Header { 1560 return @ptrCast(@alignCast(@as([*]u8, @ptrCast(map.entries)) - entries_offset)); 1561 } 1562 1563 const Entry = extern struct { 1564 value: Value, 1565 hash: u32, 1566 1567 fn acquire(entry: *const Entry) Value { 1568 return @atomicLoad(Value, &entry.value, .acquire); 1569 } 1570 fn release(entry: *Entry, value: Value) void { 1571 assert(value != .none); 1572 @atomicStore(Value, &entry.value, value, .release); 1573 } 1574 fn resetUnordered(entry: *Entry) void { 1575 @atomicStore(Value, &entry.value, .none, .unordered); 1576 } 1577 }; 1578 }; 1579 } 1580 }; 1581 1582 fn getTidMask(ip: *const InternPool) u32 { 1583 return @shlExact(@as(u32, 1), ip.tid_width) - 1; 1584 } 1585 1586 fn getIndexMask(ip: *const InternPool, comptime BackingInt: type) u32 { 1587 return @as(u32, std.math.maxInt(BackingInt)) >> ip.tid_width; 1588 } 1589 1590 const FieldMap = std.array_hash_map.Custom(void, void, std.array_hash_map.AutoContext(void), false); 1591 1592 /// An index into `maps` which might be `none`. 1593 pub const OptionalMapIndex = enum(u32) { 1594 none = std.math.maxInt(u32), 1595 _, 1596 1597 pub fn unwrap(oi: OptionalMapIndex) ?MapIndex { 1598 if (oi == .none) return null; 1599 return @fromBackingInt(@intCast(@backingInt(oi))); 1600 } 1601 }; 1602 1603 /// An index into `maps`. 1604 pub const MapIndex = enum(u32) { 1605 _, 1606 1607 pub fn get(map_index: MapIndex, ip: *const InternPool) *FieldMap { 1608 const unwrapped_map_index = map_index.unwrap(ip); 1609 const maps = ip.getLocalShared(unwrapped_map_index.tid).maps.acquire(); 1610 return &maps.view().items(.@"0")[unwrapped_map_index.index]; 1611 } 1612 1613 pub fn toOptional(i: MapIndex) OptionalMapIndex { 1614 return @fromBackingInt(@intCast(@backingInt(i))); 1615 } 1616 1617 const Unwrapped = struct { 1618 tid: Zcu.PerThread.Id, 1619 index: u32, 1620 1621 fn wrap(unwrapped: Unwrapped, ip: *const InternPool) MapIndex { 1622 assert(@backingInt(unwrapped.tid) <= ip.getTidMask()); 1623 assert(unwrapped.index <= ip.getIndexMask(u32)); 1624 return @fromBackingInt(@intCast(@shlExact(@as(u32, @backingInt(unwrapped.tid)), ip.tid_shift_32) | 1625 unwrapped.index)); 1626 } 1627 }; 1628 fn unwrap(map_index: MapIndex, ip: *const InternPool) Unwrapped { 1629 return .{ 1630 .tid = @fromBackingInt(@intCast(@backingInt(map_index) >> ip.tid_shift_32 & ip.getTidMask())), 1631 .index = @backingInt(map_index) & ip.getIndexMask(u32), 1632 }; 1633 } 1634 }; 1635 1636 pub const ComptimeAllocIndex = enum(u32) { _ }; 1637 1638 pub const NamespaceIndex = enum(u32) { 1639 _, 1640 1641 const Unwrapped = struct { 1642 tid: Zcu.PerThread.Id, 1643 bucket_index: u32, 1644 index: u32, 1645 1646 fn wrap(unwrapped: Unwrapped, ip: *const InternPool) NamespaceIndex { 1647 assert(@backingInt(unwrapped.tid) <= ip.getTidMask()); 1648 assert(unwrapped.bucket_index <= ip.getIndexMask(u32) >> Local.namespaces_bucket_width); 1649 assert(unwrapped.index <= Local.namespaces_bucket_mask); 1650 return @fromBackingInt(@intCast(@shlExact(@as(u32, @backingInt(unwrapped.tid)), ip.tid_shift_32) | 1651 unwrapped.bucket_index << Local.namespaces_bucket_width | 1652 unwrapped.index)); 1653 } 1654 }; 1655 fn unwrap(namespace_index: NamespaceIndex, ip: *const InternPool) Unwrapped { 1656 const index = @backingInt(namespace_index) & ip.getIndexMask(u32); 1657 return .{ 1658 .tid = @fromBackingInt(@intCast(@backingInt(namespace_index) >> ip.tid_shift_32 & ip.getTidMask())), 1659 .bucket_index = index >> Local.namespaces_bucket_width, 1660 .index = index & Local.namespaces_bucket_mask, 1661 }; 1662 } 1663 1664 pub fn toOptional(i: NamespaceIndex) OptionalNamespaceIndex { 1665 return @fromBackingInt(@intCast(@backingInt(i))); 1666 } 1667 }; 1668 1669 pub const OptionalNamespaceIndex = enum(u32) { 1670 none = std.math.maxInt(u32), 1671 _, 1672 1673 pub fn init(oi: ?NamespaceIndex) OptionalNamespaceIndex { 1674 return @fromBackingInt(@intCast(@backingInt(oi orelse return .none))); 1675 } 1676 1677 pub fn unwrap(oi: OptionalNamespaceIndex) ?NamespaceIndex { 1678 if (oi == .none) return null; 1679 return @fromBackingInt(@intCast(@backingInt(oi))); 1680 } 1681 }; 1682 1683 pub const FileIndex = enum(u32) { 1684 _, 1685 1686 const Unwrapped = struct { 1687 tid: Zcu.PerThread.Id, 1688 index: u32, 1689 1690 fn wrap(unwrapped: Unwrapped, ip: *const InternPool) FileIndex { 1691 assert(@backingInt(unwrapped.tid) <= ip.getTidMask()); 1692 assert(unwrapped.index <= ip.getIndexMask(u32)); 1693 return @fromBackingInt(@intCast(@shlExact(@as(u32, @backingInt(unwrapped.tid)), ip.tid_shift_32) | 1694 unwrapped.index)); 1695 } 1696 }; 1697 pub fn unwrap(file_index: FileIndex, ip: *const InternPool) Unwrapped { 1698 return .{ 1699 .tid = @fromBackingInt(@intCast(@backingInt(file_index) >> ip.tid_shift_32 & ip.getTidMask())), 1700 .index = @backingInt(file_index) & ip.getIndexMask(u32), 1701 }; 1702 } 1703 pub fn toOptional(i: FileIndex) Optional { 1704 return @fromBackingInt(@intCast(@backingInt(i))); 1705 } 1706 pub const Optional = enum(u32) { 1707 none = std.math.maxInt(u32), 1708 _, 1709 pub fn unwrap(opt: Optional) ?FileIndex { 1710 return switch (opt) { 1711 .none => null, 1712 _ => @fromBackingInt(@intCast(@backingInt(opt))), 1713 }; 1714 } 1715 }; 1716 }; 1717 1718 const File = struct { 1719 bin_digest: Cache.BinDigest, 1720 file: *Zcu.File, 1721 /// `.none` means no type has been created yet. 1722 root_type: InternPool.Index, 1723 }; 1724 1725 /// An index into `strings`. 1726 pub const String = enum(u32) { 1727 /// An empty string. 1728 empty = 0, 1729 _, 1730 1731 pub fn toSlice(string: String, len: u64, ip: *const InternPool) []const u8 { 1732 return string.toOverlongSlice(ip)[0..@intCast(len)]; 1733 } 1734 1735 pub fn at(string: String, index: u64, ip: *const InternPool) u8 { 1736 return string.toOverlongSlice(ip)[@intCast(index)]; 1737 } 1738 1739 pub fn toNullTerminatedString(string: String, len: u64, ip: *const InternPool) NullTerminatedString { 1740 assert(std.mem.findScalar(u8, string.toSlice(len, ip), 0) == null); 1741 assert(string.at(len, ip) == 0); 1742 return @fromBackingInt(@intCast(@backingInt(string))); 1743 } 1744 1745 const Unwrapped = struct { 1746 tid: Zcu.PerThread.Id, 1747 index: u32, 1748 1749 fn wrap(unwrapped: Unwrapped, ip: *const InternPool) String { 1750 assert(@backingInt(unwrapped.tid) <= ip.getTidMask()); 1751 assert(unwrapped.index <= ip.getIndexMask(u32)); 1752 return @fromBackingInt(@intCast(@shlExact(@as(u32, @backingInt(unwrapped.tid)), ip.tid_shift_32) | 1753 unwrapped.index)); 1754 } 1755 }; 1756 fn unwrap(string: String, ip: *const InternPool) Unwrapped { 1757 return .{ 1758 .tid = @fromBackingInt(@intCast(@backingInt(string) >> ip.tid_shift_32 & ip.getTidMask())), 1759 .index = @backingInt(string) & ip.getIndexMask(u32), 1760 }; 1761 } 1762 1763 fn toOverlongSlice(string: String, ip: *const InternPool) []const u8 { 1764 const unwrapped = string.unwrap(ip); 1765 const local_shared = ip.getLocalShared(unwrapped.tid); 1766 const strings = local_shared.strings.acquire().view().items(.@"0"); 1767 const string_bytes = local_shared.string_bytes.acquire().view().items(.@"0"); 1768 return string_bytes[strings[unwrapped.index]..]; 1769 } 1770 1771 const debug_state = InternPool.debug_state; 1772 }; 1773 1774 /// An index into `strings` which might be `none`. 1775 pub const OptionalString = enum(u32) { 1776 /// This is distinct from `none` - it is a valid index that represents empty string. 1777 empty = 0, 1778 none = std.math.maxInt(u32), 1779 _, 1780 1781 pub fn unwrap(string: OptionalString) ?String { 1782 return if (string != .none) @fromBackingInt(@intCast(@backingInt(string))) else null; 1783 } 1784 1785 pub fn toSlice(string: OptionalString, len: u64, ip: *const InternPool) ?[]const u8 { 1786 return (string.unwrap() orelse return null).toSlice(len, ip); 1787 } 1788 1789 const debug_state = InternPool.debug_state; 1790 }; 1791 1792 /// An index into `strings`. 1793 pub const NullTerminatedString = enum(u32) { 1794 /// An empty string. 1795 empty = 0, 1796 _, 1797 1798 /// An array of `NullTerminatedString` existing within the `extra` array. 1799 /// This type exists to provide a struct with lifetime that is 1800 /// not invalidated when items are added to the `InternPool`. 1801 pub const Slice = struct { 1802 tid: Zcu.PerThread.Id, 1803 start: u32, 1804 len: u32, 1805 1806 pub const empty: Slice = .{ .tid = .main, .start = 0, .len = 0 }; 1807 1808 pub fn get(slice: Slice, ip: *const InternPool) []NullTerminatedString { 1809 const extra = ip.getLocalShared(slice.tid).extra.acquire(); 1810 return @ptrCast(extra.view().items(.@"0")[slice.start..][0..slice.len]); 1811 } 1812 }; 1813 1814 pub fn toString(self: NullTerminatedString) String { 1815 return @fromBackingInt(@intCast(@backingInt(self))); 1816 } 1817 1818 pub fn toOptional(self: NullTerminatedString) OptionalNullTerminatedString { 1819 return @fromBackingInt(@intCast(@backingInt(self))); 1820 } 1821 1822 pub fn toSlice(string: NullTerminatedString, ip: *const InternPool) [:0]const u8 { 1823 const unwrapped = string.toString().unwrap(ip); 1824 const local_shared = ip.getLocalShared(unwrapped.tid); 1825 const strings = local_shared.strings.acquire().view().items(.@"0"); 1826 const string_bytes = local_shared.string_bytes.acquire().view().items(.@"0"); 1827 return string_bytes[strings[unwrapped.index] .. strings[unwrapped.index + 1] - 1 :0]; 1828 } 1829 1830 pub fn length(string: NullTerminatedString, ip: *const InternPool) u32 { 1831 const unwrapped = string.toString().unwrap(ip); 1832 const local_shared = ip.getLocalShared(unwrapped.tid); 1833 const strings = local_shared.strings.acquire().view().items(.@"0"); 1834 return strings[unwrapped.index + 1] - 1 - strings[unwrapped.index]; 1835 } 1836 1837 pub fn eqlSlice(string: NullTerminatedString, slice: []const u8, ip: *const InternPool) bool { 1838 const overlong_slice = string.toString().toOverlongSlice(ip); 1839 return overlong_slice.len > slice.len and 1840 std.mem.eql(u8, overlong_slice[0..slice.len], slice) and 1841 overlong_slice[slice.len] == 0; 1842 } 1843 1844 const Adapter = struct { 1845 strings: []const NullTerminatedString, 1846 1847 pub fn eql(ctx: @This(), a: NullTerminatedString, b_void: void, b_map_index: usize) bool { 1848 _ = b_void; 1849 return a == ctx.strings[b_map_index]; 1850 } 1851 1852 pub fn hash(ctx: @This(), a: NullTerminatedString) u32 { 1853 _ = ctx; 1854 return std.hash.int(@backingInt(a)); 1855 } 1856 }; 1857 1858 /// Compare based on integer value alone, ignoring the string contents. 1859 pub fn indexLessThan(ctx: void, a: NullTerminatedString, b: NullTerminatedString) bool { 1860 _ = ctx; 1861 return @backingInt(a) < @backingInt(b); 1862 } 1863 1864 pub fn toUnsigned(string: NullTerminatedString, ip: *const InternPool) ?u32 { 1865 const slice = string.toSlice(ip); 1866 if (slice.len > 1 and slice[0] == '0') return null; 1867 if (std.mem.findScalar(u8, slice, '_')) |_| return null; 1868 return std.fmt.parseUnsigned(u32, slice, 10) catch null; 1869 } 1870 1871 const FormatData = struct { 1872 string: NullTerminatedString, 1873 ip: *const InternPool, 1874 id: bool, 1875 }; 1876 fn format(data: FormatData, writer: *Io.Writer) Io.Writer.Error!void { 1877 const slice = data.string.toSlice(data.ip); 1878 if (!data.id) { 1879 try writer.writeAll(slice); 1880 } else { 1881 try writer.print("{f}", .{std.zig.fmtIdP(slice)}); 1882 } 1883 } 1884 1885 pub fn fmt(string: NullTerminatedString, ip: *const InternPool) std.fmt.Alt(FormatData, format) { 1886 return .{ .data = .{ .string = string, .ip = ip, .id = false } }; 1887 } 1888 1889 pub fn fmtId(string: NullTerminatedString, ip: *const InternPool) std.fmt.Alt(FormatData, format) { 1890 return .{ .data = .{ .string = string, .ip = ip, .id = true } }; 1891 } 1892 1893 const debug_state = InternPool.debug_state; 1894 }; 1895 1896 /// An index into `strings` which might be `none`. 1897 pub const OptionalNullTerminatedString = enum(u32) { 1898 /// This is distinct from `none` - it is a valid index that represents empty string. 1899 empty = 0, 1900 none = std.math.maxInt(u32), 1901 _, 1902 1903 pub fn unwrap(string: OptionalNullTerminatedString) ?NullTerminatedString { 1904 return if (string != .none) @fromBackingInt(@intCast(@backingInt(string))) else null; 1905 } 1906 1907 pub fn toSlice(string: OptionalNullTerminatedString, ip: *const InternPool) ?[:0]const u8 { 1908 return (string.unwrap() orelse return null).toSlice(ip); 1909 } 1910 1911 const debug_state = InternPool.debug_state; 1912 }; 1913 1914 /// A single value captured in the closure of a namespace type. This is not a plain 1915 /// `Index` because we must differentiate between the following cases: 1916 /// * runtime-known value (where we store the type) 1917 /// * comptime-known value (where we store the value) 1918 /// * `Nav` val (so that we can analyze the value lazily) 1919 /// * `Nav` ref (so that we can analyze the reference lazily) 1920 pub const CaptureValue = packed struct(u32) { 1921 tag: enum(u2) { @"comptime", runtime, nav_val, nav_ref }, 1922 idx: u30, 1923 1924 pub fn wrap(val: Unwrapped) CaptureValue { 1925 return switch (val) { 1926 .@"comptime" => |i| .{ .tag = .@"comptime", .idx = @intCast(@backingInt(i)) }, 1927 .runtime => |i| .{ .tag = .runtime, .idx = @intCast(@backingInt(i)) }, 1928 .nav_val => |i| .{ .tag = .nav_val, .idx = @intCast(@backingInt(i)) }, 1929 .nav_ref => |i| .{ .tag = .nav_ref, .idx = @intCast(@backingInt(i)) }, 1930 }; 1931 } 1932 pub fn unwrap(val: CaptureValue) Unwrapped { 1933 return switch (val.tag) { 1934 .@"comptime" => .{ .@"comptime" = @fromBackingInt(@intCast(val.idx)) }, 1935 .runtime => .{ .runtime = @fromBackingInt(@intCast(val.idx)) }, 1936 .nav_val => .{ .nav_val = @fromBackingInt(@intCast(val.idx)) }, 1937 .nav_ref => .{ .nav_ref = @fromBackingInt(@intCast(val.idx)) }, 1938 }; 1939 } 1940 1941 pub const Unwrapped = union(enum) { 1942 /// Index refers to the value. 1943 @"comptime": Index, 1944 /// Index refers to the type. 1945 runtime: Index, 1946 nav_val: Nav.Index, 1947 nav_ref: Nav.Index, 1948 }; 1949 1950 pub const Slice = struct { 1951 tid: Zcu.PerThread.Id, 1952 start: u32, 1953 len: u32, 1954 1955 pub const empty: Slice = .{ .tid = .main, .start = 0, .len = 0 }; 1956 1957 pub fn get(slice: Slice, ip: *const InternPool) []CaptureValue { 1958 const extra = ip.getLocalShared(slice.tid).extra.acquire(); 1959 return @ptrCast(extra.view().items(.@"0")[slice.start..][0..slice.len]); 1960 } 1961 }; 1962 }; 1963 1964 pub const Key = union(enum) { 1965 int_type: IntType, 1966 ptr_type: PtrType, 1967 array_type: ArrayType, 1968 vector_type: VectorType, 1969 opt_type: Index, 1970 /// `anyframe->T`. The payload is the child type, which may be `none` to indicate 1971 /// `anyframe`. 1972 anyframe_type: Index, 1973 error_union_type: ErrorUnionType, 1974 simple_type: SimpleType, 1975 /// This represents a struct that has been explicitly declared in source code, 1976 /// or was created with `@Struct`. It is unique and based on a declaration. 1977 struct_type: ContainerType, 1978 /// This is a tuple type. Tuples are logically similar to structs, but have some 1979 /// important differences in semantics; they do not undergo staged type resolution, 1980 /// so cannot be self-referential, and they are not considered container/namespace 1981 /// types, so cannot have declarations and have structural equality properties. 1982 tuple_type: TupleType, 1983 union_type: ContainerType, 1984 opaque_type: ContainerType, 1985 enum_type: ContainerType, 1986 spirv_type: SpirvType, 1987 func_type: FuncType, 1988 error_set_type: ErrorSetType, 1989 /// The payload is the function body, either a `func_decl` or `func_instance`. 1990 inferred_error_set_type: Index, 1991 1992 /// Typed `undefined`. This will never be `none`; untyped `undefined` is represented 1993 /// via `simple_value` and has a named `Index` tag for it. 1994 undef: Index, 1995 simple_value: SimpleValue, 1996 @"extern": Extern, 1997 func: Func, 1998 int: Key.Int, 1999 err: Error, 2000 error_union: ErrorUnion, 2001 enum_literal: NullTerminatedString, 2002 /// A specific enum tag, indicated by the integer tag value. 2003 enum_tag: EnumTag, 2004 float: Float, 2005 ptr: Ptr, 2006 slice: Slice, 2007 opt: Opt, 2008 /// An instance of a struct, array, or vector. 2009 /// Each element/field stored as an `Index`. 2010 /// In the case of sentinel-terminated arrays, the sentinel value *is* stored, 2011 /// so the slice length will be one more than the type's array length. 2012 /// There must be at least one element which is not `undefined`. If all elements are 2013 /// undefined, instead create an undefined value of the aggregate type. 2014 aggregate: Aggregate, 2015 /// An instance of a union. 2016 un: Union, 2017 /// An instance of a `packed struct` or `packed union`. 2018 bitpack: Bitpack, 2019 2020 /// A comptime function call with a memoized result. 2021 memoized_call: Key.MemoizedCall, 2022 2023 pub const TypeValue = extern struct { 2024 ty: Index, 2025 val: Index, 2026 }; 2027 2028 pub const IntType = std.lang.Type.Int; 2029 2030 /// Extern for hashing via memory reinterpretation. 2031 pub const ErrorUnionType = extern struct { 2032 error_set_type: Index, 2033 payload_type: Index, 2034 }; 2035 2036 pub const ErrorSetType = struct { 2037 /// Set of error names, sorted by null terminated string index. 2038 names: NullTerminatedString.Slice, 2039 /// This is ignored by `get` but will always be provided by `indexToKey`. 2040 names_map: OptionalMapIndex = .none, 2041 2042 /// Look up field index based on field name. 2043 pub fn nameIndex(self: ErrorSetType, ip: *const InternPool, name: NullTerminatedString) ?u32 { 2044 const map = self.names_map.unwrap().?.get(ip); 2045 const adapter: NullTerminatedString.Adapter = .{ .strings = self.names.get(ip) }; 2046 const field_index = map.getIndexAdapted(name, adapter) orelse return null; 2047 return @intCast(field_index); 2048 } 2049 }; 2050 2051 /// Extern layout so it can be hashed with `std.mem.asBytes`. 2052 pub const PtrType = extern struct { 2053 child: Index, 2054 sentinel: Index = .none, 2055 flags: Flags = .{}, 2056 packed_offset: PackedOffset = .{ .bit_offset = 0, .host_size = 0 }, 2057 2058 pub const VectorIndex = enum(u16) { 2059 none = std.math.maxInt(u16), 2060 _, 2061 }; 2062 2063 pub const Flags = packed struct(u32) { 2064 size: Size = .one, 2065 /// `none` indicates the ABI alignment of the pointee_type. In this 2066 /// case, this field *must* be set to `none`, otherwise the 2067 /// `InternPool` equality and hashing functions will return incorrect 2068 /// results. 2069 alignment: Alignment = .none, 2070 is_const: bool = false, 2071 is_volatile: bool = false, 2072 is_allowzero: bool = false, 2073 /// See src/target.zig defaultAddressSpace function for how to obtain 2074 /// an appropriate value for this field. 2075 address_space: AddressSpace = .generic, 2076 vector_index: VectorIndex = .none, 2077 }; 2078 2079 pub const PackedOffset = packed struct(u32) { 2080 /// If this is non-zero it means the pointer points to a sub-byte 2081 /// range of data, which is backed by a "host integer" with this 2082 /// number of bytes. 2083 /// When host_size=pointee_abi_size and bit_offset=0, this must be 2084 /// represented with host_size=0 instead. 2085 host_size: u16, 2086 bit_offset: u16, 2087 }; 2088 2089 pub const Size = std.lang.Type.Pointer.Size; 2090 pub const AddressSpace = std.lang.AddressSpace; 2091 }; 2092 2093 /// Extern so that hashing can be done via memory reinterpreting. 2094 pub const ArrayType = extern struct { 2095 len: u64, 2096 child: Index, 2097 sentinel: Index = .none, 2098 2099 pub fn lenIncludingSentinel(array_type: ArrayType) u64 { 2100 return array_type.len + @intFromBool(array_type.sentinel != .none); 2101 } 2102 }; 2103 2104 /// Extern so that hashing can be done via memory reinterpreting. 2105 pub const VectorType = extern struct { 2106 len: u32, 2107 child: Index, 2108 }; 2109 2110 pub const TupleType = struct { 2111 types: Index.Slice, 2112 /// These elements may be `none`, indicating runtime-known. 2113 values: Index.Slice, 2114 }; 2115 2116 /// This is the hashmap key. To fetch other data associated with the type, see: 2117 /// * `loadStructType` 2118 /// * `loadUnionType` 2119 /// * `loadEnumType` 2120 /// * `loadOpaqueType` 2121 pub const ContainerType = union(enum) { 2122 /// This type corresponds to an actual source declaration, e.g. `struct { ... }`. 2123 /// It is hashed based on its ZIR instruction index and set of captures. 2124 declared: Declared, 2125 /// This type originates from a reification via `@Enum`, `@Struct`, `@Union` or from an anonymous initialization. 2126 /// It is hashed based on its ZIR instruction index and fields, attributes, etc. 2127 /// To avoid making this key overly complex, the type-specific data is hashed by Sema. 2128 reified: struct { 2129 /// A `reify`, `struct_init`, `struct_init_ref`, or `struct_init_anon` instruction. 2130 /// Alternatively, this is `main_struct_inst` of a ZON file. 2131 zir_index: TrackedInst.Index, 2132 /// A hash of this type's attributes, fields, etc, generated by Sema. 2133 type_hash: u64, 2134 }, 2135 /// This type is an automatically-generated enum tag type for this union type. 2136 /// It is hashed based on the index of the union type it corresponds to. 2137 generated_union_tag: Index, 2138 2139 pub const Declared = struct { 2140 /// A `struct_decl`, `union_decl`, `enum_decl`, or `opaque_decl` instruction. 2141 zir_index: TrackedInst.Index, 2142 /// The captured values of this type. These values must be fully resolved per the language spec. 2143 captures: union(enum) { 2144 owned: CaptureValue.Slice, 2145 external: []const CaptureValue, 2146 }, 2147 }; 2148 }; 2149 2150 pub const SpirvType = extern struct { 2151 /// If tag is `.image`, this is the sampled type or `.none` if `usage` is `.storage`. 2152 /// If tag is `.sampled_image`, this is the image type. 2153 /// If tag is `.runtime_array`, this is the element type. 2154 /// Otherwise this is `.none`. 2155 ty: Index, 2156 flags: Flags, 2157 2158 pub const Flags = packed struct(u32) { 2159 tag: @typeInfo(std.lang.Type.Spirv).@"union".tag_type.?, 2160 // Image type flags 2161 usage: @typeInfo(std.lang.Type.Spirv.Image.Usage).@"union".tag_type.?, 2162 format: std.lang.Type.Spirv.Image.Format, 2163 dim: std.lang.Type.Spirv.Image.Dimensionality, 2164 depth: std.lang.Type.Spirv.Image.Depth, 2165 access: std.lang.Type.Spirv.Image.Access, 2166 is_arrayed: bool, 2167 is_multisampled: bool, 2168 2169 _: u16 = 0, 2170 }; 2171 }; 2172 2173 pub const FuncType = struct { 2174 param_types: Index.Slice, 2175 return_type: Index, 2176 /// Tells whether a parameter is comptime. See `paramIsComptime` helper 2177 /// method for accessing this. 2178 comptime_bits: u32, 2179 /// Tells whether a parameter is noalias. See `paramIsNoalias` helper 2180 /// method for accessing this. 2181 noalias_bits: u32, 2182 cc: std.lang.CallingConvention, 2183 is_var_args: bool, 2184 is_noinline: bool, 2185 2186 pub fn paramIsComptime(self: @This(), i: u5) bool { 2187 assert(i < self.param_types.len); 2188 return @as(u1, @truncate(self.comptime_bits >> i)) != 0; 2189 } 2190 2191 pub fn paramIsNoalias(self: @This(), i: u5) bool { 2192 assert(i < self.param_types.len); 2193 return @as(u1, @truncate(self.noalias_bits >> i)) != 0; 2194 } 2195 2196 pub fn eql(a: FuncType, b: FuncType, ip: *const InternPool) bool { 2197 return std.mem.eql(Index, a.param_types.get(ip), b.param_types.get(ip)) and 2198 a.return_type == b.return_type and 2199 a.comptime_bits == b.comptime_bits and 2200 a.noalias_bits == b.noalias_bits and 2201 a.is_var_args == b.is_var_args and 2202 a.is_noinline == b.is_noinline and 2203 std.meta.eql(a.cc, b.cc); 2204 } 2205 2206 pub fn hash(self: FuncType, hasher: *Hash, ip: *const InternPool) void { 2207 for (self.param_types.get(ip)) |param_type| { 2208 std.hash.autoHash(hasher, param_type); 2209 } 2210 std.hash.autoHash(hasher, self.return_type); 2211 std.hash.autoHash(hasher, self.comptime_bits); 2212 std.hash.autoHash(hasher, self.noalias_bits); 2213 std.hash.autoHash(hasher, self.cc); 2214 std.hash.autoHash(hasher, self.is_var_args); 2215 std.hash.autoHash(hasher, self.is_noinline); 2216 } 2217 }; 2218 2219 pub const Extern = struct { 2220 /// The name of the extern symbol. 2221 name: NullTerminatedString, 2222 /// The type of the extern symbol itself. 2223 /// This may be `.anyopaque_type`, in which case the value may not be loaded. 2224 ty: Index, 2225 /// Library name if specified. 2226 /// For example `extern "c" fn write(...) usize` would have 'c' as library name. 2227 /// Index into the string table bytes. 2228 lib_name: OptionalNullTerminatedString, 2229 linkage: std.lang.GlobalLinkage, 2230 visibility: std.lang.SymbolVisibility, 2231 is_threadlocal: bool, 2232 is_dll_import: bool, 2233 relocation: std.lang.ExternOptions.Relocation, 2234 decoration: ?std.lang.ExternOptions.Decoration, 2235 is_const: bool, 2236 alignment: Alignment, 2237 @"addrspace": std.lang.AddressSpace, 2238 /// The ZIR instruction which created this extern; used only for source locations. 2239 /// This is a `declaration`. 2240 zir_index: TrackedInst.Index, 2241 /// The `Nav` corresponding to this extern symbol. 2242 /// This is ignored by hashing and equality. 2243 owner_nav: Nav.Index, 2244 source: Tag.Extern.Flags.Source, 2245 }; 2246 2247 pub const Func = struct { 2248 tid: Zcu.PerThread.Id, 2249 /// In the case of a generic function, this type will potentially have fewer parameters 2250 /// than the generic owner's type, because the comptime parameters will be deleted. 2251 ty: Index, 2252 /// If this is a function body that has been coerced to a different type, for example 2253 /// ``` 2254 /// fn f2() !void {} 2255 /// const f: fn()anyerror!void = f2; 2256 /// ``` 2257 /// then it contains the original type of the function body. 2258 uncoerced_ty: Index, 2259 /// Index into extra array of the `FuncAnalysis` corresponding to this function. 2260 /// Used for mutating that data. 2261 analysis_extra_index: u32, 2262 /// Index into extra array of the `zir_body_inst` corresponding to this function. 2263 /// Used for mutating that data. 2264 zir_body_inst_extra_index: u32, 2265 /// Index into extra array of the resolved inferred error set for this function. 2266 /// Used for mutating that data. 2267 /// 0 when the function does not have an inferred error set. 2268 resolved_error_set_extra_index: u32, 2269 /// When a generic function is instantiated, branch_quota is inherited from the 2270 /// active Sema context. Importantly, this value is also updated when an existing 2271 /// generic function instantiation is found and called. 2272 /// This field contains the index into the extra array of this value, 2273 /// so that it can be mutated. 2274 /// This will be 0 when the function is not a generic function instantiation. 2275 branch_quota_extra_index: u32, 2276 owner_nav: Nav.Index, 2277 /// The ZIR instruction that is a function instruction. Use this to find 2278 /// the body. We store this rather than the body directly so that when ZIR 2279 /// is regenerated on update(), we can map this to the new corresponding 2280 /// ZIR instruction. 2281 zir_body_inst: TrackedInst.Index, 2282 /// Relative to owner Decl. 2283 lbrace_line: u32, 2284 /// Relative to owner Decl. 2285 rbrace_line: u32, 2286 lbrace_column: u32, 2287 rbrace_column: u32, 2288 2289 /// The `func_decl` which is the generic function from whence this instance was spawned. 2290 /// If this is `none` it means the function is not a generic instantiation. 2291 generic_owner: Index, 2292 /// If this is a generic function instantiation, this will be non-empty. 2293 /// Corresponds to the parameters of the `generic_owner` type, which 2294 /// may have more parameters than `ty`. 2295 /// Each element is the comptime-known value the generic function was instantiated with, 2296 /// or `none` if the element is runtime-known. 2297 /// TODO: as a follow-up optimization, don't store `none` values here since that data 2298 /// is redundant with `comptime_bits` stored elsewhere. 2299 comptime_args: Index.Slice, 2300 2301 /// Returns a pointer that becomes invalid after any additions to the `InternPool`. 2302 fn analysisPtr(func: Func, ip: *const InternPool) *FuncAnalysis { 2303 const extra = ip.getLocalShared(func.tid).extra.acquire(); 2304 return @ptrCast(&extra.view().items(.@"0")[func.analysis_extra_index]); 2305 } 2306 2307 pub fn analysisUnordered(func: Func, ip: *const InternPool) FuncAnalysis { 2308 return @atomicLoad(FuncAnalysis, func.analysisPtr(ip), .unordered); 2309 } 2310 2311 pub fn setBranchHint(func: Func, ip: *InternPool, io: Io, hint: std.lang.BranchHint) void { 2312 const extra_mutex = &ip.getLocal(func.tid).mutate.extra.mutex; 2313 extra_mutex.lockUncancelable(io); 2314 defer extra_mutex.unlock(io); 2315 2316 const analysis_ptr = func.analysisPtr(ip); 2317 var analysis = analysis_ptr.*; 2318 analysis.branch_hint = hint; 2319 @atomicStore(FuncAnalysis, analysis_ptr, analysis, .release); 2320 } 2321 2322 /// Returns a pointer that becomes invalid after any additions to the `InternPool`. 2323 fn zirBodyInstPtr(func: Func, ip: *const InternPool) *TrackedInst.Index { 2324 const extra = ip.getLocalShared(func.tid).extra.acquire(); 2325 return @ptrCast(&extra.view().items(.@"0")[func.zir_body_inst_extra_index]); 2326 } 2327 2328 pub fn zirBodyInstUnordered(func: Func, ip: *const InternPool) TrackedInst.Index { 2329 return @atomicLoad(TrackedInst.Index, func.zirBodyInstPtr(ip), .unordered); 2330 } 2331 2332 /// Returns a pointer that becomes invalid after any additions to the `InternPool`. 2333 fn branchQuotaPtr(func: Func, ip: *const InternPool) *u32 { 2334 const extra = ip.getLocalShared(func.tid).extra.acquire(); 2335 return &extra.view().items(.@"0")[func.branch_quota_extra_index]; 2336 } 2337 2338 pub fn branchQuotaUnordered(func: Func, ip: *const InternPool) u32 { 2339 return @atomicLoad(u32, func.branchQuotaPtr(ip), .unordered); 2340 } 2341 2342 pub fn maxBranchQuota(func: Func, ip: *InternPool, io: Io, new_branch_quota: u32) void { 2343 const extra_mutex = &ip.getLocal(func.tid).mutate.extra.mutex; 2344 extra_mutex.lockUncancelable(io); 2345 defer extra_mutex.unlock(io); 2346 2347 const branch_quota_ptr = func.branchQuotaPtr(ip); 2348 @atomicStore(u32, branch_quota_ptr, @max(branch_quota_ptr.*, new_branch_quota), .release); 2349 } 2350 2351 /// Returns a pointer that becomes invalid after any additions to the `InternPool`. 2352 fn resolvedErrorSetPtr(func: Func, ip: *const InternPool) *Index { 2353 const extra = ip.getLocalShared(func.tid).extra.acquire(); 2354 assert(func.analysisUnordered(ip).inferred_error_set); 2355 return @ptrCast(&extra.view().items(.@"0")[func.resolved_error_set_extra_index]); 2356 } 2357 2358 pub fn resolvedErrorSetUnordered(func: Func, ip: *const InternPool) Index { 2359 return @atomicLoad(Index, func.resolvedErrorSetPtr(ip), .unordered); 2360 } 2361 2362 pub fn setResolvedErrorSet(func: Func, ip: *InternPool, io: Io, ies: Index) void { 2363 const extra_mutex = &ip.getLocal(func.tid).mutate.extra.mutex; 2364 extra_mutex.lockUncancelable(io); 2365 defer extra_mutex.unlock(io); 2366 2367 @atomicStore(Index, func.resolvedErrorSetPtr(ip), ies, .release); 2368 } 2369 }; 2370 2371 pub const Int = struct { 2372 ty: Index, 2373 storage: Storage, 2374 2375 pub const Storage = union(enum) { 2376 u64: u64, 2377 i64: i64, 2378 big_int: BigIntConst, 2379 2380 /// Big enough to fit any non-BigInt value 2381 pub const BigIntSpace = struct { 2382 /// The +1 is headroom so that operations such as incrementing once 2383 /// or decrementing once are possible without using an allocator. 2384 limbs: [(@sizeOf(u64) / @sizeOf(std.math.big.Limb)) + 1]std.math.big.Limb, 2385 }; 2386 2387 pub fn toBigInt(storage: Storage, space: *BigIntSpace) BigIntConst { 2388 return switch (storage) { 2389 .big_int => |x| x, 2390 inline .u64, .i64 => |x| BigIntMutable.init(&space.limbs, x).toConst(), 2391 }; 2392 } 2393 }; 2394 }; 2395 2396 pub const Error = extern struct { 2397 ty: Index, 2398 name: NullTerminatedString, 2399 }; 2400 2401 pub const ErrorUnion = struct { 2402 ty: Index, 2403 val: Value, 2404 2405 pub const Value = union(enum) { 2406 err_name: NullTerminatedString, 2407 payload: Index, 2408 }; 2409 }; 2410 2411 pub const EnumTag = extern struct { 2412 /// The enum type. 2413 ty: Index, 2414 /// The integer tag value which has the integer tag type of the enum. 2415 int: Index, 2416 }; 2417 2418 pub const Float = struct { 2419 ty: Index, 2420 /// The storage used must match the size of the float type being represented. 2421 storage: Storage, 2422 2423 pub const Storage = union(enum) { 2424 f16: f16, 2425 f32: f32, 2426 f64: f64, 2427 f80: f80, 2428 f128: f128, 2429 }; 2430 }; 2431 2432 pub const Ptr = struct { 2433 /// This is the pointer type, not the element type. 2434 ty: Index, 2435 /// The base address which this pointer is offset from. 2436 base_addr: BaseAddr, 2437 /// The offset of this pointer from `base_addr` in bytes. 2438 byte_offset: u64, 2439 2440 pub const BaseAddr = union(enum) { 2441 const Tag = @typeInfo(BaseAddr).@"union".tag_type.?; 2442 2443 /// Points to the value of a single `Nav`. 2444 nav: Nav.Index, 2445 2446 /// Points to the value of a single comptime alloc stored in `Sema`. 2447 comptime_alloc: ComptimeAllocIndex, 2448 2449 /// Points to a single unnamed constant value. 2450 uav: Uav, 2451 2452 /// Points to a comptime field of a struct. Index is the field's value. 2453 /// 2454 /// TODO: this exists because these fields are semantically mutable. We 2455 /// should probably change the language so that this isn't the case. 2456 comptime_field: Index, 2457 2458 /// A pointer with a fixed integer address, usually from `@ptrFromInt`. 2459 /// 2460 /// The address is stored entirely by `byte_offset`, which will be positive 2461 /// and in-range of a `usize`. The base address is, for all intents and purposes, 0. 2462 int, 2463 2464 /// A pointer to the payload of an error union. Index is the error union pointer. 2465 /// To ensure a canonical representation, the type of the base pointer must: 2466 /// * be a one-pointer 2467 /// * be `const`, `volatile` and `allowzero` 2468 /// * have alignment 1 2469 /// * have the same address space as this pointer 2470 /// * have a host size, bit offset, and vector index of 0 2471 /// See `Value.canonicalizeBasePtr` which enforces these properties. 2472 eu_payload: Index, 2473 2474 /// A pointer to the payload of a non-pointer-like optional. Index is the 2475 /// optional pointer. To ensure a canonical representation, the base 2476 /// pointer is subject to the same restrictions as in `eu_payload`. 2477 opt_payload: Index, 2478 2479 /// A pointer to a field of a slice, or of an auto-layout struct or union. Slice fields 2480 /// are referenced according to `Value.slice_ptr_index` and `Value.slice_len_index`. 2481 /// Base is the aggregate pointer, which is subject to the same restrictions as 2482 /// in `eu_payload`. 2483 field: BaseIndex, 2484 2485 /// A pointer to an element of a comptime-only array. Base is the 2486 /// many-pointer we are indexing into. It is subject to the same restrictions 2487 /// as in `eu_payload`, except it must be a many-pointer rather than a one-pointer. 2488 /// 2489 /// The element type of the base pointer must NOT be an array. Additionally, the 2490 /// base pointer is guaranteed to not be an `arr_elem` into a pointer with the 2491 /// same child type. Thus, since there are no two comptime-only types which are 2492 /// IMC to one another, the only case where the base pointer may also be an 2493 /// `arr_elem` is when this pointer is semantically invalid (e.g. it reinterprets 2494 /// a `type` as a `comptime_int`). These restrictions are in place to ensure 2495 /// a canonical representation. 2496 /// 2497 /// This kind of base address differs from others in that it may refer to any 2498 /// sequence of values; for instance, an `arr_elem` at index 2 may refer to 2499 /// any number of elements starting from index 2. 2500 /// 2501 /// Index must not be 0. To refer to the element at index 0, simply reinterpret 2502 /// the aggregate pointer. 2503 arr_elem: BaseIndex, 2504 2505 pub const BaseIndex = struct { 2506 base: Index, 2507 index: u64, 2508 }; 2509 pub const Uav = extern struct { 2510 val: Index, 2511 /// Contains the canonical pointer type of the anonymous 2512 /// declaration. This may equal `ty` of the `Ptr` or it may be 2513 /// different. Importantly, when lowering the anonymous decl, 2514 /// the original pointer type alignment must be used. 2515 orig_ty: Index, 2516 }; 2517 2518 pub fn eql(a: BaseAddr, b: BaseAddr) bool { 2519 if (@as(Key.Ptr.BaseAddr.Tag, a) != @as(Key.Ptr.BaseAddr.Tag, b)) return false; 2520 2521 return switch (a) { 2522 .nav => |a_nav| a_nav == b.nav, 2523 .comptime_alloc => |a_alloc| a_alloc == b.comptime_alloc, 2524 .uav => |ad| ad.val == b.uav.val and 2525 ad.orig_ty == b.uav.orig_ty, 2526 .int => true, 2527 .eu_payload => |a_eu_payload| a_eu_payload == b.eu_payload, 2528 .opt_payload => |a_opt_payload| a_opt_payload == b.opt_payload, 2529 .comptime_field => |a_comptime_field| a_comptime_field == b.comptime_field, 2530 .arr_elem => |a_elem| std.meta.eql(a_elem, b.arr_elem), 2531 .field => |a_field| std.meta.eql(a_field, b.field), 2532 }; 2533 } 2534 }; 2535 }; 2536 2537 pub const Slice = struct { 2538 /// This is the slice type, not the element type. 2539 ty: Index, 2540 /// The slice's `ptr` field. Must be a many-ptr with the same properties as `ty`. 2541 ptr: Index, 2542 /// The slice's `len` field. Must be a `usize`. 2543 len: Index, 2544 }; 2545 2546 /// `null` is represented by the `val` field being `none`. 2547 pub const Opt = extern struct { 2548 /// This is the optional type; not the payload type. 2549 ty: Index, 2550 /// This could be `none`, indicating the optional is `null`. 2551 val: Index, 2552 }; 2553 2554 pub const Union = extern struct { 2555 /// This is the union type; not the field type. 2556 ty: Index, 2557 /// Indicates the active field. This could be `none`, which indicates the tag is not known. `none` is only a valid value for extern and packed unions. 2558 /// In those cases, the type of `val` is: 2559 /// extern: a u8 array of the same byte length as the union 2560 /// packed: an unsigned integer with the same bit size as the union 2561 tag: Index, 2562 /// The value of the active field. 2563 val: Index, 2564 }; 2565 2566 pub const Aggregate = struct { 2567 ty: Index, 2568 storage: Storage, 2569 2570 pub const Storage = union(enum) { 2571 bytes: String, 2572 elems: []const Index, 2573 repeated_elem: Index, 2574 2575 pub fn values(self: *const Storage) []const Index { 2576 return switch (self.*) { 2577 .bytes => &.{}, 2578 .elems => |elems| elems, 2579 .repeated_elem => |*elem| @as(*const [1]Index, elem), 2580 }; 2581 } 2582 }; 2583 }; 2584 2585 /// As well as a key, this type doubles as the payload in `extra` for `Tag.bitpack`. 2586 pub const Bitpack = struct { 2587 /// The `packed struct` or `packed union` type. 2588 ty: Index, 2589 /// The contents of the bitpack, represented as the backing integer value. The type of this 2590 /// value is the same as the backing integer type of `ty`. 2591 backing_int_val: Index, 2592 }; 2593 2594 pub const MemoizedCall = struct { 2595 func: Index, 2596 arg_values: []const Index, 2597 result: Index, 2598 branch_count: u32, 2599 branch_quota: u32, 2600 }; 2601 2602 pub fn hash32(key: Key, ip: *const InternPool) u32 { 2603 return @truncate(key.hash64(ip)); 2604 } 2605 2606 pub fn hash64(key: Key, ip: *const InternPool) u64 { 2607 const asBytes = std.mem.asBytes; 2608 const KeyTag = @typeInfo(Key).@"union".tag_type.?; 2609 const seed = @backingInt(@as(KeyTag, key)); 2610 return switch (key) { 2611 inline .ptr_type, 2612 .array_type, 2613 .vector_type, 2614 .opt_type, 2615 .anyframe_type, 2616 .error_union_type, 2617 .spirv_type, 2618 .simple_type, 2619 .simple_value, 2620 .opt, 2621 .undef, 2622 .err, 2623 .enum_literal, 2624 .enum_tag, 2625 .inferred_error_set_type, 2626 .un, 2627 => |x| { 2628 _ = extern struct { is_extern: @TypeOf(x) }; 2629 comptime assert(std.meta.hasUniqueRepresentation(@TypeOf(x))); 2630 return Hash.hash(seed, asBytes(&x)); 2631 }, 2632 2633 .int_type => |x| Hash.hash(seed + @backingInt(x.signedness), asBytes(&x.bits)), 2634 2635 .error_union => |x| switch (x.val) { 2636 .err_name => |y| Hash.hash(seed + 0, asBytes(&x.ty) ++ asBytes(&y)), 2637 .payload => |y| Hash.hash(seed + 1, asBytes(&x.ty) ++ asBytes(&y)), 2638 }, 2639 2640 .opaque_type, 2641 .enum_type, 2642 .union_type, 2643 .struct_type, 2644 => |namespace_type| { 2645 var hasher = Hash.init(seed); 2646 std.hash.autoHash(&hasher, std.meta.activeTag(namespace_type)); 2647 switch (namespace_type) { 2648 .declared => |declared| { 2649 std.hash.autoHash(&hasher, declared.zir_index); 2650 const captures = switch (declared.captures) { 2651 .owned => |cvs| cvs.get(ip), 2652 .external => |cvs| cvs, 2653 }; 2654 for (captures) |cv| { 2655 std.hash.autoHash(&hasher, cv); 2656 } 2657 }, 2658 .reified => |reified| { 2659 std.hash.autoHash(&hasher, reified.zir_index); 2660 std.hash.autoHash(&hasher, reified.type_hash); 2661 }, 2662 .generated_union_tag => |union_type| { 2663 std.hash.autoHash(&hasher, union_type); 2664 }, 2665 } 2666 return hasher.final(); 2667 }, 2668 2669 .int => |int| { 2670 var hasher = Hash.init(seed); 2671 // Canonicalize all integers by converting them to BigIntConst. 2672 var buffer: Key.Int.Storage.BigIntSpace = undefined; 2673 const big_int = int.storage.toBigInt(&buffer); 2674 2675 std.hash.autoHash(&hasher, int.ty); 2676 std.hash.autoHash(&hasher, big_int.positive or big_int.eqlZero()); 2677 for (big_int.limbs) |limb| std.hash.autoHash(&hasher, limb); 2678 return hasher.final(); 2679 }, 2680 2681 .float => |float| { 2682 var hasher = Hash.init(seed); 2683 std.hash.autoHash(&hasher, float.ty); 2684 switch (float.storage) { 2685 inline else => |val| std.hash.autoHash( 2686 &hasher, 2687 @as(@Int(.unsigned, @bitSizeOf(@TypeOf(val))), @bitCast(val)), 2688 ), 2689 } 2690 return hasher.final(); 2691 }, 2692 2693 .slice => |slice| Hash.hash(seed, asBytes(&slice.ty) ++ asBytes(&slice.ptr) ++ asBytes(&slice.len)), 2694 2695 .ptr => |ptr| { 2696 // Int-to-ptr pointers are hashed separately than decl-referencing pointers. 2697 // This is sound due to pointer provenance rules. 2698 const addr_tag: Key.Ptr.BaseAddr.Tag = ptr.base_addr; 2699 const seed2 = seed + @backingInt(addr_tag); 2700 const big_offset: i128 = ptr.byte_offset; 2701 const common = asBytes(&ptr.ty) ++ asBytes(&big_offset); 2702 return switch (ptr.base_addr) { 2703 inline .nav, 2704 .comptime_alloc, 2705 .uav, 2706 .int, 2707 .eu_payload, 2708 .opt_payload, 2709 .comptime_field, 2710 => |x| Hash.hash(seed2, common ++ asBytes(&x)), 2711 2712 .arr_elem, .field => |x| Hash.hash( 2713 seed2, 2714 common ++ asBytes(&x.base) ++ asBytes(&x.index), 2715 ), 2716 }; 2717 }, 2718 2719 .aggregate => |aggregate| { 2720 var hasher = Hash.init(seed); 2721 std.hash.autoHash(&hasher, aggregate.ty); 2722 const len = ip.aggregateTypeLen(aggregate.ty); 2723 const child = switch (ip.indexToKey(aggregate.ty)) { 2724 .array_type => |array_type| array_type.child, 2725 .vector_type => |vector_type| vector_type.child, 2726 .tuple_type, .struct_type => .none, 2727 else => unreachable, 2728 }; 2729 2730 if (child == .u8_type) { 2731 switch (aggregate.storage) { 2732 .bytes => |bytes| for (bytes.toSlice(len, ip)) |byte| { 2733 std.hash.autoHash(&hasher, KeyTag.int); 2734 std.hash.autoHash(&hasher, byte); 2735 }, 2736 .elems => |elems| for (elems[0..@intCast(len)]) |elem| { 2737 const elem_key = ip.indexToKey(elem); 2738 std.hash.autoHash(&hasher, @as(KeyTag, elem_key)); 2739 switch (elem_key) { 2740 .undef => {}, 2741 .int => |int| std.hash.autoHash( 2742 &hasher, 2743 @as(u8, @intCast(int.storage.u64)), 2744 ), 2745 else => unreachable, 2746 } 2747 }, 2748 .repeated_elem => |elem| { 2749 const elem_key = ip.indexToKey(elem); 2750 var remaining = len; 2751 while (remaining > 0) : (remaining -= 1) { 2752 std.hash.autoHash(&hasher, @as(KeyTag, elem_key)); 2753 switch (elem_key) { 2754 .undef => {}, 2755 .int => |int| std.hash.autoHash( 2756 &hasher, 2757 @as(u8, @intCast(int.storage.u64)), 2758 ), 2759 else => unreachable, 2760 } 2761 } 2762 }, 2763 } 2764 return hasher.final(); 2765 } 2766 2767 switch (aggregate.storage) { 2768 .bytes => unreachable, 2769 .elems => |elems| for (elems[0..@intCast(len)]) |elem| 2770 std.hash.autoHash(&hasher, elem), 2771 .repeated_elem => |elem| { 2772 var remaining = len; 2773 while (remaining > 0) : (remaining -= 1) std.hash.autoHash(&hasher, elem); 2774 }, 2775 } 2776 return hasher.final(); 2777 }, 2778 2779 .error_set_type => |x| Hash.hash(seed, std.mem.sliceAsBytes(x.names.get(ip))), 2780 2781 .tuple_type => |tuple_type| { 2782 var hasher = Hash.init(seed); 2783 for (tuple_type.types.get(ip)) |elem| std.hash.autoHash(&hasher, elem); 2784 for (tuple_type.values.get(ip)) |elem| std.hash.autoHash(&hasher, elem); 2785 return hasher.final(); 2786 }, 2787 2788 .func_type => |func_type| { 2789 var hasher = Hash.init(seed); 2790 func_type.hash(&hasher, ip); 2791 return hasher.final(); 2792 }, 2793 2794 .memoized_call => |memoized_call| { 2795 var hasher = Hash.init(seed); 2796 std.hash.autoHash(&hasher, memoized_call.func); 2797 for (memoized_call.arg_values) |arg| std.hash.autoHash(&hasher, arg); 2798 return hasher.final(); 2799 }, 2800 2801 .func => |func| { 2802 // In the case of a function with an inferred error set, we 2803 // must not include the inferred error set type in the hash, 2804 // otherwise we would get false negatives for interning generic 2805 // function instances which have inferred error sets. 2806 2807 if (func.generic_owner == .none and func.resolved_error_set_extra_index == 0) { 2808 const bytes = asBytes(&func.owner_nav) ++ asBytes(&func.ty) ++ 2809 [1]u8{@intFromBool(func.uncoerced_ty == func.ty)}; 2810 return Hash.hash(seed, bytes); 2811 } 2812 2813 var hasher = Hash.init(seed); 2814 std.hash.autoHash(&hasher, func.generic_owner); 2815 std.hash.autoHash(&hasher, func.uncoerced_ty == func.ty); 2816 for (func.comptime_args.get(ip)) |arg| std.hash.autoHash(&hasher, arg); 2817 if (func.resolved_error_set_extra_index == 0) { 2818 std.hash.autoHash(&hasher, func.ty); 2819 } else { 2820 var ty_info = ip.indexToFuncType(func.ty).?; 2821 ty_info.return_type = ip.errorUnionPayload(ty_info.return_type); 2822 ty_info.hash(&hasher, ip); 2823 } 2824 return hasher.final(); 2825 }, 2826 2827 .@"extern" => |e| Hash.hash(seed, asBytes(&e.name) ++ 2828 asBytes(&e.ty) ++ asBytes(&e.lib_name) ++ 2829 asBytes(&e.linkage) ++ asBytes(&e.visibility) ++ 2830 asBytes(&e.is_threadlocal) ++ asBytes(&e.is_dll_import) ++ 2831 asBytes(&e.relocation) ++ 2832 asBytes(&e.is_const) ++ asBytes(&e.alignment) ++ asBytes(&e.@"addrspace") ++ 2833 asBytes(&e.zir_index) ++ &[1]u8{@backingInt(e.source)}), 2834 2835 .bitpack => |bitpack| Hash.hash(seed, asBytes(&bitpack.ty) ++ asBytes(&bitpack.backing_int_val)), 2836 }; 2837 } 2838 2839 pub fn eql(a: Key, b: Key, ip: *const InternPool) bool { 2840 const KeyTag = @typeInfo(Key).@"union".tag_type.?; 2841 const a_tag: KeyTag = a; 2842 const b_tag: KeyTag = b; 2843 if (a_tag != b_tag) return false; 2844 switch (a) { 2845 .int_type => |a_info| { 2846 const b_info = b.int_type; 2847 return std.meta.eql(a_info, b_info); 2848 }, 2849 .ptr_type => |a_info| { 2850 const b_info = b.ptr_type; 2851 return std.meta.eql(a_info, b_info); 2852 }, 2853 .array_type => |a_info| { 2854 const b_info = b.array_type; 2855 return std.meta.eql(a_info, b_info); 2856 }, 2857 .vector_type => |a_info| { 2858 const b_info = b.vector_type; 2859 return std.meta.eql(a_info, b_info); 2860 }, 2861 .opt_type => |a_info| { 2862 const b_info = b.opt_type; 2863 return a_info == b_info; 2864 }, 2865 .anyframe_type => |a_info| { 2866 const b_info = b.anyframe_type; 2867 return a_info == b_info; 2868 }, 2869 .error_union_type => |a_info| { 2870 const b_info = b.error_union_type; 2871 return std.meta.eql(a_info, b_info); 2872 }, 2873 .spirv_type => |a_info| { 2874 const b_info = b.spirv_type; 2875 return std.meta.eql(a_info, b_info); 2876 }, 2877 .simple_type => |a_info| { 2878 const b_info = b.simple_type; 2879 return a_info == b_info; 2880 }, 2881 .simple_value => |a_info| { 2882 const b_info = b.simple_value; 2883 return a_info == b_info; 2884 }, 2885 .undef => |a_info| { 2886 const b_info = b.undef; 2887 return a_info == b_info; 2888 }, 2889 .opt => |a_info| { 2890 const b_info = b.opt; 2891 return std.meta.eql(a_info, b_info); 2892 }, 2893 .un => |a_info| { 2894 const b_info = b.un; 2895 return std.meta.eql(a_info, b_info); 2896 }, 2897 .err => |a_info| { 2898 const b_info = b.err; 2899 return std.meta.eql(a_info, b_info); 2900 }, 2901 .error_union => |a_info| { 2902 const b_info = b.error_union; 2903 return std.meta.eql(a_info, b_info); 2904 }, 2905 .enum_literal => |a_info| { 2906 const b_info = b.enum_literal; 2907 return a_info == b_info; 2908 }, 2909 .enum_tag => |a_info| { 2910 const b_info = b.enum_tag; 2911 return std.meta.eql(a_info, b_info); 2912 }, 2913 .bitpack => |a_info| { 2914 const b_info = b.bitpack; 2915 return a_info.ty == b_info.ty and a_info.backing_int_val == b_info.backing_int_val; 2916 }, 2917 2918 .@"extern" => |a_info| { 2919 const b_info = b.@"extern"; 2920 return a_info.name == b_info.name and 2921 a_info.ty == b_info.ty and 2922 a_info.lib_name == b_info.lib_name and 2923 a_info.linkage == b_info.linkage and 2924 a_info.visibility == b_info.visibility and 2925 a_info.is_threadlocal == b_info.is_threadlocal and 2926 a_info.is_dll_import == b_info.is_dll_import and 2927 a_info.relocation == b_info.relocation and 2928 a_info.is_const == b_info.is_const and 2929 a_info.alignment == b_info.alignment and 2930 a_info.@"addrspace" == b_info.@"addrspace" and 2931 a_info.zir_index == b_info.zir_index and 2932 a_info.source == b_info.source; 2933 }, 2934 .func => |a_info| { 2935 const b_info = b.func; 2936 2937 if (a_info.generic_owner != b_info.generic_owner) 2938 return false; 2939 2940 if (a_info.generic_owner == .none) { 2941 if (a_info.owner_nav != b_info.owner_nav) 2942 return false; 2943 } else { 2944 if (!std.mem.eql( 2945 Index, 2946 a_info.comptime_args.get(ip), 2947 b_info.comptime_args.get(ip), 2948 )) return false; 2949 } 2950 2951 if ((a_info.ty == a_info.uncoerced_ty) != 2952 (b_info.ty == b_info.uncoerced_ty)) 2953 { 2954 return false; 2955 } 2956 2957 if (a_info.ty == b_info.ty) 2958 return true; 2959 2960 // There is one case where the types may be inequal but we 2961 // still want to find the same function body instance. In the 2962 // case of the functions having an inferred error set, the key 2963 // used to find an existing function body will necessarily have 2964 // a unique inferred error set type, because it refers to the 2965 // function body InternPool Index. To make this case work we 2966 // omit the inferred error set from the equality check. 2967 if (a_info.resolved_error_set_extra_index == 0 or 2968 b_info.resolved_error_set_extra_index == 0) 2969 { 2970 return false; 2971 } 2972 var a_ty_info = ip.indexToFuncType(a_info.ty).?; 2973 a_ty_info.return_type = ip.errorUnionPayload(a_ty_info.return_type); 2974 var b_ty_info = ip.indexToFuncType(b_info.ty).?; 2975 b_ty_info.return_type = ip.errorUnionPayload(b_ty_info.return_type); 2976 return a_ty_info.eql(b_ty_info, ip); 2977 }, 2978 2979 .slice => |a_info| { 2980 const b_info = b.slice; 2981 if (a_info.ty != b_info.ty) return false; 2982 if (a_info.ptr != b_info.ptr) return false; 2983 if (a_info.len != b_info.len) return false; 2984 return true; 2985 }, 2986 2987 .ptr => |a_info| { 2988 const b_info = b.ptr; 2989 if (a_info.ty != b_info.ty) return false; 2990 if (a_info.byte_offset != b_info.byte_offset) return false; 2991 if (!a_info.base_addr.eql(b_info.base_addr)) return false; 2992 return true; 2993 }, 2994 2995 .int => |a_info| { 2996 const b_info = b.int; 2997 2998 if (a_info.ty != b_info.ty) 2999 return false; 3000 3001 return switch (a_info.storage) { 3002 .u64 => |aa| switch (b_info.storage) { 3003 .u64 => |bb| aa == bb, 3004 .i64 => |bb| aa == bb, 3005 .big_int => |bb| bb.orderAgainstScalar(aa) == .eq, 3006 }, 3007 .i64 => |aa| switch (b_info.storage) { 3008 .u64 => |bb| aa == bb, 3009 .i64 => |bb| aa == bb, 3010 .big_int => |bb| bb.orderAgainstScalar(aa) == .eq, 3011 }, 3012 .big_int => |aa| switch (b_info.storage) { 3013 .u64 => |bb| aa.orderAgainstScalar(bb) == .eq, 3014 .i64 => |bb| aa.orderAgainstScalar(bb) == .eq, 3015 .big_int => |bb| aa.eql(bb), 3016 }, 3017 }; 3018 }, 3019 3020 .float => |a_info| { 3021 const b_info = b.float; 3022 3023 if (a_info.ty != b_info.ty) 3024 return false; 3025 3026 if (a_info.ty == .c_longdouble_type and a_info.storage != .f80) { 3027 // These are strange: we'll sometimes represent them as f128, even if the 3028 // underlying type is smaller. f80 is an exception: see float_c_longdouble_f80. 3029 const a_val: u128 = switch (a_info.storage) { 3030 inline else => |val| @bitCast(@as(f128, @floatCast(val))), 3031 }; 3032 const b_val: u128 = switch (b_info.storage) { 3033 inline else => |val| @bitCast(@as(f128, @floatCast(val))), 3034 }; 3035 return a_val == b_val; 3036 } 3037 3038 const StorageTag = @typeInfo(Key.Float.Storage).@"union".tag_type.?; 3039 assert(@as(StorageTag, a_info.storage) == @as(StorageTag, b_info.storage)); 3040 3041 switch (a_info.storage) { 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 };