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