Skip to main content

polydat_core/library/
register_view.rs

1// Copyright 2024-2026 Jonathan Shook
2// SPDX-License-Identifier: Apache-2.0
3
4//! The register view retags the assembler inserts between register
5//! ports of different lane typings, and the register-port predicate it
6//! keys on (type_system_alignment.md ยง8.4 layer 2).
7//!
8//! A view is a free bitcast: the 128 bits are untouched and only the
9//! lane typing changes. Each view is an ordinary registered node, like
10//! every other entry of the conversion table, so a program can call it
11//! and the conversion fuzzer can reach it by the name the table gives.
12//! It used to be one hand-written node parameterized by its target
13//! type, which the assembler could insert but no program could name.
14//!
15//! Each takes the raw word: any register view satisfies a register
16//! slot (the free-bitcast rule in `Value::satisfies_slot`).
17
18use crate::ast::{Bits128, PolydatNode, PortType};
19
20/// A register word viewed raw, without a lane typing.
21#[crate::polydat_node(category = Conversions)]
22fn __reg_view_raw(r: Bits128) -> Bits128 {
23    r
24}
25
26/// A register word viewed as sixteen `i8` lanes.
27#[crate::polydat_node(category = Conversions)]
28fn __reg_view_i8x16(r: Bits128) -> [i8; 16] {
29    r.lanes_i8()
30}
31
32/// A register word viewed as eight `i16` lanes.
33#[crate::polydat_node(category = Conversions)]
34fn __reg_view_i16x8(r: Bits128) -> [i16; 8] {
35    r.lanes_i16()
36}
37
38/// A register word viewed as four `i32` lanes.
39#[crate::polydat_node(category = Conversions)]
40fn __reg_view_i32x4(r: Bits128) -> [i32; 4] {
41    r.lanes_i32()
42}
43
44/// A register word viewed as two `i64` lanes.
45#[crate::polydat_node(category = Conversions)]
46fn __reg_view_i64x2(r: Bits128) -> [i64; 2] {
47    r.lanes_i64()
48}
49
50/// A register word viewed as eight `f16` lanes.
51#[crate::polydat_node(category = Conversions)]
52fn __reg_view_f16x8(r: Bits128) -> [half::f16; 8] {
53    r.lanes_f16()
54}
55
56/// A register word viewed as four `f32` lanes.
57#[crate::polydat_node(category = Conversions)]
58fn __reg_view_f32x4(r: Bits128) -> [f32; 4] {
59    r.lanes_f32()
60}
61
62/// A register word viewed as two `f64` lanes.
63#[crate::polydat_node(category = Conversions)]
64fn __reg_view_f64x2(r: Bits128) -> [f64; 2] {
65    r.lanes_f64()
66}
67
68/// The view of a register word as `to`, the retag the assembler
69/// inserts between register ports of different lane typings. `None`
70/// when `to` is not a register type.
71pub fn reg_view(to: PortType) -> Option<Box<dyn PolydatNode>> {
72    Some(match to {
73        PortType::Reg128 => Box::new(RegViewRaw::new()),
74        PortType::RegI8x16 => Box::new(RegViewI8x16::new()),
75        PortType::RegI16x8 => Box::new(RegViewI16x8::new()),
76        PortType::RegI32x4 => Box::new(RegViewI32x4::new()),
77        PortType::RegI64x2 => Box::new(RegViewI64x2::new()),
78        PortType::RegF16x8 => Box::new(RegViewF16x8::new()),
79        PortType::RegF32x4 => Box::new(RegViewF32x4::new()),
80        PortType::RegF64x2 => Box::new(RegViewF64x2::new()),
81        _ => return None,
82    })
83}
84
85/// `true` when `t` is any register-plane PortType.
86pub fn is_reg_port(t: PortType) -> bool {
87    matches!(
88        t,
89        PortType::Reg128
90            | PortType::RegI8x16
91            | PortType::RegI16x8
92            | PortType::RegI32x4
93            | PortType::RegI64x2
94            | PortType::RegF16x8
95            | PortType::RegF32x4
96            | PortType::RegF64x2
97    )
98}