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