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 register unit in the current target ISA.
68     pub regunit: OperandKind,
69 
70     /// A trap code indicating the reason for trapping.
71     ///
72     /// The Rust enum type also has a `User(u16)` variant for user-provided trap codes.
73     pub trapcode: OperandKind,
74 
75     /// A code indicating the arithmetic operation to perform in an atomic_rmw memory access.
76     pub atomic_rmw_op: OperandKind,
77 }
78 
new_imm(format_field_name: &'static str, rust_type: &'static str) -> OperandKind79 fn new_imm(format_field_name: &'static str, rust_type: &'static str) -> OperandKind {
80     OperandKind::new(format_field_name, rust_type, OperandKindFields::ImmValue)
81 }
new_enum( format_field_name: &'static str, rust_type: &'static str, values: EnumValues, ) -> OperandKind82 fn new_enum(
83     format_field_name: &'static str,
84     rust_type: &'static str,
85     values: EnumValues,
86 ) -> OperandKind {
87     OperandKind::new(
88         format_field_name,
89         rust_type,
90         OperandKindFields::ImmEnum(values),
91     )
92 }
93 
94 impl Immediates {
new() -> Self95     pub fn new() -> Self {
96         Self {
97             imm64: new_imm("imm", "ir::immediates::Imm64").with_doc("A 64-bit immediate integer."),
98             uimm8: new_imm("imm", "ir::immediates::Uimm8")
99                 .with_doc("An 8-bit immediate unsigned integer."),
100             uimm32: new_imm("imm", "ir::immediates::Uimm32")
101                 .with_doc("A 32-bit immediate unsigned integer."),
102             uimm128: new_imm("imm", "ir::Immediate")
103                 .with_doc("A 128-bit immediate unsigned integer."),
104             pool_constant: new_imm("constant_handle", "ir::Constant")
105                 .with_doc("A constant stored in the constant pool."),
106             offset32: new_imm("offset", "ir::immediates::Offset32")
107                 .with_doc("A 32-bit immediate signed offset."),
108             ieee32: new_imm("imm", "ir::immediates::Ieee32")
109                 .with_doc("A 32-bit immediate floating point number."),
110             ieee64: new_imm("imm", "ir::immediates::Ieee64")
111                 .with_doc("A 64-bit immediate floating point number."),
112             boolean: new_imm("imm", "bool").with_doc("An immediate boolean."),
113             intcc: {
114                 let mut intcc_values = HashMap::new();
115                 intcc_values.insert("eq", "Equal");
116                 intcc_values.insert("ne", "NotEqual");
117                 intcc_values.insert("sge", "SignedGreaterThanOrEqual");
118                 intcc_values.insert("sgt", "SignedGreaterThan");
119                 intcc_values.insert("sle", "SignedLessThanOrEqual");
120                 intcc_values.insert("slt", "SignedLessThan");
121                 intcc_values.insert("uge", "UnsignedGreaterThanOrEqual");
122                 intcc_values.insert("ugt", "UnsignedGreaterThan");
123                 intcc_values.insert("ule", "UnsignedLessThanOrEqual");
124                 intcc_values.insert("ult", "UnsignedLessThan");
125                 intcc_values.insert("of", "Overflow");
126                 intcc_values.insert("nof", "NotOverflow");
127                 new_enum("cond", "ir::condcodes::IntCC", intcc_values)
128                     .with_doc("An integer comparison condition code.")
129             },
130 
131             floatcc: {
132                 let mut floatcc_values = HashMap::new();
133                 floatcc_values.insert("ord", "Ordered");
134                 floatcc_values.insert("uno", "Unordered");
135                 floatcc_values.insert("eq", "Equal");
136                 floatcc_values.insert("ne", "NotEqual");
137                 floatcc_values.insert("one", "OrderedNotEqual");
138                 floatcc_values.insert("ueq", "UnorderedOrEqual");
139                 floatcc_values.insert("lt", "LessThan");
140                 floatcc_values.insert("le", "LessThanOrEqual");
141                 floatcc_values.insert("gt", "GreaterThan");
142                 floatcc_values.insert("ge", "GreaterThanOrEqual");
143                 floatcc_values.insert("ult", "UnorderedOrLessThan");
144                 floatcc_values.insert("ule", "UnorderedOrLessThanOrEqual");
145                 floatcc_values.insert("ugt", "UnorderedOrGreaterThan");
146                 floatcc_values.insert("uge", "UnorderedOrGreaterThanOrEqual");
147                 new_enum("cond", "ir::condcodes::FloatCC", floatcc_values)
148                     .with_doc("A floating point comparison condition code")
149             },
150 
151             memflags: new_imm("flags", "ir::MemFlags").with_doc("Memory operation flags"),
152             regunit: new_imm("regunit", "isa::RegUnit")
153                 .with_doc("A register unit in the target ISA"),
154             trapcode: {
155                 let mut trapcode_values = HashMap::new();
156                 trapcode_values.insert("stk_ovf", "StackOverflow");
157                 trapcode_values.insert("heap_oob", "HeapOutOfBounds");
158                 trapcode_values.insert("int_ovf", "IntegerOverflow");
159                 trapcode_values.insert("int_divz", "IntegerDivisionByZero");
160                 new_enum("code", "ir::TrapCode", trapcode_values).with_doc("A trap reason code.")
161             },
162             atomic_rmw_op: {
163                 let mut atomic_rmw_op_values = HashMap::new();
164                 atomic_rmw_op_values.insert("add", "Add");
165                 atomic_rmw_op_values.insert("sub", "Sub");
166                 atomic_rmw_op_values.insert("and", "And");
167                 atomic_rmw_op_values.insert("nand", "Nand");
168                 atomic_rmw_op_values.insert("or", "Or");
169                 atomic_rmw_op_values.insert("xor", "Xor");
170                 atomic_rmw_op_values.insert("xchg", "Xchg");
171                 atomic_rmw_op_values.insert("umin", "Umin");
172                 atomic_rmw_op_values.insert("umax", "Umax");
173                 atomic_rmw_op_values.insert("smin", "Smin");
174                 atomic_rmw_op_values.insert("smax", "Smax");
175                 new_enum("op", "ir::AtomicRmwOp", atomic_rmw_op_values)
176                     .with_doc("Atomic Read-Modify-Write Ops")
177             },
178         }
179     }
180 }
181