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