]>
Commit | Line | Data |
---|---|---|
b4c522fa IB |
1 | |
2 | /* Compiler implementation of the D programming language | |
3 | * Copyright (C) 1999-2018 by The D Language Foundation, All Rights Reserved | |
4 | * written by KennyTM | |
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 | |
9 | */ | |
10 | ||
11 | #pragma once | |
12 | ||
13 | #include "globals.h" // for uinteger_t | |
14 | class Type; | |
15 | class Expression; | |
16 | ||
17 | /** | |
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. | |
22 | */ | |
23 | struct SignExtendedNumber | |
24 | { | |
25 | /// The lower 64-bit of the number. | |
26 | uinteger_t value; | |
27 | /// The sign (i.e. the most significant bit) of the number. | |
28 | bool negative; | |
29 | ||
30 | /// Create an uninitialized sign-extended number. | |
31 | SignExtendedNumber() {} | |
32 | ||
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_) {} | |
39 | ||
40 | /// Create a sign-extended number from a signed 64-bit number. | |
41 | static SignExtendedNumber fromInteger(uinteger_t value_); | |
42 | ||
43 | /// Get the minimum or maximum value of a sign-extended number. | |
44 | static SignExtendedNumber extreme(bool minimum); | |
45 | ||
46 | // These names probably shouldn't be used anyway, as they are common macros | |
47 | #undef max | |
48 | #undef min | |
49 | static SignExtendedNumber max(); | |
50 | static SignExtendedNumber min() { return SignExtendedNumber(0, true); } | |
51 | ||
52 | /// Check if the sign-extended number is minimum or zero. | |
53 | bool isMinimum() const { return negative && value == 0; } | |
54 | ||
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); } | |
62 | ||
63 | /// Compute the saturated negation of a sign-extended number. | |
64 | SignExtendedNumber operator-() const; | |
65 | ||
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; | |
76 | ||
77 | /// Increase the sign-extended number by 1 (saturated). | |
78 | SignExtendedNumber& operator++(); | |
79 | ||
80 | /// Compute the saturated shifts of two sign-extended number. | |
81 | SignExtendedNumber operator<<(const SignExtendedNumber&) const; | |
82 | SignExtendedNumber operator>>(const SignExtendedNumber&) const; | |
83 | }; | |
84 | ||
85 | /** | |
86 | This class represents a range of integers, denoted by its lower and upper bounds | |
87 | (inclusive). | |
88 | */ | |
89 | struct IntRange | |
90 | { | |
91 | SignExtendedNumber imin, imax; | |
92 | ||
93 | /// Create an uninitialized range. | |
94 | IntRange() {} | |
95 | ||
96 | /// Create a range consisting of a single number. | |
97 | IntRange(const SignExtendedNumber& a) | |
98 | : imin(a), imax(a) {} | |
99 | /// Create a range with the lower and upper bounds. | |
100 | IntRange(const SignExtendedNumber& lower, const SignExtendedNumber& upper) | |
101 | : imin(lower), imax(upper) {} | |
102 | ||
103 | /// Create the tightest range containing all valid integers in the specified | |
104 | /// type. | |
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); | |
109 | ||
110 | ||
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]); | |
114 | ||
115 | /// Create the widest range possible. | |
116 | static IntRange widest(); | |
117 | ||
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(); | |
124 | ||
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); | |
129 | ||
130 | /// Check if this range contains another range. | |
131 | bool contains(const IntRange& a) const; | |
132 | ||
133 | /// Check if this range contains 0. | |
134 | bool containsZero() const; | |
135 | ||
136 | /// Compute the range of the negated absolute values of the original range. | |
137 | IntRange absNeg() const; | |
138 | ||
139 | /// Compute the union of two ranges. | |
140 | IntRange unionWith(const IntRange& other) const; | |
141 | void unionOrAssign(const IntRange& other, bool& union_); | |
142 | ||
143 | /// Dump the content of the integer range to the console. | |
144 | const IntRange& dump(const char* funcName, Expression *e) const; | |
145 | ||
146 | /// Split the range into two nonnegative- and negative-only subintervals. | |
147 | void splitBySign(IntRange& negRange, bool& hasNegRange, | |
148 | IntRange& nonNegRange, bool& hasNonNegRange) const; | |
149 | }; |