pub struct Type(/* private fields */);Expand description
An IR type.
Four bytes, packed, because a type sits on every value in a function and a function has a great many values. The alternative, an enum holding a lane type and a lane count, comes out at twelve bytes for the same information, and the tables this goes in are walked often enough for that to show.
The packing is the low sixteen bits for the width in bits, the next thirteen for the lane
count biased by one, and the top three for which of the six kinds it is. That gives a
largest integer of Type::MAX_BITS and a widest vector of Type::MAX_LANES, both of
which are past anything a target has.
The kind field took a bit off the lane count when mem was added, which halved
Type::MAX_LANES from sixteen thousand to eight. The widest vector register anybody ships
is 2048 bits, so the widest useful vector is 2048 lanes of i1, and the number this leaves
is four times that. Adding cap cost nothing further, since three bits hold eight kinds.
use rucc_ir::{Float, Type};
assert_eq!(Type::int(32).to_string(), "i32");
assert_eq!(Type::float(Float::F64).to_string(), "f64");
assert_eq!(Type::PTR.to_string(), "ptr");
assert_eq!(Type::CAP.to_string(), "cap");
assert_eq!(Type::vector(Type::int(8), 16).to_string(), "i8x16");
assert_eq!(size_of::<Type>(), 4);Implementations§
Source§impl Type
impl Type
Sourcepub const MAX_BITS: u32 = BITS_MASK
pub const MAX_BITS: u32 = BITS_MASK
The widest integer that can be represented, which is what limits _BitInt.
Sixteen bits of width is more than any target’s BITINT_MAXWIDTH and more than any
vector register, and it leaves room in the same four bytes for the lane count.
Sourcepub const fn int(bits: u32) -> Self
pub const fn int(bits: u32) -> Self
An integer bits wide.
§Panics
Panics if bits is zero or above Type::MAX_BITS. A zero-width integer is not a
thing the IR has, and a caller that computed one has a bug that gets much harder to
find if it is allowed to travel.
Sourcepub const fn vector(lane: Self, lanes: u32) -> Self
pub const fn vector(lane: Self, lanes: u32) -> Self
A vector of lanes copies of lane.
§Panics
Panics if lane is not an integer or a floating point type, if it is itself a vector,
or if lanes is zero or above Type::MAX_LANES. A vector of pointers is not in the
instruction set, so admitting the type would mean admitting a value nothing can be done
with.
Sourcepub const fn bits(self) -> u32
pub const fn bits(self) -> u32
The width of one lane in bits, which for a scalar is the width of the type.
Zero for void, for ptr and for cap, since the width of an address is a property of
the target and not of the type, and a capability has no width in the IR at all. Ask the
target for the first and spec/safe-memory/05-representation.md for the second.
Sourcepub const fn with_lane(self, lane: Self) -> Self
pub const fn with_lane(self, lane: Self) -> Self
The same shape as this, with the lane type replaced.
This is what a comparison does: icmp over i32x4 produces i1x4, and the rule that
the lane count is carried across is easier to get right in one place than at every
instruction that needs it.
§Panics
Panics under the same conditions as Type::vector.
Sourcepub const fn is_ptr(self) -> bool
pub const fn is_ptr(self) -> bool
Whether this is an address. A vector of pointers cannot be built, so this is scalar.
Sourcepub const fn is_cap(self) -> bool
pub const fn is_cap(self) -> bool
Whether this is a capability. A vector of capabilities cannot be built, so this is scalar.
Sourcepub fn parse(text: &str) -> Option<Self>
pub fn parse(text: &str) -> Option<Self>
Parses the textual form, which is what the printer writes.
use rucc_ir::Type;
assert_eq!(Type::parse("i32"), Some(Type::int(32)));
assert_eq!(Type::parse("f32x4"), Some(Type::vector(Type::float(rucc_ir::Float::F32), 4)));
assert_eq!(Type::parse("i0"), None);
assert_eq!(Type::parse("i32 "), None);