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