1 //! Condition codes for the Cranelift code generator. 2 //! 3 //! A condition code here is an enumerated type that determined how to compare two numbers. There 4 //! are different rules for comparing integers and floating point numbers, so they use different 5 //! condition codes. 6 7 use core::fmt::{self, Display, Formatter}; 8 use core::str::FromStr; 9 10 /// Common traits of condition codes. 11 pub trait CondCode: Copy { 12 /// Get the inverse condition code of `self`. 13 /// 14 /// The inverse condition code produces the opposite result for all comparisons. 15 /// That is, `cmp CC, x, y` is true if and only if `cmp CC.inverse(), x, y` is false. 16 #[must_use] inverse(self) -> Self17 fn inverse(self) -> Self; 18 19 /// Get the reversed condition code for `self`. 20 /// 21 /// The reversed condition code produces the same result as swapping `x` and `y` in the 22 /// comparison. That is, `cmp CC, x, y` is the same as `cmp CC.reverse(), y, x`. 23 #[must_use] reverse(self) -> Self24 fn reverse(self) -> Self; 25 } 26 27 /// Condition code for comparing integers. 28 /// 29 /// This condition code is used by the `icmp` instruction to compare integer values. There are 30 /// separate codes for comparing the integers as signed or unsigned numbers where it makes a 31 /// difference. 32 #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] 33 pub enum IntCC { 34 /// `==`. 35 Equal, 36 /// `!=`. 37 NotEqual, 38 /// Signed `<`. 39 SignedLessThan, 40 /// Signed `>=`. 41 SignedGreaterThanOrEqual, 42 /// Signed `>`. 43 SignedGreaterThan, 44 /// Signed `<=`. 45 SignedLessThanOrEqual, 46 /// Unsigned `<`. 47 UnsignedLessThan, 48 /// Unsigned `>=`. 49 UnsignedGreaterThanOrEqual, 50 /// Unsigned `>`. 51 UnsignedGreaterThan, 52 /// Unsigned `<=`. 53 UnsignedLessThanOrEqual, 54 /// Signed Overflow. 55 Overflow, 56 /// Signed No Overflow. 57 NotOverflow, 58 } 59 60 impl CondCode for IntCC { inverse(self) -> Self61 fn inverse(self) -> Self { 62 use self::IntCC::*; 63 match self { 64 Equal => NotEqual, 65 NotEqual => Equal, 66 SignedLessThan => SignedGreaterThanOrEqual, 67 SignedGreaterThanOrEqual => SignedLessThan, 68 SignedGreaterThan => SignedLessThanOrEqual, 69 SignedLessThanOrEqual => SignedGreaterThan, 70 UnsignedLessThan => UnsignedGreaterThanOrEqual, 71 UnsignedGreaterThanOrEqual => UnsignedLessThan, 72 UnsignedGreaterThan => UnsignedLessThanOrEqual, 73 UnsignedLessThanOrEqual => UnsignedGreaterThan, 74 Overflow => NotOverflow, 75 NotOverflow => Overflow, 76 } 77 } 78 reverse(self) -> Self79 fn reverse(self) -> Self { 80 use self::IntCC::*; 81 match self { 82 Equal => Equal, 83 NotEqual => NotEqual, 84 SignedGreaterThan => SignedLessThan, 85 SignedGreaterThanOrEqual => SignedLessThanOrEqual, 86 SignedLessThan => SignedGreaterThan, 87 SignedLessThanOrEqual => SignedGreaterThanOrEqual, 88 UnsignedGreaterThan => UnsignedLessThan, 89 UnsignedGreaterThanOrEqual => UnsignedLessThanOrEqual, 90 UnsignedLessThan => UnsignedGreaterThan, 91 UnsignedLessThanOrEqual => UnsignedGreaterThanOrEqual, 92 Overflow => Overflow, 93 NotOverflow => NotOverflow, 94 } 95 } 96 } 97 98 impl IntCC { 99 /// Get the corresponding IntCC with the equal component removed. 100 /// For conditions without a zero component, this is a no-op. without_equal(self) -> Self101 pub fn without_equal(self) -> Self { 102 use self::IntCC::*; 103 match self { 104 SignedGreaterThan | SignedGreaterThanOrEqual => SignedGreaterThan, 105 SignedLessThan | SignedLessThanOrEqual => SignedLessThan, 106 UnsignedGreaterThan | UnsignedGreaterThanOrEqual => UnsignedGreaterThan, 107 UnsignedLessThan | UnsignedLessThanOrEqual => UnsignedLessThan, 108 _ => self, 109 } 110 } 111 112 /// Get the corresponding IntCC with the signed component removed. 113 /// For conditions without a signed component, this is a no-op. unsigned(self) -> Self114 pub fn unsigned(self) -> Self { 115 use self::IntCC::*; 116 match self { 117 SignedGreaterThan | UnsignedGreaterThan => UnsignedGreaterThan, 118 SignedGreaterThanOrEqual | UnsignedGreaterThanOrEqual => UnsignedGreaterThanOrEqual, 119 SignedLessThan | UnsignedLessThan => UnsignedLessThan, 120 SignedLessThanOrEqual | UnsignedLessThanOrEqual => UnsignedLessThanOrEqual, 121 _ => self, 122 } 123 } 124 125 /// Get the corresponding string condition code for the IntCC object. to_static_str(self) -> &'static str126 pub fn to_static_str(self) -> &'static str { 127 use self::IntCC::*; 128 match self { 129 Equal => "eq", 130 NotEqual => "ne", 131 SignedGreaterThan => "sgt", 132 SignedGreaterThanOrEqual => "sge", 133 SignedLessThan => "slt", 134 SignedLessThanOrEqual => "sle", 135 UnsignedGreaterThan => "ugt", 136 UnsignedGreaterThanOrEqual => "uge", 137 UnsignedLessThan => "ult", 138 UnsignedLessThanOrEqual => "ule", 139 Overflow => "of", 140 NotOverflow => "nof", 141 } 142 } 143 } 144 145 impl Display for IntCC { fmt(&self, f: &mut Formatter) -> fmt::Result146 fn fmt(&self, f: &mut Formatter) -> fmt::Result { 147 f.write_str(self.to_static_str()) 148 } 149 } 150 151 impl FromStr for IntCC { 152 type Err = (); 153 from_str(s: &str) -> Result<Self, Self::Err>154 fn from_str(s: &str) -> Result<Self, Self::Err> { 155 use self::IntCC::*; 156 match s { 157 "eq" => Ok(Equal), 158 "ne" => Ok(NotEqual), 159 "sge" => Ok(SignedGreaterThanOrEqual), 160 "sgt" => Ok(SignedGreaterThan), 161 "sle" => Ok(SignedLessThanOrEqual), 162 "slt" => Ok(SignedLessThan), 163 "uge" => Ok(UnsignedGreaterThanOrEqual), 164 "ugt" => Ok(UnsignedGreaterThan), 165 "ule" => Ok(UnsignedLessThanOrEqual), 166 "ult" => Ok(UnsignedLessThan), 167 "of" => Ok(Overflow), 168 "nof" => Ok(NotOverflow), 169 _ => Err(()), 170 } 171 } 172 } 173 174 /// Condition code for comparing floating point numbers. 175 /// 176 /// This condition code is used by the `fcmp` instruction to compare floating point values. Two 177 /// IEEE floating point values relate in exactly one of four ways: 178 /// 179 /// 1. `UN` - unordered when either value is NaN. 180 /// 2. `EQ` - equal numerical value. 181 /// 3. `LT` - `x` is less than `y`. 182 /// 4. `GT` - `x` is greater than `y`. 183 /// 184 /// Note that `0.0` and `-0.0` relate as `EQ` because they both represent the number 0. 185 /// 186 /// The condition codes described here are used to produce a single boolean value from the 187 /// comparison. The 14 condition codes here cover every possible combination of the relation above 188 /// except the impossible `!UN & !EQ & !LT & !GT` and the always true `UN | EQ | LT | GT`. 189 #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] 190 pub enum FloatCC { 191 /// EQ | LT | GT 192 Ordered, 193 /// UN 194 Unordered, 195 196 /// EQ 197 Equal, 198 /// The C '!=' operator is the inverse of '==': `NotEqual`. 199 /// UN | LT | GT 200 NotEqual, 201 /// LT | GT 202 OrderedNotEqual, 203 /// UN | EQ 204 UnorderedOrEqual, 205 206 /// LT 207 LessThan, 208 /// LT | EQ 209 LessThanOrEqual, 210 /// GT 211 GreaterThan, 212 /// GT | EQ 213 GreaterThanOrEqual, 214 215 /// UN | LT 216 UnorderedOrLessThan, 217 /// UN | LT | EQ 218 UnorderedOrLessThanOrEqual, 219 /// UN | GT 220 UnorderedOrGreaterThan, 221 /// UN | GT | EQ 222 UnorderedOrGreaterThanOrEqual, 223 } 224 225 impl CondCode for FloatCC { inverse(self) -> Self226 fn inverse(self) -> Self { 227 use self::FloatCC::*; 228 match self { 229 Ordered => Unordered, 230 Unordered => Ordered, 231 Equal => NotEqual, 232 NotEqual => Equal, 233 OrderedNotEqual => UnorderedOrEqual, 234 UnorderedOrEqual => OrderedNotEqual, 235 LessThan => UnorderedOrGreaterThanOrEqual, 236 LessThanOrEqual => UnorderedOrGreaterThan, 237 GreaterThan => UnorderedOrLessThanOrEqual, 238 GreaterThanOrEqual => UnorderedOrLessThan, 239 UnorderedOrLessThan => GreaterThanOrEqual, 240 UnorderedOrLessThanOrEqual => GreaterThan, 241 UnorderedOrGreaterThan => LessThanOrEqual, 242 UnorderedOrGreaterThanOrEqual => LessThan, 243 } 244 } reverse(self) -> Self245 fn reverse(self) -> Self { 246 use self::FloatCC::*; 247 match self { 248 Ordered => Ordered, 249 Unordered => Unordered, 250 Equal => Equal, 251 NotEqual => NotEqual, 252 OrderedNotEqual => OrderedNotEqual, 253 UnorderedOrEqual => UnorderedOrEqual, 254 LessThan => GreaterThan, 255 LessThanOrEqual => GreaterThanOrEqual, 256 GreaterThan => LessThan, 257 GreaterThanOrEqual => LessThanOrEqual, 258 UnorderedOrLessThan => UnorderedOrGreaterThan, 259 UnorderedOrLessThanOrEqual => UnorderedOrGreaterThanOrEqual, 260 UnorderedOrGreaterThan => UnorderedOrLessThan, 261 UnorderedOrGreaterThanOrEqual => UnorderedOrLessThanOrEqual, 262 } 263 } 264 } 265 266 impl Display for FloatCC { fmt(&self, f: &mut Formatter) -> fmt::Result267 fn fmt(&self, f: &mut Formatter) -> fmt::Result { 268 use self::FloatCC::*; 269 f.write_str(match *self { 270 Ordered => "ord", 271 Unordered => "uno", 272 Equal => "eq", 273 NotEqual => "ne", 274 OrderedNotEqual => "one", 275 UnorderedOrEqual => "ueq", 276 LessThan => "lt", 277 LessThanOrEqual => "le", 278 GreaterThan => "gt", 279 GreaterThanOrEqual => "ge", 280 UnorderedOrLessThan => "ult", 281 UnorderedOrLessThanOrEqual => "ule", 282 UnorderedOrGreaterThan => "ugt", 283 UnorderedOrGreaterThanOrEqual => "uge", 284 }) 285 } 286 } 287 288 impl FromStr for FloatCC { 289 type Err = (); 290 from_str(s: &str) -> Result<Self, Self::Err>291 fn from_str(s: &str) -> Result<Self, Self::Err> { 292 use self::FloatCC::*; 293 match s { 294 "ord" => Ok(Ordered), 295 "uno" => Ok(Unordered), 296 "eq" => Ok(Equal), 297 "ne" => Ok(NotEqual), 298 "one" => Ok(OrderedNotEqual), 299 "ueq" => Ok(UnorderedOrEqual), 300 "lt" => Ok(LessThan), 301 "le" => Ok(LessThanOrEqual), 302 "gt" => Ok(GreaterThan), 303 "ge" => Ok(GreaterThanOrEqual), 304 "ult" => Ok(UnorderedOrLessThan), 305 "ule" => Ok(UnorderedOrLessThanOrEqual), 306 "ugt" => Ok(UnorderedOrGreaterThan), 307 "uge" => Ok(UnorderedOrGreaterThanOrEqual), 308 _ => Err(()), 309 } 310 } 311 } 312 313 #[cfg(test)] 314 mod tests { 315 use super::*; 316 use std::string::ToString; 317 318 static INT_ALL: [IntCC; 12] = [ 319 IntCC::Equal, 320 IntCC::NotEqual, 321 IntCC::SignedLessThan, 322 IntCC::SignedGreaterThanOrEqual, 323 IntCC::SignedGreaterThan, 324 IntCC::SignedLessThanOrEqual, 325 IntCC::UnsignedLessThan, 326 IntCC::UnsignedGreaterThanOrEqual, 327 IntCC::UnsignedGreaterThan, 328 IntCC::UnsignedLessThanOrEqual, 329 IntCC::Overflow, 330 IntCC::NotOverflow, 331 ]; 332 333 #[test] int_inverse()334 fn int_inverse() { 335 for r in &INT_ALL { 336 let cc = *r; 337 let inv = cc.inverse(); 338 assert!(cc != inv); 339 assert_eq!(inv.inverse(), cc); 340 } 341 } 342 343 #[test] int_reverse()344 fn int_reverse() { 345 for r in &INT_ALL { 346 let cc = *r; 347 let rev = cc.reverse(); 348 assert_eq!(rev.reverse(), cc); 349 } 350 } 351 352 #[test] int_display()353 fn int_display() { 354 for r in &INT_ALL { 355 let cc = *r; 356 assert_eq!(cc.to_string().parse(), Ok(cc)); 357 } 358 assert_eq!("bogus".parse::<IntCC>(), Err(())); 359 } 360 361 static FLOAT_ALL: [FloatCC; 14] = [ 362 FloatCC::Ordered, 363 FloatCC::Unordered, 364 FloatCC::Equal, 365 FloatCC::NotEqual, 366 FloatCC::OrderedNotEqual, 367 FloatCC::UnorderedOrEqual, 368 FloatCC::LessThan, 369 FloatCC::LessThanOrEqual, 370 FloatCC::GreaterThan, 371 FloatCC::GreaterThanOrEqual, 372 FloatCC::UnorderedOrLessThan, 373 FloatCC::UnorderedOrLessThanOrEqual, 374 FloatCC::UnorderedOrGreaterThan, 375 FloatCC::UnorderedOrGreaterThanOrEqual, 376 ]; 377 378 #[test] float_inverse()379 fn float_inverse() { 380 for r in &FLOAT_ALL { 381 let cc = *r; 382 let inv = cc.inverse(); 383 assert!(cc != inv); 384 assert_eq!(inv.inverse(), cc); 385 } 386 } 387 388 #[test] float_reverse()389 fn float_reverse() { 390 for r in &FLOAT_ALL { 391 let cc = *r; 392 let rev = cc.reverse(); 393 assert_eq!(rev.reverse(), cc); 394 } 395 } 396 397 #[test] float_display()398 fn float_display() { 399 for r in &FLOAT_ALL { 400 let cc = *r; 401 assert_eq!(cc.to_string().parse(), Ok(cc)); 402 } 403 assert_eq!("bogus".parse::<FloatCC>(), Err(())); 404 } 405 } 406