╭─────────────╮╭────────────╮ │scroll to top││next lines →│ ╰─────────────╯╰────────────╯ ╭ Sema.zig ─────────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭ find file ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ ╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │ │ │http│ ssh │ │ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
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"; 5331 const extra = sema.code.extraData(Zir.Inst.Break, break_data.payload_index).data; 5332 const breaks_to_body = extra.block_inst == body_inst; 5333 5334 // Comptime control flow is happening, however child_block may still contain 5335 // runtime instructions which need to be copied to the parent block. 5336 if (need_debug_scope and child_block.instructions.items.len > 0) { 5337 // We need a runtime block for scoping reasons. The break 5338 // operand may have been produced by a runtime instruction 5339 // inside `child_blocks`. 5340 const operand = sema.resolveInst(break_data.operand); 5341 const operand_ty = sema.typeOf(operand); 5342 _ = try child_block.addBr(merges.block_inst, operand); 5343 try parent_block.instructions.append(sema.gpa, merges.block_inst); 5344 try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.Block).@"struct".field_names.len + 5345 child_block.instructions.items.len); 5346 sema.air_instructions.items(.data)[@backingInt(merges.block_inst)] = .{ .ty_pl = .{ 5347 .ty = operand_ty, 5348 .payload = sema.addExtraAssumeCapacity(Air.Block{ 5349 .body_len = @intCast(child_block.instructions.items.len), 5350 }), 5351 } }; 5352 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(child_block.instructions.items)); 5353 5354 // The block result now holds the operand value, so we remap 5355 // the operand such that an enclosing scope which resolves 5356 // it picks up the block result rather than the internal 5357 // block instruction. 5358 if (break_data.operand.toIndex()) |operand_zir| { 5359 sema.inst_map.putAssumeCapacity(operand_zir, merges.block_inst.toRef()); 5360 } 5361 if (breaks_to_body) { 5362 return merges.block_inst.toRef(); 5363 } else { 5364 return error.ComptimeBreak; 5365 } 5366 } else { 5367 // We can copy instructions directly to the parent block. 5368 try parent_block.instructions.appendSlice(sema.gpa, child_block.instructions.items); 5369 if (breaks_to_body) { 5370 return sema.resolveInst(break_data.operand); 5371 } else { 5372 return error.ComptimeBreak; 5373 } 5374 } 5375 }, 5376 else => |e| return e, 5377 } 5378 } 5379 } 5380 5381 /// After a body corresponding to an AIR `block` has been analyzed, this function places them into 5382 /// the block pointed at by `merges.block_inst` if necessary, or the block may be elided in favor of 5383 /// inlining the instructions directly into the parent block. Either way, it considers all merges of 5384 /// this block, and combines them appropriately using peer type resolution, returning the final 5385 /// value of the block. 5386 fn resolveAnalyzedBlock( 5387 sema: *Sema, 5388 parent_block: *Block, 5389 src: LazySrcLoc, 5390 child_block: *Block, 5391 merges: *Block.Merges, 5392 need_debug_scope: bool, 5393 ) CompileError!Air.Inst.Ref { 5394 const gpa = sema.gpa; 5395 const pt = sema.pt; 5396 const zcu = pt.zcu; 5397 5398 // Blocks must terminate with noreturn instruction. 5399 assert(child_block.instructions.items.len != 0); 5400 assert(sema.typeOf(child_block.instructions.items[child_block.instructions.items.len - 1].toRef()).isNoReturn(zcu)); 5401 5402 const block_tag = sema.air_instructions.items(.tag)[@backingInt(merges.block_inst)]; 5403 switch (block_tag) { 5404 .block => {}, 5405 .dbg_inline_block => assert(need_debug_scope), 5406 else => unreachable, 5407 } 5408 if (merges.results.items.len == 0) { 5409 switch (block_tag) { 5410 .block => { 5411 // No need for a block instruction. We can put the new instructions 5412 // directly into the parent block. 5413 if (need_debug_scope) { 5414 // The code following this block is unreachable, as the block has no 5415 // merges, so we don't necessarily need to emit this as an AIR block. 5416 // However, we need a block *somewhere* to make the scoping correct, 5417 // so forward this request to the parent block. 5418 if (parent_block.need_debug_scope) |ptr| ptr.* = true; 5419 } 5420 try parent_block.instructions.appendSlice(gpa, child_block.instructions.items); 5421 return child_block.instructions.items[child_block.instructions.items.len - 1].toRef(); 5422 }, 5423 .dbg_inline_block => { 5424 // Create a block containing all instruction from the body. 5425 try parent_block.instructions.append(gpa, merges.block_inst); 5426 try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.DbgInlineBlock).@"struct".field_names.len + 5427 child_block.instructions.items.len); 5428 sema.air_instructions.items(.data)[@backingInt(merges.block_inst)] = .{ .ty_pl = .{ 5429 .ty = .noreturn, 5430 .payload = sema.addExtraAssumeCapacity(Air.DbgInlineBlock{ 5431 .func = child_block.inlining.?.func, 5432 .body_len = @intCast(child_block.instructions.items.len), 5433 }), 5434 } }; 5435 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(child_block.instructions.items)); 5436 return merges.block_inst.toRef(); 5437 }, 5438 else => unreachable, 5439 } 5440 } 5441 if (merges.results.items.len == 1) { 5442 // If the `break` is trailing, we may be able to elide the AIR block here 5443 // by appending the new instructions directly to the parent block. 5444 if (!need_debug_scope) { 5445 const last_inst_index = child_block.instructions.items.len - 1; 5446 const last_inst = child_block.instructions.items[last_inst_index]; 5447 if (sema.getBreakBlock(last_inst)) |br_block| { 5448 if (br_block == merges.block_inst) { 5449 // Great, the last instruction is the break! Put the instructions 5450 // directly into the parent block. 5451 try parent_block.instructions.appendSlice(gpa, child_block.instructions.items[0..last_inst_index]); 5452 return merges.results.items[0]; 5453 } 5454 } 5455 } 5456 // Okay, we need a runtime block. If the value is comptime-known, the 5457 // block should just return void, and we return the merge result 5458 // directly. Otherwise, we can defer to the logic below. 5459 if (sema.resolveValue(merges.results.items[0])) |result_val| { 5460 // Create a block containing all instruction from the body. 5461 try parent_block.instructions.append(gpa, merges.block_inst); 5462 switch (block_tag) { 5463 .block => { 5464 try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).@"struct".field_names.len + 5465 child_block.instructions.items.len); 5466 sema.air_instructions.items(.data)[@backingInt(merges.block_inst)] = .{ .ty_pl = .{ 5467 .ty = .void, 5468 .payload = sema.addExtraAssumeCapacity(Air.Block{ 5469 .body_len = @intCast(child_block.instructions.items.len), 5470 }), 5471 } }; 5472 }, 5473 .dbg_inline_block => { 5474 try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.DbgInlineBlock).@"struct".field_names.len + 5475 child_block.instructions.items.len); 5476 sema.air_instructions.items(.data)[@backingInt(merges.block_inst)] = .{ .ty_pl = .{ 5477 .ty = .void, 5478 .payload = sema.addExtraAssumeCapacity(Air.DbgInlineBlock{ 5479 .func = child_block.inlining.?.func, 5480 .body_len = @intCast(child_block.instructions.items.len), 5481 }), 5482 } }; 5483 }, 5484 else => unreachable, 5485 } 5486 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(child_block.instructions.items)); 5487 // Rewrite the break to just give value {}; the value is 5488 // comptime-known and will be returned directly. 5489 sema.air_instructions.items(.data)[@backingInt(merges.br_list.items[0])].br.operand = .void_value; 5490 return Air.internedToRef(result_val.toIntern()); 5491 } 5492 } 5493 // It is impossible to have the number of results be > 1 in a comptime scope. 5494 assert(!child_block.isComptime()); // Should already got a compile error in the condbr condition. 5495 5496 // Note that we'll always create an AIR block here, so `need_debug_scope` is irrelevant. 5497 5498 // Need to set the type and emit the Block instruction. This allows machine code generation 5499 // to emit a jump instruction to after the block when it encounters the break. 5500 try parent_block.instructions.append(gpa, merges.block_inst); 5501 const resolved_ty = try sema.resolvePeerTypes(parent_block, src, merges.results.items, .{ .override = merges.src_locs.items }); 5502 resolved_ty.assertHasLayout(zcu); 5503 // TODO add note "missing else causes void value" 5504 5505 const type_src = src; // TODO: better source location 5506 if (resolved_ty.comptimeOnly(zcu)) { 5507 const msg = msg: { 5508 const msg = try sema.errMsg(type_src, "value with comptime-only type '{f}' depends on runtime control flow", .{resolved_ty.fmt(pt)}); 5509 errdefer msg.destroy(sema.gpa); 5510 5511 const runtime_src = child_block.runtime_cond orelse child_block.runtime_loop.?; 5512 try sema.errNote(runtime_src, msg, "runtime control flow here", .{}); 5513 5514 try sema.explainWhyTypeIsComptime(msg, type_src, resolved_ty); 5515 5516 break :msg msg; 5517 }; 5518 return sema.failWithOwnedErrorMsg(child_block, msg); 5519 } 5520 for (merges.results.items, merges.src_locs.items) |merge_inst, merge_src| { 5521 try sema.validateRuntimeValue(child_block, merge_src orelse src, merge_inst); 5522 } 5523 5524 try sema.checkMergeAllowed(child_block, type_src, resolved_ty); 5525 5526 switch (block_tag) { 5527 .block => { 5528 try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).@"struct".field_names.len + 5529 child_block.instructions.items.len); 5530 sema.air_instructions.items(.data)[@backingInt(merges.block_inst)] = .{ .ty_pl = .{ 5531 .ty = resolved_ty, 5532 .payload = sema.addExtraAssumeCapacity(Air.Block{ 5533 .body_len = @intCast(child_block.instructions.items.len), 5534 }), 5535 } }; 5536 }, 5537 .dbg_inline_block => { 5538 try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.DbgInlineBlock).@"struct".field_names.len + 5539 child_block.instructions.items.len); 5540 sema.air_instructions.items(.data)[@backingInt(merges.block_inst)] = .{ .ty_pl = .{ 5541 .ty = resolved_ty, 5542 .payload = sema.addExtraAssumeCapacity(Air.DbgInlineBlock{ 5543 .func = child_block.inlining.?.func, 5544 .body_len = @intCast(child_block.instructions.items.len), 5545 }), 5546 } }; 5547 }, 5548 else => unreachable, 5549 } 5550 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(child_block.instructions.items)); 5551 // Now that the block has its type resolved, we need to go back into all the break 5552 // instructions, and insert type coercion on the operands. 5553 for (merges.br_list.items) |br| { 5554 const br_operand = sema.air_instructions.items(.data)[@backingInt(br)].br.operand; 5555 const br_operand_src = src; 5556 const br_operand_ty = sema.typeOf(br_operand); 5557 if (br_operand_ty.eql(resolved_ty)) { 5558 // No type coercion needed. 5559 continue; 5560 } 5561 var coerce_block = parent_block.makeSubBlock(); 5562 defer coerce_block.instructions.deinit(gpa); 5563 const coerced_operand = try sema.coerce(&coerce_block, resolved_ty, br_operand, br_operand_src); 5564 // If no instructions were produced, such as in the case of a coercion of a 5565 // constant value to a new type, we can simply point the br operand to it. 5566 if (coerce_block.instructions.items.len == 0) { 5567 sema.air_instructions.items(.data)[@backingInt(br)].br.operand = coerced_operand; 5568 continue; 5569 } 5570 assert(coerce_block.instructions.items[coerce_block.instructions.items.len - 1].toRef() == coerced_operand); 5571 5572 // Convert the br instruction to a block instruction that has the coercion 5573 // and then a new br inside that returns the coerced instruction. 5574 const sub_block_len: u32 = @intCast(coerce_block.instructions.items.len + 1); 5575 try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).@"struct".field_names.len + 5576 sub_block_len); 5577 try sema.air_instructions.ensureUnusedCapacity(gpa, 1); 5578 const sub_br_inst: Air.Inst.Index = @fromBackingInt(@intCast(sema.air_instructions.len)); 5579 5580 sema.air_instructions.items(.tag)[@backingInt(br)] = .block; 5581 sema.air_instructions.items(.data)[@backingInt(br)] = .{ .ty_pl = .{ 5582 .ty = .noreturn, 5583 .payload = sema.addExtraAssumeCapacity(Air.Block{ 5584 .body_len = sub_block_len, 5585 }), 5586 } }; 5587 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(coerce_block.instructions.items)); 5588 sema.air_extra.appendAssumeCapacity(@backingInt(sub_br_inst)); 5589 5590 sema.air_instructions.appendAssumeCapacity(.{ 5591 .tag = .br, 5592 .data = .{ .br = .{ 5593 .block_inst = merges.block_inst, 5594 .operand = coerced_operand, 5595 } }, 5596 }); 5597 } 5598 5599 if (try resolved_ty.onePossibleValue(pt)) |opv| return .fromValue(opv); 5600 return merges.block_inst.toRef(); 5601 } 5602 5603 fn zirExport(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { 5604 const pt = sema.pt; 5605 const zcu = pt.zcu; 5606 const ip = &zcu.intern_pool; 5607 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 5608 const extra = sema.code.extraData(Zir.Inst.Export, inst_data.payload_index).data; 5609 5610 const src = block.nodeOffset(inst_data.src_node); 5611 const ptr_src = block.builtinCallArgSrc(inst_data.src_node, 0); 5612 const options_src = block.builtinCallArgSrc(inst_data.src_node, 1); 5613 5614 const ptr = sema.resolveInst(extra.exported); 5615 const ptr_val = try sema.resolveConstDefinedValue(block, ptr_src, ptr, .{ .simple = .export_target }); 5616 const ptr_ty = ptr_val.typeOf(zcu); 5617 5618 const options = try sema.resolveExportOptions(block, options_src, extra.options); 5619 5620 { 5621 if (ptr_ty.zigTypeTag(zcu) != .pointer) { 5622 return sema.fail(block, ptr_src, "expected pointer type, found '{f}'", .{ptr_ty.fmt(pt)}); 5623 } 5624 const ptr_ty_info = ptr_ty.ptrInfo(zcu); 5625 if (ptr_ty_info.flags.size == .slice) { 5626 return sema.fail(block, ptr_src, "export target cannot be slice", .{}); 5627 } 5628 if (ptr_ty_info.packed_offset.host_size != 0) { 5629 return sema.fail(block, ptr_src, "export target cannot be bit-pointer", .{}); 5630 } 5631 } 5632 5633 const export_ty = ptr_ty.childType(zcu); 5634 try sema.ensureLayoutResolved(export_ty, src, .@"export"); 5635 if (!export_ty.validateExtern(.other, zcu)) { 5636 return sema.failWithOwnedErrorMsg(block, msg: { 5637 const msg = try sema.errMsg(src, "unable to export type '{f}'", .{export_ty.fmt(pt)}); 5638 errdefer msg.destroy(sema.gpa); 5639 try sema.explainWhyTypeIsNotExtern(msg, src, export_ty, .other); 5640 try sema.addDeclaredHereNote(msg, export_ty); 5641 break :msg msg; 5642 }); 5643 } 5644 5645 const ptr_info = ip.indexToKey(ptr_val.toIntern()).ptr; 5646 const target: Zcu.Exported = switch (ptr_info.base_addr) { 5647 .comptime_alloc, .int, .comptime_field => return sema.fail(block, ptr_src, "export target must be a global variable or a comptime-known constant", .{}), 5648 .eu_payload, .opt_payload, .field, .arr_elem => return sema.fail(block, ptr_src, "TODO: export pointer in middle of value", .{}), 5649 .uav => |uav| .{ .uav = uav.val }, 5650 .nav => |orig_nav| target: { 5651 try sema.ensureNavResolved(block, src, orig_nav, .fully); 5652 const export_nav = switch (ip.indexToKey(ip.getNav(orig_nav).resolved.?.value)) { 5653 .@"extern" => |e| e.owner_nav, 5654 .func => |f| f.owner_nav, 5655 else => orig_nav, 5656 }; 5657 if (ip.getNav(export_nav).getExtern(ip) != null) { 5658 return sema.fail(block, src, "export target cannot be extern", .{}); 5659 } 5660 try sema.maybeQueueFuncBodyAnalysis(block, src, export_nav); 5661 break :target .{ .nav = export_nav }; 5662 }, 5663 }; 5664 if (ptr_info.byte_offset != 0) { 5665 return sema.fail(block, ptr_src, "TODO: export pointer in middle of value", .{}); 5666 } 5667 try sema.exports.append(zcu.gpa, .{ 5668 .opts = options, 5669 .src = src, 5670 .exported = target, 5671 }); 5672 } 5673 5674 /// Asserts that `sema.owner` is a `.nav_val` whose value is resolved. 5675 /// 5676 /// Exports that `Nav` by the given name with all other options set to default. 5677 pub fn analyzeExportSelfNav( 5678 sema: *Sema, 5679 block: *Block, 5680 src: LazySrcLoc, 5681 name: InternPool.NullTerminatedString, 5682 ) !void { 5683 const gpa = sema.gpa; 5684 const pt = sema.pt; 5685 const zcu = pt.zcu; 5686 const ip = &zcu.intern_pool; 5687 5688 const orig_nav = sema.owner.unwrap().nav_val; 5689 const export_val: Value = .fromInterned(ip.getNav(orig_nav).resolved.?.value); 5690 const export_ty = export_val.typeOf(zcu); 5691 5692 if (!export_ty.validateExtern(.other, zcu)) { 5693 return sema.failWithOwnedErrorMsg(block, msg: { 5694 const msg = try sema.errMsg(src, "unable to export type '{f}'", .{export_ty.fmt(pt)}); 5695 errdefer msg.destroy(gpa); 5696 try sema.explainWhyTypeIsNotExtern(msg, src, export_ty, .other); 5697 try sema.addDeclaredHereNote(msg, export_ty); 5698 break :msg msg; 5699 }); 5700 } 5701 5702 const export_nav = switch (ip.indexToKey(export_val.toIntern())) { 5703 .@"extern" => |e| e.owner_nav, 5704 .func => |f| export_nav: { 5705 assert(export_ty.fnHasRuntimeBits(zcu)); // otherwise `validateExtern` failed above 5706 const orig_fn_index = ip.unwrapCoercedFunc(export_val.toIntern()); 5707 try sema.addReferenceEntry(block, src, .wrap(.{ .func = orig_fn_index })); 5708 try zcu.ensureFuncBodyAnalysisQueued(orig_fn_index); 5709 break :export_nav f.owner_nav; 5710 }, 5711 else => orig_nav, 5712 }; 5713 5714 try sema.exports.append(gpa, .{ 5715 .opts = .{ .name = name }, 5716 .src = src, 5717 .exported = .{ .nav = export_nav }, 5718 }); 5719 } 5720 5721 fn zirDisableInstrumentation(sema: *Sema) CompileError!void { 5722 const pt = sema.pt; 5723 const zcu = pt.zcu; 5724 const io = zcu.comp.io; 5725 const ip = &zcu.intern_pool; 5726 const func = switch (sema.owner.unwrap()) { 5727 .func => |func| func, 5728 .@"comptime", 5729 .nav_val, 5730 .nav_ty, 5731 .type_layout, 5732 .struct_defaults, 5733 .memoized_state, 5734 => return, // does nothing outside a function 5735 }; 5736 ip.funcSetDisableInstrumentation(io, func); 5737 sema.allow_memoize = false; 5738 } 5739 5740 fn zirDisableIntrinsics(sema: *Sema) CompileError!void { 5741 const pt = sema.pt; 5742 const zcu = pt.zcu; 5743 const io = zcu.comp.io; 5744 const ip = &zcu.intern_pool; 5745 const func = switch (sema.owner.unwrap()) { 5746 .func => |func| func, 5747 .@"comptime", 5748 .nav_val, 5749 .nav_ty, 5750 .type_layout, 5751 .struct_defaults, 5752 .memoized_state, 5753 => return, // does nothing outside a function 5754 }; 5755 ip.funcSetDisableIntrinsics(io, func); 5756 sema.allow_memoize = false; 5757 } 5758 5759 fn zirSetFloatMode(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!void { 5760 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; 5761 const src = block.builtinCallArgSrc(extra.node, 0); 5762 block.float_mode = try sema.resolveStdLangEnum(block, src, extra.operand, .FloatMode, .{ .simple = .operand_setFloatMode }); 5763 } 5764 5765 fn zirSetRuntimeSafety(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { 5766 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].un_node; 5767 const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); 5768 block.want_safety = try sema.resolveConstBool(block, operand_src, inst_data.operand, .{ .simple = .operand_setRuntimeSafety }); 5769 } 5770 5771 fn zirBreak(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) CompileError!void { 5772 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].@"break"; 5773 const extra = sema.code.extraData(Zir.Inst.Break, inst_data.payload_index).data; 5774 const operand = sema.resolveInst(inst_data.operand); 5775 const zir_block = extra.block_inst; 5776 5777 var block = start_block; 5778 while (true) { 5779 if (block.label) |label| { 5780 if (label.zir_block == zir_block) { 5781 const br_ref = try start_block.addBr(label.merges.block_inst, operand); 5782 const src_loc = if (extra.operand_src_node.unwrap()) |operand_src_node| 5783 start_block.nodeOffset(operand_src_node) 5784 else 5785 null; 5786 try label.merges.src_locs.append(sema.gpa, src_loc); 5787 try label.merges.results.append(sema.gpa, operand); 5788 try label.merges.br_list.append(sema.gpa, br_ref.toIndex().?); 5789 block.runtime_index.increment(); 5790 if (block.runtime_cond == null and block.runtime_loop == null) { 5791 block.runtime_cond = start_block.runtime_cond orelse start_block.runtime_loop; 5792 block.runtime_loop = start_block.runtime_loop; 5793 } 5794 return; 5795 } 5796 } 5797 block = block.parent.?; 5798 } 5799 } 5800 5801 fn zirSwitchContinue(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index) CompileError!void { 5802 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].@"break"; 5803 const extra = sema.code.extraData(Zir.Inst.Break, inst_data.payload_index).data; 5804 const operand_src = start_block.nodeOffset(extra.operand_src_node.unwrap().?); 5805 const uncoerced_operand = sema.resolveInst(inst_data.operand); 5806 const switch_inst = extra.block_inst; 5807 5808 switch (sema.code.instructions.items(.tag)[@backingInt(switch_inst)]) { 5809 .switch_block, .switch_block_ref => {}, 5810 .switch_block_err_union => unreachable, // wrong code path! 5811 else => unreachable, // assertion failure 5812 } 5813 5814 const operand_ty = (sema.resolveInst(switch_inst.toRef())).toType(); 5815 const operand = try sema.coerce(start_block, operand_ty, uncoerced_operand, operand_src); 5816 try sema.validateRuntimeValue(start_block, operand_src, operand); 5817 5818 // We want to generate a `switch_dispatch` instruction with the switch condition, 5819 // possibly preceded by a store to the stack alloc containing the raw operand. 5820 // However, to avoid too much special-case state in Sema, this is handled by the 5821 // `switch` lowering logic. As such, we will find the `Block` corresponding to 5822 // the parent `switch_block[_ref]` instruction, create a dummy `br`, and add a 5823 // merge to signal to the switch logic to rewrite this into an appropriate dispatch. 5824 5825 var block = start_block; 5826 while (true) : (block = block.parent.?) { 5827 if (block.label) |label| { 5828 if (label.zir_block == switch_inst) { 5829 const br_ref = try start_block.addBr(label.merges.block_inst, operand); 5830 try label.merges.extra_insts.append(sema.gpa, br_ref.toIndex().?); 5831 try label.merges.extra_src_locs.append(sema.gpa, operand_src); 5832 block.runtime_index.increment(); 5833 if (block.runtime_cond == null and block.runtime_loop == null) { 5834 block.runtime_cond = start_block.runtime_cond orelse start_block.runtime_loop; 5835 block.runtime_loop = start_block.runtime_loop; 5836 } 5837 return; 5838 } 5839 } 5840 } 5841 } 5842 5843 fn zirDbgStmt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { 5844 if (block.isComptime() or block.ownerModule().strip) return; 5845 5846 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].dbg_stmt; 5847 5848 if (block.instructions.items.len != 0) { 5849 const idx = block.instructions.items[block.instructions.items.len - 1]; 5850 if (sema.air_instructions.items(.tag)[@backingInt(idx)] == .dbg_stmt) { 5851 // The previous dbg_stmt didn't correspond to any actual code, so replace it. 5852 sema.air_instructions.items(.data)[@backingInt(idx)].dbg_stmt = .{ 5853 .line = inst_data.line, 5854 .column = inst_data.column, 5855 }; 5856 return; 5857 } 5858 } 5859 5860 _ = try block.addInst(.{ 5861 .tag = .dbg_stmt, 5862 .data = .{ .dbg_stmt = .{ 5863 .line = inst_data.line, 5864 .column = inst_data.column, 5865 } }, 5866 }); 5867 } 5868 5869 fn zirDbgEmptyStmt(_: *Sema, block: *Block, _: Zir.Inst.Index) CompileError!void { 5870 if (block.isComptime() or block.ownerModule().strip) return; 5871 _ = try block.addNoOp(.dbg_empty_stmt); 5872 } 5873 5874 fn zirDbgVar( 5875 sema: *Sema, 5876 block: *Block, 5877 inst: Zir.Inst.Index, 5878 air_tag: Air.Inst.Tag, 5879 ) CompileError!void { 5880 const str_op = sema.code.instructions.items(.data)[@backingInt(inst)].str_op; 5881 const operand = sema.resolveInst(str_op.operand); 5882 const name = str_op.getStr(sema.code); 5883 try sema.addDbgVar(block, operand, air_tag, name); 5884 } 5885 5886 fn addDbgVar( 5887 sema: *Sema, 5888 block: *Block, 5889 operand: Air.Inst.Ref, 5890 air_tag: Air.Inst.Tag, 5891 name: []const u8, 5892 ) CompileError!void { 5893 if (block.isComptime() or block.ownerModule().strip) return; 5894 5895 const pt = sema.pt; 5896 const zcu = pt.zcu; 5897 const operand_ty = sema.typeOf(operand); 5898 const val_ty = switch (air_tag) { 5899 .dbg_var_ptr => operand_ty.childType(zcu), 5900 .dbg_var_val, .dbg_arg_inline => operand_ty, 5901 else => unreachable, 5902 }; 5903 if (val_ty.comptimeOnly(zcu)) return; 5904 if (!val_ty.hasRuntimeBits(zcu)) return; 5905 if (sema.resolveValue(operand)) |operand_val| { 5906 if (operand_val.canMutateComptimeVarState(zcu)) return; 5907 } 5908 5909 // To ensure the lexical scoping is known to backends, this alloc must be 5910 // within a real runtime block. We set a flag which communicates information 5911 // to the closest lexically enclosing block: 5912 // * If it is a `block_inline`, communicates to logic in `analyzeBodyInner` 5913 // to create a post-hoc block. 5914 // * Otherwise, communicates to logic in `resolveBlockBody` to create a 5915 // real `block` instruction. 5916 if (block.need_debug_scope) |ptr| ptr.* = true; 5917 5918 // Add the name to the AIR. 5919 const name_nts = try sema.appendAirString(name); 5920 5921 _ = try block.addInst(.{ 5922 .tag = air_tag, 5923 .data = .{ .pl_op = .{ 5924 .payload = @backingInt(name_nts), 5925 .operand = operand, 5926 } }, 5927 }); 5928 } 5929 5930 pub fn appendAirString(sema: *Sema, str: []const u8) Allocator.Error!Air.NullTerminatedString { 5931 if (str.len == 0) return .none; 5932 const nts: Air.NullTerminatedString = @fromBackingInt(@intCast(sema.air_extra.items.len)); 5933 const elements_used = str.len / 4 + 1; 5934 const elements = try sema.air_extra.addManyAsSlice(sema.gpa, elements_used); 5935 const buffer = mem.sliceAsBytes(elements); 5936 @memcpy(buffer[0..str.len], str); 5937 buffer[str.len] = 0; 5938 return nts; 5939 } 5940 5941 fn zirDeclRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 5942 const pt = sema.pt; 5943 const zcu = pt.zcu; 5944 const comp = zcu.comp; 5945 const gpa = comp.gpa; 5946 const io = comp.io; 5947 5948 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].str_tok; 5949 const src = block.tokenOffset(inst_data.src_tok); 5950 const decl_name = try zcu.intern_pool.getOrPutString( 5951 gpa, 5952 io, 5953 pt.tid, 5954 inst_data.get(sema.code), 5955 .no_embedded_nulls, 5956 ); 5957 const nav_index = try sema.lookupIdentifier(block, decl_name); 5958 return sema.analyzeNavRef(block, src, nav_index); 5959 } 5960 5961 fn zirDeclVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 5962 const pt = sema.pt; 5963 const zcu = pt.zcu; 5964 const comp = zcu.comp; 5965 const gpa = comp.gpa; 5966 const io = comp.io; 5967 5968 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].str_tok; 5969 const src = block.tokenOffset(inst_data.src_tok); 5970 const decl_name = try zcu.intern_pool.getOrPutString( 5971 gpa, 5972 io, 5973 pt.tid, 5974 inst_data.get(sema.code), 5975 .no_embedded_nulls, 5976 ); 5977 const nav = try sema.lookupIdentifier(block, decl_name); 5978 return sema.analyzeNavVal(block, src, nav); 5979 } 5980 5981 fn lookupIdentifier(sema: *Sema, block: *Block, name: InternPool.NullTerminatedString) !InternPool.Nav.Index { 5982 const pt = sema.pt; 5983 const zcu = pt.zcu; 5984 var namespace = block.namespace; 5985 while (true) { 5986 if (try sema.lookupInNamespace(block, namespace, name)) |lookup| { 5987 assert(lookup.accessible == .public or lookup.accessible == .private_same_file); 5988 return lookup.nav; 5989 } 5990 namespace = zcu.namespacePtr(namespace).parent.unwrap() orelse break; 5991 } 5992 unreachable; // AstGen detects use of undeclared identifiers. 5993 } 5994 5995 /// This looks up a member of a specific namespace. 5996 fn lookupInNamespace( 5997 sema: *Sema, 5998 block: *Block, 5999 namespace_index: InternPool.NamespaceIndex, 6000 ident_name: InternPool.NullTerminatedString, 6001 ) CompileError!?struct { 6002 nav: InternPool.Nav.Index, 6003 accessible: enum { public, private_same_file, private }, 6004 } { 6005 const pt = sema.pt; 6006 const zcu = pt.zcu; 6007 6008 pt.ensureNamespaceUpToDate(namespace_index) catch |err| switch (err) { 6009 error.LostZirContainerDecl => { 6010 const namespace = zcu.namespacePtr(namespace_index); 6011 const ns_ty: Type = .fromInterned(namespace.owner_type); 6012 return sema.failTransitive(.{ .lost_tracking = ns_ty.typeDeclInstAllowGeneratedTag(zcu).? }); 6013 }, 6014 else => |e| return e, 6015 }; 6016 6017 const namespace = zcu.namespacePtr(namespace_index); 6018 6019 const adapter: Zcu.Namespace.NameAdapter = .{ .zcu = zcu }; 6020 6021 const src_file = zcu.namespacePtr(block.namespace).file_scope; 6022 6023 if (Type.fromInterned(namespace.owner_type).typeDeclInst(zcu)) |type_decl_inst| { 6024 try sema.declareDependency(.{ .namespace_name = .{ 6025 .namespace = type_decl_inst, 6026 .name = ident_name, 6027 } }); 6028 } 6029 6030 if (namespace.pub_decls.getKeyAdapted(ident_name, adapter)) |nav_index| { 6031 return .{ 6032 .nav = nav_index, 6033 .accessible = .public, 6034 }; 6035 } else if (namespace.priv_decls.getKeyAdapted(ident_name, adapter)) |nav_index| { 6036 return .{ 6037 .nav = nav_index, 6038 .accessible = if (src_file == namespace.file_scope) .private_same_file else .private, 6039 }; 6040 } 6041 6042 return null; 6043 } 6044 6045 fn funcDeclSrcInst(sema: *Sema, func_inst: Air.Inst.Ref) !?InternPool.TrackedInst.Index { 6046 const pt = sema.pt; 6047 const zcu = pt.zcu; 6048 const ip = &zcu.intern_pool; 6049 const func_val = sema.resolveValue(func_inst) orelse return null; 6050 if (func_val.isUndef(zcu)) return null; 6051 const nav = switch (ip.indexToKey(func_val.toIntern())) { 6052 .@"extern" => |e| e.owner_nav, 6053 .func => |f| f.owner_nav, 6054 .ptr => |ptr| switch (ptr.base_addr) { 6055 .nav => |nav| if (ptr.byte_offset == 0) nav else return null, 6056 else => return null, 6057 }, 6058 else => return null, 6059 }; 6060 return ip.getNav(nav).srcInst(ip); 6061 } 6062 6063 pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref { 6064 const pt = sema.pt; 6065 const zcu = pt.zcu; 6066 const comp = zcu.comp; 6067 const gpa = comp.gpa; 6068 const io = comp.io; 6069 6070 if (block.isComptime() or block.is_typeof) { 6071 const index_val = try pt.intValue_u64(.usize, sema.comptime_err_ret_trace.items.len); 6072 return Air.internedToRef(index_val.toIntern()); 6073 } 6074 6075 if (!block.ownerModule().error_tracing) return .none; 6076 6077 const stack_trace_ty = try sema.getStdLangType(block.nodeOffset(.zero), .StackTrace); 6078 const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "index", .no_embedded_nulls); 6079 const field_index = sema.structFieldIndex(block, stack_trace_ty, field_name, LazySrcLoc.unneeded) catch |err| switch (err) { 6080 error.AlreadyReported => @panic("std.lang.StackTrace is corrupt"), 6081 error.ComptimeReturn, error.ComptimeBreak => unreachable, 6082 error.OutOfMemory, error.Canceled => |e| return e, 6083 }; 6084 6085 return try block.addInst(.{ 6086 .tag = .save_err_return_trace_index, 6087 .data = .{ .ty_pl = .{ 6088 .ty = stack_trace_ty, 6089 .payload = @intCast(field_index), 6090 } }, 6091 }); 6092 } 6093 6094 /// Add instructions to block to "pop" the error return trace. 6095 /// If `operand` is provided, only pops if operand is non-error. 6096 fn popErrorReturnTrace( 6097 sema: *Sema, 6098 block: *Block, 6099 src: LazySrcLoc, 6100 operand: Air.Inst.Ref, 6101 saved_error_trace_index: Air.Inst.Ref, 6102 ) CompileError!void { 6103 const pt = sema.pt; 6104 const zcu = pt.zcu; 6105 const comp = zcu.comp; 6106 const gpa = comp.gpa; 6107 const io = comp.io; 6108 var is_non_error: ?bool = null; 6109 var is_non_error_inst: Air.Inst.Ref = undefined; 6110 if (operand != .none) { 6111 is_non_error_inst = try sema.analyzeIsNonErr(block, src, operand); 6112 if (try sema.resolveDefinedValue(block, src, is_non_error_inst)) |cond_val| 6113 is_non_error = cond_val.toBool(); 6114 } else is_non_error = true; // no operand means pop unconditionally 6115 6116 if (is_non_error == true) { 6117 // AstGen determined this result does not go to an error-handling expr (try/catch/return etc.), or 6118 // the result is comptime-known to be a non-error. Either way, pop unconditionally. 6119 6120 const stack_trace_ty = try sema.getStdLangType(src, .StackTrace); 6121 const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty); 6122 const err_return_trace = try block.addTy(.err_return_trace, ptr_stack_trace_ty); 6123 const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "index", .no_embedded_nulls); 6124 const field_ptr = try sema.structFieldPtr(block, src, err_return_trace, field_name, src, stack_trace_ty); 6125 try sema.storePtr2(block, src, field_ptr, src, saved_error_trace_index, src, .store); 6126 } else if (is_non_error == null) { 6127 // The result might be an error. If it is, we leave the error trace alone. If it isn't, we need 6128 // to pop any error trace that may have been propagated from our arguments. 6129 6130 try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Block).@"struct".field_names.len); 6131 const cond_block_inst = try block.addInstAsIndex(.{ 6132 .tag = .block, 6133 .data = .{ 6134 .ty_pl = .{ 6135 .ty = .void, 6136 .payload = undefined, // updated below 6137 }, 6138 }, 6139 }); 6140 6141 var then_block = block.makeSubBlock(); 6142 defer then_block.instructions.deinit(gpa); 6143 6144 // If non-error, then pop the error return trace by restoring the index. 6145 const stack_trace_ty = try sema.getStdLangType(src, .StackTrace); 6146 const ptr_stack_trace_ty = try pt.singleMutPtrType(stack_trace_ty); 6147 const err_return_trace = try then_block.addTy(.err_return_trace, ptr_stack_trace_ty); 6148 const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "index", .no_embedded_nulls); 6149 const field_ptr = try sema.structFieldPtr(&then_block, src, err_return_trace, field_name, src, stack_trace_ty); 6150 try sema.storePtr2(&then_block, src, field_ptr, src, saved_error_trace_index, src, .store); 6151 _ = try then_block.addBr(cond_block_inst, .void_value); 6152 6153 // Otherwise, do nothing 6154 var else_block = block.makeSubBlock(); 6155 defer else_block.instructions.deinit(gpa); 6156 _ = try else_block.addBr(cond_block_inst, .void_value); 6157 6158 try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.CondBr).@"struct".field_names.len + 6159 then_block.instructions.items.len + else_block.instructions.items.len + 6160 @typeInfo(Air.Block).@"struct".field_names.len + 1); // +1 for the sole .cond_br instruction in the .block 6161 6162 const cond_br_inst: Air.Inst.Index = @fromBackingInt(@intCast(sema.air_instructions.len)); 6163 try sema.air_instructions.append(gpa, .{ 6164 .tag = .cond_br, 6165 .data = .{ 6166 .pl_op = .{ 6167 .operand = is_non_error_inst, 6168 .payload = sema.addExtraAssumeCapacity(Air.CondBr{ 6169 .then_body_len = @intCast(then_block.instructions.items.len), 6170 .else_body_len = @intCast(else_block.instructions.items.len), 6171 .branch_hints = .{ 6172 // Weight against error branch. 6173 .true = .likely, 6174 .false = .unlikely, 6175 // Code coverage is not valuable on either branch. 6176 .then_cov = .none, 6177 .else_cov = .none, 6178 }, 6179 }), 6180 }, 6181 }, 6182 }); 6183 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(then_block.instructions.items)); 6184 sema.air_extra.appendSliceAssumeCapacity(@ptrCast(else_block.instructions.items)); 6185 6186 sema.air_instructions.items(.data)[@backingInt(cond_block_inst)].ty_pl.payload = sema.addExtraAssumeCapacity(Air.Block{ .body_len = 1 }); 6187 sema.air_extra.appendAssumeCapacity(@backingInt(cond_br_inst)); 6188 } 6189 } 6190 6191 fn zirCall( 6192 sema: *Sema, 6193 block: *Block, 6194 inst: Zir.Inst.Index, 6195 comptime kind: enum { direct, field }, 6196 ) CompileError!Air.Inst.Ref { 6197 const pt = sema.pt; 6198 const zcu = pt.zcu; 6199 const comp = zcu.comp; 6200 const gpa = comp.gpa; 6201 const io = comp.io; 6202 6203 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 6204 const callee_src = block.src(.{ .node_offset_call_func = inst_data.src_node }); 6205 const call_src = block.nodeOffset(inst_data.src_node); 6206 const ExtraType = switch (kind) { 6207 .direct => Zir.Inst.Call, 6208 .field => Zir.Inst.FieldCall, 6209 }; 6210 const extra = sema.code.extraData(ExtraType, inst_data.payload_index); 6211 const args_len = extra.data.flags.args_len; 6212 6213 const modifier: std.lang.CallModifier = @fromBackingInt(@intCast(extra.data.flags.packed_modifier)); 6214 const ensure_result_used = extra.data.flags.ensure_result_used; 6215 const pop_error_return_trace = extra.data.flags.pop_error_return_trace; 6216 6217 const callee: ResolvedFieldCallee = switch (kind) { 6218 .direct => .{ .direct = sema.resolveInst(extra.data.callee) }, 6219 .field => blk: { 6220 const object_ptr = sema.resolveInst(extra.data.obj_ptr); 6221 const field_name = try zcu.intern_pool.getOrPutString( 6222 gpa, 6223 io, 6224 pt.tid, 6225 sema.code.nullTerminatedString(extra.data.field_name_start), 6226 .no_embedded_nulls, 6227 ); 6228 const field_name_src = block.src(.{ .node_offset_field_name = inst_data.src_node }); 6229 break :blk try sema.fieldCallBind(block, callee_src, object_ptr, field_name, field_name_src); 6230 }, 6231 }; 6232 const func: Air.Inst.Ref = switch (callee) { 6233 .direct => |func_inst| func_inst, 6234 .method => |method| method.func_inst, 6235 }; 6236 6237 const callee_ty = sema.typeOf(func); 6238 const total_args = args_len + @intFromBool(callee == .method); 6239 const func_ty = try sema.checkCallArgumentCount(block, func, callee_src, callee_ty, total_args, callee == .method); 6240 6241 // The block index before the call, so we can potentially insert an error trace save here later. 6242 const block_index: Air.Inst.Index = @fromBackingInt(@intCast(block.instructions.items.len)); 6243 6244 // This will be set by `analyzeCall` to indicate whether any parameter was an error (making the 6245 // error trace potentially dirty). 6246 var input_is_error = false; 6247 6248 const args_info: CallArgsInfo = .{ .zir_call = .{ 6249 .bound_arg = switch (callee) { 6250 .direct => .none, 6251 .method => |method| method.arg0_inst, 6252 }, 6253 .bound_arg_src = callee_src, 6254 .call_inst = inst, 6255 .call_node_offset = inst_data.src_node, 6256 .num_args = args_len, 6257 .args_body = @ptrCast(sema.code.extra[extra.end..]), 6258 .any_arg_is_error = &input_is_error, 6259 } }; 6260 6261 // AstGen ensures that a call instruction is always preceded by a dbg_stmt instruction. 6262 const call_dbg_node: Zir.Inst.Index = @fromBackingInt(@intCast(@backingInt(inst) - 1)); 6263 const call_inst = try sema.analyzeCall(block, func, func_ty, callee_src, call_src, modifier, ensure_result_used, args_info, call_dbg_node, .call); 6264 6265 if (block.ownerModule().error_tracing and 6266 !block.isComptime() and !block.is_typeof and (input_is_error or pop_error_return_trace)) 6267 { 6268 const return_ty = sema.typeOf(call_inst); 6269 if (modifier != .always_tail and return_ty.isNoReturn(zcu)) 6270 return call_inst; // call to "fn (...) noreturn", don't pop 6271 6272 // TODO: we don't fix up the error trace for always_tail correctly, we should be doing it 6273 // *before* the recursive call. This will be a bit tricky to do and probably requires 6274 // moving this logic into analyzeCall. But that's probably a good idea anyway. 6275 if (modifier == .always_tail) 6276 return call_inst; 6277 6278 // If any input is an error-type, we might need to pop any trace it generated. Otherwise, we only 6279 // need to clean-up our own trace if we were passed to a non-error-handling expression. 6280 if (input_is_error or (pop_error_return_trace and return_ty.isError(zcu))) { 6281 const stack_trace_ty = try sema.getStdLangType(call_src, .StackTrace); 6282 const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "index", .no_embedded_nulls); 6283 const field_index = try sema.structFieldIndex(block, stack_trace_ty, field_name, call_src); 6284 6285 // Insert a save instruction before the arg resolution + call instructions we just generated 6286 const save_inst = try block.insertInst(block_index, .{ 6287 .tag = .save_err_return_trace_index, 6288 .data = .{ .ty_pl = .{ 6289 .ty = stack_trace_ty, 6290 .payload = @intCast(field_index), 6291 } }, 6292 }); 6293 6294 // Pop the error return trace, testing the result for non-error if necessary 6295 const operand = if (pop_error_return_trace or modifier == .always_tail) .none else call_inst; 6296 try sema.popErrorReturnTrace(block, call_src, operand, save_inst); 6297 } 6298 6299 return call_inst; 6300 } else { 6301 return call_inst; 6302 } 6303 } 6304 6305 fn checkCallArgumentCount( 6306 sema: *Sema, 6307 block: *Block, 6308 func: Air.Inst.Ref, 6309 func_src: LazySrcLoc, 6310 callee_ty: Type, 6311 total_args: usize, 6312 member_fn: bool, 6313 ) !Type { 6314 const pt = sema.pt; 6315 const zcu = pt.zcu; 6316 const func_ty: Type = func_ty: { 6317 switch (callee_ty.zigTypeTag(zcu)) { 6318 .@"fn" => break :func_ty callee_ty, 6319 .pointer => { 6320 const ptr_info = callee_ty.ptrInfo(zcu); 6321 if (ptr_info.flags.size == .one and Type.fromInterned(ptr_info.child).zigTypeTag(zcu) == .@"fn") { 6322 break :func_ty .fromInterned(ptr_info.child); 6323 } 6324 }, 6325 .optional => { 6326 const opt_child = callee_ty.optionalChild(zcu); 6327 if (opt_child.zigTypeTag(zcu) == .@"fn" or (opt_child.isSinglePointer(zcu) and 6328 opt_child.childType(zcu).zigTypeTag(zcu) == .@"fn")) 6329 { 6330 const msg = msg: { 6331 const msg = try sema.errMsg(func_src, "cannot call optional type '{f}'", .{ 6332 callee_ty.fmt(pt), 6333 }); 6334 errdefer msg.destroy(sema.gpa); 6335 try sema.errNote(func_src, msg, "consider using '.?', 'orelse' or 'if'", .{}); 6336 break :msg msg; 6337 }; 6338 return sema.failWithOwnedErrorMsg(block, msg); 6339 } 6340 }, 6341 else => {}, 6342 } 6343 return sema.fail(block, func_src, "type '{f}' not a function", .{callee_ty.fmt(pt)}); 6344 }; 6345 6346 const func_ty_info = zcu.typeToFunc(func_ty).?; 6347 const fn_params_len = func_ty_info.param_types.len; 6348 const args_len = total_args - @intFromBool(member_fn); 6349 if (func_ty_info.is_var_args) { 6350 assert(callConvSupportsVarArgs(func_ty_info.cc)); 6351 if (total_args >= fn_params_len) return func_ty; 6352 } else if (fn_params_len == total_args) { 6353 return func_ty; 6354 } 6355 6356 const maybe_func_inst = try sema.funcDeclSrcInst(func); 6357 const member_str = if (member_fn) "member function " else ""; 6358 const variadic_str = if (func_ty_info.is_var_args) "at least " else ""; 6359 const msg = msg: { 6360 const msg = try sema.errMsg( 6361 func_src, 6362 "{s}expected {s}{d} argument(s), found {d}", 6363 .{ 6364 member_str, 6365 variadic_str, 6366 fn_params_len - @intFromBool(member_fn), 6367 args_len, 6368 }, 6369 ); 6370 errdefer msg.destroy(sema.gpa); 6371 6372 if (maybe_func_inst) |func_inst| { 6373 try sema.errNote(.{ 6374 .base_node_inst = func_inst, 6375 .offset = LazySrcLoc.Offset.nodeOffset(.zero), 6376 }, msg, "function declared here", .{}); 6377 } 6378 break :msg msg; 6379 }; 6380 return sema.failWithOwnedErrorMsg(block, msg); 6381 } 6382 6383 fn callBuiltin( 6384 sema: *Sema, 6385 block: *Block, 6386 call_src: LazySrcLoc, 6387 builtin_fn: Air.Inst.Ref, 6388 modifier: std.lang.CallModifier, 6389 args: []const Air.Inst.Ref, 6390 operation: CallOperation, 6391 ) !void { 6392 const pt = sema.pt; 6393 const zcu = pt.zcu; 6394 const callee_ty = sema.typeOf(builtin_fn); 6395 const func_ty: Type = func_ty: { 6396 switch (callee_ty.zigTypeTag(zcu)) { 6397 .@"fn" => break :func_ty callee_ty, 6398 .pointer => { 6399 const ptr_info = callee_ty.ptrInfo(zcu); 6400 if (ptr_info.flags.size == .one and Type.fromInterned(ptr_info.child).zigTypeTag(zcu) == .@"fn") { 6401 break :func_ty .fromInterned(ptr_info.child); 6402 } 6403 }, 6404 else => {}, 6405 } 6406 std.debug.panic("type '{f}' is not a function calling builtin fn", .{callee_ty.fmt(pt)}); 6407 }; 6408 6409 const func_ty_info = zcu.typeToFunc(func_ty).?; 6410 const fn_params_len = func_ty_info.param_types.len; 6411 if (args.len != fn_params_len or (func_ty_info.is_var_args and args.len < fn_params_len)) { 6412 std.debug.panic("parameter count mismatch calling builtin fn, expected {d}, found {d}", .{ fn_params_len, args.len }); 6413 } 6414 6415 _ = try sema.analyzeCall( 6416 block, 6417 builtin_fn, 6418 func_ty, 6419 call_src, 6420 call_src, 6421 modifier, 6422 false, 6423 .{ .resolved = .{ .src = call_src, .args = args } }, 6424 null, 6425 operation, 6426 ); 6427 } 6428 6429 const CallOperation = enum { 6430 call, 6431 @"@call", 6432 @"@panic", 6433 @"safety check", 6434 @"error return", 6435 }; 6436 6437 const CallArgsInfo = union(enum) { 6438 /// The full list of resolved (but uncoerced) arguments is known ahead of time. 6439 resolved: struct { 6440 src: LazySrcLoc, 6441 args: []const Air.Inst.Ref, 6442 }, 6443 6444 /// The list of resolved (but uncoerced) arguments is known ahead of time, but 6445 /// originated from a usage of the @call builtin at the given node offset. 6446 call_builtin: struct { 6447 call_node_offset: std.zig.Ast.Node.Offset, 6448 args: []const Air.Inst.Ref, 6449 }, 6450 6451 /// This call corresponds to a ZIR call instruction. The arguments have not yet been 6452 /// resolved. They must be resolved by `analyzeCall` so that argument resolution and 6453 /// generic instantiation may be interleaved. This is required for RLS to work on 6454 /// generic parameters. 6455 zir_call: struct { 6456 /// This may be `none`, in which case it is ignored. Otherwise, it is the 6457 /// already-resolved value of the first argument, from method call syntax. 6458 bound_arg: Air.Inst.Ref, 6459 /// The source location of `bound_arg` if it is not `null`. Otherwise `undefined`. 6460 bound_arg_src: LazySrcLoc, 6461 /// The ZIR call instruction. The parameter type is placed at this index while 6462 /// analyzing arguments. 6463 call_inst: Zir.Inst.Index, 6464 /// The node offset of `call_inst`. 6465 call_node_offset: std.zig.Ast.Node.Offset, 6466 /// The number of arguments to this call, not including `bound_arg`. 6467 num_args: u32, 6468 /// The ZIR corresponding to all function arguments (other than `bound_arg`, if it 6469 /// is not `none`). Format is precisely the same as trailing data of ZIR `call`. 6470 args_body: []const Zir.Inst.Index, 6471 /// This bool will be set to true if any argument evaluated turns out to have an error set or error union type. 6472 /// This is used by the caller to restore the error return trace when necessary. 6473 any_arg_is_error: *bool, 6474 }, 6475 6476 fn count(cai: CallArgsInfo) usize { 6477 return switch (cai) { 6478 inline .resolved, .call_builtin => |resolved| resolved.args.len, 6479 .zir_call => |zir_call| zir_call.num_args + @intFromBool(zir_call.bound_arg != .none), 6480 }; 6481 } 6482 6483 fn argSrc(cai: CallArgsInfo, block: *Block, arg_index: usize) LazySrcLoc { 6484 return switch (cai) { 6485 .resolved => |resolved| resolved.src, 6486 .call_builtin => |call_builtin| block.src(.{ .call_arg = .{ 6487 .call_node_offset = call_builtin.call_node_offset, 6488 .arg_index = @intCast(arg_index), 6489 } }), 6490 .zir_call => |zir_call| if (arg_index == 0 and zir_call.bound_arg != .none) { 6491 return zir_call.bound_arg_src; 6492 } else block.src(.{ .call_arg = .{ 6493 .call_node_offset = zir_call.call_node_offset, 6494 .arg_index = @intCast(arg_index - @intFromBool(zir_call.bound_arg != .none)), 6495 } }), 6496 }; 6497 } 6498 6499 /// Analyzes the arg at `arg_index` and coerces it to `param_ty`. 6500 /// `param_ty` may be `generic_poison`. A value of `null` indicates a varargs parameter. 6501 /// `func_ty_info` may be the type before instantiation, even if a generic instantiation is in progress. 6502 /// Emits a compile error if the argument is not comptime-known despite either `block.isComptime()` or 6503 /// the parameter being marked `comptime`. 6504 fn analyzeArg( 6505 cai: CallArgsInfo, 6506 sema: *Sema, 6507 block: *Block, 6508 arg_index: usize, 6509 maybe_param_ty: ?Type, 6510 func_ty_info: InternPool.Key.FuncType, 6511 func_inst: Air.Inst.Ref, 6512 maybe_func_src_inst: ?InternPool.TrackedInst.Index, 6513 ) CompileError!Air.Inst.Ref { 6514 const pt = sema.pt; 6515 const zcu = pt.zcu; 6516 const param_count = func_ty_info.param_types.len; 6517 const uncoerced_arg: Air.Inst.Ref = switch (cai) { 6518 inline .resolved, .call_builtin => |resolved| resolved.args[arg_index], 6519 .zir_call => |zir_call| arg_val: { 6520 // Generate args to comptime params in comptime block 6521 const parent_comptime = block.comptime_reason; 6522 defer block.comptime_reason = parent_comptime; 6523 // Note that we are indexing into parameters, not arguments, so use `arg_index` instead of `real_arg_idx` 6524 if (std.math.cast(u5, arg_index)) |i| { 6525 if (i < param_count and func_ty_info.paramIsComptime(i)) { 6526 block.comptime_reason = .{ 6527 .reason = .{ 6528 .src = cai.argSrc(block, arg_index), 6529 .r = .{ 6530 .comptime_param = .{ 6531 .comptime_src = if (maybe_func_src_inst) |src_inst| .{ 6532 .base_node_inst = src_inst, 6533 .offset = .{ .func_decl_param_comptime = @intCast(arg_index) }, 6534 } else unreachable, // should be non-null because the function is generic 6535 }, 6536 }, 6537 }, 6538 }; 6539 } 6540 } 6541 6542 const has_bound_arg = zir_call.bound_arg != .none; 6543 const uncoerced_arg = if (arg_index == 0 and has_bound_arg) zir_call.bound_arg else arg: { 6544 const real_arg_idx = arg_index - @intFromBool(has_bound_arg); 6545 6546 const arg_body = if (real_arg_idx == 0) blk: { 6547 const start = zir_call.num_args; 6548 const end = @backingInt(zir_call.args_body[0]); 6549 break :blk zir_call.args_body[start..end]; 6550 } else blk: { 6551 const start = @backingInt(zir_call.args_body[real_arg_idx - 1]); 6552 const end = @backingInt(zir_call.args_body[real_arg_idx]); 6553 break :blk zir_call.args_body[start..end]; 6554 }; 6555 6556 // Give the arg its result type 6557 const provide_param_ty: Type = maybe_param_ty orelse .generic_poison; 6558 sema.inst_map.putAssumeCapacity(zir_call.call_inst, Air.internedToRef(provide_param_ty.toIntern())); 6559 // Resolve the arg! 6560 break :arg try sema.resolveInlineBody(block, arg_body, zir_call.call_inst); 6561 }; 6562 6563 if (block.isComptime() and !try sema.isComptimeKnown(uncoerced_arg)) { 6564 return sema.failWithNeededComptime(block, cai.argSrc(block, arg_index), null); 6565 } 6566 6567 if (sema.typeOf(uncoerced_arg).classify(zcu) == .no_possible_value) { 6568 // This terminates resolution of arguments. The caller should 6569 // propagate this. 6570 return uncoerced_arg; 6571 } 6572 6573 if (sema.typeOf(uncoerced_arg).isError(zcu)) { 6574 zir_call.any_arg_is_error.* = true; 6575 } 6576 6577 break :arg_val uncoerced_arg; 6578 }, 6579 }; 6580 const param_ty = maybe_param_ty orelse { 6581 return sema.coerceVarArgParam(block, uncoerced_arg, cai.argSrc(block, arg_index)); 6582 }; 6583 switch (param_ty.toIntern()) { 6584 .generic_poison_type => return uncoerced_arg, 6585 else => return sema.coerceExtra( 6586 block, 6587 param_ty, 6588 uncoerced_arg, 6589 cai.argSrc(block, arg_index), 6590 .{ .param_src = .{ 6591 .func_inst = func_inst, 6592 .param_i = @intCast(arg_index), 6593 } }, 6594 ) catch |err| switch (err) { 6595 error.NotCoercible => unreachable, 6596 else => |e| return e, 6597 }, 6598 } 6599 } 6600 }; 6601 6602 fn analyzeCall( 6603 sema: *Sema, 6604 block: *Block, 6605 callee: Air.Inst.Ref, 6606 func_ty: Type, 6607 func_src: LazySrcLoc, 6608 call_src: LazySrcLoc, 6609 modifier: std.lang.CallModifier, 6610 ensure_result_used: bool, 6611 args_info: CallArgsInfo, 6612 call_dbg_node: ?Zir.Inst.Index, 6613 operation: CallOperation, 6614 ) CompileError!Air.Inst.Ref { 6615 const pt = sema.pt; 6616 const zcu = pt.zcu; 6617 const comp = zcu.comp; 6618 const gpa = comp.gpa; 6619 const io = comp.io; 6620 const ip = &zcu.intern_pool; 6621 const arena = sema.arena; 6622 6623 const maybe_func_inst = try sema.funcDeclSrcInst(callee); 6624 const func_ret_ty_src: LazySrcLoc = if (maybe_func_inst) |fn_decl_inst| .{ 6625 .base_node_inst = fn_decl_inst, 6626 .offset = .{ .node_offset_fn_type_ret_ty = .zero }, 6627 } else func_src; 6628 6629 const func_ty_info = zcu.typeToFunc(func_ty).?; 6630 6631 for (func_ty_info.param_types.get(ip), 0..) |param_ty_ip, param_index| { 6632 const arg_src = args_info.argSrc(block, param_index); 6633 try sema.ensureLayoutResolved(.fromInterned(param_ty_ip), arg_src, .init); 6634 } 6635 try sema.ensureLayoutResolved(.fromInterned(func_ty_info.return_type), func_ret_ty_src, .return_type); 6636 try sema.validateResolvedFuncType( 6637 block, 6638 func_ty_info.cc, 6639 func_ty_info.param_types.get(ip), 6640 .fromInterned(func_ty_info.return_type), 6641 func_src, 6642 maybe_func_inst, 6643 ); 6644 6645 if (!callConvIsCallable(func_ty_info.cc)) { 6646 return sema.failWithOwnedErrorMsg(block, msg: { 6647 const msg = try sema.errMsg( 6648 func_src, 6649 "unable to call function with calling convention '{s}'", 6650 .{@tagName(func_ty_info.cc)}, 6651 ); 6652 errdefer msg.destroy(gpa); 6653 if (maybe_func_inst) |func_inst| try sema.errNote(.{ 6654 .base_node_inst = func_inst, 6655 .offset = .nodeOffset(.zero), 6656 }, msg, "function declared here", .{}); 6657 break :msg msg; 6658 }); 6659 } 6660 6661 const any_comptime_params = func_ty_info.comptime_bits != 0 or ct: { 6662 for (func_ty_info.param_types.get(ip)) |param_ty| { 6663 if (Type.fromInterned(param_ty).comptimeOnly(zcu)) break :ct true; 6664 } 6665 break :ct Type.fromInterned(func_ty_info.return_type).comptimeOnly(zcu); 6666 }; 6667 const any_generic_types = generic: { 6668 for (func_ty_info.param_types.get(ip)) |param_ty| { 6669 if (param_ty == .generic_poison_type) break :generic true; 6670 } 6671 const ret_ty: Type = .fromInterned(func_ty_info.return_type); 6672 if (ret_ty.toIntern() == .generic_poison_type) { 6673 break :generic true; 6674 } 6675 if (ret_ty.zigTypeTag(zcu) == .error_union and 6676 ret_ty.errorUnionPayload(zcu).toIntern() == .generic_poison_type) 6677 { 6678 break :generic true; 6679 } 6680 break :generic false; 6681 }; 6682 6683 // We need this value in a few code paths. 6684 const callee_val = try sema.resolveDefinedValue(block, call_src, callee); 6685 // If the callee is a comptime-known *non-extern* function, `func_val` is populated. 6686 // If it is a comptime-known extern function, `func_is_extern` is set instead. 6687 // If it is not comptime-known, neither is set. 6688 const func_val: ?Value, const func_is_extern: bool = if (callee_val) |c| switch (ip.indexToKey(c.toIntern())) { 6689 .func => .{ c, false }, 6690 .ptr => switch (try sema.pointerDerefExtra(block, func_src, c)) { 6691 .runtime_load, .needed_well_defined, .out_of_bounds => .{ null, false }, 6692 .val => |pointee| switch (ip.indexToKey(pointee.toIntern())) { 6693 .func => .{ pointee, false }, 6694 .@"extern" => .{ null, true }, 6695 else => unreachable, 6696 }, 6697 }, 6698 .@"extern" => .{ null, true }, 6699 else => unreachable, 6700 } else .{ null, false }; 6701 6702 if ((any_generic_types or any_comptime_params) and func_val == null) { 6703 return sema.failWithNeededComptime(block, func_src, .{ .simple = .generic_call_target }); 6704 } 6705 6706 const inline_requested = func_ty_info.cc == .@"inline" or modifier == .always_inline; 6707 6708 // If the modifier is `.compile_time`, or if the return type is non-generic and comptime-only, 6709 // then we need to enter a comptime scope *now* to make sure the args are comptime-eval'd. 6710 const old_block_comptime_reason = block.comptime_reason; 6711 defer block.comptime_reason = old_block_comptime_reason; 6712 if (!block.isComptime()) { 6713 if (modifier == .compile_time) { 6714 block.comptime_reason = .{ .reason = .{ 6715 .src = call_src, 6716 .r = .{ .simple = .comptime_call_modifier }, 6717 } }; 6718 } else if (!inline_requested) { 6719 const ret_ty: Type = .fromInterned(func_ty_info.return_type); 6720 if (ret_ty.comptimeOnly(zcu)) { 6721 block.comptime_reason = .{ .reason = .{ 6722 .src = call_src, 6723 .r = .{ .comptime_only_ret_ty = .{ 6724 .ty = .fromInterned(func_ty_info.return_type), 6725 .is_generic_inst = false, 6726 .ret_ty_src = func_ret_ty_src, 6727 } }, 6728 } }; 6729 } 6730 } 6731 } 6732 6733 // This is whether we already know this to be an inline call. 6734 // If so, then comptime-known arguments are propagated when evaluating generic parameter/return types. 6735 // We might still learn that this call is inline *after* evaluating the generic return type. 6736 const early_known_inline = inline_requested or block.isComptime(); 6737 6738 // These values are undefined if `func_val == null`. 6739 const fn_nav: InternPool.Nav, const fn_zir: Zir, const fn_tracked_inst: InternPool.TrackedInst.Index, const fn_zir_inst: Zir.Inst.Index, const fn_zir_info: Zir.FnInfo = if (func_val) |f| b: { 6740 const info = ip.indexToKey(f.toIntern()).func; 6741 const nav = ip.getNav(info.owner_nav); 6742 const resolved_func_inst = info.zir_body_inst.resolveFull(ip) orelse { 6743 return sema.failTransitive(.{ .lost_tracking = info.zir_body_inst }); 6744 }; 6745 const file = zcu.fileByIndex(resolved_func_inst.file); 6746 const zir_info = file.zir.?.getFnInfo(resolved_func_inst.inst); 6747 break :b .{ nav, file.zir.?, info.zir_body_inst, resolved_func_inst.inst, zir_info }; 6748 } else .{ undefined, undefined, undefined, undefined, undefined }; 6749 6750 // This is the `inst_map` used when evaluating generic parameters and return types. 6751 var generic_inst_map: InstMap = .{}; 6752 defer generic_inst_map.deinit(gpa); 6753 if (any_generic_types) { 6754 try generic_inst_map.ensureSpaceForInstructions(gpa, fn_zir_info.param_body); 6755 } 6756 6757 // This exists so that `generic_block` below can include a "called from here" note back to this 6758 // call site when analyzing generic parameter/return types. 6759 var generic_inlining: Block.Inlining = if (any_generic_types) .{ 6760 .call_block = block, 6761 .call_src = call_src, 6762 .func = func_val.?.toIntern(), 6763 .is_generic_instantiation = true, // this allows the following fields to be `undefined` 6764 .has_comptime_args = undefined, 6765 .comptime_result = undefined, 6766 .merges = undefined, 6767 } else undefined; 6768 6769 // This is the block in which we evaluate generic function components: that is, generic parameter 6770 // types and the generic return type. This must not be used if the function is not generic. 6771 // `comptime_reason` is set as needed. 6772 var generic_block: Block = if (any_generic_types) .{ 6773 .parent = null, 6774 .sema = sema, 6775 .namespace = fn_nav.analysis.?.namespace, 6776 .instructions = .empty, 6777 .inlining = &generic_inlining, 6778 .src_base_inst = fn_nav.analysis.?.zir_index, 6779 .type_name_ctx = fn_nav.name, 6780 .type_fqn_ctx = fn_nav.fqn, 6781 } else undefined; 6782 defer if (any_generic_types) generic_block.instructions.deinit(gpa); 6783 6784 if (any_generic_types) { 6785 // We certainly depend on the generic owner's signature! 6786 try sema.declareDependency(.{ .src_hash = fn_tracked_inst }); 6787 } 6788 6789 const args = try arena.alloc(Air.Inst.Ref, args_info.count()); 6790 for (args, 0..) |*arg, arg_idx| { 6791 const param_ty: ?Type = if (arg_idx < func_ty_info.param_types.len) ty: { 6792 const raw = func_ty_info.param_types.get(ip)[arg_idx]; 6793 if (raw != .generic_poison_type) break :ty .fromInterned(raw); 6794 6795 // We must discover the generic parameter type. 6796 assert(any_generic_types); 6797 const param_inst_idx = fn_zir_info.param_body[arg_idx]; 6798 const param_inst = fn_zir.instructions.get(@backingInt(param_inst_idx)); 6799 switch (param_inst.tag) { 6800 .param_anytype, .param_anytype_comptime => break :ty .generic_poison, 6801 .param, .param_comptime => {}, 6802 else => unreachable, 6803 } 6804 6805 // Evaluate the generic parameter type. We need to switch out `sema.code` and `sema.inst_map`, because 6806 // the function definition may be in a different file to the call site. 6807 const old_code = sema.code; 6808 const old_inst_map = sema.inst_map; 6809 defer { 6810 generic_inst_map = sema.inst_map; 6811 sema.code = old_code; 6812 sema.inst_map = old_inst_map; 6813 } 6814 sema.code = fn_zir; 6815 sema.inst_map = generic_inst_map; 6816 6817 const extra = sema.code.extraData(Zir.Inst.Param, param_inst.data.pl_tok.payload_index); 6818 const param_src = generic_block.tokenOffset(param_inst.data.pl_tok.src_tok); 6819 const body = sema.code.bodySlice(extra.end, extra.data.type.body_len); 6820 6821 generic_block.comptime_reason = .{ .reason = .{ 6822 .r = .{ .simple = .fn_param_types }, 6823 .src = param_src, 6824 } }; 6825 6826 const ty_ref = try sema.resolveInlineBody(&generic_block, body, param_inst_idx); 6827 const param_ty = try sema.analyzeAsType(&generic_block, param_src, .fn_param_types, ty_ref); 6828 6829 if (!param_ty.isValidParamType(zcu)) { 6830 const opaque_str = if (param_ty.zigTypeTag(zcu) == .@"opaque") "opaque " else ""; 6831 return sema.fail(block, param_src, "parameter of {s}type '{f}' not allowed", .{ 6832 opaque_str, param_ty.fmt(pt), 6833 }); 6834 } 6835 6836 break :ty param_ty; 6837 } else null; // vararg 6838 6839 arg.* = try args_info.analyzeArg(sema, block, arg_idx, param_ty, func_ty_info, callee, maybe_func_inst); 6840 const arg_ty = sema.typeOf(arg.*); 6841 if (arg_ty.classify(zcu) == .no_possible_value) { 6842 return arg.*; // terminate analysis here 6843 } 6844 6845 if (any_generic_types) { 6846 // We need to put the argument into `generic_inst_map` so that other parameters can refer to it. 6847 const param_inst_idx = fn_zir_info.param_body[arg_idx]; 6848 const declared_comptime = if (std.math.cast(u5, arg_idx)) |i| func_ty_info.paramIsComptime(i) else false; 6849 const param_is_comptime = declared_comptime or arg_ty.comptimeOnly(zcu); 6850 // We allow comptime-known arguments to propagate to generic types not only for comptime 6851 // parameters, but if the call is known to be inline. 6852 if (param_is_comptime or early_known_inline) { 6853 if (param_is_comptime and !try sema.isComptimeKnown(arg.*)) { 6854 assert(!declared_comptime); // `analyzeArg` handles this 6855 const arg_src = args_info.argSrc(block, arg_idx); 6856 const param_ty_src: LazySrcLoc = .{ 6857 .base_node_inst = maybe_func_inst.?, // the function is generic 6858 .offset = .{ .func_decl_param_ty = @intCast(arg_idx) }, 6859 }; 6860 return sema.failWithNeededComptime( 6861 block, 6862 arg_src, 6863 .{ .comptime_only_param_ty = .{ .ty = arg_ty, .param_ty_src = param_ty_src } }, 6864 ); 6865 } 6866 generic_inst_map.putAssumeCapacityNoClobber(param_inst_idx, arg.*); 6867 } else if (try arg_ty.onePossibleValue(pt)) |opv| { 6868 // The argument is comptime-known, even though this is a generic instantiation (as 6869 // opposed to an inline call), because the parameter type is OPV. 6870 generic_inst_map.putAssumeCapacityNoClobber(param_inst_idx, .fromValue(opv)); 6871 } else { 6872 // We need a dummy instruction with this type. It doesn't actually need to be in any block, 6873 // since it will never be referenced at runtime! 6874 const dummy: Air.Inst.Index = @fromBackingInt(@intCast(sema.air_instructions.len)); 6875 try sema.air_instructions.append(gpa, .{ .tag = .alloc, .data = .{ .ty = arg_ty } }); 6876 generic_inst_map.putAssumeCapacityNoClobber(param_inst_idx, dummy.toRef()); 6877 } 6878 } 6879 } 6880 6881 // This return type is never generic poison. 6882 // However, if it has an IES, it is always associated with the callee value. 6883 // This is not correct for inline calls (where it should be an ad-hoc IES), nor for generic 6884 // calls (where it should be the IES of the instantiation). However, it's how we print this 6885 // in error messages. 6886 const resolved_ret_ty: Type = ret_ty: { 6887 if (!any_generic_types) break :ret_ty .fromInterned(func_ty_info.return_type); 6888 6889 const maybe_poison_bare = if (fn_zir_info.inferred_error_set) maybe_poison: { 6890 break :maybe_poison ip.errorUnionPayload(func_ty_info.return_type); 6891 } else func_ty_info.return_type; 6892 6893 if (maybe_poison_bare != .generic_poison_type) break :ret_ty .fromInterned(func_ty_info.return_type); 6894 6895 // Evaluate the generic return type. As with generic parameters, we switch out `sema.code` and `sema.inst_map`. 6896 6897 assert(any_generic_types); 6898 6899 const old_code = sema.code; 6900 const old_inst_map = sema.inst_map; 6901 defer { 6902 generic_inst_map = sema.inst_map; 6903 sema.code = old_code; 6904 sema.inst_map = old_inst_map; 6905 } 6906 sema.code = fn_zir; 6907 sema.inst_map = generic_inst_map; 6908 6909 generic_block.comptime_reason = .{ .reason = .{ 6910 .r = .{ .simple = .fn_ret_ty }, 6911 .src = func_ret_ty_src, 6912 } }; 6913 6914 const bare_ty = if (fn_zir_info.ret_ty_ref != .none) bare: { 6915 assert(fn_zir_info.ret_ty_body.len == 0); 6916 break :bare try sema.resolveType(&generic_block, func_ret_ty_src, fn_zir_info.ret_ty_ref); 6917 } else bare: { 6918 assert(fn_zir_info.ret_ty_body.len != 0); 6919 const ty_ref = try sema.resolveInlineBody(&generic_block, fn_zir_info.ret_ty_body, fn_zir_inst); 6920 break :bare try sema.analyzeAsType(&generic_block, func_ret_ty_src, .fn_ret_ty, ty_ref); 6921 }; 6922 assert(bare_ty.toIntern() != .generic_poison_type); 6923 6924 const full_ty = if (fn_zir_info.inferred_error_set) full: { 6925 try sema.validateErrorUnionPayloadType(block, bare_ty, func_ret_ty_src); 6926 const set = ip.errorUnionSet(func_ty_info.return_type); 6927 break :full try pt.errorUnionType(.fromInterned(set), bare_ty); 6928 } else bare_ty; 6929 6930 if (!full_ty.isValidReturnType(zcu)) { 6931 const opaque_str = if (full_ty.zigTypeTag(zcu) == .@"opaque") "opaque " else ""; 6932 return sema.fail(block, func_ret_ty_src, "{s}return type '{f}' not allowed", .{ 6933 opaque_str, full_ty.fmt(pt), 6934 }); 6935 } 6936 6937 break :ret_ty full_ty; 6938 }; 6939 try sema.ensureLayoutResolved(resolved_ret_ty, func_ret_ty_src, .return_type); 6940 6941 // If we've discovered after evaluating arguments that a generic function instantiation is 6942 // comptime-only, then we can mark the block as comptime *now*. 6943 if (!inline_requested and !block.isComptime() and resolved_ret_ty.comptimeOnly(zcu)) { 6944 block.comptime_reason = .{ 6945 .reason = .{ 6946 .src = call_src, 6947 .r = .{ 6948 .comptime_only_ret_ty = .{ 6949 .ty = resolved_ret_ty, 6950 .is_generic_inst = true, 6951 .ret_ty_src = func_ret_ty_src, 6952 }, 6953 }, 6954 }, 6955 }; 6956 } 6957 6958 if (call_dbg_node) |some| try sema.zirDbgStmt(block, some); 6959 6960 const is_inline_call = block.isComptime() or inline_requested; 6961 6962 if (!is_inline_call) { 6963 if (func_val == null and !func_is_extern and !block.is_typeof and zcu.getTarget().cpu.arch.isSpirV()) { 6964 return sema.fail(block, func_src, "SPIR-V does not support calling function pointers", .{}); 6965 } 6966 if (sema.func_is_naked) return sema.failWithOwnedErrorMsg(block, msg: { 6967 const msg = try sema.errMsg(call_src, "runtime {s} not allowed in naked function", .{@tagName(operation)}); 6968 errdefer msg.destroy(gpa); 6969 switch (operation) { 6970 .call, .@"@call", .@"@panic", .@"error return" => {}, 6971 .@"safety check" => try sema.errNote(call_src, msg, "use @setRuntimeSafety to disable runtime safety", .{}), 6972 } 6973 break :msg msg; 6974 }); 6975 if (func_ty_info.cc == .auto) { 6976 switch (sema.owner.unwrap()) { 6977 .@"comptime", 6978 .nav_ty, 6979 .nav_val, 6980 .type_layout, 6981 .struct_defaults, 6982 .memoized_state, 6983 => {}, 6984 6985 .func => |owner_func| ip.funcSetHasErrorTrace(io, owner_func, true), 6986 } 6987 } 6988 for (args, 0..) |arg, arg_idx| { 6989 const arg_src = args_info.argSrc(block, arg_idx); 6990 try sema.validateRuntimeValue(block, arg_src, arg); 6991 } 6992 const runtime_func: Air.Inst.Ref, const runtime_args: []const Air.Inst.Ref = func: { 6993 if (!any_generic_types and !any_comptime_params) break :func .{ callee, args }; 6994 6995 // Instantiate the generic function! 6996 6997 // This may be an overestimate, but it's definitely sufficient. 6998 const max_runtime_args = args_info.count() - @popCount(func_ty_info.comptime_bits); 6999 var runtime_args: std.ArrayList(Air.Inst.Ref) = try .initCapacity(arena, max_runtime_args); 7000 var runtime_param_tys: std.ArrayList(InternPool.Index) = try .initCapacity(arena, max_runtime_args); 7001 7002 const comptime_args = try arena.alloc(InternPool.Index, args_info.count()); 7003 7004 var noalias_bits: u32 = 0; 7005 7006 for (args, comptime_args, 0..) |arg, *comptime_arg, arg_idx| { 7007 const arg_ty = sema.typeOf(arg); 7008 7009 const is_comptime = c: { 7010 if (std.math.cast(u5, arg_idx)) |i| { 7011 if (func_ty_info.paramIsComptime(i)) { 7012 break :c true; 7013 } 7014 } 7015 break :c arg_ty.comptimeOnly(zcu); 7016 }; 7017 const is_noalias = if (std.math.cast(u5, arg_idx)) |i| func_ty_info.paramIsNoalias(i) else false; 7018 7019 if (is_comptime) { 7020 // We already emitted an error if the argument isn't comptime-known. 7021 comptime_arg.* = sema.resolveValue(arg).?.toIntern(); 7022 } else { 7023 comptime_arg.* = .none; 7024 if (is_noalias) { 7025 const runtime_idx = runtime_args.items.len; 7026 noalias_bits |= @as(u32, 1) << @intCast(runtime_idx); 7027 } 7028 runtime_args.appendAssumeCapacity(arg); 7029 runtime_param_tys.appendAssumeCapacity(arg_ty.toIntern()); 7030 } 7031 } 7032 7033 const bare_ret_ty = if (fn_zir_info.inferred_error_set) t: { 7034 break :t resolved_ret_ty.errorUnionPayload(zcu); 7035 } else resolved_ret_ty; 7036 7037 // We now need to actually create the function instance. 7038 const func_instance = try ip.getFuncInstance(gpa, io, pt.tid, .{ 7039 .param_types = runtime_param_tys.items, 7040 .noalias_bits = noalias_bits, 7041 .bare_return_type = bare_ret_ty.toIntern(), 7042 .is_noinline = func_ty_info.is_noinline, 7043 .inferred_error_set = fn_zir_info.inferred_error_set, 7044 .generic_owner = func_val.?.toIntern(), 7045 .comptime_args = comptime_args, 7046 .anon_name_counter = &zcu.anon_name_counter, 7047 }); 7048 if (zcu.comp.debugIncremental()) { 7049 const nav = ip.indexToKey(func_instance).func.owner_nav; 7050 const gop = try zcu.incremental_debug_state.navs.getOrPut(gpa, nav); 7051 if (!gop.found_existing) gop.value_ptr.* = zcu.generation; 7052 } 7053 7054 // This call is problematic as it breaks guarantees about order-independency of semantic analysis. 7055 // These guarantees are necessary for incremental compilation and parallel semantic analysis. 7056 // See: #22410 7057 zcu.funcInfo(func_instance).maxBranchQuota(ip, io, sema.branch_quota); 7058 7059 break :func .{ Air.internedToRef(func_instance), runtime_args.items }; 7060 }; 7061 7062 ref_func: { 7063 const runtime_func_val = sema.resolveValue(runtime_func) orelse break :ref_func; 7064 if (!ip.isFuncBody(runtime_func_val.toIntern())) break :ref_func; 7065 const orig_fn_index = ip.unwrapCoercedFunc(runtime_func_val.toIntern()); 7066 try sema.addReferenceEntry(block, call_src, .wrap(.{ .func = orig_fn_index })); 7067 try zcu.ensureFuncBodyAnalysisQueued(orig_fn_index); 7068 } 7069 7070 const call_tag: Air.Inst.Tag = switch (modifier) { 7071 .auto, .no_suspend => .call, 7072 .never_tail => .call_never_tail, 7073 .never_inline => .call_never_inline, 7074 .always_tail => .call_always_tail, 7075 7076 .always_inline, 7077 .compile_time, 7078 => unreachable, 7079 }; 7080 7081 try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.Call).@"struct".field_names.len + runtime_args.len); 7082 const call_ref = try block.addInst(.{ 7083 .tag = call_tag, 7084 .data = .{ .pl_op = .{ 7085 .operand = runtime_func, 7086 .payload = sema.addExtraAssumeCapacity(Air.Call{ 7087 .args_len = @intCast(runtime_args.len), 7088 }), 7089 } }, 7090 }); 7091 sema.appendRefsAssumeCapacity(runtime_args); 7092 7093 const actual_ret_ty = sema.typeOf(call_ref); 7094 7095 if (ensure_result_used) { 7096 try sema.ensureResultUsed(block, actual_ret_ty, call_src); 7097 } 7098 7099 if (call_tag == .call_always_tail) { 7100 const func_or_ptr_ty = sema.typeOf(runtime_func); 7101 const runtime_func_ty = switch (func_or_ptr_ty.zigTypeTag(zcu)) { 7102 .@"fn" => func_or_ptr_ty, 7103 .pointer => func_or_ptr_ty.childType(zcu), 7104 else => unreachable, 7105 }; 7106 const result = sema.coerceExtra(block, sema.fn_ret_ty, call_ref, call_src, .{ .is_ret = true }) catch |err| switch (err) { 7107 error.NotCoercible => unreachable, 7108 else => |e| return e, 7109 }; 7110 return sema.handleTailCall(block, call_src, runtime_func_ty, result); 7111 } 7112 7113 switch (actual_ret_ty.classify(zcu)) { 7114 .no_possible_value => { 7115 const want_check = c: { 7116 if (!block.wantSafety()) break :c false; 7117 if (func_val != null) break :c false; 7118 break :c true; 7119 }; 7120 if (want_check) { 7121 try sema.safetyPanic(block, call_src, .noreturn_returned); 7122 } else { 7123 _ = try block.addNoOp(.unreach); 7124 } 7125 return .unreachable_value; 7126 }, 7127 .one_possible_value => { 7128 return .fromValue((try actual_ret_ty.onePossibleValue(pt)).?); 7129 }, 7130 .runtime => { 7131 return call_ref; 7132 }, 7133 .partially_comptime => unreachable, 7134 .fully_comptime => unreachable, 7135 } 7136 } 7137 7138 // This is an inline call. The function must be comptime-known. We will analyze its body directly using this `Sema`. 7139 7140 if (zcu.comp.time_report) |*tr| { 7141 if (!block.isComptime()) { 7142 tr.stats.n_inline_calls += 1; 7143 } 7144 } 7145 7146 if (func_ty_info.is_noinline and !block.isComptime()) { 7147 return sema.fail(block, call_src, "inline call of noinline function", .{}); 7148 } 7149 7150 const call_type: []const u8 = if (block.isComptime()) "comptime" else "inline"; 7151 if (modifier == .never_inline) { 7152 const msg, const fail_block = msg: { 7153 const msg = try sema.errMsg(call_src, "cannot perform {s} call with 'never_inline' modifier", .{call_type}); 7154 errdefer msg.destroy(gpa); 7155 const fail_block = if (block.isComptime()) b: { 7156 break :b try block.explainWhyBlockIsComptime(msg); 7157 } else block; 7158 break :msg .{ msg, fail_block }; 7159 }; 7160 return sema.failWithOwnedErrorMsg(fail_block, msg); 7161 } 7162 if (func_ty_info.is_var_args) { 7163 const msg, const fail_block = msg: { 7164 const msg = try sema.errMsg(call_src, "{s} call of variadic function", .{call_type}); 7165 errdefer msg.destroy(gpa); 7166 const fail_block = if (block.isComptime()) b: { 7167 break :b try block.explainWhyBlockIsComptime(msg); 7168 } else block; 7169 break :msg .{ msg, fail_block }; 7170 }; 7171 return sema.failWithOwnedErrorMsg(fail_block, msg); 7172 } 7173 if (func_val == null) { 7174 if (func_is_extern) { 7175 const msg, const fail_block = msg: { 7176 const msg = try sema.errMsg(call_src, "{s} call of extern function", .{call_type}); 7177 errdefer msg.destroy(gpa); 7178 const fail_block = if (block.isComptime()) b: { 7179 break :b try block.explainWhyBlockIsComptime(msg); 7180 } else block; 7181 break :msg .{ msg, fail_block }; 7182 }; 7183 return sema.failWithOwnedErrorMsg(fail_block, msg); 7184 } 7185 return sema.failWithNeededComptime( 7186 block, 7187 func_src, 7188 if (block.isComptime()) null else .{ .simple = .inline_call_target }, 7189 ); 7190 } 7191 7192 if (block.isComptime()) { 7193 for (args, 0..) |arg, arg_idx| { 7194 if (!try sema.isComptimeKnown(arg)) { 7195 const arg_src = args_info.argSrc(block, arg_idx); 7196 return sema.failWithNeededComptime(block, arg_src, null); 7197 } 7198 } 7199 } 7200 7201 // For an inline call, we depend on the source code of the whole function definition. 7202 try sema.declareDependency(.{ .src_hash = fn_nav.analysis.?.zir_index }); 7203 7204 try sema.emitBackwardBranch(block, call_src); 7205 7206 const want_memoize = m: { 7207 // TODO: comptime call memoization is currently not supported under incremental compilation 7208 // since dependencies are not marked on callers. If we want to keep this around (we should 7209 // check that it's worthwhile first!), each memoized call needs an `AnalUnit`. 7210 if (zcu.comp.config.incremental) break :m false; 7211 if (!block.isComptime()) break :m false; 7212 for (args) |a| { 7213 const val = sema.resolveValue(a).?; 7214 if (val.canMutateComptimeVarState(zcu)) break :m false; 7215 } 7216 break :m true; 7217 }; 7218 const memoized_arg_values: []const InternPool.Index = if (want_memoize) arg_vals: { 7219 const vals = try sema.arena.alloc(InternPool.Index, args.len); 7220 for (vals, args) |*v, a| v.* = sema.resolveValue(a).?.toIntern(); 7221 break :arg_vals vals; 7222 } else undefined; 7223 if (want_memoize) memoize: { 7224 const memoized_call_index = ip.getIfExists(.{ 7225 .memoized_call = .{ 7226 .func = func_val.?.toIntern(), 7227 .arg_values = memoized_arg_values, 7228 .result = undefined, // ignored by hash+eql 7229 .branch_count = undefined, // ignored by hash+eql 7230 .branch_quota = undefined, // ignored by hash+eql 7231 }, 7232 }) orelse break :memoize; 7233 const memoized_call = ip.indexToKey(memoized_call_index).memoized_call; 7234 if (sema.branch_count + memoized_call.branch_count > sema.branch_quota) { 7235 // Let the call play out se we get the correct source location for the 7236 // "evaluation exceeded X backwards branches" error. 7237 break :memoize; 7238 } 7239 sema.branch_count += memoized_call.branch_count; 7240 sema.branch_quota = @max(sema.branch_quota, memoized_call.branch_quota); 7241 sema.quota_request = @max(sema.quota_request, memoized_call.branch_quota); 7242 const result = Air.internedToRef(memoized_call.result); 7243 if (ensure_result_used) { 7244 try sema.ensureResultUsed(block, sema.typeOf(result), call_src); 7245 } 7246 return result; 7247 } 7248 7249 var new_ies: InferredErrorSet = .{ .func = .none }; 7250 7251 const old_inst_map = sema.inst_map; 7252 const old_code = sema.code; 7253 const old_func_index = sema.func_index; 7254 const old_fn_ret_ty = sema.fn_ret_ty; 7255 const old_fn_ret_ty_ies = sema.fn_ret_ty_ies; 7256 const old_error_return_trace_index_on_fn_entry = sema.error_return_trace_index_on_fn_entry; 7257 defer { 7258 sema.inst_map.deinit(gpa); 7259 sema.inst_map = old_inst_map; 7260 sema.code = old_code; 7261 sema.func_index = old_func_index; 7262 sema.fn_ret_ty = old_fn_ret_ty; 7263 sema.fn_ret_ty_ies = old_fn_ret_ty_ies; 7264 sema.error_return_trace_index_on_fn_entry = old_error_return_trace_index_on_fn_entry; 7265 } 7266 sema.inst_map = .{}; 7267 sema.code = fn_zir; 7268 sema.func_index = func_val.?.toIntern(); 7269 sema.fn_ret_ty = if (fn_zir_info.inferred_error_set) try pt.errorUnionType( 7270 .fromInterned(.adhoc_inferred_error_set_type), 7271 resolved_ret_ty.errorUnionPayload(zcu), 7272 ) else resolved_ret_ty; 7273 sema.fn_ret_ty_ies = if (fn_zir_info.inferred_error_set) &new_ies else null; 7274 7275 try sema.inst_map.ensureSpaceForInstructions(gpa, fn_zir_info.param_body); 7276 for (args, 0..) |arg, arg_idx| { 7277 sema.inst_map.putAssumeCapacityNoClobber(fn_zir_info.param_body[arg_idx], arg); 7278 } 7279 7280 const need_debug_scope = !block.isComptime() and !block.is_typeof and !block.ownerModule().strip; 7281 const block_inst: Air.Inst.Index = @fromBackingInt(@intCast(sema.air_instructions.len)); 7282 try sema.air_instructions.append(gpa, .{ 7283 .tag = if (need_debug_scope) .dbg_inline_block else .block, 7284 .data = undefined, 7285 }); 7286 7287 var inlining: Block.Inlining = .{ 7288 .call_block = block, 7289 .call_src = call_src, 7290 .func = func_val.?.toIntern(), 7291 .is_generic_instantiation = false, 7292 .has_comptime_args = for (args) |a| { 7293 if (try sema.isComptimeKnown(a)) break true; 7294 } else false, 7295 .comptime_result = undefined, 7296 .merges = .{ 7297 .block_inst = block_inst, 7298 .results = .empty, 7299 .br_list = .empty, 7300 .src_locs = .empty, 7301 }, 7302 }; 7303 var child_block: Block = .{ 7304 .parent = null, 7305 .sema = sema, 7306 .namespace = fn_nav.analysis.?.namespace, 7307 .instructions = .empty, 7308 .inlining = &inlining, 7309 .is_typeof = block.is_typeof, 7310 .comptime_reason = if (block.isComptime()) .inlining_parent else null, 7311 .error_return_trace_index = block.error_return_trace_index, 7312 .runtime_cond = block.runtime_cond, 7313 .runtime_loop = block.runtime_loop, 7314 .runtime_index = block.runtime_index, 7315 .src_base_inst = fn_nav.analysis.?.zir_index, 7316 .type_name_ctx = fn_nav.name, 7317 .type_fqn_ctx = fn_nav.fqn, 7318 }; 7319 7320 defer child_block.instructions.deinit(gpa); 7321 defer inlining.merges.deinit(gpa); 7322 7323 if (!inlining.has_comptime_args) { 7324 var block_it = block; 7325 while (block_it.inlining) |parent_inlining| { 7326 if (!parent_inlining.is_generic_instantiation and 7327 !parent_inlining.has_comptime_args and 7328 parent_inlining.func == func_val.?.toIntern()) 7329 { 7330 return sema.fail(block, call_src, "inline call is recursive", .{}); 7331 } 7332 block_it = parent_inlining.call_block; 7333 } 7334 } 7335 7336 if (!block.isComptime() and !block.is_typeof) { 7337 const zir_tags = sema.code.instructions.items(.tag); 7338 const zir_datas = sema.code.instructions.items(.data); 7339 for (fn_zir_info.param_body) |inst| switch (zir_tags[@backingInt(inst)]) { 7340 .param, .param_comptime => { 7341 const extra = sema.code.extraData(Zir.Inst.Param, zir_datas[@backingInt(inst)].pl_tok.payload_index); 7342 const param_name = sema.code.nullTerminatedString(extra.data.name); 7343 const air_inst = sema.inst_map.get(inst).?; 7344 try sema.addDbgVar(&child_block, air_inst, .dbg_arg_inline, param_name); 7345 }, 7346 .param_anytype, .param_anytype_comptime => { 7347 const param_name = zir_datas[@backingInt(inst)].str_tok.get(sema.code); 7348 const air_inst = sema.inst_map.get(inst).?; 7349 try sema.addDbgVar(&child_block, air_inst, .dbg_arg_inline, param_name); 7350 }, 7351 else => {}, 7352 }; 7353 } 7354 7355 child_block.error_return_trace_index = try sema.analyzeSaveErrRetIndex(&child_block); 7356 // Save the error trace as our first action in the function 7357 // to match the behavior of runtime function calls. 7358 const error_return_trace_index_on_parent_fn_entry = sema.error_return_trace_index_on_fn_entry; 7359 sema.error_return_trace_index_on_fn_entry = child_block.error_return_trace_index; 7360 defer sema.error_return_trace_index_on_fn_entry = error_return_trace_index_on_parent_fn_entry; 7361 7362 // We temporarily set `allow_memoize` to `true` to track this comptime call. 7363 // It is restored after the call finishes analysis, so that a caller may 7364 // know whether an in-progress call (containing this call) may be memoized. 7365 const old_allow_memoize = sema.allow_memoize; 7366 defer sema.allow_memoize = old_allow_memoize and sema.allow_memoize; 7367 sema.allow_memoize = true; 7368 7369 const old_quota_request = sema.quota_request; 7370 defer sema.quota_request = @max(old_quota_request, sema.quota_request); 7371 sema.quota_request = 0; 7372 7373 // Store the current eval branch count so we can find out how many eval branches 7374 // the comptime call caused. 7375 const old_branch_count = sema.branch_count; 7376 7377 const result_raw: Air.Inst.Ref = result: { 7378 sema.analyzeFnBody(&child_block, fn_zir_info.body) catch |err| switch (err) { 7379 error.ComptimeReturn => break :result inlining.comptime_result, 7380 else => |e| return e, 7381 }; 7382 break :result try sema.resolveAnalyzedBlock(block, call_src, &child_block, &inlining.merges, need_debug_scope); 7383 }; 7384 7385 if (sema.typeOf(result_raw).isNoReturn(zcu)) { 7386 return .unreachable_value; 7387 } 7388 7389 const maybe_opv: Air.Inst.Ref = if (sema.resolveValue(result_raw)) |result_val| r: { 7390 const val_resolved = try sema.resolveAdHocInferredErrorSet(block, call_src, result_val.toIntern()); 7391 break :r Air.internedToRef(val_resolved); 7392 } else r: { 7393 const resolved_ty = try sema.resolveAdHocInferredErrorSetTy(block, call_src, sema.typeOf(result_raw).toIntern()); 7394 if (resolved_ty == .none) break :r result_raw; 7395 // TODO: mutate in place the previous instruction if possible 7396 // rather than adding a bitcast instruction. 7397 break :r try block.addTyOp(.error_cast, .fromInterned(resolved_ty), result_raw); 7398 }; 7399 7400 if (block.isComptime()) { 7401 const result_val = sema.resolveValue(maybe_opv).?; 7402 if (want_memoize and sema.allow_memoize and !result_val.canMutateComptimeVarState(zcu)) { 7403 _ = try pt.intern(.{ .memoized_call = .{ 7404 .func = func_val.?.toIntern(), 7405 .arg_values = memoized_arg_values, 7406 .result = result_val.toIntern(), 7407 .branch_count = sema.branch_count - old_branch_count, 7408 .branch_quota = sema.quota_request, 7409 } }); 7410 } 7411 } 7412 7413 if (ensure_result_used) { 7414 try sema.ensureResultUsed(block, sema.typeOf(maybe_opv), call_src); 7415 } 7416 7417 return maybe_opv; 7418 } 7419 7420 fn handleTailCall(sema: *Sema, block: *Block, call_src: LazySrcLoc, func_ty: Type, result: Air.Inst.Ref) !Air.Inst.Ref { 7421 const pt = sema.pt; 7422 const zcu = pt.zcu; 7423 const target = zcu.getTarget(); 7424 const backend = zcu.comp.getZigBackend(); 7425 if (!target_util.supportsTailCall(target, backend)) { 7426 return sema.fail(block, call_src, "unable to perform tail call: compiler backend '{s}' does not support tail calls on target architecture '{s}' with the selected CPU feature flags", .{ 7427 @tagName(backend), @tagName(target.cpu.arch), 7428 }); 7429 } 7430 const owner_func_ty: Type = .fromInterned(zcu.funcInfo(sema.owner.unwrap().func).ty); 7431 if (owner_func_ty.toIntern() != func_ty.toIntern()) { 7432 return sema.fail(block, call_src, "unable to perform tail call: type of function being called '{f}' does not match type of calling function '{f}'", .{ 7433 func_ty.fmt(pt), owner_func_ty.fmt(pt), 7434 }); 7435 } 7436 _ = try block.addUnOp(.ret, result); 7437 return .unreachable_value; 7438 } 7439 7440 fn zirIntType(sema: *Sema, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 7441 const int_type = sema.code.instructions.items(.data)[@backingInt(inst)].int_type; 7442 const ty = try sema.pt.intType(int_type.signedness, int_type.bit_count); 7443 return Air.internedToRef(ty.toIntern()); 7444 } 7445 7446 fn zirOptionalType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 7447 const pt = sema.pt; 7448 const zcu = pt.zcu; 7449 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].un_node; 7450 const operand_src = block.src(.{ .node_offset_un_op = inst_data.src_node }); 7451 const child_type = try sema.resolveType(block, operand_src, inst_data.operand); 7452 if (child_type.zigTypeTag(zcu) == .@"opaque") { 7453 return sema.fail(block, operand_src, "opaque type '{f}' cannot be optional", .{child_type.fmt(pt)}); 7454 } else if (child_type.zigTypeTag(zcu) == .null) { 7455 return sema.fail(block, operand_src, "type '{f}' cannot be optional", .{child_type.fmt(pt)}); 7456 } 7457 const opt_type = try pt.optionalType(child_type.toIntern()); 7458 7459 return Air.internedToRef(opt_type.toIntern()); 7460 } 7461 7462 fn zirArrayInitElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 7463 const pt = sema.pt; 7464 const zcu = pt.zcu; 7465 const bin = sema.code.instructions.items(.data)[@backingInt(inst)].bin; 7466 const maybe_wrapped_indexable_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, bin.lhs) orelse return .generic_poison_type; 7467 const indexable_ty = maybe_wrapped_indexable_ty.optEuBaseType(zcu); 7468 assert(indexable_ty.isIndexable(zcu)); // validated by a previous instruction 7469 const elem_ty = switch (indexable_ty.zigTypeTag(zcu)) { 7470 .@"struct" => indexable_ty.fieldType(@backingInt(bin.rhs), zcu), 7471 else => indexable_ty.indexableElem(zcu), 7472 }; 7473 return .fromType(elem_ty); 7474 } 7475 7476 fn zirElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 7477 const pt = sema.pt; 7478 const zcu = pt.zcu; 7479 const un_node = sema.code.instructions.items(.data)[@backingInt(inst)].un_node; 7480 const maybe_wrapped_ptr_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, un_node.operand) orelse return .generic_poison_type; 7481 const ptr_ty = maybe_wrapped_ptr_ty.optEuBaseType(zcu); 7482 assert(ptr_ty.zigTypeTag(zcu) == .pointer); // validated by a previous instruction 7483 const elem_ty = ptr_ty.childType(zcu); 7484 if (elem_ty.toIntern() == .anyopaque_type) { 7485 // The pointer's actual child type is effectively unknown, so it makes 7486 // sense to represent it with a generic poison. 7487 return .generic_poison_type; 7488 } 7489 return Air.internedToRef(ptr_ty.childType(zcu).toIntern()); 7490 } 7491 7492 fn zirIndexablePtrElemType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 7493 const pt = sema.pt; 7494 const zcu = pt.zcu; 7495 const un_node = sema.code.instructions.items(.data)[@backingInt(inst)].un_node; 7496 const src = block.nodeOffset(un_node.src_node); 7497 const ptr_ty = try sema.resolveTypeOrPoison(block, src, un_node.operand) orelse return .generic_poison_type; 7498 try sema.checkMemOperand(block, src, ptr_ty); 7499 const elem_ty = switch (ptr_ty.ptrSize(zcu)) { 7500 .slice, .many, .c => ptr_ty.childType(zcu), 7501 .one => ptr_ty.childType(zcu).childType(zcu), 7502 }; 7503 return Air.internedToRef(elem_ty.toIntern()); 7504 } 7505 7506 fn zirSplatOpResultType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 7507 const pt = sema.pt; 7508 const zcu = pt.zcu; 7509 const un_node = sema.code.instructions.items(.data)[@backingInt(inst)].un_node; 7510 7511 const raw_ty = try sema.resolveTypeOrPoison(block, LazySrcLoc.unneeded, un_node.operand) orelse return .generic_poison_type; 7512 const vec_ty = raw_ty.optEuBaseType(zcu); 7513 7514 switch (vec_ty.zigTypeTag(zcu)) { 7515 .array, .vector => {}, 7516 else => return sema.fail(block, block.nodeOffset(un_node.src_node), "expected array or vector type, found '{f}'", .{vec_ty.fmt(pt)}), 7517 } 7518 return Air.internedToRef(vec_ty.childType(zcu).toIntern()); 7519 } 7520 7521 fn zirVectorType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 7522 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 7523 const len_src = block.builtinCallArgSrc(inst_data.src_node, 0); 7524 const elem_type_src = block.builtinCallArgSrc(inst_data.src_node, 1); 7525 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; 7526 const len: u32 = @intCast(try sema.resolveInt(block, len_src, extra.lhs, .u32, .{ .simple = .vector_length })); 7527 const elem_type = try sema.resolveType(block, elem_type_src, extra.rhs); 7528 try sema.checkVectorElemType(block, elem_type_src, elem_type); 7529 const vector_type = try sema.pt.vectorType(.{ 7530 .len = len, 7531 .child = elem_type.toIntern(), 7532 }); 7533 return Air.internedToRef(vector_type.toIntern()); 7534 } 7535 7536 fn zirArrayType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 7537 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 7538 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; 7539 const len_src = block.src(.{ .node_offset_array_type_len = inst_data.src_node }); 7540 const elem_src = block.src(.{ .node_offset_array_type_elem = inst_data.src_node }); 7541 const len = try sema.resolveInt(block, len_src, extra.lhs, .usize, .{ .simple = .array_length }); 7542 const elem_type = try sema.resolveType(block, elem_src, extra.rhs); 7543 try sema.validateArrayElemType(block, elem_type, elem_src); 7544 const array_ty = try sema.pt.arrayType(.{ 7545 .len = len, 7546 .child = elem_type.toIntern(), 7547 }); 7548 7549 return Air.internedToRef(array_ty.toIntern()); 7550 } 7551 7552 fn zirArrayTypeSentinel(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 7553 const pt = sema.pt; 7554 const zcu = pt.zcu; 7555 const comp = zcu.comp; 7556 const gpa = comp.gpa; 7557 const io = comp.io; 7558 const ip = &zcu.intern_pool; 7559 7560 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 7561 const extra = sema.code.extraData(Zir.Inst.ArrayTypeSentinel, inst_data.payload_index).data; 7562 const len_src = block.src(.{ .node_offset_array_type_len = inst_data.src_node }); 7563 const sentinel_src = block.src(.{ .node_offset_array_type_sentinel = inst_data.src_node }); 7564 const elem_src = block.src(.{ .node_offset_array_type_elem = inst_data.src_node }); 7565 const len = try sema.resolveInt(block, len_src, extra.len, .usize, .{ .simple = .array_length }); 7566 const elem_type = try sema.resolveType(block, elem_src, extra.elem_type); 7567 try sema.validateArrayElemType(block, elem_type, elem_src); 7568 const uncasted_sentinel = sema.resolveInst(extra.sentinel); 7569 const sentinel = try sema.coerce(block, elem_type, uncasted_sentinel, sentinel_src); 7570 const sentinel_val = try sema.resolveConstDefinedValue(block, sentinel_src, sentinel, .{ .simple = .array_sentinel }); 7571 if (sentinel_val.canMutateComptimeVarState(zcu)) { 7572 const sentinel_name = try ip.getOrPutString(gpa, io, pt.tid, "sentinel", .no_embedded_nulls); 7573 return sema.failWithContainsReferenceToComptimeVar(block, sentinel_src, sentinel_name, "sentinel", sentinel_val); 7574 } 7575 const array_ty = try pt.arrayType(.{ 7576 .len = len, 7577 .sentinel = sentinel_val.toIntern(), 7578 .child = elem_type.toIntern(), 7579 }); 7580 try sema.checkSentinelType(block, sentinel_src, elem_type); 7581 7582 return Air.internedToRef(array_ty.toIntern()); 7583 } 7584 7585 fn validateArrayElemType(sema: *Sema, block: *Block, elem_type: Type, elem_src: LazySrcLoc) !void { 7586 const pt = sema.pt; 7587 const zcu = pt.zcu; 7588 if (elem_type.zigTypeTag(zcu) == .@"opaque") { 7589 return sema.fail(block, elem_src, "array of opaque type '{f}' not allowed", .{elem_type.fmt(pt)}); 7590 } else if (elem_type.zigTypeTag(zcu) == .noreturn) { 7591 return sema.fail(block, elem_src, "array of 'noreturn' not allowed", .{}); 7592 } 7593 } 7594 7595 fn zirAnyframeType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 7596 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].un_node; 7597 if (true) { 7598 return sema.failWithUseOfAsync(block, block.nodeOffset(inst_data.src_node)); 7599 } 7600 const zcu = sema.zcu; 7601 const operand_src = block.src(.{ .node_offset_anyframe_type = inst_data.src_node }); 7602 const return_type = try sema.resolveType(block, operand_src, inst_data.operand); 7603 const anyframe_type = try zcu.anyframeType(return_type); 7604 7605 return Air.internedToRef(anyframe_type.toIntern()); 7606 } 7607 7608 fn zirErrorUnionType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 7609 const pt = sema.pt; 7610 const zcu = pt.zcu; 7611 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 7612 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; 7613 const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); 7614 const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); 7615 const error_set = try sema.resolveType(block, lhs_src, extra.lhs); 7616 const payload = try sema.resolveType(block, rhs_src, extra.rhs); 7617 7618 if (error_set.zigTypeTag(zcu) != .error_set) { 7619 return sema.fail(block, lhs_src, "expected error set type, found '{f}'", .{ 7620 error_set.fmt(pt), 7621 }); 7622 } 7623 try sema.validateErrorUnionPayloadType(block, payload, rhs_src); 7624 const err_union_ty = try pt.errorUnionType(error_set, payload); 7625 return Air.internedToRef(err_union_ty.toIntern()); 7626 } 7627 7628 fn validateErrorUnionPayloadType(sema: *Sema, block: *Block, payload_ty: Type, payload_src: LazySrcLoc) !void { 7629 const pt = sema.pt; 7630 const zcu = pt.zcu; 7631 if (payload_ty.zigTypeTag(zcu) == .@"opaque") { 7632 return sema.fail(block, payload_src, "error union with payload of opaque type '{f}' not allowed", .{ 7633 payload_ty.fmt(pt), 7634 }); 7635 } else if (payload_ty.zigTypeTag(zcu) == .error_set) { 7636 return sema.fail(block, payload_src, "error union with payload of error set type '{f}' not allowed", .{ 7637 payload_ty.fmt(pt), 7638 }); 7639 } 7640 } 7641 7642 fn zirErrorValue(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 7643 _ = block; 7644 7645 const pt = sema.pt; 7646 const zcu = pt.zcu; 7647 const comp = zcu.comp; 7648 const gpa = comp.gpa; 7649 const io = comp.io; 7650 7651 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].str_tok; 7652 const name = try pt.zcu.intern_pool.getOrPutString( 7653 gpa, 7654 io, 7655 pt.tid, 7656 inst_data.get(sema.code), 7657 .no_embedded_nulls, 7658 ); 7659 _ = try pt.getErrorValue(name); 7660 // Create an error set type with only this error value, and return the value. 7661 const error_set_type = try pt.singleErrorSetType(name); 7662 return Air.internedToRef((try pt.intern(.{ .err = .{ 7663 .ty = error_set_type.toIntern(), 7664 .name = name, 7665 } }))); 7666 } 7667 7668 fn zirIntFromError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { 7669 const pt = sema.pt; 7670 const zcu = pt.zcu; 7671 const ip = &zcu.intern_pool; 7672 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; 7673 const src = block.nodeOffset(extra.node); 7674 const operand_src = block.builtinCallArgSrc(extra.node, 0); 7675 const uncasted_operand = sema.resolveInst(extra.operand); 7676 const operand = try sema.coerce(block, .anyerror, uncasted_operand, operand_src); 7677 const err_int_ty = try pt.errorIntType(); 7678 7679 if (sema.resolveValue(operand)) |val| { 7680 if (val.isUndef(zcu)) { 7681 return pt.undefRef(err_int_ty); 7682 } 7683 const err_name = ip.indexToKey(val.toIntern()).err.name; 7684 return Air.internedToRef((try pt.intValue( 7685 err_int_ty, 7686 try pt.getErrorValue(err_name), 7687 )).toIntern()); 7688 } 7689 7690 const op_ty = sema.typeOf(uncasted_operand); 7691 switch (try sema.resolveInferredErrorSetTy(block, src, op_ty.toIntern())) { 7692 .anyerror_type => {}, 7693 else => |err_set_ty_index| { 7694 const names = ip.indexToKey(err_set_ty_index).error_set_type.names; 7695 switch (names.len) { 7696 0 => return Air.internedToRef((try pt.intValue(err_int_ty, 0)).toIntern()), 7697 1 => return pt.intRef(err_int_ty, ip.getErrorValueIfExists(names.get(ip)[0]).?), 7698 else => {}, 7699 } 7700 }, 7701 } 7702 7703 try sema.requireRuntimeBlock(block, src, operand_src); 7704 return block.addTyOp(.int_from_error, err_int_ty, operand); 7705 } 7706 7707 fn zirErrorFromInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData) CompileError!Air.Inst.Ref { 7708 const pt = sema.pt; 7709 const zcu = pt.zcu; 7710 const io = zcu.comp.io; 7711 const ip = &zcu.intern_pool; 7712 7713 const extra = sema.code.extraData(Zir.Inst.UnNode, extended.operand).data; 7714 const src = block.nodeOffset(extra.node); 7715 const operand_src = block.builtinCallArgSrc(extra.node, 0); 7716 const uncasted_operand = sema.resolveInst(extra.operand); 7717 const err_int_ty = try pt.errorIntType(); 7718 const operand = try sema.coerce(block, err_int_ty, uncasted_operand, operand_src); 7719 7720 if (try sema.resolveDefinedValue(block, operand_src, operand)) |value| { 7721 const int = try sema.usizeCast(block, operand_src, value.toUnsignedInt(zcu)); 7722 if (int > len: { 7723 const mutate = &ip.global_error_set.mutate; 7724 mutate.map.mutex.lockUncancelable(io); 7725 defer mutate.map.mutex.unlock(io); 7726 break :len mutate.names.len; 7727 } or int == 0) 7728 return sema.fail(block, operand_src, "integer value '{d}' represents no error", .{int}); 7729 return Air.internedToRef((try pt.intern(.{ .err = .{ 7730 .ty = .anyerror_type, 7731 .name = ip.global_error_set.shared.names.acquire().view().items(.@"0")[int - 1], 7732 } }))); 7733 } 7734 try sema.requireRuntimeBlock(block, src, operand_src); 7735 if (block.wantSafety()) { 7736 const is_lte_len = try block.addUnOp(.cmp_lte_errors_len, operand); 7737 const zero_val = Air.internedToRef((try pt.intValue(err_int_ty, 0)).toIntern()); 7738 const is_non_zero = try block.addBinOp(.cmp_neq, operand, zero_val); 7739 const ok = try block.addBinOp(.bit_and, is_lte_len, is_non_zero); 7740 try sema.addSafetyCheck(block, src, ok, .invalid_error_code); 7741 } 7742 return block.addTyOp(.error_from_int, .anyerror, operand); 7743 } 7744 7745 fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 7746 const pt = sema.pt; 7747 const zcu = pt.zcu; 7748 const ip = &zcu.intern_pool; 7749 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 7750 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; 7751 const src = block.src(.{ .node_offset_bin_op = inst_data.src_node }); 7752 const lhs_src = block.src(.{ .node_offset_bin_lhs = inst_data.src_node }); 7753 const rhs_src = block.src(.{ .node_offset_bin_rhs = inst_data.src_node }); 7754 const lhs = sema.resolveInst(extra.lhs); 7755 const rhs = sema.resolveInst(extra.rhs); 7756 if (sema.typeOf(lhs).zigTypeTag(zcu) == .bool and sema.typeOf(rhs).zigTypeTag(zcu) == .bool) { 7757 const msg = msg: { 7758 const msg = try sema.errMsg(lhs_src, "expected error set type, found 'bool'", .{}); 7759 errdefer msg.destroy(sema.gpa); 7760 try sema.errNote(src, msg, "'||' merges error sets; 'or' performs boolean OR", .{}); 7761 break :msg msg; 7762 }; 7763 return sema.failWithOwnedErrorMsg(block, msg); 7764 } 7765 const lhs_ty = try sema.analyzeAsType(block, lhs_src, .type, lhs); 7766 const rhs_ty = try sema.analyzeAsType(block, rhs_src, .type, rhs); 7767 if (lhs_ty.zigTypeTag(zcu) != .error_set) 7768 return sema.fail(block, lhs_src, "expected error set type, found '{f}'", .{lhs_ty.fmt(pt)}); 7769 if (rhs_ty.zigTypeTag(zcu) != .error_set) 7770 return sema.fail(block, rhs_src, "expected error set type, found '{f}'", .{rhs_ty.fmt(pt)}); 7771 7772 // Anything merged with anyerror is anyerror. 7773 if (lhs_ty.toIntern() == .anyerror_type or rhs_ty.toIntern() == .anyerror_type) { 7774 return .anyerror_type; 7775 } 7776 7777 switch (ip.indexToKey(lhs_ty.toIntern())) { 7778 .inferred_error_set_type => |func_index| { 7779 try sema.ensureFuncIesResolved(block, src, func_index); 7780 if (ip.funcIesResolvedUnordered(func_index) == .anyerror_type) return .anyerror_type; 7781 }, 7782 .error_set_type => {}, 7783 else => unreachable, 7784 } 7785 switch (ip.indexToKey(rhs_ty.toIntern())) { 7786 .inferred_error_set_type => |func_index| { 7787 try sema.ensureFuncIesResolved(block, src, func_index); 7788 if (ip.funcIesResolvedUnordered(func_index) == .anyerror_type) return .anyerror_type; 7789 }, 7790 .error_set_type => {}, 7791 else => unreachable, 7792 } 7793 7794 const err_set_ty = try sema.errorSetMerge(lhs_ty, rhs_ty); 7795 return Air.internedToRef(err_set_ty.toIntern()); 7796 } 7797 7798 fn zirEnumLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 7799 _ = block; 7800 7801 const pt = sema.pt; 7802 const zcu = pt.zcu; 7803 const comp = zcu.comp; 7804 const gpa = comp.gpa; 7805 const io = comp.io; 7806 7807 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].str_tok; 7808 const name = inst_data.get(sema.code); 7809 return Air.internedToRef((try pt.intern(.{ 7810 .enum_literal = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, name, .no_embedded_nulls), 7811 }))); 7812 } 7813 7814 fn zirDeclLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index, do_coerce: bool) CompileError!Air.Inst.Ref { 7815 const pt = sema.pt; 7816 const zcu = pt.zcu; 7817 const comp = zcu.comp; 7818 const gpa = comp.gpa; 7819 const io = comp.io; 7820 7821 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 7822 const src = block.nodeOffset(inst_data.src_node); 7823 const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data; 7824 const name = try zcu.intern_pool.getOrPutString( 7825 gpa, 7826 io, 7827 pt.tid, 7828 sema.code.nullTerminatedString(extra.field_name_start), 7829 .no_embedded_nulls, 7830 ); 7831 const orig_ty: Type = try sema.resolveTypeOrPoison(block, src, extra.lhs) orelse .generic_poison; 7832 return sema.analyzeDeclLiteral(block, src, name, orig_ty, do_coerce); 7833 } 7834 7835 fn analyzeDeclLiteral( 7836 sema: *Sema, 7837 block: *Block, 7838 src: LazySrcLoc, 7839 name: InternPool.NullTerminatedString, 7840 orig_ty: Type, 7841 do_coerce: bool, 7842 ) CompileError!Air.Inst.Ref { 7843 const pt = sema.pt; 7844 const zcu = pt.zcu; 7845 7846 const uncoerced_result = res: { 7847 if (orig_ty.toIntern() == .generic_poison_type) { 7848 // Treat this as a normal enum literal. 7849 break :res Air.internedToRef(try pt.intern(.{ .enum_literal = name })); 7850 } 7851 7852 var ty = orig_ty; 7853 while (true) switch (ty.zigTypeTag(zcu)) { 7854 .error_union => ty = ty.errorUnionPayload(zcu), 7855 .optional => ty = ty.optionalChild(zcu), 7856 .pointer => ty = if (ty.isSinglePointer(zcu)) ty.childType(zcu) else break, 7857 .enum_literal, .error_set => { 7858 // Treat this as a normal enum literal. 7859 break :res Air.internedToRef(try pt.intern(.{ .enum_literal = name })); 7860 }, 7861 else => break, 7862 }; 7863 7864 break :res try sema.fieldVal(block, src, Air.internedToRef(ty.toIntern()), name, src); 7865 }; 7866 7867 // Decl literals cannot lookup runtime `var`s. 7868 if (!try sema.isComptimeKnown(uncoerced_result)) { 7869 return sema.fail(block, src, "decl literal must be comptime-known", .{}); 7870 } 7871 7872 if (do_coerce) { 7873 return sema.coerce(block, orig_ty, uncoerced_result, src); 7874 } else { 7875 return uncoerced_result; 7876 } 7877 } 7878 7879 fn zirIntFromEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 7880 const pt = sema.pt; 7881 const zcu = pt.zcu; 7882 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].un_node; 7883 const src = block.nodeOffset(inst_data.src_node); 7884 const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); 7885 const operand = sema.resolveInst(inst_data.operand); 7886 const operand_ty = sema.typeOf(operand); 7887 7888 const enum_tag: Air.Inst.Ref = switch (operand_ty.zigTypeTag(zcu)) { 7889 .@"enum" => operand, 7890 .@"union" => blk: { 7891 if (operand_ty.unionTagType(zcu) == null) { 7892 return sema.fail( 7893 block, 7894 operand_src, 7895 "untagged union '{f}' cannot be converted to integer", 7896 .{operand_ty.fmt(pt)}, 7897 ); 7898 } 7899 7900 break :blk try sema.unionToTag(block, operand); 7901 }, 7902 else => { 7903 return sema.fail(block, operand_src, "expected enum or tagged union, found '{f}'", .{ 7904 operand_ty.fmt(pt), 7905 }); 7906 }, 7907 }; 7908 const enum_tag_ty = sema.typeOf(enum_tag); 7909 const int_tag_ty = enum_tag_ty.backingIntType(zcu); 7910 assert(int_tag_ty.classify(zcu) != .no_possible_value); 7911 7912 if (sema.resolveValue(enum_tag)) |enum_tag_val| { 7913 if (enum_tag_val.isUndef(zcu)) return pt.undefRef(int_tag_ty); 7914 return .fromValue(enum_tag_val.backingInt(zcu)); 7915 } 7916 7917 try sema.requireRuntimeBlock(block, src, operand_src); 7918 return block.addTyOp(.bit_cast, int_tag_ty, enum_tag); 7919 } 7920 7921 fn zirEnumFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 7922 const pt = sema.pt; 7923 const zcu = pt.zcu; 7924 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 7925 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; 7926 const src = block.nodeOffset(inst_data.src_node); 7927 const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); 7928 const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@enumFromInt"); 7929 const operand = sema.resolveInst(extra.rhs); 7930 const operand_ty = sema.typeOf(operand); 7931 7932 if (dest_ty.zigTypeTag(zcu) != .@"enum") { 7933 return sema.fail(block, src, "expected enum, found '{f}'", .{dest_ty.fmt(pt)}); 7934 } 7935 try sema.ensureLayoutResolved(dest_ty, src, .init); 7936 _ = try sema.checkIntType(block, operand_src, operand_ty); 7937 7938 if (sema.resolveValue(operand)) |int_val| { 7939 if (dest_ty.isNonexhaustiveEnum(zcu)) { 7940 const int_tag_ty = dest_ty.backingIntType(zcu); 7941 if (int_val.intFitsInType(int_tag_ty, null, zcu)) { 7942 return Air.internedToRef((try pt.getCoerced(int_val, dest_ty)).toIntern()); 7943 } 7944 return sema.fail(block, src, "int value '{f}' out of range of non-exhaustive enum '{f}'", .{ 7945 int_val.fmtValueSema(pt, sema), dest_ty.fmt(pt), 7946 }); 7947 } 7948 if (int_val.isUndef(zcu)) { 7949 return sema.failWithUseOfUndef(block, operand_src, null); 7950 } 7951 if (!(try sema.enumHasInt(dest_ty, int_val))) { 7952 return sema.fail(block, src, "enum '{f}' has no tag with value '{f}'", .{ 7953 dest_ty.fmt(pt), int_val.fmtValueSema(pt, sema), 7954 }); 7955 } 7956 return Air.internedToRef((try pt.getCoerced(int_val, dest_ty)).toIntern()); 7957 } 7958 7959 if (try dest_ty.onePossibleValue(pt)) |opv| { 7960 if (block.wantSafety()) { 7961 // The operand is runtime-known but the result is comptime-known. In 7962 // this case we still need a safety check. 7963 const expect_int = try pt.getCoerced(opv.backingInt(zcu), operand_ty); 7964 const ok = try block.addBinOp(.cmp_eq, operand, .fromValue(expect_int)); 7965 try sema.addSafetyCheck(block, src, ok, .invalid_enum_value); 7966 } 7967 return .fromValue(opv); 7968 } 7969 7970 try sema.requireRuntimeBlock(block, src, operand_src); 7971 if (block.wantSafety()) { 7972 try sema.preparePanicId(src, .invalid_enum_value); 7973 return block.addTyOp(.int_cast_safe, dest_ty, operand); 7974 } 7975 return block.addTyOp(.int_cast, dest_ty, operand); 7976 } 7977 7978 /// Pointer in, pointer out. 7979 fn zirOptionalPayloadPtr( 7980 sema: *Sema, 7981 block: *Block, 7982 inst: Zir.Inst.Index, 7983 safety_check: bool, 7984 ) CompileError!Air.Inst.Ref { 7985 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].un_node; 7986 const optional_ptr = sema.resolveInst(inst_data.operand); 7987 const src = block.nodeOffset(inst_data.src_node); 7988 7989 const ptr_ty = sema.typeOf(optional_ptr); 7990 assert(ptr_ty.zigTypeTag(sema.pt.zcu) == .pointer); 7991 try sema.ensureLayoutResolved(ptr_ty.childType(sema.pt.zcu), src, .ptr_access); 7992 7993 return sema.analyzeOptionalPayloadPtr(block, src, optional_ptr, safety_check, false); 7994 } 7995 7996 /// Asserts that the layout of the pointer child type is already resolved. 7997 fn analyzeOptionalPayloadPtr( 7998 sema: *Sema, 7999 block: *Block, 8000 src: LazySrcLoc, 8001 optional_ptr: Air.Inst.Ref, 8002 safety_check: bool, 8003 initializing: bool, 8004 ) CompileError!Air.Inst.Ref { 8005 const pt = sema.pt; 8006 const zcu = pt.zcu; 8007 const optional_ptr_ty = sema.typeOf(optional_ptr); 8008 assert(optional_ptr_ty.zigTypeTag(zcu) == .pointer); 8009 8010 const opt_type = optional_ptr_ty.childType(zcu); 8011 opt_type.assertHasLayout(zcu); 8012 if (opt_type.zigTypeTag(zcu) != .optional) { 8013 return sema.failWithExpectedOptionalType(block, src, opt_type); 8014 } 8015 8016 const child_type = opt_type.optionalChild(zcu); 8017 const child_pointer = try pt.ptrType(info: { 8018 var new = optional_ptr_ty.ptrInfo(zcu); 8019 new.child = child_type.toIntern(); 8020 break :info new; 8021 }); 8022 8023 if (try sema.resolveDefinedValue(block, src, optional_ptr)) |ptr_val| { 8024 if (initializing) { 8025 if (sema.isComptimeMutablePtr(ptr_val)) { 8026 // Set the optional to non-null at comptime. 8027 // If the payload is OPV, we must use that value instead of undef. 8028 const payload_val = try child_type.onePossibleValue(pt) orelse try pt.undefValue(child_type); 8029 const opt_val = try pt.intern(.{ .opt = .{ 8030 .ty = opt_type.toIntern(), 8031 .val = payload_val.toIntern(), 8032 } }); 8033 try sema.storePtrVal(block, src, ptr_val, Value.fromInterned(opt_val), opt_type); 8034 } else { 8035 // Emit runtime instructions to set the optional non-null bit. 8036 const opt_payload_ptr = try block.addTyOp(.optional_payload_ptr_set, child_pointer, optional_ptr); 8037 try sema.checkKnownAllocPtr(block, optional_ptr, opt_payload_ptr); 8038 } 8039 return Air.internedToRef((try ptr_val.ptrOptPayload(pt)).toIntern()); 8040 } 8041 if (try sema.pointerDeref(block, src, ptr_val, optional_ptr_ty)) |val| { 8042 if (val.isNull(zcu)) { 8043 return sema.fail(block, src, "unable to unwrap null", .{}); 8044 } 8045 return Air.internedToRef((try ptr_val.ptrOptPayload(pt)).toIntern()); 8046 } 8047 } 8048 8049 try sema.requireRuntimeBlock(block, src, null); 8050 if (safety_check and block.wantSafety()) { 8051 const is_non_null = try block.addUnOp(.is_non_null_ptr, optional_ptr); 8052 try sema.addSafetyCheck(block, src, is_non_null, .unwrap_null); 8053 } 8054 8055 if (initializing) { 8056 const opt_payload_ptr = try block.addTyOp(.optional_payload_ptr_set, child_pointer, optional_ptr); 8057 try sema.checkKnownAllocPtr(block, optional_ptr, opt_payload_ptr); 8058 return opt_payload_ptr; 8059 } else { 8060 return block.addTyOp(.optional_payload_ptr, child_pointer, optional_ptr); 8061 } 8062 } 8063 8064 /// Value in, value out. 8065 fn zirOptionalPayload( 8066 sema: *Sema, 8067 block: *Block, 8068 inst: Zir.Inst.Index, 8069 safety_check: bool, 8070 ) CompileError!Air.Inst.Ref { 8071 const pt = sema.pt; 8072 const zcu = pt.zcu; 8073 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].un_node; 8074 const src = block.nodeOffset(inst_data.src_node); 8075 const operand = sema.resolveInst(inst_data.operand); 8076 const operand_ty = sema.typeOf(operand); 8077 const result_ty = switch (operand_ty.zigTypeTag(zcu)) { 8078 .optional => operand_ty.optionalChild(zcu), 8079 // TODO: https://github.com/ziglang/zig/issues/6597 will eliminate this branch so that we only need to handle optionals. 8080 .pointer => switch (operand_ty.ptrSize(zcu)) { 8081 .c => operand_ty, // if `ptr` is a `[*c]T`, then `ptr.?` is also a `[*c]T` 8082 .one, .many, .slice => return sema.failWithExpectedOptionalType(block, src, operand_ty), 8083 }, 8084 else => return sema.failWithExpectedOptionalType(block, src, operand_ty), 8085 }; 8086 8087 ct: { 8088 if (try sema.resolveDefinedValue(block, src, operand)) |val| { 8089 if (val.optionalValue(zcu)) |payload| return .fromValue(payload); // comptime-known payload 8090 } else if (try sema.resolveIsNullFromType(block, src, operand_ty)) |is_null| { 8091 if (!is_null) break :ct; // fully runtime-known 8092 } else { 8093 break :ct; // fully runtime-known 8094 } 8095 // Comptime-known to be `null`. 8096 if (block.isComptime()) return sema.fail(block, src, "unable to unwrap null", .{}); 8097 if (safety_check and block.wantSafety()) { 8098 try sema.safetyPanic(block, src, .unwrap_null); 8099 } else { 8100 _ = try block.addNoOp(.unreach); 8101 } 8102 return .unreachable_value; 8103 } 8104 8105 if (safety_check and block.wantSafety()) { 8106 const is_non_null = try block.addUnOp(.is_non_null, operand); 8107 try sema.addSafetyCheck(block, src, is_non_null, .unwrap_null); 8108 } 8109 8110 // If the payload is OPV, we need the safety check but have a comptime-known result. 8111 if (try result_ty.onePossibleValue(pt)) |opv| return .fromValue(opv); 8112 8113 return block.addTyOp(.optional_payload, result_ty, operand); 8114 } 8115 8116 /// Value in, value out 8117 fn zirErrUnionPayload( 8118 sema: *Sema, 8119 block: *Block, 8120 inst: Zir.Inst.Index, 8121 ) CompileError!Air.Inst.Ref { 8122 const pt = sema.pt; 8123 const zcu = pt.zcu; 8124 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].un_node; 8125 const src = block.nodeOffset(inst_data.src_node); 8126 const operand = sema.resolveInst(inst_data.operand); 8127 const operand_src = src; 8128 const err_union_ty = sema.typeOf(operand); 8129 if (err_union_ty.zigTypeTag(zcu) != .error_union) { 8130 return sema.fail(block, operand_src, "expected error union type, found '{f}'", .{ 8131 err_union_ty.fmt(pt), 8132 }); 8133 } 8134 return sema.analyzeErrUnionPayload(block, src, err_union_ty, operand, operand_src, false); 8135 } 8136 8137 fn analyzeErrUnionPayload( 8138 sema: *Sema, 8139 block: *Block, 8140 src: LazySrcLoc, 8141 err_union_ty: Type, 8142 operand: Air.Inst.Ref, 8143 operand_src: LazySrcLoc, 8144 safety_check: bool, 8145 ) CompileError!Air.Inst.Ref { 8146 const pt = sema.pt; 8147 const zcu = pt.zcu; 8148 const payload_ty = err_union_ty.errorUnionPayload(zcu); 8149 if (try sema.resolveDefinedValue(block, operand_src, operand)) |val| { 8150 if (val.getErrorName(zcu).unwrap()) |name| { 8151 return sema.failWithComptimeErrorRetTrace(block, src, name); 8152 } 8153 return Air.internedToRef(zcu.intern_pool.indexToKey(val.toIntern()).error_union.val.payload); 8154 } 8155 8156 try sema.requireRuntimeBlock(block, src, null); 8157 8158 // If the error set has no fields then no safety check is needed. 8159 if (safety_check and block.wantSafety() and 8160 !err_union_ty.errorUnionSet(zcu).errorSetIsEmpty(zcu)) 8161 { 8162 try sema.addSafetyCheckUnwrapError(block, src, operand, .unwrap_errunion_err, .is_non_err); 8163 } 8164 8165 if (try payload_ty.onePossibleValue(pt)) |payload_opv| { 8166 return .fromValue(payload_opv); 8167 } 8168 8169 return block.addTyOp(.unwrap_errunion_payload, payload_ty, operand); 8170 } 8171 8172 /// Pointer in, pointer out. 8173 fn zirErrUnionPayloadPtr( 8174 sema: *Sema, 8175 block: *Block, 8176 inst: Zir.Inst.Index, 8177 ) CompileError!Air.Inst.Ref { 8178 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].un_node; 8179 const operand = sema.resolveInst(inst_data.operand); 8180 const src = block.nodeOffset(inst_data.src_node); 8181 8182 const ptr_ty = sema.typeOf(operand); 8183 assert(ptr_ty.zigTypeTag(sema.pt.zcu) == .pointer); 8184 try sema.ensureLayoutResolved(ptr_ty.childType(sema.pt.zcu), src, .ptr_access); 8185 8186 return sema.analyzeErrUnionPayloadPtr(block, src, operand, false, false); 8187 } 8188 8189 /// Asserts that the layout of the pointer child type is already resolved. 8190 fn analyzeErrUnionPayloadPtr( 8191 sema: *Sema, 8192 block: *Block, 8193 src: LazySrcLoc, 8194 operand: Air.Inst.Ref, 8195 safety_check: bool, 8196 initializing: bool, 8197 ) CompileError!Air.Inst.Ref { 8198 const pt = sema.pt; 8199 const zcu = pt.zcu; 8200 const operand_ty = sema.typeOf(operand); 8201 assert(operand_ty.zigTypeTag(zcu) == .pointer); 8202 8203 if (operand_ty.childType(zcu).zigTypeTag(zcu) != .error_union) { 8204 return sema.fail(block, src, "expected error union type, found '{f}'", .{ 8205 operand_ty.childType(zcu).fmt(pt), 8206 }); 8207 } 8208 8209 const err_union_ty = operand_ty.childType(zcu); 8210 err_union_ty.assertHasLayout(zcu); 8211 const payload_ty = err_union_ty.errorUnionPayload(zcu); 8212 const operand_pointer_ty = try pt.ptrType(.{ 8213 .child = payload_ty.toIntern(), 8214 .flags = .{ 8215 .is_const = operand_ty.isConstPtr(zcu), 8216 .address_space = operand_ty.ptrAddressSpace(zcu), 8217 }, 8218 }); 8219 8220 if (try sema.resolveDefinedValue(block, src, operand)) |ptr_val| { 8221 if (initializing) { 8222 if (sema.isComptimeMutablePtr(ptr_val)) { 8223 // Set the error union to non-error at comptime. 8224 // If the payload is OPV, we must use that value instead of undef. 8225 const payload_val = try payload_ty.onePossibleValue(pt) orelse try pt.undefValue(payload_ty); 8226 const eu_val = try pt.intern(.{ .error_union = .{ 8227 .ty = err_union_ty.toIntern(), 8228 .val = .{ .payload = payload_val.toIntern() }, 8229 } }); 8230 try sema.storePtrVal(block, src, ptr_val, Value.fromInterned(eu_val), err_union_ty); 8231 } else { 8232 // Emit runtime instructions to set the error union error code. 8233 try sema.requireRuntimeBlock(block, src, null); 8234 const eu_payload_ptr = try block.addTyOp(.errunion_payload_ptr_set, operand_pointer_ty, operand); 8235 try sema.checkKnownAllocPtr(block, operand, eu_payload_ptr); 8236 } 8237 return Air.internedToRef((try ptr_val.ptrEuPayload(pt)).toIntern()); 8238 } 8239 if (try sema.pointerDeref(block, src, ptr_val, operand_ty)) |val| { 8240 if (val.getErrorName(zcu).unwrap()) |name| { 8241 return sema.failWithComptimeErrorRetTrace(block, src, name); 8242 } 8243 return Air.internedToRef((try ptr_val.ptrEuPayload(pt)).toIntern()); 8244 } 8245 } 8246 8247 try sema.requireRuntimeBlock(block, src, null); 8248 8249 // If the error set has no fields then no safety check is needed. 8250 if (safety_check and block.wantSafety() and 8251 !err_union_ty.errorUnionSet(zcu).errorSetIsEmpty(zcu)) 8252 { 8253 try sema.addSafetyCheckUnwrapError(block, src, operand, .unwrap_errunion_err_ptr, .is_non_err_ptr); 8254 } 8255 8256 if (initializing) { 8257 const eu_payload_ptr = try block.addTyOp(.errunion_payload_ptr_set, operand_pointer_ty, operand); 8258 try sema.checkKnownAllocPtr(block, operand, eu_payload_ptr); 8259 return eu_payload_ptr; 8260 } else { 8261 return block.addTyOp(.unwrap_errunion_payload_ptr, operand_pointer_ty, operand); 8262 } 8263 } 8264 8265 /// Value in, value out 8266 fn zirErrUnionCode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 8267 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].un_node; 8268 const src = block.nodeOffset(inst_data.src_node); 8269 const operand = sema.resolveInst(inst_data.operand); 8270 return sema.analyzeErrUnionCode(block, src, operand); 8271 } 8272 8273 /// If `operand` is comptime-known, asserts that it is an error value rather than a payload value. 8274 fn analyzeErrUnionCode(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Inst.Ref) CompileError!Air.Inst.Ref { 8275 const pt = sema.pt; 8276 const zcu = pt.zcu; 8277 const operand_ty = sema.typeOf(operand); 8278 if (operand_ty.zigTypeTag(zcu) != .error_union) { 8279 return sema.fail(block, src, "expected error union type, found '{f}'", .{ 8280 operand_ty.fmt(pt), 8281 }); 8282 } 8283 8284 const result_ty = operand_ty.errorUnionSet(zcu); 8285 8286 if (try sema.resolveDefinedValue(block, src, operand)) |val| { 8287 if (val.getErrorName(zcu) == .none) return .unreachable_value; 8288 return Air.internedToRef((try pt.intern(.{ .err = .{ 8289 .ty = result_ty.toIntern(), 8290 .name = zcu.intern_pool.indexToKey(val.toIntern()).error_union.val.err_name, 8291 } }))); 8292 } 8293 8294 try sema.requireRuntimeBlock(block, src, null); 8295 return block.addTyOp(.unwrap_errunion_err, result_ty, operand); 8296 } 8297 8298 /// Pointer in, value out 8299 fn zirErrUnionCodePtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 8300 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].un_node; 8301 const src = block.nodeOffset(inst_data.src_node); 8302 const operand = sema.resolveInst(inst_data.operand); 8303 return sema.analyzeErrUnionCodePtr(block, src, operand); 8304 } 8305 8306 fn analyzeErrUnionCodePtr(sema: *Sema, block: *Block, src: LazySrcLoc, operand: Air.Inst.Ref) CompileError!Air.Inst.Ref { 8307 const pt = sema.pt; 8308 const zcu = pt.zcu; 8309 const operand_ty = sema.typeOf(operand); 8310 assert(operand_ty.zigTypeTag(zcu) == .pointer); 8311 8312 if (operand_ty.childType(zcu).zigTypeTag(zcu) != .error_union) { 8313 return sema.fail(block, src, "expected error union type, found '{f}'", .{ 8314 operand_ty.childType(zcu).fmt(pt), 8315 }); 8316 } 8317 8318 const result_ty = operand_ty.childType(zcu).errorUnionSet(zcu); 8319 8320 if (try sema.resolveDefinedValue(block, src, operand)) |pointer_val| { 8321 if (try sema.pointerDeref(block, src, pointer_val, operand_ty)) |val| { 8322 if (val.getErrorName(zcu) == .none) return .unreachable_value; 8323 return Air.internedToRef((try pt.intern(.{ .err = .{ 8324 .ty = result_ty.toIntern(), 8325 .name = zcu.intern_pool.indexToKey(val.toIntern()).error_union.val.err_name, 8326 } }))); 8327 } 8328 } 8329 8330 try sema.requireRuntimeBlock(block, src, null); 8331 return block.addTyOp(.unwrap_errunion_err_ptr, result_ty, operand); 8332 } 8333 8334 fn zirFunc( 8335 sema: *Sema, 8336 block: *Block, 8337 inst: Zir.Inst.Index, 8338 inferred_error_set: bool, 8339 ) CompileError!Air.Inst.Ref { 8340 const pt = sema.pt; 8341 const zcu = pt.zcu; 8342 const comp = zcu.comp; 8343 const gpa = comp.gpa; 8344 const io = comp.io; 8345 const ip = &zcu.intern_pool; 8346 8347 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 8348 const extra = sema.code.extraData(Zir.Inst.Func, inst_data.payload_index); 8349 const target = zcu.getTarget(); 8350 const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = inst_data.src_node }); 8351 const src = block.nodeOffset(inst_data.src_node); 8352 8353 var extra_index = extra.end; 8354 8355 const ret_ty: Type = if (extra.data.ret_ty.is_generic) 8356 .generic_poison 8357 else switch (extra.data.ret_ty.body_len) { 8358 0 => .void, 8359 1 => blk: { 8360 const ret_ty_ref: Zir.Inst.Ref = @fromBackingInt(@intCast(sema.code.extra[extra_index])); 8361 extra_index += 1; 8362 break :blk try sema.resolveType(block, ret_ty_src, ret_ty_ref); 8363 }, 8364 else => blk: { 8365 const ret_ty_body = sema.code.bodySlice(extra_index, extra.data.ret_ty.body_len); 8366 extra_index += ret_ty_body.len; 8367 8368 const ret_ty_val = try sema.resolveGenericBody(block, ret_ty_src, ret_ty_body, inst, .type, .{ .simple = .fn_ret_ty }); 8369 break :blk ret_ty_val.toType(); 8370 }, 8371 }; 8372 8373 var src_locs: Zir.Inst.Func.SrcLocs = undefined; 8374 const has_body = extra.data.body_len != 0; 8375 if (has_body) { 8376 extra_index += extra.data.body_len; 8377 src_locs = sema.code.extraData(Zir.Inst.Func.SrcLocs, extra_index).data; 8378 } 8379 8380 // If this instruction has a body, then it's a function declaration, and we decide 8381 // the callconv based on whether it is exported. Otherwise, the callconv defaults 8382 // to `.auto`. 8383 const cc: std.lang.CallingConvention = if (has_body) cc: { 8384 const func_decl_nav = sema.owner.unwrap().nav_val; 8385 const fn_is_exported = exported: { 8386 const decl_ti = ip.getNav(func_decl_nav).analysis.?.zir_index; 8387 const decl_inst = decl_ti.resolve(ip) orelse { 8388 return sema.failTransitive(.{ .lost_tracking = decl_ti }); 8389 }; 8390 const zir_decl = sema.code.getDeclaration(decl_inst); 8391 break :exported zir_decl.linkage == .@"export"; 8392 }; 8393 if (fn_is_exported) { 8394 break :cc target.cCallingConvention() orelse { 8395 // This target has no default C calling convention. We sometimes trigger a similar 8396 // error by trying to evaluate `std.lang.CallingConvention.c`, so for consistency, 8397 // let's eval that now and just get the transitive error. (It's guaranteed to error 8398 // because it does the exact `cCallingConvention` call we just did.) 8399 const cc_type = try sema.getStdLangType(src, .CallingConvention); 8400 _ = try sema.namespaceLookupVal( 8401 block, 8402 LazySrcLoc.unneeded, 8403 cc_type.getNamespaceIndex(zcu), 8404 try ip.getOrPutString(gpa, io, pt.tid, "c", .no_embedded_nulls), 8405 ); 8406 // The above should have errored. 8407 @panic("std.lang is corrupt"); 8408 }; 8409 } else { 8410 break :cc .auto; 8411 } 8412 } else .auto; 8413 8414 return sema.funcCommon( 8415 block, 8416 inst_data.src_node, 8417 inst, 8418 cc, 8419 ret_ty, 8420 false, 8421 inferred_error_set, 8422 has_body, 8423 src_locs, 8424 0, 8425 false, 8426 ); 8427 } 8428 8429 fn resolveGenericBody( 8430 sema: *Sema, 8431 block: *Block, 8432 src: LazySrcLoc, 8433 body: []const Zir.Inst.Index, 8434 func_inst: Zir.Inst.Index, 8435 dest_ty: Type, 8436 reason: ComptimeReason, 8437 ) !Value { 8438 assert(body.len != 0); 8439 8440 // Make sure any nested param instructions don't clobber our work. 8441 const prev_params = block.params; 8442 block.params = .{}; 8443 defer { 8444 block.params = prev_params; 8445 } 8446 8447 const uncasted = try sema.resolveInlineBody(block, body, func_inst); 8448 const result = try sema.coerce(block, dest_ty, uncasted, src); 8449 return sema.resolveConstDefinedValue(block, src, result, reason); 8450 } 8451 8452 /// Given a library name, examines if the library name should end up in 8453 /// `link.File.Options.windows_libs` table (for example, libc is always 8454 /// specified via dedicated flag `link_libc` instead), 8455 /// and puts it there if it doesn't exist. 8456 /// It also dupes the library name which can then be saved as part of the 8457 /// respective `Decl` (either `ExternFn` or `Var`). 8458 /// The liveness of the duped library name is tied to liveness of `Zcu`. 8459 /// To deallocate, call `deinit` on the respective `Decl` (`ExternFn` or `Var`). 8460 pub fn handleExternLibName( 8461 sema: *Sema, 8462 block: *Block, 8463 src_loc: LazySrcLoc, 8464 lib_name: []const u8, 8465 ) CompileError!void { 8466 blk: { 8467 const pt = sema.pt; 8468 const zcu = pt.zcu; 8469 const comp = zcu.comp; 8470 const target = zcu.getTarget(); 8471 log.debug("extern fn symbol expected in lib '{s}'", .{lib_name}); 8472 if (std.zig.target.isLibCLibName(target, lib_name)) { 8473 if (!comp.config.link_libc) { 8474 return sema.fail( 8475 block, 8476 src_loc, 8477 "dependency on libc must be explicitly specified in the build command", 8478 .{}, 8479 ); 8480 } 8481 break :blk; 8482 } 8483 if (std.zig.target.isLibCxxLibName(target, lib_name)) { 8484 if (!comp.config.link_libcpp) return sema.fail( 8485 block, 8486 src_loc, 8487 "dependency on libc++ must be explicitly specified in the build command", 8488 .{}, 8489 ); 8490 break :blk; 8491 } 8492 if (mem.eql(u8, lib_name, "unwind")) { 8493 if (!comp.config.link_libunwind) return sema.fail( 8494 block, 8495 src_loc, 8496 "dependency on libunwind must be explicitly specified in the build command", 8497 .{}, 8498 ); 8499 break :blk; 8500 } 8501 if (!target_util.canDynamicLink(target)) { 8502 return sema.fail( 8503 block, 8504 src_loc, 8505 "dependency on dynamic library '{s}' cannot be satisfied because target does not support dynamic linking", 8506 .{lib_name}, 8507 ); 8508 } 8509 if (!block.ownerModule().pic and target_util.requiresPicForDynamicLink(target)) { 8510 return sema.fail( 8511 block, 8512 src_loc, 8513 "dependency on dynamic library '{s}' requires enabling Position Independent Code; fixed by '-l{s}' or '-fPIC'", 8514 .{ lib_name, lib_name }, 8515 ); 8516 } 8517 comp.addLinkLib(lib_name) catch |err| { 8518 return sema.fail(block, src_loc, "unable to add link lib '{s}': {s}", .{ 8519 lib_name, @errorName(err), 8520 }); 8521 }; 8522 } 8523 } 8524 8525 /// These are calling conventions that are confirmed to work with variadic functions. 8526 /// Any calling conventions not included here are either not yet verified to work with variadic 8527 /// functions or there are no more other calling conventions that support variadic functions. 8528 const calling_conventions_supporting_var_args = [_]std.lang.CallingConvention.Tag{ 8529 .x86_16_cdecl, 8530 .x86_64_sysv, 8531 .x86_64_x32, 8532 .x86_64_win, 8533 .x86_sysv, 8534 .x86_win, 8535 .x86_mingw, 8536 .aarch64_aapcs, 8537 .aarch64_aapcs_darwin, 8538 .aarch64_aapcs_win, 8539 .aarch64_vfabi, 8540 .aarch64_vfabi_sve, 8541 .alpha_osf, 8542 .arm_aapcs, 8543 .arm_aapcs_vfp, 8544 .microblaze_std, 8545 .mips64_n64, 8546 .mips64_n32, 8547 .mips_o32, 8548 .riscv64_lp64, 8549 .riscv64_lp64_v, 8550 .riscv32_ilp32, 8551 .riscv32_ilp32_v, 8552 .sparc64_sysv, 8553 .sparc_sysv, 8554 .powerpc64_elf, 8555 .powerpc64_elf_altivec, 8556 .powerpc64_elf_v2, 8557 .powerpc_sysv, 8558 .powerpc_sysv_altivec, 8559 .powerpc_aix, 8560 .powerpc_aix_altivec, 8561 .wasm_mvp, 8562 .arc_sysv, 8563 .avr_gnu, 8564 .bpf_std, 8565 .csky_sysv, 8566 .hexagon_sysv, 8567 .hexagon_sysv_hvx, 8568 .hppa_elf, 8569 .hppa64_elf, 8570 .kvx_lp64, 8571 .kvx_ilp32, 8572 .lanai_sysv, 8573 .loongarch64_lp64, 8574 .loongarch32_ilp32, 8575 .m68k_sysv, 8576 .m68k_gnu, 8577 .m68k_rtd, 8578 .m88k_sysv, 8579 .msp430_eabi, 8580 .or1k_sysv, 8581 .s390x_sysv, 8582 .s390x_sysv_vx, 8583 .sh_gnu, 8584 .sh_renesas, 8585 .ve_sysv, 8586 .xcore_xs1, 8587 .xcore_xs2, 8588 .xtensa_call0, 8589 .xtensa_windowed, 8590 }; 8591 fn callConvSupportsVarArgs(cc: std.lang.CallingConvention.Tag) bool { 8592 return for (calling_conventions_supporting_var_args) |supported_cc| { 8593 if (cc == supported_cc) return true; 8594 } else false; 8595 } 8596 fn checkCallConvSupportsVarArgs(sema: *Sema, block: *Block, src: LazySrcLoc, cc: std.lang.CallingConvention.Tag) CompileError!void { 8597 const CallingConventionsSupportingVarArgsList = struct { 8598 arch: std.Target.Cpu.Arch, 8599 pub fn format(ctx: @This(), w: *std.Io.Writer) std.Io.Writer.Error!void { 8600 var first = true; 8601 for (calling_conventions_supporting_var_args) |cc_inner| { 8602 for (std.Target.Cpu.Arch.fromCallingConvention(cc_inner)) |supported_arch| { 8603 if (supported_arch == ctx.arch) break; 8604 } else continue; // callconv not supported by this arch 8605 if (!first) { 8606 try w.writeAll(", "); 8607 } 8608 first = false; 8609 try w.print("'{s}'", .{@tagName(cc_inner)}); 8610 } 8611 } 8612 }; 8613 8614 if (!callConvSupportsVarArgs(cc)) { 8615 return sema.failWithOwnedErrorMsg(block, msg: { 8616 const msg = try sema.errMsg(src, "variadic function does not support '{s}' calling convention", .{@tagName(cc)}); 8617 errdefer msg.destroy(sema.gpa); 8618 const target = sema.pt.zcu.getTarget(); 8619 try sema.errNote(src, msg, "supported calling conventions: {f}", .{CallingConventionsSupportingVarArgsList{ .arch = target.cpu.arch }}); 8620 break :msg msg; 8621 }); 8622 } 8623 } 8624 8625 fn checkParamType( 8626 sema: *Sema, 8627 block: *Block, 8628 param_idx: u32, 8629 param_ty: Type, 8630 param_is_comptime: bool, 8631 param_is_noalias: bool, 8632 param_src: LazySrcLoc, 8633 cc: std.lang.CallingConvention, 8634 ) CompileError!void { 8635 const pt = sema.pt; 8636 const zcu = pt.zcu; 8637 const target = zcu.getTarget(); 8638 8639 if (!param_ty.isValidParamType(zcu)) { 8640 const opaque_str = if (param_ty.zigTypeTag(zcu) == .@"opaque") "opaque " else ""; 8641 return sema.fail(block, param_src, "parameter of {s}type '{f}' not allowed", .{ 8642 opaque_str, param_ty.fmt(pt), 8643 }); 8644 } 8645 if (!target_util.fnCallConvAllowsZigTypes(cc)) { 8646 if (param_is_comptime) { 8647 return sema.fail(block, param_src, "comptime parameters not allowed in function with calling convention '{t}'", .{cc}); 8648 } 8649 if (param_ty.isGenericPoison()) { 8650 return sema.fail(block, param_src, "generic parameters not allowed in function with calling convention '{t}'", .{cc}); 8651 } 8652 // The `validateExtern` check happens later, in `validateResolvedFuncType`. 8653 } 8654 switch (cc) { 8655 .x86_64_interrupt, .x86_interrupt => { 8656 const err_code_size = target.ptrBitWidth(); 8657 switch (param_idx) { 8658 0 => if (param_ty.zigTypeTag(zcu) != .pointer) return sema.fail(block, param_src, "first parameter of function with '{t}' calling convention must be a pointer type", .{cc}), 8659 1 => if (param_ty.bitSize(zcu) != err_code_size) return sema.fail(block, param_src, "second parameter of function with '{t}' calling convention must be a {d}-bit integer", .{ cc, err_code_size }), 8660 else => return sema.fail(block, param_src, "'{t}' calling convention supports up to 2 parameters, found {d}", .{ cc, param_idx + 1 }), 8661 } 8662 }, 8663 .arc_interrupt, 8664 .arm_interrupt, 8665 .microblaze_interrupt, 8666 .mips64_interrupt, 8667 .mips_interrupt, 8668 .riscv64_interrupt, 8669 .riscv32_interrupt, 8670 .sh_interrupt, 8671 .avr_interrupt, 8672 .csky_interrupt, 8673 .m68k_interrupt, 8674 .msp430_interrupt, 8675 .avr_signal, 8676 => return sema.fail(block, param_src, "parameters are not allowed with '{t}' calling convention", .{cc}), 8677 else => {}, 8678 } 8679 if (param_is_noalias and !param_ty.isGenericPoison() and !param_ty.isPtrAtRuntime(zcu) and !param_ty.isSliceAtRuntime(zcu)) { 8680 return sema.fail(block, param_src, "non-pointer parameter declared noalias", .{}); 8681 } 8682 switch (target.os.tag) { 8683 .vulkan, .opengl => if (cc != .@"inline" and param_ty.isPtrAtRuntime(zcu)) { 8684 switch (param_ty.ptrAddressSpace(zcu)) { 8685 .input, .output => |as| return sema.failWithOwnedErrorMsg(block, msg: { 8686 const msg = try sema.errMsg(param_src, "function parameter cannot be a pointer in '{s}' address space", .{@tagName(as)}); 8687 errdefer msg.destroy(sema.gpa); 8688 try sema.errNote(param_src, msg, "mark the function as 'inline' so the parameter is substituted at call sites", .{}); 8689 break :msg msg; 8690 }), 8691 else => {}, 8692 } 8693 }, 8694 else => {}, 8695 } 8696 } 8697 8698 fn checkReturnTypeAndCallConv( 8699 sema: *Sema, 8700 block: *Block, 8701 bare_ret_ty: Type, 8702 ret_ty_src: LazySrcLoc, 8703 @"callconv": std.lang.CallingConvention, 8704 callconv_src: LazySrcLoc, 8705 /// non-`null` only if the function is varargs. 8706 opt_varargs_src: ?LazySrcLoc, 8707 inferred_error_set: bool, 8708 is_noinline: bool, 8709 ) CompileError!void { 8710 const pt = sema.pt; 8711 const zcu = pt.zcu; 8712 const target = zcu.getTarget(); 8713 if (opt_varargs_src) |varargs_src| { 8714 try sema.checkCallConvSupportsVarArgs(block, varargs_src, @"callconv"); 8715 } 8716 if (inferred_error_set and !bare_ret_ty.isGenericPoison()) { 8717 try sema.validateErrorUnionPayloadType(block, bare_ret_ty, ret_ty_src); 8718 } 8719 const ies_ret_ty_prefix: []const u8 = if (inferred_error_set) "!" else ""; 8720 if (!bare_ret_ty.isValidReturnType(zcu)) { 8721 const opaque_str = if (bare_ret_ty.zigTypeTag(zcu) == .@"opaque") "opaque " else ""; 8722 return sema.fail(block, ret_ty_src, "{s}return type '{s}{f}' not allowed", .{ 8723 opaque_str, ies_ret_ty_prefix, bare_ret_ty.fmt(pt), 8724 }); 8725 } 8726 if (!target_util.fnCallConvAllowsZigTypes(@"callconv")) { 8727 if (inferred_error_set) { 8728 return sema.fail(block, ret_ty_src, "return type '!{f}' not allowed in function with calling convention '{t}'", .{ bare_ret_ty.fmt(pt), @"callconv" }); 8729 } 8730 if (bare_ret_ty.isGenericPoison()) { 8731 return sema.fail(block, ret_ty_src, "generic return type not allowed in function with calling convention '{t}'", .{@"callconv"}); 8732 } 8733 // The `validateExtern` check happens later, in `validateResolvedFuncType`. 8734 } 8735 validate_incoming_stack_align: { 8736 const a: u64 = switch (@"callconv") { 8737 inline else => |payload| if (@TypeOf(payload) != void and @hasField(@TypeOf(payload), "incoming_stack_alignment")) 8738 payload.incoming_stack_alignment orelse break :validate_incoming_stack_align 8739 else 8740 break :validate_incoming_stack_align, 8741 }; 8742 if (!std.math.isPowerOfTwo(a)) { 8743 return sema.fail(block, callconv_src, "calling convention incoming stack alignment '{d}' is not a power of two", .{a}); 8744 } 8745 } 8746 switch (@"callconv") { 8747 .x86_64_interrupt, 8748 .x86_interrupt, 8749 .arm_interrupt, 8750 .mips64_interrupt, 8751 .mips_interrupt, 8752 .riscv64_interrupt, 8753 .riscv32_interrupt, 8754 .sh_interrupt, 8755 .arc_interrupt, 8756 .avr_interrupt, 8757 .csky_interrupt, 8758 .m68k_interrupt, 8759 .microblaze_interrupt, 8760 .msp430_interrupt, 8761 .avr_signal, 8762 => { 8763 const ret_ok = !inferred_error_set and switch (bare_ret_ty.toIntern()) { 8764 .void_type, .noreturn_type => true, 8765 else => false, 8766 }; 8767 if (!ret_ok) { 8768 return sema.fail(block, ret_ty_src, "function with calling convention '{t}' must return 'void' or 'noreturn'", .{@"callconv"}); 8769 } 8770 }, 8771 .@"inline" => if (is_noinline) { 8772 return sema.fail(block, callconv_src, "'noinline' function cannot have calling convention 'inline'", .{}); 8773 }, 8774 .spirv_fragment => |fragment| { 8775 if (fragment.pixel_centered_integer and target.os.tag != .opengl) { 8776 return sema.fail(block, callconv_src, "'pixel_centered_integer' is not supported on this target", .{}); 8777 } 8778 }, 8779 .spirv_kernel => |kernel| { 8780 if (kernel.x == 0 or kernel.y == 0 or kernel.z == 0) { 8781 return sema.fail(block, callconv_src, "kernel workgroup dimensions must be at least 1", .{}); 8782 } 8783 }, 8784 .spirv_task => |task| { 8785 if (task.x == 0 or task.y == 0 or task.z == 0) { 8786 return sema.fail(block, callconv_src, "kernel workgroup dimensions must be at least 1", .{}); 8787 } 8788 if (!target.cpu.has(.spirv, .mesh_shading_ext)) { 8789 return sema.fail(block, callconv_src, "calling convention '{t}' requires the 'mesh_shading_ext' feature", .{@"callconv"}); 8790 } 8791 }, 8792 .spirv_mesh => |mesh| { 8793 if (mesh.max_vertices == 0 or mesh.max_primitives == 0) { 8794 return sema.fail(block, callconv_src, "mesh shader 'max_vertices' and 'max_primitives' must be at least 1", .{}); 8795 } 8796 if (mesh.x == 0 or mesh.y == 0 or mesh.z == 0) { 8797 return sema.fail(block, callconv_src, "mesh shader workgroup dimensions must be at least 1", .{}); 8798 } 8799 if (!target.cpu.has(.spirv, .mesh_shading_ext)) { 8800 return sema.fail(block, callconv_src, "calling convention '{t}' requires the 'mesh_shading_ext' feature", .{@"callconv"}); 8801 } 8802 }, 8803 else => {}, 8804 } 8805 switch (zcu.callconvSupported(@"callconv")) { 8806 .ok => {}, 8807 .bad_arch => |allowed_archs| { 8808 const ArchListFormatter = struct { 8809 archs: []const std.Target.Cpu.Arch, 8810 pub fn format(formatter: @This(), w: *std.Io.Writer) std.Io.Writer.Error!void { 8811 for (formatter.archs, 0..) |arch, i| { 8812 if (i != 0) 8813 try w.writeAll(", "); 8814 try w.print("'{s}'", .{@tagName(arch)}); 8815 } 8816 } 8817 }; 8818 return sema.fail(block, callconv_src, "calling convention '{t}' only available on architectures {f}", .{ 8819 @"callconv", ArchListFormatter{ .archs = allowed_archs }, 8820 }); 8821 }, 8822 .bad_backend => |bad_backend| return sema.fail(block, callconv_src, "calling convention '{t}' not supported by compiler backend '{t}'", .{ 8823 @"callconv", bad_backend, 8824 }), 8825 } 8826 } 8827 8828 /// To avoid forcing type layout resolution too quickly, some validation of function types cannot be 8829 /// performed when the type is first constructed, and instead must happen when either (a) a function 8830 /// with that type is declared, or (b) a function with that type is called. That validation is 8831 /// handled here. 8832 /// 8833 /// Asserts that all parameter types and return types have their layout fully resolved. 8834 fn validateResolvedFuncType( 8835 sema: *Sema, 8836 block: *Block, 8837 @"callconv": std.lang.CallingConvention, 8838 param_types: []const InternPool.Index, 8839 ret_ty: Type, 8840 src: LazySrcLoc, 8841 maybe_func_decl_inst: ?InternPool.TrackedInst.Index, 8842 ) SemaError!void { 8843 const pt = sema.pt; 8844 const zcu = pt.zcu; 8845 const gpa = zcu.comp.gpa; 8846 if (!target_util.fnCallConvAllowsZigTypes(@"callconv")) { 8847 // Check that all parameter types are extern-compatible. 8848 for (param_types, 0..) |param_ty_ip, param_index| { 8849 const param_ty: Type = .fromInterned(param_ty_ip); 8850 if (!param_ty.validateExtern(.param_ty, zcu)) { 8851 const param_src: LazySrcLoc = if (maybe_func_decl_inst) |inst| .{ 8852 .base_node_inst = inst, 8853 .offset = .{ .fn_proto_param = .{ 8854 .fn_proto_node_offset = .zero, 8855 .param_index = @intCast(param_index), 8856 } }, 8857 } else src; 8858 return sema.failWithOwnedErrorMsg(block, msg: { 8859 const msg = try sema.errMsg(param_src, "parameter of type '{f}' not allowed in function with calling convention '{t}'", .{ 8860 param_ty.fmt(pt), @"callconv", 8861 }); 8862 errdefer msg.destroy(gpa); 8863 try sema.explainWhyTypeIsNotExtern(msg, param_src, param_ty, .param_ty); 8864 try sema.addDeclaredHereNote(msg, param_ty); 8865 break :msg msg; 8866 }); 8867 } 8868 } 8869 // Check that the return type is extern-compatible. 8870 if (!ret_ty.validateExtern(.ret_ty, zcu)) { 8871 const ret_ty_src: LazySrcLoc = if (maybe_func_decl_inst) |inst| .{ 8872 .base_node_inst = inst, 8873 .offset = .{ .node_offset_fn_type_ret_ty = .zero }, 8874 } else src; 8875 return sema.failWithOwnedErrorMsg(block, msg: { 8876 const msg = try sema.errMsg(ret_ty_src, "return type '{f}' not allowed in function with calling convention '{t}'", .{ 8877 ret_ty.fmt(pt), @"callconv", 8878 }); 8879 errdefer msg.destroy(gpa); 8880 try sema.explainWhyTypeIsNotExtern(msg, ret_ty_src, ret_ty, .ret_ty); 8881 try sema.addDeclaredHereNote(msg, ret_ty); 8882 break :msg msg; 8883 }); 8884 } 8885 } 8886 } 8887 8888 fn callConvIsCallable(cc: std.lang.CallingConvention.Tag) bool { 8889 return switch (cc) { 8890 .naked, 8891 8892 .arc_interrupt, 8893 .arm_interrupt, 8894 .avr_interrupt, 8895 .avr_signal, 8896 .csky_interrupt, 8897 .m68k_interrupt, 8898 .microblaze_interrupt, 8899 .mips_interrupt, 8900 .mips64_interrupt, 8901 .msp430_interrupt, 8902 .riscv32_interrupt, 8903 .riscv64_interrupt, 8904 .sh_interrupt, 8905 .x86_interrupt, 8906 .x86_64_interrupt, 8907 8908 .amdgcn_kernel, 8909 .nvptx_kernel, 8910 .spirv_kernel, 8911 .spirv_fragment, 8912 .spirv_vertex, 8913 .spirv_task, 8914 .spirv_mesh, 8915 => false, 8916 8917 else => true, 8918 }; 8919 } 8920 8921 fn checkMergeAllowed(sema: *Sema, block: *Block, src: LazySrcLoc, peer_ty: Type) !void { 8922 const pt = sema.pt; 8923 const zcu = pt.zcu; 8924 const target = zcu.getTarget(); 8925 8926 if (!peer_ty.isPtrAtRuntime(zcu)) { 8927 return; 8928 } 8929 8930 const as = peer_ty.ptrAddressSpace(zcu); 8931 if (!target_util.shouldBlockPointerOps(target, as)) { 8932 return; 8933 } 8934 8935 return sema.failWithOwnedErrorMsg(block, msg: { 8936 const msg = try sema.errMsg(src, "value with non-mergable pointer type '{f}' depends on runtime control flow", .{peer_ty.fmt(pt)}); 8937 errdefer msg.destroy(sema.gpa); 8938 8939 const runtime_src = block.runtime_cond orelse block.runtime_loop.?; 8940 try sema.errNote(runtime_src, msg, "runtime control flow here", .{}); 8941 8942 const backend = target_util.zigBackend(target, zcu.comp.config.use_llvm); 8943 try sema.errNote(src, msg, "pointers with address space '{s}' cannot be returned from a branch on target '{s}-{s}' by compiler backend '{s}'", .{ 8944 @tagName(as), 8945 @tagName(target.cpu.arch.family()), 8946 @tagName(target.os.tag), 8947 @tagName(backend), 8948 }); 8949 8950 break :msg msg; 8951 }); 8952 } 8953 8954 const Section = union(enum) { 8955 generic, 8956 default, 8957 explicit: InternPool.NullTerminatedString, 8958 }; 8959 8960 fn funcCommon( 8961 sema: *Sema, 8962 block: *Block, 8963 src_node_offset: std.zig.Ast.Node.Offset, 8964 func_inst: Zir.Inst.Index, 8965 cc: std.lang.CallingConvention, 8966 /// this might be Type.generic_poison 8967 bare_return_type: Type, 8968 var_args: bool, 8969 inferred_error_set: bool, 8970 has_body: bool, 8971 src_locs: Zir.Inst.Func.SrcLocs, 8972 noalias_bits: u32, 8973 is_noinline: bool, 8974 ) CompileError!Air.Inst.Ref { 8975 const pt = sema.pt; 8976 const zcu = pt.zcu; 8977 const comp = zcu.comp; 8978 const gpa = comp.gpa; 8979 const io = comp.io; 8980 const ip = &zcu.intern_pool; 8981 8982 const src = block.nodeOffset(src_node_offset); 8983 const ret_ty_src = block.src(.{ .node_offset_fn_type_ret_ty = src_node_offset }); 8984 const cc_src = block.src(.{ .node_offset_fn_type_cc = src_node_offset }); 8985 8986 var comptime_bits: u32 = 0; 8987 for (block.params.items(.ty), block.params.items(.is_comptime), 0..) |param_ty_ip, param_is_comptime, i| { 8988 const param_ty: Type = .fromInterned(param_ty_ip); 8989 const is_noalias = blk: { 8990 const index = std.math.cast(u5, i) orelse break :blk false; 8991 break :blk @as(u1, @truncate(noalias_bits >> index)) != 0; 8992 }; 8993 const param_src = block.src(.{ .fn_proto_param = .{ 8994 .fn_proto_node_offset = src_node_offset, 8995 .param_index = @intCast(i), 8996 } }); 8997 if (param_is_comptime) { 8998 comptime_bits |= @as(u32, 1) << @intCast(i); // TODO: handle cast error 8999 } 9000 try sema.checkParamType( 9001 block, 9002 @intCast(i), 9003 param_ty, 9004 param_is_comptime, 9005 is_noalias, 9006 param_src, 9007 cc, 9008 ); 9009 } 9010 9011 try sema.checkReturnTypeAndCallConv( 9012 block, 9013 bare_return_type, 9014 ret_ty_src, 9015 cc, 9016 cc_src, 9017 if (var_args) block.src(.{ .fn_proto_param = .{ 9018 .fn_proto_node_offset = src_node_offset, 9019 .param_index = @intCast(block.params.len), 9020 } }) else null, 9021 inferred_error_set, 9022 is_noinline, 9023 ); 9024 9025 const param_types = block.params.items(.ty); 9026 9027 if (has_body) { 9028 for (param_types, 0..) |param_ty_ip, param_index| { 9029 const param_ty: Type = .fromInterned(param_ty_ip); 9030 const param_src = block.src(.{ .fn_proto_param = .{ 9031 .fn_proto_node_offset = src_node_offset, 9032 .param_index = @intCast(param_index), 9033 } }); 9034 try sema.ensureLayoutResolved(param_ty, param_src, .parameter); 9035 } 9036 try sema.ensureLayoutResolved(bare_return_type, ret_ty_src, .return_type); 9037 try sema.validateResolvedFuncType( 9038 block, 9039 cc, 9040 param_types, 9041 bare_return_type, 9042 src, 9043 ip.getNav(sema.owner.unwrap().nav_val).srcInst(ip), 9044 ); 9045 } 9046 9047 if (inferred_error_set) { 9048 assert(has_body); 9049 return .fromIntern(try ip.getFuncDeclIes(gpa, io, pt.tid, .{ 9050 .owner_nav = sema.owner.unwrap().nav_val, 9051 9052 .param_types = param_types, 9053 .noalias_bits = noalias_bits, 9054 .comptime_bits = comptime_bits, 9055 .bare_return_type = bare_return_type.toIntern(), 9056 .cc = cc, 9057 .is_var_args = var_args, 9058 .is_noinline = is_noinline, 9059 9060 .zir_body_inst = try block.trackZir(func_inst), 9061 .lbrace_line = src_locs.lbrace_line, 9062 .rbrace_line = src_locs.rbrace_line, 9063 .lbrace_column = @as(u16, @truncate(src_locs.columns)), 9064 .rbrace_column = @as(u16, @truncate(src_locs.columns >> 16)), 9065 })); 9066 } 9067 9068 const func_ty = try ip.getFuncType(gpa, io, pt.tid, .{ 9069 .param_types = param_types, 9070 .noalias_bits = noalias_bits, 9071 .comptime_bits = comptime_bits, 9072 .return_type = bare_return_type.toIntern(), 9073 .cc = cc, 9074 .is_var_args = var_args, 9075 .is_noinline = is_noinline, 9076 }); 9077 9078 if (has_body) { 9079 return .fromIntern(try ip.getFuncDecl(gpa, io, pt.tid, .{ 9080 .owner_nav = sema.owner.unwrap().nav_val, 9081 .ty = func_ty, 9082 .cc = cc, 9083 .is_noinline = is_noinline, 9084 .zir_body_inst = try block.trackZir(func_inst), 9085 .lbrace_line = src_locs.lbrace_line, 9086 .rbrace_line = src_locs.rbrace_line, 9087 .lbrace_column = @as(u16, @truncate(src_locs.columns)), 9088 .rbrace_column = @as(u16, @truncate(src_locs.columns >> 16)), 9089 })); 9090 } 9091 9092 return .fromIntern(func_ty); 9093 } 9094 9095 fn zirParam( 9096 sema: *Sema, 9097 block: *Block, 9098 inst: Zir.Inst.Index, 9099 comptime_syntax: bool, 9100 ) CompileError!void { 9101 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_tok; 9102 const src = block.tokenOffset(inst_data.src_tok); 9103 const extra = sema.code.extraData(Zir.Inst.Param, inst_data.payload_index); 9104 const param_name: Zir.NullTerminatedString = extra.data.name; 9105 const body = sema.code.bodySlice(extra.end, extra.data.type.body_len); 9106 9107 const param_ty: Type = if (extra.data.type.is_generic) .generic_poison else ty: { 9108 // Make sure any nested param instructions don't clobber our work. 9109 const prev_params = block.params; 9110 block.params = .{}; 9111 defer { 9112 block.params = prev_params; 9113 } 9114 9115 const param_ty_inst = try sema.resolveInlineBody(block, body, inst); 9116 break :ty try sema.analyzeAsType(block, src, .fn_param_types, param_ty_inst); 9117 }; 9118 9119 try block.params.append(sema.arena, .{ 9120 .ty = param_ty.toIntern(), 9121 .is_comptime = comptime_syntax, 9122 .name = param_name, 9123 }); 9124 } 9125 9126 fn zirParamAnytype( 9127 sema: *Sema, 9128 block: *Block, 9129 inst: Zir.Inst.Index, 9130 comptime_syntax: bool, 9131 ) CompileError!void { 9132 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].str_tok; 9133 const param_name: Zir.NullTerminatedString = inst_data.start; 9134 9135 try block.params.append(sema.arena, .{ 9136 .ty = .generic_poison_type, 9137 .is_comptime = comptime_syntax, 9138 .name = param_name, 9139 }); 9140 } 9141 9142 fn zirAsNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 9143 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 9144 const src = block.nodeOffset(inst_data.src_node); 9145 const extra = sema.code.extraData(Zir.Inst.As, inst_data.payload_index).data; 9146 return sema.analyzeAs(block, src, extra.dest_type, extra.operand, false); 9147 } 9148 9149 fn zirAsShiftOperand(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 9150 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 9151 const src = block.nodeOffset(inst_data.src_node); 9152 const extra = sema.code.extraData(Zir.Inst.As, inst_data.payload_index).data; 9153 return sema.analyzeAs(block, src, extra.dest_type, extra.operand, true); 9154 } 9155 9156 fn analyzeAs( 9157 sema: *Sema, 9158 block: *Block, 9159 src: LazySrcLoc, 9160 zir_dest_type: Zir.Inst.Ref, 9161 zir_operand: Zir.Inst.Ref, 9162 no_cast_to_comptime_int: bool, 9163 ) CompileError!Air.Inst.Ref { 9164 const pt = sema.pt; 9165 const zcu = pt.zcu; 9166 const operand = sema.resolveInst(zir_operand); 9167 const dest_ty = try sema.resolveTypeOrPoison(block, src, zir_dest_type) orelse return operand; 9168 switch (dest_ty.zigTypeTag(zcu)) { 9169 .@"opaque" => return sema.fail(block, src, "cannot cast to opaque type '{f}'", .{dest_ty.fmt(pt)}), 9170 .noreturn => return sema.fail(block, src, "cannot cast to noreturn", .{}), 9171 else => {}, 9172 } 9173 9174 const is_ret = if (zir_dest_type.toIndex()) |ptr_index| 9175 sema.code.instructions.items(.tag)[@backingInt(ptr_index)] == .ret_type 9176 else 9177 false; 9178 return sema.coerceExtra(block, dest_ty, operand, src, .{ .is_ret = is_ret, .no_cast_to_comptime_int = no_cast_to_comptime_int }) catch |err| switch (err) { 9179 error.NotCoercible => unreachable, 9180 else => |e| return e, 9181 }; 9182 } 9183 9184 fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 9185 const pt = sema.pt; 9186 const zcu = pt.zcu; 9187 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].un_node; 9188 const ptr_src = block.builtinCallArgSrc(inst_data.src_node, 0); 9189 const operand = sema.resolveInst(inst_data.operand); 9190 const operand_ty = sema.typeOf(operand); 9191 const ptr_ty = operand_ty.scalarType(zcu); 9192 const is_vector = operand_ty.zigTypeTag(zcu) == .vector; 9193 if (!ptr_ty.isPtrAtRuntime(zcu)) { 9194 return sema.fail(block, ptr_src, "expected pointer, found '{f}'", .{ptr_ty.fmt(pt)}); 9195 } 9196 9197 const len = if (is_vector) operand_ty.vectorLen(zcu) else undefined; 9198 const dest_ty: Type = if (is_vector) try pt.vectorType(.{ .child = .usize_type, .len = len }) else .usize; 9199 9200 if (sema.resolveValue(operand)) |operand_val| ct: { 9201 if (!is_vector) { 9202 if (operand_val.isUndef(zcu)) { 9203 return .undef_usize; 9204 } 9205 const addr = operand_val.getUnsignedInt(zcu) orelse { 9206 // Wasn't an integer pointer. This is a runtime operation. 9207 break :ct; 9208 }; 9209 return Air.internedToRef((try pt.intValue( 9210 .usize, 9211 addr, 9212 )).toIntern()); 9213 } 9214 const new_elems = try sema.arena.alloc(InternPool.Index, len); 9215 for (new_elems, 0..) |*new_elem, i| { 9216 const ptr_val = try operand_val.elemValue(pt, i); 9217 if (ptr_val.isUndef(zcu)) { 9218 new_elem.* = .undef_usize; 9219 continue; 9220 } 9221 const addr = ptr_val.getUnsignedInt(zcu) orelse { 9222 // A vector element wasn't an integer pointer. This is a runtime operation. 9223 break :ct; 9224 }; 9225 new_elem.* = (try pt.intValue( 9226 .usize, 9227 addr, 9228 )).toIntern(); 9229 } 9230 return Air.internedToRef((try pt.aggregateValue(dest_ty, new_elems)).toIntern()); 9231 } 9232 try sema.requireRuntimeBlock(block, block.nodeOffset(inst_data.src_node), ptr_src); 9233 try sema.validateRuntimeValue(block, ptr_src, operand); 9234 try sema.checkLogicalPtrOperation(block, ptr_src, ptr_ty); 9235 return block.addTyOp(.int_from_ptr, dest_ty, operand); 9236 } 9237 9238 fn zirFieldPtrLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 9239 const pt = sema.pt; 9240 const zcu = pt.zcu; 9241 const comp = zcu.comp; 9242 const gpa = comp.gpa; 9243 const io = comp.io; 9244 9245 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 9246 const src = block.nodeOffset(inst_data.src_node); 9247 const field_name_src = block.src(.{ .node_offset_field_name = inst_data.src_node }); 9248 const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data; 9249 const field_name = try zcu.intern_pool.getOrPutString( 9250 gpa, 9251 io, 9252 pt.tid, 9253 sema.code.nullTerminatedString(extra.field_name_start), 9254 .no_embedded_nulls, 9255 ); 9256 const object_ptr = sema.resolveInst(extra.lhs); 9257 return fieldPtrLoad(sema, block, src, object_ptr, field_name, field_name_src); 9258 } 9259 9260 fn zirFieldPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 9261 const pt = sema.pt; 9262 const zcu = pt.zcu; 9263 const comp = zcu.comp; 9264 const gpa = comp.gpa; 9265 const io = comp.io; 9266 9267 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 9268 const src = block.nodeOffset(inst_data.src_node); 9269 const field_name_src = block.src(.{ .node_offset_field_name = inst_data.src_node }); 9270 const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data; 9271 const field_name = try zcu.intern_pool.getOrPutString( 9272 gpa, 9273 io, 9274 pt.tid, 9275 sema.code.nullTerminatedString(extra.field_name_start), 9276 .no_embedded_nulls, 9277 ); 9278 const object_ptr = sema.resolveInst(extra.lhs); 9279 return sema.fieldPtr(block, src, object_ptr, field_name, field_name_src, false); 9280 } 9281 9282 fn zirStructInitFieldPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 9283 const pt = sema.pt; 9284 const zcu = pt.zcu; 9285 const comp = zcu.comp; 9286 const gpa = comp.gpa; 9287 const io = comp.io; 9288 9289 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 9290 const src = block.nodeOffset(inst_data.src_node); 9291 const field_name_src = block.src(.{ .node_offset_field_name_init = inst_data.src_node }); 9292 const extra = sema.code.extraData(Zir.Inst.Field, inst_data.payload_index).data; 9293 const field_name = try zcu.intern_pool.getOrPutString( 9294 gpa, 9295 io, 9296 pt.tid, 9297 sema.code.nullTerminatedString(extra.field_name_start), 9298 .no_embedded_nulls, 9299 ); 9300 const object_ptr = sema.resolveInst(extra.lhs); 9301 const struct_ty = sema.typeOf(object_ptr).childType(zcu); 9302 switch (struct_ty.zigTypeTag(zcu)) { 9303 .@"struct", .@"union" => { 9304 return sema.fieldPtr(block, src, object_ptr, field_name, field_name_src, true); 9305 }, 9306 else => { 9307 return sema.failWithStructInitNotSupported(block, src, struct_ty); 9308 }, 9309 } 9310 } 9311 9312 fn zirFieldPtrNamedLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 9313 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 9314 const src = block.nodeOffset(inst_data.src_node); 9315 const field_name_src = block.builtinCallArgSrc(inst_data.src_node, 1); 9316 const extra = sema.code.extraData(Zir.Inst.FieldNamed, inst_data.payload_index).data; 9317 const object_ptr = sema.resolveInst(extra.lhs); 9318 const field_name = try sema.resolveConstStringIntern(block, field_name_src, extra.field_name, .{ .simple = .field_name }); 9319 return fieldPtrLoad(sema, block, src, object_ptr, field_name, field_name_src); 9320 } 9321 9322 fn zirFieldPtrNamed(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 9323 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 9324 const src = block.nodeOffset(inst_data.src_node); 9325 const field_name_src = block.builtinCallArgSrc(inst_data.src_node, 1); 9326 const extra = sema.code.extraData(Zir.Inst.FieldNamed, inst_data.payload_index).data; 9327 const object_ptr = sema.resolveInst(extra.lhs); 9328 const field_name = try sema.resolveConstStringIntern(block, field_name_src, extra.field_name, .{ .simple = .field_name }); 9329 return sema.fieldPtr(block, src, object_ptr, field_name, field_name_src, false); 9330 } 9331 9332 fn zirIntCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 9333 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 9334 const src = block.nodeOffset(inst_data.src_node); 9335 const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); 9336 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; 9337 9338 const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@intCast"); 9339 const operand = sema.resolveInst(extra.rhs); 9340 9341 return sema.intCast(block, block.nodeOffset(inst_data.src_node), dest_ty, src, operand, operand_src); 9342 } 9343 9344 fn intCast( 9345 sema: *Sema, 9346 block: *Block, 9347 src: LazySrcLoc, 9348 dest_ty: Type, 9349 dest_ty_src: LazySrcLoc, 9350 operand: Air.Inst.Ref, 9351 operand_src: LazySrcLoc, 9352 ) CompileError!Air.Inst.Ref { 9353 const pt = sema.pt; 9354 const zcu = pt.zcu; 9355 const operand_ty = sema.typeOf(operand); 9356 const dest_scalar_ty = try sema.checkIntOrVectorAllowComptime(block, dest_ty, dest_ty_src); 9357 const operand_scalar_ty = try sema.checkIntOrVectorAllowComptime(block, operand_ty, operand_src); 9358 9359 if (try sema.isComptimeKnown(operand)) { 9360 return sema.coerce(block, dest_ty, operand, operand_src); 9361 } else if (dest_scalar_ty.zigTypeTag(zcu) == .comptime_int) { 9362 return sema.fail(block, operand_src, "unable to cast runtime value to 'comptime_int'", .{}); 9363 } 9364 9365 try sema.checkVectorizableBinaryOperands(block, operand_src, dest_ty, operand_ty, dest_ty_src, operand_src); 9366 const is_vector = dest_ty.zigTypeTag(zcu) == .vector; 9367 9368 if (try dest_ty.onePossibleValue(pt)) |opv| { 9369 // requirement: intCast(u0, input) iff input == 0 9370 if (block.wantSafety()) { 9371 try sema.requireRuntimeBlock(block, src, operand_src); 9372 const wanted_info = dest_scalar_ty.intInfo(zcu); 9373 const wanted_bits = wanted_info.bits; 9374 9375 if (wanted_bits == 0) { 9376 const ok = if (is_vector) ok: { 9377 const zeros = try sema.splat(operand_ty, try pt.intValue(operand_scalar_ty, 0)); 9378 const zero_inst = Air.internedToRef(zeros.toIntern()); 9379 const is_in_range = try block.addCmpVector(operand, zero_inst, .eq); 9380 const all_in_range = try block.addReduce(is_in_range, .And); 9381 break :ok all_in_range; 9382 } else ok: { 9383 const zero_inst = Air.internedToRef((try pt.intValue(operand_ty, 0)).toIntern()); 9384 const is_in_range = try block.addBinOp(.cmp_eq, operand, zero_inst); 9385 break :ok is_in_range; 9386 }; 9387 try sema.addSafetyCheck(block, src, ok, .integer_out_of_bounds); 9388 } 9389 } 9390 9391 return Air.internedToRef(opv.toIntern()); 9392 } 9393 9394 try sema.requireRuntimeBlock(block, src, operand_src); 9395 if (block.wantSafety()) { 9396 try sema.preparePanicId(src, .integer_out_of_bounds); 9397 return block.addTyOp(.int_cast_safe, dest_ty, operand); 9398 } 9399 return block.addTyOp(.int_cast, dest_ty, operand); 9400 } 9401 9402 fn zirBitcast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 9403 const pt = sema.pt; 9404 const zcu = pt.zcu; 9405 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 9406 const src = block.nodeOffset(inst_data.src_node); 9407 const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); 9408 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; 9409 9410 const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@bitCast"); 9411 const operand = sema.resolveInst(extra.rhs); 9412 const operand_ty = sema.typeOf(operand); 9413 9414 // Check for pointers before checking `hasBitRepresentation` so we can emit a better message for slices. 9415 switch (dest_ty.scalarType(zcu).zigTypeTag(zcu)) { 9416 .pointer, .optional => return sema.failWithOwnedErrorMsg(block, msg: { 9417 const msg = try sema.errMsg(src, "cannot @bitCast to '{f}'", .{dest_ty.fmt(pt)}); 9418 errdefer msg.destroy(sema.gpa); 9419 switch (operand_ty.zigTypeTag(zcu)) { 9420 .int, .comptime_int => try sema.errNote(src, msg, "use @ptrFromInt to cast from '{f}'", .{operand_ty.fmt(pt)}), 9421 .pointer => try sema.errNote(src, msg, "use @ptrCast to cast from '{f}'", .{operand_ty.fmt(pt)}), 9422 else => {}, 9423 } 9424 break :msg msg; 9425 }), 9426 .array => switch (dest_ty.arrayBase(zcu)[0].zigTypeTag(zcu)) { 9427 .pointer, .optional => return sema.fail(block, src, "cannot @bitCast to '{f}'", .{dest_ty.fmt(pt)}), 9428 else => {}, 9429 }, 9430 else => {}, 9431 } 9432 if (!dest_ty.hasBitRepresentation(zcu)) { 9433 return sema.fail(block, src, "cannot @bitCast to '{f}'", .{dest_ty.fmt(pt)}); 9434 } 9435 9436 // Check for pointers before checking `hasBitRepresentation` so we can emit a better message for slices. 9437 switch (operand_ty.scalarType(zcu).zigTypeTag(zcu)) { 9438 .pointer, .optional => return sema.failWithOwnedErrorMsg(block, msg: { 9439 const msg = try sema.errMsg(operand_src, "cannot @bitCast from '{f}'", .{operand_ty.fmt(pt)}); 9440 errdefer msg.destroy(sema.gpa); 9441 switch (dest_ty.zigTypeTag(zcu)) { 9442 .int, .comptime_int => try sema.errNote(operand_src, msg, "use @intFromPtr to cast to '{f}'", .{dest_ty.fmt(pt)}), 9443 .pointer => try sema.errNote(operand_src, msg, "use @ptrCast to cast to '{f}'", .{dest_ty.fmt(pt)}), 9444 else => {}, 9445 } 9446 break :msg msg; 9447 }), 9448 .array => switch (operand_ty.arrayBase(zcu)[0].zigTypeTag(zcu)) { 9449 .pointer, .optional => return sema.fail(block, operand_src, "cannot @bitCast from '{f}'", .{dest_ty.fmt(pt)}), 9450 else => {}, 9451 }, 9452 else => {}, 9453 } 9454 if (!operand_ty.hasBitRepresentation(zcu)) { 9455 return sema.fail(block, operand_src, "cannot @bitCast from '{f}'", .{operand_ty.fmt(pt)}); 9456 } 9457 9458 operand_ty.assertHasLayout(zcu); 9459 try sema.ensureLayoutResolved(dest_ty, src, .init); 9460 9461 const operand_bits = operand_ty.bitSize(zcu); 9462 const dest_bits = dest_ty.bitSize(zcu); 9463 if (operand_bits != dest_bits) { 9464 return sema.fail(block, src, "@bitCast size mismatch: destination type '{f}' has {d} bits but source type '{f}' has {d} bits", .{ 9465 dest_ty.fmt(pt), 9466 dest_bits, 9467 operand_ty.fmt(pt), 9468 operand_bits, 9469 }); 9470 } 9471 9472 if (sema.resolveValue(operand)) |operand_val| { 9473 const dest_is_exhaustive_enum = dest_ty.zigTypeTag(zcu) == .@"enum" and 9474 !dest_ty.isNonexhaustiveEnum(zcu); 9475 if (dest_is_exhaustive_enum and operand_val.isUndef(zcu)) { 9476 return sema.failWithUseOfUndef(block, operand_src, null); 9477 } 9478 9479 const result_val = try sema.bitCastVal(operand_val, dest_ty); 9480 9481 if (dest_is_exhaustive_enum and 9482 dest_ty.enumTagFieldIndex(result_val, zcu) == null) 9483 { 9484 return sema.fail(block, src, "enum '{f}' has no tag with value '{f}'", .{ 9485 dest_ty.fmt(pt), result_val.backingInt(zcu).fmtValueSema(pt, sema), 9486 }); 9487 } 9488 9489 return .fromValue(result_val); 9490 } 9491 9492 try sema.validateRuntimeValue(block, src, operand); 9493 9494 if (block.wantSafety()) { 9495 try sema.preparePanicId(src, .invalid_enum_value); 9496 return block.addTyOp(.bit_cast_safe, dest_ty, operand); 9497 } 9498 return block.addTyOp(.bit_cast, dest_ty, operand); 9499 } 9500 9501 fn zirBackingInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 9502 const pt = sema.pt; 9503 const zcu = pt.zcu; 9504 const gpa = zcu.comp.gpa; 9505 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].un_node; 9506 const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); 9507 9508 const operand = sema.resolveInst(inst_data.operand); 9509 const operand_ty = sema.typeOf(operand); 9510 operand_ty.assertHasLayout(zcu); 9511 const int_backed_ref: Air.Inst.Ref = ref: switch (operand_ty.zigTypeTag(zcu)) { 9512 .@"enum" => operand, 9513 .@"union" => { 9514 const union_obj = zcu.intern_pool.loadUnionType(operand_ty.toIntern()); 9515 if (union_obj.tag_usage == .tagged) break :ref try sema.unionToTag(block, operand); 9516 if (union_obj.layout == .@"packed") break :ref operand; 9517 return sema.failWithOwnedErrorMsg(block, msg: { 9518 const msg = try sema.errMsg(operand_src, "non-packed union '{f}' does not have a backing integer", .{operand_ty.fmt(pt)}); 9519 errdefer msg.deinit(gpa); 9520 try sema.errNote(operand_src, msg, "untagged union '{f}' does not have an enum tag with a backing integer", .{operand_ty.fmt(pt)}); 9521 try sema.addDeclaredHereNote(msg, operand_ty); 9522 break :msg msg; 9523 }); 9524 }, 9525 .@"struct" => { 9526 if (operand_ty.containerLayout(zcu) != .@"packed") { 9527 return sema.fail(block, operand_src, "non-packed struct '{f}' does not have a backing integer", .{ 9528 operand_ty.fmt(pt), 9529 }); 9530 } 9531 break :ref operand; 9532 }, 9533 else => { 9534 return sema.fail(block, operand_src, "expected enum, tagged union, packed union or packed struct, found '{f}'", .{ 9535 operand_ty.fmt(pt), 9536 }); 9537 }, 9538 }; 9539 const int_backed_ty = sema.typeOf(int_backed_ref); 9540 if (int_backed_ty.backingIntMode(zcu) != .explicit and int_backed_ty.zigTypeTag(zcu) != .@"enum") 9541 return sema.failWithAmbiguousBackingIntType(block, operand_src, int_backed_ty, "@backingInt"); 9542 const backing_int_ty = int_backed_ty.backingIntType(zcu); 9543 9544 if (sema.resolveValue(int_backed_ref)) |int_backed_val| { 9545 if (int_backed_val.isUndef(zcu)) return pt.undefRef(backing_int_ty); 9546 return .fromValue(int_backed_val.backingInt(zcu)); 9547 } 9548 9549 switch (backing_int_ty.classify(zcu)) { 9550 .partially_comptime, .fully_comptime => unreachable, // does not apply to integers 9551 .no_possible_value => unreachable, // enum also NPV, cannot instantiate NPV types 9552 .one_possible_value => unreachable, // enum or bitpack also OPV, should have been resolve above 9553 .runtime => {}, 9554 } 9555 9556 return block.addTyOp(.bit_cast, backing_int_ty, int_backed_ref); 9557 } 9558 9559 fn zirFromBackingIntArgTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 9560 const pt = sema.pt; 9561 const zcu = pt.zcu; 9562 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].un_node; 9563 const src = block.nodeOffset(inst_data.src_node); 9564 9565 const dest_ty = try sema.resolveDestType(block, src, inst_data.operand, .remove_eu_opt, "@fromBackingInt"); 9566 try sema.ensureLayoutResolved(dest_ty, src, .init); 9567 switch (dest_ty.zigTypeTag(zcu)) { 9568 .@"enum" => {}, 9569 .@"struct", .@"union" => |type_tag| if (dest_ty.containerLayout(zcu) != .@"packed") { 9570 return sema.fail(block, src, "non-packed {t} '{f}' does not have a backing integer", .{ 9571 type_tag, dest_ty.fmt(pt), 9572 }); 9573 }, 9574 else => { 9575 return sema.fail(block, src, "expected enum, packed union or packed struct, found '{f}'", .{ 9576 dest_ty.fmt(pt), 9577 }); 9578 }, 9579 } 9580 if (dest_ty.backingIntMode(zcu) != .explicit and dest_ty.zigTypeTag(zcu) != .@"enum") 9581 return sema.failWithAmbiguousBackingIntType(block, src, dest_ty, "@fromBackingInt"); 9582 return .fromType(dest_ty.backingIntType(zcu)); 9583 } 9584 9585 fn zirFromBackingInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 9586 const pt = sema.pt; 9587 const zcu = pt.zcu; 9588 const ip = &zcu.intern_pool; 9589 9590 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 9591 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; 9592 const src = block.nodeOffset(inst_data.src_node); 9593 const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); 9594 9595 // Type has already been validated and layout-resolved by `zirFromBackingIntArgTy`. 9596 const dest_ty = try sema.resolveDestType(block, .unneeded, extra.lhs, .remove_eu_opt, undefined); 9597 dest_ty.assertHasLayout(zcu); 9598 9599 const operand = sema.resolveInst(extra.rhs); 9600 const backing_int_ref = try sema.coerce(block, dest_ty.backingIntType(zcu), operand, operand_src); 9601 9602 if (sema.resolveValue(backing_int_ref)) |backing_int_val| { 9603 if (dest_ty.zigTypeTag(zcu) != .@"enum") { 9604 // we don't do any safety checks for bitpacks 9605 if (backing_int_val.isUndef(zcu)) return pt.undefRef(dest_ty); 9606 return .fromValue(try pt.bitpackValue(dest_ty, backing_int_val)); 9607 } 9608 const enum_obj = ip.loadEnumType(dest_ty.toIntern()); 9609 if (backing_int_val.isUndef(zcu)) { 9610 if (enum_obj.nonexhaustive) return pt.undefRef(dest_ty); 9611 return sema.failWithUseOfUndef(block, operand_src, null); 9612 } 9613 if (!enum_obj.nonexhaustive and 9614 enum_obj.tagValueIndex(ip, backing_int_val.toIntern()) == null) 9615 { 9616 return sema.fail(block, src, "enum '{f}' has no tag with value '{f}'", .{ 9617 dest_ty.fmt(pt), backing_int_val.fmtValueSema(pt, sema), 9618 }); 9619 } 9620 return .fromValue(try pt.enumValue(dest_ty, backing_int_val)); 9621 } 9622 9623 switch (dest_ty.classify(zcu)) { 9624 .partially_comptime, .fully_comptime => unreachable, // does not apply to enums or bitpacks 9625 .no_possible_value => unreachable, // backing int also NPV, cannot coerce to NPV type 9626 .one_possible_value => unreachable, // backing int also OPV, should have been resolve above 9627 .runtime => {}, 9628 } 9629 9630 if (block.wantSafety()) { 9631 try sema.preparePanicId(src, .invalid_enum_value); 9632 return block.addTyOp(.bit_cast_safe, dest_ty, backing_int_ref); 9633 } 9634 return block.addTyOp(.bit_cast, dest_ty, backing_int_ref); 9635 } 9636 9637 fn zirFloatCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 9638 const pt = sema.pt; 9639 const zcu = pt.zcu; 9640 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 9641 const src = block.nodeOffset(inst_data.src_node); 9642 const operand_src = block.builtinCallArgSrc(inst_data.src_node, 0); 9643 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; 9644 9645 const dest_ty = try sema.resolveDestType(block, src, extra.lhs, .remove_eu_opt, "@floatCast"); 9646 const dest_scalar_ty = dest_ty.scalarType(zcu); 9647 9648 const operand = sema.resolveInst(extra.rhs); 9649 const operand_ty = sema.typeOf(operand); 9650 const operand_scalar_ty = operand_ty.scalarType(zcu); 9651 9652 try sema.checkVectorizableBinaryOperands(block, operand_src, dest_ty, operand_ty, src, operand_src); 9653 const is_vector = dest_ty.zigTypeTag(zcu) == .vector; 9654 9655 const target = zcu.getTarget(); 9656 const dest_is_comptime_float = switch (dest_scalar_ty.zigTypeTag(zcu)) { 9657 .comptime_float => true, 9658 .float => false, 9659 else => return sema.fail( 9660 block, 9661 src, 9662 "expected float or vector type, found '{f}'", 9663 .{dest_ty.fmt(pt)}, 9664 ), 9665 }; 9666 9667 switch (operand_scalar_ty.zigTypeTag(zcu)) { 9668 .comptime_float, .float, .comptime_int => {}, 9669 else => return sema.fail( 9670 block, 9671 operand_src, 9672 "expected float or vector type, found '{f}'", 9673 .{operand_ty.fmt(pt)}, 9674 ), 9675 } 9676 9677 if (sema.resolveValue(operand)) |operand_val| { 9678 if (!is_vector) { 9679 return Air.internedToRef((try operand_val.floatCast(dest_ty, pt)).toIntern()); 9680 } 9681 const vec_len = operand_ty.vectorLen(zcu); 9682 const new_elems = try sema.arena.alloc(InternPool.Index, vec_len); 9683 for (new_elems, 0..) |*new_elem, i| { 9684 const old_elem = try operand_val.elemValue(pt, i); 9685 new_elem.* = (try old_elem.floatCast(dest_scalar_ty, pt)).toIntern(); 9686 } 9687 return Air.internedToRef((try pt.aggregateValue(dest_ty, new_elems)).toIntern()); 9688 } 9689 if (dest_is_comptime_float) { 9690 return sema.fail(block, operand_src, "unable to cast runtime value to 'comptime_float'", .{}); 9691 } 9692 try sema.requireRuntimeBlock(block, block.nodeOffset(inst_data.src_node), operand_src); 9693 9694 const src_bits = operand_scalar_ty.floatBits(target); 9695 const dst_bits = dest_scalar_ty.floatBits(target); 9696 if (dst_bits >= src_bits) { 9697 return sema.coerce(block, dest_ty, operand, operand_src); 9698 } 9699 return block.addTyOp(.fptrunc, dest_ty, operand); 9700 } 9701 9702 fn zirElemVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 9703 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 9704 const src = block.nodeOffset(inst_data.src_node); 9705 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; 9706 const array = sema.resolveInst(extra.lhs); 9707 const elem_index = sema.resolveInst(extra.rhs); 9708 return sema.elemVal(block, src, array, elem_index, src, false); 9709 } 9710 9711 fn zirElemPtrLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 9712 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 9713 const src = block.nodeOffset(inst_data.src_node); 9714 const elem_index_src = block.src(.{ .node_offset_array_access_index = inst_data.src_node }); 9715 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; 9716 const array_ptr = sema.resolveInst(extra.lhs); 9717 const uncoerced_elem_index = sema.resolveInst(extra.rhs); 9718 if (try sema.resolveDefinedValue(block, src, array_ptr)) |array_ptr_val| { 9719 const array_ptr_ty = sema.typeOf(array_ptr); 9720 if (try sema.pointerDeref(block, src, array_ptr_val, array_ptr_ty)) |array_val| { 9721 const array: Air.Inst.Ref = .fromValue(array_val); 9722 return elemVal(sema, block, src, array, uncoerced_elem_index, elem_index_src, true); 9723 } 9724 } 9725 const elem_index = try sema.coerce(block, .usize, uncoerced_elem_index, elem_index_src); 9726 const elem_ptr = try elemPtr(sema, block, src, array_ptr, elem_index, elem_index_src, false, true); 9727 return analyzeLoad(sema, block, src, elem_ptr, elem_index_src); 9728 } 9729 9730 fn zirElemValImm(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 9731 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].elem_val_imm; 9732 const array = sema.resolveInst(inst_data.operand); 9733 const elem_index = try sema.pt.intRef(.usize, inst_data.idx); 9734 return sema.elemVal(block, LazySrcLoc.unneeded, array, elem_index, LazySrcLoc.unneeded, false); 9735 } 9736 9737 fn zirElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 9738 const pt = sema.pt; 9739 const zcu = pt.zcu; 9740 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 9741 const src = block.nodeOffset(inst_data.src_node); 9742 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; 9743 const array_ptr = sema.resolveInst(extra.lhs); 9744 const elem_index = sema.resolveInst(extra.rhs); 9745 const indexable_ty = sema.typeOf(array_ptr); 9746 if (indexable_ty.zigTypeTag(zcu) != .pointer) { 9747 const capture_src = block.src(.{ .for_capture_from_input = inst_data.src_node }); 9748 const msg = msg: { 9749 const msg = try sema.errMsg(capture_src, "pointer capture of non pointer type '{f}'", .{ 9750 indexable_ty.fmt(pt), 9751 }); 9752 errdefer msg.destroy(sema.gpa); 9753 if (indexable_ty.isIndexable(zcu)) { 9754 try sema.errNote(src, msg, "consider using '&' here", .{}); 9755 } 9756 break :msg msg; 9757 }; 9758 return sema.failWithOwnedErrorMsg(block, msg); 9759 } 9760 try sema.checkIndexable(block, src, indexable_ty); 9761 try sema.ensureLayoutResolved(indexable_ty.childType(zcu), src, .ptr_access); 9762 return sema.elemPtrOneLayerOnly(block, src, array_ptr, elem_index, src, false, false); 9763 } 9764 9765 fn zirElemPtrNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 9766 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 9767 const src = block.nodeOffset(inst_data.src_node); 9768 const elem_index_src = block.src(.{ .node_offset_array_access_index = inst_data.src_node }); 9769 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data; 9770 const array_ptr = sema.resolveInst(extra.lhs); 9771 const uncoerced_elem_index = sema.resolveInst(extra.rhs); 9772 const elem_index = try sema.coerce(block, .usize, uncoerced_elem_index, elem_index_src); 9773 return sema.elemPtr(block, src, array_ptr, elem_index, elem_index_src, false, true); 9774 } 9775 9776 fn zirArrayInitElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 9777 const pt = sema.pt; 9778 const zcu = pt.zcu; 9779 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 9780 const src = block.nodeOffset(inst_data.src_node); 9781 const extra = sema.code.extraData(Zir.Inst.ElemPtrImm, inst_data.payload_index).data; 9782 const array_ptr = sema.resolveInst(extra.ptr); 9783 const elem_index = try pt.intRef(.usize, extra.index); 9784 const array_ty = sema.typeOf(array_ptr).childType(zcu); 9785 switch (array_ty.zigTypeTag(zcu)) { 9786 .array, .vector => {}, 9787 else => if (!array_ty.isTuple(zcu)) { 9788 return sema.failWithArrayInitNotSupported(block, src, array_ty); 9789 }, 9790 } 9791 return sema.elemPtr(block, src, array_ptr, elem_index, src, true, true); 9792 } 9793 9794 fn zirSliceStart(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 9795 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 9796 const src = block.nodeOffset(inst_data.src_node); 9797 const extra = sema.code.extraData(Zir.Inst.SliceStart, inst_data.payload_index).data; 9798 const array_ptr = sema.resolveInst(extra.lhs); 9799 const start = sema.resolveInst(extra.start); 9800 const ptr_src = block.src(.{ .node_offset_slice_ptr = inst_data.src_node }); 9801 const start_src = block.src(.{ .node_offset_slice_start = inst_data.src_node }); 9802 const end_src = block.src(.{ .node_offset_slice_end = inst_data.src_node }); 9803 9804 return sema.analyzeSlice(block, src, array_ptr, start, .none, .none, LazySrcLoc.unneeded, ptr_src, start_src, end_src, false); 9805 } 9806 9807 fn zirSliceEnd(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 9808 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 9809 const src = block.nodeOffset(inst_data.src_node); 9810 const extra = sema.code.extraData(Zir.Inst.SliceEnd, inst_data.payload_index).data; 9811 const array_ptr = sema.resolveInst(extra.lhs); 9812 const start = sema.resolveInst(extra.start); 9813 const end = sema.resolveInst(extra.end); 9814 const ptr_src = block.src(.{ .node_offset_slice_ptr = inst_data.src_node }); 9815 const start_src = block.src(.{ .node_offset_slice_start = inst_data.src_node }); 9816 const end_src = block.src(.{ .node_offset_slice_end = inst_data.src_node }); 9817 9818 return sema.analyzeSlice(block, src, array_ptr, start, end, .none, LazySrcLoc.unneeded, ptr_src, start_src, end_src, false); 9819 } 9820 9821 fn zirSliceSentinel(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 9822 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 9823 const src = block.nodeOffset(inst_data.src_node); 9824 const sentinel_src = block.src(.{ .node_offset_slice_sentinel = inst_data.src_node }); 9825 const extra = sema.code.extraData(Zir.Inst.SliceSentinel, inst_data.payload_index).data; 9826 const array_ptr = sema.resolveInst(extra.lhs); 9827 const start = sema.resolveInst(extra.start); 9828 const end: Air.Inst.Ref = if (extra.end == .none) .none else sema.resolveInst(extra.end); 9829 const sentinel = sema.resolveInst(extra.sentinel); 9830 const ptr_src = block.src(.{ .node_offset_slice_ptr = inst_data.src_node }); 9831 const start_src = block.src(.{ .node_offset_slice_start = inst_data.src_node }); 9832 const end_src = block.src(.{ .node_offset_slice_end = inst_data.src_node }); 9833 9834 return sema.analyzeSlice(block, src, array_ptr, start, end, sentinel, sentinel_src, ptr_src, start_src, end_src, false); 9835 } 9836 9837 fn zirSliceLength(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 9838 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].pl_node; 9839 const src = block.nodeOffset(inst_data.src_node); 9840 const extra = sema.code.extraData(Zir.Inst.SliceLength, inst_data.payload_index).data; 9841 const array_ptr = sema.resolveInst(extra.lhs); 9842 const start = sema.resolveInst(extra.start); 9843 const len = sema.resolveInst(extra.len); 9844 const sentinel = if (extra.sentinel == .none) .none else sema.resolveInst(extra.sentinel); 9845 const ptr_src = block.src(.{ .node_offset_slice_ptr = inst_data.src_node }); 9846 const start_src = block.src(.{ .node_offset_slice_start = extra.start_src_node_offset }); 9847 const end_src = block.src(.{ .node_offset_slice_end = inst_data.src_node }); 9848 const sentinel_src: LazySrcLoc = if (sentinel == .none) 9849 LazySrcLoc.unneeded 9850 else 9851 block.src(.{ .node_offset_slice_sentinel = inst_data.src_node }); 9852 9853 return sema.analyzeSlice(block, src, array_ptr, start, len, sentinel, sentinel_src, ptr_src, start_src, end_src, true); 9854 } 9855 9856 fn zirSliceSentinelTy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 9857 const pt = sema.pt; 9858 const zcu = pt.zcu; 9859 9860 const inst_data = sema.code.instructions.items(.data)[@backingInt(inst)].un_node; 9861 9862 const src = block.nodeOffset(inst_data.src_node); 9863 const ptr_src = block.src(.{ .node_offset_slice_ptr = inst_data.src_node }); 9864 const sentinel_src = block.src(.{ .node_offset_slice_sentinel = inst_data.src_node }); 9865 9866 // This is like the logic in `analyzeSlice`; since we've evaluated the LHS as an lvalue, we will 9867 // have a double pointer if it was already a pointer. 9868 9869 const lhs_ptr_ty = sema.typeOf(sema.resolveInst(inst_data.operand)); 9870 const lhs_ty = switch (lhs_ptr_ty.zigTypeTag(zcu)) { 9871 .pointer => lhs_ptr_ty.childType(zcu), 9872 else => return sema.fail(block, ptr_src, "expected pointer, found '{f}'", .{lhs_ptr_ty.fmt(pt)}), 9873 }; 9874 9875 const sentinel_ty: Type = switch (lhs_ty.zigTypeTag(zcu)) { 9876 .array => lhs_ty.childType(zcu), 9877 .pointer => switch (lhs_ty.ptrSize(zcu)) { 9878 .many, .c, .slice => lhs_ty.childType(zcu), 9879 .one => s: { 9880 const lhs_elem_ty = lhs_ty.childType(zcu); 9881 break :s switch (lhs_elem_ty.zigTypeTag(zcu)) { 9882 .array => lhs_elem_ty.childType(zcu), // array element type 9883 else => return sema.fail(block, sentinel_src, "slice of single-item pointer cannot have sentinel", .{}), 9884 }; 9885 }, 9886 }, 9887 else => return sema.fail(block, src, "slice of non-array type '{f}'", .{lhs_ty.fmt(pt)}), 9888 }; 9889 9890 return Air.internedToRef(sentinel_ty.toIntern()); 9891 } 9892 9893 fn zirSwitchBlockErrUnion(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { 9894 const pt = sema.pt; 9895 const zcu = pt.zcu; 9896 const gpa = sema.gpa; 9897 9898 const zir_switch = sema.code.getSwitchBlock(inst); 9899 const src_node_offset = zir_switch.catch_or_if_src_node_offset.unwrap().?; 9900 const src = block.src(.{ .node_offset_main_token = src_node_offset }); 9901 const operand_src = block.src(.{ .node_offset_if_cond = src_node_offset }); 9902 9903 assert(!zir_switch.has_continue); // wrong codepath! 9904 9905 const block_inst: Air.Inst.Index = @fromBackingInt(@intCast(sema.air_instructions.len)); 9906 try sema.air_instructions.append(gpa, .{ 9907 .tag = .block, 9908 .data = undefined, 9909 }); 9910 var label: Block.Label = .{ 9911 .zir_block = inst, 9912 .merges = .{ 9913 .src_locs = .empty, 9914 .results = .empty, 9915 .br_list = .empty, 9916 .block_inst = block_inst, 9917 }, 9918 }; 9919 var child_block = block.makeSubBlock(); 9920 child_block.label = &label; 9921 const merges = &child_block.label.?.merges; 9922 defer child_block.instructions.deinit(gpa); 9923 defer merges.deinit(gpa); 9924 9925 const non_err_case = zir_switch.non_err_case.?; 9926 9927 var non_err_block: Block = child_block.makeSubBlock(); 9928 non_err_block.runtime_loop = null; 9929 non_err_block.runtime_cond = operand_src; 9930 non_err_block.runtime_index.increment(); 9931 non_err_block.need_debug_scope = null; 9932 defer non_err_block.instructions.deinit(gpa); 9933 9934 var switch_block: Block = child_block.makeSubBlock(); 9935 switch_block.runtime_loop = null; 9936 switch_block.runtime_cond = operand_src; 9937 switch_block.runtime_index.increment(); 9938 switch_block.need_debug_scope = null; 9939 defer switch_block.instructions.deinit(gpa); 9940 9941 // We begin with unwrapping the error union we're switching on as necessary. 9942 // Then we analyze the non-error prong if it's not comptime-unreachable. 9943 // Lastly, we analyze the error prong(s) as a regular switch. 9944 9945 const raw_switch_operand, const non_err_cond, const non_err_hint = non_err: { 9946 const eu_maybe_ptr = sema.resolveInst(zir_switch.main_operand);