diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 8081fdc..6e45607 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -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: diff --git a/Cargo.toml b/Cargo.toml index d43fbad..59bff97 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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"] diff --git a/src/index.rs b/src/index.rs index 4c376fa..d847484 100644 --- a/src/index.rs +++ b/src/index.rs @@ -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)] diff --git a/src/ion/data_structures.rs b/src/ion/data_structures.rs index 5b60bfb..89f7350 100644 --- a/src/ion/data_structures.rs +++ b/src/ion/data_structures.rs @@ -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, diff --git a/src/lib.rs b/src/lib.rs index b9edcf3..c6267c4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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),