╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭ Air.zig ──────────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭ find file ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ ╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │ │ │http│ ssh │ │ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
915 field_parent_ptr, 916 917 /// Implements @wasmMemorySize builtin. 918 /// Result type is always `usize`, 919 /// Uses the `pl_op` field, payload represents the index of the target memory. 920 /// The operand is unused and always set to `Ref.none`. 921 wasm_memory_size, 922 923 /// Implements @wasmMemoryGrow builtin. 924 /// Result type is always `isize`, 925 /// Uses the `pl_op` field, payload represents the index of the target memory. 926 wasm_memory_grow, 927 928 /// Returns `true` if and only if the operand, an integer with the same 929 /// size as the error integer type, is less than *or equal to* the total 930 /// number of errors in the Zcu. The "or equal to" is a consequence of 931 /// value 0 being reserved for the "non-error" status in error unions. 932 /// 933 /// This instruction exists (as opposed to just using `cmp_lte` against 934 /// a constant) because the number of errors in the Zcu is not known 935 /// until `Compilation.flush`. Before then, semantic analysis could 936 /// discover new errors at any time. 937 /// 938 /// Result type is always `bool`. 939 /// 940 /// Uses the `un_op` field. 941 cmp_lte_errors_len, 942 943 /// Returns pointer to current error return trace. 944 err_return_trace, 945 946 /// Sets the operand as the current error return trace, 947 set_err_return_trace, 948 949 /// Convert the address space of a pointer. 950 /// Uses the `ty_op` field. 951 addrspace_cast, 952 953 /// Saves the error return trace index, if any. Otherwise, returns 0. 954 /// Uses the `ty_pl` field. 955 save_err_return_trace_index, 956 957 /// Compute a pointer to a `Nav` at runtime, always one of: 958 /// 959 /// * `threadlocal var` 960 /// * `extern threadlocal var` (or corresponding `@extern`) 961 /// * `@extern` with `.is_dll_import = true` 962 /// * `@extern` with `.relocation = .pcrel` 963 /// 964 /// Such pointers are runtime values, so cannot be represented with an InternPool index. 965 /// 966 /// Uses the `ty_nav` field. 967 runtime_nav_ptr, 968 969 /// Implements @cVaArg builtin. 970 /// Uses the `ty_op` field. 971 c_va_arg, 972 /// Implements @cVaCopy builtin. 973 /// Uses the `ty_op` field. 974 c_va_copy, 975 /// Implements @cVaEnd builtin. 976 /// Uses the `un_op` field. 977 c_va_end, 978 /// Implements @cVaStart builtin. 979 /// Uses the `ty` field. 980 c_va_start, 981 982 /// Implements `.len` field for `@SpirvType(.{ .runtime_array = T })`. 983 /// Result type is always `u32`. 984 /// Uses the `ty_pl` field, payload is `StructField`. 985 spirv_runtime_array_len, 986 987 /// Implements @workItemId builtin. 988 /// Result type is always `u32` 989 /// Uses the `pl_op` field, payload is the dimension to get the work item id for. 990 /// Operand is unused and set to Ref.none 991 work_item_id, 992 /// Implements @workGroupSize builtin. 993 /// Result type is always `u32` 994 /// Uses the `pl_op` field, payload is the dimension to get the work group size for. 995 /// Operand is unused and set to Ref.none 996 work_group_size, 997 /// Implements @workGroupId builtin. 998 /// Result type is always `u32` 999 /// Uses the `pl_op` field, payload is the dimension to get the work group id for. 1000 /// Operand is unused and set to Ref.none 1001 work_group_id, 1002 1003 // The remaining instructions are not emitted by Sema. They are only emitted by `Legalize`, 1004 // depending on the enabled features. As such, backends can consider them `unreachable` if 1005 // they do not enable the relevant legalizations. 1006 1007 /// Given a pointer to a vector, a runtime-known index, and a scalar value, store the value 1008 /// into the vector at the given index. Zig does not support this operation, but `Legalize` 1009 /// may emit it when scalarizing vector operations. 1010 /// 1011 /// Uses the `pl_op` field with payload `Bin`. `operand` is the vector pointer. `lhs` is the 1012 /// element index of type `usize`. `rhs` is the element value. Result is always void. 1013 legalize_vec_store_elem, 1014 /// Given a vector value and a runtime-known index, return the element value at that index. 1015 /// This instruction is similar to `array_elem_val`; the only difference is that the index 1016 /// here is runtime-known, which is usually not allowed for vectors. `Legalize` may emit 1017 /// this instruction when scalarizing vector operations. 1018 /// 1019 /// Uses the `bin_op` field. `lhs` is the vector value. `rhs` is the element index. Result 1020 /// type is the vector element type. 1021 legalize_vec_elem_val, 1022 1023 /// A call to a compiler_rt routine. `Legalize` may emit this instruction if any soft-float 1024 /// legalizations are enabled. 1025 /// 1026 /// Uses the `legalize_compiler_rt_call` union field. 1027 /// 1028 /// The name of the function symbol is given by `func.name(target)`. 1029 /// The calling convention is given by `func.@"callconv"(target)`. 1030 /// The return type (and hence the result type of this instruction) is `func.returnType()`. 1031 /// The parameter types are the types of the arguments given in `Air.Call`. 1032 /// 1033 /// See `unwrapCompilerRtCall` for a way to load this tag's data. 1034 legalize_compiler_rt_call, 1035 1036 pub fn fromCmpOp(op: std.math.CompareOperator, optimized: bool) Tag { 1037 switch (op) { 1038 .lt => return if (optimized) .cmp_lt_optimized else .cmp_lt, 1039 .lte => return if (optimized) .cmp_lte_optimized else .cmp_lte, 1040 .eq => return if (optimized) .cmp_eq_optimized else .cmp_eq, 1041 .gte => return if (optimized) .cmp_gte_optimized else .cmp_gte, 1042 .gt => return if (optimized) .cmp_gt_optimized else .cmp_gt, 1043 .neq => return if (optimized) .cmp_neq_optimized else .cmp_neq, 1044 } 1045 } 1046 1047 pub fn toCmpOp(tag: Tag) ?std.math.CompareOperator { 1048 return switch (tag) { 1049 .cmp_lt, .cmp_lt_optimized => .lt, 1050 .cmp_lte, .cmp_lte_optimized => .lte, 1051 .cmp_eq, .cmp_eq_optimized => .eq, 1052 .cmp_gte, .cmp_gte_optimized => .gte, 1053 .cmp_gt, .cmp_gt_optimized => .gt, 1054 .cmp_neq, .cmp_neq_optimized => .neq, 1055 else => null, 1056 }; 1057 } 1058 }; 1059 1060 /// The position of an AIR instruction within the `Air` instructions array. 1061 pub const Index = enum(u32) { 1062 _, 1063 1064 pub fn unwrap(index: Index) union(enum) { ref: Inst.Ref, target: u31 } { 1065 const low_index: u31 = @truncate(@backingInt(index)); 1066 return switch (@as(u1, @intCast(@backingInt(index) >> 31))) { 1067 0 => .{ .ref = @fromBackingInt(@intCast(@as(u32, 1 << 31) | low_index)) }, 1068 1 => .{ .target = low_index }, 1069 }; 1070 } 1071 1072 pub fn toRef(index: Index) Inst.Ref { 1073 return index.unwrap().ref; 1074 } 1075 1076 pub fn fromTargetIndex(index: u31) Index { 1077 return @fromBackingInt(@intCast((1 << 31) | @as(u32, index))); 1078 } 1079 1080 pub fn toTargetIndex(index: Index) u31 { 1081 return index.unwrap().target; 1082 } 1083 1084 pub fn format(index: Index, w: *std.Io.Writer) std.Io.Writer.Error!void { 1085 try w.writeByte('%'); 1086 switch (index.unwrap()) { 1087 .ref => {}, 1088 .target => try w.writeByte('t'), 1089 } 1090 try w.print("{d}", .{@as(u31, @truncate(@backingInt(index)))}); 1091 } 1092 }; 1093 1094 /// Either a reference to a value stored in the InternPool, or a reference to an AIR instruction. 1095 /// The most-significant bit of the value is a tag bit. This bit is 1 if the value represents an 1096 /// instruction index and 0 if it represents an InternPool index. 1097 /// 1098 /// The ref `none` is an exception: it has the tag bit set but refers to the InternPool. 1099 pub const Ref = enum(u32) { 1100 u0_type = @backingInt(InternPool.Index.u0_type), 1101 u1_type = @backingInt(InternPool.Index.u1_type), 1102 u8_type = @backingInt(InternPool.Index.u8_type), 1103 i8_type = @backingInt(InternPool.Index.i8_type), 1104 u16_type = @backingInt(InternPool.Index.u16_type), 1105 i16_type = @backingInt(InternPool.Index.i16_type), 1106 u29_type = @backingInt(InternPool.Index.u29_type), 1107 u32_type = @backingInt(InternPool.Index.u32_type), 1108 i32_type = @backingInt(InternPool.Index.i32_type), 1109 u64_type = @backingInt(InternPool.Index.u64_type), 1110 i64_type = @backingInt(InternPool.Index.i64_type), 1111 u80_type = @backingInt(InternPool.Index.u80_type), 1112 u128_type = @backingInt(InternPool.Index.u128_type), 1113 i128_type = @backingInt(InternPool.Index.i128_type), 1114 u256_type = @backingInt(InternPool.Index.u256_type), 1115 usize_type = @backingInt(InternPool.Index.usize_type), 1116 isize_type = @backingInt(InternPool.Index.isize_type), 1117 c_char_type = @backingInt(InternPool.Index.c_char_type), 1118 c_short_type = @backingInt(InternPool.Index.c_short_type), 1119 c_ushort_type = @backingInt(InternPool.Index.c_ushort_type), 1120 c_int_type = @backingInt(InternPool.Index.c_int_type), 1121 c_uint_type = @backingInt(InternPool.Index.c_uint_type), 1122 c_long_type = @backingInt(InternPool.Index.c_long_type), 1123 c_ulong_type = @backingInt(InternPool.Index.c_ulong_type), 1124 c_longlong_type = @backingInt(InternPool.Index.c_longlong_type), 1125 c_ulonglong_type = @backingInt(InternPool.Index.c_ulonglong_type), 1126 c_longdouble_type = @backingInt(InternPool.Index.c_longdouble_type), 1127 f16_type = @backingInt(InternPool.Index.f16_type), 1128 f32_type = @backingInt(InternPool.Index.f32_type), 1129 f64_type = @backingInt(InternPool.Index.f64_type), 1130 f80_type = @backingInt(InternPool.Index.f80_type), 1131 f128_type = @backingInt(InternPool.Index.f128_type), 1132 anyopaque_type = @backingInt(InternPool.Index.anyopaque_type), 1133 bool_type = @backingInt(InternPool.Index.bool_type), 1134 void_type = @backingInt(InternPool.Index.void_type), 1135 type_type = @backingInt(InternPool.Index.type_type), 1136 anyerror_type = @backingInt(InternPool.Index.anyerror_type), 1137 comptime_int_type = @backingInt(InternPool.Index.comptime_int_type), 1138 comptime_float_type = @backingInt(InternPool.Index.comptime_float_type), 1139 noreturn_type = @backingInt(InternPool.Index.noreturn_type), 1140 anyframe_type = @backingInt(InternPool.Index.anyframe_type), 1141 null_type = @backingInt(InternPool.Index.null_type), 1142 undefined_type = @backingInt(InternPool.Index.undefined_type), 1143 enum_literal_type = @backingInt(InternPool.Index.enum_literal_type), 1144 ptr_usize_type = @backingInt(InternPool.Index.ptr_usize_type), 1145 ptr_const_comptime_int_type = @backingInt(InternPool.Index.ptr_const_comptime_int_type), 1146 manyptr_u8_type = @backingInt(InternPool.Index.manyptr_u8_type), 1147 manyptr_const_u8_type = @backingInt(InternPool.Index.manyptr_const_u8_type), 1148 manyptr_const_u8_sentinel_0_type = @backingInt(InternPool.Index.manyptr_const_u8_sentinel_0_type), 1149 slice_const_u8_type = @backingInt(InternPool.Index.slice_const_u8_type), 1150 slice_const_u8_sentinel_0_type = @backingInt(InternPool.Index.slice_const_u8_sentinel_0_type), 1151 manyptr_const_slice_const_u8_type = @backingInt(InternPool.Index.manyptr_const_slice_const_u8_type), 1152 slice_const_slice_const_u8_type = @backingInt(InternPool.Index.slice_const_slice_const_u8_type), 1153 optional_type_type = @backingInt(InternPool.Index.optional_type_type), 1154 manyptr_const_type_type = @backingInt(InternPool.Index.manyptr_const_type_type), 1155 slice_const_type_type = @backingInt(InternPool.Index.slice_const_type_type), 1156 vector_8_i8_type = @backingInt(InternPool.Index.vector_8_i8_type), 1157 vector_16_i8_type = @backingInt(InternPool.Index.vector_16_i8_type), 1158 vector_32_i8_type = @backingInt(InternPool.Index.vector_32_i8_type), 1159 vector_64_i8_type = @backingInt(InternPool.Index.vector_64_i8_type), 1160 vector_1_u8_type = @backingInt(InternPool.Index.vector_1_u8_type), 1161 vector_2_u8_type = @backingInt(InternPool.Index.vector_2_u8_type), 1162 vector_4_u8_type = @backingInt(InternPool.Index.vector_4_u8_type), 1163 vector_8_u8_type = @backingInt(InternPool.Index.vector_8_u8_type), 1164 vector_16_u8_type = @backingInt(InternPool.Index.vector_16_u8_type), 1165 vector_32_u8_type = @backingInt(InternPool.Index.vector_32_u8_type), 1166 vector_64_u8_type = @backingInt(InternPool.Index.vector_64_u8_type), 1167 vector_2_i16_type = @backingInt(InternPool.Index.vector_2_i16_type), 1168 vector_4_i16_type = @backingInt(InternPool.Index.vector_4_i16_type), 1169 vector_8_i16_type = @backingInt(InternPool.Index.vector_8_i16_type), 1170 vector_16_i16_type = @backingInt(InternPool.Index.vector_16_i16_type), 1171 vector_32_i16_type = @backingInt(InternPool.Index.vector_32_i16_type), 1172 vector_4_u16_type = @backingInt(InternPool.Index.vector_4_u16_type), 1173 vector_8_u16_type = @backingInt(InternPool.Index.vector_8_u16_type), 1174 vector_16_u16_type = @backingInt(InternPool.Index.vector_16_u16_type), 1175 vector_32_u16_type = @backingInt(InternPool.Index.vector_32_u16_type), 1176 vector_2_i32_type = @backingInt(InternPool.Index.vector_2_i32_type), 1177 vector_4_i32_type = @backingInt(InternPool.Index.vector_4_i32_type), 1178 vector_8_i32_type = @backingInt(InternPool.Index.vector_8_i32_type), 1179 vector_16_i32_type = @backingInt(InternPool.Index.vector_16_i32_type), 1180 vector_4_u32_type = @backingInt(InternPool.Index.vector_4_u32_type), 1181 vector_8_u32_type = @backingInt(InternPool.Index.vector_8_u32_type), 1182 vector_16_u32_type = @backingInt(InternPool.Index.vector_16_u32_type), 1183 vector_2_i64_type = @backingInt(InternPool.Index.vector_2_i64_type), 1184 vector_4_i64_type = @backingInt(InternPool.Index.vector_4_i64_type), 1185 vector_8_i64_type = @backingInt(InternPool.Index.vector_8_i64_type), 1186 vector_2_u64_type = @backingInt(InternPool.Index.vector_2_u64_type), 1187 vector_4_u64_type = @backingInt(InternPool.Index.vector_4_u64_type), 1188 vector_8_u64_type = @backingInt(InternPool.Index.vector_8_u64_type), 1189 vector_1_u128_type = @backingInt(InternPool.Index.vector_1_u128_type), 1190 vector_2_u128_type = @backingInt(InternPool.Index.vector_2_u128_type), 1191 vector_1_u256_type = @backingInt(InternPool.Index.vector_1_u256_type), 1192 vector_4_f16_type = @backingInt(InternPool.Index.vector_4_f16_type), 1193 vector_8_f16_type = @backingInt(InternPool.Index.vector_8_f16_type), 1194 vector_16_f16_type = @backingInt(InternPool.Index.vector_16_f16_type), 1195 vector_32_f16_type = @backingInt(InternPool.Index.vector_32_f16_type), 1196 vector_2_f32_type = @backingInt(InternPool.Index.vector_2_f32_type), 1197 vector_4_f32_type = @backingInt(InternPool.Index.vector_4_f32_type), 1198 vector_8_f32_type = @backingInt(InternPool.Index.vector_8_f32_type), 1199 vector_16_f32_type = @backingInt(InternPool.Index.vector_16_f32_type), 1200 vector_2_f64_type = @backingInt(InternPool.Index.vector_2_f64_type), 1201 vector_4_f64_type = @backingInt(InternPool.Index.vector_4_f64_type), 1202 vector_8_f64_type = @backingInt(InternPool.Index.vector_8_f64_type), 1203 optional_noreturn_type = @backingInt(InternPool.Index.optional_noreturn_type), 1204 anyerror_void_error_union_type = @backingInt(InternPool.Index.anyerror_void_error_union_type), 1205 adhoc_inferred_error_set_type = @backingInt(InternPool.Index.adhoc_inferred_error_set_type), 1206 generic_poison_type = @backingInt(InternPool.Index.generic_poison_type), 1207 empty_tuple_type = @backingInt(InternPool.Index.empty_tuple_type), 1208 undef = @backingInt(InternPool.Index.undef), 1209 undef_bool = @backingInt(InternPool.Index.undef_bool), 1210 undef_usize = @backingInt(InternPool.Index.undef_usize), 1211 undef_u1 = @backingInt(InternPool.Index.undef_u1), 1212 zero = @backingInt(InternPool.Index.zero), 1213 zero_usize = @backingInt(InternPool.Index.zero_usize), 1214 zero_u1 = @backingInt(InternPool.Index.zero_u1), 1215 zero_u8 = @backingInt(InternPool.Index.zero_u8), 1216 one = @backingInt(InternPool.Index.one), 1217 one_usize = @backingInt(InternPool.Index.one_usize), 1218 one_u1 = @backingInt(InternPool.Index.one_u1), 1219 one_u8 = @backingInt(InternPool.Index.one_u8), 1220 four_u8 = @backingInt(InternPool.Index.four_u8), 1221 negative_one = @backingInt(InternPool.Index.negative_one), 1222 void_value = @backingInt(InternPool.Index.void_value), 1223 unreachable_value = @backingInt(InternPool.Index.unreachable_value), 1224 null_value = @backingInt(InternPool.Index.null_value), 1225 bool_true = @backingInt(InternPool.Index.bool_true), 1226 bool_false = @backingInt(InternPool.Index.bool_false), 1227 empty_tuple = @backingInt(InternPool.Index.empty_tuple), 1228 1229 /// This Ref does not correspond to any AIR instruction or constant 1230 /// value and may instead be used as a sentinel to indicate null. 1231 none = @backingInt(InternPool.Index.none), 1232 _, 1233 1234 pub fn toInterned(ref: Ref) ?InternPool.Index { 1235 assert(ref != .none); 1236 return ref.toInternedAllowNone(); 1237 } 1238 1239 pub fn toInternedAllowNone(ref: Ref) ?InternPool.Index { 1240 return switch (ref) { 1241 .none => .none, 1242 else => if (@backingInt(ref) >> 31 == 0) 1243 @fromBackingInt(@intCast(@as(u31, @truncate(@backingInt(ref))))) 1244 else 1245 null, 1246 }; 1247 } 1248 1249 pub fn toIndex(ref: Ref) ?Index { 1250 assert(ref != .none); 1251 return ref.toIndexAllowNone(); 1252 } 1253 1254 pub fn toIndexAllowNone(ref: Ref) ?Index { 1255 return switch (ref) { 1256 .none => null, 1257 else => if (@backingInt(ref) >> 31 != 0) 1258 @fromBackingInt(@intCast(@as(u31, @truncate(@backingInt(ref))))) 1259 else 1260 null, 1261 }; 1262 } 1263 1264 pub fn toType(ref: Ref) Type { 1265 return .fromInterned(ref.toInterned().?); 1266 } 1267 1268 pub fn fromIntern(ip_index: InternPool.Index) Ref { 1269 return switch (ip_index) { 1270 .none => .none, 1271 else => { 1272 assert(@backingInt(ip_index) >> 31 == 0); 1273 return @fromBackingInt(@intCast(@as(u31, @intCast(@backingInt(ip_index))))); 1274 }, 1275 }; 1276 } 1277 1278 pub fn fromValue(v: Value) Ref { 1279 return .fromIntern(v.toIntern()); 1280 } 1281 1282 pub fn fromType(t: Type) Ref { 1283 return .fromIntern(t.toIntern()); 1284 } 1285 }; 1286 1287 /// All instructions have an 8-byte payload, which is contained within 1288 /// this union. `Tag` determines which union field is active, as well as 1289 /// how to interpret the data within. 1290 pub const Data = union { 1291 no_op: void, 1292 un_op: Ref, 1293 1294 bin_op: struct { 1295 lhs: Ref, 1296 rhs: Ref, 1297 }, 1298 ty: Type, 1299 arg: struct { 1300 ty: Type, 1301 zir_param_index: u32, 1302 }, 1303 ty_op: struct { 1304 ty: Type, 1305 operand: Ref, 1306 }, 1307 ty_pl: struct { 1308 ty: Type, 1309 // Index into a different array. 1310 payload: u32, 1311 }, 1312 br: struct { 1313 block_inst: Index, 1314 operand: Ref, 1315 }, 1316 repeat: struct { 1317 loop_inst: Index, 1318 }, 1319 pl_op: struct { 1320 operand: Ref, 1321 payload: u32, 1322 }, 1323 dbg_stmt: struct { 1324 line: u32, 1325 column: u32, 1326 }, 1327 atomic_load: struct { 1328 ptr: Ref, 1329 order: std.lang.AtomicOrder, 1330 }, 1331 prefetch: struct { 1332 ptr: Ref, 1333 rw: std.lang.PrefetchOptions.Rw, 1334 locality: u2, 1335 cache: std.lang.PrefetchOptions.Cache, 1336 }, 1337 reduce: struct { 1338 operand: Ref, 1339 operation: std.lang.ReduceOp, 1340 }, 1341 ty_nav: struct { 1342 ty: Type, 1343 nav: InternPool.Nav.Index, 1344 }, 1345 legalize_compiler_rt_call: struct { 1346 func: CompilerRtFunc, 1347 /// Index into `extra` to a payload of type `Call`. 1348 payload: u32, 1349 }, 1350 inferred_alloc_comptime: InferredAllocComptime, 1351 inferred_alloc: InferredAlloc, 1352 1353 pub const InferredAllocComptime = struct { 1354 alignment: InternPool.Alignment, 1355 is_const: bool, 1356 /// This is `undefined` until we encounter a `store_to_inferred_alloc`, 1357 /// at which point the pointer is created and stored here. 1358 ptr: InternPool.Index, 1359 }; 1360 1361 pub const InferredAlloc = struct { 1362 alignment: InternPool.Alignment, 1363 is_const: bool, 1364 }; 1365 1366 // Make sure we don't accidentally add a field to make this union 1367 // bigger than expected. Note that in safety builds, Zig is allowed 1368 // to insert a secret field for safety checks. 1369 comptime { 1370 if (!std.debug.runtime_safety) { 1371 assert(@sizeOf(Data) == 8); 1372 } 1373 } 1374 }; 1375 }; 1376 1377 /// Trailing is a list of instruction indexes for every `body_len`. 1378 pub const Block = struct { 1379 body_len: u32, 1380 }; 1381 1382 /// Trailing is a list of instruction indexes for every `body_len`. 1383 pub const DbgInlineBlock = struct { 1384 func: InternPool.Index, 1385 body_len: u32, 1386 }; 1387 1388 /// Trailing is a list of `Inst.Ref` for every `args_len`. 1389 pub const Call = struct { 1390 args_len: u32, 1391 }; 1392 1393 /// This data is stored inside extra, with two sets of trailing `Inst.Ref`: 1394 /// * 0. the then body, according to `then_body_len`. 1395 /// * 1. the else body, according to `else_body_len`. 1396 pub const CondBr = struct { 1397 then_body_len: u32, 1398 else_body_len: u32, 1399 branch_hints: BranchHints, 1400 pub const BranchHints = packed struct(u32) { 1401 true: std.lang.BranchHint = .none, 1402 false: std.lang.BranchHint = .none, 1403 then_cov: CoveragePoint = .none, 1404 else_cov: CoveragePoint = .none, 1405 _: u24 = 0, 1406 }; 1407 }; 1408 1409 /// Trailing: 1410 /// * 0. `BranchHint` for each `cases_len + 1`. bit-packed into `u32` 1411 /// elems such that each `u32` contains up to 10x `BranchHint`. 1412 /// LSBs are first case. Final hint is `else`. 1413 /// * 1. `Case` for each `cases_len` 1414 /// * 2. the else body, according to `else_body_len`. 1415 pub const SwitchBr = struct { 1416 cases_len: u32, 1417 else_body_len: u32, 1418 1419 /// Trailing: 1420 /// * item: Inst.Ref // for each `items_len` 1421 /// * { range_start: Inst.Ref, range_end: Inst.Ref } // for each `ranges_len` 1422 /// * body_inst: Inst.Index // for each `body_len` 1423 pub const Case = struct { 1424 items_len: u32, 1425 ranges_len: u32, 1426 body_len: u32, 1427 }; 1428 }; 1429 1430 /// This data is stored inside extra. Trailing: 1431 /// 0. body: Inst.Index // for each body_len 1432 pub const Try = struct { 1433 body_len: u32, 1434 }; 1435 1436 /// This data is stored inside extra. Trailing: 1437 /// 0. body: Inst.Index // for each body_len 1438 pub const TryPtr = struct { 1439 ptr: Inst.Ref, 1440 body_len: u32, 1441 }; 1442 1443 pub const StructField = struct { 1444 /// Whether this is a pointer or byval is determined by the AIR tag. 1445 struct_operand: Inst.Ref, 1446 field_index: u32, 1447 }; 1448 1449 pub const Bin = struct { 1450 lhs: Inst.Ref, 1451 rhs: Inst.Ref, 1452 }; 1453 1454 pub const FieldParentPtr = struct { 1455 field_ptr: Inst.Ref, 1456 field_index: u32, 1457 }; 1458 1459 pub const VectorCmp = struct { 1460 lhs: Inst.Ref, 1461 rhs: Inst.Ref, 1462 op: u32, 1463 1464 pub fn compareOperator(self: VectorCmp) std.math.CompareOperator { 1465 return @fromBackingInt(@intCast(@as(u3, @intCast(self.op)))); 1466 } 1467 1468 pub fn encodeOp(compare_operator: std.math.CompareOperator) u32 { 1469 return @backingInt(compare_operator); 1470 } 1471 }; 1472 1473 /// Used by `Inst.Tag.shuffle_one`. Represents a mask element which either indexes into a 1474 /// runtime-known vector, or is a comptime-known value. 1475 pub const ShuffleOneMask = packed struct(u32) { 1476 index: u31, 1477 kind: enum(u1) { elem, value }, 1478 pub fn elem(idx: u32) ShuffleOneMask { 1479 return .{ .index = @intCast(idx), .kind = .elem }; 1480 } 1481 pub fn value(val: Value) ShuffleOneMask { 1482 return .{ .index = @intCast(@backingInt(val.toIntern())), .kind = .value }; 1483 } 1484 pub const Unwrapped = union(enum) { 1485 /// The resulting element is this index into the runtime vector. 1486 elem: u32, 1487 /// The resulting element is this comptime-known value. 1488 /// It is correctly typed. It might be `undefined`. 1489 value: InternPool.Index, 1490 }; 1491 pub fn unwrap(raw: ShuffleOneMask) Unwrapped { 1492 return switch (raw.kind) { 1493 .elem => .{ .elem = raw.index }, 1494 .value => .{ .value = @fromBackingInt(@intCast(raw.index)) }, 1495 }; 1496 } 1497 }; 1498 1499 /// Used by `Inst.Tag.shuffle_two`. Represents a mask element which either indexes into one 1500 /// of two runtime-known vectors, or is undefined. 1501 pub const ShuffleTwoMask = enum(u32) { 1502 undef = std.math.maxInt(u32), 1503 _, 1504 pub fn aElem(idx: u32) ShuffleTwoMask { 1505 return @fromBackingInt(@intCast(idx << 1)); 1506 } 1507 pub fn bElem(idx: u32) ShuffleTwoMask { 1508 return @fromBackingInt(@intCast(idx << 1 | 1)); 1509 } 1510 pub const Unwrapped = union(enum) { 1511 /// The resulting element is this index into the first runtime vector. 1512 a_elem: u32, 1513 /// The resulting element is this index into the second runtime vector. 1514 b_elem: u32, 1515 /// The resulting element is `undefined`. 1516 undef, 1517 }; 1518 pub fn unwrap(raw: ShuffleTwoMask) Unwrapped { 1519 switch (raw) { 1520 .undef => return .undef, 1521 _ => {}, 1522 } 1523 const x = @backingInt(raw); 1524 return switch (@as(u1, @truncate(x))) { 1525 0 => .{ .a_elem = x >> 1 }, 1526 1 => .{ .b_elem = x >> 1 }, 1527 }; 1528 } 1529 }; 1530 1531 /// Trailing: 1532 /// 0. `Inst.Ref` for every outputs_len 1533 /// 1. `Inst.Ref` for every inputs_len 1534 /// 2. A number of u32 elements follow according to the equation `@divCeil(source_len, 4)`. 1535 /// Memory starting at this position is reinterpreted as the source bytes. 1536 /// 3. for every outputs_len 1537 /// - constraint: memory at this position is reinterpreted as a null 1538 /// terminated string. 1539 /// - name: memory at this position is reinterpreted as a null 1540 /// terminated string. pad to the next u32 after the null byte. 1541 /// 4. for every inputs_len 1542 /// - constraint: memory at this position is reinterpreted as a null 1543 /// terminated string. 1544 /// - name: memory at this position is reinterpreted as a null 1545 /// terminated string. pad to the next u32 after the null byte. 1546 pub const Asm = struct { 1547 /// Length of the assembly source in bytes. 1548 source_len: u32, 1549 inputs_len: u32, 1550 /// A comptime `std.lang.assembly.Clobbers` value for the target architecture. 1551 clobbers: InternPool.Index, 1552 flags: Flags, 1553 1554 pub const Flags = packed struct(u32) { 1555 outputs_len: u31, 1556 is_volatile: bool, 1557 }; 1558 }; 1559 1560 pub const Cmpxchg = struct { 1561 ptr: Inst.Ref, 1562 expected_value: Inst.Ref, 1563 new_value: Inst.Ref, 1564 /// 0b00000000000000000000000000000XXX - success_order 1565 /// 0b00000000000000000000000000XXX000 - failure_order 1566 flags: u32, 1567 1568 pub fn successOrder(self: Cmpxchg) std.lang.AtomicOrder { 1569 return @fromBackingInt(@intCast(@as(u3, @truncate(self.flags)))); 1570 } 1571 1572 pub fn failureOrder(self: Cmpxchg) std.lang.AtomicOrder { 1573 return @fromBackingInt(@intCast(@as(u3, @intCast(self.flags >> 3)))); 1574 } 1575 }; 1576 1577 pub const AtomicRmw = struct { 1578 operand: Inst.Ref, 1579 /// 0b00000000000000000000000000000XXX - ordering 1580 /// 0b0000000000000000000000000XXXX000 - op 1581 flags: u32, 1582 1583 pub fn ordering(self: AtomicRmw) std.lang.AtomicOrder { 1584 return @fromBackingInt(@intCast(@as(u3, @truncate(self.flags)))); 1585 } 1586 1587 pub fn op(self: AtomicRmw) std.lang.AtomicRmwOp { 1588 return @fromBackingInt(@intCast(@as(u4, @intCast(self.flags >> 3)))); 1589 } 1590 }; 1591 1592 pub const UnionInit = struct { 1593 field_index: u32, 1594 init: Inst.Ref, 1595 }; 1596 1597 pub fn getMainBody(air: Air) []const Air.Inst.Index { 1598 const body_index = air.extra.items[@backingInt(ExtraIndex.main_block)]; 1599 const extra = air.extraData(Block, body_index); 1600 return @ptrCast(air.extra.items[extra.end..][0..extra.data.body_len]); 1601 } 1602 1603 pub fn typeOf(air: *const Air, inst: Air.Inst.Ref, ip: *const InternPool) Type { 1604 if (inst.toInterned()) |ip_index| { 1605 return .fromInterned(ip.typeOf(ip_index)); 1606 } else { 1607 return air.typeOfIndex(inst.toIndex().?, ip); 1608 } 1609 } 1610 1611 pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool) Type { 1612 const datas = air.instructions.items(.data); 1613 switch (air.instructions.items(.tag)[@backingInt(inst)]) { 1614 .add, 1615 .add_safe, 1616 .add_wrap, 1617 .add_sat, 1618 .sub, 1619 .sub_safe, 1620 .sub_wrap, 1621 .sub_sat, 1622 .mul, 1623 .mul_safe, 1624 .mul_wrap, 1625 .mul_sat, 1626 .div_float, 1627 .div_trunc, 1628 .div_floor, 1629 .div_ceil, 1630 .div_exact, 1631 .rem, 1632 .mod, 1633 .bit_and, 1634 .bit_or, 1635 .xor, 1636 .shr, 1637 .shr_exact, 1638 .shl, 1639 .shl_exact, 1640 .shl_sat, 1641 .min, 1642 .max, 1643 .add_optimized, 1644 .sub_optimized, 1645 .mul_optimized, 1646 .div_float_optimized, 1647 .div_trunc_optimized, 1648 .div_floor_optimized, 1649 .div_ceil_optimized, 1650 .div_exact_optimized, 1651 .rem_optimized, 1652 .mod_optimized, 1653 => return air.typeOf(datas[@backingInt(inst)].bin_op.lhs, ip), 1654 1655 .sqrt, 1656 .sin, 1657 .cos, 1658 .tan, 1659 .exp, 1660 .exp2, 1661 .log, 1662 .log2, 1663 .log10, 1664 .floor, 1665 .ceil, 1666 .round, 1667 .trunc_float, 1668 .neg, 1669 .neg_optimized, 1670 => return air.typeOf(datas[@backingInt(inst)].un_op, ip), 1671 1672 .cmp_lt, 1673 .cmp_lte, 1674 .cmp_eq, 1675 .cmp_gte, 1676 .cmp_gt, 1677 .cmp_neq, 1678 .cmp_lt_optimized, 1679 .cmp_lte_optimized, 1680 .cmp_eq_optimized, 1681 .cmp_gte_optimized, 1682 .cmp_gt_optimized, 1683 .cmp_neq_optimized, 1684 .cmp_lte_errors_len, 1685 .is_null, 1686 .is_non_null, 1687 .is_null_ptr, 1688 .is_non_null_ptr, 1689 .is_err, 1690 .is_non_err, 1691 .is_err_ptr, 1692 .is_non_err_ptr, 1693 .is_named_enum_value, 1694 .error_set_has_value, 1695 => return .bool, 1696 1697 .alloc, 1698 .ret_ptr, 1699 .err_return_trace, 1700 .c_va_start, 1701 => return datas[@backingInt(inst)].ty, 1702 1703 .arg => return datas[@backingInt(inst)].arg.ty, 1704 1705 .assembly, 1706 .block, 1707 .dbg_inline_block, 1708 .struct_field_ptr, 1709 .agg_field_val, 1710 .slice_elem_ptr, 1711 .ptr_elem_ptr, 1712 .cmpxchg_weak, 1713 .cmpxchg_strong, 1714 .slice, 1715 .aggregate_init, 1716 .union_init, 1717 .field_parent_ptr, 1718 .cmp_vector, 1719 .cmp_vector_optimized, 1720 .add_with_overflow, 1721 .sub_with_overflow, 1722 .mul_with_overflow, 1723 .shl_with_overflow, 1724 .ptr_add, 1725 .ptr_sub, 1726 .try_ptr, 1727 .try_ptr_cold, 1728 .shuffle_one, 1729 .shuffle_two, 1730 => return datas[@backingInt(inst)].ty_pl.ty, 1731 1732 .not, 1733 .bit_cast, 1734 .bit_cast_safe, 1735 .ptr_cast, 1736 .ptr_from_int, 1737 .int_from_ptr, 1738 .error_cast, 1739 .error_from_int, 1740 .int_from_error, 1741 .union_from_enum, 1742 .load, 1743 .fpext, 1744 .fptrunc, 1745 .int_cast, 1746 .int_cast_safe, 1747 .trunc, 1748 .optional_payload, 1749 .optional_payload_ptr, 1750 .optional_payload_ptr_set, 1751 .errunion_payload_ptr_set, 1752 .wrap_optional, 1753 .unwrap_errunion_payload, 1754 .unwrap_errunion_err, 1755 .unwrap_errunion_payload_ptr, 1756 .unwrap_errunion_err_ptr, 1757 .wrap_errunion_payload, 1758 .wrap_errunion_err, 1759 .slice_ptr, 1760 .ptr_slice_len_ptr, 1761 .ptr_slice_ptr_ptr, 1762 .struct_field_ptr_index_0, 1763 .struct_field_ptr_index_1, 1764 .struct_field_ptr_index_2, 1765 .struct_field_ptr_index_3, 1766 .array_to_slice, 1767 .array_to_vector, 1768 .int_from_float, 1769 .int_from_float_optimized, 1770 .int_from_float_safe, 1771 .int_from_float_optimized_safe, 1772 .float_from_int, 1773 .splat, 1774 .get_union_tag, 1775 .clz, 1776 .ctz, 1777 .popcount, 1778 .byte_swap, 1779 .bit_reverse, 1780 .addrspace_cast, 1781 .c_va_arg, 1782 .c_va_copy, 1783 .abs, 1784 => return datas[@backingInt(inst)].ty_op.ty, 1785 1786 .loop, 1787 .repeat, 1788 .br, 1789 .cond_br, 1790 .switch_br, 1791 .loop_switch_br, 1792 .switch_dispatch, 1793 .ret, 1794 .ret_safe, 1795 .ret_load, 1796 .unreach, 1797 .trap, 1798 => return .noreturn, 1799 1800 .breakpoint, 1801 .dbg_stmt, 1802 .dbg_empty_stmt, 1803 .dbg_var_ptr, 1804 .dbg_var_val, 1805 .dbg_arg_inline, 1806 .store, 1807 .store_safe, 1808 .atomic_store_unordered, 1809 .atomic_store_monotonic, 1810 .atomic_store_release, 1811 .atomic_store_seq_cst, 1812 .memset, 1813 .memset_safe, 1814 .memcpy, 1815 .memmove, 1816 .set_union_tag, 1817 .prefetch, 1818 .set_err_return_trace, 1819 .c_va_end, 1820 .legalize_vec_store_elem, 1821 => return .void, 1822 1823 .slice_len, 1824 .ret_addr, 1825 .frame_addr, 1826 .save_err_return_trace_index, 1827 => return .usize, 1828 1829 .wasm_memory_grow => return .isize, 1830 .wasm_memory_size => return .usize, 1831 1832 .tag_name, .error_name => return .slice_const_u8_sentinel_0, 1833 1834 .call, .call_always_tail, .call_never_tail, .call_never_inline => { 1835 const callee_ty = air.typeOf(datas[@backingInt(inst)].pl_op.operand, ip); 1836 return .fromInterned(ip.funcTypeReturnType(callee_ty.toIntern())); 1837 }, 1838 1839 .slice_elem_val, .ptr_elem_val, .array_elem_val, .legalize_vec_elem_val => { 1840 const ptr_ty = air.typeOf(datas[@backingInt(inst)].bin_op.lhs, ip); 1841 return ptr_ty.childTypeIp(ip); 1842 }, 1843 .atomic_load => { 1844 const ptr_ty = air.typeOf(datas[@backingInt(inst)].atomic_load.ptr, ip); 1845 return ptr_ty.childTypeIp(ip); 1846 }, 1847 .atomic_rmw => { 1848 const ptr_ty = air.typeOf(datas[@backingInt(inst)].pl_op.operand, ip); 1849 return ptr_ty.childTypeIp(ip); 1850 }, 1851 1852 .reduce, .reduce_optimized => { 1853 const operand_ty = air.typeOf(datas[@backingInt(inst)].reduce.operand, ip); 1854 return .fromInterned(ip.indexToKey(operand_ty.ip_index).vector_type.child); 1855 }, 1856 1857 .mul_add => return air.typeOf(datas[@backingInt(inst)].pl_op.operand, ip), 1858 .select => { 1859 const extra = air.extraData(Air.Bin, datas[@backingInt(inst)].pl_op.payload).data; 1860 return air.typeOf(extra.lhs, ip); 1861 }, 1862 1863 .@"try", .try_cold => { 1864 const err_union_ty = air.typeOf(datas[@backingInt(inst)].pl_op.operand, ip); 1865 return .fromInterned(ip.indexToKey(err_union_ty.ip_index).error_union_type.payload_type); 1866 }, 1867 1868 .runtime_nav_ptr => return datas[@backingInt(inst)].ty_nav.ty, 1869 1870 .work_item_id, 1871 .work_group_size, 1872 .work_group_id, 1873 .spirv_runtime_array_len, 1874 => return .u32, 1875 1876 .legalize_compiler_rt_call => return datas[@backingInt(inst)].legalize_compiler_rt_call.func.returnType(), 1877 1878 .inferred_alloc => unreachable, 1879 .inferred_alloc_comptime => unreachable, 1880 } 1881 } 1882 1883 /// Returns the requested data, as well as the new index which is at the start of the 1884 /// trailers for the object. 1885 pub fn extraData(air: Air, comptime T: type, index: usize) struct { data: T, end: usize } { 1886 const info = @typeInfo(T).@"struct"; 1887 var i: usize = index; 1888 var result: T = undefined; 1889 inline for (info.field_names, info.field_types) |field_name, field_type| { 1890 @field(result, field_name) = switch (field_type) { 1891 u32 => air.extra.items[i], 1892 InternPool.Index, Inst.Ref => @fromBackingInt(@intCast(air.extra.items[i])), 1893 i32, CondBr.BranchHints, Asm.Flags => @bitCast(air.extra.items[i]), 1894 else => @compileError("bad field type: " ++ @typeName(field_type)), 1895 }; 1896 i += 1; 1897 } 1898 return .{ 1899 .data = result, 1900 .end = i, 1901 }; 1902 } 1903 1904 pub fn deinit(air: *Air, gpa: std.mem.Allocator) void { 1905 air.instructions.deinit(gpa); 1906 air.extra.deinit(gpa); 1907 air.* = undefined; 1908 } 1909 1910 pub fn internedToRef(ip_index: InternPool.Index) Inst.Ref { 1911 return .fromIntern(ip_index); 1912 } 1913 1914 pub const NullTerminatedString = enum(u32) { 1915 none = std.math.maxInt(u32), 1916 _, 1917 1918 pub fn toSlice(nts: NullTerminatedString, air: Air) [:0]const u8 { 1919 if (nts == .none) return ""; 1920 const bytes = std.mem.sliceAsBytes(air.extra.items[@backingInt(nts)..]); 1921 return bytes[0..std.mem.findScalar(u8, bytes, 0).? :0]; 1922 } 1923 }; 1924 1925 /// Returns whether the given instruction must always be lowered, for instance 1926 /// because it can cause side effects. If an instruction does not need to be 1927 /// lowered, and Liveness determines its result is unused, backends should 1928 /// avoid lowering it. 1929 pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool { 1930 const data = air.instructions.items(.data)[@backingInt(inst)]; 1931 return switch (air.instructions.items(.tag)[@backingInt(inst)]) { 1932 .arg, 1933 .assembly, 1934 .block, 1935 .loop, 1936 .repeat, 1937 .br, 1938 .trap, 1939 .breakpoint, 1940 .call, 1941 .call_always_tail, 1942 .call_never_tail, 1943 .call_never_inline, 1944 .cond_br, 1945 .switch_br, 1946 .loop_switch_br, 1947 .switch_dispatch, 1948 .@"try", 1949 .try_cold, 1950 .try_ptr, 1951 .try_ptr_cold, 1952 .dbg_stmt, 1953 .dbg_empty_stmt, 1954 .dbg_inline_block, 1955 .dbg_var_ptr, 1956 .dbg_var_val, 1957 .dbg_arg_inline, 1958 .ret, 1959 .ret_safe, 1960 .ret_load, 1961 .store, 1962 .store_safe, 1963 .unreach, 1964 .optional_payload_ptr_set, 1965 .errunion_payload_ptr_set, 1966 .set_union_tag, 1967 .memset, 1968 .memset_safe, 1969 .memcpy, 1970 .memmove, 1971 .cmpxchg_weak, 1972 .cmpxchg_strong, 1973 .atomic_store_unordered, 1974 .atomic_store_monotonic, 1975 .atomic_store_release, 1976 .atomic_store_seq_cst, 1977 .atomic_rmw, 1978 .prefetch, 1979 .wasm_memory_grow, 1980 .set_err_return_trace, 1981 .c_va_arg, 1982 .c_va_copy, 1983 .c_va_end, 1984 .c_va_start, 1985 .add_safe, 1986 .sub_safe, 1987 .mul_safe, 1988 .bit_cast_safe, 1989 .int_cast_safe, 1990 .int_from_float_safe, 1991 .int_from_float_optimized_safe, 1992 .legalize_vec_store_elem, 1993 .legalize_compiler_rt_call, 1994 => true, 1995 1996 .add, 1997 .add_optimized, 1998 .add_wrap, 1999 .add_sat, 2000 .sub, 2001 .sub_optimized, 2002 .sub_wrap, 2003 .sub_sat, 2004 .mul, 2005 .mul_optimized, 2006 .mul_wrap, 2007 .mul_sat, 2008 .div_float, 2009 .div_float_optimized, 2010 .div_trunc, 2011 .div_trunc_optimized, 2012 .div_floor, 2013 .div_floor_optimized, 2014 .div_ceil, 2015 .div_ceil_optimized, 2016 .div_exact, 2017 .div_exact_optimized, 2018 .rem, 2019 .rem_optimized, 2020 .mod, 2021 .mod_optimized, 2022 .ptr_add, 2023 .ptr_sub, 2024 .max, 2025 .min, 2026 .add_with_overflow, 2027 .sub_with_overflow, 2028 .mul_with_overflow, 2029 .shl_with_overflow, 2030 .alloc, 2031 .inferred_alloc, 2032 .inferred_alloc_comptime, 2033 .ret_ptr, 2034 .bit_and, 2035 .bit_or, 2036 .shr, 2037 .shr_exact, 2038 .shl, 2039 .shl_exact, 2040 .shl_sat, 2041 .xor, 2042 .not, 2043 .bit_cast, 2044 .ptr_cast, 2045 .ptr_from_int, 2046 .int_from_ptr, 2047 .error_cast, 2048 .error_from_int, 2049 .int_from_error, 2050 .union_from_enum, 2051 .ret_addr, 2052 .frame_addr, 2053 .clz, 2054 .ctz, 2055 .popcount, 2056 .byte_swap, 2057 .bit_reverse, 2058 .sqrt, 2059 .sin, 2060 .cos, 2061 .tan, 2062 .exp, 2063 .exp2, 2064 .log, 2065 .log2, 2066 .log10, 2067 .abs, 2068 .floor, 2069 .ceil, 2070 .round, 2071 .trunc_float, 2072 .neg, 2073 .neg_optimized, 2074 .cmp_lt, 2075 .cmp_lt_optimized, 2076 .cmp_lte, 2077 .cmp_lte_optimized, 2078 .cmp_eq, 2079 .cmp_eq_optimized, 2080 .cmp_gte, 2081 .cmp_gte_optimized, 2082 .cmp_gt, 2083 .cmp_gt_optimized, 2084 .cmp_neq, 2085 .cmp_neq_optimized, 2086 .cmp_vector, 2087 .cmp_vector_optimized, 2088 .is_null, 2089 .is_non_null, 2090 .is_err, 2091 .is_non_err, 2092 .fptrunc, 2093 .fpext, 2094 .int_cast, 2095 .trunc, 2096 .optional_payload, 2097 .optional_payload_ptr, 2098 .wrap_optional, 2099 .unwrap_errunion_payload, 2100 .unwrap_errunion_err, 2101 .unwrap_errunion_payload_ptr, 2102 .wrap_errunion_payload, 2103 .wrap_errunion_err, 2104 .struct_field_ptr, 2105 .struct_field_ptr_index_0, 2106 .struct_field_ptr_index_1, 2107 .struct_field_ptr_index_2, 2108 .struct_field_ptr_index_3, 2109 .agg_field_val, 2110 .get_union_tag, 2111 .slice, 2112 .slice_len, 2113 .slice_ptr, 2114 .ptr_slice_len_ptr, 2115 .ptr_slice_ptr_ptr, 2116 .array_elem_val, 2117 .slice_elem_ptr, 2118 .ptr_elem_ptr, 2119 .array_to_slice, 2120 .array_to_vector, 2121 .int_from_float, 2122 .int_from_float_optimized, 2123 .float_from_int, 2124 .reduce, 2125 .reduce_optimized, 2126 .splat, 2127 .shuffle_one, 2128 .shuffle_two, 2129 .select, 2130 .is_named_enum_value, 2131 .tag_name, 2132 .error_name, 2133 .error_set_has_value, 2134 .aggregate_init, 2135 .union_init, 2136 .mul_add, 2137 .field_parent_ptr, 2138 .wasm_memory_size, 2139 .cmp_lte_errors_len, 2140 .err_return_trace, 2141 .addrspace_cast, 2142 .save_err_return_trace_index, 2143 .runtime_nav_ptr, 2144 .work_item_id, 2145 .work_group_size, 2146 .work_group_id, 2147 .legalize_vec_elem_val, 2148 .spirv_runtime_array_len, 2149 => false, 2150 2151 .is_non_null_ptr, .is_null_ptr, .is_non_err_ptr, .is_err_ptr => air.typeOf(data.un_op, ip).isVolatilePtrIp(ip), 2152 .load, .unwrap_errunion_err_ptr => air.typeOf(data.ty_op.operand, ip).isVolatilePtrIp(ip), 2153 .slice_elem_val, .ptr_elem_val => air.typeOf(data.bin_op.lhs, ip).isVolatilePtrIp(ip), 2154 .atomic_load => switch (data.atomic_load.order) { 2155 .unordered, .monotonic => air.typeOf(data.atomic_load.ptr, ip).isVolatilePtrIp(ip), 2156 else => true, // Stronger memory orderings have inter-thread side effects. 2157 }, 2158 }; 2159 } 2160 2161 pub const UnwrappedSwitch = struct { 2162 air: *const Air, 2163 operand: Inst.Ref, 2164 cases_len: u32, 2165 else_body_len: u32, 2166 branch_hints_start: u32, 2167 cases_start: u32, 2168 2169 /// Asserts that `case_idx < us.cases_len`. 2170 pub fn getHint(us: UnwrappedSwitch, case_idx: u32) std.lang.BranchHint { 2171 assert(case_idx < us.cases_len); 2172 return us.getHintInner(case_idx); 2173 } 2174 pub fn getElseHint(us: UnwrappedSwitch) std.lang.BranchHint { 2175 return us.getHintInner(us.cases_len); 2176 } 2177 fn getHintInner(us: UnwrappedSwitch, idx: u32) std.lang.BranchHint { 2178 const bag = us.air.extra.items[us.branch_hints_start..][idx / 10]; 2179 const bits: u3 = @truncate(bag >> @intCast(3 * (idx % 10))); 2180 return @fromBackingInt(@intCast(bits)); 2181 } 2182 2183 pub fn iterateCases(us: UnwrappedSwitch) CaseIterator { 2184 return .{ 2185 .air = us.air, 2186 .cases_len = us.cases_len, 2187 .else_body_len = us.else_body_len, 2188 .next_case = 0, 2189 .extra_index = us.cases_start, 2190 }; 2191 } 2192 pub const CaseIterator = struct { 2193 air: *const Air, 2194 cases_len: u32, 2195 else_body_len: u32, 2196 next_case: u32, 2197 extra_index: u32, 2198 2199 pub fn next(it: *CaseIterator) ?Case { 2200 if (it.next_case == it.cases_len) return null; 2201 const idx = it.next_case; 2202 it.next_case += 1; 2203 2204 const extra = it.air.extraData(SwitchBr.Case, it.extra_index); 2205 var extra_index = extra.end; 2206 const items: []const Inst.Ref = @ptrCast(it.air.extra.items[extra_index..][0..extra.data.items_len]); 2207 extra_index += items.len; 2208 // TODO: ptrcast from []const Inst.Ref to []const [2]Inst.Ref when supported 2209 const ranges_ptr: [*]const [2]Inst.Ref = @ptrCast(it.air.extra.items[extra_index..]); 2210 const ranges: []const [2]Inst.Ref = ranges_ptr[0..extra.data.ranges_len]; 2211 extra_index += ranges.len * 2; 2212 const body: []const Inst.Index = @ptrCast(it.air.extra.items[extra_index..][0..extra.data.body_len]); 2213 extra_index += body.len; 2214 it.extra_index = @intCast(extra_index); 2215 2216 return .{ 2217 .idx = idx, 2218 .items = items, 2219 .ranges = ranges, 2220 .body = body, 2221 }; 2222 } 2223 /// Only valid to call once all cases have been iterated, i.e. `next` returns `null`. 2224 /// Returns the body of the "default" (`else`) case. 2225 pub fn elseBody(it: *CaseIterator) []const Inst.Index { 2226 assert(it.next_case == it.cases_len); 2227 return @ptrCast(it.air.extra.items[it.extra_index..][0..it.else_body_len]); 2228 } 2229 pub const Case = struct { 2230 idx: u32, 2231 items: []const Inst.Ref, 2232 ranges: []const [2]Inst.Ref, 2233 body: []const Inst.Index, 2234 }; 2235 }; 2236 }; 2237 2238 pub fn unwrapSwitch(air: *const Air, switch_inst: Inst.Index) UnwrappedSwitch { 2239 const inst = air.instructions.get(@backingInt(switch_inst)); 2240 switch (inst.tag) { 2241 .switch_br, .loop_switch_br => {}, 2242 else => unreachable, // assertion failure 2243 } 2244 const pl_op = inst.data.pl_op; 2245 const extra = air.extraData(SwitchBr, pl_op.payload); 2246 const hint_bag_count = @divCeil(extra.data.cases_len + 1, 10); 2247 return .{ 2248 .air = air, 2249 .operand = pl_op.operand, 2250 .cases_len = extra.data.cases_len, 2251 .else_body_len = extra.data.else_body_len, 2252 .branch_hints_start = @intCast(extra.end), 2253 .cases_start = @intCast(extra.end + hint_bag_count), 2254 }; 2255 } 2256 2257 pub const UnwrappedDbgInlineBlock = struct { 2258 func: InternPool.Index, 2259 body: []const Inst.Index, 2260 ty: Type, 2261 }; 2262 2263 pub fn unwrapDbgBlock(air: *const Air, inst_index: Inst.Index) UnwrappedDbgInlineBlock { 2264 const data = air.instructions.items(.data)[@backingInt(inst_index)]; 2265 const tag = air.instructions.items(.tag)[@backingInt(inst_index)]; 2266 assert(tag == .dbg_inline_block); 2267 const payload = data.ty_pl.payload; 2268 const extra = air.extraData(Air.DbgInlineBlock, payload); 2269 return .{ 2270 .func = extra.data.func, 2271 .ty = data.ty_pl.ty, 2272 .body = @ptrCast(air.extra.items[extra.end..][0..extra.data.body_len]), 2273 }; 2274 } 2275 2276 pub const UnwrappedBlock = struct { 2277 body: []const Inst.Index, 2278 ty: Type, 2279 }; 2280 2281 pub fn unwrapBlock(air: *const Air, inst_index: Inst.Index) UnwrappedBlock { 2282 const data = air.instructions.items(.data)[@backingInt(inst_index)]; 2283 const tag = air.instructions.items(.tag)[@backingInt(inst_index)]; 2284 const payload = switch (tag) { 2285 .block, .loop => data.ty_pl.payload, 2286 else => unreachable, 2287 }; 2288 const extra = air.extraData(Air.Block, payload); 2289 return .{ 2290 .ty = data.ty_pl.ty, 2291 .body = @ptrCast(air.extra.items[extra.end..][0..extra.data.body_len]), 2292 }; 2293 } 2294 2295 pub const UnwrappedCall = struct { 2296 callee: Inst.Ref, 2297 args: []const Air.Inst.Ref, 2298 }; 2299 2300 pub fn unwrapCall(air: *const Air, inst_index: Inst.Index) UnwrappedCall { 2301 const data = air.instructions.items(.data)[@backingInt(inst_index)]; 2302 const tag = air.instructions.items(.tag)[@backingInt(inst_index)]; 2303 const payload = switch (tag) { 2304 .call, .call_always_tail, .call_never_tail, .call_never_inline => data.pl_op.payload, 2305 else => unreachable, 2306 }; 2307 const extra = air.extraData(Air.Call, payload); 2308 return .{ 2309 .callee = data.pl_op.operand, 2310 .args = @ptrCast(air.extra.items[extra.end..][0..extra.data.args_len]), 2311 }; 2312 } 2313 2314 pub const UnwrappedCompilerRtCall = struct { 2315 func: CompilerRtFunc, 2316 args: []const Air.Inst.Ref, 2317 }; 2318 2319 pub fn unwrapCompilerRtCall(air: *const Air, inst_index: Inst.Index) UnwrappedCompilerRtCall { 2320 const data = air.instructions.items(.data)[@backingInt(inst_index)]; 2321 const tag = air.instructions.items(.tag)[@backingInt(inst_index)]; 2322 assert(tag == .legalize_compiler_rt_call); 2323 const payload = data.legalize_compiler_rt_call.payload; 2324 const extra = air.extraData(Air.Call, payload); 2325 return .{ 2326 .func = data.legalize_compiler_rt_call.func, 2327 .args = @ptrCast(air.extra.items[extra.end..][0..extra.data.args_len]), 2328 }; 2329 } 2330 2331 pub const UnwrappedCondBr = struct { 2332 condition: Inst.Ref, 2333 then_body: []const Inst.Index, 2334 else_body: []const Inst.Index, 2335 branch_hints: CondBr.BranchHints, 2336 }; 2337 2338 pub fn unwrapCondBr(air: *const Air, inst_index: Inst.Index) UnwrappedCondBr { 2339 const data = air.instructions.items(.data)[@backingInt(inst_index)]; 2340 const tag = air.instructions.items(.tag)[@backingInt(inst_index)]; 2341 assert(tag == .cond_br); 2342 const payload = data.pl_op.payload; 2343 const extra = air.extraData(Air.CondBr, payload); 2344 return .{ 2345 .condition = data.pl_op.operand, 2346 .then_body = @ptrCast(air.extra.items[extra.end..][0..extra.data.then_body_len]), 2347 .else_body = @ptrCast(air.extra.items[extra.end + extra.data.then_body_len ..][0..extra.data.else_body_len]), 2348 .branch_hints = extra.data.branch_hints, 2349 }; 2350 } 2351 2352 pub const UnwrappedTry = struct { 2353 error_union: Inst.Ref, 2354 else_body: []const Inst.Index, 2355 }; 2356 2357 pub fn unwrapTry(air: *const Air, inst_index: Inst.Index) UnwrappedTry { 2358 const data = air.instructions.items(.data)[@backingInt(inst_index)]; 2359 const tag = air.instructions.items(.tag)[@backingInt(inst_index)]; 2360 assert(tag == .@"try" or tag == .try_cold); 2361 const payload = data.pl_op.payload; 2362 const extra = air.extraData(Air.Try, payload); 2363 return .{ 2364 .error_union = data.pl_op.operand, 2365 .else_body = @ptrCast(air.extra.items[extra.end..][0..extra.data.body_len]), 2366 }; 2367 } 2368 2369 pub const UnwrappedTryPtr = struct { 2370 error_union_payload_ptr_ty: Type, 2371 error_union_ptr: Inst.Ref, 2372 else_body: []const Inst.Index, 2373 }; 2374 2375 pub fn unwrapTryPtr(air: *const Air, inst_index: Inst.Index) UnwrappedTryPtr { 2376 const data = air.instructions.items(.data)[@backingInt(inst_index)]; 2377 const tag = air.instructions.items(.tag)[@backingInt(inst_index)]; 2378 assert(tag == .try_ptr or tag == .try_ptr_cold); 2379 const payload = data.ty_pl.payload; 2380 const extra = air.extraData(Air.TryPtr, payload); 2381 return .{ 2382 .error_union_ptr = extra.data.ptr, 2383 .error_union_payload_ptr_ty = data.ty_pl.ty, 2384 .else_body = @ptrCast(air.extra.items[extra.end..][0..extra.data.body_len]), 2385 }; 2386 } 2387 2388 pub const UnwrappedAsm = struct { 2389 outputs: []const Air.Inst.Ref, 2390 inputs: []const Air.Inst.Ref, 2391 source: [:0]u8, 2392 input_constraint_names: []const u32, 2393 output_constraint_names: []const u32, 2394 clobbers: InternPool.Index, 2395 is_volatile: bool, 2396 2397 const AsmIterator = struct { 2398 current: u32, 2399 operands: []const Air.Inst.Ref, 2400 constraint_names: []const u32, 2401 2402 pub fn next(self: *AsmIterator) ?struct { constraint: []const u8, operand: Inst.Ref, name: []const u8, index: u32 } { 2403 if (self.current >= self.operands.len) { 2404 return null; 2405 } 2406 defer { 2407 self.current += 1; 2408 } 2409 2410 const constraint_name = std.mem.sliceAsBytes(self.constraint_names); 2411 const constraint = std.mem.sliceTo(constraint_name, 0); 2412 const name = std.mem.sliceTo(constraint_name[constraint.len + 1 ..], 0); 2413 // This equation accounts for the fact that even if we have exactly 4 bytes 2414 // for the string, we still use the next u32 for the null terminator. 2415 const next_offset = @divCeil(constraint.len + 1 + name.len + 1, @sizeOf(u32)); 2416 self.constraint_names = self.constraint_names[next_offset..]; 2417 2418 return .{ 2419 .constraint = constraint, 2420 .operand = self.operands[self.current], 2421 .name = name, 2422 .index = self.current, 2423 }; 2424 } 2425 }; 2426 2427 pub fn iterateInputs(self: *const UnwrappedAsm) AsmIterator { 2428 return .{ 2429 .current = 0, 2430 .operands = self.inputs, 2431 .constraint_names = self.input_constraint_names, 2432 }; 2433 } 2434 2435 pub fn iterateOutputs(self: *const UnwrappedAsm) AsmIterator { 2436 return .{ 2437 .current = 0, 2438 .operands = self.outputs, 2439 .constraint_names = self.output_constraint_names, 2440 }; 2441 } 2442 }; 2443 2444 pub fn unwrapAsm(air: *const Air, inst_index: Inst.Index) UnwrappedAsm { 2445 const data = air.instructions.items(.data)[@backingInt(inst_index)]; 2446 const tag = air.instructions.items(.tag)[@backingInt(inst_index)]; 2447 assert(tag == .assembly); 2448 const payload = data.ty_pl.payload; 2449 const extra = air.extraData(Air.Asm, payload); 2450 const source_start = extra.end + extra.data.flags.outputs_len + extra.data.inputs_len; 2451 const output_constraint_name_start = source_start + (extra.data.source_len / 4) + 1; 2452 const output_constraint_name = air.extra.items[output_constraint_name_start..]; 2453 const outputs: []Inst.Ref = @ptrCast(air.extra.items[extra.end..][0..extra.data.flags.outputs_len]); 2454 // Get the input names and constraints offset place after the output. 2455 var it = UnwrappedAsm.AsmIterator{ 2456 .current = 0, 2457 .constraint_names = output_constraint_name, 2458 .operands = outputs, 2459 }; 2460 while (it.next()) |_| {} 2461 2462 return .{ 2463 .clobbers = extra.data.clobbers, 2464 .is_volatile = extra.data.flags.is_volatile, 2465 .inputs = @ptrCast(air.extra.items[extra.end + extra.data.flags.outputs_len ..][0..extra.data.inputs_len]), 2466 .outputs = outputs, 2467 .source = std.mem.sliceAsBytes(air.extra.items[source_start..])[0..extra.data.source_len :0], 2468 .output_constraint_names = output_constraint_name, 2469 .input_constraint_names = it.constraint_names, 2470 }; 2471 } 2472 2473 pub const UnwrappedShuffleOne = struct { 2474 result_ty: Type, 2475 operand: Inst.Ref, 2476 mask: []const ShuffleOneMask, 2477 }; 2478 2479 pub fn unwrapShuffleOne(air: *const Air, zcu: *const Zcu, inst_index: Inst.Index) UnwrappedShuffleOne { 2480 const inst = air.instructions.get(@backingInt(inst_index)); 2481 switch (inst.tag) { 2482 .shuffle_one => {}, 2483 else => unreachable, // assertion failure 2484 } 2485 const result_ty: Type = inst.data.ty_pl.ty; 2486 const mask_len: u32 = result_ty.vectorLen(zcu); 2487 const extra_idx = inst.data.ty_pl.payload; 2488 return .{ 2489 .result_ty = result_ty, 2490 .operand = @fromBackingInt(@intCast(air.extra.items[extra_idx + mask_len])), 2491 .mask = @ptrCast(air.extra.items[extra_idx..][0..mask_len]), 2492 }; 2493 } 2494 2495 pub const UnwrappedShuffleTwo = struct { 2496 result_ty: Type, 2497 operand_a: Inst.Ref, 2498 operand_b: Inst.Ref, 2499 mask: []const ShuffleTwoMask, 2500 }; 2501 2502 pub fn unwrapShuffleTwo(air: *const Air, zcu: *const Zcu, inst_index: Inst.Index) UnwrappedShuffleTwo { 2503 const inst = air.instructions.get(@backingInt(inst_index)); 2504 switch (inst.tag) { 2505 .shuffle_two => {}, 2506 else => unreachable, // assertion failure 2507 } 2508 const result_ty: Type = inst.data.ty_pl.ty; 2509 const mask_len: u32 = result_ty.vectorLen(zcu); 2510 const extra_idx = inst.data.ty_pl.payload; 2511 return .{ 2512 .result_ty = result_ty, 2513 .operand_a = @fromBackingInt(@intCast(air.extra.items[extra_idx + mask_len + 0])), 2514 .operand_b = @fromBackingInt(@intCast(air.extra.items[extra_idx + mask_len + 1])), 2515 .mask = @ptrCast(air.extra.items[extra_idx..][0..mask_len]), 2516 }; 2517 } 2518 2519 pub const legalize = Legalize.legalize; 2520 pub const write = print.write; 2521 pub const writeInst = print.writeInst; 2522 pub const dump = print.dump; 2523 pub const dumpInst = print.dumpInst; 2524 2525 pub const CoveragePoint = enum(u1) { 2526 /// Indicates the block is not a place of interest corresponding to 2527 /// a source location for coverage purposes. 2528 none, 2529 /// Point of interest. The next instruction emitted corresponds to 2530 /// a source location used for coverage instrumentation. 2531 poi, 2532 }; 2533 2534 pub const CompilerRtFunc = enum(u32) { 2535 // zig fmt: off 2536 2537 // float simple arithmetic 2538 __addhf3, __addsf3, __adddf3, __addxf3, __addtf3, 2539 __subhf3, __subsf3, __subdf3, __subxf3, __subtf3, 2540 __mulhf3, __mulsf3, __muldf3, __mulxf3, __multf3, 2541 __divhf3, __divsf3, __divdf3, __divxf3, __divtf3, 2542 2543 // float minmax 2544 __fminh, fminf, fmin, __fminx, fminq, 2545 __fmaxh, fmaxf, fmax, __fmaxx, fmaxq, 2546 2547 // float round 2548 __ceilh, ceilf, ceil, __ceilx, ceilq, 2549 __floorh, floorf, floor, __floorx, floorq, 2550 __trunch, truncf, trunc, __truncx, truncq, 2551 __roundh, roundf, round, __roundx, roundq, 2552 2553 // float log 2554 __logh, logf, log, __logx, logq, 2555 __log2h, log2f, log2, __log2x, log2q, 2556 __log10h, log10f, log10, __log10x, log10q, 2557 2558 // float exp 2559 __exph, expf, exp, __expx, expq, 2560 __exp2h, exp2f, exp2, __exp2x, exp2q, 2561 2562 // float trigonometry 2563 __sinh, sinf, sin, __sinx, sinq, 2564 __cosh, cosf, cos, __cosx, cosq, 2565 __tanh, tanf, tan, __tanx, tanq, 2566 2567 // float misc ops 2568 __fabsh, fabsf, fabs, __fabsx, fabsq, 2569 __sqrth, sqrtf, sqrt, __sqrtx, sqrtq, 2570 __fmodh, fmodf, fmod, __fmodx, fmodq, 2571 __fmah, fmaf, fma, __fmax, fmaq, 2572 2573 // float comparison 2574 __eqhf2, __eqsf2, __eqdf2, __eqxf2, __eqtf2, // == iff return == 0 2575 __nehf2, __nesf2, __nedf2, __nexf2, __netf2, // != iff return != 0 2576 __lthf2, __ltsf2, __ltdf2, __ltxf2, __lttf2, // < iff return < 0 2577 __lehf2, __lesf2, __ledf2, __lexf2, __letf2, // <= iff return <= 0 2578 __gthf2, __gtsf2, __gtdf2, __gtxf2, __gttf2, // > iff return > 0 2579 __gehf2, __gesf2, __gedf2, __gexf2, __getf2, // >= iff return >= 0 2580 2581 // AEABI float comparison. On ARM, the `sf`/`df` functions above are not available, 2582 // and these must be used instead. They are not just aliases for the above functions 2583 // because they have a different (better) ABI. 2584 __aeabi_fcmpeq, __aeabi_dcmpeq, // ==, returns bool 2585 __aeabi_fcmplt, __aeabi_dcmplt, // <, returns bool 2586 __aeabi_fcmple, __aeabi_dcmple, // <=, returns bool 2587 __aeabi_fcmpgt, __aeabi_dcmpgt, // >, returns bool 2588 __aeabi_fcmpge, __aeabi_dcmpge, // >=, returns bool 2589 2590 // float shortening 2591 // to f16 // to f32 // to f64 // to f80 2592 __trunctfhf2, __trunctfsf2, __trunctfdf2, __trunctfxf2, // from f128 2593 __truncxfhf2, __truncxfsf2, __truncxfdf2, // from f80 2594 __truncdfhf2, __truncdfsf2, // from f64 2595 __truncsfhf2, // from f32 2596 2597 // float widening 2598 // to f128 // to f80 // to f64 // to f32 2599 __extendhftf2, __extendhfxf2, __extendhfdf2, __extendhfsf2, // from f16 2600 __extendsftf2, __extendsfxf2, __extendsfdf2, // from f32 2601 __extenddftf2, __extenddfxf2, // from f64 2602 __extendxftf2, // from f80 2603 2604 // int to float 2605 __floatsihf, __floatsisf, __floatsidf, __floatsixf, __floatsitf, // i32 to float 2606 __floatdihf, __floatdisf, __floatdidf, __floatdixf, __floatditf, // i64 to float 2607 __floattihf, __floattisf, __floattidf, __floattixf, __floattitf, // i128 to float 2608 __floateihf, __floateisf, __floateidf, __floateixf, __floateitf, // arbitrary iN to float 2609 __floatunsihf, __floatunsisf, __floatunsidf, __floatunsixf, __floatunsitf, // u32 to float 2610 __floatundihf, __floatundisf, __floatundidf, __floatundixf, __floatunditf, // u64 to float 2611 __floatuntihf, __floatuntisf, __floatuntidf, __floatuntixf, __floatuntitf, // u128 to float 2612 __floatuneihf, __floatuneisf, __floatuneidf, __floatuneixf, __floatuneitf, // arbitrary uN to float 2613 2614 // float to int 2615 __fixhfsi, __fixsfsi, __fixdfsi, __fixxfsi, __fixtfsi, // float to i32 2616 __fixhfdi, __fixsfdi, __fixdfdi, __fixxfdi, __fixtfdi, // float to i64 2617 __fixhfti, __fixsfti, __fixdfti, __fixxfti, __fixtfti, // float to i128 2618 __fixhfei, __fixsfei, __fixdfei, __fixxfei, __fixtfei, // float to arbitray iN 2619 __fixunshfsi, __fixunssfsi, __fixunsdfsi, __fixunsxfsi, __fixunstfsi, // float to u32 2620 __fixunshfdi, __fixunssfdi, __fixunsdfdi, __fixunsxfdi, __fixunstfdi, // float to u64 2621 __fixunshfti, __fixunssfti, __fixunsdfti, __fixunsxfti, __fixunstfti, // float to u128 2622 __fixunshfei, __fixunssfei, __fixunsdfei, __fixunsxfei, __fixunstfei, // float to arbitray uN 2623 2624 // zig fmt: on 2625 2626 /// Usually, the tag names of `CompilerRtFunc` match the corresponding symbol name, but not 2627 /// always; some target triples have slightly different compiler-rt ABIs for one reason or 2628 /// another. 2629 pub fn name(f: CompilerRtFunc, target: *const std.Target) []const u8 { 2630 const use_gnu_f16_abi = switch (target.cpu.arch) { 2631 .wasm32, 2632 .wasm64, 2633 .riscv64, 2634 .riscv64be, 2635 .riscv32, 2636 .riscv32be, 2637 => false, 2638 .x86, .x86_64 => true, 2639 .arm, .armeb, .thumb, .thumbeb => switch (target.abi) { 2640 .eabi, .eabihf => false, 2641 else => true, 2642 }, 2643 else => !target.os.tag.isDarwin(), 2644 }; 2645 const use_aeabi = target.cpu.arch.isArm() and switch (target.abi) { 2646 .eabi, 2647 .eabihf, 2648 .musleabi, 2649 .musleabihf, 2650 .gnueabi, 2651 .gnueabihf, 2652 .android, 2653 .androideabi, 2654 => true, 2655 else => false, 2656 }; 2657 2658 // GNU didn't like the standard names specifically for conversions between f16 2659 // and f32, so decided to make their own naming convention with blackjack and 2660 // hookers (but only use it on a few random targets of course). This overrides 2661 // the ARM EABI in some cases. I don't like GNU. 2662 if (use_gnu_f16_abi) switch (f) { 2663 .__truncsfhf2 => return "__gnu_f2h_ieee", 2664 .__extendhfsf2 => return "__gnu_h2f_ieee", 2665 else => {}, 2666 }; 2667 2668 if (use_aeabi) return switch (f) { 2669 .__addsf3 => "__aeabi_fadd", 2670 .__adddf3 => "__aeabi_dadd", 2671 .__subsf3 => "__aeabi_fsub", 2672 .__subdf3 => "__aeabi_dsub", 2673 .__mulsf3 => "__aeabi_fmul", 2674 .__muldf3 => "__aeabi_dmul", 2675 .__divsf3 => "__aeabi_fdiv", 2676 .__divdf3 => "__aeabi_ddiv", 2677 .__truncdfhf2 => "__aeabi_d2h", 2678 .__truncdfsf2 => "__aeabi_d2f", 2679 .__truncsfhf2 => "__aeabi_f2h", 2680 .__extendsfdf2 => "__aeabi_f2d", 2681 .__extendhfsf2 => "__aeabi_h2f", 2682 .__floatsisf => "__aeabi_i2f", 2683 .__floatsidf => "__aeabi_i2d", 2684 .__floatdisf => "__aeabi_l2f", 2685 .__floatdidf => "__aeabi_l2d", 2686 .__floatunsisf => "__aeabi_ui2f", 2687 .__floatunsidf => "__aeabi_ui2d", 2688 .__floatundisf => "__aeabi_ul2f", 2689 .__floatundidf => "__aeabi_ul2d", 2690 .__fixsfsi => "__aeabi_f2iz", 2691 .__fixdfsi => "__aeabi_d2iz", 2692 .__fixsfdi => "__aeabi_f2lz", 2693 .__fixdfdi => "__aeabi_d2lz", 2694 .__fixunssfsi => "__aeabi_f2uiz", 2695 .__fixunsdfsi => "__aeabi_d2uiz", 2696 .__fixunssfdi => "__aeabi_f2ulz", 2697 .__fixunsdfdi => "__aeabi_d2ulz", 2698 2699 // These functions are not available on AEABI. The AEABI equivalents are 2700 // separate fields rather than aliases because they have a different ABI. 2701 .__eqsf2, .__eqdf2 => unreachable, 2702 .__nesf2, .__nedf2 => unreachable, 2703 .__ltsf2, .__ltdf2 => unreachable, 2704 .__lesf2, .__ledf2 => unreachable, 2705 .__gtsf2, .__gtdf2 => unreachable, 2706 .__gesf2, .__gedf2 => unreachable, 2707 2708 else => @tagName(f), 2709 }; 2710 2711 return switch (f) { 2712 // These functions are only available on AEABI. 2713 .__aeabi_fcmpeq, .__aeabi_dcmpeq => unreachable, 2714 .__aeabi_fcmplt, .__aeabi_dcmplt => unreachable, 2715 .__aeabi_fcmple, .__aeabi_dcmple => unreachable, 2716 .__aeabi_fcmpgt, .__aeabi_dcmpgt => unreachable, 2717 .__aeabi_fcmpge, .__aeabi_dcmpge => unreachable, 2718 2719 else => @tagName(f), 2720 }; 2721 } 2722 2723 pub fn @"callconv"(f: CompilerRtFunc, target: *const std.Target) std.lang.CallingConvention { 2724 const use_gnu_f16_abi = switch (target.cpu.arch) { 2725 .wasm32, 2726 .wasm64, 2727 .riscv64, 2728 .riscv64be, 2729 .riscv32, 2730 .riscv32be, 2731 => false, 2732 .x86, .x86_64 => true, 2733 .arm, .armeb, .thumb, .thumbeb => switch (target.abi) { 2734 .eabi, .eabihf => false, 2735 else => true, 2736 }, 2737 else => !target.os.tag.isDarwin(), 2738 }; 2739 const use_aeabi = target.cpu.arch.isArm() and switch (target.abi) { 2740 .eabi, 2741 .eabihf, 2742 .musleabi, 2743 .musleabihf, 2744 .gnueabi, 2745 .gnueabihf, 2746 .android, 2747 .androideabi, 2748 => true, 2749 else => false, 2750 }; 2751 2752 if (use_gnu_f16_abi) switch (f) { 2753 .__truncsfhf2, 2754 .__extendhfsf2, 2755 => return target.cCallingConvention().?, 2756 else => {}, 2757 }; 2758 2759 if (use_aeabi) switch (f) { 2760 // zig fmt: off 2761 .__addsf3, .__adddf3, .__subsf3, .__subdf3, 2762 .__mulsf3, .__muldf3, .__divsf3, .__divdf3, 2763 .__truncdfhf2, .__truncdfsf2, .__truncsfhf2, 2764 .__extendsfdf2, .__extendhfsf2, 2765 .__floatsisf, .__floatsidf, .__floatdisf, .__floatdidf, 2766 .__floatunsisf, .__floatunsidf, .__floatundisf, .__floatundidf, 2767 .__fixsfsi, .__fixdfsi, .__fixsfdi, .__fixdfdi, 2768 .__fixunssfsi, .__fixunsdfsi, .__fixunssfdi, .__fixunsdfdi, 2769 => return .{ .arm_aapcs = .{} }, 2770 // zig fmt: on 2771 else => {}, 2772 }; 2773 2774 return target.cCallingConvention().?; 2775 } 2776 2777 pub fn returnType(f: CompilerRtFunc) Type { 2778 return switch (f) { 2779 .__addhf3, .__subhf3, .__mulhf3, .__divhf3 => .f16, 2780 .__addsf3, .__subsf3, .__mulsf3, .__divsf3 => .f32, 2781 .__adddf3, .__subdf3, .__muldf3, .__divdf3 => .f64, 2782 .__addxf3, .__subxf3, .__mulxf3, .__divxf3 => .f80, 2783 .__addtf3, .__subtf3, .__multf3, .__divtf3 => .f128, 2784 2785 // zig fmt: off 2786 .__fminh, .__fmaxh, 2787 .__ceilh, .__floorh, .__trunch, .__roundh, 2788 .__logh, .__log2h, .__log10h, 2789 .__exph, .__exp2h, 2790 .__sinh, .__cosh, .__tanh, 2791 .__fabsh, .__sqrth, .__fmodh, .__fmah, 2792 => .f16, 2793 .fminf, .fmaxf, 2794 .ceilf, .floorf, .truncf, .roundf, 2795 .logf, .log2f, .log10f, 2796 .expf, .exp2f, 2797 .sinf, .cosf, .tanf, 2798 .fabsf, .sqrtf, .fmodf, .fmaf, 2799 => .f32, 2800 .fmin, .fmax, 2801 .ceil, .floor, .trunc, .round, 2802 .log, .log2, .log10, 2803 .exp, .exp2, 2804 .sin, .cos, .tan, 2805 .fabs, .sqrt, .fmod, .fma, 2806 => .f64, 2807 .__fminx, .__fmaxx, 2808 .__ceilx, .__floorx, .__truncx, .__roundx, 2809 .__logx, .__log2x, .__log10x, 2810 .__expx, .__exp2x, 2811 .__sinx, .__cosx, .__tanx, 2812 .__fabsx, .__sqrtx, .__fmodx, .__fmax, 2813 => .f80, 2814 .fminq, .fmaxq, 2815 .ceilq, .floorq, .truncq, .roundq, 2816 .logq, .log2q, .log10q, 2817 .expq, .exp2q, 2818 .sinq, .cosq, .tanq, 2819 .fabsq, .sqrtq, .fmodq, .fmaq, 2820 => .f128, 2821 // zig fmt: on 2822 2823 .__eqhf2, .__eqsf2, .__eqdf2, .__eqxf2, .__eqtf2 => .i32, 2824 .__nehf2, .__nesf2, .__nedf2, .__nexf2, .__netf2 => .i32, 2825 .__lthf2, .__ltsf2, .__ltdf2, .__ltxf2, .__lttf2 => .i32, 2826 .__lehf2, .__lesf2, .__ledf2, .__lexf2, .__letf2 => .i32, 2827 .__gthf2, .__gtsf2, .__gtdf2, .__gtxf2, .__gttf2 => .i32, 2828 .__gehf2, .__gesf2, .__gedf2, .__gexf2, .__getf2 => .i32, 2829 2830 .__aeabi_fcmpeq, .__aeabi_dcmpeq => .i32, 2831 .__aeabi_fcmplt, .__aeabi_dcmplt => .i32, 2832 .__aeabi_fcmple, .__aeabi_dcmple => .i32, 2833 .__aeabi_fcmpgt, .__aeabi_dcmpgt => .i32, 2834 .__aeabi_fcmpge, .__aeabi_dcmpge => .i32, 2835 2836 .__trunctfhf2, .__truncxfhf2, .__truncdfhf2, .__truncsfhf2 => .f16, 2837 .__trunctfsf2, .__truncxfsf2, .__truncdfsf2 => .f32, 2838 .__trunctfdf2, .__truncxfdf2 => .f64, 2839 .__trunctfxf2 => .f80, 2840 2841 .__extendhftf2, .__extendsftf2, .__extenddftf2, .__extendxftf2 => .f128, 2842 .__extendhfxf2, .__extendsfxf2, .__extenddfxf2 => .f80, 2843 .__extendhfdf2, .__extendsfdf2 => .f64, 2844 .__extendhfsf2 => .f32, 2845 2846 .__floatsihf, .__floatdihf, .__floattihf, .__floateihf => .f16, 2847 .__floatsisf, .__floatdisf, .__floattisf, .__floateisf => .f32, 2848 .__floatsidf, .__floatdidf, .__floattidf, .__floateidf => .f64, 2849 .__floatsixf, .__floatdixf, .__floattixf, .__floateixf => .f80, 2850 .__floatsitf, .__floatditf, .__floattitf, .__floateitf => .f128, 2851 .__floatunsihf, .__floatundihf, .__floatuntihf, .__floatuneihf => .f16, 2852 .__floatunsisf, .__floatundisf, .__floatuntisf, .__floatuneisf => .f32, 2853 .__floatunsidf, .__floatundidf, .__floatuntidf, .__floatuneidf => .f64, 2854 .__floatunsixf, .__floatundixf, .__floatuntixf, .__floatuneixf => .f80, 2855 .__floatunsitf, .__floatunditf, .__floatuntitf, .__floatuneitf => .f128, 2856 2857 .__fixhfsi, .__fixsfsi, .__fixdfsi, .__fixxfsi, .__fixtfsi => .i32, 2858 .__fixhfdi, .__fixsfdi, .__fixdfdi, .__fixxfdi, .__fixtfdi => .i64, 2859 .__fixhfti, .__fixsfti, .__fixdfti, .__fixxfti, .__fixtfti => .i128, 2860 .__fixhfei, .__fixsfei, .__fixdfei, .__fixxfei, .__fixtfei => .void, 2861 .__fixunshfsi, .__fixunssfsi, .__fixunsdfsi, .__fixunsxfsi, .__fixunstfsi => .u32, 2862 .__fixunshfdi, .__fixunssfdi, .__fixunsdfdi, .__fixunsxfdi, .__fixunstfdi => .u64, 2863 .__fixunshfti, .__fixunssfti, .__fixunsdfti, .__fixunsxfti, .__fixunstfti => .u128, 2864 .__fixunshfei, .__fixunssfei, .__fixunsdfei, .__fixunsxfei, .__fixunstfei => .void, 2865 }; 2866 } 2867 }; 2868