Add serde serialization support for the full clif ir

This commit is contained in:
bjorn3
2020-12-19 16:32:46 +01:00
parent 7b4652bb82
commit 2fc964ea35
25 changed files with 195 additions and 4 deletions

3
Cargo.lock generated
View File

@@ -550,6 +550,9 @@ dependencies = [
[[package]] [[package]]
name = "cranelift-codegen-shared" name = "cranelift-codegen-shared"
version = "0.70.0" version = "0.70.0"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "cranelift-entity" name = "cranelift-entity"

View File

@@ -74,7 +74,12 @@ all-arch = [
] ]
# For dependent crates that want to serialize some parts of cranelift # For dependent crates that want to serialize some parts of cranelift
enable-serde = ["serde", "regalloc/enable-serde"] enable-serde = [
"serde",
"regalloc/enable-serde",
"cranelift-entity/enable-serde",
"cranelift-codegen-shared/enable-serde"
]
# Allow snapshotting regalloc test cases. Useful only to report bad register # Allow snapshotting regalloc test cases. Useful only to report bad register
# allocation failures, or for regalloc.rs developers. # allocation failures, or for regalloc.rs developers.

View File

@@ -68,6 +68,7 @@ fn gen_formats(formats: &[&InstructionFormat], fmt: &mut Formatter) {
/// `ValueList` to store the additional information out of line. /// `ValueList` to store the additional information out of line.
fn gen_instruction_data(formats: &[&InstructionFormat], fmt: &mut Formatter) { fn gen_instruction_data(formats: &[&InstructionFormat], fmt: &mut Formatter) {
fmt.line("#[derive(Clone, Debug)]"); fmt.line("#[derive(Clone, Debug)]");
fmt.line(r#"#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]"#);
fmt.line("#[allow(missing_docs)]"); fmt.line("#[allow(missing_docs)]");
fmt.line("pub enum InstructionData {"); fmt.line("pub enum InstructionData {");
fmt.indent(|fmt| { fmt.indent(|fmt| {
@@ -410,7 +411,10 @@ fn gen_opcodes(all_inst: &AllInstructions, fmt: &mut Formatter) {
fmt.line("#[repr(u16)]"); fmt.line("#[repr(u16)]");
fmt.line("#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]"); fmt.line("#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]");
fmt.line( fmt.line(
r#"#[cfg_attr(feature = "enable-peepmatic", derive(serde::Serialize, serde::Deserialize))]"# r#"#[cfg_attr(
any(feature = "enable-peepmatic", feature = "enable-serde"),
derive(serde::Serialize, serde::Deserialize)
)]"#,
); );
// We explicitly set the discriminant of the first variant to 1, which allows us to take // We explicitly set the discriminant of the first variant to 1, which allows us to take

View File

@@ -8,4 +8,10 @@ repository = "https://github.com/bytecodealliance/wasmtime"
readme = "README.md" readme = "README.md"
edition = "2018" edition = "2018"
# Since this is a shared dependency of several packages, please strive to keep this dependency-free. [dependencies]
# Since this is a shared dependency of several packages, please strive to keep this dependency-free
# when no features are enabled.
serde = { version = "1.0.94", features = ["derive"], optional = true }
[features]
enable-serde = ["serde"]

View File

@@ -7,6 +7,9 @@
use core::fmt::{self, Display, Formatter}; use core::fmt::{self, Display, Formatter};
use core::str::FromStr; use core::str::FromStr;
#[cfg(feature = "enable-serde")]
use serde::{Deserialize, Serialize};
/// Common traits of condition codes. /// Common traits of condition codes.
pub trait CondCode: Copy { pub trait CondCode: Copy {
/// Get the inverse condition code of `self`. /// Get the inverse condition code of `self`.
@@ -30,6 +33,7 @@ pub trait CondCode: Copy {
/// separate codes for comparing the integers as signed or unsigned numbers where it makes a /// separate codes for comparing the integers as signed or unsigned numbers where it makes a
/// difference. /// difference.
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub enum IntCC { pub enum IntCC {
/// `==`. /// `==`.
Equal, Equal,
@@ -187,6 +191,7 @@ impl FromStr for IntCC {
/// comparison. The 14 condition codes here cover every possible combination of the relation above /// comparison. The 14 condition codes here cover every possible combination of the relation above
/// except the impossible `!UN & !EQ & !LT & !GT` and the always true `UN | EQ | LT | GT`. /// except the impossible `!UN & !EQ & !LT & !GT` and the always true `UN | EQ | LT | GT`.
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub enum FloatCC { pub enum FloatCC {
/// EQ | LT | GT /// EQ | LT | GT
Ordered, Ordered,

View File

@@ -19,12 +19,16 @@ use core::slice::Iter;
use core::str::{from_utf8, FromStr}; use core::str::{from_utf8, FromStr};
use cranelift_entity::EntityRef; use cranelift_entity::EntityRef;
#[cfg(feature = "enable-serde")]
use serde::{Deserialize, Serialize};
/// This type describes the actual constant data. Note that the bytes stored in this structure are /// This type describes the actual constant data. Note that the bytes stored in this structure are
/// expected to be in little-endian order; this is due to ease-of-use when interacting with /// expected to be in little-endian order; this is due to ease-of-use when interacting with
/// WebAssembly values, which are [little-endian by design]. /// WebAssembly values, which are [little-endian by design].
/// ///
/// [little-endian by design]: https://github.com/WebAssembly/design/blob/master/Portability.md /// [little-endian by design]: https://github.com/WebAssembly/design/blob/master/Portability.md
#[derive(Clone, Hash, Eq, PartialEq, Debug, Default)] #[derive(Clone, Hash, Eq, PartialEq, Debug, Default)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct ConstantData(Vec<u8>); pub struct ConstantData(Vec<u8>);
impl FromIterator<u8> for ConstantData { impl FromIterator<u8> for ConstantData {
@@ -173,6 +177,7 @@ pub type ConstantOffset = u32;
/// from the beginning of the function is known (see /// from the beginning of the function is known (see
/// `relaxation` in `relaxation.rs`). /// `relaxation` in `relaxation.rs`).
#[derive(Clone)] #[derive(Clone)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct ConstantPoolEntry { pub struct ConstantPoolEntry {
data: ConstantData, data: ConstantData,
offset: Option<ConstantOffset>, offset: Option<ConstantOffset>,
@@ -197,6 +202,7 @@ impl ConstantPoolEntry {
/// Maintains the mapping between a constant handle (i.e. [`Constant`](crate::ir::Constant)) and /// Maintains the mapping between a constant handle (i.e. [`Constant`](crate::ir::Constant)) and
/// its constant data (i.e. [`ConstantData`](crate::ir::ConstantData)). /// its constant data (i.e. [`ConstantData`](crate::ir::ConstantData)).
#[derive(Clone)] #[derive(Clone)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct ConstantPool { pub struct ConstantPool {
/// This mapping maintains the insertion order as long as Constants are created with /// This mapping maintains the insertion order as long as Constants are created with
/// sequentially increasing integers. /// sequentially increasing integers.

View File

@@ -21,6 +21,9 @@ use core::mem;
use core::ops::{Index, IndexMut}; use core::ops::{Index, IndexMut};
use core::u16; use core::u16;
#[cfg(feature = "enable-serde")]
use serde::{Deserialize, Serialize};
/// A data flow graph defines all instructions and basic blocks in a function as well as /// A data flow graph defines all instructions and basic blocks in a function as well as
/// the data flow dependencies between them. The DFG also tracks values which can be either /// the data flow dependencies between them. The DFG also tracks values which can be either
/// instruction results or block parameters. /// instruction results or block parameters.
@@ -29,6 +32,7 @@ use core::u16;
/// `Layout` data structure which forms the other half of the function representation. /// `Layout` data structure which forms the other half of the function representation.
/// ///
#[derive(Clone)] #[derive(Clone)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct DataFlowGraph { pub struct DataFlowGraph {
/// Data about all of the instructions in the function, including opcodes and operands. /// Data about all of the instructions in the function, including opcodes and operands.
/// The instructions in this map are not in program order. That is tracked by `Layout`, along /// The instructions in this map are not in program order. That is tracked by `Layout`, along
@@ -416,6 +420,7 @@ impl ValueDef {
/// Internal table storage for extended values. /// Internal table storage for extended values.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
enum ValueData { enum ValueData {
/// Value is defined by an instruction. /// Value is defined by an instruction.
Inst { ty: Type, num: u16, inst: Inst }, Inst { ty: Type, num: u16, inst: Inst },
@@ -935,6 +940,7 @@ impl DataFlowGraph {
/// branches to this block must provide matching arguments, and the arguments to the entry block must /// branches to this block must provide matching arguments, and the arguments to the entry block must
/// match the function arguments. /// match the function arguments.
#[derive(Clone)] #[derive(Clone)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
struct BlockData { struct BlockData {
/// List of parameters to this block. /// List of parameters to this block.
params: ValueList, params: ValueList,

View File

@@ -33,6 +33,7 @@ use serde::{Deserialize, Serialize};
/// ///
/// While the order is stable, it is arbitrary and does not necessarily resemble the layout order. /// While the order is stable, it is arbitrary and does not necessarily resemble the layout order.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct Block(u32); pub struct Block(u32);
entity_impl!(Block, "block"); entity_impl!(Block, "block");
@@ -65,6 +66,7 @@ impl Block {
/// ///
/// While the order is stable, it is arbitrary. /// While the order is stable, it is arbitrary.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct Value(u32); pub struct Value(u32);
entity_impl!(Value, "v"); entity_impl!(Value, "v");
@@ -97,6 +99,7 @@ impl Value {
/// ///
/// While the order is stable, it is arbitrary and does not necessarily resemble the layout order. /// While the order is stable, it is arbitrary and does not necessarily resemble the layout order.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct Inst(u32); pub struct Inst(u32);
entity_impl!(Inst, "inst"); entity_impl!(Inst, "inst");
@@ -152,6 +155,7 @@ impl StackSlot {
/// ///
/// While the order is stable, it is arbitrary. /// While the order is stable, it is arbitrary.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct GlobalValue(u32); pub struct GlobalValue(u32);
entity_impl!(GlobalValue, "gv"); entity_impl!(GlobalValue, "gv");
@@ -177,6 +181,7 @@ impl GlobalValue {
/// While the order is stable, it is arbitrary and does not necessarily resemble the order in which /// While the order is stable, it is arbitrary and does not necessarily resemble the order in which
/// the constants are written in the constant pool. /// the constants are written in the constant pool.
#[derive(Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)] #[derive(Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct Constant(u32); pub struct Constant(u32);
entity_impl!(Constant, "const"); entity_impl!(Constant, "const");
@@ -202,6 +207,7 @@ impl Constant {
/// ///
/// While the order is stable, it is arbitrary. /// While the order is stable, it is arbitrary.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct Immediate(u32); pub struct Immediate(u32);
entity_impl!(Immediate, "imm"); entity_impl!(Immediate, "imm");
@@ -267,6 +273,7 @@ impl JumpTable {
/// ///
/// While the order is stable, it is arbitrary. /// While the order is stable, it is arbitrary.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct FuncRef(u32); pub struct FuncRef(u32);
entity_impl!(FuncRef, "fn"); entity_impl!(FuncRef, "fn");
@@ -298,6 +305,7 @@ impl FuncRef {
/// ///
/// While the order is stable, it is arbitrary. /// While the order is stable, it is arbitrary.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct SigRef(u32); pub struct SigRef(u32);
entity_impl!(SigRef, "sig"); entity_impl!(SigRef, "sig");
@@ -323,6 +331,7 @@ impl SigRef {
/// ///
/// While the order is stable, it is arbitrary. /// While the order is stable, it is arbitrary.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct Heap(u32); pub struct Heap(u32);
entity_impl!(Heap, "heap"); entity_impl!(Heap, "heap");
@@ -349,6 +358,7 @@ impl Heap {
/// ///
/// While the order is stable, it is arbitrary. /// While the order is stable, it is arbitrary.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct Table(u32); pub struct Table(u32);
entity_impl!(Table, "table"); entity_impl!(Table, "table");
@@ -367,6 +377,7 @@ impl Table {
/// An opaque reference to any of the entities defined in this module that can appear in CLIF IR. /// An opaque reference to any of the entities defined in this module that can appear in CLIF IR.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub enum AnyEntity { pub enum AnyEntity {
/// The whole function. /// The whole function.
Function, Function,

View File

@@ -409,6 +409,7 @@ impl FromStr for ArgumentPurpose {
/// ///
/// Information about a function that can be called directly with a direct `call` instruction. /// Information about a function that can be called directly with a direct `call` instruction.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct ExtFuncData { pub struct ExtFuncData {
/// Name of the external function. /// Name of the external function.
pub name: ExternalName, pub name: ExternalName,

View File

@@ -9,6 +9,9 @@ use core::cmp;
use core::fmt::{self, Write}; use core::fmt::{self, Write};
use core::str::FromStr; use core::str::FromStr;
#[cfg(feature = "enable-serde")]
use serde::{Deserialize, Serialize};
const TESTCASE_NAME_LENGTH: usize = 16; const TESTCASE_NAME_LENGTH: usize = 16;
/// The name of an external is either a reference to a user-defined symbol /// The name of an external is either a reference to a user-defined symbol
@@ -23,6 +26,7 @@ const TESTCASE_NAME_LENGTH: usize = 16;
/// In particular, many `.clif` test files use function names to identify /// In particular, many `.clif` test files use function names to identify
/// functions. /// functions.
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub enum ExternalName { pub enum ExternalName {
/// A name in a user-defined symbol table. Cranelift does not interpret /// A name in a user-defined symbol table. Cranelift does not interpret
/// these numbers in any way. /// these numbers in any way.

View File

@@ -21,11 +21,15 @@ use crate::write::write_function;
use alloc::vec::Vec; use alloc::vec::Vec;
use core::fmt; use core::fmt;
#[cfg(feature = "enable-serde")]
use serde::{Deserialize, Serialize};
/// A function. /// A function.
/// ///
/// Functions can be cloned, but it is not a very fast operation. /// Functions can be cloned, but it is not a very fast operation.
/// The clone will have all the same entity numbers as the original. /// The clone will have all the same entity numbers as the original.
#[derive(Clone)] #[derive(Clone)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct Function { pub struct Function {
/// Name of this function. Mostly used by `.clif` files. /// Name of this function. Mostly used by `.clif` files.
pub name: ExternalName, pub name: ExternalName,

View File

@@ -6,8 +6,12 @@ use crate::isa::TargetIsa;
use crate::machinst::RelocDistance; use crate::machinst::RelocDistance;
use core::fmt; use core::fmt;
#[cfg(feature = "enable-serde")]
use serde::{Deserialize, Serialize};
/// Information about a global value declaration. /// Information about a global value declaration.
#[derive(Clone)] #[derive(Clone)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub enum GlobalValueData { pub enum GlobalValueData {
/// Value is the address of the VM context struct. /// Value is the address of the VM context struct.
VMContext, VMContext,

View File

@@ -4,8 +4,12 @@ use crate::ir::immediates::Uimm64;
use crate::ir::{GlobalValue, Type}; use crate::ir::{GlobalValue, Type};
use core::fmt; use core::fmt;
#[cfg(feature = "enable-serde")]
use serde::{Deserialize, Serialize};
/// Information about a heap declaration. /// Information about a heap declaration.
#[derive(Clone)] #[derive(Clone)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct HeapData { pub struct HeapData {
/// The address of the start of the heap's storage. /// The address of the start of the heap's storage.
pub base: GlobalValue, pub base: GlobalValue,
@@ -26,6 +30,7 @@ pub struct HeapData {
/// Style of heap including style-specific information. /// Style of heap including style-specific information.
#[derive(Clone)] #[derive(Clone)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub enum HeapStyle { pub enum HeapStyle {
/// A dynamic heap can be relocated to a different base address when it is grown. /// A dynamic heap can be relocated to a different base address when it is grown.
Dynamic { Dynamic {

View File

@@ -48,6 +48,7 @@ impl IntoBytes for Vec<u8> {
/// An `Imm64` operand can also be used to represent immediate values of smaller integer types by /// An `Imm64` operand can also be used to represent immediate values of smaller integer types by
/// sign-extending to `i64`. /// sign-extending to `i64`.
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct Imm64(i64); pub struct Imm64(i64);
impl Imm64 { impl Imm64 {
@@ -148,6 +149,7 @@ impl FromStr for Imm64 {
/// A `Uimm64` operand can also be used to represent immediate values of smaller integer types by /// A `Uimm64` operand can also be used to represent immediate values of smaller integer types by
/// zero-extending to `i64`. /// zero-extending to `i64`.
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct Uimm64(u64); pub struct Uimm64(u64);
impl Uimm64 { impl Uimm64 {
@@ -279,6 +281,7 @@ pub type Uimm8 = u8;
/// ///
/// This is used to represent sizes of memory objects. /// This is used to represent sizes of memory objects.
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct Uimm32(u32); pub struct Uimm32(u32);
impl Into<u32> for Uimm32 { impl Into<u32> for Uimm32 {
@@ -362,6 +365,7 @@ impl From<&[u8]> for V128Imm {
/// This is used to encode an immediate offset for load/store instructions. All supported ISAs have /// This is used to encode an immediate offset for load/store instructions. All supported ISAs have
/// a maximum load/store offset that fits in an `i32`. /// a maximum load/store offset that fits in an `i32`.
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct Offset32(i32); pub struct Offset32(i32);
impl Offset32 { impl Offset32 {
@@ -451,6 +455,7 @@ impl FromStr for Offset32 {
/// ///
/// All bit patterns are allowed. /// All bit patterns are allowed.
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[repr(C)] #[repr(C)]
pub struct Ieee32(u32); pub struct Ieee32(u32);
@@ -459,6 +464,7 @@ pub struct Ieee32(u32);
/// ///
/// All bit patterns are allowed. /// All bit patterns are allowed.
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
#[repr(C)] #[repr(C)]
pub struct Ieee64(u64); pub struct Ieee64(u64);

View File

@@ -13,6 +13,9 @@ use core::num::NonZeroU32;
use core::ops::{Deref, DerefMut}; use core::ops::{Deref, DerefMut};
use core::str::FromStr; use core::str::FromStr;
#[cfg(feature = "enable-serde")]
use serde::{Deserialize, Serialize};
use crate::ir::{self, trapcode::TrapCode, types, Block, FuncRef, JumpTable, SigRef, Type, Value}; use crate::ir::{self, trapcode::TrapCode, types, Block, FuncRef, JumpTable, SigRef, Type, Value};
use crate::isa; use crate::isa;

View File

@@ -8,10 +8,14 @@ use alloc::vec::Vec;
use core::fmt::{self, Display, Formatter}; use core::fmt::{self, Display, Formatter};
use core::slice::{Iter, IterMut}; use core::slice::{Iter, IterMut};
#[cfg(feature = "enable-serde")]
use serde::{Deserialize, Serialize};
/// Contents of a jump table. /// Contents of a jump table.
/// ///
/// All jump tables use 0-based indexing and are densely populated. /// All jump tables use 0-based indexing and are densely populated.
#[derive(Clone)] #[derive(Clone)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct JumpTableData { pub struct JumpTableData {
// Table entries. // Table entries.
table: Vec<Block>, table: Vec<Block>,

View File

@@ -781,6 +781,86 @@ impl<'f> DoubleEndedIterator for Insts<'f> {
} }
} }
#[cfg(feature = "enable-serde")]
mod serde {
use ::serde::de::{Deserializer, Error, SeqAccess, Visitor};
use ::serde::ser::{SerializeSeq, Serializer};
use ::serde::{Deserialize, Serialize};
use core::convert::TryFrom;
use core::fmt;
use core::marker::PhantomData;
use super::*;
impl Serialize for Layout {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let size = self.blocks().count() * 2
+ self
.blocks()
.map(|block| self.block_insts(block).count())
.sum::<usize>();
let mut seq = serializer.serialize_seq(Some(size))?;
for block in self.blocks() {
seq.serialize_element(&block)?;
seq.serialize_element(&u32::try_from(self.block_insts(block).count()).unwrap())?;
for inst in self.block_insts(block) {
seq.serialize_element(&inst)?;
}
}
seq.end()
}
}
impl<'de> Deserialize<'de> for Layout {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_seq(LayoutVisitor {
marker: PhantomData,
})
}
}
struct LayoutVisitor {
marker: PhantomData<fn() -> Layout>,
}
impl<'de> Visitor<'de> for LayoutVisitor {
type Value = Layout;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "a `cranelift_codegen::ir::Layout`")
}
fn visit_seq<M>(self, mut access: M) -> Result<Self::Value, M::Error>
where
M: SeqAccess<'de>,
{
let mut layout = Layout::new();
while let Some(block) = access.next_element::<Block>()? {
layout.append_block(block);
let count = access
.next_element::<u32>()?
.ok_or_else(|| Error::missing_field("count"))?;
for _ in 0..count {
let inst = access
.next_element::<Inst>()?
.ok_or_else(|| Error::missing_field("inst"))?;
layout.append_inst(inst, block);
}
}
Ok(layout)
}
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::Layout; use super::Layout;

View File

@@ -2,6 +2,9 @@
use core::fmt; use core::fmt;
#[cfg(feature = "enable-serde")]
use serde::{Deserialize, Serialize};
enum FlagBit { enum FlagBit {
Notrap, Notrap,
Aligned, Aligned,
@@ -32,6 +35,7 @@ pub enum Endianness {
/// be overridden for individual accesses by explicitly specifying little- or big-endian /// be overridden for individual accesses by explicitly specifying little- or big-endian
/// semantics via the flags. /// semantics via the flags.
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)] #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct MemFlags { pub struct MemFlags {
bits: u8, bits: u8,
} }

View File

@@ -91,6 +91,7 @@ entity_impl!(ValueLabel, "val");
/// A label of a Value. /// A label of a Value.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct ValueLabelStart { pub struct ValueLabelStart {
/// Source location when it is in effect /// Source location when it is in effect
pub from: SourceLoc, pub from: SourceLoc,
@@ -101,6 +102,7 @@ pub struct ValueLabelStart {
/// Value label assignements: label starts or value aliases. /// Value label assignements: label starts or value aliases.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub enum ValueLabelAssignments { pub enum ValueLabelAssignments {
/// Original value labels assigned at transform. /// Original value labels assigned at transform.
Starts(alloc::vec::Vec<ValueLabelStart>), Starts(alloc::vec::Vec<ValueLabelStart>),

View File

@@ -4,8 +4,12 @@ use crate::ir::immediates::Uimm64;
use crate::ir::{GlobalValue, Type}; use crate::ir::{GlobalValue, Type};
use core::fmt; use core::fmt;
#[cfg(feature = "enable-serde")]
use serde::{Deserialize, Serialize};
/// Information about a table declaration. /// Information about a table declaration.
#[derive(Clone)] #[derive(Clone)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct TableData { pub struct TableData {
/// Global value giving the address of the start of the table. /// Global value giving the address of the start of the table.
pub base_gv: GlobalValue, pub base_gv: GlobalValue,

View File

@@ -6,6 +6,9 @@ use crate::isa::constraints::{BranchRange, RecipeConstraints};
use crate::regalloc::RegDiversions; use crate::regalloc::RegDiversions;
use core::fmt; use core::fmt;
#[cfg(feature = "enable-serde")]
use serde::{Deserialize, Serialize};
/// Bits needed to encode an instruction as binary machine code. /// Bits needed to encode an instruction as binary machine code.
/// ///
/// The encoding consists of two parts, both specific to the target ISA: An encoding *recipe*, and /// The encoding consists of two parts, both specific to the target ISA: An encoding *recipe*, and
@@ -13,6 +16,7 @@ use core::fmt;
/// operands to encoded bits. The encoding bits provide additional information to the recipe, /// operands to encoded bits. The encoding bits provide additional information to the recipe,
/// typically parts of the opcode. /// typically parts of the opcode.
#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct Encoding { pub struct Encoding {
recipe: u16, recipe: u16,
bits: u16, bits: u16,

View File

@@ -15,6 +15,9 @@ use crate::isa::{RegInfo, RegUnit};
use core::fmt; use core::fmt;
use cranelift_entity::{SparseMap, SparseMapValue}; use cranelift_entity::{SparseMap, SparseMapValue};
#[cfg(feature = "enable-serde")]
use serde::{Deserialize, Serialize};
/// A diversion of a value from its original location to a new register or stack location. /// A diversion of a value from its original location to a new register or stack location.
/// ///
/// In IR, a diversion is represented by a `regmove` instruction, possibly a chain of them for the /// In IR, a diversion is represented by a `regmove` instruction, possibly a chain of them for the
@@ -23,6 +26,7 @@ use cranelift_entity::{SparseMap, SparseMapValue};
/// When tracking diversions, the `from` field is the original assigned value location, and `to` is /// When tracking diversions, the `from` field is the original assigned value location, and `to` is
/// the current one. /// the current one.
#[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct Diversion { pub struct Diversion {
/// The original value location. /// The original value location.
pub from: ValueLoc, pub from: ValueLoc,
@@ -40,18 +44,21 @@ impl Diversion {
/// Keep track of diversions in a block. /// Keep track of diversions in a block.
#[derive(Clone)] #[derive(Clone)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct RegDiversions { pub struct RegDiversions {
current: FxHashMap<Value, Diversion>, current: FxHashMap<Value, Diversion>,
} }
/// Keep track of diversions at the entry of block. /// Keep track of diversions at the entry of block.
#[derive(Clone)] #[derive(Clone)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
struct EntryRegDiversionsValue { struct EntryRegDiversionsValue {
key: Block, key: Block,
divert: RegDiversions, divert: RegDiversions,
} }
/// Map block to their matching RegDiversions at basic blocks entry. /// Map block to their matching RegDiversions at basic blocks entry.
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct EntryRegDiversions { pub struct EntryRegDiversions {
map: SparseMap<Block, EntryRegDiversionsValue>, map: SparseMap<Block, EntryRegDiversionsValue>,
} }

View File

@@ -5,6 +5,9 @@ use alloc::vec::Vec;
use core::marker::PhantomData; use core::marker::PhantomData;
use core::mem; use core::mem;
#[cfg(feature = "enable-serde")]
use serde::{Deserialize, Serialize};
/// A small list of entity references allocated from a pool. /// A small list of entity references allocated from a pool.
/// ///
/// An `EntityList<T>` type provides similar functionality to `Vec<T>`, but with some important /// An `EntityList<T>` type provides similar functionality to `Vec<T>`, but with some important
@@ -59,7 +62,8 @@ use core::mem;
/// ///
/// The index stored in an `EntityList` points to part 2, the list elements. The value 0 is /// The index stored in an `EntityList` points to part 2, the list elements. The value 0 is
/// reserved for the empty list which isn't allocated in the vector. /// reserved for the empty list which isn't allocated in the vector.
#[derive(Clone, Debug)] #[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct EntityList<T: EntityRef + ReservedValue> { pub struct EntityList<T: EntityRef + ReservedValue> {
index: u32, index: u32,
unused: PhantomData<T>, unused: PhantomData<T>,
@@ -77,6 +81,7 @@ impl<T: EntityRef + ReservedValue> Default for EntityList<T> {
/// A memory pool for storing lists of `T`. /// A memory pool for storing lists of `T`.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct ListPool<T: EntityRef + ReservedValue> { pub struct ListPool<T: EntityRef + ReservedValue> {
// The main array containing the lists. // The main array containing the lists.
data: Vec<T>, data: Vec<T>,

View File

@@ -10,6 +10,9 @@
use core::fmt; use core::fmt;
use core::mem; use core::mem;
#[cfg(feature = "enable-serde")]
use serde::{Deserialize, Serialize};
/// Types that have a reserved value which can't be created any other way. /// Types that have a reserved value which can't be created any other way.
pub trait ReservedValue { pub trait ReservedValue {
/// Create an instance of the reserved value. /// Create an instance of the reserved value.
@@ -20,6 +23,7 @@ pub trait ReservedValue {
/// Packed representation of `Option<T>`. /// Packed representation of `Option<T>`.
#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)] #[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct PackedOption<T: ReservedValue>(T); pub struct PackedOption<T: ReservedValue>(T);
impl<T: ReservedValue> PackedOption<T> { impl<T: ReservedValue> PackedOption<T> {

View File

@@ -14,6 +14,9 @@ use core::mem;
use core::slice; use core::slice;
use core::u32; use core::u32;
#[cfg(feature = "enable-serde")]
use serde::{Deserialize, Serialize};
/// Trait for extracting keys from values stored in a `SparseMap`. /// Trait for extracting keys from values stored in a `SparseMap`.
/// ///
/// All values stored in a `SparseMap` must keep track of their own key in the map and implement /// All values stored in a `SparseMap` must keep track of their own key in the map and implement
@@ -53,6 +56,7 @@ pub trait SparseMapValue<K> {
/// is). /// is).
/// - `SparseMap` requires the values to implement `SparseMapValue<K>` which means that they must /// - `SparseMap` requires the values to implement `SparseMapValue<K>` which means that they must
/// contain their own key. /// contain their own key.
#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
pub struct SparseMap<K, V> pub struct SparseMap<K, V>
where where
K: EntityRef, K: EntityRef,