cranelift_codegen_meta/cdsl/
formats.rs1use crate::cdsl::operands::OperandKind;
2use std::fmt;
3use std::rc::Rc;
4
5#[derive(Debug)]
10pub(crate) struct FormatField {
11    pub kind: OperandKind,
13
14    pub member: &'static str,
16}
17
18#[derive(Debug)]
30pub(crate) struct InstructionFormat {
31    pub name: &'static str,
34
35    pub num_value_operands: usize,
36
37    pub has_value_list: bool,
38
39    pub imm_fields: Vec<FormatField>,
40
41    pub num_block_operands: usize,
42
43    pub num_raw_block_operands: usize,
44
45    pub typevar_operand: Option<usize>,
49}
50
51#[derive(Hash, PartialEq, Eq)]
53pub(crate) struct FormatStructure {
54    pub num_value_operands: usize,
55    pub has_value_list: bool,
56    pub num_block_operands: usize,
57    pub num_raw_block_operands: usize,
58    pub imm_field_names: Vec<(&'static str, &'static str)>,
60}
61
62impl fmt::Display for InstructionFormat {
63    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
64        let imm_args = self
65            .imm_fields
66            .iter()
67            .map(|field| format!("{}: {}", field.member, field.kind.rust_type))
68            .collect::<Vec<_>>()
69            .join(", ");
70        fmt.write_fmt(format_args!(
71            "{}(imms=({}), vals={}, blocks={}, raw_blocks={})",
72            self.name,
73            imm_args,
74            self.num_value_operands,
75            self.num_block_operands,
76            self.num_raw_block_operands,
77        ))?;
78        Ok(())
79    }
80}
81
82impl InstructionFormat {
83    pub fn structure(&self) -> FormatStructure {
85        FormatStructure {
86            num_value_operands: self.num_value_operands,
87            has_value_list: self.has_value_list,
88            num_block_operands: self.num_block_operands,
89            num_raw_block_operands: self.num_raw_block_operands,
90            imm_field_names: self
91                .imm_fields
92                .iter()
93                .map(|field| (field.kind.rust_field_name, field.kind.rust_type))
94                .collect::<Vec<_>>(),
95        }
96    }
97}
98
99pub(crate) struct InstructionFormatBuilder(InstructionFormat);
100
101impl InstructionFormatBuilder {
102    pub fn new(name: &'static str) -> Self {
103        Self(InstructionFormat {
104            name,
105            num_value_operands: 0,
106            has_value_list: false,
107            num_block_operands: 0,
108            num_raw_block_operands: 0,
109            imm_fields: Vec::new(),
110            typevar_operand: None,
111        })
112    }
113
114    pub fn value(mut self) -> Self {
115        self.0.num_value_operands += 1;
116        self
117    }
118
119    pub fn varargs(mut self) -> Self {
120        self.0.has_value_list = true;
121        self
122    }
123
124    pub fn block(mut self) -> Self {
125        self.0.num_block_operands += 1;
126        self
127    }
128
129    pub fn raw_block(mut self) -> Self {
130        self.0.num_raw_block_operands += 1;
131        self
132    }
133
134    pub fn imm(mut self, operand_kind: &OperandKind) -> Self {
135        let field = FormatField {
136            kind: operand_kind.clone(),
137            member: operand_kind.rust_field_name,
138        };
139        self.0.imm_fields.push(field);
140        self
141    }
142
143    pub fn typevar_operand(mut self, operand_index: usize) -> Self {
144        assert!(self.0.typevar_operand.is_none());
145        assert!(operand_index < self.0.num_value_operands);
146        self.0.typevar_operand = Some(operand_index);
147        self
148    }
149
150    pub fn build(mut self) -> Rc<InstructionFormat> {
151        if self.0.typevar_operand.is_none() && self.0.num_value_operands > 0 {
152            self.0.typevar_operand = Some(0);
154        };
155
156        Rc::new(self.0)
157    }
158}