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