Add serde support for exposed types. (#40)
This adds derived `Serialize` and `Deserialize` implementations for exposed types that describe registers, operands, and related program inputs; entity indices; and regalloc output types. This allows serialization of any of the embedder's IR data types that may embed or build upon regalloc2 types. These implementations (and the dependency on the `serde` crate itself) are enabled only when the non-default `enable-serde` feature is specified.
This commit is contained in:
8
.github/workflows/rust.yml
vendored
8
.github/workflows/rust.yml
vendored
@@ -29,6 +29,14 @@ jobs:
|
|||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: cargo test --all --verbose
|
run: cargo test --all --verbose
|
||||||
|
|
||||||
|
# Make sure the code typechecks with non-default features enabled.
|
||||||
|
features:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Check with all features
|
||||||
|
run: cargo check --all-features
|
||||||
|
|
||||||
# Lint dependency graph for security advisories, duplicate versions, and
|
# Lint dependency graph for security advisories, duplicate versions, and
|
||||||
# incompatible licences.
|
# incompatible licences.
|
||||||
cargo_deny:
|
cargo_deny:
|
||||||
|
|||||||
@@ -16,6 +16,9 @@ smallvec = "1.6.1"
|
|||||||
fxhash = "0.2.1"
|
fxhash = "0.2.1"
|
||||||
slice-group-by = "0.3.0"
|
slice-group-by = "0.3.0"
|
||||||
|
|
||||||
|
# Optional serde support, enabled by feature below.
|
||||||
|
serde = { version = "1.0.136", features = ["derive"], optional = true }
|
||||||
|
|
||||||
# The below are only needed for fuzzing.
|
# The below are only needed for fuzzing.
|
||||||
# Keep this in sync with libfuzzer_sys's crate version:
|
# Keep this in sync with libfuzzer_sys's crate version:
|
||||||
arbitrary = { version = "^0.4.6", optional = true }
|
arbitrary = { version = "^0.4.6", optional = true }
|
||||||
@@ -37,3 +40,6 @@ trace-log = []
|
|||||||
|
|
||||||
# Exposes the internal API for fuzzing.
|
# Exposes the internal API for fuzzing.
|
||||||
fuzzing = ["arbitrary", "checker", "trace-log"]
|
fuzzing = ["arbitrary", "checker", "trace-log"]
|
||||||
|
|
||||||
|
# Enables serde for exposed types.
|
||||||
|
enable-serde = ["serde"]
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
macro_rules! define_index {
|
macro_rules! define_index {
|
||||||
($ix:ident) => {
|
($ix:ident) => {
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
#[cfg_attr(
|
||||||
|
feature = "enable-serde",
|
||||||
|
derive(::serde::Serialize, ::serde::Deserialize)
|
||||||
|
)]
|
||||||
pub struct $ix(pub u32);
|
pub struct $ix(pub u32);
|
||||||
impl $ix {
|
impl $ix {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
|||||||
@@ -584,6 +584,7 @@ impl PosWithPrio {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Default)]
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
|
#[cfg_attr(feature = "enable-serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
pub struct Stats {
|
pub struct Stats {
|
||||||
pub livein_blocks: usize,
|
pub livein_blocks: usize,
|
||||||
pub livein_iterations: usize,
|
pub livein_iterations: usize,
|
||||||
|
|||||||
19
src/lib.rs
19
src/lib.rs
@@ -39,6 +39,9 @@ pub mod checker;
|
|||||||
#[cfg(feature = "fuzzing")]
|
#[cfg(feature = "fuzzing")]
|
||||||
pub mod fuzzing;
|
pub mod fuzzing;
|
||||||
|
|
||||||
|
#[cfg(feature = "enable-serde")]
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
/// Register classes.
|
/// Register classes.
|
||||||
///
|
///
|
||||||
/// Every value has a "register class", which is like a type at the
|
/// Every value has a "register class", which is like a type at the
|
||||||
@@ -53,6 +56,7 @@ pub mod fuzzing;
|
|||||||
/// operations. If needed, we could adjust bitpacking to allow for
|
/// operations. If needed, we could adjust bitpacking to allow for
|
||||||
/// more classes in the future.
|
/// more classes in the future.
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
pub enum RegClass {
|
pub enum RegClass {
|
||||||
Int = 0,
|
Int = 0,
|
||||||
Float = 1,
|
Float = 1,
|
||||||
@@ -73,6 +77,7 @@ pub enum RegClass {
|
|||||||
/// the MSB, or equivalently, declaring that indices 0..=63 are the 64
|
/// the MSB, or equivalently, declaring that indices 0..=63 are the 64
|
||||||
/// integer registers and indices 64..=127 are the 64 float registers.
|
/// integer registers and indices 64..=127 are the 64 float registers.
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
pub struct PReg {
|
pub struct PReg {
|
||||||
bits: u8,
|
bits: u8,
|
||||||
}
|
}
|
||||||
@@ -171,6 +176,7 @@ impl std::fmt::Display for PReg {
|
|||||||
/// we need the vreg's live range in order to track the use of that
|
/// we need the vreg's live range in order to track the use of that
|
||||||
/// location.
|
/// location.
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
pub struct VReg {
|
pub struct VReg {
|
||||||
bits: u32,
|
bits: u32,
|
||||||
}
|
}
|
||||||
@@ -236,6 +242,7 @@ impl std::fmt::Display for VReg {
|
|||||||
/// and will specify how many spillslots have been used when the
|
/// and will specify how many spillslots have been used when the
|
||||||
/// allocation is completed.
|
/// allocation is completed.
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
pub struct SpillSlot {
|
pub struct SpillSlot {
|
||||||
bits: u32,
|
bits: u32,
|
||||||
}
|
}
|
||||||
@@ -308,6 +315,7 @@ impl std::fmt::Display for SpillSlot {
|
|||||||
/// is usually a programming error in the client, rather than a
|
/// is usually a programming error in the client, rather than a
|
||||||
/// function of bad input).
|
/// function of bad input).
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
pub enum OperandConstraint {
|
pub enum OperandConstraint {
|
||||||
/// Any location is fine (register or stack slot).
|
/// Any location is fine (register or stack slot).
|
||||||
Any,
|
Any,
|
||||||
@@ -336,6 +344,7 @@ impl std::fmt::Display for OperandConstraint {
|
|||||||
/// The "kind" of the operand: whether it reads a vreg (Use), writes a
|
/// The "kind" of the operand: whether it reads a vreg (Use), writes a
|
||||||
/// vreg (Def), or reads and then writes (Mod, for "modify").
|
/// vreg (Def), or reads and then writes (Mod, for "modify").
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
pub enum OperandKind {
|
pub enum OperandKind {
|
||||||
Def = 0,
|
Def = 0,
|
||||||
Mod = 1,
|
Mod = 1,
|
||||||
@@ -361,6 +370,7 @@ pub enum OperandKind {
|
|||||||
/// the use (normally complete at "Early") and the def (normally
|
/// the use (normally complete at "Early") and the def (normally
|
||||||
/// starting at "Late"). See `Operand` for more.
|
/// starting at "Late"). See `Operand` for more.
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
pub enum OperandPos {
|
pub enum OperandPos {
|
||||||
Early = 0,
|
Early = 0,
|
||||||
Late = 1,
|
Late = 1,
|
||||||
@@ -389,6 +399,7 @@ pub enum OperandPos {
|
|||||||
/// that the conflict (overlap) is properly accounted for. See
|
/// that the conflict (overlap) is properly accounted for. See
|
||||||
/// comments on the constructors below for more.
|
/// comments on the constructors below for more.
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
pub struct Operand {
|
pub struct Operand {
|
||||||
/// Bit-pack into 32 bits.
|
/// Bit-pack into 32 bits.
|
||||||
///
|
///
|
||||||
@@ -686,6 +697,7 @@ impl std::fmt::Display for Operand {
|
|||||||
/// An Allocation represents the end result of regalloc for an
|
/// An Allocation represents the end result of regalloc for an
|
||||||
/// Operand.
|
/// Operand.
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
pub struct Allocation {
|
pub struct Allocation {
|
||||||
/// Bit-pack in 32 bits.
|
/// Bit-pack in 32 bits.
|
||||||
///
|
///
|
||||||
@@ -820,6 +832,7 @@ impl Allocation {
|
|||||||
/// spillslot/stack.
|
/// spillslot/stack.
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
pub enum AllocationKind {
|
pub enum AllocationKind {
|
||||||
None = 0,
|
None = 0,
|
||||||
Reg = 1,
|
Reg = 1,
|
||||||
@@ -1042,6 +1055,7 @@ pub trait Function {
|
|||||||
/// describe these two insertion points.
|
/// describe these two insertion points.
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
pub enum InstPosition {
|
pub enum InstPosition {
|
||||||
Before = 0,
|
Before = 0,
|
||||||
After = 1,
|
After = 1,
|
||||||
@@ -1049,6 +1063,7 @@ pub enum InstPosition {
|
|||||||
|
|
||||||
/// A program point: a single point before or after a given instruction.
|
/// A program point: a single point before or after a given instruction.
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
pub struct ProgPoint {
|
pub struct ProgPoint {
|
||||||
bits: u32,
|
bits: u32,
|
||||||
}
|
}
|
||||||
@@ -1140,6 +1155,7 @@ impl ProgPoint {
|
|||||||
|
|
||||||
/// An instruction to insert into the program to perform some data movement.
|
/// An instruction to insert into the program to perform some data movement.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
pub enum Edit {
|
pub enum Edit {
|
||||||
/// Move one allocation to another. Each allocation may be a
|
/// Move one allocation to another. Each allocation may be a
|
||||||
/// register or a stack slot (spillslot). However, stack-to-stack
|
/// register or a stack slot (spillslot). However, stack-to-stack
|
||||||
@@ -1196,6 +1212,7 @@ impl<'a> Iterator for OutputIter<'a> {
|
|||||||
/// scratch register for each class, and some other miscellaneous info
|
/// scratch register for each class, and some other miscellaneous info
|
||||||
/// as well.
|
/// as well.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
pub struct MachineEnv {
|
pub struct MachineEnv {
|
||||||
/// Preferred physical registers for each class. These are the
|
/// Preferred physical registers for each class. These are the
|
||||||
/// registers that will be allocated first, if free.
|
/// registers that will be allocated first, if free.
|
||||||
@@ -1231,6 +1248,7 @@ pub struct MachineEnv {
|
|||||||
|
|
||||||
/// The output of the register allocator.
|
/// The output of the register allocator.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
pub struct Output {
|
pub struct Output {
|
||||||
/// How many spillslots are needed in the frame?
|
/// How many spillslots are needed in the frame?
|
||||||
pub num_spillslots: usize,
|
pub num_spillslots: usize,
|
||||||
@@ -1303,6 +1321,7 @@ impl Output {
|
|||||||
|
|
||||||
/// An error that prevents allocation.
|
/// An error that prevents allocation.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
|
||||||
pub enum RegAllocError {
|
pub enum RegAllocError {
|
||||||
/// Critical edge is not split between given blocks.
|
/// Critical edge is not split between given blocks.
|
||||||
CritEdge(Block, Block),
|
CritEdge(Block, Block),
|
||||||
|
|||||||
Reference in New Issue
Block a user