2 /* Compiler implementation of the D programming language
3 * Copyright (C) 1999-2018 by The D Language Foundation, All Rights Reserved
5 * http://www.digitalmars.com
6 * Distributed under the Boost Software License, Version 1.0.
7 * http://www.boost.org/LICENSE_1_0.txt
8 * https://github.com/dlang/dmd/blob/master/src/intrange.h
13 #include "globals.h" // for uinteger_t
18 This class represents a "sign-extended number", i.e. a 65-bit number, which can
19 represent all built-in integer types in D. This class is mainly used for
20 performing value-range propagation only, therefore all arithmetic are done with
21 saturation, not wrapping as usual.
23 struct SignExtendedNumber
25 /// The lower 64-bit of the number.
27 /// The sign (i.e. the most significant bit) of the number.
30 /// Create an uninitialized sign-extended number.
31 SignExtendedNumber() {}
33 /// Create a sign-extended number from an unsigned 64-bit number.
34 SignExtendedNumber(uinteger_t value_
)
35 : value(value_
), negative(false) {}
36 /// Create a sign-extended number from the lower 64-bit and the sign bit.
37 SignExtendedNumber(uinteger_t value_
, bool negative_
)
38 : value(value_
), negative(negative_
) {}
40 /// Create a sign-extended number from a signed 64-bit number.
41 static SignExtendedNumber
fromInteger(uinteger_t value_
);
43 /// Get the minimum or maximum value of a sign-extended number.
44 static SignExtendedNumber
extreme(bool minimum
);
46 // These names probably shouldn't be used anyway, as they are common macros
49 static SignExtendedNumber
max();
50 static SignExtendedNumber
min() { return SignExtendedNumber(0, true); }
52 /// Check if the sign-extended number is minimum or zero.
53 bool isMinimum() const { return negative
&& value
== 0; }
55 /// Compare two sign-extended number.
56 bool operator==(const SignExtendedNumber
&) const;
57 bool operator!=(const SignExtendedNumber
& a
) const { return !(*this == a
); }
58 bool operator<(const SignExtendedNumber
&) const;
59 bool operator>(const SignExtendedNumber
& a
) const { return a
< *this; }
60 bool operator<=(const SignExtendedNumber
& a
) const { return !(a
< *this); }
61 bool operator>=(const SignExtendedNumber
& a
) const { return !(*this < a
); }
63 /// Compute the saturated negation of a sign-extended number.
64 SignExtendedNumber
operator-() const;
66 /// Compute the saturated sum of two sign-extended number.
67 SignExtendedNumber
operator+(const SignExtendedNumber
&) const;
68 /// Compute the saturated difference of two sign-extended number.
69 SignExtendedNumber
operator-(const SignExtendedNumber
& a
) const;
70 /// Compute the saturated product of two sign-extended number.
71 SignExtendedNumber
operator*(const SignExtendedNumber
&) const;
72 /// Compute the saturated quotient of two sign-extended number.
73 SignExtendedNumber
operator/(const SignExtendedNumber
&) const;
74 /// Compute the saturated modulus of two sign-extended number.
75 SignExtendedNumber
operator%(const SignExtendedNumber
&) const;
77 /// Increase the sign-extended number by 1 (saturated).
78 SignExtendedNumber
& operator++();
80 /// Compute the saturated shifts of two sign-extended number.
81 SignExtendedNumber
operator<<(const SignExtendedNumber
&) const;
82 SignExtendedNumber
operator>>(const SignExtendedNumber
&) const;
86 This class represents a range of integers, denoted by its lower and upper bounds
91 SignExtendedNumber imin
, imax
;
93 /// Create an uninitialized range.
96 /// Create a range consisting of a single number.
97 IntRange(const SignExtendedNumber
& a
)
99 /// Create a range with the lower and upper bounds.
100 IntRange(const SignExtendedNumber
& lower
, const SignExtendedNumber
& upper
)
101 : imin(lower
), imax(upper
) {}
103 /// Create the tightest range containing all valid integers in the specified
105 static IntRange
fromType(Type
*type
);
106 /// Create the tightest range containing all valid integers in the type with
107 /// a forced signedness.
108 static IntRange
fromType(Type
*type
, bool isUnsigned
);
111 /// Create the tightest range containing all specified numbers.
112 static IntRange
fromNumbers2(const SignExtendedNumber numbers
[2]);
113 static IntRange
fromNumbers4(const SignExtendedNumber numbers
[4]);
115 /// Create the widest range possible.
116 static IntRange
widest();
118 /// Cast the integer range to a signed type with the given size mask.
119 IntRange
& castSigned(uinteger_t mask
);
120 /// Cast the integer range to an unsigned type with the given size mask.
121 IntRange
& castUnsigned(uinteger_t mask
);
122 /// Cast the integer range to the dchar type.
123 IntRange
& castDchar();
125 /// Cast the integer range to a specific type.
126 IntRange
& cast(Type
*type
);
127 /// Cast the integer range to a specific type, forcing it to be unsigned.
128 IntRange
& castUnsigned(Type
*type
);
130 /// Check if this range contains another range.
131 bool contains(const IntRange
& a
) const;
133 /// Check if this range contains 0.
134 bool containsZero() const;
136 /// Compute the range of the negated absolute values of the original range.
137 IntRange
absNeg() const;
139 /// Compute the union of two ranges.
140 IntRange
unionWith(const IntRange
& other
) const;
141 void unionOrAssign(const IntRange
& other
, bool& union_
);
143 /// Dump the content of the integer range to the console.
144 const IntRange
& dump(const char* funcName
, Expression
*e
) const;
146 /// Split the range into two nonnegative- and negative-only subintervals.
147 void splitBySign(IntRange
& negRange
, bool& hasNegRange
,
148 IntRange
& nonNegRange
, bool& hasNonNegRange
) const;