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