1//! Intermediate representation for integral types.
2
3/// Which integral type are we dealing with?
4#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
5pub enum IntKind {
6 /// A `bool`.
7 Bool,
8
9 /// A `signed char`.
10 SChar,
11
12 /// An `unsigned char`.
13 UChar,
14
15 /// A `wchar_t`.
16 WChar,
17
18 /// A platform-dependent `char` type, with the signedness support.
19 Char {
20 /// Whether the char is signed for the target platform.
21 is_signed: bool,
22 },
23
24 /// A `short`.
25 Short,
26
27 /// An `unsigned short`.
28 UShort,
29
30 /// An `int`.
31 Int,
32
33 /// An `unsigned int`.
34 UInt,
35
36 /// A `long`.
37 Long,
38
39 /// An `unsigned long`.
40 ULong,
41
42 /// A `long long`.
43 LongLong,
44
45 /// An `unsigned long long`.
46 ULongLong,
47
48 /// A 8-bit signed integer.
49 I8,
50
51 /// A 8-bit unsigned integer.
52 U8,
53
54 /// A 16-bit signed integer.
55 I16,
56
57 /// Either a `char16_t` or a `wchar_t`.
58 U16,
59
60 /// A 32-bit signed integer.
61 I32,
62
63 /// A 32-bit unsigned integer.
64 U32,
65
66 /// A 64-bit signed integer.
67 I64,
68
69 /// A 64-bit unsigned integer.
70 U64,
71
72 /// An `int128_t`
73 I128,
74
75 /// A `uint128_t`.
76 U128,
77
78 /// A custom integer type, used to allow custom macro types depending on
79 /// range.
80 Custom {
81 /// The name of the type, which would be used without modification.
82 name: &'static str,
83 /// Whether the type is signed or not.
84 is_signed: bool,
85 },
86}
87
88impl IntKind {
89 /// Is this integral type signed?
90 pub(crate) fn is_signed(&self) -> bool {
91 use self::IntKind::*;
92 match *self {
93 // TODO(emilio): wchar_t can in theory be signed, but we have no way
94 // to know whether it is or not right now (unlike char, there's no
95 // WChar_S / WChar_U).
96 Bool | UChar | UShort | UInt | ULong | ULongLong | U8 | U16 |
97 WChar | U32 | U64 | U128 => false,
98
99 SChar | Short | Int | Long | LongLong | I8 | I16 | I32 | I64 |
100 I128 => true,
101
102 Char { is_signed } => is_signed,
103
104 Custom { is_signed, .. } => is_signed,
105 }
106 }
107
108 /// If this type has a known size, return it (in bytes). This is to
109 /// alleviate libclang sometimes not giving us a layout (like in the case
110 /// when an enum is defined inside a class with template parameters).
111 pub(crate) fn known_size(&self) -> Option<usize> {
112 use self::IntKind::*;
113 Some(match *self {
114 Bool | UChar | SChar | U8 | I8 | Char { .. } => 1,
115 U16 | I16 => 2,
116 U32 | I32 => 4,
117 U64 | I64 => 8,
118 I128 | U128 => 16,
119 _ => return None,
120 })
121 }
122
123 /// Whether this type's signedness matches the value.
124 pub(crate) fn signedness_matches(&self, val: i64) -> bool {
125 val >= 0 || self.is_signed()
126 }
127}
128