1 use crate::cdsl::operands::{EnumValues, OperandKind, OperandKindFields};
2 
3 use std::collections::HashMap;
4 
5 pub(crate) struct Immediates {
6     /// A 64-bit immediate integer operand.
7     ///
8     /// This type of immediate integer can interact with SSA values with any IntType type.
9     pub imm64: OperandKind,
10 
11     /// An unsigned 8-bit immediate integer operand.
12     ///
13     /// This small operand is used to indicate lane indexes in SIMD vectors and immediate bit
14     /// counts on shift instructions.
15     pub uimm8: OperandKind,
16 
17     /// An unsigned 32-bit immediate integer operand.
18     pub uimm32: OperandKind,
19 
20     /// An unsigned 128-bit immediate integer operand.
21     ///
22     /// This operand is used to pass entire 128-bit vectors as immediates to instructions like
23     /// const.
24     pub uimm128: OperandKind,
25 
26     /// A constant stored in the constant pool.
27     ///
28     /// This operand is used to pass constants to instructions like vconst while storing the
29     /// actual bytes in the constant pool.
30     pub pool_constant: OperandKind,
31 
32     /// A 32-bit immediate signed offset.
33     ///
34     /// This is used to represent an immediate address offset in load/store instructions.
35     pub offset32: OperandKind,
36 
37     /// A 32-bit immediate floating point operand.
38     ///
39     /// IEEE 754-2008 binary32 interchange format.
40     pub ieee32: OperandKind,
41 
42     /// A 64-bit immediate floating point operand.
43     ///
44     /// IEEE 754-2008 binary64 interchange format.
45     pub ieee64: OperandKind,
46 
47     /// An immediate boolean operand.
48     ///
49     /// This type of immediate boolean can interact with SSA values with any BoolType type.
50     pub boolean: OperandKind,
51 
52     /// A condition code for comparing integer values.
53     ///
54     /// This enumerated operand kind is used for the `icmp` instruction and corresponds to the
55     /// condcodes::IntCC` Rust type.
56     pub intcc: OperandKind,
57 
58     /// A condition code for comparing floating point values.
59     ///
60     /// This enumerated operand kind is used for the `fcmp` instruction and corresponds to the
61     /// `condcodes::FloatCC` Rust type.
62     pub floatcc: OperandKind,
63 
64     /// Flags for memory operations like `load` and `store`.
65     pub memflags: OperandKind,
66 
67     /// A trap code indicating the reason for trapping.
68     ///
69     /// The Rust enum type also has a `User(u16)` variant for user-provided trap codes.
70     pub trapcode: OperandKind,
71 
72     /// A code indicating the arithmetic operation to perform in an atomic_rmw memory access.
73     pub atomic_rmw_op: OperandKind,
74 }
75 
76 fn new_imm(
77     format_field_name: &'static str,
78     rust_type: &'static str,
79     doc: &'static str,
80 ) -> OperandKind {
81     OperandKind::new(
82         format_field_name,
83         rust_type,
84         OperandKindFields::ImmValue,
85         doc,
86     )
87 }
88 fn new_enum(
89     format_field_name: &'static str,
90     rust_type: &'static str,
91     values: EnumValues,
92     doc: &'static str,
93 ) -> OperandKind {
94     OperandKind::new(
95         format_field_name,
96         rust_type,
97         OperandKindFields::ImmEnum(values),
98         doc,
99     )
100 }
101 
102 impl Immediates {
103     pub fn new() -> Self {
104         Self {
105             imm64: new_imm(
106                 "imm",
107                 "ir::immediates::Imm64",
108                 "A 64-bit immediate integer.",
109             ),
110             uimm8: new_imm(
111                 "imm",
112                 "ir::immediates::Uimm8",
113                 "An 8-bit immediate unsigned integer.",
114             ),
115             uimm32: new_imm(
116                 "imm",
117                 "ir::immediates::Uimm32",
118                 "A 32-bit immediate unsigned integer.",
119             ),
120             uimm128: new_imm(
121                 "imm",
122                 "ir::Immediate",
123                 "A 128-bit immediate unsigned integer.",
124             ),
125             pool_constant: new_imm(
126                 "constant_handle",
127                 "ir::Constant",
128                 "A constant stored in the constant pool.",
129             ),
130             offset32: new_imm(
131                 "offset",
132                 "ir::immediates::Offset32",
133                 "A 32-bit immediate signed offset.",
134             ),
135             ieee32: new_imm(
136                 "imm",
137                 "ir::immediates::Ieee32",
138                 "A 32-bit immediate floating point number.",
139             ),
140             ieee64: new_imm(
141                 "imm",
142                 "ir::immediates::Ieee64",
143                 "A 64-bit immediate floating point number.",
144             ),
145             boolean: new_imm("imm", "bool", "An immediate boolean."),
146             intcc: {
147                 let mut intcc_values = HashMap::new();
148                 intcc_values.insert("eq", "Equal");
149                 intcc_values.insert("ne", "NotEqual");
150                 intcc_values.insert("sge", "SignedGreaterThanOrEqual");
151                 intcc_values.insert("sgt", "SignedGreaterThan");
152                 intcc_values.insert("sle", "SignedLessThanOrEqual");
153                 intcc_values.insert("slt", "SignedLessThan");
154                 intcc_values.insert("uge", "UnsignedGreaterThanOrEqual");
155                 intcc_values.insert("ugt", "UnsignedGreaterThan");
156                 intcc_values.insert("ule", "UnsignedLessThanOrEqual");
157                 intcc_values.insert("ult", "UnsignedLessThan");
158                 intcc_values.insert("of", "Overflow");
159                 intcc_values.insert("nof", "NotOverflow");
160                 new_enum(
161                     "cond",
162                     "ir::condcodes::IntCC",
163                     intcc_values,
164                     "An integer comparison condition code.",
165                 )
166             },
167 
168             floatcc: {
169                 let mut floatcc_values = HashMap::new();
170                 floatcc_values.insert("ord", "Ordered");
171                 floatcc_values.insert("uno", "Unordered");
172                 floatcc_values.insert("eq", "Equal");
173                 floatcc_values.insert("ne", "NotEqual");
174                 floatcc_values.insert("one", "OrderedNotEqual");
175                 floatcc_values.insert("ueq", "UnorderedOrEqual");
176                 floatcc_values.insert("lt", "LessThan");
177                 floatcc_values.insert("le", "LessThanOrEqual");
178                 floatcc_values.insert("gt", "GreaterThan");
179                 floatcc_values.insert("ge", "GreaterThanOrEqual");
180                 floatcc_values.insert("ult", "UnorderedOrLessThan");
181                 floatcc_values.insert("ule", "UnorderedOrLessThanOrEqual");
182                 floatcc_values.insert("ugt", "UnorderedOrGreaterThan");
183                 floatcc_values.insert("uge", "UnorderedOrGreaterThanOrEqual");
184                 new_enum(
185                     "cond",
186                     "ir::condcodes::FloatCC",
187                     floatcc_values,
188                     "A floating point comparison condition code",
189                 )
190             },
191 
192             memflags: new_imm("flags", "ir::MemFlags", "Memory operation flags"),
193             trapcode: {
194                 let mut trapcode_values = HashMap::new();
195                 trapcode_values.insert("stk_ovf", "StackOverflow");
196                 trapcode_values.insert("heap_oob", "HeapOutOfBounds");
197                 trapcode_values.insert("int_ovf", "IntegerOverflow");
198                 trapcode_values.insert("int_divz", "IntegerDivisionByZero");
199                 new_enum(
200                     "code",
201                     "ir::TrapCode",
202                     trapcode_values,
203                     "A trap reason code.",
204                 )
205             },
206             atomic_rmw_op: {
207                 let mut atomic_rmw_op_values = HashMap::new();
208                 atomic_rmw_op_values.insert("add", "Add");
209                 atomic_rmw_op_values.insert("sub", "Sub");
210                 atomic_rmw_op_values.insert("and", "And");
211                 atomic_rmw_op_values.insert("nand", "Nand");
212                 atomic_rmw_op_values.insert("or", "Or");
213                 atomic_rmw_op_values.insert("xor", "Xor");
214                 atomic_rmw_op_values.insert("xchg", "Xchg");
215                 atomic_rmw_op_values.insert("umin", "Umin");
216                 atomic_rmw_op_values.insert("umax", "Umax");
217                 atomic_rmw_op_values.insert("smin", "Smin");
218                 atomic_rmw_op_values.insert("smax", "Smax");
219                 new_enum(
220                     "op",
221                     "ir::AtomicRmwOp",
222                     atomic_rmw_op_values,
223                     "Atomic Read-Modify-Write Ops",
224                 )
225             },
226         }
227     }
228 }
229