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:
Chris Fallin
2022-04-13 10:14:00 -07:00
committed by GitHub
parent 94cd6c421c
commit 4cac1614bf
5 changed files with 38 additions and 0 deletions

View File

@@ -29,6 +29,14 @@ jobs:
- name: Run tests
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
# incompatible licences.
cargo_deny:

View File

@@ -16,6 +16,9 @@ smallvec = "1.6.1"
fxhash = "0.2.1"
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.
# Keep this in sync with libfuzzer_sys's crate version:
arbitrary = { version = "^0.4.6", optional = true }
@@ -37,3 +40,6 @@ trace-log = []
# Exposes the internal API for fuzzing.
fuzzing = ["arbitrary", "checker", "trace-log"]
# Enables serde for exposed types.
enable-serde = ["serde"]

View File

@@ -2,6 +2,10 @@
macro_rules! define_index {
($ix:ident) => {
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(
feature = "enable-serde",
derive(::serde::Serialize, ::serde::Deserialize)
)]
pub struct $ix(pub u32);
impl $ix {
#[inline(always)]

View File

@@ -584,6 +584,7 @@ impl PosWithPrio {
}
#[derive(Clone, Copy, Debug, Default)]
#[cfg_attr(feature = "enable-serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Stats {
pub livein_blocks: usize,
pub livein_iterations: usize,

View File

@@ -39,6 +39,9 @@ pub mod checker;
#[cfg(feature = "fuzzing")]
pub mod fuzzing;
#[cfg(feature = "enable-serde")]
use serde::{Deserialize, Serialize};
/// Register classes.
///
/// 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
/// more classes in the future.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub enum RegClass {
Int = 0,
Float = 1,
@@ -73,6 +77,7 @@ pub enum RegClass {
/// the MSB, or equivalently, declaring that indices 0..=63 are the 64
/// integer registers and indices 64..=127 are the 64 float registers.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct PReg {
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
/// location.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct VReg {
bits: u32,
}
@@ -236,6 +242,7 @@ impl std::fmt::Display for VReg {
/// and will specify how many spillslots have been used when the
/// allocation is completed.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct SpillSlot {
bits: u32,
}
@@ -308,6 +315,7 @@ impl std::fmt::Display for SpillSlot {
/// is usually a programming error in the client, rather than a
/// function of bad input).
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub enum OperandConstraint {
/// Any location is fine (register or stack slot).
Any,
@@ -336,6 +344,7 @@ impl std::fmt::Display for OperandConstraint {
/// The "kind" of the operand: whether it reads a vreg (Use), writes a
/// vreg (Def), or reads and then writes (Mod, for "modify").
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub enum OperandKind {
Def = 0,
Mod = 1,
@@ -361,6 +370,7 @@ pub enum OperandKind {
/// the use (normally complete at "Early") and the def (normally
/// starting at "Late"). See `Operand` for more.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub enum OperandPos {
Early = 0,
Late = 1,
@@ -389,6 +399,7 @@ pub enum OperandPos {
/// that the conflict (overlap) is properly accounted for. See
/// comments on the constructors below for more.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct Operand {
/// 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
/// Operand.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct Allocation {
/// Bit-pack in 32 bits.
///
@@ -820,6 +832,7 @@ impl Allocation {
/// spillslot/stack.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(u8)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub enum AllocationKind {
None = 0,
Reg = 1,
@@ -1042,6 +1055,7 @@ pub trait Function {
/// describe these two insertion points.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(u8)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub enum InstPosition {
Before = 0,
After = 1,
@@ -1049,6 +1063,7 @@ pub enum InstPosition {
/// A program point: a single point before or after a given instruction.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct ProgPoint {
bits: u32,
}
@@ -1140,6 +1155,7 @@ impl ProgPoint {
/// An instruction to insert into the program to perform some data movement.
#[derive(Clone, Debug)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub enum Edit {
/// Move one allocation to another. Each allocation may be a
/// 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
/// as well.
#[derive(Clone, Debug)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct MachineEnv {
/// Preferred physical registers for each class. These are the
/// registers that will be allocated first, if free.
@@ -1231,6 +1248,7 @@ pub struct MachineEnv {
/// The output of the register allocator.
#[derive(Clone, Debug)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct Output {
/// How many spillslots are needed in the frame?
pub num_spillslots: usize,
@@ -1303,6 +1321,7 @@ impl Output {
/// An error that prevents allocation.
#[derive(Clone, Debug)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub enum RegAllocError {
/// Critical edge is not split between given blocks.
CritEdge(Block, Block),