When analyzing a case body, the switch instruction itself refers to the
captured payload. Whether this is captured by reference or by value
depends on whether the byref bit is set for the corresponding body.
pub const SwitchBlock = struct {
/// The operand passed to the `switch` expression. If this is a
/// `switch_block`, this is the operand value; if `switch_block_ref` it
/// is a pointer to the operand. `switch_block_ref` is always used if
/// any prong has a byref capture.
operand: Ref,
bits: Bits,
/// These are stored in trailing data in `extra` for each prong.
pub const ProngInfo = packed struct(u32) {
body_len: u28,
capture: ProngInfo.Capture,
is_inline: bool,
has_tag_capture: bool,
pub const Capture = enum(u2) {
none,
by_val,
by_ref,
};
};
pub const Bits = packed struct(u32) {
/// If true, one or more prongs have multiple items.
has_multi_cases: bool,
/// If true, there is an else prong. This is mutually exclusive with `has_under`.
has_else: bool,
/// If true, there is an underscore prong. This is mutually exclusive with `has_else`.
has_under: bool,
/// If true, at least one prong has an inline tag capture.
any_has_tag_capture: bool,
/// If true, at least one prong has a capture which may not
/// be comptime-known via `inline`.
any_non_inline_capture: bool,
has_continue: bool,
scalar_cases_len: ScalarCasesLen,
pub const ScalarCasesLen = u26;
pub fn specialProng(bits: Bits) SpecialProng {
const has_else: u2 = @intFromBool(bits.has_else);
const has_under: u2 = @intFromBool(bits.has_under);
return switch ((has_else << 1) | has_under) {
0b00 => .none,
0b01 => .under,
0b10 => .@"else",
0b11 => unreachable,
};
}
};
pub const MultiProng = struct {
items: []const Ref,
body: []const Index,
};
}