xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/d/dmd/intrange.h (revision 627f7eb200a4419d89b531d55fccd2ee3ffdcde0)
1*627f7eb2Smrg 
2*627f7eb2Smrg /* Compiler implementation of the D programming language
3*627f7eb2Smrg  * Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved
4*627f7eb2Smrg  * written by KennyTM
5*627f7eb2Smrg  * http://www.digitalmars.com
6*627f7eb2Smrg  * Distributed under the Boost Software License, Version 1.0.
7*627f7eb2Smrg  * http://www.boost.org/LICENSE_1_0.txt
8*627f7eb2Smrg  * https://github.com/dlang/dmd/blob/master/src/intrange.h
9*627f7eb2Smrg  */
10*627f7eb2Smrg 
11*627f7eb2Smrg #pragma once
12*627f7eb2Smrg 
13*627f7eb2Smrg #include "globals.h"   // for uinteger_t
14*627f7eb2Smrg class Type;
15*627f7eb2Smrg class Expression;
16*627f7eb2Smrg 
17*627f7eb2Smrg /**
18*627f7eb2Smrg This class represents a "sign-extended number", i.e. a 65-bit number, which can
19*627f7eb2Smrg represent all built-in integer types in D. This class is mainly used for
20*627f7eb2Smrg performing value-range propagation only, therefore all arithmetic are done with
21*627f7eb2Smrg saturation, not wrapping as usual.
22*627f7eb2Smrg */
23*627f7eb2Smrg struct SignExtendedNumber
24*627f7eb2Smrg {
25*627f7eb2Smrg     /// The lower 64-bit of the number.
26*627f7eb2Smrg     uinteger_t value;
27*627f7eb2Smrg     /// The sign (i.e. the most significant bit) of the number.
28*627f7eb2Smrg     bool negative;
29*627f7eb2Smrg 
30*627f7eb2Smrg     /// Create an uninitialized sign-extended number.
SignExtendedNumberSignExtendedNumber31*627f7eb2Smrg     SignExtendedNumber() {}
32*627f7eb2Smrg 
33*627f7eb2Smrg     /// Create a sign-extended number from an unsigned 64-bit number.
SignExtendedNumberSignExtendedNumber34*627f7eb2Smrg     SignExtendedNumber(uinteger_t value_)
35*627f7eb2Smrg         : value(value_), negative(false) {}
36*627f7eb2Smrg     /// Create a sign-extended number from the lower 64-bit and the sign bit.
SignExtendedNumberSignExtendedNumber37*627f7eb2Smrg     SignExtendedNumber(uinteger_t value_, bool negative_)
38*627f7eb2Smrg         : value(value_), negative(negative_) {}
39*627f7eb2Smrg 
40*627f7eb2Smrg     /// Create a sign-extended number from a signed 64-bit number.
41*627f7eb2Smrg     static SignExtendedNumber fromInteger(uinteger_t value_);
42*627f7eb2Smrg 
43*627f7eb2Smrg     /// Get the minimum or maximum value of a sign-extended number.
44*627f7eb2Smrg     static SignExtendedNumber extreme(bool minimum);
45*627f7eb2Smrg 
46*627f7eb2Smrg     // These names probably shouldn't be used anyway, as they are common macros
47*627f7eb2Smrg #undef max
48*627f7eb2Smrg #undef min
49*627f7eb2Smrg     static SignExtendedNumber max();
minSignExtendedNumber50*627f7eb2Smrg     static SignExtendedNumber min() { return SignExtendedNumber(0, true); }
51*627f7eb2Smrg 
52*627f7eb2Smrg     /// Check if the sign-extended number is minimum or zero.
isMinimumSignExtendedNumber53*627f7eb2Smrg     bool isMinimum() const { return negative && value == 0; }
54*627f7eb2Smrg 
55*627f7eb2Smrg     /// Compare two sign-extended number.
56*627f7eb2Smrg     bool operator==(const SignExtendedNumber&) const;
57*627f7eb2Smrg     bool operator!=(const SignExtendedNumber& a) const { return !(*this == a); }
58*627f7eb2Smrg     bool operator<(const SignExtendedNumber&) const;
59*627f7eb2Smrg     bool operator>(const SignExtendedNumber& a) const { return a < *this; }
60*627f7eb2Smrg     bool operator<=(const SignExtendedNumber& a) const { return !(a < *this); }
61*627f7eb2Smrg     bool operator>=(const SignExtendedNumber& a) const { return !(*this < a); }
62*627f7eb2Smrg 
63*627f7eb2Smrg     /// Increase the sign-extended number by 1 (saturated).
64*627f7eb2Smrg     SignExtendedNumber& operator++();
65*627f7eb2Smrg     /// Compute the saturated complement of a sign-extended number.
66*627f7eb2Smrg     SignExtendedNumber operator~() const;
67*627f7eb2Smrg     /// Compute the saturated negation of a sign-extended number.
68*627f7eb2Smrg     SignExtendedNumber operator-() const;
69*627f7eb2Smrg 
70*627f7eb2Smrg     /// Compute the saturated binary and of two sign-extended number.
71*627f7eb2Smrg     SignExtendedNumber operator&(const SignExtendedNumber&) const;
72*627f7eb2Smrg     /// Compute the saturated binary or of two sign-extended number.
73*627f7eb2Smrg     SignExtendedNumber operator|(const SignExtendedNumber&) const;
74*627f7eb2Smrg     /// Compute the saturated binary xor of two sign-extended number.
75*627f7eb2Smrg     SignExtendedNumber operator^(const SignExtendedNumber&) const;
76*627f7eb2Smrg     /// Compute the saturated sum of two sign-extended number.
77*627f7eb2Smrg     SignExtendedNumber operator+(const SignExtendedNumber&) const;
78*627f7eb2Smrg     /// Compute the saturated difference of two sign-extended number.
79*627f7eb2Smrg     SignExtendedNumber operator-(const SignExtendedNumber&) const;
80*627f7eb2Smrg     /// Compute the saturated product of two sign-extended number.
81*627f7eb2Smrg     SignExtendedNumber operator*(const SignExtendedNumber&) const;
82*627f7eb2Smrg     /// Compute the saturated quotient of two sign-extended number.
83*627f7eb2Smrg     SignExtendedNumber operator/(const SignExtendedNumber&) const;
84*627f7eb2Smrg     /// Compute the saturated modulus of two sign-extended number.
85*627f7eb2Smrg     SignExtendedNumber operator%(const SignExtendedNumber&) const;
86*627f7eb2Smrg 
87*627f7eb2Smrg     /// Compute the saturated shifts of two sign-extended number.
88*627f7eb2Smrg     SignExtendedNumber operator<<(const SignExtendedNumber&) const;
89*627f7eb2Smrg     SignExtendedNumber operator>>(const SignExtendedNumber&) const;
90*627f7eb2Smrg };
91*627f7eb2Smrg 
92*627f7eb2Smrg /**
93*627f7eb2Smrg This class represents a range of integers, denoted by its lower and upper bounds
94*627f7eb2Smrg (inclusive).
95*627f7eb2Smrg */
96*627f7eb2Smrg struct IntRange
97*627f7eb2Smrg {
98*627f7eb2Smrg     SignExtendedNumber imin, imax;
99*627f7eb2Smrg 
100*627f7eb2Smrg     /// Create an uninitialized range.
IntRangeIntRange101*627f7eb2Smrg     IntRange() {}
102*627f7eb2Smrg 
103*627f7eb2Smrg     /// Create a range consisting of a single number.
IntRangeIntRange104*627f7eb2Smrg     IntRange(const SignExtendedNumber& a)
105*627f7eb2Smrg         : imin(a), imax(a) {}
106*627f7eb2Smrg     /// Create a range with the lower and upper bounds.
IntRangeIntRange107*627f7eb2Smrg     IntRange(const SignExtendedNumber& lower, const SignExtendedNumber& upper)
108*627f7eb2Smrg         : imin(lower), imax(upper) {}
109*627f7eb2Smrg 
110*627f7eb2Smrg     /// Create the tightest range containing all valid integers in the specified
111*627f7eb2Smrg     /// type.
112*627f7eb2Smrg     static IntRange fromType(Type *type);
113*627f7eb2Smrg     /// Create the tightest range containing all valid integers in the type with
114*627f7eb2Smrg     /// a forced signedness.
115*627f7eb2Smrg     static IntRange fromType(Type *type, bool isUnsigned);
116*627f7eb2Smrg 
117*627f7eb2Smrg 
118*627f7eb2Smrg     /// Create the tightest range containing all specified numbers.
119*627f7eb2Smrg     static IntRange fromNumbers2(const SignExtendedNumber numbers[2]);
120*627f7eb2Smrg     static IntRange fromNumbers4(const SignExtendedNumber numbers[4]);
121*627f7eb2Smrg 
122*627f7eb2Smrg     /// Create the widest range possible.
123*627f7eb2Smrg     static IntRange widest();
124*627f7eb2Smrg 
125*627f7eb2Smrg     /// Cast the integer range to a signed type with the given size mask.
126*627f7eb2Smrg     IntRange& castSigned(uinteger_t mask);
127*627f7eb2Smrg     /// Cast the integer range to an unsigned type with the given size mask.
128*627f7eb2Smrg     IntRange& castUnsigned(uinteger_t mask);
129*627f7eb2Smrg     /// Cast the integer range to the dchar type.
130*627f7eb2Smrg     IntRange& castDchar();
131*627f7eb2Smrg 
132*627f7eb2Smrg     /// Cast the integer range to a specific type.
133*627f7eb2Smrg     IntRange& cast(Type *type);
134*627f7eb2Smrg     /// Cast the integer range to a specific type, forcing it to be unsigned.
135*627f7eb2Smrg     IntRange& castUnsigned(Type *type);
136*627f7eb2Smrg 
137*627f7eb2Smrg     /// Check if this range contains another range.
138*627f7eb2Smrg     bool contains(const IntRange& a) const;
139*627f7eb2Smrg 
140*627f7eb2Smrg     /// Check if this range contains 0.
141*627f7eb2Smrg     bool containsZero() const;
142*627f7eb2Smrg 
143*627f7eb2Smrg     /// Compute the range of the negated absolute values of the original range.
144*627f7eb2Smrg     IntRange absNeg() const;
145*627f7eb2Smrg 
146*627f7eb2Smrg     /// Compute the union of two ranges.
147*627f7eb2Smrg     IntRange unionWith(const IntRange& other) const;
148*627f7eb2Smrg     void unionOrAssign(const IntRange& other, bool& union_);
149*627f7eb2Smrg 
150*627f7eb2Smrg     /// Dump the content of the integer range to the console.
151*627f7eb2Smrg     const IntRange& dump(const char* funcName, Expression *e) const;
152*627f7eb2Smrg 
153*627f7eb2Smrg     /// Split the range into two nonnegative- and negative-only subintervals.
154*627f7eb2Smrg     void splitBySign(IntRange& negRange, bool& hasNegRange,
155*627f7eb2Smrg                      IntRange& nonNegRange, bool& hasNonNegRange) const;
156*627f7eb2Smrg 
157*627f7eb2Smrg     /// Credits to Timon Gehr maxOr, minOr, maxAnd, minAnd
158*627f7eb2Smrg     /// https://github.com/tgehr/d-compiler/blob/master/vrange.d
159*627f7eb2Smrg     static SignExtendedNumber maxOr(const IntRange&, const IntRange&);
160*627f7eb2Smrg     static SignExtendedNumber minOr(const IntRange&, const IntRange&);
161*627f7eb2Smrg     static SignExtendedNumber maxAnd(const IntRange&, const IntRange&);
162*627f7eb2Smrg     static SignExtendedNumber minAnd(const IntRange&, const IntRange&);
163*627f7eb2Smrg     static void swap(IntRange&, IntRange&);
164*627f7eb2Smrg 
165*627f7eb2Smrg     IntRange operator~() const;
166*627f7eb2Smrg     IntRange operator-() const;
167*627f7eb2Smrg     IntRange operator&(const IntRange&) const;
168*627f7eb2Smrg     IntRange operator|(const IntRange&) const;
169*627f7eb2Smrg     IntRange operator^(const IntRange&) const;
170*627f7eb2Smrg     IntRange operator+(const IntRange&) const;
171*627f7eb2Smrg     IntRange operator-(const IntRange&) const;
172*627f7eb2Smrg     IntRange operator*(const IntRange&) const;
173*627f7eb2Smrg     IntRange operator/(const IntRange&) const;
174*627f7eb2Smrg     IntRange operator%(const IntRange&) const;
175*627f7eb2Smrg     IntRange operator<<(const IntRange&) const;
176*627f7eb2Smrg     IntRange operator>>(const IntRange&) const;
177*627f7eb2Smrg };
178