╭─────────────╮╭────────────╮ │scroll to top││next lines →│ ╰─────────────╯╰────────────╯ ╭ Sema.zig ─────────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭ find file ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ ╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │ │ │http│ ssh │ │ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
331 if (better_start <= start and end < better_capacity + better_start) 332 break; 333 } 334 335 const start_diff = old_start - better_start; 336 const new_items = try allocator.alloc(Air.Inst.Ref, better_capacity); 337 @memset(new_items[0..start_diff], .none); 338 @memcpy(new_items[start_diff..][0..map.items.len], map.items); 339 @memset(new_items[start_diff + map.items.len ..], .none); 340 341 allocator.free(map.items); 342 map.items = new_items; 343 map.start = @fromBackingInt(@intCast(better_start)); 344 } 345 }; 346 347 /// This is the context needed to semantically analyze ZIR instructions and 348 /// produce AIR instructions. 349 /// This is a temporary structure stored on the stack; references to it are valid only 350 /// during semantic analysis of the block. 351 pub const Block = struct { 352 parent: ?*Block, 353 /// Shared among all child blocks. 354 sema: *Sema, 355 /// The namespace to use for lookups from this source block 356 namespace: InternPool.NamespaceIndex, 357 /// The AIR instructions generated for this block. 358 instructions: std.ArrayList(Air.Inst.Index), 359 // `param` instructions are collected here to be used by the `func` instruction. 360 /// When doing a generic function instantiation, this array collects a type 361 /// for each *runtime-known* parameter. This array corresponds to the instance 362 /// function type, while `Sema.comptime_args` corresponds to the generic owner 363 /// function type. 364 /// This memory is allocated by a parent `Sema` in the temporary arena, and is 365 /// used to add a `func_instance` into the `InternPool`. 366 params: std.MultiArrayList(Param) = .{}, 367 368 label: ?*Label = null, 369 inlining: ?*Inlining, 370 /// If runtime_index is not 0 then one of these is guaranteed to be non null. 371 runtime_cond: ?LazySrcLoc = null, 372 runtime_loop: ?LazySrcLoc = null, 373 /// Non zero if a non-inline loop or a runtime conditional have been encountered. 374 /// Stores to comptime variables are only allowed when var.runtime_index <= runtime_index. 375 runtime_index: RuntimeIndex = .zero, 376 inline_block: Zir.Inst.OptionalIndex = .none, 377 378 comptime_reason: ?BlockComptimeReason = null, 379 is_typeof: bool = false, 380 381 /// Keep track of the active error return trace index around blocks so that we can correctly 382 /// pop the error trace upon block exit. 383 error_return_trace_index: Air.Inst.Ref = .none, 384 385 /// when null, it is determined by the owner modules build mode, changed by @setRuntimeSafety 386 want_safety: ?bool = null, 387 388 /// What mode to generate float operations in, set by @setFloatMode 389 float_mode: std.lang.FloatMode = .strict, 390 391 /// If not `null`, this boolean is set when a `dbg_var_ptr`, `dbg_var_val`, or `dbg_arg_inline`. 392 /// instruction is emitted. It signals that the innermost lexically 393 /// enclosing `block`/`block_inline` should be translated into a real AIR 394 /// `block` in order for codegen to match lexical scoping for debug vars. 395 need_debug_scope: ?*bool = null, 396 397 /// Relative source locations encountered while traversing this block should be 398 /// treated as relative to the AST node of this ZIR instruction. 399 src_base_inst: InternPool.TrackedInst.Index, 400 401 /// The name of the current "context" for naming namespace types. 402 /// The interpretation of this depends on the name strategy in ZIR, but the name 403 /// is always incorporated into the type name somehow. 404 /// See `Sema.setTypeName`. 405 type_name_ctx: InternPool.NullTerminatedString, 406 type_fqn_ctx: InternPool.NullTerminatedString, 407 408 /// Create a `LazySrcLoc` based on an `Offset` from the code being analyzed in this block. 409 /// Specifically, the given `Offset` is treated as relative to `block.src_base_inst`. 410 pub fn src(block: Block, offset: LazySrcLoc.Offset) LazySrcLoc { 411 return .{ 412 .base_node_inst = block.src_base_inst, 413 .offset = offset, 414 }; 415 } 416 417 fn isComptime(block: Block) bool { 418 return block.comptime_reason != null; 419 } 420 421 pub fn builtinCallArgSrc(block: *Block, builtin_call_node: std.zig.Ast.Node.Offset, arg_index: u32) LazySrcLoc { 422 return block.src(.{ .node_offset_builtin_call_arg = .{ 423 .builtin_call_node = builtin_call_node, 424 .arg_index = arg_index, 425 } }); 426 } 427 428 pub fn nodeOffset(block: Block, node_offset: std.zig.Ast.Node.Offset) LazySrcLoc { 429 return block.src(LazySrcLoc.Offset.nodeOffset(node_offset)); 430 } 431 432 fn tokenOffset(block: Block, tok_offset: std.zig.Ast.TokenOffset) LazySrcLoc { 433 return block.src(.{ .token_offset = tok_offset }); 434 } 435 436 const Param = struct { 437 /// `none` means `anytype`. 438 ty: InternPool.Index, 439 is_comptime: bool, 440 name: Zir.NullTerminatedString, 441 }; 442 443 /// This `Block` maps a block ZIR instruction to the corresponding 444 /// AIR instruction for break instruction analysis. 445 pub const Label = struct { 446 zir_block: Zir.Inst.Index, 447 merges: Merges, 448 }; 449 450 /// This `Block` indicates that an inline function call is happening 451 /// and return instructions should be analyzed as a break instruction 452 /// to this AIR block instruction. 453 /// It is shared among all the blocks in an inline or comptime called 454 /// function. 455 pub const Inlining = struct { 456 call_block: *Block, 457 call_src: LazySrcLoc, 458 func: InternPool.Index, 459 460 /// Populated lazily by `refFrame`. 461 ref_frame: Zcu.InlineReferenceFrame.Index.Optional = .none, 462 463 /// If `true`, the following fields are `undefined`. This doesn't represent a true inline 464 /// call, but rather a generic call analyzing the instantiation's generic type bodies. 465 is_generic_instantiation: bool, 466 467 has_comptime_args: bool, 468 comptime_result: Air.Inst.Ref, 469 merges: Merges, 470 471 fn refFrame(inlining: *Inlining, zcu: *Zcu) Allocator.Error!Zcu.InlineReferenceFrame.Index { 472 if (inlining.ref_frame == .none) { 473 inlining.ref_frame = (try zcu.addInlineReferenceFrame(.{ 474 .callee = inlining.func, 475 .call_src = inlining.call_src, 476 .parent = if (inlining.call_block.inlining) |parent_inlining| p: { 477 break :p (try parent_inlining.refFrame(zcu)).toOptional(); 478 } else .none, 479 })).toOptional(); 480 } 481 return inlining.ref_frame.unwrap().?; 482 } 483 }; 484 485 pub const Merges = struct { 486 block_inst: Air.Inst.Index, 487 /// Separate array list from break_inst_list so that it can be passed directly 488 /// to resolvePeerTypes. 489 results: std.ArrayList(Air.Inst.Ref), 490 /// Keeps track of the break instructions so that the operand can be replaced 491 /// if we need to add type coercion at the end of block analysis. 492 /// Same indexes, capacity, length as `results`. 493 br_list: std.ArrayList(Air.Inst.Index), 494 /// Keeps the source location of the rhs operand of the break instruction, 495 /// to enable more precise compile errors. 496 /// Same indexes, capacity, length as `results`. 497 src_locs: std.ArrayList(?LazySrcLoc), 498 /// Most blocks do not utilize this field. When it is used, its use is 499 /// contextual. The possible uses are as follows: 500 /// * for a `switch_block[_ref]`, this refers to dummy `br` instructions 501 /// which correspond to `switch_continue` ZIR. The switch logic will 502 /// rewrite these to appropriate AIR switch dispatches. 503 extra_insts: std.ArrayList(Air.Inst.Index) = .empty, 504 /// Same indexes, capacity, length as `extra_insts`. 505 extra_src_locs: std.ArrayList(LazySrcLoc) = .empty, 506 507 pub fn deinit(merges: *@This(), allocator: Allocator) void { 508 merges.results.deinit(allocator); 509 merges.br_list.deinit(allocator); 510 merges.src_locs.deinit(allocator); 511 merges.extra_insts.deinit(allocator); 512 merges.extra_src_locs.deinit(allocator); 513 } 514 }; 515 516 pub fn makeSubBlock(parent: *Block) Block { 517 return .{ 518 .parent = parent, 519 .sema = parent.sema, 520 .namespace = parent.namespace, 521 .instructions = .empty, 522 .label = null, 523 .inlining = parent.inlining, 524 .comptime_reason = parent.comptime_reason, 525 .is_typeof = parent.is_typeof, 526 .runtime_cond = parent.runtime_cond, 527 .runtime_loop = parent.runtime_loop, 528 .runtime_index = parent.runtime_index, 529 .want_safety = parent.want_safety, 530 .float_mode = parent.float_mode, 531 .error_return_trace_index = parent.error_return_trace_index, 532 .need_debug_scope = parent.need_debug_scope, 533 .src_base_inst = parent.src_base_inst, 534 .type_name_ctx = parent.type_name_ctx, 535 .type_fqn_ctx = parent.type_fqn_ctx, 536 }; 537 } 538 539 fn wantSafeTypes(block: *const Block) bool { 540 return block.want_safety orelse switch (block.ownerModule().optimize_mode) { 541 .debug => true, 542 .safe => true, 543 .fast => false, 544 .small => false, 545 }; 546 } 547 548 fn wantSafety(block: *const Block) bool { 549 if (block.isComptime()) return false; // runtime safety checks are pointless in comptime blocks 550 return block.want_safety orelse switch (block.ownerModule().optimize_mode) { 551 .debug => true, 552 .safe => true, 553 .fast => false, 554 .small => false, 555 }; 556 } 557 558 pub fn getFileScope(block: *Block, zcu: *Zcu) *Zcu.File { 559 return zcu.fileByIndex(getFileScopeIndex(block, zcu)); 560 } 561 562 pub fn getFileScopeIndex(block: *Block, zcu: *Zcu) Zcu.File.Index { 563 return zcu.namespacePtr(block.namespace).file_scope; 564 } 565 566 fn addTy( 567 block: *Block, 568 tag: Air.Inst.Tag, 569 ty: Type, 570 ) error{OutOfMemory}!Air.Inst.Ref { 571 return block.addInst(.{ 572 .tag = tag, 573 .data = .{ .ty = ty }, 574 }); 575 } 576 577 fn addTyOp( 578 block: *Block, 579 tag: Air.Inst.Tag, 580 ty: Type, 581 operand: Air.Inst.Ref, 582 ) error{OutOfMemory}!Air.Inst.Ref { 583 return block.addInst(.{ 584 .tag = tag, 585 .data = .{ .ty_op = .{ 586 .ty = ty, 587 .operand = operand, 588 } }, 589 }); 590 } 591 592 fn addNoOp(block: *Block, tag: Air.Inst.Tag) error{OutOfMemory}!Air.Inst.Ref { 593 return block.addInst(.{ 594 .tag = tag, 595 .data = .{ .no_op = {} }, 596 }); 597 } 598 599 fn addUnOp( 600 block: *Block, 601 tag: Air.Inst.Tag, 602 operand: Air.Inst.Ref, 603 ) error{OutOfMemory}!Air.Inst.Ref { 604 return block.addInst(.{ 605 .tag = tag, 606 .data = .{ .un_op = operand }, 607 }); 608 } 609 610 fn addBr( 611 block: *Block, 612 target_block: Air.Inst.Index, 613 operand: Air.Inst.Ref, 614 ) error{OutOfMemory}!Air.Inst.Ref { 615 return block.addInst(.{ 616 .tag = .br, 617 .data = .{ .br = .{ 618 .block_inst = target_block, 619 .operand = operand, 620 } }, 621 }); 622 } 623 624 fn addBinOp( 625 block: *Block, 626 tag: Air.Inst.Tag, 627 lhs: Air.Inst.Ref, 628 rhs: Air.Inst.Ref, 629 ) error{OutOfMemory}!Air.Inst.Ref { 630 return block.addInst(.{ 631 .tag = tag, 632 .data = .{ .bin_op = .{ 633 .lhs = lhs, 634 .rhs = rhs, 635 } }, 636 }); 637 } 638 639 fn addStructFieldPtr( 640 block: *Block, 641 struct_ptr: Air.Inst.Ref, 642 field_index: u32, 643 ptr_field_ty: Type, 644 ) !Air.Inst.Ref { 645 const tag: Air.Inst.Tag = switch (field_index) { 646 0 => .struct_field_ptr_index_0, 647 1 => .struct_field_ptr_index_1, 648 2 => .struct_field_ptr_index_2, 649 3 => .struct_field_ptr_index_3, 650 else => { 651 return block.addInst(.{ 652 .tag = .struct_field_ptr, 653 .data = .{ .ty_pl = .{ 654 .ty = ptr_field_ty, 655 .payload = try block.sema.addExtra(Air.StructField{ 656 .struct_operand = struct_ptr, 657 .field_index = field_index, 658 }), 659 } }, 660 }); 661 }, 662 }; 663 return block.addInst(.{ 664 .tag = tag, 665 .data = .{ .ty_op = .{ 666 .ty = ptr_field_ty, 667 .operand = struct_ptr, 668 } }, 669 }); 670 } 671 672 fn addStructFieldVal( 673 block: *Block, 674 struct_val: Air.Inst.Ref, 675 field_index: u32, 676 field_ty: Type, 677 ) !Air.Inst.Ref { 678 return block.addInst(.{ 679 .tag = .agg_field_val, 680 .data = .{ .ty_pl = .{ 681 .ty = field_ty, 682 .payload = try block.sema.addExtra(Air.StructField{ 683 .struct_operand = struct_val, 684 .field_index = field_index, 685 }), 686 } }, 687 }); 688 } 689 690 fn addSliceElemPtr( 691 block: *Block, 692 slice: Air.Inst.Ref, 693 elem_index: Air.Inst.Ref, 694 elem_ptr_ty: Type, 695 ) !Air.Inst.Ref { 696 return block.addInst(.{ 697 .tag = .slice_elem_ptr, 698 .data = .{ .ty_pl = .{ 699 .ty = elem_ptr_ty, 700 .payload = try block.sema.addExtra(Air.Bin{ 701 .lhs = slice, 702 .rhs = elem_index, 703 }), 704 } }, 705 }); 706 } 707 708 fn addPtrElemPtr( 709 block: *Block, 710 array_ptr: Air.Inst.Ref, 711 elem_index: Air.Inst.Ref, 712 elem_ptr_ty: Type, 713 ) !Air.Inst.Ref { 714 return block.addInst(.{ 715 .tag = .ptr_elem_ptr, 716 .data = .{ .ty_pl = .{ 717 .ty = elem_ptr_ty, 718 .payload = try block.sema.addExtra(Air.Bin{ 719 .lhs = array_ptr, 720 .rhs = elem_index, 721 }), 722 } }, 723 }); 724 } 725 726 fn addCmpVector(block: *Block, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref, cmp_op: std.math.CompareOperator) !Air.Inst.Ref { 727 const sema = block.sema; 728 const pt = sema.pt; 729 const zcu = pt.zcu; 730 return block.addInst(.{ 731 .tag = if (block.float_mode == .optimized) .cmp_vector_optimized else .cmp_vector, 732 .data = .{ .ty_pl = .{ 733 .ty = (try pt.vectorType(.{ 734 .len = sema.typeOf(lhs).vectorLen(zcu), 735 .child = .bool_type, 736 })), 737 .payload = try sema.addExtra(Air.VectorCmp{ 738 .lhs = lhs, 739 .rhs = rhs, 740 .op = Air.VectorCmp.encodeOp(cmp_op), 741 }), 742 } }, 743 }); 744 } 745 746 fn addReduce(block: *Block, operand: Air.Inst.Ref, operation: std.lang.ReduceOp) !Air.Inst.Ref { 747 const sema = block.sema; 748 const zcu = sema.pt.zcu; 749 const allow_optimized = switch (sema.typeOf(operand).childType(zcu).zigTypeTag(zcu)) { 750 .float => true, 751 .bool, .int => false, 752 else => unreachable, 753 }; 754 return block.addInst(.{ 755 .tag = if (allow_optimized and block.float_mode == .optimized) .reduce_optimized else .reduce, 756 .data = .{ .reduce = .{ 757 .operand = operand, 758 .operation = operation, 759 } }, 760 }); 761 } 762 763 fn addAggregateInit( 764 block: *Block, 765 aggregate_ty: Type, 766 elements: []const Air.Inst.Ref, 767 ) !Air.Inst.Ref { 768 const sema = block.sema; 769 try sema.air_extra.ensureUnusedCapacity(sema.gpa, elements.len); 770 const extra_index: u32 = @intCast(sema.air_extra.items.len); 771 sema.appendRefsAssumeCapacity(elements); 772 773 return block.addInst(.{ 774 .tag = .aggregate_init, 775 .data = .{ .ty_pl = .{ 776 .ty = aggregate_ty, 777 .payload = extra_index, 778 } }, 779 }); 780 } 781 782 fn addUnionInit( 783 block: *Block, 784 union_ty: Type, 785 field_index: u32, 786 init: Air.Inst.Ref, 787 ) !Air.Inst.Ref { 788 return block.addInst(.{ 789 .tag = .union_init, 790 .data = .{ .ty_pl = .{ 791 .ty = union_ty, 792 .payload = try block.sema.addExtra(Air.UnionInit{ 793 .field_index = field_index, 794 .init = init, 795 }), 796 } }, 797 }); 798 } 799 800 pub fn addInst(block: *Block, inst: Air.Inst) error{OutOfMemory}!Air.Inst.Ref { 801 return (try block.addInstAsIndex(inst)).toRef(); 802 } 803 804 pub fn addInstAsIndex(block: *Block, inst: Air.Inst) error{OutOfMemory}!Air.Inst.Index { 805 const sema = block.sema; 806 const gpa = sema.gpa; 807 808 try sema.air_instructions.ensureUnusedCapacity(gpa, 1); 809 try block.instructions.ensureUnusedCapacity(gpa, 1); 810 811 const result_index: Air.Inst.Index = @fromBackingInt(@intCast(sema.air_instructions.len)); 812 sema.air_instructions.appendAssumeCapacity(inst); 813 block.instructions.appendAssumeCapacity(result_index); 814 return result_index; 815 } 816 817 /// Insert an instruction into the block at `index`. Moves all following 818 /// instructions forward in the block to make room. Operation is O(N). 819 pub fn insertInst(block: *Block, index: Air.Inst.Index, inst: Air.Inst) error{OutOfMemory}!Air.Inst.Ref { 820 return (try block.insertInstAsIndex(index, inst)).toRef(); 821 } 822 823 pub fn insertInstAsIndex(block: *Block, index: Air.Inst.Index, inst: Air.Inst) error{OutOfMemory}!Air.Inst.Index { 824 const sema = block.sema; 825 const gpa = sema.gpa; 826 827 try sema.air_instructions.ensureUnusedCapacity(gpa, 1); 828 829 const result_index: Air.Inst.Index = @fromBackingInt(@intCast(sema.air_instructions.len)); 830 sema.air_instructions.appendAssumeCapacity(inst); 831 832 try block.instructions.insert(gpa, @backingInt(index), result_index); 833 return result_index; 834 } 835 836 pub fn ownerModule(block: Block) *Module { 837 const zcu = block.sema.pt.zcu; 838 return zcu.namespacePtr(block.namespace).fileScope(zcu).mod.?; 839 } 840 841 fn trackZir(block: *Block, inst: Zir.Inst.Index) Allocator.Error!InternPool.TrackedInst.Index { 842 const pt = block.sema.pt; 843 const comp = pt.zcu.comp; 844 block.sema.code.assertTrackable(inst); 845 return pt.zcu.intern_pool.trackZir(comp.gpa, comp.io, pt.tid, .{ 846 .file = block.getFileScopeIndex(pt.zcu), 847 .inst = inst, 848 }); 849 } 850 851 /// Returns the `*Block` that should be passed to `Sema.failWithOwnedErrorMsg`, because all inline 852 /// calls below it have already been reported with "called at comptime from here" notes. 853 fn explainWhyBlockIsComptime(start_block: *Block, err_msg: *Zcu.ErrorMsg) !*Block { 854 const sema = start_block.sema; 855 var block = start_block; 856 while (true) { 857 switch (block.comptime_reason.?) { 858 .inlining_parent => { 859 const inlining = block.inlining.?; 860 try sema.errNote(inlining.call_src, err_msg, "called at comptime from here", .{}); 861 block = inlining.call_block; 862 }, 863 .reason => |r| { 864 try r.r.explain(sema, r.src, err_msg); 865 return block; 866 }, 867 } 868 } 869 } 870 }; 871 872 /// Represents the reason we are resolving a value or evaluating code at comptime. 873 /// Most reasons are represented by a `std.zig.SimpleComptimeReason`, which provides a plain message. 874 const ComptimeReason = union(enum) { 875 /// Evaluating at comptime for a reason in the `std.zig.SimpleComptimeReason` enum. 876 simple: std.zig.SimpleComptimeReason, 877 878 /// Evaluating at comptime because of a comptime-only type. This field is separate so that 879 /// the type in question can be included in the error message. AstGen could never emit this 880 /// reason, because it knows nothing of types. 881 /// The format string looks like "foo '{f}' bar", where "{f}" is the comptime-only type. 882 /// We will then explain why this type is comptime-only. 883 comptime_only: struct { 884 ty: Type, 885 msg: enum { 886 union_init, 887 struct_init, 888 tuple_init, 889 }, 890 }, 891 892 /// Like `comptime_only`, but for a parameter type. 893 /// Includes a "parameter type declared here" note. 894 comptime_only_param_ty: struct { 895 ty: Type, 896 param_ty_src: LazySrcLoc, 897 }, 898 899 /// Like `comptime_only`, but for a return type. 900 /// Includes a "return type declared here" note. 901 comptime_only_ret_ty: struct { 902 ty: Type, 903 is_generic_inst: bool, 904 ret_ty_src: LazySrcLoc, 905 }, 906 907 /// Evaluating at comptime because we're evaluating an argument to a parameter marked `comptime`. 908 comptime_param: struct { 909 comptime_src: LazySrcLoc, 910 }, 911 912 fn explain(reason: ComptimeReason, sema: *Sema, src: LazySrcLoc, err_msg: *Zcu.ErrorMsg) !void { 913 switch (reason) { 914 .simple => |simple| { 915 try sema.errNote(src, err_msg, "{s}", .{simple.message()}); 916 }, 917 .comptime_only => |co| { 918 const pre, const post = switch (co.msg) { 919 .union_init => .{ "initializer of comptime-only union", "must be comptime-known" }, 920 .struct_init => .{ "initializer of comptime-only struct", "must be comptime-known" }, 921 .tuple_init => .{ "initializer of comptime-only tuple", "must be comptime-known" }, 922 }; 923 try sema.errNote(src, err_msg, "{s} '{f}' {s}", .{ pre, co.ty.fmt(sema.pt), post }); 924 try sema.explainWhyTypeIsComptime(err_msg, src, co.ty); 925 }, 926 .comptime_only_param_ty => |co| { 927 try sema.errNote(src, err_msg, "argument to parameter with comptime-only type '{f}' must be comptime-known", .{co.ty.fmt(sema.pt)}); 928 try sema.errNote(co.param_ty_src, err_msg, "parameter type declared here", .{}); 929 try sema.explainWhyTypeIsComptime(err_msg, src, co.ty); 930 }, 931 .comptime_only_ret_ty => |co| { 932 const function_with: []const u8 = if (co.is_generic_inst) "generic function instantiated with" else "function with"; 933 try sema.errNote(src, err_msg, "call to {s} comptime-only return type '{f}' is evaluated at comptime", .{ function_with, co.ty.fmt(sema.pt) }); 934 try sema.errNote(co.ret_ty_src, err_msg, "return type declared here", .{}); 935 try sema.explainWhyTypeIsComptime(err_msg, src, co.ty); 936 }, 937 .comptime_param => |cp| { 938 try sema.errNote(src, err_msg, "argument to comptime parameter must be comptime-known", .{}); 939 try sema.errNote(cp.comptime_src, err_msg, "parameter declared comptime here", .{}); 940 }, 941 } 942 } 943 }; 944 945 /// Represents the reason a `Block` is being evaluated at comptime. 946 const BlockComptimeReason = union(enum) { 947 /// This block inherits being comptime-only from the `inlining` call site. 948 inlining_parent, 949 950 /// Comptime evaluation began somewhere in the current function for a given `ComptimeReason`. 951 reason: struct { 952 /// The source location which this reason originates from. `r` is reported here. 953 src: LazySrcLoc, 954 r: ComptimeReason, 955 }, 956 }; 957 958 const LabeledBlock = struct { 959 block: Block, 960 label: Block.Label, 961 962 fn destroy(lb: *LabeledBlock, gpa: Allocator) void { 963 lb.block.instructions.deinit(gpa); 964 lb.label.merges.deinit(gpa); 965 gpa.destroy(lb); 966 } 967 }; 968 969 /// The value stored in the inferred allocation. This will go into 970 /// peer type resolution. This is stored in a separate list so that 971 /// the items are contiguous in memory and thus can be passed to 972 /// `Zcu.resolvePeerTypes`. 973 const InferredAlloc = struct { 974 /// The placeholder `store` instructions used before the result pointer type 975 /// is known. These should be rewritten to perform any required coercions 976 /// when the type is resolved. 977 /// Allocated from `sema.arena`. 978 prongs: std.ArrayList(Air.Inst.Index) = .empty, 979 }; 980 981 pub fn deinit(sema: *Sema) void { 982 const gpa = sema.gpa; 983 sema.air_instructions.deinit(gpa); 984 sema.air_extra.deinit(gpa); 985 sema.inst_map.deinit(gpa); 986 { 987 var it = sema.post_hoc_blocks.iterator(); 988 while (it.next()) |entry| { 989 const labeled_block = entry.value_ptr.*; 990 labeled_block.destroy(gpa); 991 } 992 sema.post_hoc_blocks.deinit(gpa); 993 } 994 sema.unresolved_inferred_allocs.deinit(gpa); 995 sema.base_allocs.deinit(gpa); 996 sema.maybe_comptime_allocs.deinit(gpa); 997 sema.comptime_allocs.deinit(gpa); 998 sema.exports.deinit(gpa); 999 sema.references.deinit(gpa); 1000 sema.type_references.deinit(gpa); 1001 sema.dependencies.deinit(gpa); 1002 sema.* = undefined; 1003 } 1004 1005 /// Performs semantic analysis of a ZIR body which is behind a runtime condition. If comptime 1006 /// control flow happens here, Sema will convert it to runtime control flow by introducing post-hoc 1007 /// blocks where necessary. 1008 /// Returns the branch hint for this branch. 1009 fn analyzeBodyRuntimeBreak(sema: *Sema, block: *Block, body: []const Zir.Inst.Index) !std.lang.BranchHint { 1010 const parent_hint = sema.branch_hint; 1011 defer sema.branch_hint = parent_hint; 1012 sema.branch_hint = null; 1013 1014 sema.analyzeBodyInner(block, body) catch |err| switch (err) { 1015 error.ComptimeBreak => { 1016 const zir_datas = sema.code.instructions.items(.data); 1017 const break_data = zir_datas[@backingInt(sema.comptime_break_inst)].@"break"; 1018 const extra = sema.code.extraData(Zir.Inst.Break, break_data.payload_index).data; 1019 try sema.addRuntimeBreak(block, extra.block_inst, break_data.operand); 1020 }, 1021 else => |e| return e, 1022 }; 1023 1024 return sema.branch_hint orelse .none; 1025 } 1026 1027 /// Semantically analyze a ZIR function body. It is guaranteed by AstGen that such a body cannot 1028 /// trigger comptime control flow to move above the function body. 1029 pub fn analyzeFnBody( 1030 sema: *Sema, 1031 block: *Block, 1032 body: []const Zir.Inst.Index, 1033 ) !void { 1034 sema.analyzeBodyInner(block, body) catch |err| switch (err) { 1035 error.ComptimeBreak => unreachable, // unexpected comptime control flow 1036 else => |e| return e, 1037 }; 1038 } 1039 1040 /// Given a ZIR body which can be exited via a `break_inline` instruction, or a non-inline body which 1041 /// we are evaluating at comptime, semantically analyze the body and return the result from it. 1042 /// Returns `null` if control flow did not break from this block, but instead terminated with some 1043 /// other runtime noreturn instruction. Compile-time breaks to blocks further up the stack still 1044 /// return `error.ComptimeBreak`. If `block.isComptime()`, this function will never return `null`. 1045 fn analyzeInlineBody( 1046 sema: *Sema, 1047 block: *Block, 1048 body: []const Zir.Inst.Index, 1049 /// The index which a break instruction can target to break from this body. 1050 break_target: Zir.Inst.Index, 1051 ) CompileError!?Air.Inst.Ref { 1052 if (sema.analyzeBodyInner(block, body)) { 1053 return null; 1054 } else |err| switch (err) { 1055 error.ComptimeBreak => {}, 1056 else => |e| return e, 1057 } 1058 const break_inst = sema.code.instructions.get(@backingInt(sema.comptime_break_inst)); 1059 switch (break_inst.tag) { 1060 .switch_continue => { 1061 // This is handled by separate logic. 1062 return error.ComptimeBreak; 1063 }, 1064 .break_inline, .@"break" => {}, 1065 else => unreachable, 1066 } 1067 const extra = sema.code.extraData(Zir.Inst.Break, break_inst.data.@"break".payload_index).data; 1068 if (extra.block_inst != break_target) { 1069 // This control flow goes further up the stack. 1070 return error.ComptimeBreak; 1071 } 1072 return sema.resolveInst(break_inst.data.@"break".operand); 1073 } 1074 1075 /// Like `analyzeInlineBody`, but if the body does not break with a value, returns 1076 /// `.unreachable_value` instead of `null`. Notably, use this to evaluate an arbitrary 1077 /// body at comptime to a single result value. 1078 pub fn resolveInlineBody( 1079 sema: *Sema, 1080 block: *Block, 1081 body: []const Zir.Inst.Index, 1082 /// The index which a break instruction can target to break from this body. 1083 break_target: Zir.Inst.Index, 1084 ) CompileError!Air.Inst.Ref { 1085 return (try sema.analyzeInlineBody(block, body, break_target)) orelse .unreachable_value; 1086 } 1087 1088 /// This function is the main loop of `Sema`. It analyzes a single body of ZIR instructions. 1089 /// 1090 /// If this function returns normally, the merges of `block` were populated with all possible 1091 /// (runtime) results of this block. Peer type resolution should be performed on the result, 1092 /// and relevant runtime instructions written to perform necessary coercions and breaks. See 1093 /// `resolveAnalyzedBlock`. This form of return is impossible if `block.isComptime()`. 1094 /// 1095 /// Alternatively, this function may return `error.ComptimeBreak`. This indicates that comptime 1096 /// control flow is happening, and we are breaking at comptime from a block indicated by the 1097 /// break instruction in `sema.comptime_break_inst`. This occurs for any `break_inline`, or for a 1098 /// standard `break` at comptime. This error is pushed up the stack until the target block is 1099 /// reached, at which point the break operand will be fetched. 1100 /// 1101 /// It is rare to call this function directly. Usually, you want one of the following wrappers: 1102 /// * If the body is exited via a `break_inline`, or is being evaluated at comptime, 1103 /// use `Sema.analyzeInlineBody` or `Sema.resolveInlineBody`. 1104 /// * If the body is behind a fresh runtime condition, use `Sema.analyzeBodyRuntimeBreak`. 1105 /// * If the body is an entire function body, use `Sema.analyzeFnBody`. 1106 /// * If the body is to be generated into an AIR `block`, use `Sema.resolveBlockBody`. 1107 /// * Otherwise, direct usage of `Sema.analyzeBodyInner` may be necessary. 1108 fn analyzeBodyInner( 1109 sema: *Sema, 1110 block: *Block, 1111 body: []const Zir.Inst.Index, 1112 ) CompileError!void { 1113 try sema.inst_map.ensureSpaceForInstructions(sema.gpa, body); 1114 1115 const pt = sema.pt; 1116 const zcu = pt.zcu; 1117 const map = &sema.inst_map; 1118 const tags = sema.code.instructions.items(.tag); 1119 const datas = sema.code.instructions.items(.data); 1120 1121 var crash_info: crash_report.AnalyzeBody = undefined; 1122 crash_info.push(sema, block, body); 1123 defer crash_info.pop(); 1124 1125 // We use a while (true) loop here to avoid a redundant way of breaking out of 1126 // the loop. The only way to break out of the loop is with a `noreturn` 1127 // instruction. 1128 var i: u32 = 0; 1129 while (true) { 1130 crash_info.setBodyIndex(i); 1131 const inst = body[i]; 1132 1133 // The hashmap lookup in here is a little expensive, and LLVM fails to optimize it away. 1134 if (build_options.enable_logging) { 1135 std.log.scoped(.sema_zir).debug("sema ZIR {f} %{d}", .{ path: { 1136 const file_index = block.src_base_inst.resolveFile(&zcu.intern_pool); 1137 const file = zcu.fileByIndex(file_index); 1138 break :path file.path.fmt(zcu.comp); 1139 }, inst }); 1140 } 1141 1142 const air_ref: Air.Inst.Ref = inst: switch (tags[@backingInt(inst)]) { 1143 // zig fmt: off 1144 .alloc => try sema.zirAlloc(block, inst), 1145 .alloc_inferred => try sema.zirAllocInferred(block, true), 1146 .alloc_inferred_mut => try sema.zirAllocInferred(block, false), 1147 .alloc_inferred_comptime => try sema.zirAllocInferredComptime(true), 1148 .alloc_inferred_comptime_mut => try sema.zirAllocInferredComptime(false), 1149 .resolve_inferred_alloc => try sema.zirResolveInferredAlloc(block, inst), 1150 .alloc_mut => try sema.zirAllocMut(block, inst), 1151 .alloc_comptime_mut => try sema.zirAllocComptime(block, inst), 1152 .make_ptr_const => try sema.zirMakePtrConst(block, inst), 1153 .anyframe_type => try sema.zirAnyframeType(block, inst), 1154 .array_cat => try sema.zirArrayCat(block, inst), 1155 .array_type => try sema.zirArrayType(block, inst), 1156 .array_type_sentinel => try sema.zirArrayTypeSentinel(block, inst), 1157 .reify_int => try sema.zirReifyInt(block, inst), 1158 .vector_type => try sema.zirVectorType(block, inst), 1159 .as_node => try sema.zirAsNode(block, inst), 1160 .as_shift_operand => try sema.zirAsShiftOperand(block, inst), 1161 .bit_and => try sema.zirBitwise(block, inst, .bit_and), 1162 .bit_not => try sema.zirBitNot(block, inst), 1163 .bit_or => try sema.zirBitwise(block, inst, .bit_or), 1164 .bitcast => try sema.zirBitcast(block, inst), 1165 .suspend_block => try sema.zirSuspendBlock(block, inst), 1166 .bool_not => try sema.zirBoolNot(block, inst), 1167 .bool_br_and => try sema.zirBoolBr(block, inst, false), 1168 .bool_br_or => try sema.zirBoolBr(block, inst, true), 1169 .call => try sema.zirCall(block, inst, .direct), 1170 .field_call => try sema.zirCall(block, inst, .field), 1171 .cmp_lt => try sema.zirCmp(block, inst, .lt), 1172 .cmp_lte => try sema.zirCmp(block, inst, .lte), 1173 .cmp_eq => try sema.zirCmpEq(block, inst, .eq, Air.Inst.Tag.fromCmpOp(.eq, block.float_mode == .optimized)), 1174 .cmp_gte => try sema.zirCmp(block, inst, .gte), 1175 .cmp_gt => try sema.zirCmp(block, inst, .gt), 1176 .cmp_neq => try sema.zirCmpEq(block, inst, .neq, Air.Inst.Tag.fromCmpOp(.neq, block.float_mode == .optimized)), 1177 .decl_ref => try sema.zirDeclRef(block, inst), 1178 .decl_val => try sema.zirDeclVal(block, inst), 1179 .load => try sema.zirLoad(block, inst), 1180 .elem_ptr => try sema.zirElemPtr(block, inst), 1181 .elem_ptr_node => try sema.zirElemPtrNode(block, inst), 1182 .elem_val => try sema.zirElemVal(block, inst), 1183 .elem_ptr_load => try sema.zirElemPtrLoad(block, inst), 1184 .elem_val_imm => try sema.zirElemValImm(block, inst), 1185 .elem_type => try sema.zirElemType(block, inst), 1186 .indexable_ptr_elem_type => try sema.zirIndexablePtrElemType(block, inst), 1187 .splat_op_result_ty => try sema.zirSplatOpResultType(block, inst), 1188 .from_backing_int_arg_ty => try sema.zirFromBackingIntArgTy(block, inst), 1189 .enum_literal => try sema.zirEnumLiteral(block, inst), 1190 .decl_literal => try sema.zirDeclLiteral(block, inst, true), 1191 .decl_literal_no_coerce => try sema.zirDeclLiteral(block, inst, false), 1192 .int_from_enum => try sema.zirIntFromEnum(block, inst), 1193 .enum_from_int => try sema.zirEnumFromInt(block, inst), 1194 .backing_int => try sema.zirBackingInt(block, inst), 1195 .from_backing_int => try sema.zirFromBackingInt(block, inst), 1196 .err_union_code => try sema.zirErrUnionCode(block, inst), 1197 .err_union_code_ptr => try sema.zirErrUnionCodePtr(block, inst), 1198 .err_union_payload_unsafe => try sema.zirErrUnionPayload(block, inst), 1199 .err_union_payload_unsafe_ptr => try sema.zirErrUnionPayloadPtr(block, inst), 1200 .error_union_type => try sema.zirErrorUnionType(block, inst), 1201 .error_value => try sema.zirErrorValue(block, inst), 1202 .field_ptr => try sema.zirFieldPtr(block, inst), 1203 .field_ptr_named => try sema.zirFieldPtrNamed(block, inst), 1204 .field_ptr_load => try sema.zirFieldPtrLoad(block, inst), 1205 .field_ptr_named_load => try sema.zirFieldPtrNamedLoad(block, inst), 1206 .func => try sema.zirFunc(block, inst, false), 1207 .func_inferred => try sema.zirFunc(block, inst, true), 1208 .func_fancy => try sema.zirFuncFancy(block, inst), 1209 .import => try sema.zirImport(block, inst), 1210 .indexable_ptr_len => try sema.zirIndexablePtrLen(block, inst), 1211 .int => try sema.zirInt(block, inst), 1212 .int_big => try sema.zirIntBig(block, inst), 1213 .float => try sema.zirFloat(block, inst), 1214 .float128 => try sema.zirFloat128(block, inst), 1215 .int_type => try sema.zirIntType(inst), 1216 .is_non_err => try sema.zirIsNonErr(block, inst), 1217 .is_non_err_ptr => try sema.zirIsNonErrPtr(block, inst), 1218 .ret_is_non_err => try sema.zirRetIsNonErr(block, inst), 1219 .is_non_null => try sema.zirIsNonNull(block, inst), 1220 .is_non_null_ptr => try sema.zirIsNonNullPtr(block, inst), 1221 .merge_error_sets => try sema.zirMergeErrorSets(block, inst), 1222 .negate => try sema.zirNegate(block, inst), 1223 .negate_wrap => try sema.zirNegateWrap(block, inst), 1224 .optional_payload_safe => try sema.zirOptionalPayload(block, inst, true), 1225 .optional_payload_safe_ptr => try sema.zirOptionalPayloadPtr(block, inst, true), 1226 .optional_payload_unsafe => try sema.zirOptionalPayload(block, inst, false), 1227 .optional_payload_unsafe_ptr => try sema.zirOptionalPayloadPtr(block, inst, false), 1228 .optional_type => try sema.zirOptionalType(block, inst), 1229 .ptr_type => try sema.zirPtrType(block, inst), 1230 .ref => try sema.zirRef(block, inst), 1231 .deref => try sema.zirDeref(block, inst), 1232 .ref_deref => try sema.zirRefDeref(block, inst), 1233 .shr => try sema.zirShr(block, inst, .shr), 1234 .shr_exact => try sema.zirShr(block, inst, .shr_exact), 1235 .slice_end => try sema.zirSliceEnd(block, inst), 1236 .slice_sentinel => try sema.zirSliceSentinel(block, inst), 1237 .slice_start => try sema.zirSliceStart(block, inst), 1238 .slice_length => try sema.zirSliceLength(block, inst), 1239 .slice_sentinel_ty => try sema.zirSliceSentinelTy(block, inst), 1240 .str => try sema.zirStr(inst), 1241 .switch_block => try sema.zirSwitchBlock(block, inst, false), 1242 .switch_block_ref => try sema.zirSwitchBlock(block, inst, true), 1243 .switch_block_err_union => try sema.zirSwitchBlockErrUnion(block, inst), 1244 .type_info => try sema.zirTypeInfo(block, inst), 1245 .size_of => try sema.zirSizeOf(block, inst), 1246 .bit_size_of => try sema.zirBitSizeOf(block, inst), 1247 .typeof => try sema.zirTypeof(block, inst), 1248 .typeof_builtin => try sema.zirTypeofBuiltin(block, inst), 1249 .typeof_log2_int_type => try sema.zirTypeofLog2IntType(block, inst), 1250 .xor => try sema.zirBitwise(block, inst, .xor), 1251 .struct_init_empty => try sema.zirStructInitEmpty(block, inst), 1252 .struct_init_empty_result => try sema.zirStructInitEmptyResult(block, inst, false), 1253 .struct_init_empty_ref_result => try sema.zirStructInitEmptyResult(block, inst, true), 1254 .struct_init_anon => try sema.zirStructInitAnon(block, inst), 1255 .struct_init => try sema.zirStructInit(block, inst, false), 1256 .struct_init_ref => try sema.zirStructInit(block, inst, true), 1257 .struct_init_field_type => try sema.zirStructInitFieldType(block, inst), 1258 .struct_init_field_ptr => try sema.zirStructInitFieldPtr(block, inst), 1259 .array_init_anon => try sema.zirArrayInitAnon(block, inst), 1260 .array_init => try sema.zirArrayInit(block, inst, false), 1261 .array_init_ref => try sema.zirArrayInit(block, inst, true), 1262 .array_init_elem_type => try sema.zirArrayInitElemType(block, inst), 1263 .array_init_elem_ptr => try sema.zirArrayInitElemPtr(block, inst), 1264 .union_init => try sema.zirUnionInit(block, inst), 1265 .field_type_ref => try sema.zirFieldTypeRef(block, inst), 1266 .int_from_ptr => try sema.zirIntFromPtr(block, inst), 1267 .align_of => try sema.zirAlignOf(block, inst), 1268 .int_from_bool => try sema.zirIntFromBool(block, inst), 1269 .embed_file => try sema.zirEmbedFile(block, inst), 1270 .error_name => try sema.zirErrorName(block, inst), 1271 .tag_name => try sema.zirTagName(block, inst), 1272 .type_name => try sema.zirTypeName(block, inst), 1273 .frame_type => try sema.zirFrameType(block, inst), 1274 .int_from_float => try sema.zirIntFromFloat(block, inst), 1275 .float_from_int => try sema.zirFloatFromInt(block, inst), 1276 .ptr_from_int => try sema.zirPtrFromInt(block, inst), 1277 .float_cast => try sema.zirFloatCast(block, inst), 1278 .int_cast => try sema.zirIntCast(block, inst), 1279 .ptr_cast => try sema.zirPtrCast(block, inst), 1280 .truncate => try sema.zirTruncate(block, inst), 1281 .has_decl => try sema.zirHasDecl(block, inst), 1282 .has_field => try sema.zirHasField(block, inst), 1283 .byte_swap => try sema.zirByteSwap(block, inst), 1284 .bit_reverse => try sema.zirBitReverse(block, inst), 1285 .bit_offset_of => try sema.zirBitOffsetOf(block, inst), 1286 .offset_of => try sema.zirOffsetOf(block, inst), 1287 .splat => try sema.zirSplat(block, inst), 1288 .reduce => try sema.zirReduce(block, inst), 1289 .shuffle => try sema.zirShuffle(block, inst), 1290 .atomic_load => try sema.zirAtomicLoad(block, inst), 1291 .atomic_rmw => try sema.zirAtomicRmw(block, inst), 1292 .mul_add => try sema.zirMulAdd(block, inst), 1293 .builtin_call => try sema.zirBuiltinCall(block, inst), 1294 .@"resume" => try sema.zirResume(block, inst), 1295 .for_len => try sema.zirForLen(block, inst), 1296 .validate_array_init_ref_ty => try sema.zirValidateArrayInitRefTy(block, inst), 1297 .opt_eu_base_ptr_init => try sema.zirOptEuBasePtrInit(block, inst), 1298 .coerce_ptr_elem_ty => try sema.zirCoercePtrElemTy(block, inst), 1299 1300 .clz => try sema.zirBitCount(block, inst, .clz, Value.clz), 1301 .ctz => try sema.zirBitCount(block, inst, .ctz, Value.ctz), 1302 .pop_count => try sema.zirBitCount(block, inst, .popcount, Value.popCount), 1303 .abs => try sema.zirAbs(block, inst), 1304 1305 .sqrt => try sema.zirUnaryMath(block, inst, .sqrt, Value.sqrt), 1306 .sin => try sema.zirUnaryMath(block, inst, .sin, Value.sin), 1307 .cos => try sema.zirUnaryMath(block, inst, .cos, Value.cos), 1308 .tan => try sema.zirUnaryMath(block, inst, .tan, Value.tan), 1309 .exp => try sema.zirUnaryMath(block, inst, .exp, Value.exp), 1310 .exp2 => try sema.zirUnaryMath(block, inst, .exp2, Value.exp2), 1311 .log => try sema.zirUnaryMath(block, inst, .log, Value.log), 1312 .log2 => try sema.zirUnaryMath(block, inst, .log2, Value.log2), 1313 .log10 => try sema.zirUnaryMath(block, inst, .log10, Value.log10), 1314 .floor => try sema.zirUnaryMath(block, inst, .floor, Value.floor), 1315 .ceil => try sema.zirUnaryMath(block, inst, .ceil, Value.ceil), 1316 .round => try sema.zirUnaryMath(block, inst, .round, Value.round), 1317 .trunc => try sema.zirUnaryMath(block, inst, .trunc_float, Value.trunc), 1318 1319 .error_set_decl => try sema.zirErrorSetDecl(inst), 1320 1321 .add => try sema.zirArithmetic(block, inst, .add, true), 1322 .addwrap => try sema.zirArithmetic(block, inst, .addwrap, true), 1323 .add_sat => try sema.zirArithmetic(block, inst, .add_sat, true), 1324 .add_unsafe => try sema.zirArithmetic(block, inst, .add_unsafe, false), 1325 .mul => try sema.zirArithmetic(block, inst, .mul, true), 1326 .mulwrap => try sema.zirArithmetic(block, inst, .mulwrap, true), 1327 .mul_sat => try sema.zirArithmetic(block, inst, .mul_sat, true), 1328 .sub => try sema.zirArithmetic(block, inst, .sub, true), 1329 .subwrap => try sema.zirArithmetic(block, inst, .subwrap, true), 1330 .sub_sat => try sema.zirArithmetic(block, inst, .sub_sat, true), 1331 1332 .div => try sema.zirDiv(block, inst), 1333 .div_exact => try sema.zirDivExact(block, inst), 1334 .div_floor => try sema.zirDivFloor(block, inst), 1335 .div_ceil => try sema.zirDivCeil(block, inst), 1336 .div_trunc => try sema.zirDivTrunc(block, inst), 1337 1338 .mod_rem => try sema.zirModRem(block, inst), 1339 .mod => try sema.zirMod(block, inst), 1340 .rem => try sema.zirRem(block, inst), 1341 1342 .max => try sema.zirMinMax(block, inst, .max), 1343 .min => try sema.zirMinMax(block, inst, .min), 1344 1345 .shl => try sema.zirShl(block, inst, .shl), 1346 .shl_exact => try sema.zirShl(block, inst, .shl_exact), 1347 .shl_sat => try sema.zirShl(block, inst, .shl_sat), 1348 1349 .ret_ptr => try sema.zirRetPtr(block, inst), 1350 .ret_type => Air.internedToRef(sema.fn_ret_ty.toIntern()), 1351 1352 // Instructions that we know to *always* be noreturn based solely on their tag. 1353 // These functions match the return type of analyzeBody so that we can 1354 // tail call them here. 1355 .compile_error => break try sema.zirCompileError(block, inst), 1356 .ret_implicit => break try sema.zirRetImplicit(block, inst), 1357 .ret_node => break try sema.zirRetNode(block, inst), 1358 .ret_load => break try sema.zirRetLoad(block, inst), 1359 .ret_err_value => break try sema.zirRetErrValue(block, inst), 1360 .@"unreachable" => break try sema.zirUnreachable(block, inst), 1361 .panic => break try sema.zirPanic(block, inst), 1362 .trap => break try sema.zirTrap(block, inst), 1363 // zig fmt: on 1364 1365 // This instruction never exists in an analyzed body. It exists only in the declaration 1366 // list for a container type. 1367 .declaration => unreachable, 1368 1369 .extended => ext: { 1370 const extended = datas[@backingInt(inst)].extended; 1371 break :ext switch (extended.opcode) { 1372 // zig fmt: off 1373 .struct_decl => try sema.zirStructDecl( block, inst), 1374 .enum_decl => try sema.zirEnumDecl( block, inst), 1375 .union_decl => try sema.zirUnionDecl( block, inst), 1376 .opaque_decl => try sema.zirOpaqueDecl( block, inst), 1377 .tuple_decl => try sema.zirTupleDecl( block, extended), 1378 .this => try sema.zirThis( block, extended), 1379 .ret_addr => try sema.zirRetAddr( block, extended), 1380 .builtin_src => try sema.zirBuiltinSrc( block, extended), 1381 .error_return_trace => try sema.zirErrorReturnTrace( block), 1382 .frame => try sema.zirFrame( block, extended), 1383 .frame_address => try sema.zirFrameAddress( block, extended), 1384 .alloc => try sema.zirAllocExtended( block, extended), 1385 .builtin_extern => try sema.zirBuiltinExtern( block, extended), 1386 .@"asm" => try sema.zirAsm( block, extended, false), 1387 .asm_expr => try sema.zirAsm( block, extended, true), 1388 .typeof_peer => try sema.zirTypeofPeer( block, extended, inst), 1389 .round_op => try sema.zirRoundCast( block, extended), 1390 .round_op_ty => try sema.zirRoundOpType( block, extended), 1391 .compile_log => try sema.zirCompileLog( block, extended), 1392 .min_multi => try sema.zirMinMaxMulti( block, extended, .min), 1393 .max_multi => try sema.zirMinMaxMulti( block, extended, .max), 1394 .add_with_overflow => try sema.zirOverflowArithmetic(block, extended, extended.opcode), 1395 .sub_with_overflow => try sema.zirOverflowArithmetic(block, extended, extended.opcode), 1396 .mul_with_overflow => try sema.zirOverflowArithmetic(block, extended, extended.opcode), 1397 .shl_with_overflow => try sema.zirOverflowArithmetic(block, extended, extended.opcode), 1398 .wasm_memory_size => try sema.zirWasmMemorySize( block, extended), 1399 .wasm_memory_grow => try sema.zirWasmMemoryGrow( block, extended), 1400 .prefetch => try sema.zirPrefetch( block, extended), 1401 .error_cast => try sema.zirErrorCast( block, extended), 1402 .select => try sema.zirSelect( block, extended), 1403 .int_from_error => try sema.zirIntFromError( block, extended), 1404 .error_from_int => try sema.zirErrorFromInt( block, extended), 1405 .cmpxchg => try sema.zirCmpxchg( block, extended), 1406 .c_va_arg => try sema.zirCVaArg( block, extended), 1407 .c_va_copy => try sema.zirCVaCopy( block, extended), 1408 .c_va_end => try sema.zirCVaEnd( block, extended), 1409 .c_va_start => try sema.zirCVaStart( block, extended), 1410 .ptr_cast_full => try sema.zirPtrCastFull( block, extended), 1411 .ptr_cast_no_dest => try sema.zirPtrCastNoDest( block, extended), 1412 .work_item_id => try sema.zirWorkItem( block, extended, extended.opcode), 1413 .work_group_size => try sema.zirWorkItem( block, extended, extended.opcode), 1414 .work_group_id => try sema.zirWorkItem( block, extended, extended.opcode), 1415 .in_comptime => try sema.zirInComptime( block), 1416 .closure_get => try sema.zirClosureGet( block, extended), 1417 1418 .reify_slice_arg_ty => try sema.zirReifySliceArgTy( block, extended), 1419 .reify_enum_value_slice_ty => try sema.zirReifyEnumValueSliceTy(block, extended), 1420 .reify_pointer_sentinel_ty => try sema.zirReifyPointerSentinelTy(block, extended), 1421 .reify_tuple => try sema.zirReifyTuple( block, extended), 1422 .reify_pointer => try sema.zirReifyPointer( block, extended), 1423 .reify_fn => try sema.zirReifyFn( block, extended), 1424 .reify_struct => try sema.zirReifyStruct( block, extended, inst), 1425 .reify_union => try sema.zirReifyUnion( block, extended, inst), 1426 .reify_enum => try sema.zirReifyEnum( block, extended, inst), 1427 .reify_spirv_type => try sema.zirReifySpirvType( block, extended, inst), 1428 // zig fmt: on 1429 1430 .set_float_mode => { 1431 try sema.zirSetFloatMode(block, extended); 1432 i += 1; 1433 continue; 1434 }, 1435 .breakpoint => { 1436 try sema.zirBreakpoint(block, extended); 1437 i += 1; 1438 continue; 1439 }, 1440 .disable_instrumentation => { 1441 try sema.zirDisableInstrumentation(); 1442 i += 1; 1443 continue; 1444 }, 1445 .disable_intrinsics => { 1446 try sema.zirDisableIntrinsics(); 1447 i += 1; 1448 continue; 1449 }, 1450 .restore_err_ret_index => { 1451 try sema.zirRestoreErrRetIndex(block, extended); 1452 i += 1; 1453 continue; 1454 }, 1455 .branch_hint => { 1456 try sema.zirBranchHint(block, extended); 1457 i += 1; 1458 continue; 1459 }, 1460 .value_placeholder => unreachable, // never appears in a body 1461 .field_parent_ptr => try sema.zirFieldParentPtr(block, extended), 1462 .std_lang_value => try sema.zirStdLangValue(block, extended), 1463 .inplace_arith_result_ty => try sema.zirInplaceArithResultTy(extended), 1464 .dbg_empty_stmt => { 1465 try sema.zirDbgEmptyStmt(block, inst); 1466 i += 1; 1467 continue; 1468 }, 1469 .astgen_error => return sema.failTransitive(.astgen_error), 1470 .float_op_result_ty => try sema.zirFloatOpResultType(block, extended), 1471 }; 1472 }, 1473 1474 // Instructions that we know can *never* be noreturn based solely on 1475 // their tag. We avoid needlessly checking if they are noreturn and 1476 // continue the loop. 1477 // We also know that they cannot be referenced later, so we avoid 1478 // putting them into the map. 1479 .dbg_stmt => { 1480 try sema.zirDbgStmt(block, inst); 1481 i += 1; 1482 continue; 1483 }, 1484 .dbg_var_ptr => { 1485 try sema.zirDbgVar(block, inst, .dbg_var_ptr); 1486 i += 1; 1487 continue; 1488 }, 1489 .dbg_var_val => { 1490 try sema.zirDbgVar(block, inst, .dbg_var_val); 1491 i += 1; 1492 continue; 1493 }, 1494 .ensure_err_union_payload_void => { 1495 try sema.zirEnsureErrUnionPayloadVoid(block, inst); 1496 i += 1; 1497 continue; 1498 }, 1499 .ensure_result_non_error => { 1500 try sema.zirEnsureResultNonError(block, inst); 1501 i += 1; 1502 continue; 1503 }, 1504 .ensure_result_used => { 1505 try sema.zirEnsureResultUsed(block, inst); 1506 i += 1; 1507 continue; 1508 }, 1509 .set_eval_branch_quota => { 1510 try sema.zirSetEvalBranchQuota(block, inst); 1511 i += 1; 1512 continue; 1513 }, 1514 .atomic_store => { 1515 try sema.zirAtomicStore(block, inst); 1516 i += 1; 1517 continue; 1518 }, 1519 .store_node => { 1520 try sema.zirStoreNode(block, inst); 1521 i += 1; 1522 continue; 1523 }, 1524 .store_to_inferred_ptr => { 1525 try sema.zirStoreToInferredPtr(block, inst); 1526 i += 1; 1527 continue; 1528 }, 1529 .validate_struct_init_ty => { 1530 try sema.zirValidateStructInitTy(block, inst, false); 1531 i += 1; 1532 continue; 1533 }, 1534 .validate_struct_init_result_ty => { 1535 try sema.zirValidateStructInitTy(block, inst, true); 1536 i += 1; 1537 continue; 1538 }, 1539 .validate_array_init_ty => { 1540 try sema.zirValidateArrayInitTy(block, inst, false); 1541 i += 1; 1542 continue; 1543 }, 1544 .validate_array_init_result_ty => { 1545 try sema.zirValidateArrayInitTy(block, inst, true); 1546 i += 1; 1547 continue; 1548 }, 1549 .validate_ptr_struct_init => { 1550 try sema.zirValidatePtrStructInit(block, inst); 1551 i += 1; 1552 continue; 1553 }, 1554 .validate_ptr_array_init => { 1555 try sema.zirValidatePtrArrayInit(block, inst); 1556 i += 1; 1557 continue; 1558 }, 1559 .validate_destructure => { 1560 try sema.zirValidateDestructure(block, inst); 1561 i += 1; 1562 continue; 1563 }, 1564 .validate_ref_ty => { 1565 try sema.zirValidateRefTy(block, inst); 1566 i += 1; 1567 continue; 1568 }, 1569 .validate_const => { 1570 try sema.zirValidateConst(block, inst); 1571 i += 1; 1572 continue; 1573 }, 1574 .@"export" => { 1575 try sema.zirExport(block, inst); 1576 i += 1; 1577 continue; 1578 }, 1579 .set_runtime_safety => { 1580 try sema.zirSetRuntimeSafety(block, inst); 1581 i += 1; 1582 continue; 1583 }, 1584 .param => { 1585 try sema.zirParam(block, inst, false); 1586 i += 1; 1587 continue; 1588 }, 1589 .param_comptime => { 1590 try sema.zirParam(block, inst, true); 1591 i += 1; 1592 continue; 1593 }, 1594 .param_anytype => { 1595 try sema.zirParamAnytype(block, inst, false); 1596 i += 1; 1597 continue; 1598 }, 1599 .param_anytype_comptime => { 1600 try sema.zirParamAnytype(block, inst, true); 1601 i += 1; 1602 continue; 1603 }, 1604 .memcpy => { 1605 try sema.zirMemcpy(block, inst, .memcpy, true); 1606 i += 1; 1607 continue; 1608 }, 1609 .memmove => { 1610 try sema.zirMemcpy(block, inst, .memmove, false); 1611 i += 1; 1612 continue; 1613 }, 1614 .memset => { 1615 try sema.zirMemset(block, inst); 1616 i += 1; 1617 continue; 1618 }, 1619 .check_comptime_control_flow => { 1620 if (!block.isComptime()) { 1621 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].un_node; 1622 const src = block.nodeOffset(inst_data.src_node); 1623 const inline_block = inst_data.operand.toIndex().?; 1624 1625 var check_block = block; 1626 const target_runtime_index = while (true) { 1627 if (check_block.inline_block == inline_block.toOptional()) { 1628 break check_block.runtime_index; 1629 } 1630 check_block = check_block.parent.?; 1631 }; 1632 1633 if (@backingInt(target_runtime_index) < @backingInt(block.runtime_index)) { 1634 const runtime_src = block.runtime_cond orelse block.runtime_loop.?; 1635 const msg = msg: { 1636 const msg = try sema.errMsg(src, "comptime control flow inside runtime block", .{}); 1637 errdefer msg.destroy(sema.gpa); 1638 try sema.errNote(runtime_src, msg, "runtime control flow here", .{}); 1639 break :msg msg; 1640 }; 1641 return sema.failWithOwnedErrorMsg(block, msg); 1642 } 1643 } 1644 i += 1; 1645 continue; 1646 }, 1647 .save_err_ret_index => { 1648 try sema.zirSaveErrRetIndex(block, inst); 1649 i += 1; 1650 continue; 1651 }, 1652 .restore_err_ret_index_unconditional => { 1653 const un_node = datas[@backingInt(inst)].un_node; 1654 try sema.restoreErrRetIndex(block, block.nodeOffset(un_node.src_node), un_node.operand, .none); 1655 i += 1; 1656 continue; 1657 }, 1658 .restore_err_ret_index_fn_entry => { 1659 const un_node = datas[@backingInt(inst)].un_node; 1660 try sema.restoreErrRetIndex(block, block.nodeOffset(un_node.src_node), .none, un_node.operand); 1661 i += 1; 1662 continue; 1663 }, 1664 1665 // Special case instructions to handle comptime control flow. 1666 .@"break" => { 1667 if (block.isComptime()) { 1668 sema.comptime_break_inst = inst; 1669 return error.ComptimeBreak; 1670 } else { 1671 try sema.zirBreak(block, inst); 1672 break; 1673 } 1674 }, 1675 .break_inline => { 1676 sema.comptime_break_inst = inst; 1677 return error.ComptimeBreak; 1678 }, 1679 .repeat => { 1680 if (block.isComptime()) { 1681 // Send comptime control flow back to the beginning of this block. 1682 const src = block.nodeOffset(datas[@backingInt(inst)].node); 1683 try sema.emitBackwardBranch(block, src); 1684 i = 0; 1685 continue; 1686 } else { 1687 // We are definitely called by `zirLoop`, which will treat the 1688 // fact that this body does not terminate `noreturn` as an 1689 // implicit repeat. 1690 // TODO: since AIR has `repeat` now, we could change ZIR to generate 1691 // more optimal code utilizing `repeat` instructions across blocks! 1692 break; 1693 } 1694 }, 1695 .repeat_inline => { 1696 // Send comptime control flow back to the beginning of this block. 1697 const src = block.nodeOffset(datas[@backingInt(inst)].node); 1698 try sema.emitBackwardBranch(block, src); 1699 i = 0; 1700 continue; 1701 }, 1702 .switch_continue => if (block.isComptime()) { 1703 sema.comptime_break_inst = inst; 1704 return error.ComptimeBreak; 1705 } else { 1706 try sema.zirSwitchContinue(block, inst); 1707 break; 1708 }, 1709 1710 .loop => if (block.isComptime()) { 1711 continue :inst .block_inline; 1712 } else try sema.zirLoop(block, inst), 1713 1714 .block => if (block.isComptime()) { 1715 continue :inst .block_inline; 1716 } else try sema.zirBlock(block, inst), 1717 1718 .block_comptime => { 1719 const pl_node = datas[@backingInt(inst)].pl_node; 1720 const src = block.nodeOffset(pl_node.src_node); 1721 const extra = sema.code.extraData(Zir.Inst.BlockComptime, pl_node.payload_index); 1722 const block_body = sema.code.bodySlice(extra.end, extra.data.body_len); 1723 1724 var child_block = block.makeSubBlock(); 1725 defer child_block.instructions.deinit(sema.gpa); 1726 1727 // We won't have any merges, but we must ensure this block is properly labeled for 1728 // any `.restore_err_ret_index_*` instructions. 1729 var label: Block.Label = .{ 1730 .zir_block = inst, 1731 .merges = undefined, 1732 }; 1733 child_block.label = &label; 1734 1735 child_block.comptime_reason = .{ .reason = .{ 1736 .src = src, 1737 .r = .{ .simple = extra.data.reason }, 1738 } }; 1739 1740 const result = try sema.resolveInlineBody(&child_block, block_body, inst); 1741 1742 // Only check for the result being comptime-known in the outermost `block_comptime`. 1743 // That way, AstGen can safely elide redundant `block_comptime` without affecting semantics. 1744 if (!block.isComptime() and !try sema.isComptimeKnown(result)) { 1745 return sema.failWithNeededComptime(&child_block, src, null); 1746 } 1747 1748 break :inst result; 1749 }, 1750 1751 .block_inline => blk: { 1752 // Directly analyze the block body without introducing a new block. 1753 // However, in the case of a corresponding break_inline which reaches 1754 // through a runtime conditional branch, we must retroactively emit 1755 // a block, so we remember the block index here just in case. 1756 const block_index = block.instructions.items.len; 1757 const inst_data = datas[@backingInt(inst)].pl_node; 1758 const extra = sema.code.extraData(Zir.Inst.Block, inst_data.payload_index); 1759 const inline_body = sema.code.bodySlice(extra.end, extra.data.body_len); 1760 const gpa = sema.gpa; 1761 1762 const BreakResult = struct { 1763 block_inst: Zir.Inst.Index, 1764 operand: Zir.Inst.Ref, 1765 }; 1766 1767 const opt_break_data: ?BreakResult, const need_debug_scope = b: { 1768 // Create a temporary child block so that this inline block is properly 1769 // labeled for any .restore_err_ret_index instructions 1770 var child_block = block.makeSubBlock(); 1771 var need_debug_scope = false; 1772 child_block.need_debug_scope = &need_debug_scope; 1773 1774 // If this block contains a function prototype, we need to reset the 1775 // current list of parameters and restore it later. 1776 // Note: this probably needs to be resolved in a more general manner. 1777 const tag_index = @backingInt(inline_body[inline_body.len - 1]); 1778 child_block.inline_block = (if (tags[tag_index] == .repeat_inline) 1779 inline_body[0] 1780 else 1781 inst).toOptional(); 1782 1783 var label: Block.Label = .{ 1784 .zir_block = inst, 1785 .merges = undefined, 1786 }; 1787 child_block.label = &label; 1788 1789 // Write these instructions directly into the parent block 1790 child_block.instructions = block.instructions; 1791 defer block.instructions = child_block.instructions; 1792 1793 const break_result: ?BreakResult = if (sema.analyzeBodyInner(&child_block, inline_body)) r: { 1794 break :r null; 1795 } else |err| switch (err) { 1796 error.ComptimeBreak => brk_res: { 1797 const break_inst = sema.comptime_break_inst; 1798 const break_data = sema.code.instructions.items(.data)[@backingInt(break_inst)].@"break"; 1799 const break_extra = sema.code.extraData(Zir.Inst.Break, break_data.payload_index).data; 1800 break :brk_res .{ 1801 .block_inst = break_extra.block_inst, 1802 .operand = break_data.operand, 1803 }; 1804 }, 1805 else => |e| return e, 1806 }; 1807 1808 if (need_debug_scope) { 1809 _ = try sema.ensurePostHoc(block, inst); 1810 } 1811 1812 break :b .{ break_result, need_debug_scope }; 1813 }; 1814 1815 // A runtime conditional branch that needs a post-hoc block to be 1816 // emitted communicates this by mapping the block index into the inst map. 1817 if (map.get(inst)) |new_block_ref| ph: { 1818 // Comptime control flow populates the map, so we don't actually know 1819 // if this is a post-hoc runtime block until we check the 1820 // post_hoc_block map. 1821 const new_block_inst = new_block_ref.toIndex() orelse break :ph; 1822 const labeled_block = sema.post_hoc_blocks.get(new_block_inst) orelse 1823 break :ph; 1824 1825 // In this case we need to move all the instructions starting at 1826 // block_index from the current block into this new one. 1827 1828 if (opt_break_data) |break_data| { 1829 // This is a comptime break which we now change to a runtime break 1830 // since it crosses a runtime branch. 1831 // It may pass through our currently being analyzed block_inline or it 1832 // may point directly to it. In the latter case, this modifies the 1833 // block that we looked up in the post_hoc_blocks map above. 1834 try sema.addRuntimeBreak(block, break_data.block_inst, break_data.operand); 1835 } 1836 1837 try labeled_block.block.instructions.appendSlice(gpa, block.instructions.items[block_index..]); 1838 block.instructions.items.len = block_index; 1839 1840 const block_result = try sema.resolveAnalyzedBlock(block, block.nodeOffset(inst_data.src_node), &labeled_block.block, &labeled_block.label.merges, need_debug_scope); 1841 { 1842 // Destroy the ad-hoc block entry so that it does not interfere with 1843 // the next iteration of comptime control flow, if any. 1844 labeled_block.destroy(gpa); 1845 assert(sema.post_hoc_blocks.remove(new_block_inst)); 1846 } 1847 1848 break :blk block_result; 1849 } 1850 1851 const break_data = opt_break_data orelse break; 1852 if (inst == break_data.block_inst) { 1853 break :blk sema.resolveInst(break_data.operand); 1854 } else { 1855 // `comptime_break_inst` preserved from `analyzeBodyInner` above. 1856 return error.ComptimeBreak; 1857 } 1858 }, 1859 .condbr => if (block.isComptime()) { 1860 continue :inst .condbr_inline; 1861 } else { 1862 try sema.zirCondbr(block, inst); 1863 break; 1864 }, 1865 .condbr_inline => { 1866 const inst_data = datas[@backingInt(inst)].pl_node; 1867 const cond_src = block.src(.{ .node_offset_if_cond = inst_data.src_node }); 1868 const extra = sema.code.extraData(Zir.Inst.CondBr, inst_data.payload_index); 1869 const then_body = sema.code.bodySlice(extra.end, extra.data.then_body_len); 1870 const else_body = sema.code.bodySlice( 1871 extra.end + then_body.len, 1872 extra.data.else_body_len, 1873 ); 1874 const uncasted_cond = sema.resolveInst(extra.data.condition); 1875 const cond = try sema.coerce(block, .bool, uncasted_cond, cond_src); 1876 const cond_val = try sema.resolveConstDefinedValue( 1877 block, 1878 cond_src, 1879 cond, 1880 // If this block is comptime, it's more helpful to just give the outer message. 1881 // This is particularly true if this came from a comptime `condbr` above. 1882 if (block.isComptime()) null else .{ .simple = .inline_loop_operand }, 1883 ); 1884 const inline_body = if (cond_val.toBool()) then_body else else_body; 1885 1886 try sema.maybeErrorUnwrapCondbr(block, inline_body, extra.data.condition, cond_src); 1887 const old_runtime_index = block.runtime_index; 1888 defer block.runtime_index = old_runtime_index; 1889 1890 const result = try sema.analyzeInlineBody(block, inline_body, inst) orelse break; 1891 break :inst result; 1892 }, 1893 .@"try" => blk: { 1894 if (!block.isComptime()) break :blk try sema.zirTry(block, inst); 1895 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 1896 const src = block.nodeOffset(inst_data.src_node); 1897 const operand_src = block.src(.{ .node_offset_try_operand = inst_data.src_node }); 1898 const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index); 1899 const inline_body = sema.code.bodySlice(extra.end, extra.data.body_len); 1900 const err_union = sema.resolveInst(extra.data.operand); 1901 const err_union_ty = sema.typeOf(err_union); 1902 if (err_union_ty.zigTypeTag(zcu) != .error_union) { 1903 return sema.failWithOwnedErrorMsg(block, msg: { 1904 const msg = try sema.errMsg(operand_src, "expected error union type, found '{f}'", .{err_union_ty.fmt(pt)}); 1905 errdefer msg.destroy(sema.gpa); 1906 try sema.addDeclaredHereNote(msg, err_union_ty); 1907 try sema.errNote(operand_src, msg, "consider omitting 'try'", .{}); 1908 break :msg msg; 1909 }); 1910 } 1911 const is_non_err_val = (try sema.resolveIsNonErrVal(block, operand_src, err_union)).?; 1912 if (is_non_err_val.isUndef(zcu)) return sema.failWithUseOfUndef(block, operand_src, null); 1913 if (is_non_err_val.toBool()) { 1914 break :blk try sema.analyzeErrUnionPayload(block, src, err_union_ty, err_union, operand_src, false); 1915 } 1916 const result = try sema.analyzeInlineBody(block, inline_body, inst) orelse break; 1917 break :blk result; 1918 }, 1919 .try_ptr => blk: { 1920 if (!block.isComptime()) break :blk try sema.zirTryPtr(block, inst); 1921 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 1922 const src = block.nodeOffset(inst_data.src_node); 1923 const operand_src = block.src(.{ .node_offset_try_operand = inst_data.src_node }); 1924 const extra = sema.code.extraData(Zir.Inst.Try, inst_data.payload_index); 1925 const inline_body = sema.code.bodySlice(extra.end, extra.data.body_len); 1926 const operand = sema.resolveInst(extra.data.operand); 1927 const err_union = try sema.analyzeLoad(block, src, operand, operand_src); 1928 const is_non_err_val = (try sema.resolveIsNonErrVal(block, operand_src, err_union)).?; 1929 if (is_non_err_val.isUndef(zcu)) return sema.failWithUseOfUndef(block, operand_src, null); 1930 if (is_non_err_val.toBool()) { 1931 break :blk try sema.analyzeErrUnionPayloadPtr(block, src, operand, false, false); 1932 } 1933 const result = try sema.analyzeInlineBody(block, inline_body, inst) orelse break; 1934 break :blk result; 1935 }, 1936 .@"defer" => blk: { 1937 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].@"defer"; 1938 const defer_body = sema.code.bodySlice(inst_data.index, inst_data.len); 1939 if (sema.analyzeBodyInner(block, defer_body)) { 1940 // The defer terminated noreturn - no more analysis needed. 1941 break; 1942 } else |err| switch (err) { 1943 error.ComptimeBreak => {}, 1944 else => |e| return e, 1945 } 1946 if (sema.comptime_break_inst != defer_body[defer_body.len - 1]) { 1947 return error.ComptimeBreak; 1948 } 1949 break :blk .void_value; 1950 }, 1951 }; 1952 1953 const is_inferred_alloc = if (air_ref.toIndex()) |air_inst| switch (sema.air_instructions.items(.tag)[@backingInt(air_inst)]) { 1954 .inferred_alloc, .inferred_alloc_comptime => true, 1955 else => false, 1956 } else false; 1957 // We must resolve the layout of a type before creating a value of that type. Therefore, 1958 // the layout of the type of `air_ref` must already be resolved. The call to `classify` 1959 // doubles as an assertion of this. 1960 if (!is_inferred_alloc) switch (sema.typeOf(air_ref).classify(zcu)) { 1961 .no_possible_value => { 1962 // The instruction result was noreturn, which should mean that the body itself now 1963 // ends with a noreturn instruction. Let's confirm that. 1964 const last_inst = block.instructions.items[block.instructions.items.len - 1]; 1965 const last_inst_ty = sema.typeOf(last_inst.toRef()); 1966 assert(last_inst_ty.classify(zcu) == .no_possible_value); 1967 break; 1968 }, 1969 .one_possible_value => assert(air_ref.toInterned() != null), // the value should be comptime-known 1970 .partially_comptime => assert(air_ref.toInterned() != null), // the value should be comptime-known 1971 .fully_comptime => assert(air_ref.toInterned() != null), // the value should be comptime-known 1972 .runtime => {}, 1973 }; 1974 1975 map.putAssumeCapacity(inst, air_ref); 1976 i += 1; 1977 } 1978 } 1979 1980 fn resolveInstAllowNone(sema: *Sema, zir_ref: Zir.Inst.Ref) Air.Inst.Ref { 1981 if (zir_ref == .none) { 1982 return .none; 1983 } else { 1984 return resolveInst(sema, zir_ref); 1985 } 1986 } 1987 1988 fn resolveInst(sema: *Sema, zir_ref: Zir.Inst.Ref) Air.Inst.Ref { 1989 assert(zir_ref != .none); 1990 if (zir_ref.toIndex()) |i| { 1991 return sema.inst_map.get(i).?; 1992 } 1993 // First section of indexes correspond to a set number of constant values. 1994 // We intentionally map the same indexes to the same values between ZIR and AIR. 1995 return @fromBackingInt(@intCast(@backingInt(zir_ref))); 1996 } 1997 1998 fn resolveConstBool( 1999 sema: *Sema, 2000 block: *Block, 2001 src: LazySrcLoc, 2002 zir_ref: Zir.Inst.Ref, 2003 reason: ComptimeReason, 2004 ) !bool { 2005 const air_inst = sema.resolveInst(zir_ref); 2006 const wanted_type: Type = .bool; 2007 const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src); 2008 const val = try sema.resolveConstDefinedValue(block, src, coerced_inst, reason); 2009 return val.toBool(); 2010 } 2011 2012 fn resolveConstString( 2013 sema: *Sema, 2014 block: *Block, 2015 src: LazySrcLoc, 2016 zir_ref: Zir.Inst.Ref, 2017 /// `null` may be passed only if `block.isComptime()`. It indicates that the reason for the value 2018 /// being comptime-resolved is that the block is being comptime-evaluated. 2019 reason: ?ComptimeReason, 2020 ) ![]u8 { 2021 const air_inst = sema.resolveInst(zir_ref); 2022 return sema.toConstString(block, src, air_inst, reason); 2023 } 2024 2025 pub fn toConstString( 2026 sema: *Sema, 2027 block: *Block, 2028 src: LazySrcLoc, 2029 air_inst: Air.Inst.Ref, 2030 /// `null` may be passed only if `block.isComptime()`. It indicates that the reason for the value 2031 /// being comptime-resolved is that the block is being comptime-evaluated. 2032 reason: ?ComptimeReason, 2033 ) ![]u8 { 2034 const pt = sema.pt; 2035 const coerced_inst = try sema.coerce(block, .slice_const_u8, air_inst, src); 2036 const slice_val = try sema.resolveConstDefinedValue(block, src, coerced_inst, reason); 2037 const arr_val = try sema.derefSliceAsArray(block, src, slice_val, reason); 2038 return arr_val.toAllocatedBytes(arr_val.typeOf(pt.zcu), sema.arena, pt); 2039 } 2040 2041 pub fn resolveConstStringIntern( 2042 sema: *Sema, 2043 block: *Block, 2044 src: LazySrcLoc, 2045 zir_ref: Zir.Inst.Ref, 2046 reason: ComptimeReason, 2047 ) !InternPool.NullTerminatedString { 2048 const air_inst = sema.resolveInst(zir_ref); 2049 const wanted_type: Type = .slice_const_u8; 2050 const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src); 2051 const val = try sema.resolveConstDefinedValue(block, src, coerced_inst, reason); 2052 return sema.sliceToIpString(block, src, val, reason); 2053 } 2054 2055 fn resolveTypeOrPoison(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) !?Type { 2056 const air_inst = sema.resolveInst(zir_ref); 2057 const ty = try sema.analyzeAsType(block, src, .type, air_inst); 2058 if (ty.isGenericPoison()) return null; 2059 return ty; 2060 } 2061 2062 pub fn resolveType(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) !Type { 2063 return (try sema.resolveTypeOrPoison(block, src, zir_ref)).?; 2064 } 2065 2066 fn resolveDestType( 2067 sema: *Sema, 2068 block: *Block, 2069 src: LazySrcLoc, 2070 zir_ref: Zir.Inst.Ref, 2071 strat: enum { remove_eu_opt, remove_eu, remove_opt }, 2072 builtin_name: []const u8, 2073 ) !Type { 2074 const pt = sema.pt; 2075 const zcu = pt.zcu; 2076 const remove_eu = switch (strat) { 2077 .remove_eu_opt, .remove_eu => true, 2078 .remove_opt => false, 2079 }; 2080 const remove_opt = switch (strat) { 2081 .remove_eu_opt, .remove_opt => true, 2082 .remove_eu => false, 2083 }; 2084 2085 const raw_ty = try sema.resolveTypeOrPoison(block, src, zir_ref) orelse { 2086 // Cast builtins use their result type as the destination type, but 2087 // it could be an anytype argument, which we can't catch in AstGen. 2088 const msg = msg: { 2089 const msg = try sema.errMsg(src, "{s} must have a known result type", .{builtin_name}); 2090 errdefer msg.destroy(sema.gpa); 2091 switch (sema.genericPoisonReason(block, zir_ref)) { 2092 .anytype_param => |call_src| try sema.errNote(call_src, msg, "result type is unknown due to anytype parameter", .{}), 2093 .anyopaque_ptr => |ptr_src| try sema.errNote(ptr_src, msg, "result type is unknown due to opaque pointer type", .{}), 2094 .unknown => {}, 2095 } 2096 try sema.errNote(src, msg, "use @as to provide explicit result type", .{}); 2097 break :msg msg; 2098 }; 2099 return sema.failWithOwnedErrorMsg(block, msg); 2100 }; 2101 2102 if (remove_eu and raw_ty.zigTypeTag(zcu) == .error_union) { 2103 const eu_child = raw_ty.errorUnionPayload(zcu); 2104 if (remove_opt and eu_child.zigTypeTag(zcu) == .optional) { 2105 return eu_child.childType(zcu); 2106 } 2107 return eu_child; 2108 } 2109 if (remove_opt and raw_ty.zigTypeTag(zcu) == .optional) { 2110 return raw_ty.childType(zcu); 2111 } 2112 return raw_ty; 2113 } 2114 2115 const GenericPoisonReason = union(enum) { 2116 anytype_param: LazySrcLoc, 2117 anyopaque_ptr: LazySrcLoc, 2118 unknown, 2119 }; 2120 2121 /// Backtracks through ZIR instructions to determine the reason a generic poison 2122 /// type was created. Used for error reporting. 2123 fn genericPoisonReason(sema: *Sema, block: *Block, ref: Zir.Inst.Ref) GenericPoisonReason { 2124 var cur = ref; 2125 while (true) { 2126 const inst = cur.toIndex() orelse return .unknown; 2127 switch (sema.code.instructions.items(.tag)[@backingInt(inst)]) { 2128 .validate_array_init_ref_ty => { 2129 const pl_node = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 2130 const extra = sema.code.extraData(Zir.Inst.ArrayInitRefTy, pl_node.payload_index).data; 2131 cur = extra.ptr_ty; 2132 }, 2133 .array_init_elem_type => { 2134 const bin = sema.code.instructions.items(.data)[@backingInt(inst)].bin; 2135 cur = bin.lhs; 2136 }, 2137 .indexable_ptr_elem_type, .splat_op_result_ty => { 2138 const un_node = sema.code.instructions.items(.data)[@backingInt(inst)].un_node; 2139 cur = un_node.operand; 2140 }, 2141 .struct_init_field_type => { 2142 const pl_node = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 2143 const extra = sema.code.extraData(Zir.Inst.FieldType, pl_node.payload_index).data; 2144 cur = extra.container_type; 2145 }, 2146 .elem_type => { 2147 // There are two cases here: the pointer type may already have been 2148 // generic poison, or it may have been an anyopaque pointer. 2149 const un_node = sema.code.instructions.items(.data)[@backingInt(inst)].un_node; 2150 const operand_ref = sema.resolveInst(un_node.operand); 2151 const operand_val = operand_ref.toInterned() orelse return .unknown; 2152 if (operand_val == .generic_poison_type) { 2153 // The pointer was generic poison - keep looking. 2154 cur = un_node.operand; 2155 } else { 2156 // This must be an anyopaque pointer! 2157 return .{ .anyopaque_ptr = block.nodeOffset(un_node.src_node) }; 2158 } 2159 }, 2160 .call, .field_call => { 2161 // A function call can never return generic poison, so we must be 2162 // evaluating an `anytype` function parameter. 2163 // TODO: better source location - function decl rather than call 2164 const pl_node = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 2165 return .{ .anytype_param = block.nodeOffset(pl_node.src_node) }; 2166 }, 2167 else => return .unknown, 2168 } 2169 } 2170 } 2171 2172 pub fn analyzeAsType( 2173 sema: *Sema, 2174 block: *Block, 2175 src: LazySrcLoc, 2176 reason: std.zig.SimpleComptimeReason, 2177 air_inst: Air.Inst.Ref, 2178 ) !Type { 2179 const wanted_type: Type = .type; 2180 const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src); 2181 const val = try sema.resolveConstDefinedValue(block, src, coerced_inst, .{ .simple = reason }); 2182 return val.toType(); 2183 } 2184 2185 pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize) !void { 2186 const pt = sema.pt; 2187 const comp = pt.zcu.comp; 2188 const gpa = comp.gpa; 2189 const io = comp.io; 2190 const ip = &pt.zcu.intern_pool; 2191 2192 if (!comp.config.any_error_tracing) return; 2193 2194 assert(!block.isComptime()); 2195 var err_trace_block = block.makeSubBlock(); 2196 defer err_trace_block.instructions.deinit(gpa); 2197 2198 const src: LazySrcLoc = LazySrcLoc.unneeded; 2199 2200 // var addrs: [err_return_trace_addr_count]usize = undefined; 2201 const err_return_trace_addr_count = 32; 2202 const addr_arr_ty = try pt.arrayType(.{ 2203 .len = err_return_trace_addr_count, 2204 .child = .usize_type, 2205 }); 2206 const addrs_ptr = try err_trace_block.addTy(.alloc, try pt.singleMutPtrType(addr_arr_ty)); 2207 2208 // var st: StackTrace = undefined; 2209 const stack_trace_ty = try sema.getStdLangType(block.nodeOffset(.zero), .StackTrace); 2210 const st_ptr = try err_trace_block.addTy(.alloc, try pt.singleMutPtrType(stack_trace_ty)); 2211 2212 // st.instruction_addresses = &addrs; 2213 const instruction_addresses_field_name = try ip.getOrPutString(gpa, io, pt.tid, "instruction_addresses", .no_embedded_nulls); 2214 const addr_field_ptr = try sema.fieldPtr(&err_trace_block, src, st_ptr, instruction_addresses_field_name, src, true); 2215 try sema.storePtr2(&err_trace_block, src, addr_field_ptr, src, addrs_ptr, src, .store); 2216 2217 // st.index = 0; 2218 const index_field_name = try ip.getOrPutString(gpa, io, pt.tid, "index", .no_embedded_nulls); 2219 const index_field_ptr = try sema.fieldPtr(&err_trace_block, src, st_ptr, index_field_name, src, true); 2220 try sema.storePtr2(&err_trace_block, src, index_field_ptr, src, .zero_usize, src, .store); 2221 2222 // @errorReturnTrace() = &st; 2223 _ = try err_trace_block.addUnOp(.set_err_return_trace, st_ptr); 2224 2225 try block.instructions.insertSlice(gpa, last_arg_index, err_trace_block.instructions.items); 2226 } 2227 2228 /// Return the Value corresponding to a given AIR ref, or `null` if it refers to a runtime value. 2229 fn resolveValue(sema: *Sema, inst: Air.Inst.Ref) ?Value { 2230 const zcu = sema.pt.zcu; 2231 assert(inst != .none); 2232 2233 if (inst.toInterned()) |ip_index| { 2234 return .fromInterned(ip_index); 2235 } 2236 2237 // Runtime-known value. We'll be returning `null`, but first, some assertions. 2238 const air_tags = sema.air_instructions.items(.tag); 2239 switch (air_tags[@backingInt(inst.toIndex().?)]) { 2240 .inferred_alloc => unreachable, // assertion failure 2241 .inferred_alloc_comptime => unreachable, // assertion failure 2242 else => {}, 2243 } 2244 // LLVM fails to eliminate this `classify` call in -Ofast, which hurts performance, so 2245 // we must explicitly check for `std.debug.runtime_safety`. 2246 if (std.debug.runtime_safety) switch (sema.typeOf(inst).classify(zcu)) { 2247 .no_possible_value => unreachable, // values of this type do not exist 2248 .one_possible_value => unreachable, // the value should be comptime-known 2249 .partially_comptime => unreachable, // the value should be comptime-known 2250 .fully_comptime => unreachable, // the value should be comptime-known 2251 .runtime => {}, 2252 }; 2253 return null; 2254 } 2255 2256 /// Like `resolveValue`, but emits an error if the value is not comptime-known. 2257 pub fn resolveConstValue( 2258 sema: *Sema, 2259 block: *Block, 2260 src: LazySrcLoc, 2261 inst: Air.Inst.Ref, 2262 /// `null` may be passed only if `block.isComptime()`. It indicates that the reason for the value 2263 /// being comptime-resolved is that the block is being comptime-evaluated. 2264 reason: ?ComptimeReason, 2265 ) CompileError!Value { 2266 assert(reason != null or block.isComptime()); 2267 return sema.resolveValue(inst) orelse { 2268 return sema.failWithNeededComptime(block, src, reason); 2269 }; 2270 } 2271 2272 /// Like `resolveValue`, but emits an error if the value is comptime-known to be undefined. 2273 fn resolveDefinedValue( 2274 sema: *Sema, 2275 block: *Block, 2276 src: LazySrcLoc, 2277 air_ref: Air.Inst.Ref, 2278 ) CompileError!?Value { 2279 const pt = sema.pt; 2280 const zcu = pt.zcu; 2281 const val = sema.resolveValue(air_ref) orelse return null; 2282 if (val.isUndef(zcu)) return sema.failWithUseOfUndef(block, src, null); 2283 return val; 2284 } 2285 2286 /// Like `resolveValue`, but emits an error if the value is not comptime-known or is undefined. 2287 pub fn resolveConstDefinedValue( 2288 sema: *Sema, 2289 block: *Block, 2290 src: LazySrcLoc, 2291 air_ref: Air.Inst.Ref, 2292 /// `null` may be passed only if `block.isComptime()`. It indicates that the reason for the value 2293 /// being comptime-resolved is that the block is being comptime-evaluated. 2294 reason: ?ComptimeReason, 2295 ) CompileError!Value { 2296 const val = try sema.resolveConstValue(block, src, air_ref, reason); 2297 if (val.isUndef(sema.pt.zcu)) return sema.failWithUseOfUndef(block, src, null); 2298 return val; 2299 } 2300 2301 /// Value Tag may be `undef` or `variable`. 2302 pub fn resolveFinalDeclValue( 2303 sema: *Sema, 2304 block: *Block, 2305 src: LazySrcLoc, 2306 air_ref: Air.Inst.Ref, 2307 ) CompileError!Value { 2308 const zcu = sema.pt.zcu; 2309 const val = try sema.resolveConstValue(block, src, air_ref, .{ .simple = .container_var_init }); 2310 if (val.canMutateComptimeVarState(zcu)) { 2311 const ip = &zcu.intern_pool; 2312 const nav = ip.getNav(sema.owner.unwrap().nav_val); 2313 return sema.failWithContainsReferenceToComptimeVar(block, src, nav.name, "global variable", val); 2314 } 2315 return val; 2316 } 2317 2318 fn failWithNeededComptime( 2319 sema: *Sema, 2320 block: *Block, 2321 src: LazySrcLoc, 2322 /// `null` may be passed only if `block.isComptime()`. It indicates that the reason for the value 2323 /// being comptime-resolved is that the block is being comptime-evaluated. 2324 reason: ?ComptimeReason, 2325 ) CompileError { 2326 const msg, const fail_block = msg: { 2327 const msg = try sema.errMsg(src, "unable to resolve comptime value", .{}); 2328 errdefer msg.destroy(sema.gpa); 2329 const fail_block = if (reason) |r| b: { 2330 try r.explain(sema, src, msg); 2331 break :b block; 2332 } else b: { 2333 break :b try block.explainWhyBlockIsComptime(msg); 2334 }; 2335 break :msg .{ msg, fail_block }; 2336 }; 2337 return sema.failWithOwnedErrorMsg(fail_block, msg); 2338 } 2339 2340 pub fn failWithUseOfUndef(sema: *Sema, block: *Block, src: LazySrcLoc, vector_index: ?usize) CompileError { 2341 return sema.failWithOwnedErrorMsg(block, msg: { 2342 const msg = try sema.errMsg(src, "use of undefined value here causes illegal behavior", .{}); 2343 errdefer msg.destroy(sema.gpa); 2344 if (vector_index) |i| try sema.errNote(src, msg, "when computing vector element at index '{d}'", .{i}); 2345 break :msg msg; 2346 }); 2347 } 2348 2349 pub fn failWithUndefSliceLen(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError { 2350 return sema.fail(block, src, "use of slice with undefined length here causes illegal behavior", .{}); 2351 } 2352 2353 pub fn failWithDivideByZero(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError { 2354 return sema.fail(block, src, "division by zero here causes illegal behavior", .{}); 2355 } 2356 2357 pub fn failWithTooLargeShiftAmount( 2358 sema: *Sema, 2359 block: *Block, 2360 operand_ty: Type, 2361 shift_amt: Value, 2362 shift_src: LazySrcLoc, 2363 vector_index: ?usize, 2364 ) CompileError { 2365 return sema.failWithOwnedErrorMsg(block, msg: { 2366 const msg = try sema.errMsg( 2367 shift_src, 2368 "shift amount '{f}' is too large for operand type '{f}'", 2369 .{ shift_amt.fmtValueSema(sema.pt, sema), operand_ty.fmt(sema.pt) }, 2370 ); 2371 errdefer msg.destroy(sema.gpa); 2372 if (vector_index) |i| try sema.errNote(shift_src, msg, "when computing vector element at index '{d}'", .{i}); 2373 break :msg msg; 2374 }); 2375 } 2376 2377 pub fn failWithNegativeShiftAmount(sema: *Sema, block: *Block, src: LazySrcLoc, shift_amt: Value, vector_index: ?usize) CompileError { 2378 return sema.failWithOwnedErrorMsg(block, msg: { 2379 const msg = try sema.errMsg(src, "shift by negative amount '{f}'", .{shift_amt.fmtValueSema(sema.pt, sema)}); 2380 errdefer msg.destroy(sema.gpa); 2381 if (vector_index) |i| try sema.errNote(src, msg, "when computing vector element at index '{d}'", .{i}); 2382 break :msg msg; 2383 }); 2384 } 2385 2386 pub fn failWithUnsupportedComptimeShiftAmount(sema: *Sema, block: *Block, src: LazySrcLoc, vector_index: ?usize) CompileError { 2387 return sema.failWithOwnedErrorMsg(block, msg: { 2388 const msg = try sema.errMsg( 2389 src, 2390 "this implementation only supports comptime shift amounts of up to 2^{d} - 1 bits", 2391 .{@min(@bitSizeOf(usize), 64)}, 2392 ); 2393 errdefer msg.destroy(sema.gpa); 2394 if (vector_index) |i| try sema.errNote(src, msg, "when computing vector element at index '{d}'", .{i}); 2395 break :msg msg; 2396 }); 2397 } 2398 2399 fn failWithModRemNegative(sema: *Sema, block: *Block, src: LazySrcLoc, lhs_ty: Type, rhs_ty: Type) CompileError { 2400 const pt = sema.pt; 2401 return sema.fail(block, src, "remainder division with '{f}' and '{f}': signed integers and floats must use @rem or @mod", .{ 2402 lhs_ty.fmt(pt), rhs_ty.fmt(pt), 2403 }); 2404 } 2405 2406 fn failWithInvalidSwitchTagCapture(sema: *Sema, block: *Block, tag_capture_src: LazySrcLoc, operand_ty: Type) CompileError { 2407 const pt = sema.pt; 2408 const zcu = pt.zcu; 2409 2410 if (operand_ty.zigTypeTag(zcu) == .@"union") { 2411 assert(operand_ty.containerLayout(zcu) == .@"packed"); 2412 return sema.failWithOwnedErrorMsg(block, msg: { 2413 const msg = try sema.errMsg(tag_capture_src, "cannot capture tag of packed union", .{}); 2414 errdefer msg.destroy(sema.gpa); 2415 try sema.addDeclaredHereNote(msg, operand_ty); 2416 if (operand_ty.srcLocOrNull(zcu)) |ty_src| { 2417 try sema.errNote(ty_src, msg, "consider using a tagged union", .{}); 2418 } 2419 break :msg msg; 2420 }); 2421 } 2422 return sema.failWithOwnedErrorMsg(block, msg: { 2423 const msg = try sema.errMsg(tag_capture_src, "cannot capture tag of non-union type '{f}'", .{ 2424 operand_ty.fmt(pt), 2425 }); 2426 errdefer msg.destroy(sema.gpa); 2427 try sema.addDeclaredHereNote(msg, operand_ty); 2428 break :msg msg; 2429 }); 2430 } 2431 2432 fn failWithAmbiguousBackingIntType( 2433 sema: *Sema, 2434 block: *Block, 2435 src: LazySrcLoc, 2436 int_backed_ty: Type, 2437 builtin_name: []const u8, 2438 ) CompileError { 2439 const pt = sema.pt; 2440 const zcu = pt.zcu; 2441 return sema.failWithOwnedErrorMsg(block, msg: { 2442 const msg = try sema.errMsg(src, "{s} is ambiguous for type '{f}'", .{ 2443 builtin_name, int_backed_ty.fmt(pt), 2444 }); 2445 errdefer msg.destroy(sema.gpa); 2446 try sema.errNote(int_backed_ty.srcLoc(zcu), msg, "backing integer type of {t} is inferred", .{ 2447 int_backed_ty.zigTypeTag(zcu), 2448 }); 2449 try sema.errNote(int_backed_ty.srcLoc(zcu), msg, "consider explicitly specifying the backing integer type", .{}); 2450 break :msg msg; 2451 }); 2452 } 2453 2454 fn failWithExpectedOptionalType(sema: *Sema, block: *Block, src: LazySrcLoc, non_optional_ty: Type) CompileError { 2455 const pt = sema.pt; 2456 const msg = msg: { 2457 const msg = try sema.errMsg(src, "expected optional type, found '{f}'", .{ 2458 non_optional_ty.fmt(pt), 2459 }); 2460 errdefer msg.destroy(sema.gpa); 2461 if (non_optional_ty.zigTypeTag(pt.zcu) == .error_union) { 2462 try sema.errNote(src, msg, "consider using 'try', 'catch', or 'if'", .{}); 2463 } 2464 try addDeclaredHereNote(sema, msg, non_optional_ty); 2465 break :msg msg; 2466 }; 2467 return sema.failWithOwnedErrorMsg(block, msg); 2468 } 2469 2470 fn failWithArrayInitNotSupported(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError { 2471 const pt = sema.pt; 2472 const zcu = pt.zcu; 2473 const msg = msg: { 2474 const msg = try sema.errMsg(src, "type '{f}' does not support array initialization syntax", .{ 2475 ty.fmt(pt), 2476 }); 2477 errdefer msg.destroy(sema.gpa); 2478 if (ty.isSlice(zcu)) { 2479 try sema.errNote(src, msg, "inferred array length is specified with an underscore: '[_]{f}'", .{ty.childType(zcu).fmt(pt)}); 2480 } 2481 break :msg msg; 2482 }; 2483 return sema.failWithOwnedErrorMsg(block, msg); 2484 } 2485 2486 fn failWithStructInitNotSupported(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) CompileError { 2487 const pt = sema.pt; 2488 return sema.fail(block, src, "type '{f}' does not support struct initialization syntax", .{ 2489 ty.fmt(pt), 2490 }); 2491 } 2492 2493 pub fn failWithIntegerOverflow(sema: *Sema, block: *Block, src: LazySrcLoc, int_ty: Type, val: Value, vector_index: ?usize) CompileError { 2494 const pt = sema.pt; 2495 return sema.failWithOwnedErrorMsg(block, msg: { 2496 const msg = try sema.errMsg(src, "overflow of integer type '{f}' with value '{f}'", .{ 2497 int_ty.fmt(pt), val.fmtValueSema(pt, sema), 2498 }); 2499 errdefer msg.destroy(sema.gpa); 2500 if (vector_index) |i| try sema.errNote(src, msg, "when computing vector element at index '{d}'", .{i}); 2501 break :msg msg; 2502 }); 2503 } 2504 2505 fn failWithInvalidComptimeFieldStore(sema: *Sema, block: *Block, init_src: LazySrcLoc, container_ty: Type, field_index: usize) CompileError { 2506 const pt = sema.pt; 2507 const zcu = pt.zcu; 2508 const msg = msg: { 2509 const msg = try sema.errMsg(init_src, "value stored in comptime field does not match the default value of the field", .{}); 2510 errdefer msg.destroy(sema.gpa); 2511 2512 const struct_type = zcu.typeToStruct(container_ty) orelse break :msg msg; 2513 try sema.errNote(.{ 2514 .base_node_inst = struct_type.zir_index, 2515 .offset = .{ .container_field_value = @intCast(field_index) }, 2516 }, msg, "default value set here", .{}); 2517 break :msg msg; 2518 }; 2519 return sema.failWithOwnedErrorMsg(block, msg); 2520 } 2521 2522 fn failWithUseOfAsync(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError { 2523 const msg = msg: { 2524 const msg = try sema.errMsg(src, "async has not been implemented in the self-hosted compiler yet", .{}); 2525 errdefer msg.destroy(sema.gpa); 2526 break :msg msg; 2527 }; 2528 return sema.failWithOwnedErrorMsg(block, msg); 2529 } 2530 2531 fn failWithInvalidFieldAccess( 2532 sema: *Sema, 2533 block: *Block, 2534 src: LazySrcLoc, 2535 object_ty: Type, 2536 field_name: InternPool.NullTerminatedString, 2537 ) CompileError { 2538 const pt = sema.pt; 2539 const zcu = pt.zcu; 2540 const inner_ty = if (object_ty.isSinglePointer(zcu)) object_ty.childType(zcu) else object_ty; 2541 2542 if (inner_ty.zigTypeTag(zcu) == .optional) opt: { 2543 const child_ty = inner_ty.optionalChild(zcu); 2544 if (!typeSupportsFieldAccess(zcu, child_ty, field_name)) break :opt; 2545 const msg = msg: { 2546 const msg = try sema.errMsg(src, "optional type '{f}' does not support field access", .{object_ty.fmt(pt)}); 2547 errdefer msg.destroy(sema.gpa); 2548 try sema.errNote(src, msg, "consider using '.?', 'orelse', or 'if'", .{}); 2549 break :msg msg; 2550 }; 2551 return sema.failWithOwnedErrorMsg(block, msg); 2552 } else if (inner_ty.zigTypeTag(zcu) == .error_union) err: { 2553 const child_ty = inner_ty.errorUnionPayload(zcu); 2554 if (!typeSupportsFieldAccess(zcu, child_ty, field_name)) break :err; 2555 const msg = msg: { 2556 const msg = try sema.errMsg(src, "error union type '{f}' does not support field access", .{object_ty.fmt(pt)}); 2557 errdefer msg.destroy(sema.gpa); 2558 try sema.errNote(src, msg, "consider using 'try', 'catch', or 'if'", .{}); 2559 break :msg msg; 2560 }; 2561 return sema.failWithOwnedErrorMsg(block, msg); 2562 } 2563 return sema.fail(block, src, "type '{f}' does not support field access", .{object_ty.fmt(pt)}); 2564 } 2565 2566 fn typeSupportsFieldAccess(zcu: *const Zcu, ty: Type, field_name: InternPool.NullTerminatedString) bool { 2567 const ip = &zcu.intern_pool; 2568 switch (ty.zigTypeTag(zcu)) { 2569 .array => return field_name.eqlSlice("len", ip), 2570 .pointer => { 2571 const ptr_info = ty.ptrInfo(zcu); 2572 if (ptr_info.flags.size == .slice) { 2573 return field_name.eqlSlice("ptr", ip) or field_name.eqlSlice("len", ip); 2574 } else if (Type.fromInterned(ptr_info.child).zigTypeTag(zcu) == .array) { 2575 return field_name.eqlSlice("len", ip); 2576 } else return false; 2577 }, 2578 .type, .@"struct", .@"union" => return true, 2579 else => return false, 2580 } 2581 } 2582 2583 fn failWithComptimeErrorRetTrace( 2584 sema: *Sema, 2585 block: *Block, 2586 src: LazySrcLoc, 2587 name: InternPool.NullTerminatedString, 2588 ) CompileError { 2589 const pt = sema.pt; 2590 const zcu = pt.zcu; 2591 const msg = msg: { 2592 const msg = try sema.errMsg(src, "caught unexpected error '{f}'", .{name.fmt(&zcu.intern_pool)}); 2593 errdefer msg.destroy(sema.gpa); 2594 2595 for (sema.comptime_err_ret_trace.items) |src_loc| { 2596 try sema.errNote(src_loc, msg, "error returned here", .{}); 2597 } 2598 break :msg msg; 2599 }; 2600 return sema.failWithOwnedErrorMsg(block, msg); 2601 } 2602 2603 fn failWithInvalidPtrArithmetic(sema: *Sema, block: *Block, src: LazySrcLoc, arithmetic: []const u8, supports: []const u8) CompileError { 2604 const msg = msg: { 2605 const msg = try sema.errMsg(src, "invalid {s} arithmetic operator", .{arithmetic}); 2606 errdefer msg.destroy(sema.gpa); 2607 try sema.errNote(src, msg, "{s} arithmetic only supports {s}", .{ arithmetic, supports }); 2608 break :msg msg; 2609 }; 2610 return sema.failWithOwnedErrorMsg(block, msg); 2611 } 2612 2613 /// We don't return a pointer to the new error note because the pointer 2614 /// becomes invalid when you add another one. 2615 pub fn errNote( 2616 sema: *Sema, 2617 src: LazySrcLoc, 2618 parent: *Zcu.ErrorMsg, 2619 comptime format: []const u8, 2620 args: anytype, 2621 ) error{OutOfMemory}!void { 2622 return sema.pt.zcu.errNote(src, parent, format, args); 2623 } 2624 2625 fn addFieldErrNote( 2626 sema: *Sema, 2627 container_ty: Type, 2628 field_index: usize, 2629 parent: *Zcu.ErrorMsg, 2630 comptime format: []const u8, 2631 args: anytype, 2632 ) !void { 2633 @branchHint(.cold); 2634 const type_src = container_ty.srcLocOrNull(sema.pt.zcu) orelse return; 2635 const field_src: LazySrcLoc = .{ 2636 .base_node_inst = type_src.base_node_inst, 2637 .offset = .{ .container_field_name = @intCast(field_index) }, 2638 }; 2639 try sema.errNote(field_src, parent, format, args); 2640 } 2641 2642 pub fn errMsg( 2643 sema: *Sema, 2644 src: LazySrcLoc, 2645 comptime format: []const u8, 2646 args: anytype, 2647 ) Allocator.Error!*Zcu.ErrorMsg { 2648 assert(src.offset != .unneeded); 2649 return Zcu.ErrorMsg.create(sema.gpa, src, format, args); 2650 } 2651 2652 fn typeMismatchErrMsg(sema: *Sema, src: LazySrcLoc, expected: Type, found: Type) Allocator.Error!*Zcu.ErrorMsg { 2653 const pt = sema.pt; 2654 var cmp: Type.Comparison = try .init(&.{ expected, found }, pt); 2655 defer cmp.deinit(pt); 2656 2657 const msg = try sema.errMsg(src, "expected type '{f}', found '{f}'", .{ 2658 cmp.fmtType(expected, pt), 2659 cmp.fmtType(found, pt), 2660 }); 2661 errdefer msg.destroy(sema.gpa); 2662 2663 for (cmp.type_dedupe_cache.keys(), cmp.type_dedupe_cache.values()) |ty, value| { 2664 if (value == .dont_dedupe) continue; 2665 const placeholder = value.dedupe; 2666 try sema.errNote(src, msg, "{f} = {f}", .{ placeholder, ty.fmt(pt) }); 2667 } 2668 2669 return msg; 2670 } 2671 2672 pub fn fail( 2673 sema: *Sema, 2674 block: *Block, 2675 src: LazySrcLoc, 2676 comptime format: []const u8, 2677 args: anytype, 2678 ) SemaError { 2679 const err_msg = try sema.errMsg(src, format, args); 2680 inline for (args) |arg| { 2681 if (@TypeOf(arg) == Type.Formatter) { 2682 try addDeclaredHereNote(sema, err_msg, arg.data.ty); 2683 } 2684 } 2685 return sema.failWithOwnedErrorMsg(block, err_msg); 2686 } 2687 2688 fn failWithTypeMismatch(sema: *Sema, block: *Block, src: LazySrcLoc, expected: Type, found: Type) CompileError { 2689 return sema.failWithOwnedErrorMsg(block, msg: { 2690 const msg = try sema.typeMismatchErrMsg(src, expected, found); 2691 errdefer msg.destroy(sema.gpa); 2692 try addDeclaredHereNote(sema, msg, expected); 2693 try addDeclaredHereNote(sema, msg, found); 2694 break :msg msg; 2695 }); 2696 } 2697 2698 pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Zcu.ErrorMsg) SemaError { 2699 @branchHint(.cold); 2700 const zcu = sema.pt.zcu; 2701 const comp = zcu.comp; 2702 const gpa = comp.gpa; 2703 const io = comp.io; 2704 2705 assert(sema.err == null); 2706 2707 if (build_options.enable_debug_extensions and comp.debug_compile_errors) { 2708 var wip_errors: std.zig.ErrorBundle.Wip = undefined; 2709 wip_errors.init(gpa) catch @panic("out of memory"); 2710 Compilation.addModuleErrorMsg(zcu, &wip_errors, err_msg.*, false) catch @panic("out of memory"); 2711 std.debug.print("compile error during Sema:\n", .{}); 2712 var error_bundle = wip_errors.toOwnedBundle("") catch @panic("out of memory"); 2713 error_bundle.renderToStderr(io, .{}, .auto) catch @panic("failed to print to stderr"); 2714 std.debug.panicExtra(@returnAddress(), "unexpected compile error occurred", .{}); 2715 } 2716 2717 if (block) |start_block| { 2718 var block_it = start_block; 2719 while (block_it.inlining) |inlining| { 2720 const note_str = note: { 2721 if (inlining.is_generic_instantiation) break :note "generic function instantiated here"; 2722 if (inlining.call_block.isComptime()) break :note "called at comptime here"; 2723 break :note "called inline here"; 2724 }; 2725 try sema.errNote(inlining.call_src, err_msg, "{s}", .{note_str}); 2726 block_it = inlining.call_block; 2727 } 2728 } 2729 2730 err_msg.reference_trace_root = sema.owner.toOptional(); 2731 2732 try zcu.failed_analysis.putNoClobber(gpa, sema.owner, err_msg); 2733 assert(!zcu.transitive_failed_analysis.contains(sema.owner)); 2734 2735 sema.err = err_msg; 2736 return error.AlreadyReported; 2737 } 2738 2739 /// Given an ErrorMsg, modify its message and source location to the given values, turning the 2740 /// original message into a note. Notes on the original message are preserved as further notes. 2741 /// Reference trace is preserved. 2742 fn reparentOwnedErrorMsg( 2743 sema: *Sema, 2744 src: LazySrcLoc, 2745 msg: *Zcu.ErrorMsg, 2746 comptime format: []const u8, 2747 args: anytype, 2748 ) !void { 2749 const msg_str = try std.fmt.allocPrint(sema.gpa, format, args); 2750 2751 const orig_notes = msg.notes.len; 2752 msg.notes = try sema.gpa.realloc(msg.notes, orig_notes + 1); 2753 @memmove(msg.notes[1..][0..orig_notes], msg.notes[0..orig_notes]); 2754 msg.notes[0] = .{ 2755 .src_loc = msg.src_loc, 2756 .msg = msg.msg, 2757 }; 2758 2759 msg.src_loc = src; 2760 msg.msg = msg_str; 2761 } 2762 2763 const align_ty: Type = .u29; 2764 2765 pub fn analyzeAsAlign( 2766 sema: *Sema, 2767 block: *Block, 2768 src: LazySrcLoc, 2769 air_ref: Air.Inst.Ref, 2770 ) !Alignment { 2771 const alignment_big = try sema.analyzeAsInt( 2772 block, 2773 src, 2774 air_ref, 2775 align_ty, 2776 .{ .simple = .@"align" }, 2777 ); 2778 return sema.validateAlign(block, src, alignment_big); 2779 } 2780 2781 fn validateAlign( 2782 sema: *Sema, 2783 block: *Block, 2784 src: LazySrcLoc, 2785 alignment: u64, 2786 ) !Alignment { 2787 if (alignment == 0) return sema.fail(block, src, "alignment must be >= 1", .{}); 2788 if (!std.math.isPowerOfTwo(alignment)) { 2789 return sema.fail(block, src, "alignment value '{d}' is not a power of two", .{ 2790 alignment, 2791 }); 2792 } 2793 return Alignment.fromNonzeroByteUnits(alignment); 2794 } 2795 2796 fn resolveAlign( 2797 sema: *Sema, 2798 block: *Block, 2799 src: LazySrcLoc, 2800 zir_ref: Zir.Inst.Ref, 2801 ) !Alignment { 2802 const air_ref = sema.resolveInst(zir_ref); 2803 return sema.analyzeAsAlign(block, src, air_ref); 2804 } 2805 2806 fn resolveInt( 2807 sema: *Sema, 2808 block: *Block, 2809 src: LazySrcLoc, 2810 zir_ref: Zir.Inst.Ref, 2811 dest_ty: Type, 2812 reason: ComptimeReason, 2813 ) !u64 { 2814 const air_ref = sema.resolveInst(zir_ref); 2815 return sema.analyzeAsInt(block, src, air_ref, dest_ty, reason); 2816 } 2817 2818 fn analyzeAsInt( 2819 sema: *Sema, 2820 block: *Block, 2821 src: LazySrcLoc, 2822 air_ref: Air.Inst.Ref, 2823 dest_ty: Type, 2824 reason: ComptimeReason, 2825 ) !u64 { 2826 const coerced = try sema.coerce(block, dest_ty, air_ref, src); 2827 const val = try sema.resolveConstDefinedValue(block, src, coerced, reason); 2828 return val.toUnsignedInt(sema.pt.zcu); 2829 } 2830 2831 fn analyzeValueAsCallconv( 2832 sema: *Sema, 2833 block: *Block, 2834 src: LazySrcLoc, 2835 val: Value, 2836 ) !std.lang.CallingConvention { 2837 return interpretStdLangType(sema, block, src, val, std.lang.CallingConvention); 2838 } 2839 2840 fn interpretStdLangType( 2841 sema: *Sema, 2842 block: *Block, 2843 src: LazySrcLoc, 2844 val: Value, 2845 comptime T: type, 2846 ) !T { 2847 return val.interpret(T, sema.pt) catch |err| switch (err) { 2848 error.OutOfMemory => |e| return e, 2849 error.UndefinedValue => return sema.failWithUseOfUndef(block, src, null), 2850 error.TypeMismatch => @panic("std.lang is corrupt"), 2851 }; 2852 } 2853 2854 fn uninterpretStdLangType( 2855 sema: *Sema, 2856 val: anytype, 2857 ty: Type, 2858 ) !Value { 2859 return Value.uninterpret(val, ty, sema.pt) catch |err| switch (err) { 2860 error.OutOfMemory => |e| return e, 2861 error.TypeMismatch => @panic("std.lang is corrupt"), 2862 }; 2863 } 2864 2865 fn zirTupleDecl( 2866 sema: *Sema, 2867 block: *Block, 2868 extended: Zir.Inst.Extended.InstData, 2869 ) CompileError!Air.Inst.Ref { 2870 const pt = sema.pt; 2871 const zcu = pt.zcu; 2872 const comp = zcu.comp; 2873 const gpa = comp.gpa; 2874 const io = comp.io; 2875 2876 const fields_len = extended.small; 2877 const extra = sema.code.extraData(Zir.Inst.TupleDecl, extended.operand); 2878 var extra_index = extra.end; 2879 2880 const types = try sema.arena.alloc(InternPool.Index, fields_len); 2881 const inits = try sema.arena.alloc(InternPool.Index, fields_len); 2882 2883 const extra_as_refs: []const Zir.Inst.Ref = @ptrCast(sema.code.extra); 2884 2885 for (types, inits, 0..) |*field_ty, *field_init, field_index| { 2886 const zir_field_ty, const zir_field_init = extra_as_refs[extra_index..][0..2].*; 2887 extra_index += 2; 2888 2889 const type_src = block.src(.{ .tuple_field_type = .{ 2890 .tuple_decl_node_offset = extra.data.src_node, 2891 .elem_index = @intCast(field_index), 2892 } }); 2893 const init_src = block.src(.{ .tuple_field_init = .{ 2894 .tuple_decl_node_offset = extra.data.src_node, 2895 .elem_index = @intCast(field_index), 2896 } }); 2897 2898 const field_type = try sema.resolveType(block, type_src, zir_field_ty); 2899 try sema.validateTupleFieldType(block, field_type, type_src); 2900 2901 field_ty.* = field_type.toIntern(); 2902 field_init.* = init: { 2903 if (zir_field_init != .none) { 2904 const uncoerced_field_init = sema.resolveInst(zir_field_init); 2905 const coerced_field_init = try sema.coerce(block, field_type, uncoerced_field_init, init_src); 2906 const field_init_val = try sema.resolveConstDefinedValue(block, init_src, coerced_field_init, .{ .simple = .tuple_field_default_value }); 2907 if (field_init_val.canMutateComptimeVarState(zcu)) { 2908 const field_name = try zcu.intern_pool.getOrPutStringFmt(gpa, io, pt.tid, "{d}", .{field_index}, .no_embedded_nulls); 2909 return sema.failWithContainsReferenceToComptimeVar(block, init_src, field_name, "field default value", field_init_val); 2910 } 2911 break :init field_init_val.toIntern(); 2912 } 2913 break :init .none; 2914 }; 2915 } 2916 2917 return Air.internedToRef(try zcu.intern_pool.getTupleType(gpa, io, pt.tid, .{ 2918 .types = types, 2919 .values = inits, 2920 })); 2921 } 2922 2923 fn validateTupleFieldType( 2924 sema: *Sema, 2925 block: *Block, 2926 field_ty: Type, 2927 field_ty_src: LazySrcLoc, 2928 ) CompileError!void { 2929 const gpa = sema.gpa; 2930 const zcu = sema.pt.zcu; 2931 if (field_ty.zigTypeTag(zcu) == .@"opaque") { 2932 return sema.failWithOwnedErrorMsg(block, msg: { 2933 const msg = try sema.errMsg(field_ty_src, "opaque types have unknown size and therefore cannot be directly embedded in tuples", .{}); 2934 errdefer msg.destroy(gpa); 2935 2936 try sema.addDeclaredHereNote(msg, field_ty); 2937 break :msg msg; 2938 }); 2939 } 2940 if (field_ty.zigTypeTag(zcu) == .noreturn) { 2941 return sema.failWithOwnedErrorMsg(block, msg: { 2942 const msg = try sema.errMsg(field_ty_src, "tuple fields cannot be 'noreturn'", .{}); 2943 errdefer msg.destroy(gpa); 2944 2945 try sema.addDeclaredHereNote(msg, field_ty); 2946 break :msg msg; 2947 }); 2948 } 2949 } 2950 2951 /// Given a ZIR extra index which points to a list of `Zir.Inst.Capture`, 2952 /// resolves this into a list of `InternPool.CaptureValue` allocated by `arena`. 2953 fn getCaptures( 2954 sema: *Sema, 2955 block: *Block, 2956 type_src: LazySrcLoc, 2957 zir_captures: []const Zir.Inst.Capture, 2958 zir_capture_names: []const Zir.NullTerminatedString, 2959 ) ![]InternPool.CaptureValue { 2960 const pt = sema.pt; 2961 const zcu = pt.zcu; 2962 const comp = zcu.comp; 2963 const gpa = comp.gpa; 2964 const io = comp.io; 2965 const ip = &zcu.intern_pool; 2966 2967 const parent_ty: Type = .fromInterned(zcu.namespacePtr(block.namespace).owner_type); 2968 const parent_captures: InternPool.CaptureValue.Slice = parent_ty.getCaptures(zcu); 2969 2970 const captures = try sema.arena.alloc(InternPool.CaptureValue, zir_captures.len); 2971 2972 for (zir_captures, zir_capture_names, captures) |zir_capture, zir_name, *capture| { 2973 const zir_name_slice = sema.code.nullTerminatedString(zir_name); 2974 capture.* = switch (zir_capture.unwrap()) { 2975 .nested => |parent_idx| parent_captures.get(ip)[parent_idx], 2976 .instruction_load => |ptr_inst| capture: { 2977 const ptr_ref = sema.resolveInst(ptr_inst.toRef()); 2978 const ptr_val = sema.resolveValue(ptr_ref) orelse { 2979 break :capture .wrap(.{ .runtime = sema.typeOf(ptr_ref).childType(zcu).toIntern() }); 2980 }; 2981 // TODO: better source location 2982 const loaded_val = try sema.pointerDeref(block, type_src, ptr_val, sema.typeOf(ptr_ref)) orelse { 2983 break :capture .wrap(.{ .runtime = sema.typeOf(ptr_ref).childType(zcu).toIntern() }); 2984 }; 2985 if (loaded_val.canMutateComptimeVarState(zcu)) { 2986 const field_name = try ip.getOrPutString(gpa, io, pt.tid, zir_name_slice, .no_embedded_nulls); 2987 return sema.failWithContainsReferenceToComptimeVar(block, type_src, field_name, "captured value", loaded_val); 2988 } 2989 break :capture .wrap(.{ .@"comptime" = loaded_val.toIntern() }); 2990 }, 2991 .instruction => |inst| capture: { 2992 const air_ref = sema.resolveInst(inst.toRef()); 2993 if (sema.resolveValue(air_ref)) |val| { 2994 if (val.canMutateComptimeVarState(zcu)) { 2995 const field_name = try ip.getOrPutString(gpa, io, pt.tid, zir_name_slice, .no_embedded_nulls); 2996 return sema.failWithContainsReferenceToComptimeVar(block, type_src, field_name, "captured value", val); 2997 } 2998 break :capture .wrap(.{ .@"comptime" = val.toIntern() }); 2999 } 3000 break :capture .wrap(.{ .runtime = sema.typeOf(air_ref).toIntern() }); 3001 }, 3002 .decl_val => |str| capture: { 3003 const decl_name = try ip.getOrPutString( 3004 gpa, 3005 io, 3006 pt.tid, 3007 sema.code.nullTerminatedString(str), 3008 .no_embedded_nulls, 3009 ); 3010 const nav = try sema.lookupIdentifier(block, decl_name); 3011 break :capture .wrap(.{ .nav_val = nav }); 3012 }, 3013 .decl_ref => |str| capture: { 3014 const decl_name = try ip.getOrPutString( 3015 gpa, 3016 io, 3017 pt.tid, 3018 sema.code.nullTerminatedString(str), 3019 .no_embedded_nulls, 3020 ); 3021 const nav = try sema.lookupIdentifier(block, decl_name); 3022 break :capture InternPool.CaptureValue.wrap(.{ .nav_ref = nav }); 3023 }, 3024 }; 3025 } 3026 3027 return captures; 3028 } 3029 3030 fn zirErrorSetDecl( 3031 sema: *Sema, 3032 inst: Zir.Inst.Index, 3033 ) CompileError!Air.Inst.Ref { 3034 const pt = sema.pt; 3035 const zcu = pt.zcu; 3036 const comp = zcu.comp; 3037 const gpa = comp.gpa; 3038 const io = comp.io; 3039 3040 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 3041 const extra = sema.code.extraData(Zir.Inst.ErrorSetDecl, inst_data.payload_index); 3042 3043 var names: InferredErrorSet.NameMap = .{}; 3044 try names.ensureUnusedCapacity(sema.arena, extra.data.fields_len); 3045 3046 var extra_index: u32 = @intCast(extra.end); 3047 const extra_index_end = extra_index + extra.data.fields_len; 3048 while (extra_index < extra_index_end) : (extra_index += 1) { 3049 const name_index: Zir.NullTerminatedString = @fromBackingInt(@intCast(sema.code.extra[extra_index])); 3050 const name = sema.code.nullTerminatedString(name_index); 3051 const name_ip = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, name, .no_embedded_nulls); 3052 _ = try pt.getErrorValue(name_ip); 3053 const result = names.getOrPutAssumeCapacity(name_ip); 3054 assert(!result.found_existing); // verified in AstGen 3055 } 3056 3057 return Air.internedToRef((try pt.errorSetFromUnsortedNames(names.keys())).toIntern()); 3058 } 3059 3060 fn zirRetPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 3061 const pt = sema.pt; 3062 const zcu = pt.zcu; 3063 3064 const src = block.nodeOffset(sema.code.instructions.items(.data)[@backingInt(inst)].node); 3065 3066 if (block.isComptime() or sema.fn_ret_ty.comptimeOnly(zcu)) { 3067 return sema.analyzeComptimeAlloc(block, src, sema.fn_ret_ty, .none); 3068 } 3069 3070 const target = zcu.getTarget(); 3071 const ptr_type = try pt.ptrType(.{ 3072 .child = sema.fn_ret_ty.toIntern(), 3073 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) }, 3074 }); 3075 3076 if (block.inlining != null) { 3077 // We are inlining a function call; this should be emitted as an alloc, not a ret_ptr. 3078 // TODO when functions gain result location support, the inlining struct in 3079 // Block should contain the return pointer, and we would pass that through here. 3080 return block.addTy(.alloc, ptr_type); 3081 } 3082 3083 return block.addTy(.ret_ptr, ptr_type); 3084 } 3085 3086 fn zirRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 3087 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].un_tok; 3088 const operand = sema.resolveInst(inst_data.operand); 3089 return sema.analyzeRef(block, block.tokenOffset(inst_data.src_tok), operand, .none); 3090 } 3091 3092 fn zirDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 3093 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].un_node; 3094 const src = block.nodeOffset(inst_data.src_node); 3095 const ptr_src = block.src(.{ .node_offset_deref_ptr = inst_data.src_node }); 3096 const operand = sema.resolveInst(inst_data.operand); 3097 3098 try sema.validateDeref(block, src, operand, sema.typeOf(operand)); 3099 3100 return sema.analyzeLoad(block, src, operand, ptr_src); 3101 } 3102 3103 fn zirRefDeref(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 3104 const pt = sema.pt; 3105 const zcu = pt.zcu; 3106 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].un_node; 3107 const src = block.nodeOffset(inst_data.src_node); 3108 const operand = sema.resolveInst(inst_data.operand); 3109 const operand_ty = sema.typeOf(operand); 3110 3111 try sema.validateDeref(block, src, operand, operand_ty); 3112 3113 const ptr_info = operand_ty.ptrInfo(zcu); 3114 return single_ptr: switch (ptr_info.flags.size) { 3115 .many => unreachable, // cannot be dereferenced directly 3116 .slice => { 3117 const slice_val = sema.resolveValue(operand).?; 3118 const slice = zcu.intern_pool.indexToKey(slice_val.toIntern()).slice; 3119 break :single_ptr .fromValue(try pt.sliceToArrayPtr(slice)); 3120 }, 3121 .c => { 3122 const single_ptr_ty = try pt.ptrType(p: { 3123 var p = ptr_info; 3124 p.flags.size = .one; 3125 p.flags.is_allowzero = false; 3126 break :p p; 3127 }); 3128 // https://github.com/ziglang/zig/issues/6597 3129 if (sema.resolveValue(operand)) |operand_val| { 3130 if (!operand_val.isNull(zcu)) { 3131 break :single_ptr .fromValue(try pt.getCoerced(operand_val, single_ptr_ty)); 3132 } 3133 } 3134 if (block.wantSafety()) { 3135 const is_non_null = try block.addUnOp(.is_non_null, operand); 3136 try sema.addSafetyCheck(block, src, is_non_null, .unwrap_null); 3137 } 3138 const single_ptr = try block.addTyOp(.ptr_cast, single_ptr_ty, operand); 3139 try sema.checkKnownAllocPtr(block, operand, single_ptr); 3140 break :single_ptr single_ptr; 3141 }, 3142 .one => operand, 3143 }; 3144 } 3145 3146 fn validateDeref( 3147 sema: *Sema, 3148 block: *Block, 3149 src: LazySrcLoc, 3150 ref: Air.Inst.Ref, 3151 ty: Type, 3152 ) CompileError!void { 3153 const pt = sema.pt; 3154 const zcu = pt.zcu; 3155 const ip = &zcu.intern_pool; 3156 if (ty.zigTypeTag(zcu) != .pointer) { 3157 return sema.fail(block, src, "cannot dereference non-pointer type '{f}'", .{ty.fmt(pt)}); 3158 } 3159 const size = ty.ptrSize(zcu); 3160 switch (size) { 3161 .many => return sema.fail(block, src, "index syntax required for unknown-length pointer type '{f}'", .{ty.fmt(pt)}), 3162 .one, .c, .slice => {}, 3163 } 3164 if (sema.resolveValue(ref)) |val| { 3165 // Error for deref of undef pointer, unless the pointee is OPV in which case it's legal. 3166 if (val.isUndef(zcu) and ty.childType(zcu).classify(zcu) != .one_possible_value) { 3167 return sema.fail(block, src, "cannot dereference undefined value", .{}); 3168 } 3169 // We need a defined slice length for the array type the slice should be dereferenced to. 3170 if (size == .slice and ip.indexToKey(val.toIntern()).slice.len == .undef_usize) { 3171 return sema.fail(block, src, "cannot dereference slice with undefined length", .{}); 3172 } 3173 } else if (size == .slice) { 3174 return sema.fail(block, src, "index syntax required to access runtime-known slice", .{}); 3175 } 3176 } 3177 3178 fn zirEnsureResultUsed(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { 3179 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].un_node; 3180 const operand = sema.resolveInst(inst_data.operand); 3181 const src = block.nodeOffset(inst_data.src_node); 3182 3183 return sema.ensureResultUsed(block, sema.typeOf(operand), src); 3184 } 3185 3186 fn ensureResultUsed( 3187 sema: *Sema, 3188 block: *Block, 3189 ty: Type, 3190 src: LazySrcLoc, 3191 ) CompileError!void { 3192 const pt = sema.pt; 3193 const zcu = pt.zcu; 3194 switch (ty.zigTypeTag(zcu)) { 3195 .void, .noreturn => return, 3196 .error_set => { 3197 return sema.fail(block, src, "error set of type '{f}' is ignored", .{ty.fmt(pt)}); 3198 }, 3199 .error_union => { 3200 const msg = msg: { 3201 const msg = try sema.errMsg(src, "error union of type '{f}' is ignored", .{ty.fmt(pt)}); 3202 errdefer msg.destroy(sema.gpa); 3203 try sema.errNote(src, msg, "consider using 'try', 'catch', or 'if'", .{}); 3204 break :msg msg; 3205 }; 3206 return sema.failWithOwnedErrorMsg(block, msg); 3207 }, 3208 else => { 3209 const msg = msg: { 3210 const msg = try sema.errMsg(src, "value of type '{f}' ignored", .{ty.fmt(pt)}); 3211 errdefer msg.destroy(sema.gpa); 3212 try sema.errNote(src, msg, "all non-void values must be used", .{}); 3213 try sema.errNote(src, msg, "to discard the value, assign it to '_'", .{}); 3214 break :msg msg; 3215 }; 3216 return sema.failWithOwnedErrorMsg(block, msg); 3217 }, 3218 } 3219 } 3220 3221 fn zirEnsureResultNonError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { 3222 const pt = sema.pt; 3223 const zcu = pt.zcu; 3224 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].un_node; 3225 const operand = sema.resolveInst(inst_data.operand); 3226 const src = block.nodeOffset(inst_data.src_node); 3227 const operand_ty = sema.typeOf(operand); 3228 switch (operand_ty.zigTypeTag(zcu)) { 3229 .error_set => return sema.fail(block, src, "error set is discarded", .{}), 3230 .error_union => { 3231 const msg = msg: { 3232 const msg = try sema.errMsg(src, "error union is discarded", .{}); 3233 errdefer msg.destroy(sema.gpa); 3234 try sema.errNote(src, msg, "consider using 'try', 'catch', or 'if'", .{}); 3235 break :msg msg; 3236 }; 3237 return sema.failWithOwnedErrorMsg(block, msg); 3238 }, 3239 else => return, 3240 } 3241 } 3242 3243 fn zirEnsureErrUnionPayloadVoid(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { 3244 const pt = sema.pt; 3245 const zcu = pt.zcu; 3246 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].un_node; 3247 const src = block.nodeOffset(inst_data.src_node); 3248 const operand = sema.resolveInst(inst_data.operand); 3249 const operand_ty = sema.typeOf(operand); 3250 const err_union_ty = if (operand_ty.zigTypeTag(zcu) == .pointer) 3251 operand_ty.childType(zcu) 3252 else 3253 operand_ty; 3254 if (err_union_ty.zigTypeTag(zcu) != .error_union) return; 3255 const payload_ty = err_union_ty.errorUnionPayload(zcu).zigTypeTag(zcu); 3256 if (payload_ty != .void and payload_ty != .noreturn) { 3257 const msg = msg: { 3258 const msg = try sema.errMsg(src, "error union payload is ignored", .{}); 3259 errdefer msg.destroy(sema.gpa); 3260 try sema.errNote(src, msg, "payload value can be explicitly ignored with '|_|'", .{}); 3261 break :msg msg; 3262 }; 3263 return sema.failWithOwnedErrorMsg(block, msg); 3264 } 3265 } 3266 3267 fn zirIndexablePtrLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 3268 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].un_node; 3269 const src = block.nodeOffset(inst_data.src_node); 3270 const object = sema.resolveInst(inst_data.operand); 3271 3272 return indexablePtrLen(sema, block, src, object); 3273 } 3274 3275 fn indexablePtrLen( 3276 sema: *Sema, 3277 block: *Block, 3278 src: LazySrcLoc, 3279 object: Air.Inst.Ref, 3280 ) CompileError!Air.Inst.Ref { 3281 const pt = sema.pt; 3282 const zcu = pt.zcu; 3283 const comp = zcu.comp; 3284 const gpa = comp.gpa; 3285 const io = comp.io; 3286 const object_ty = sema.typeOf(object); 3287 const is_pointer_to = object_ty.isSinglePointer(zcu); 3288 const indexable_ty = if (is_pointer_to) object_ty.childType(zcu) else object_ty; 3289 try sema.checkIndexable(block, src, indexable_ty); 3290 const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "len", .no_embedded_nulls); 3291 return sema.fieldVal(block, src, object, field_name, src); 3292 } 3293 3294 fn indexablePtrLenOrNone( 3295 sema: *Sema, 3296 block: *Block, 3297 src: LazySrcLoc, 3298 operand: Air.Inst.Ref, 3299 ) CompileError!Air.Inst.Ref { 3300 const pt = sema.pt; 3301 const zcu = pt.zcu; 3302 const comp = zcu.comp; 3303 const gpa = comp.gpa; 3304 const io = comp.io; 3305 const operand_ty = sema.typeOf(operand); 3306 try checkMemOperand(sema, block, src, operand_ty); 3307 switch (operand_ty.ptrSize(zcu)) { 3308 .many, .c => return .none, 3309 .one, .slice => {}, 3310 } 3311 const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "len", .no_embedded_nulls); 3312 return sema.fieldVal(block, src, operand, field_name, src); 3313 } 3314 3315 fn zirAllocExtended( 3316 sema: *Sema, 3317 block: *Block, 3318 extended: Zir.Inst.Extended.InstData, 3319 ) CompileError!Air.Inst.Ref { 3320 const pt = sema.pt; 3321 const zcu = pt.zcu; 3322 const gpa = sema.gpa; 3323 const extra = sema.code.extraData(Zir.Inst.AllocExtended, extended.operand); 3324 const var_src = block.nodeOffset(extra.data.src_node); 3325 const ty_src = block.src(.{ .node_offset_var_decl_ty = extra.data.src_node }); 3326 const align_src = block.src(.{ .node_offset_var_decl_align = extra.data.src_node }); 3327 const small: Zir.Inst.AllocExtended.Small = @bitCast(extended.small); 3328 3329 var extra_index: usize = extra.end; 3330 3331 const var_ty: Type = if (small.has_type) blk: { 3332 const type_ref: Zir.Inst.Ref = @fromBackingInt(@intCast(sema.code.extra[extra_index])); 3333 extra_index += 1; 3334 break :blk try sema.resolveType(block, ty_src, type_ref); 3335 } else undefined; 3336 3337 const alignment = if (small.has_align) blk: { 3338 const align_ref: Zir.Inst.Ref = @fromBackingInt(@intCast(sema.code.extra[extra_index])); 3339 extra_index += 1; 3340 break :blk try sema.resolveAlign(block, align_src, align_ref); 3341 } else .none; 3342 3343 if (small.has_type) { 3344 try sema.ensureLayoutResolved(var_ty, var_src, if (small.is_const) .constant else .variable); 3345 if (block.isComptime() or small.is_comptime or var_ty.comptimeOnly(zcu)) { 3346 return sema.analyzeComptimeAlloc(block, var_src, var_ty, alignment); 3347 } 3348 if (!small.is_const) { 3349 try sema.validateVarType(block, ty_src, var_ty, false); 3350 } 3351 const target = pt.zcu.getTarget(); 3352 if (sema.func_is_naked and var_ty.hasRuntimeBits(zcu)) { 3353 const store_src = block.src(.{ .node_offset_store_ptr = extra.data.src_node }); 3354 return sema.fail(block, store_src, "local variable in naked function", .{}); 3355 } 3356 const ptr_type = try pt.ptrType(.{ 3357 .child = var_ty.toIntern(), 3358 .flags = .{ 3359 .alignment = alignment, 3360 .address_space = target_util.defaultAddressSpace(target, .local), 3361 }, 3362 }); 3363 const ptr = try block.addTy(.alloc, ptr_type); 3364 if (small.is_const) { 3365 const ptr_inst = ptr.toIndex().?; 3366 try sema.maybe_comptime_allocs.put(gpa, ptr_inst, .{ .runtime_index = block.runtime_index }); 3367 try sema.base_allocs.put(gpa, ptr_inst, ptr_inst); 3368 } 3369 return ptr; 3370 } 3371 3372 if (block.isComptime() or small.is_comptime) { 3373 const iac_index: Air.Inst.Index = @fromBackingInt(@intCast(sema.air_instructions.len)); 3374 try sema.air_instructions.append(gpa, .{ 3375 .tag = .inferred_alloc_comptime, 3376 .data = .{ .inferred_alloc_comptime = .{ 3377 .alignment = alignment, 3378 .is_const = small.is_const, 3379 .ptr = undefined, 3380 } }, 3381 }); 3382 return iac_index.toRef(); 3383 } 3384 3385 const result_index = try block.addInstAsIndex(.{ 3386 .tag = .inferred_alloc, 3387 .data = .{ .inferred_alloc = .{ 3388 .alignment = alignment, 3389 .is_const = small.is_const, 3390 } }, 3391 }); 3392 try sema.unresolved_inferred_allocs.putNoClobber(gpa, result_index, .{}); 3393 if (small.is_const) { 3394 try sema.maybe_comptime_allocs.put(gpa, result_index, .{ .runtime_index = block.runtime_index }); 3395 try sema.base_allocs.put(gpa, result_index, result_index); 3396 } 3397 return result_index.toRef(); 3398 } 3399 3400 fn zirAllocComptime(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 3401 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].un_node; 3402 const ty_src = block.src(.{ .node_offset_var_decl_ty = inst_data.src_node }); 3403 const var_src = block.nodeOffset(inst_data.src_node); 3404 const var_ty = try sema.resolveType(block, ty_src, inst_data.operand); 3405 try sema.ensureLayoutResolved(var_ty, var_src, .variable); 3406 return sema.analyzeComptimeAlloc(block, var_src, var_ty, .none); 3407 } 3408 3409 fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 3410 const pt = sema.pt; 3411 const zcu = pt.zcu; 3412 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].un_node; 3413 const alloc = sema.resolveInst(inst_data.operand); 3414 const alloc_ty = sema.typeOf(alloc); 3415 const ptr_info = alloc_ty.ptrInfo(zcu); 3416 const elem_ty: Type = .fromInterned(ptr_info.child); 3417 3418 // If the alloc was created in a comptime scope, we already created a comptime alloc for it. 3419 // However, if the final constructed value does not reference comptime-mutable memory, we wish 3420 // to promote it to an anon decl. 3421 already_ct: { 3422 const ptr_val = sema.resolveValue(alloc) orelse break :already_ct; 3423 3424 // If this was a comptime inferred alloc, then `storeToInferredAllocComptime` 3425 // might have already done our job and created an anon decl ref. 3426 switch (zcu.intern_pool.indexToKey(ptr_val.toIntern())) { 3427 .ptr => |ptr| switch (ptr.base_addr) { 3428 .uav => { 3429 // The comptime-ification was already done for us. 3430 // Just make sure the pointer is const. 3431 return sema.makePtrConst(block, alloc); 3432 }, 3433 else => {}, 3434 }, 3435 else => {}, 3436 } 3437 3438 if (!sema.isComptimeMutablePtr(ptr_val)) break :already_ct; 3439 const ptr = zcu.intern_pool.indexToKey(ptr_val.toIntern()).ptr; 3440 assert(ptr.byte_offset == 0); 3441 const alloc_index = ptr.base_addr.comptime_alloc; 3442 const ct_alloc = sema.getComptimeAlloc(alloc_index); 3443 const interned = try ct_alloc.val.intern(pt, sema.arena); 3444 if (interned.canMutateComptimeVarState(zcu)) { 3445 // Preserve the comptime alloc, just make the pointer const. 3446 ct_alloc.val = .{ .interned = interned.toIntern() }; 3447 ct_alloc.is_const = true; 3448 return sema.makePtrConst(block, alloc); 3449 } else { 3450 // Promote the constant to an anon decl. 3451 const new_mut_ptr = Air.internedToRef(try pt.intern(.{ .ptr = .{ 3452 .ty = alloc_ty.toIntern(), 3453 .base_addr = .{ .uav = .{ 3454 .val = interned.toIntern(), 3455 .orig_ty = alloc_ty.toIntern(), 3456 } }, 3457 .byte_offset = 0, 3458 } })); 3459 return sema.makePtrConst(block, new_mut_ptr); 3460 } 3461 } 3462 3463 // Otherwise, check if the alloc is comptime-known despite being in a runtime scope. 3464 if (try sema.resolveComptimeKnownAllocPtr(block, alloc, null)) |ptr_val| { 3465 return sema.makePtrConst(block, Air.internedToRef(ptr_val)); 3466 } 3467 3468 if (elem_ty.comptimeOnly(zcu)) { 3469 // The value was initialized through RLS, so we didn't detect the runtime condition earlier. 3470 // TODO: source location of runtime control flow 3471 const init_src = block.src(.{ .node_offset_var_decl_init = inst_data.src_node }); 3472 return sema.fail(block, init_src, "value with comptime-only type '{f}' depends on runtime control flow", .{elem_ty.fmt(pt)}); 3473 } 3474 3475 // This is a runtime value. 3476 return sema.makePtrConst(block, alloc); 3477 } 3478 3479 /// If `alloc` is an inferred allocation, `resolved_inferred_ty` is taken to be its resolved 3480 /// type. Otherwise, it may be `null`, and the type will be inferred from `alloc`. 3481 fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref, resolved_alloc_ty: ?Type) CompileError!?InternPool.Index { 3482 const pt = sema.pt; 3483 const zcu = pt.zcu; 3484 const comp = zcu.comp; 3485 const gpa = comp.gpa; 3486 const io = comp.io; 3487 3488 const alloc_ty = resolved_alloc_ty orelse sema.typeOf(alloc); 3489 const ptr_info = alloc_ty.ptrInfo(zcu); 3490 const elem_ty: Type = .fromInterned(ptr_info.child); 3491 elem_ty.assertHasLayout(zcu); 3492 3493 const alloc_inst = alloc.toIndex() orelse return null; 3494 const comptime_info = sema.maybe_comptime_allocs.fetchRemove(alloc_inst) orelse return null; 3495 const stores = comptime_info.value.stores.items(.inst); 3496 3497 // If the elem type is OPV, no need to faff about with `stores`; just use the OPV. 3498 if (try elem_ty.onePossibleValue(pt)) |opv| { 3499 return sema.finishResolveComptimeKnownAllocPtr(block, alloc_ty, opv.toIntern(), null, alloc_inst, comptime_info.value); 3500 } 3501 3502 // Since the elem type isn't OPV, there should have been at least one store. 3503 assert(stores.len > 0); 3504 3505 // Since the entry existed in `maybe_comptime_allocs`, the allocation is comptime-known. 3506 // We will resolve and return its value. 3507 3508 // In general, we want to create a comptime alloc of the correct type and 3509 // apply the stores to that alloc in order. However, before going to all 3510 // that effort, let's optimize for the common case of a single store. 3511 3512 simple: { 3513 if (stores.len != 1) break :simple; 3514 const store_inst = sema.air_instructions.get(@backingInt(stores[0])); 3515 switch (store_inst.tag) { 3516 .store, .store_safe => {}, 3517 .set_union_tag, .optional_payload_ptr_set, .errunion_payload_ptr_set => break :simple, // there's OPV stuff going on! 3518 else => unreachable, 3519 } 3520 if (store_inst.data.bin_op.lhs != alloc) break :simple; 3521 3522 const val = store_inst.data.bin_op.rhs.toInterned().?; 3523 assert(zcu.intern_pool.typeOf(val) == elem_ty.toIntern()); 3524 return sema.finishResolveComptimeKnownAllocPtr(block, alloc_ty, val, null, alloc_inst, comptime_info.value); 3525 } 3526 3527 // The simple strategy failed: we must create a mutable comptime alloc and 3528 // perform all of the runtime store operations at comptime. 3529 3530 const ct_alloc = try sema.newComptimeAlloc(block, .unneeded, elem_ty, ptr_info.flags.alignment); 3531 3532 const alloc_ptr = try pt.intern(.{ .ptr = .{ 3533 .ty = alloc_ty.toIntern(), 3534 .base_addr = .{ .comptime_alloc = ct_alloc }, 3535 .byte_offset = 0, 3536 } }); 3537 3538 // Maps from pointers into the runtime allocs, to comptime-mutable pointers into the comptime alloc 3539 var ptr_mapping = std.AutoHashMap(Air.Inst.Index, InternPool.Index).init(sema.arena); 3540 try ptr_mapping.ensureTotalCapacity(@intCast(stores.len)); 3541 ptr_mapping.putAssumeCapacity(alloc_inst, alloc_ptr); 3542 3543 // Whilst constructing our mapping, we will also initialize optional and error union payloads when 3544 // we encounter the corresponding pointers. For this reason, the ordering of `to_map` matters. 3545 var to_map = try std.array_list.Managed(Air.Inst.Index).initCapacity(sema.arena, stores.len); 3546 3547 for (stores) |store_inst_idx| { 3548 const store_inst = sema.air_instructions.get(@backingInt(store_inst_idx)); 3549 const ptr_to_map = switch (store_inst.tag) { 3550 .store, .store_safe => store_inst.data.bin_op.lhs.toIndex().?, // Map the pointer being stored to. 3551 .set_union_tag => store_inst.data.bin_op.lhs.toIndex().?, // Map the union pointer. 3552 .optional_payload_ptr_set, .errunion_payload_ptr_set => store_inst_idx, // Map the generated pointer itself. 3553 else => unreachable, 3554 }; 3555 to_map.appendAssumeCapacity(ptr_to_map); 3556 } 3557 3558 const tmp_air = sema.getTmpAir(); 3559 3560 while (to_map.pop()) |air_ptr| { 3561 if (ptr_mapping.contains(air_ptr)) continue; 3562 const PointerMethod = union(enum) { 3563 same_addr, 3564 opt_payload, 3565 eu_payload, 3566 field: u32, 3567 elem: u64, 3568 }; 3569 const inst_tag = tmp_air.instructions.items(.tag)[@backingInt(air_ptr)]; 3570 const air_parent_ptr: Air.Inst.Ref, const method: PointerMethod = switch (inst_tag) { 3571 .struct_field_ptr => blk: { 3572 const data = tmp_air.extraData( 3573 Air.StructField, 3574 tmp_air.instructions.items(.data)[@backingInt(air_ptr)].ty_pl.payload, 3575 ).data; 3576 break :blk .{ 3577 data.struct_operand, 3578 .{ .field = data.field_index }, 3579 }; 3580 }, 3581 .struct_field_ptr_index_0, 3582 .struct_field_ptr_index_1, 3583 .struct_field_ptr_index_2, 3584 .struct_field_ptr_index_3, 3585 => .{ 3586 tmp_air.instructions.items(.data)[@backingInt(air_ptr)].ty_op.operand, 3587 .{ .field = switch (inst_tag) { 3588 .struct_field_ptr_index_0 => 0, 3589 .struct_field_ptr_index_1 => 1, 3590 .struct_field_ptr_index_2 => 2, 3591 .struct_field_ptr_index_3 => 3, 3592 else => unreachable, 3593 } }, 3594 }, 3595 .ptr_slice_ptr_ptr => .{ 3596 tmp_air.instructions.items(.data)[@backingInt(air_ptr)].ty_op.operand, 3597 .{ .field = Value.slice_ptr_index }, 3598 }, 3599 .ptr_slice_len_ptr => .{ 3600 tmp_air.instructions.items(.data)[@backingInt(air_ptr)].ty_op.operand, 3601 .{ .field = Value.slice_len_index }, 3602 }, 3603 .ptr_elem_ptr => blk: { 3604 const data = tmp_air.extraData( 3605 Air.Bin, 3606 tmp_air.instructions.items(.data)[@backingInt(air_ptr)].ty_pl.payload, 3607 ).data; 3608 const idx_val = sema.resolveValue(data.rhs).?; 3609 break :blk .{ 3610 data.lhs, 3611 .{ .elem = idx_val.toUnsignedInt(zcu) }, 3612 }; 3613 }, 3614 .ptr_cast => .{ 3615 tmp_air.instructions.items(.data)[@backingInt(air_ptr)].ty_op.operand, 3616 .same_addr, 3617 }, 3618 .optional_payload_ptr_set => .{ 3619 tmp_air.instructions.items(.data)[@backingInt(air_ptr)].ty_op.operand, 3620 .opt_payload, 3621 }, 3622 .errunion_payload_ptr_set => .{ 3623 tmp_air.instructions.items(.data)[@backingInt(air_ptr)].ty_op.operand, 3624 .eu_payload, 3625 }, 3626 else => unreachable, 3627 }; 3628 3629 const decl_parent_ptr = ptr_mapping.get(air_parent_ptr.toIndex().?) orelse { 3630 // Resolve the parent pointer first. 3631 // Note that we add in what seems like the wrong order, because we're popping from the end of this array. 3632 try to_map.appendSlice(&.{ air_ptr, air_parent_ptr.toIndex().? }); 3633 continue; 3634 }; 3635 const new_ptr_ty = tmp_air.typeOfIndex(air_ptr, &zcu.intern_pool).toIntern(); 3636 const new_ptr = switch (method) { 3637 .same_addr => try zcu.intern_pool.getCoerced(gpa, io, pt.tid, decl_parent_ptr, new_ptr_ty), 3638 .opt_payload => ptr: { 3639 // Set the optional to non-null at comptime. 3640 // If the payload is OPV, we must use that value instead of undef. 3641 const opt_ty = Value.fromInterned(decl_parent_ptr).typeOf(zcu).childType(zcu); 3642 const payload_ty = opt_ty.optionalChild(zcu); 3643 const payload_val = try payload_ty.onePossibleValue(pt) orelse try pt.undefValue(payload_ty); 3644 const opt_val = try pt.intern(.{ .opt = .{ 3645 .ty = opt_ty.toIntern(), 3646 .val = payload_val.toIntern(), 3647 } }); 3648 try sema.storePtrVal(block, LazySrcLoc.unneeded, Value.fromInterned(decl_parent_ptr), Value.fromInterned(opt_val), opt_ty); 3649 break :ptr (try Value.fromInterned(decl_parent_ptr).ptrOptPayload(pt)).toIntern(); 3650 }, 3651 .eu_payload => ptr: { 3652 // Set the error union to non-error at comptime. 3653 // If the payload is OPV, we must use that value instead of undef. 3654 const eu_ty = Value.fromInterned(decl_parent_ptr).typeOf(zcu).childType(zcu); 3655 const payload_ty = eu_ty.errorUnionPayload(zcu); 3656 const payload_val = try payload_ty.onePossibleValue(pt) orelse try pt.undefValue(payload_ty); 3657 const eu_val = try pt.intern(.{ .error_union = .{ 3658 .ty = eu_ty.toIntern(), 3659 .val = .{ .payload = payload_val.toIntern() }, 3660 } }); 3661 try sema.storePtrVal(block, LazySrcLoc.unneeded, Value.fromInterned(decl_parent_ptr), Value.fromInterned(eu_val), eu_ty); 3662 break :ptr (try Value.fromInterned(decl_parent_ptr).ptrEuPayload(pt)).toIntern(); 3663 }, 3664 .field => |idx| ptr: { 3665 const maybe_union_ty = Value.fromInterned(decl_parent_ptr).typeOf(zcu).childType(zcu); 3666 if (zcu.typeToUnion(maybe_union_ty)) |union_obj| if (union_obj.layout == .auto) { 3667 // As this is a union field, we must store to the pointer now to set the tag. 3668 // The payload value will be stored later, so undef is a sufficent payload for now. 3669 const payload_ty: Type = .fromInterned(union_obj.field_types.get(&zcu.intern_pool)[idx]); 3670 const payload_val = try pt.undefValue(payload_ty); 3671 const tag_val = try pt.enumValueFieldIndex(.fromInterned(union_obj.enum_tag_type), idx); 3672 const store_val = try pt.unionValue(maybe_union_ty, tag_val, payload_val); 3673 try sema.storePtrVal(block, .unneeded, .fromInterned(decl_parent_ptr), store_val, maybe_union_ty); 3674 }; 3675 break :ptr (try Value.fromInterned(decl_parent_ptr).ptrField(idx, pt)).toIntern(); 3676 }, 3677 .elem => |idx| ptr: { 3678 const parent_ptr_val: Value = .fromInterned(decl_parent_ptr); 3679 if (parent_ptr_val.typeOf(zcu).childType(zcu).zigTypeTag(zcu) == .vector) { 3680 const elem_ptr_ty: Type = .fromInterned(new_ptr_ty); 3681 // Vectors are a bit weird; see logic in `elemPtrVector`. 3682 if (elem_ptr_ty.ptrInfo(zcu).flags.vector_index != .none) { 3683 break :ptr (try pt.getCoerced(parent_ptr_val, elem_ptr_ty)).toIntern(); 3684 } else { 3685 const bit_offset = idx * @divExact(elem_ptr_ty.childType(zcu).bitSize(zcu), 8); 3686 break :ptr (try parent_ptr_val.getOffsetPtr(bit_offset, elem_ptr_ty, pt)).toIntern(); 3687 } 3688 } 3689 break :ptr (try parent_ptr_val.ptrElem(idx, pt)).toIntern(); 3690 }, 3691 }; 3692 try ptr_mapping.put(air_ptr, new_ptr); 3693 } 3694 3695 // We have a correlation between AIR pointers and decl pointers. Perform all stores at comptime. 3696 // Any implicit stores performed by `optional_payload_ptr_set` or `errunion_payload_ptr_set` 3697 // instructions were already done above. 3698 3699 for (stores) |store_inst_idx| { 3700 const store_inst = sema.air_instructions.get(@backingInt(store_inst_idx)); 3701 switch (store_inst.tag) { 3702 .optional_payload_ptr_set, .errunion_payload_ptr_set => {}, // Handled explicitly above 3703 .set_union_tag => { 3704 // Usually, we can ignore these, because the creation of the field pointer above 3705 // already did it for us. However, if the field is OPV, this is relevant, because 3706 // there is not going to be a store to the field. So we must initialize the union 3707 // tag if the field is OPV. 3708 const union_ptr_inst = store_inst.data.bin_op.lhs.toIndex().?; 3709 const union_ptr_val: Value = .fromInterned(ptr_mapping.get(union_ptr_inst).?); 3710 const tag_val: Value = .fromInterned(store_inst.data.bin_op.rhs.toInterned().?); 3711 const union_ty = union_ptr_val.typeOf(zcu).childType(zcu); 3712 const field_ty = union_ty.unionFieldType(tag_val, zcu).?; 3713 if (try field_ty.onePossibleValue(pt)) |payload_val| { 3714 const new_union_val = try pt.unionValue(union_ty, tag_val, payload_val); 3715 try sema.storePtrVal(block, .unneeded, union_ptr_val, new_union_val, union_ty); 3716 } 3717 }, 3718 .store, .store_safe => { 3719 const air_ptr_inst = store_inst.data.bin_op.lhs.toIndex().?; 3720 const store_val = sema.resolveValue(store_inst.data.bin_op.rhs).?; 3721 const new_ptr = ptr_mapping.get(air_ptr_inst).?; 3722 try sema.storePtrVal(block, .unneeded, .fromInterned(new_ptr), store_val, store_val.typeOf(zcu)); 3723 }, 3724 else => unreachable, 3725 } 3726 } 3727 3728 // The value is finalized - load it! 3729 const val = (try sema.pointerDeref(block, LazySrcLoc.unneeded, Value.fromInterned(alloc_ptr), alloc_ty)).?.toIntern(); 3730 return sema.finishResolveComptimeKnownAllocPtr(block, alloc_ty, val, ct_alloc, alloc_inst, comptime_info.value); 3731 } 3732 3733 /// Given the resolved comptime-known value, rewrites the dead AIR to not 3734 /// create a runtime stack allocation. Also places the resulting value into 3735 /// either an anon decl ref or a comptime alloc depending on whether it 3736 /// references comptime-mutable memory. If `existing_comptime_alloc` is 3737 /// passed, it is a scratch allocation which already contains `result_val`. 3738 /// Same return type as `resolveComptimeKnownAllocPtr` so we can tail call. 3739 fn finishResolveComptimeKnownAllocPtr( 3740 sema: *Sema, 3741 block: *Block, 3742 alloc_ty: Type, 3743 result_val: InternPool.Index, 3744 existing_comptime_alloc: ?ComptimeAllocIndex, 3745 alloc_inst: Air.Inst.Index, 3746 comptime_info: MaybeComptimeAlloc, 3747 ) CompileError!?InternPool.Index { 3748 const pt = sema.pt; 3749 const zcu = pt.zcu; 3750 3751 // We're almost done - we have the resolved comptime value. We just need to 3752 // eliminate the now-dead runtime instructions. 3753 3754 // This instruction has type `alloc_ty`, meaning we can rewrite the `alloc` AIR instruction to 3755 // this one to drop the side effect. We also need to rewrite the stores; we'll turn them to this 3756 // too because it doesn't really matter what they become. 3757 const nop_inst: Air.Inst = .{ .tag = .ptr_from_int, .data = .{ .ty_op = .{ 3758 .ty = alloc_ty, 3759 .operand = .zero_usize, 3760 } } }; 3761 3762 sema.air_instructions.set(@backingInt(alloc_inst), nop_inst); 3763 for (comptime_info.stores.items(.inst)) |store_inst| { 3764 sema.air_instructions.set(@backingInt(store_inst), nop_inst); 3765 } 3766 3767 if (Value.fromInterned(result_val).canMutateComptimeVarState(zcu)) { 3768 const alloc_index = existing_comptime_alloc orelse a: { 3769 const idx = try sema.newComptimeAlloc(block, .unneeded, alloc_ty.childType(zcu), alloc_ty.ptrAlignment(zcu)); 3770 const alloc = sema.getComptimeAlloc(idx); 3771 alloc.val = .{ .interned = result_val }; 3772 break :a idx; 3773 }; 3774 sema.getComptimeAlloc(alloc_index).is_const = true; 3775 return try pt.intern(.{ .ptr = .{ 3776 .ty = alloc_ty.toIntern(), 3777 .base_addr = .{ .comptime_alloc = alloc_index }, 3778 .byte_offset = 0, 3779 } }); 3780 } else { 3781 return try pt.intern(.{ .ptr = .{ 3782 .ty = alloc_ty.toIntern(), 3783 .base_addr = .{ .uav = .{ 3784 .orig_ty = alloc_ty.toIntern(), 3785 .val = result_val, 3786 } }, 3787 .byte_offset = 0, 3788 } }); 3789 } 3790 } 3791 3792 fn makePtrTyConst(sema: *Sema, ptr_ty: Type) CompileError!Type { 3793 var ptr_info = ptr_ty.ptrInfo(sema.pt.zcu); 3794 ptr_info.flags.is_const = true; 3795 return sema.pt.ptrType(ptr_info); 3796 } 3797 3798 fn makePtrConst(sema: *Sema, block: *Block, alloc: Air.Inst.Ref) CompileError!Air.Inst.Ref { 3799 const alloc_ty = sema.typeOf(alloc); 3800 const const_ptr_ty = try sema.makePtrTyConst(alloc_ty); 3801 3802 // Detect if a comptime value simply needs to have its type changed. 3803 if (sema.resolveValue(alloc)) |val| { 3804 return Air.internedToRef((try sema.pt.getCoerced(val, const_ptr_ty)).toIntern()); 3805 } 3806 3807 return block.addTyOp(.ptr_cast, const_ptr_ty, alloc); 3808 } 3809 3810 fn zirAllocInferredComptime( 3811 sema: *Sema, 3812 is_const: bool, 3813 ) CompileError!Air.Inst.Ref { 3814 const gpa = sema.gpa; 3815 3816 try sema.air_instructions.append(gpa, .{ 3817 .tag = .inferred_alloc_comptime, 3818 .data = .{ .inferred_alloc_comptime = .{ 3819 .alignment = .none, 3820 .is_const = is_const, 3821 .ptr = undefined, 3822 } }, 3823 }); 3824 return @as(Air.Inst.Index, @fromBackingInt(@intCast(sema.air_instructions.len - 1))).toRef(); 3825 } 3826 3827 fn zirAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 3828 const pt = sema.pt; 3829 const zcu = pt.zcu; 3830 3831 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].un_node; 3832 const ty_src = block.src(.{ .node_offset_var_decl_ty = inst_data.src_node }); 3833 const var_src = block.nodeOffset(inst_data.src_node); 3834 3835 const var_ty = try sema.resolveType(block, ty_src, inst_data.operand); 3836 try sema.ensureLayoutResolved(var_ty, var_src, .constant); 3837 if (block.isComptime() or var_ty.comptimeOnly(zcu)) { 3838 return sema.analyzeComptimeAlloc(block, var_src, var_ty, .none); 3839 } 3840 if (sema.func_is_naked and var_ty.hasRuntimeBits(zcu)) { 3841 const mut_src = block.src(.{ .node_offset_store_ptr = inst_data.src_node }); 3842 return sema.fail(block, mut_src, "local variable in naked function", .{}); 3843 } 3844 const target = zcu.getTarget(); 3845 const ptr_type = try pt.ptrType(.{ 3846 .child = var_ty.toIntern(), 3847 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) }, 3848 }); 3849 const ptr = try block.addTy(.alloc, ptr_type); 3850 const ptr_inst = ptr.toIndex().?; 3851 try sema.maybe_comptime_allocs.put(sema.gpa, ptr_inst, .{ .runtime_index = block.runtime_index }); 3852 try sema.base_allocs.put(sema.gpa, ptr_inst, ptr_inst); 3853 return ptr; 3854 } 3855 3856 fn zirAllocMut(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 3857 const pt = sema.pt; 3858 const zcu = pt.zcu; 3859 3860 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].un_node; 3861 const ty_src = block.src(.{ .node_offset_var_decl_ty = inst_data.src_node }); 3862 const var_src = block.nodeOffset(inst_data.src_node); 3863 3864 const var_ty = try sema.resolveType(block, ty_src, inst_data.operand); 3865 try sema.ensureLayoutResolved(var_ty, var_src, .variable); 3866 if (block.isComptime()) { 3867 return sema.analyzeComptimeAlloc(block, var_src, var_ty, .none); 3868 } 3869 if (sema.func_is_naked and var_ty.hasRuntimeBits(zcu)) { 3870 const store_src = block.src(.{ .node_offset_store_ptr = inst_data.src_node }); 3871 return sema.fail(block, store_src, "local variable in naked function", .{}); 3872 } 3873 try sema.validateVarType(block, ty_src, var_ty, false); 3874 const target = zcu.getTarget(); 3875 const ptr_type = try pt.ptrType(.{ 3876 .child = var_ty.toIntern(), 3877 .flags = .{ .address_space = target_util.defaultAddressSpace(target, .local) }, 3878 }); 3879 return block.addTy(.alloc, ptr_type); 3880 } 3881 3882 fn zirAllocInferred( 3883 sema: *Sema, 3884 block: *Block, 3885 is_const: bool, 3886 ) CompileError!Air.Inst.Ref { 3887 const gpa = sema.gpa; 3888 3889 if (block.isComptime()) { 3890 try sema.air_instructions.append(gpa, .{ 3891 .tag = .inferred_alloc_comptime, 3892 .data = .{ .inferred_alloc_comptime = .{ 3893 .alignment = .none, 3894 .is_const = is_const, 3895 .ptr = undefined, 3896 } }, 3897 }); 3898 return @as(Air.Inst.Index, @fromBackingInt(@intCast(sema.air_instructions.len - 1))).toRef(); 3899 } 3900 3901 const result_index = try block.addInstAsIndex(.{ 3902 .tag = .inferred_alloc, 3903 .data = .{ .inferred_alloc = .{ 3904 .alignment = .none, 3905 .is_const = is_const, 3906 } }, 3907 }); 3908 try sema.unresolved_inferred_allocs.putNoClobber(gpa, result_index, .{}); 3909 if (is_const) { 3910 try sema.maybe_comptime_allocs.put(gpa, result_index, .{ .runtime_index = block.runtime_index }); 3911 try sema.base_allocs.put(sema.gpa, result_index, result_index); 3912 } 3913 return result_index.toRef(); 3914 } 3915 3916 fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 3917 const pt = sema.pt; 3918 const zcu = pt.zcu; 3919 const gpa = sema.gpa; 3920 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].un_node; 3921 const src = block.nodeOffset(inst_data.src_node); 3922 const ty_src = block.src(.{ .node_offset_var_decl_ty = inst_data.src_node }); 3923 const ptr = sema.resolveInst(inst_data.operand); 3924 const ptr_inst = ptr.toIndex().?; 3925 const target = zcu.getTarget(); 3926 3927 switch (sema.air_instructions.items(.tag)[@backingInt(ptr_inst)]) { 3928 .inferred_alloc_comptime => { 3929 // The work was already done for us by `Sema.storeToInferredAllocComptime`. Also, since 3930 // we had a value of the exact correct type to store, the result type's layout must be 3931 // already resolved. So all we need to do here is return the pointer. 3932 const iac = sema.air_instructions.items(.data)[@backingInt(ptr_inst)].inferred_alloc_comptime; 3933 const resolved_ptr = iac.ptr; 3934 3935 if (std.debug.runtime_safety) { 3936 // The inferred_alloc_comptime should never be referenced again 3937 sema.air_instructions.set(@backingInt(ptr_inst), .{ .tag = undefined, .data = undefined }); 3938 } 3939 3940 const val = switch (zcu.intern_pool.indexToKey(resolved_ptr).ptr.base_addr) { 3941 .uav => |a| a.val, 3942 .comptime_alloc => |i| val: { 3943 const alloc = sema.getComptimeAlloc(i); 3944 break :val (try alloc.val.intern(pt, sema.arena)).toIntern(); 3945 }, 3946 else => unreachable, 3947 }; 3948 if (zcu.intern_pool.isFuncBody(val)) { 3949 const ty: Type = .fromInterned(zcu.intern_pool.typeOf(val)); 3950 if (ty.fnHasRuntimeBits(zcu)) { 3951 const orig_fn_index = zcu.intern_pool.unwrapCoercedFunc(val); 3952 try sema.addReferenceEntry(block, src, .wrap(.{ .func = orig_fn_index })); 3953 try zcu.ensureFuncBodyAnalysisQueued(orig_fn_index); 3954 } 3955 } 3956 3957 return Air.internedToRef(resolved_ptr); 3958 }, 3959 .inferred_alloc => { 3960 const ia1 = sema.air_instructions.items(.data)[@backingInt(ptr_inst)].inferred_alloc; 3961 const ia2 = sema.unresolved_inferred_allocs.fetchSwapRemove(ptr_inst).?.value; 3962 const peer_vals = try sema.arena.alloc(Air.Inst.Ref, ia2.prongs.items.len); 3963 for (peer_vals, ia2.prongs.items) |*peer_val, store_inst| { 3964 assert(sema.air_instructions.items(.tag)[@backingInt(store_inst)] == .store); 3965 const bin_op = sema.air_instructions.items(.data)[@backingInt(store_inst)].bin_op; 3966 peer_val.* = bin_op.rhs; 3967 } 3968 const final_elem_ty = try sema.resolvePeerTypes(block, ty_src, peer_vals, .none); 3969 // The layout of the peers is already resolved, so the layout of `final_elem_ty` is too. 3970 final_elem_ty.assertHasLayout(zcu); 3971 3972 const final_ptr_ty = try pt.ptrType(.{ 3973 .child = final_elem_ty.toIntern(), 3974 .flags = .{ 3975 .alignment = ia1.alignment, 3976 .address_space = target_util.defaultAddressSpace(target, .local), 3977 }, 3978 }); 3979 3980 if (!ia1.is_const) { 3981 try sema.validateVarType(block, ty_src, final_elem_ty, false); 3982 } else if (try sema.resolveComptimeKnownAllocPtr(block, ptr, final_ptr_ty)) |ptr_val| { 3983 const const_ptr_ty = try sema.makePtrTyConst(final_ptr_ty); 3984 const new_const_ptr = try pt.getCoerced(Value.fromInterned(ptr_val), const_ptr_ty); 3985 3986 return Air.internedToRef(new_const_ptr.toIntern()); 3987 } 3988 3989 if (final_elem_ty.comptimeOnly(zcu)) { 3990 // The alloc wasn't comptime-known per the above logic, so the 3991 // type cannot be comptime-only. 3992 // TODO: source location of runtime control flow 3993 return sema.fail(block, src, "value with comptime-only type '{f}' depends on runtime control flow", .{final_elem_ty.fmt(pt)}); 3994 } 3995 if (sema.func_is_naked and final_elem_ty.hasRuntimeBits(zcu)) { 3996 const mut_src = block.src(.{ .node_offset_store_ptr = inst_data.src_node }); 3997 return sema.fail(block, mut_src, "local variable in naked function", .{}); 3998 } 3999 // Change it to a normal alloc. 4000 sema.air_instructions.set(@backingInt(ptr_inst), .{ 4001 .tag = .alloc, 4002 .data = .{ .ty = final_ptr_ty }, 4003 }); 4004 4005 // Now we need to go back over all the store instructions, and do the logic as if 4006 // the new result ptr type was available. 4007 4008 for (ia2.prongs.items) |placeholder_inst| { 4009 var replacement_block = block.makeSubBlock(); 4010 defer replacement_block.instructions.deinit(gpa); 4011 4012 assert(sema.air_instructions.items(.tag)[@backingInt(placeholder_inst)] == .store); 4013 const bin_op = sema.air_instructions.items(.data)[@backingInt(placeholder_inst)].bin_op; 4014 try sema.storePtr2(&replacement_block, src, bin_op.lhs, src, bin_op.rhs, src, .store); 4015 4016 // If only one instruction is produced then we can replace the store 4017 // placeholder instruction with this instruction; no need for an entire block. 4018 if (replacement_block.instructions.items.len == 1) { 4019 const only_inst = replacement_block.instructions.items[0]; 4020 sema.air_instructions.set(@backingInt(placeholder_inst), sema.air_instructions.get(@backingInt(only_inst))); 4021 continue; 4022 } 4023 4024 // Here we replace the placeholder store instruction with a block 4025 // that does the actual store logic. 4026 _ = try replacement_block.addBr(placeholder_inst, .void_value); 4027 try sema.air_extra.ensureUnusedCapacity( 4028 gpa, 4029 @typeInfo(Air.Block).@"struct".field_names.len + replacement_block.instructions.items.len, 4030 ); 4031 sema.air_instructions.set(@backingInt(placeholder_inst), .{ 4032 .tag = .block, 4033 .data = .{ .ty_pl = .{ 4034 .ty = .void, 4035 .payload = sema.addExtraAssumeCapacity(Air.Block{ 4036 .body_len = @intCast(replacement_block.instructions.items.len), 4037 }), 4038 } }, 4039 }); 4040 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(replacement_block.instructions.items)); 4041 } 4042 4043 if (ia1.is_const) { 4044 return sema.makePtrConst(block, ptr); 4045 } else { 4046 return ptr; 4047 } 4048 }, 4049 else => unreachable, 4050 } 4051 } 4052 4053 fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 4054 const pt = sema.pt; 4055 const zcu = pt.zcu; 4056 const comp = zcu.comp; 4057 const gpa = comp.gpa; 4058 const io = comp.io; 4059 const ip = &zcu.intern_pool; 4060 4061 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 4062 const extra = sema.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index); 4063 const all_args = sema.code.refSlice(extra.end, extra.data.operands_len); 4064 const arg_pairs: []const [2]Zir.Inst.Ref = @as([*]const [2]Zir.Inst.Ref, @ptrCast(all_args))[0..@divExact(all_args.len, 2)]; 4065 const src = block.nodeOffset(inst_data.src_node); 4066 4067 var len: Air.Inst.Ref = .none; 4068 var len_val: ?Value = null; 4069 var len_idx: u32 = undefined; 4070 var any_runtime = false; 4071 4072 const runtime_arg_lens = try gpa.alloc(Air.Inst.Ref, arg_pairs.len); 4073 defer gpa.free(runtime_arg_lens); 4074 4075 // First pass to look for comptime values. 4076 for (arg_pairs, 0..) |zir_arg_pair, i_usize| { 4077 const i: u32 = @intCast(i_usize); 4078 runtime_arg_lens[i] = .none; 4079 if (zir_arg_pair[0] == .none) continue; 4080 4081 const arg_src = block.src(.{ .for_input = .{ 4082 .for_node_offset = inst_data.src_node, 4083 .input_index = i, 4084 } }); 4085 4086 const arg_len_uncoerced = if (zir_arg_pair[1] == .none) l: { 4087 // This argument is an indexable. 4088 const object = sema.resolveInst(zir_arg_pair[0]); 4089 const object_ty = sema.typeOf(object); 4090 if (!object_ty.isIndexable(zcu)) { 4091 // Instead of using checkIndexable we customize this error. 4092 const msg = msg: { 4093 const msg = try sema.errMsg(arg_src, "type '{f}' is not indexable and not a range", .{object_ty.fmt(pt)}); 4094 errdefer msg.destroy(sema.gpa); 4095 try sema.errNote(arg_src, msg, "for loop operand must be a range, array, slice, tuple, or vector", .{}); 4096 4097 if (object_ty.zigTypeTag(zcu) == .error_union) { 4098 try sema.errNote(arg_src, msg, "consider using 'try', 'catch', or 'if'", .{}); 4099 } 4100 4101 break :msg msg; 4102 }; 4103 return sema.failWithOwnedErrorMsg(block, msg); 4104 } 4105 if (!object_ty.indexableHasLen(zcu)) continue; 4106 break :l try sema.fieldVal(block, arg_src, object, try ip.getOrPutString(gpa, io, pt.tid, "len", .no_embedded_nulls), arg_src); 4107 } else l: { 4108 // This argument is a range. 4109 const range_start = sema.resolveInst(zir_arg_pair[0]); 4110 const range_end = sema.resolveInst(zir_arg_pair[1]); 4111 if (try sema.resolveDefinedValue(block, arg_src, range_start)) |start| { 4112 if (try sema.valuesEqual(start, .zero_usize, .usize)) break :l range_end; 4113 } 4114 break :l try sema.analyzeArithmetic(block, .sub, range_end, range_start, arg_src, arg_src, arg_src, true); 4115 }; 4116 const arg_len = try sema.coerce(block, .usize, arg_len_uncoerced, arg_src); 4117 if (len == .none) { 4118 len = arg_len; 4119 len_idx = i; 4120 } 4121 if (try sema.resolveDefinedValue(block, src, arg_len)) |arg_val| { 4122 if (len_val) |v| { 4123 if (!(try sema.valuesEqual(arg_val, v, .usize))) { 4124 const msg = msg: { 4125 const msg = try sema.errMsg(src, "non-matching for loop lengths", .{}); 4126 errdefer msg.destroy(gpa); 4127 const a_src = block.src(.{ .for_input = .{ 4128 .for_node_offset = inst_data.src_node, 4129 .input_index = len_idx, 4130 } }); 4131 try sema.errNote(a_src, msg, "length {f} here", .{ 4132 v.fmtValueSema(pt, sema), 4133 }); 4134 try sema.errNote(arg_src, msg, "length {f} here", .{ 4135 arg_val.fmtValueSema(pt, sema), 4136 }); 4137 break :msg msg; 4138 }; 4139 return sema.failWithOwnedErrorMsg(block, msg); 4140 } 4141 } else { 4142 len = arg_len; 4143 len_val = arg_val; 4144 len_idx = i; 4145 } 4146 continue; 4147 } 4148 runtime_arg_lens[i] = arg_len; 4149 any_runtime = true; 4150 } 4151 4152 if (len == .none) { 4153 const msg = msg: { 4154 const msg = try sema.errMsg(src, "unbounded for loop", .{}); 4155 errdefer msg.destroy(gpa); 4156 for (arg_pairs, 0..) |zir_arg_pair, i_usize| { 4157 const i: u32 = @intCast(i_usize); 4158 if (zir_arg_pair[0] == .none) continue; 4159 if (zir_arg_pair[1] != .none) continue; 4160 const object = sema.resolveInst(zir_arg_pair[0]); 4161 const object_ty = sema.typeOf(object); 4162 const arg_src = block.src(.{ .for_input = .{ 4163 .for_node_offset = inst_data.src_node, 4164 .input_index = i, 4165 } }); 4166 try sema.errNote(arg_src, msg, "type '{f}' has no upper bound", .{ 4167 object_ty.fmt(pt), 4168 }); 4169 } 4170 break :msg msg; 4171 }; 4172 return sema.failWithOwnedErrorMsg(block, msg); 4173 } 4174 4175 // Now for the runtime checks. 4176 if (any_runtime and block.wantSafety()) { 4177 var ok: Air.Inst.Ref = .none; 4178 for (runtime_arg_lens, 0..) |arg_len, i| { 4179 if (arg_len == .none) continue; 4180 if (i == len_idx) continue; 4181 const eq = try block.addBinOp(.cmp_eq, len, arg_len); 4182 ok = if (ok != .none) 4183 try block.addBinOp(.bit_and, ok, eq) 4184 else 4185 eq; 4186 } 4187 if (ok != .none) 4188 try sema.addSafetyCheck(block, src, ok, .for_len_mismatch); 4189 } 4190 4191 return len; 4192 } 4193 4194 /// Given any single pointer, retrieve a pointer to the payload of any optional 4195 /// or error union pointed to, initializing these pointers along the way. 4196 /// Given a `*E!?T`, returns a (valid) `*T`. 4197 /// May invalidate already-stored payload data. 4198 /// Asserts that the layout of the pointer child type is already resolved. 4199 fn optEuBasePtrInit(sema: *Sema, block: *Block, ptr: Air.Inst.Ref, src: LazySrcLoc) CompileError!Air.Inst.Ref { 4200 const pt = sema.pt; 4201 const zcu = pt.zcu; 4202 sema.typeOf(ptr).childType(zcu).assertHasLayout(zcu); 4203 var base_ptr = ptr; 4204 while (true) switch (sema.typeOf(base_ptr).childType(zcu).zigTypeTag(zcu)) { 4205 .error_union => base_ptr = try sema.analyzeErrUnionPayloadPtr(block, src, base_ptr, false, true), 4206 .optional => base_ptr = try sema.analyzeOptionalPayloadPtr(block, src, base_ptr, false, true), 4207 else => break, 4208 }; 4209 try sema.checkKnownAllocPtr(block, ptr, base_ptr); 4210 return base_ptr; 4211 } 4212 4213 fn zirOptEuBasePtrInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 4214 const un_node = sema.code.instructions.items(.data)[@backingInt(inst)].un_node; 4215 const ptr = sema.resolveInst(un_node.operand); 4216 const src = block.nodeOffset(un_node.src_node); 4217 try sema.ensureLayoutResolved(sema.typeOf(ptr).childType(sema.pt.zcu), src, .init); 4218 return sema.optEuBasePtrInit(block, ptr, src); 4219 } 4220 4221 fn zirCoercePtrElemTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 4222 const pt = sema.pt; 4223 const zcu = pt.zcu; 4224 const pl_node = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 4225 const src = block.nodeOffset(pl_node.src_node); 4226 const extra = sema.code.extraData(Zir.Inst.Bin, pl_node.payload_index).data; 4227 const uncoerced_val = sema.resolveInst(extra.rhs); 4228 const maybe_wrapped_ptr_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, extra.lhs) orelse return uncoerced_val; 4229 const ptr_ty = maybe_wrapped_ptr_ty.optEuBaseType(zcu); 4230 assert(ptr_ty.zigTypeTag(zcu) == .pointer); // validated by a previous instruction 4231 const elem_ty = ptr_ty.childType(zcu); 4232 switch (ptr_ty.ptrSize(zcu)) { 4233 .one => { 4234 const uncoerced_ty = sema.typeOf(uncoerced_val); 4235 if (elem_ty.zigTypeTag(zcu) == .array and elem_ty.childType(zcu).toIntern() == uncoerced_ty.toIntern()) { 4236 // We're trying to initialize a *[1]T with a reference to a T - don't perform any coercion. 4237 return uncoerced_val; 4238 } 4239 // If the destination type is anyopaque, don't coerce - the pointer will coerce instead. 4240 if (elem_ty.toIntern() == .anyopaque_type) { 4241 return uncoerced_val; 4242 } else { 4243 return sema.coerce(block, elem_ty, uncoerced_val, src); 4244 } 4245 }, 4246 .slice, .many => { 4247 // Our goal is to coerce `uncoerced_val` to an array of `elem_ty`. 4248 const val_ty = sema.typeOf(uncoerced_val); 4249 switch (val_ty.zigTypeTag(zcu)) { 4250 .array, .vector => {}, 4251 else => if (!val_ty.isTuple(zcu)) { 4252 return sema.fail(block, src, "expected array of '{f}', found '{f}'", .{ elem_ty.fmt(pt), val_ty.fmt(pt) }); 4253 }, 4254 } 4255 const want_ty = try pt.arrayType(.{ 4256 .len = val_ty.arrayLen(zcu), 4257 .child = elem_ty.toIntern(), 4258 .sentinel = if (ptr_ty.sentinel(zcu)) |s| s.toIntern() else .none, 4259 }); 4260 return sema.coerce(block, want_ty, uncoerced_val, src); 4261 }, 4262 .c => { 4263 // There's nothing meaningful to do here, because we don't know if this is meant to be a 4264 // single-pointer or a many-pointer. 4265 return uncoerced_val; 4266 }, 4267 } 4268 } 4269 4270 fn zirTryOperandTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is_ref: bool) CompileError!Air.Inst.Ref { 4271 const pt = sema.pt; 4272 const zcu = pt.zcu; 4273 const comp = zcu.comp; 4274 const gpa = comp.gpa; 4275 const io = comp.io; 4276 4277 const un_node = sema.code.instructions.items(.data)[@backingInt(inst)].un_node; 4278 const src = block.nodeOffset(un_node.src_node); 4279 4280 const operand_ty = try sema.resolveTypeOrPoison(block, src, un_node.operand) orelse return .generic_poison_type; 4281 4282 const payload_ty = if (is_ref) ty: { 4283 if (!operand_ty.isSinglePointer(zcu)) { 4284 return .generic_poison_type; // we can't get a meaningful result type here, since it will be `*E![n]T`, and we don't know `n`. 4285 } 4286 break :ty operand_ty.childType(zcu); 4287 } else operand_ty; 4288 4289 const err_set_ty: Type = err_set: { 4290 // There are awkward cases, like `?E`. Our strategy is to repeatedly unwrap optionals 4291 // until we hit an error union or set. 4292 var cur_ty = sema.fn_ret_ty; 4293 while (true) { 4294 switch (cur_ty.zigTypeTag(zcu)) { 4295 .error_set => break :err_set cur_ty, 4296 .error_union => break :err_set cur_ty.errorUnionSet(zcu), 4297 .optional => cur_ty = cur_ty.optionalChild(zcu), 4298 else => { 4299 // This function cannot return an error. 4300 // `try` is still valid if the error case is impossible, i.e. no error is returned. 4301 // So, the result type has an error set of `error{}`. 4302 break :err_set .fromInterned(try zcu.intern_pool.getErrorSetType(gpa, io, pt.tid, &.{})); 4303 }, 4304 } 4305 } 4306 }; 4307 4308 const eu_ty = try pt.errorUnionType(err_set_ty, payload_ty); 4309 4310 if (is_ref) { 4311 var ptr_info = operand_ty.ptrInfo(zcu); 4312 ptr_info.child = eu_ty.toIntern(); 4313 const eu_ptr_ty = try pt.ptrType(ptr_info); 4314 return Air.internedToRef(eu_ptr_ty.toIntern()); 4315 } else { 4316 return Air.internedToRef(eu_ty.toIntern()); 4317 } 4318 } 4319 4320 fn zirValidateRefTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { 4321 const pt = sema.pt; 4322 const zcu = pt.zcu; 4323 const un_tok = sema.code.instructions.items(.data)[@backingInt(inst)].un_tok; 4324 const src = block.tokenOffset(un_tok.src_tok); 4325 // In case of GenericPoison, we don't actually have a type, so this will be 4326 // treated as an untyped address-of operator. 4327 const ty_operand = try sema.resolveTypeOrPoison(block, src, un_tok.operand) orelse return; 4328 if (ty_operand.optEuBaseType(zcu).zigTypeTag(zcu) != .pointer) { 4329 return sema.failWithOwnedErrorMsg(block, msg: { 4330 const msg = try sema.errMsg(src, "expected type '{f}', found pointer", .{ty_operand.fmt(pt)}); 4331 errdefer msg.destroy(sema.gpa); 4332 try sema.errNote(src, msg, "address-of operator always returns a pointer", .{}); 4333 break :msg msg; 4334 }); 4335 } 4336 } 4337 4338 fn zirValidateConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { 4339 if (!block.isComptime()) return; 4340 4341 const un_node = sema.code.instructions.items(.data)[@backingInt(inst)].un_node; 4342 const src = block.nodeOffset(un_node.src_node); 4343 const init_ref = sema.resolveInst(un_node.operand); 4344 if (!try sema.isComptimeKnown(init_ref)) { 4345 return sema.failWithNeededComptime(block, src, null); 4346 } 4347 } 4348 4349 fn zirValidateArrayInitRefTy( 4350 sema: *Sema, 4351 block: *Block, 4352 inst: Zir.Inst.Index, 4353 ) CompileError!Air.Inst.Ref { 4354 const pt = sema.pt; 4355 const zcu = pt.zcu; 4356 const pl_node = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 4357 const src = block.nodeOffset(pl_node.src_node); 4358 const extra = sema.code.extraData(Zir.Inst.ArrayInitRefTy, pl_node.payload_index).data; 4359 const maybe_wrapped_ptr_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, extra.ptr_ty) orelse return .generic_poison_type; 4360 const ptr_ty = maybe_wrapped_ptr_ty.optEuBaseType(zcu); 4361 assert(ptr_ty.zigTypeTag(zcu) == .pointer); // validated by a previous instruction 4362 switch (zcu.intern_pool.indexToKey(ptr_ty.toIntern())) { 4363 .ptr_type => |ptr_type| switch (ptr_type.flags.size) { 4364 .slice, .many => { 4365 // Use array of correct length 4366 const arr_ty = try pt.arrayType(.{ 4367 .len = extra.elem_count, 4368 .child = ptr_ty.childType(zcu).toIntern(), 4369 .sentinel = if (ptr_ty.sentinel(zcu)) |s| s.toIntern() else .none, 4370 }); 4371 return Air.internedToRef(arr_ty.toIntern()); 4372 }, 4373 else => {}, 4374 }, 4375 else => {}, 4376 } 4377 // Otherwise, we just want the pointer child type 4378 const ret_ty = ptr_ty.childType(zcu); 4379 if (ret_ty.toIntern() == .anyopaque_type) { 4380 // The actual array type is unknown, which we represent with a generic poison. 4381 return .generic_poison_type; 4382 } 4383 const arr_ty = ret_ty.optEuBaseType(zcu); 4384 try sema.validateArrayInitTy(block, src, src, extra.elem_count, arr_ty); 4385 return Air.internedToRef(ret_ty.toIntern()); 4386 } 4387 4388 fn zirValidateArrayInitTy( 4389 sema: *Sema, 4390 block: *Block, 4391 inst: Zir.Inst.Index, 4392 is_result_ty: bool, 4393 ) CompileError!void { 4394 const pt = sema.pt; 4395 const zcu = pt.zcu; 4396 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 4397 const src = block.nodeOffset(inst_data.src_node); 4398 const ty_src: LazySrcLoc = if (is_result_ty) src else block.src(.{ .node_offset_init_ty = inst_data.src_node }); 4399 const extra = sema.code.extraData(Zir.Inst.ArrayInit, inst_data.payload_index).data; 4400 // It's okay for the type to be poison: this will result in an anonymous array init. 4401 const ty = try sema.resolveTypeOrPoison(block, ty_src, extra.ty) orelse return; 4402 const arr_ty = if (is_result_ty) ty.optEuBaseType(zcu) else ty; 4403 return sema.validateArrayInitTy(block, src, ty_src, extra.init_count, arr_ty); 4404 } 4405 4406 fn validateArrayInitTy( 4407 sema: *Sema, 4408 block: *Block, 4409 src: LazySrcLoc, 4410 ty_src: LazySrcLoc, 4411 init_count: u32, 4412 ty: Type, 4413 ) CompileError!void { 4414 const pt = sema.pt; 4415 const zcu = pt.zcu; 4416 switch (ty.zigTypeTag(zcu)) { 4417 .array => { 4418 const array_len = ty.arrayLen(zcu); 4419 if (init_count != array_len) { 4420 return sema.fail(block, src, "expected {d} array elements; found {d}", .{ 4421 array_len, init_count, 4422 }); 4423 } 4424 return; 4425 }, 4426 .vector => { 4427 const array_len = ty.arrayLen(zcu); 4428 if (init_count != array_len) { 4429 return sema.fail(block, src, "expected {d} vector elements; found {d}", .{ 4430 array_len, init_count, 4431 }); 4432 } 4433 return; 4434 }, 4435 .@"struct" => if (ty.isTuple(zcu)) { 4436 const array_len = ty.arrayLen(zcu); 4437 if (init_count > array_len) { 4438 return sema.fail(block, src, "expected at most {d} tuple fields; found {d}", .{ 4439 array_len, init_count, 4440 }); 4441 } 4442 return; 4443 }, 4444 else => {}, 4445 } 4446 return sema.failWithArrayInitNotSupported(block, ty_src, ty); 4447 } 4448 4449 fn zirValidateStructInitTy( 4450 sema: *Sema, 4451 block: *Block, 4452 inst: Zir.Inst.Index, 4453 is_result_ty: bool, 4454 ) CompileError!void { 4455 const pt = sema.pt; 4456 const zcu = pt.zcu; 4457 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].un_node; 4458 const src = block.nodeOffset(inst_data.src_node); 4459 // It's okay for the type to be poison: this will result in an anonymous struct init. 4460 const ty = try sema.resolveTypeOrPoison(block, src, inst_data.operand) orelse return; 4461 const struct_ty = if (is_result_ty) ty.optEuBaseType(zcu) else ty; 4462 4463 switch (struct_ty.zigTypeTag(zcu)) { 4464 .@"struct", .@"union" => return, 4465 else => {}, 4466 } 4467 return sema.failWithStructInitNotSupported(block, src, struct_ty); 4468 } 4469 4470 fn zirValidatePtrStructInit( 4471 sema: *Sema, 4472 block: *Block, 4473 inst: Zir.Inst.Index, 4474 ) CompileError!void { 4475 const pt = sema.pt; 4476 const zcu = pt.zcu; 4477 const validate_inst = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 4478 const init_src = block.nodeOffset(validate_inst.src_node); 4479 const validate_extra = sema.code.extraData(Zir.Inst.Block, validate_inst.payload_index); 4480 const instrs = sema.code.bodySlice(validate_extra.end, validate_extra.data.body_len); 4481 const field_ptr_data = sema.code.instructions.items(.data)[@backingInt(instrs[0])].pl_node; 4482 const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data; 4483 const object_ptr = sema.resolveInst(field_ptr_extra.lhs); 4484 const agg_ty = sema.typeOf(object_ptr).childType(zcu).optEuBaseType(zcu); 4485 switch (agg_ty.zigTypeTag(zcu)) { 4486 .@"struct" => return sema.validateStructInit( 4487 block, 4488 agg_ty, 4489 init_src, 4490 instrs, 4491 object_ptr, 4492 ), 4493 .@"union" => return sema.validateUnionInit( 4494 block, 4495 agg_ty, 4496 init_src, 4497 instrs, 4498 ), 4499 else => unreachable, 4500 } 4501 } 4502 4503 fn validateUnionInit( 4504 sema: *Sema, 4505 block: *Block, 4506 union_ty: Type, 4507 init_src: LazySrcLoc, 4508 instrs: []const Zir.Inst.Index, 4509 ) CompileError!void { 4510 if (instrs.len == 1) { 4511 // Trvial validation done, and the union tag was already set by machinery in `unionFieldPtr`. 4512 return; 4513 } 4514 const msg = msg: { 4515 const msg = try sema.errMsg( 4516 init_src, 4517 "cannot initialize multiple union fields at once; unions can only have one active field", 4518 .{}, 4519 ); 4520 errdefer msg.destroy(sema.gpa); 4521 4522 for (instrs[1..]) |inst| { 4523 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 4524 const inst_src = block.src(.{ .node_offset_initializer = inst_data.src_node }); 4525 try sema.errNote(inst_src, msg, "additional initializer here", .{}); 4526 } 4527 try sema.addDeclaredHereNote(msg, union_ty); 4528 break :msg msg; 4529 }; 4530 return sema.failWithOwnedErrorMsg(block, msg); 4531 } 4532 4533 fn validateStructInit( 4534 sema: *Sema, 4535 block: *Block, 4536 struct_ty: Type, 4537 init_src: LazySrcLoc, 4538 instrs: []const Zir.Inst.Index, 4539 struct_ptr: Air.Inst.Ref, 4540 ) CompileError!void { 4541 const pt = sema.pt; 4542 const zcu = pt.zcu; 4543 const comp = zcu.comp; 4544 const gpa = comp.gpa; 4545 const io = comp.io; 4546 const ip = &zcu.intern_pool; 4547 4548 // Tracks whether each field was explicitly initialized. 4549 const found_fields = try gpa.alloc(bool, struct_ty.structFieldCount(zcu)); 4550 defer gpa.free(found_fields); 4551 @memset(found_fields, false); 4552 4553 for (instrs) |field_ptr| { 4554 const field_ptr_data = sema.code.instructions.items(.data)[@backingInt(field_ptr)].pl_node; 4555 const field_src = block.src(.{ .node_offset_initializer = field_ptr_data.src_node }); 4556 const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data; 4557 const field_name = try ip.getOrPutString( 4558 gpa, 4559 io, 4560 pt.tid, 4561 sema.code.nullTerminatedString(field_ptr_extra.field_name_start), 4562 .no_embedded_nulls, 4563 ); 4564 const field_index = if (struct_ty.isTuple(zcu)) 4565 try sema.tupleFieldIndex(block, struct_ty, field_name, field_src) 4566 else 4567 try sema.structFieldIndex(block, struct_ty, field_name, field_src); 4568 assert(found_fields[field_index] == false); 4569 found_fields[field_index] = true; 4570 } 4571 4572 // Our job is simply to deal with default field values. Specifically, any field which was not 4573 // explicitly initialized must have its default value stored to the field pointer, or, if the 4574 // field has no default value, a compile error must be emitted instead. 4575 4576 // In the past, this code had other responsibilities, which involved some nasty AIR rewrites. However, 4577 // that work was actually all redundant: 4578 // 4579 // * If the struct value is comptime-known, field stores remain a perfectly valid way of initializing 4580 // the struct through RLS; there is no need to turn the field stores into one store. Comptime-known 4581 // consts are handled correctly either way thanks to `maybe_comptime_allocs` and friends. 4582 // 4583 // * If the struct type is comptime-only, we need to make sure all of the fields were comptime-known. 4584 // But the comptime-only type means that `struct_ptr` must be a comptime-mutable pointer, so the 4585 // field stores were to comptime-mutable pointers, so have already errored if not comptime-known. 4586 // 4587 // * If the value is runtime-known, then comptime-known fields must be validated as runtime values. 4588 // But this was already handled for every field store by the machinery in `checkComptimeKnownStore`. 4589 4590 var root_msg: ?*Zcu.ErrorMsg = null; 4591 errdefer if (root_msg) |msg| msg.destroy(sema.gpa); 4592 4593 for (found_fields, 0..) |explicit, i_usize| { 4594 const i: u32 = @intCast(i_usize); 4595 4596 if (explicit) continue; 4597 if (struct_ty.structFieldIsComptime(i, zcu)) continue; 4598 4599 if (!struct_ty.isTuple(zcu)) { 4600 try sema.ensureStructDefaultsResolved(struct_ty, init_src); 4601 } 4602 4603 const default_val = struct_ty.structFieldDefaultValue(i, zcu) orelse { 4604 const field_name = struct_ty.structFieldName(i, zcu).unwrap() orelse { 4605 const template = "missing tuple field with index {d}"; 4606 if (root_msg) |msg| { 4607 try sema.errNote(init_src, msg, template, .{i}); 4608 } else { 4609 root_msg = try sema.errMsg(init_src, template, .{i}); 4610 } 4611 continue; 4612 }; 4613 const template = "missing struct field: {f}"; 4614 const args = .{field_name.fmt(ip)}; 4615 if (root_msg) |msg| { 4616 try sema.errNote(init_src, msg, template, args); 4617 } else { 4618 root_msg = try sema.errMsg(init_src, template, args); 4619 } 4620 continue; 4621 }; 4622 4623 const field_src = init_src; // TODO better source location 4624 const default_field_ptr = try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(i), struct_ty); 4625 try sema.checkKnownAllocPtr(block, struct_ptr, default_field_ptr); 4626 try sema.storePtr2(block, init_src, default_field_ptr, init_src, .fromValue(default_val), field_src, .store); 4627 } 4628 4629 if (root_msg) |msg| { 4630 try sema.addDeclaredHereNote(msg, struct_ty); 4631 root_msg = null; 4632 return sema.failWithOwnedErrorMsg(block, msg); 4633 } 4634 } 4635 4636 fn zirValidatePtrArrayInit( 4637 sema: *Sema, 4638 block: *Block, 4639 inst: Zir.Inst.Index, 4640 ) CompileError!void { 4641 const pt = sema.pt; 4642 const zcu = pt.zcu; 4643 const validate_inst = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 4644 const init_src = block.nodeOffset(validate_inst.src_node); 4645 const validate_extra = sema.code.extraData(Zir.Inst.Block, validate_inst.payload_index); 4646 const instrs = sema.code.bodySlice(validate_extra.end, validate_extra.data.body_len); 4647 const first_elem_ptr_data = sema.code.instructions.items(.data)[@backingInt(instrs[0])].pl_node; 4648 const elem_ptr_extra = sema.code.extraData(Zir.Inst.ElemPtrImm, first_elem_ptr_data.payload_index).data; 4649 const array_ptr = sema.resolveInst(elem_ptr_extra.ptr); 4650 const array_ty = sema.typeOf(array_ptr).childType(zcu).optEuBaseType(zcu); 4651 const array_len = array_ty.arrayLen(zcu); 4652 4653 // Analagously to `validateStructInit`, our job is to handle default fields; either emitting AIR 4654 // to initialize them, or emitting a compile error if an unspecified field has no default. For 4655 // tuples, there are literally default field values, although they're guaranteed to be comptime 4656 // fields so we don't need to initialize them. For arrays, we may have a sentinel, which is never 4657 // specified so we always need to initialize here. For vectors, there's no such thing. 4658 4659 switch (array_ty.zigTypeTag(zcu)) { 4660 .@"struct" => if (instrs.len != array_len) { 4661 var root_msg: ?*Zcu.ErrorMsg = null; 4662 errdefer if (root_msg) |msg| msg.destroy(sema.gpa); 4663 4664 var i = instrs.len; 4665 while (i < array_len) : (i += 1) { 4666 if (array_ty.structFieldDefaultValue(i, zcu) == null) { 4667 const template = "missing tuple field with index {d}"; 4668 if (root_msg) |msg| { 4669 try sema.errNote(init_src, msg, template, .{i}); 4670 } else { 4671 root_msg = try sema.errMsg(init_src, template, .{i}); 4672 } 4673 continue; 4674 } 4675 } 4676 4677 if (root_msg) |msg| { 4678 root_msg = null; 4679 return sema.failWithOwnedErrorMsg(block, msg); 4680 } 4681 }, 4682 4683 .array => if (instrs.len != array_len) { 4684 return sema.fail(block, init_src, "expected {d} array elements; found {d}", .{ 4685 array_len, instrs.len, 4686 }); 4687 } else if (array_ty.sentinel(zcu)) |sentinel| { 4688 const array_len_ref = try pt.intRef(.usize, array_len); 4689 const sentinel_ptr = try sema.elemPtrArray(block, init_src, init_src, array_ptr, init_src, array_len_ref, true, true); 4690 try sema.checkKnownAllocPtr(block, array_ptr, sentinel_ptr); 4691 try sema.storePtr2(block, init_src, sentinel_ptr, init_src, .fromValue(sentinel), init_src, .store); 4692 }, 4693 4694 .vector => if (instrs.len != array_len) { 4695 return sema.fail(block, init_src, "expected {d} vector elements; found {d}", .{ 4696 array_len, instrs.len, 4697 }); 4698 }, 4699 4700 else => unreachable, 4701 } 4702 } 4703 4704 fn zirValidateDestructure(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { 4705 const pt = sema.pt; 4706 const zcu = pt.zcu; 4707 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 4708 const extra = sema.code.extraData(Zir.Inst.ValidateDestructure, inst_data.payload_index).data; 4709 const src = block.nodeOffset(inst_data.src_node); 4710 const destructure_src = block.nodeOffset(extra.destructure_node); 4711 const operand = sema.resolveInst(extra.operand); 4712 const operand_ty = sema.typeOf(operand); 4713 4714 if (!operand_ty.destructurable(zcu)) { 4715 return sema.failWithOwnedErrorMsg(block, msg: { 4716 const msg = try sema.errMsg(src, "type '{f}' cannot be destructured", .{operand_ty.fmt(pt)}); 4717 errdefer msg.destroy(sema.gpa); 4718 try sema.errNote(destructure_src, msg, "result destructured here", .{}); 4719 if (operand_ty.zigTypeTag(pt.zcu) == .error_union) { 4720 const base_op_ty = operand_ty.errorUnionPayload(zcu); 4721 if (base_op_ty.destructurable(zcu)) 4722 try sema.errNote(src, msg, "consider using 'try', 'catch', or 'if'", .{}); 4723 } 4724 break :msg msg; 4725 }); 4726 } 4727 4728 if (operand_ty.arrayLen(zcu) != extra.expect_len) { 4729 return sema.failWithOwnedErrorMsg(block, msg: { 4730 const msg = try sema.errMsg(src, "expected {d} elements for destructure, found {d}", .{ 4731 extra.expect_len, operand_ty.arrayLen(zcu), 4732 }); 4733 errdefer msg.destroy(sema.gpa); 4734 try sema.errNote(destructure_src, msg, "result destructured here", .{}); 4735 break :msg msg; 4736 }); 4737 } 4738 } 4739 4740 fn failWithBadMemberAccess( 4741 sema: *Sema, 4742 block: *Block, 4743 agg_ty: Type, 4744 field_src: LazySrcLoc, 4745 field_name: InternPool.NullTerminatedString, 4746 ) CompileError { 4747 const pt = sema.pt; 4748 const zcu = pt.zcu; 4749 const ip = &zcu.intern_pool; 4750 const kw_name = switch (agg_ty.zigTypeTag(zcu)) { 4751 .@"union" => "union", 4752 .@"struct" => "struct", 4753 .@"opaque" => "opaque", 4754 .@"enum" => "enum", 4755 else => unreachable, 4756 }; 4757 if (agg_ty.typeDeclInst(zcu)) |inst| { 4758 const inst_index = inst.resolve(ip) orelse return sema.failTransitive(.{ .lost_tracking = inst }); 4759 if (inst_index == .main_struct_inst) { 4760 return sema.fail(block, field_src, "root source file struct '{f}' has no member named '{f}'", .{ 4761 agg_ty.fmt(pt), field_name.fmt(ip), 4762 }); 4763 } 4764 } 4765 4766 return sema.fail(block, field_src, "{s} '{f}' has no member named '{f}'", .{ 4767 kw_name, agg_ty.fmt(pt), field_name.fmt(ip), 4768 }); 4769 } 4770 4771 fn failWithBadStructFieldAccess( 4772 sema: *Sema, 4773 block: *Block, 4774 struct_ty: Type, 4775 struct_type: InternPool.LoadedStructType, 4776 field_src: LazySrcLoc, 4777 field_name: InternPool.NullTerminatedString, 4778 ) CompileError { 4779 const pt = sema.pt; 4780 const zcu = pt.zcu; 4781 const ip = &zcu.intern_pool; 4782 4783 const msg = msg: { 4784 const msg = try sema.errMsg( 4785 field_src, 4786 "no field named '{f}' in struct '{f}'", 4787 .{ field_name.fmt(ip), struct_type.fqn.fmt(ip) }, 4788 ); 4789 errdefer msg.destroy(sema.gpa); 4790 try sema.errNote(struct_ty.srcLoc(zcu), msg, "struct declared here", .{}); 4791 break :msg msg; 4792 }; 4793 return sema.failWithOwnedErrorMsg(block, msg); 4794 } 4795 4796 fn failWithBadUnionFieldAccess( 4797 sema: *Sema, 4798 block: *Block, 4799 union_ty: Type, 4800 union_obj: InternPool.LoadedUnionType, 4801 field_src: LazySrcLoc, 4802 field_name: InternPool.NullTerminatedString, 4803 ) CompileError { 4804 const pt = sema.pt; 4805 const zcu = pt.zcu; 4806 const ip = &zcu.intern_pool; 4807 const gpa = sema.gpa; 4808 4809 const msg = msg: { 4810 const msg = try sema.errMsg( 4811 field_src, 4812 "no field named '{f}' in union '{f}'", 4813 .{ field_name.fmt(ip), union_obj.fqn.fmt(ip) }, 4814 ); 4815 errdefer msg.destroy(gpa); 4816 try sema.errNote(union_ty.srcLoc(zcu), msg, "union declared here", .{}); 4817 break :msg msg; 4818 }; 4819 return sema.failWithOwnedErrorMsg(block, msg); 4820 } 4821 4822 pub fn addDeclaredHereNote(sema: *Sema, parent: *Zcu.ErrorMsg, decl_ty: Type) Allocator.Error!void { 4823 const zcu = sema.pt.zcu; 4824 const src_loc = decl_ty.srcLocOrNull(zcu) orelse return; 4825 const category = switch (decl_ty.zigTypeTag(zcu)) { 4826 .@"union" => "union", 4827 .@"struct" => "struct", 4828 .@"enum" => "enum", 4829 .@"opaque" => "opaque", 4830 else => unreachable, 4831 }; 4832 try sema.errNote(src_loc, parent, "{s} declared here", .{category}); 4833 } 4834 4835 fn zirStoreToInferredPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { 4836 const pl_node = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 4837 const src = block.nodeOffset(pl_node.src_node); 4838 const bin = sema.code.extraData(Zir.Inst.Bin, pl_node.payload_index).data; 4839 const ptr = sema.resolveInst(bin.lhs); 4840 const operand = sema.resolveInst(bin.rhs); 4841 const ptr_inst = ptr.toIndex().?; 4842 const air_datas = sema.air_instructions.items(.data); 4843 4844 switch (sema.air_instructions.items(.tag)[@backingInt(ptr_inst)]) { 4845 .inferred_alloc_comptime => { 4846 const iac = &air_datas[@backingInt(ptr_inst)].inferred_alloc_comptime; 4847 return sema.storeToInferredAllocComptime(block, src, operand, iac); 4848 }, 4849 .inferred_alloc => { 4850 const ia = sema.unresolved_inferred_allocs.getPtr(ptr_inst).?; 4851 return sema.storeToInferredAlloc(block, src, ptr, operand, ia); 4852 }, 4853 else => unreachable, 4854 } 4855 } 4856 4857 fn storeToInferredAlloc( 4858 sema: *Sema, 4859 block: *Block, 4860 src: LazySrcLoc, 4861 ptr: Air.Inst.Ref, 4862 operand: Air.Inst.Ref, 4863 inferred_alloc: *InferredAlloc, 4864 ) CompileError!void { 4865 // Create a store instruction as a placeholder. This will be replaced by a 4866 // proper store sequence once we know the stored type. 4867 const dummy_store = try block.addBinOp(.store, ptr, operand); 4868 try sema.checkComptimeKnownStore(block, dummy_store, src); 4869 // Add the stored instruction to the set we will use to resolve peer types 4870 // for the inferred allocation. 4871 try inferred_alloc.prongs.append(sema.arena, dummy_store.toIndex().?); 4872 } 4873 4874 fn storeToInferredAllocComptime( 4875 sema: *Sema, 4876 block: *Block, 4877 src: LazySrcLoc, 4878 operand: Air.Inst.Ref, 4879 iac: *Air.Inst.Data.InferredAllocComptime, 4880 ) CompileError!void { 4881 const pt = sema.pt; 4882 const zcu = pt.zcu; 4883 const operand_ty = sema.typeOf(operand); 4884 // There will be only one store_to_inferred_ptr because we are running at comptime. 4885 // The alloc will turn into a Decl or a ComptimeAlloc. 4886 const operand_val = sema.resolveValue(operand) orelse { 4887 return sema.failWithNeededComptime(block, src, .{ .simple = .stored_to_comptime_var }); 4888 }; 4889 const alloc_ty = try pt.ptrType(.{ 4890 .child = operand_ty.toIntern(), 4891 .flags = .{ 4892 .alignment = iac.alignment, 4893 .is_const = iac.is_const, 4894 }, 4895 }); 4896 if (operand_ty.classify(zcu) == .one_possible_value or 4897 (iac.is_const and !operand_val.canMutateComptimeVarState(zcu))) 4898 { 4899 iac.ptr = try pt.intern(.{ .ptr = .{ 4900 .ty = alloc_ty.toIntern(), 4901 .base_addr = .{ .uav = .{ 4902 .val = operand_val.toIntern(), 4903 .orig_ty = alloc_ty.toIntern(), 4904 } }, 4905 .byte_offset = 0, 4906 } }); 4907 } else { 4908 const alloc_index = try sema.newComptimeAlloc(block, src, operand_ty, iac.alignment); 4909 sema.getComptimeAlloc(alloc_index).val = .{ .interned = operand_val.toIntern() }; 4910 iac.ptr = try pt.intern(.{ .ptr = .{ 4911 .ty = alloc_ty.toIntern(), 4912 .base_addr = .{ .comptime_alloc = alloc_index }, 4913 .byte_offset = 0, 4914 } }); 4915 } 4916 } 4917 4918 fn zirSetEvalBranchQuota(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { 4919 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].un_node; 4920 const src = block.nodeOffset(inst_data.src_node); 4921 const quota: u32 = @intCast(try sema.resolveInt(block, src, inst_data.operand, .u32, .{ .simple = .operand_setEvalBranchQuota })); 4922 sema.branch_quota = @max(sema.branch_quota, quota); 4923 sema.quota_request = @max(sema.quota_request, quota); 4924 } 4925 4926 fn zirStoreNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { 4927 const zir_tags = sema.code.instructions.items(.tag); 4928 const zir_datas = sema.code.instructions.items(.data); 4929 const inst_data = zir_datas[@backingInt(inst)].pl_node; 4930 const src = block.nodeOffset(inst_data.src_node); 4931 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; 4932 const ptr = sema.resolveInst(extra.lhs); 4933 const operand = sema.resolveInst(extra.rhs); 4934 4935 const is_ret = if (extra.lhs.toIndex()) |ptr_index| 4936 zir_tags[@backingInt(ptr_index)] == .ret_ptr 4937 else 4938 false; 4939 4940 const ptr_src = block.src(.{ .node_offset_store_ptr = inst_data.src_node }); 4941 const operand_src = block.src(.{ .node_offset_store_operand = inst_data.src_node }); 4942 const air_tag: Air.Inst.Tag = if (is_ret) 4943 .ret_ptr 4944 else if (block.wantSafety()) 4945 .store_safe 4946 else 4947 .store; 4948 return sema.storePtr2(block, src, ptr, ptr_src, operand, operand_src, air_tag); 4949 } 4950 4951 fn zirStr(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 4952 const pt = sema.pt; 4953 const zcu = pt.zcu; 4954 const comp = zcu.comp; 4955 const gpa = comp.gpa; 4956 const io = comp.io; 4957 const ip = &zcu.intern_pool; 4958 const bytes = sema.code.instructions.items(.data)[@backingInt(inst)].str.get(sema.code); 4959 return sema.addStrLit( 4960 try ip.getOrPutString(gpa, io, pt.tid, bytes, .maybe_embedded_nulls), 4961 bytes.len, 4962 ); 4963 } 4964 4965 fn addNullTerminatedStrLit(sema: *Sema, string: InternPool.NullTerminatedString) CompileError!Air.Inst.Ref { 4966 return sema.addStrLit(string.toString(), string.length(&sema.pt.zcu.intern_pool)); 4967 } 4968 4969 pub fn addStrLit(sema: *Sema, string: InternPool.String, len: u64) CompileError!Air.Inst.Ref { 4970 const pt = sema.pt; 4971 const array_ty = try pt.arrayType(.{ 4972 .len = len, 4973 .sentinel = .zero_u8, 4974 .child = .u8_type, 4975 }); 4976 const val = try pt.intern(.{ .aggregate = .{ 4977 .ty = array_ty.toIntern(), 4978 .storage = .{ .bytes = string }, 4979 } }); 4980 return sema.uavRef(.fromInterned(val)); 4981 } 4982 4983 fn uavRef(sema: *Sema, val: Value) CompileError!Air.Inst.Ref { 4984 return .fromValue(try sema.pt.uavValue(val)); 4985 } 4986 4987 fn zirInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 4988 _ = block; 4989 4990 const int = sema.code.instructions.items(.data)[@backingInt(inst)].int; 4991 return sema.pt.intRef(.comptime_int, int); 4992 } 4993 4994 fn zirIntBig(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 4995 _ = block; 4996 4997 const int = sema.code.instructions.items(.data)[@backingInt(inst)].str; 4998 const byte_count = int.len * @sizeOf(std.math.big.Limb); 4999 const limb_bytes = sema.code.string_bytes[@backingInt(int.start)..][0..byte_count]; 5000 5001 // TODO: this allocation and copy is only needed because the limbs may be unaligned. 5002 // If ZIR is adjusted so that big int limbs are guaranteed to be aligned, these 5003 // two lines can be removed. 5004 const limbs = try sema.arena.alloc(std.math.big.Limb, int.len); 5005 @memcpy(mem.sliceAsBytes(limbs), limb_bytes); 5006 5007 return Air.internedToRef((try sema.pt.intValue_big(.comptime_int, .{ 5008 .limbs = limbs, 5009 .positive = true, 5010 })).toIntern()); 5011 } 5012 5013 fn zirFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 5014 _ = block; 5015 const number = sema.code.instructions.items(.data)[@backingInt(inst)].float; 5016 return Air.internedToRef((try sema.pt.floatValue( 5017 .comptime_float, 5018 number, 5019 )).toIntern()); 5020 } 5021 5022 fn zirFloat128(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 5023 _ = block; 5024 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 5025 const extra = sema.code.extraData(Zir.Inst.Float128, inst_data.payload_index).data; 5026 const number = extra.get(); 5027 return Air.internedToRef((try sema.pt.floatValue(.comptime_float, number)).toIntern()); 5028 } 5029 5030 fn zirCompileError(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { 5031 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].un_node; 5032 const src = block.nodeOffset(inst_data.src_node); 5033 const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); 5034 const msg = try sema.resolveConstString(block, operand_src, inst_data.operand, .{ .simple = .compile_error_string }); 5035 return sema.fail(block, src, "{s}", .{msg}); 5036 } 5037 5038 fn zirCompileLog( 5039 sema: *Sema, 5040 block: *Block, 5041 extended: Zir.Inst.Extended.InstData, 5042 ) CompileError!Air.Inst.Ref { 5043 const pt = sema.pt; 5044 const zcu = pt.zcu; 5045 const comp = zcu.comp; 5046 const gpa = comp.gpa; 5047 const io = comp.io; 5048 5049 var aw: std.Io.Writer.Allocating = .init(gpa); 5050 defer aw.deinit(); 5051 const writer = &aw.writer; 5052 5053 const extra = sema.code.extraData(Zir.Inst.NodeMultiOp, extended.operand); 5054 const src_node = extra.data.src_node; 5055 const args = sema.code.refSlice(extra.end, extended.small); 5056 5057 for (args, 0..) |arg_ref, i| { 5058 if (i != 0) writer.writeAll(", ") catch return error.OutOfMemory; 5059 5060 const arg = sema.resolveInst(arg_ref); 5061 const arg_ty = sema.typeOf(arg); 5062 if (sema.resolveValue(arg)) |val| { 5063 writer.print("@as({f}, {f})", .{ 5064 arg_ty.fmt(pt), val.fmtValueSema(pt, sema), 5065 }) catch return error.OutOfMemory; 5066 } else { 5067 writer.print("@as({f}, [runtime value])", .{arg_ty.fmt(pt)}) catch return error.OutOfMemory; 5068 } 5069 } 5070 5071 const line_data = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, aw.written(), .no_embedded_nulls); 5072 5073 const line_idx: Zcu.CompileLogLine.Index = if (zcu.free_compile_log_lines.pop()) |idx| idx: { 5074 zcu.compile_log_lines.items[@backingInt(idx)] = .{ 5075 .next = .none, 5076 .data = line_data, 5077 }; 5078 break :idx idx; 5079 } else idx: { 5080 try zcu.compile_log_lines.append(gpa, .{ 5081 .next = .none, 5082 .data = line_data, 5083 }); 5084 break :idx @fromBackingInt(@intCast(zcu.compile_log_lines.items.len - 1)); 5085 }; 5086 5087 const gop = try zcu.compile_logs.getOrPut(gpa, sema.owner); 5088 if (gop.found_existing) { 5089 const prev_line = gop.value_ptr.last_line.get(zcu); 5090 assert(prev_line.next == .none); 5091 prev_line.next = line_idx.toOptional(); 5092 gop.value_ptr.last_line = line_idx; 5093 } else { 5094 gop.value_ptr.* = .{ 5095 .base_node_inst = block.src_base_inst, 5096 .node_offset = src_node, 5097 .first_line = line_idx, 5098 .last_line = line_idx, 5099 }; 5100 } 5101 return .void_value; 5102 } 5103 5104 fn zirPanic(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { 5105 const pt = sema.pt; 5106 const zcu = pt.zcu; 5107 5108 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].un_node; 5109 const src = block.nodeOffset(inst_data.src_node); 5110 const msg_inst = sema.resolveInst(inst_data.operand); 5111 5112 const arg_src = block.builtinCallArgSrc(inst_data.src_node, 0); 5113 const coerced_msg = try sema.coerce(block, .slice_const_u8, msg_inst, arg_src); 5114 5115 if (block.isComptime()) { 5116 const string = try sema.resolveConstString(block, arg_src, inst_data.operand, null); 5117 return sema.fail(block, src, "encountered @panic at comptime: {s}", .{string}); 5118 } 5119 5120 // We only apply the first hint in a branch. 5121 // This allows user-provided hints to override implicit cold hints. 5122 if (sema.branch_hint == null) { 5123 sema.branch_hint = .cold; 5124 } 5125 5126 if (!zcu.backendSupportsFeature(.panic_fn)) { 5127 _ = try block.addNoOp(.trap); 5128 return; 5129 } 5130 5131 try sema.ensureMemoizedStateResolved(src, .panic); 5132 const panic_fn_index = zcu.std_lang_decl_values.get(.@"panic.call"); 5133 const opt_usize_ty = try pt.optionalType(.usize_type); 5134 const null_ret_addr = Air.internedToRef((try pt.intern(.{ .opt = .{ 5135 .ty = opt_usize_ty.toIntern(), 5136 .val = .none, 5137 } }))); 5138 // `callBuiltin` also calls `addReferenceEntry` to the function body for us. 5139 try sema.callBuiltin( 5140 block, 5141 src, 5142 .fromIntern(panic_fn_index), 5143 .auto, 5144 &.{ coerced_msg, null_ret_addr }, 5145 .@"@panic", 5146 ); 5147 } 5148 5149 fn zirTrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { 5150 const src_node = sema.code.instructions.items(.data)[@backingInt(inst)].node; 5151 const src = block.nodeOffset(src_node); 5152 if (block.isComptime()) 5153 return sema.fail(block, src, "encountered @trap at comptime", .{}); 5154 _ = try block.addNoOp(.trap); 5155 } 5156 5157 fn zirBreakpoint(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void { 5158 const src_node: std.zig.Ast.Node.Offset = @fromBackingInt(@intCast(@as(i32, @bitCast(extended.operand)))); 5159 const src = block.nodeOffset(src_node); 5160 if (block.isComptime()) 5161 return sema.fail(block, src, "encountered @breakpoint at comptime", .{}); 5162 _ = try block.addNoOp(.breakpoint); 5163 } 5164 5165 fn zirLoop(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 5166 const pt = sema.pt; 5167 const zcu = pt.zcu; 5168 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 5169 const src = parent_block.nodeOffset(inst_data.src_node); 5170 const extra = sema.code.extraData(Zir.Inst.Block, inst_data.payload_index); 5171 const body = sema.code.bodySlice(extra.end, extra.data.body_len); 5172 const gpa = sema.gpa; 5173 5174 // AIR expects a block outside the loop block too. 5175 // Reserve space for a Loop instruction so that generated Break instructions can 5176 // point to it, even if it doesn't end up getting used because the code ends up being 5177 // comptime evaluated. 5178 const block_inst: Air.Inst.Index = @fromBackingInt(@intCast(sema.air_instructions.len)); 5179 const loop_inst: Air.Inst.Index = @fromBackingInt(@intCast(@backingInt(block_inst) + 1)); 5180 try sema.air_instructions.ensureUnusedCapacity(gpa, 2); 5181 sema.air_instructions.appendAssumeCapacity(.{ 5182 .tag = .block, 5183 .data = undefined, 5184 }); 5185 sema.air_instructions.appendAssumeCapacity(.{ 5186 .tag = .loop, 5187 .data = .{ .ty_pl = .{ 5188 .ty = .noreturn, 5189 .payload = undefined, 5190 } }, 5191 }); 5192 var label: Block.Label = .{ 5193 .zir_block = inst, 5194 .merges = .{ 5195 .src_locs = .empty, 5196 .results = .empty, 5197 .br_list = .empty, 5198 .block_inst = block_inst, 5199 }, 5200 }; 5201 var child_block = parent_block.makeSubBlock(); 5202 child_block.label = &label; 5203 child_block.runtime_cond = null; 5204 child_block.runtime_loop = src; 5205 child_block.runtime_index.increment(); 5206 const merges = &child_block.label.?.merges; 5207 5208 defer child_block.instructions.deinit(gpa); 5209 defer merges.deinit(gpa); 5210 5211 var loop_block = child_block.makeSubBlock(); 5212 defer loop_block.instructions.deinit(gpa); 5213 5214 // Use `analyzeBodyInner` directly to push any comptime control flow up the stack. 5215 try sema.analyzeBodyInner(&loop_block, body); 5216 5217 // TODO: since AIR has `repeat` now, we could change ZIR to generate 5218 // more optimal code utilizing `repeat` instructions across blocks! 5219 // For now, if the generated loop body does not terminate `noreturn`, 5220 // then `analyzeBodyInner` is signalling that it ended with `repeat`. 5221 5222 const loop_block_len = loop_block.instructions.items.len; 5223 if (loop_block_len > 0 and sema.typeOf(loop_block.instructions.items[loop_block_len - 1].toRef()).isNoReturn(zcu)) { 5224 // If the loop ended with a noreturn terminator, then there is no way for it to loop, 5225 // so we can just use the block instead. 5226 try child_block.instructions.appendSlice(gpa, loop_block.instructions.items); 5227 } else { 5228 _ = try loop_block.addInst(.{ 5229 .tag = .repeat, 5230 .data = .{ .repeat = .{ 5231 .loop_inst = loop_inst, 5232 } }, 5233 }); 5234 // Note that `loop_block_len` is now off by one. 5235 5236 try child_block.instructions.append(gpa, loop_inst); 5237 5238 try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).@"struct".field_names.len + loop_block_len + 1); 5239 sema.air_instructions.items(.data)[@backingInt(loop_inst)].ty_pl.payload = sema.addExtraAssumeCapacity( 5240 Air.Block{ .body_len = @intCast(loop_block_len + 1) }, 5241 ); 5242 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(loop_block.instructions.items)); 5243 } 5244 return sema.resolveAnalyzedBlock(parent_block, src, &child_block, merges, false); 5245 } 5246 5247 fn zirSuspendBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 5248 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 5249 const src = parent_block.nodeOffset(inst_data.src_node); 5250 return sema.failWithUseOfAsync(parent_block, src); 5251 } 5252 5253 fn zirBlock(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 5254 const pl_node = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 5255 const src = parent_block.nodeOffset(pl_node.src_node); 5256 const extra = sema.code.extraData(Zir.Inst.Block, pl_node.payload_index); 5257 const body = sema.code.bodySlice(extra.end, extra.data.body_len); 5258 const gpa = sema.gpa; 5259 5260 // Reserve space for a Block instruction so that generated Break instructions can 5261 // point to it, even if it doesn't end up getting used because the code ends up being 5262 // comptime evaluated or is an unlabeled block. 5263 const block_inst: Air.Inst.Index = @fromBackingInt(@intCast(sema.air_instructions.len)); 5264 try sema.air_instructions.append(gpa, .{ 5265 .tag = .block, 5266 .data = undefined, 5267 }); 5268 5269 var label: Block.Label = .{ 5270 .zir_block = inst, 5271 .merges = .{ 5272 .src_locs = .empty, 5273 .results = .empty, 5274 .br_list = .empty, 5275 .block_inst = block_inst, 5276 }, 5277 }; 5278 5279 var child_block: Block = .{ 5280 .parent = parent_block, 5281 .sema = sema, 5282 .namespace = parent_block.namespace, 5283 .instructions = .empty, 5284 .label = &label, 5285 .inlining = parent_block.inlining, 5286 .comptime_reason = parent_block.comptime_reason, 5287 .is_typeof = parent_block.is_typeof, 5288 .want_safety = parent_block.want_safety, 5289 .float_mode = parent_block.float_mode, 5290 .runtime_cond = parent_block.runtime_cond, 5291 .runtime_loop = parent_block.runtime_loop, 5292 .runtime_index = parent_block.runtime_index, 5293 .error_return_trace_index = parent_block.error_return_trace_index, 5294 .src_base_inst = parent_block.src_base_inst, 5295 .type_name_ctx = parent_block.type_name_ctx, 5296 .type_fqn_ctx = parent_block.type_fqn_ctx, 5297 }; 5298 5299 defer child_block.instructions.deinit(gpa); 5300 defer label.merges.deinit(gpa); 5301 5302 return sema.resolveBlockBody(parent_block, src, &child_block, body, inst, &label.merges); 5303 } 5304 5305 /// Semantically analyze the given ZIR body, emitting any resulting runtime code into the AIR block 5306 /// specified by `child_block` if necessary (and emitting this block into `parent_block`). 5307 /// TODO: `merges` is known from `child_block`, remove this parameter. 5308 fn resolveBlockBody( 5309 sema: *Sema, 5310 parent_block: *Block, 5311 src: LazySrcLoc, 5312 child_block: *Block, 5313 body: []const Zir.Inst.Index, 5314 /// This is the instruction that a break instruction within `body` can 5315 /// use to return from the body. 5316 body_inst: Zir.Inst.Index, 5317 merges: *Block.Merges, 5318 ) CompileError!Air.Inst.Ref { 5319 if (child_block.isComptime()) { 5320 return sema.resolveInlineBody(child_block, body, body_inst); 5321 } else { 5322 assert(sema.air_instructions.items(.tag)[@backingInt(merges.block_inst)] == .block); 5323 var need_debug_scope = false; 5324 child_block.need_debug_scope = &need_debug_scope; 5325 if (sema.analyzeBodyInner(child_block, body)) { 5326 return sema.resolveAnalyzedBlock(parent_block, src, child_block, merges, need_debug_scope); 5327 } else |err| switch (err) { 5328 error.ComptimeBreak => { 5329 const break_inst = sema.comptime_break_inst; 5330 const break_data = sema.code.instructions.items(.data)[@backingInt(break_inst)].@"break";