Skip to main content

pcode_types/
lib.rs

1//! The vocabulary types shared between a p-code *producer* and a p-code
2//! *consumer*.
3//!
4//! A SLEIGH specification describes memory spaces, processor registers and
5//! user-defined p-code operations; an IR built from that specification refers
6//! to the same things. Both sides need to agree on how those are identified, so
7//! the definitions live here rather than in either crate — which lets the
8//! decoder and the IR depend on each other only through this vocabulary.
9//!
10//! These types appear directly in precompiled specification blobs, so their
11//! serialized form is part of the producer/consumer compatibility contract.
12//! A producer must version its blob format; serde alone does not provide a
13//! cross-version or cross-platform wire-format guarantee.
14
15pub mod error;
16pub mod expression;
17pub mod instruction;
18pub mod register;
19pub mod space;
20pub mod statement;
21
22pub use error::{PcodeError, PcodeErrorTy, PcodeResult};
23pub use expression::{
24    BinaryOperator, Binop, Builtin, Expression, ExpressionTy, Ident, Load, LocalVarId,
25    LocalVarInterner, Range, RangeParam, SpaceRef as PcodeSpaceRef, UnaryOperator, Unop,
26    pretty_print_ident,
27};
28pub use instruction::{
29    BitRangeInfo, BodyWidths, InstructionPcode, LabelId, LocalSizes, Opcode, PcodeLowerError,
30    PcodeLoweringContext, PcodeOp, PcodePlan, PcodeSink, SymbolicWidth, Varnode, Width,
31    emit_instruction, infer_local_sizes, lower_instruction, lower_instruction_into,
32    plan_instruction, plan_instruction_with, resolve_body_widths,
33};
34pub use register::{Register, RegisterId, RegisterMutRef, RegisterRef};
35pub use space::{SPACE_CONST, Space, SpaceId, SpaceRef, SpaceStore, SpaceType};
36pub use statement::{Ast, AstNode, DelaySlotArg, LabelOrNode};
37
38use jstd::Identifier;
39
40/// A stable identifier for a user-defined p-code operation.
41///
42/// These are the `define pcodeop` names in a SLEIGH specification: operations
43/// with no p-code semantics, which a consumer must interpret itself.
44#[derive(Identifier)]
45pub struct PCodeOpId(usize);
46
47/// Identifier used by source-shaped p-code for a decoder field.
48#[derive(Identifier)]
49pub struct FieldId(usize);
50/// Identifier used by `build` statements for a decoder table.
51#[derive(Identifier)]
52pub struct TableId(usize);
53/// Identifier of a p-code macro definition.
54#[derive(Identifier)]
55pub struct PMacroId(usize);
56/// Identifier of a named register bit range.
57#[derive(Identifier)]
58pub struct BitRangeFieldId(usize);
59
60/// Backend-neutral, source-shaped p-code AST for one decoded instruction.
61#[derive(Debug, Clone, PartialEq, Eq, Default, serde::Serialize, serde::Deserialize)]
62pub struct PcodeAst {
63    /// Statements in execution order.
64    pub statements: Vec<Ast>,
65}
66
67impl PcodeAst {
68    /// Pretty-prints the statements using a producer-specific name resolver.
69    pub fn pretty_print(&self, resolver: &impl PcodeResolver) -> String {
70        self.statements
71            .iter()
72            .map(|statement| statement.pretty_print(resolver))
73            .collect::<Vec<_>>()
74            .join("\n")
75    }
76}
77
78/// Supplies names for formatting a p-code AST without coupling it to a
79/// particular producer such as SLEIGH.
80pub trait PcodeResolver {
81    /// Name of an identifier.
82    fn ident_name(&self, ident: &Ident) -> String;
83    /// Name of a field.
84    fn field_name(&self, id: FieldId) -> String;
85    /// Name of an address space.
86    fn space_name(&self, id: SpaceId) -> String;
87    /// Name of a user-defined operation.
88    fn pcode_op_name(&self, id: PCodeOpId) -> String;
89    /// Name of a macro.
90    fn macro_name(&self, id: PMacroId) -> String;
91}