aboutsummaryrefslogtreecommitdiff
path: root/gcc/d
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gcc.gnu.org>2018-12-09 15:06:22 +0000
committerIain Buclaw <ibuclaw@gcc.gnu.org>2018-12-09 15:06:22 +0000
commit9d7d33ac5800da1e76d0fb6a838111ca1378f522 (patch)
treee271a577a601d6f4c9a9b7079e7470e736ff6ee8 /gcc/d
parent5d62bfc3e7e954218fafe377324226621e47229d (diff)
downloadgcc-9d7d33ac5800da1e76d0fb6a838111ca1378f522.zip
gcc-9d7d33ac5800da1e76d0fb6a838111ca1378f522.tar.gz
gcc-9d7d33ac5800da1e76d0fb6a838111ca1378f522.tar.bz2
Merge dmd upstream e2fe2687b
Backports VRP fixes from the D front-end implementation to the C++ port, and fixes errors reported by ubsan build where the conversion from D didn't include adjusting integer suffixes from 'UL' to 'ULL'. Fixes https://gcc.gnu.org/PR88366 Reviewed-on: https://github.com/dlang/dmd/pull/9046 From-SVN: r266925
Diffstat (limited to 'gcc/d')
-rw-r--r--gcc/d/dmd/MERGE2
-rw-r--r--gcc/d/dmd/constfold.c4
-rw-r--r--gcc/d/dmd/dcast.c226
-rw-r--r--gcc/d/dmd/dsymbol.c4
-rw-r--r--gcc/d/dmd/intrange.c470
-rw-r--r--gcc/d/dmd/intrange.h36
-rw-r--r--gcc/d/dmd/mtype.c5
7 files changed, 496 insertions, 251 deletions
diff --git a/gcc/d/dmd/MERGE b/gcc/d/dmd/MERGE
index 223ffbd..a1a1fa0 100644
--- a/gcc/d/dmd/MERGE
+++ b/gcc/d/dmd/MERGE
@@ -1,4 +1,4 @@
-5220ad51eebe06754e6881d9bd5aab89dba2b065
+e2fe2687b817a201528abaa3aa882333e04db01b
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.
diff --git a/gcc/d/dmd/constfold.c b/gcc/d/dmd/constfold.c
index 4b5dceb..c3df013 100644
--- a/gcc/d/dmd/constfold.c
+++ b/gcc/d/dmd/constfold.c
@@ -446,13 +446,13 @@ UnionExp Div(Loc loc, Type *type, Expression *e1, Expression *e2)
if (n2 == -1 && !type->isunsigned())
{
// Check for int.min / -1
- if ((dinteger_t)n1 == 0xFFFFFFFF80000000UL && type->toBasetype()->ty != Tint64)
+ if ((dinteger_t)n1 == 0xFFFFFFFF80000000ULL && type->toBasetype()->ty != Tint64)
{
e2->error("integer overflow: int.min / -1");
new(&ue) ErrorExp();
return ue;
}
- else if ((dinteger_t)n1 == 0x8000000000000000L) // long.min / -1
+ else if ((dinteger_t)n1 == 0x8000000000000000LL) // long.min / -1
{
e2->error("integer overflow: long.min / -1");
new(&ue) ErrorExp();
diff --git a/gcc/d/dmd/dcast.c b/gcc/d/dmd/dcast.c
index 3947166..9606c99 100644
--- a/gcc/d/dmd/dcast.c
+++ b/gcc/d/dmd/dcast.c
@@ -986,6 +986,19 @@ MATCH implicitConvTo(Expression *e, Type *t)
visit((Expression *)e);
}
+ void visit(AndExp *e)
+ {
+ visit((Expression *)e);
+ if (result != MATCHnomatch)
+ return;
+
+ MATCH m1 = e->e1->implicitConvTo(t);
+ MATCH m2 = e->e2->implicitConvTo(t);
+
+ // Pick the worst match
+ result = (m1 < m2) ? m1 : m2;
+ }
+
void visit(OrExp *e)
{
visit((Expression *)e);
@@ -3381,74 +3394,6 @@ IntRange getIntRange(Expression *e)
{
class IntRangeVisitor : public Visitor
{
- private:
- static uinteger_t getMask(uinteger_t v)
- {
- // Ref: http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
- v |= v >> 1;
- v |= v >> 2;
- v |= v >> 4;
- v |= v >> 8;
- v |= v >> 16;
- v |= v >> 32;
- return v;
- }
-
- // The algorithms for &, |, ^ are not yet the best! Sometimes they will produce
- // not the tightest bound. See
- // https://github.com/D-Programming-Language/dmd/pull/116
- // for detail.
- static IntRange unsignedBitwiseAnd(const IntRange& a, const IntRange& b)
- {
- // the DiffMasks stores the mask of bits which are variable in the range.
- uinteger_t aDiffMask = getMask(a.imin.value ^ a.imax.value);
- uinteger_t bDiffMask = getMask(b.imin.value ^ b.imax.value);
- // Since '&' computes the digitwise-minimum, the we could set all varying
- // digits to 0 to get a lower bound, and set all varying digits to 1 to get
- // an upper bound.
- IntRange result;
- result.imin.value = (a.imin.value & ~aDiffMask) & (b.imin.value & ~bDiffMask);
- result.imax.value = (a.imax.value | aDiffMask) & (b.imax.value | bDiffMask);
- // Sometimes the upper bound is overestimated. The upper bound will never
- // exceed the input.
- if (result.imax.value > a.imax.value)
- result.imax.value = a.imax.value;
- if (result.imax.value > b.imax.value)
- result.imax.value = b.imax.value;
- result.imin.negative = result.imax.negative = a.imin.negative && b.imin.negative;
- return result;
- }
- static IntRange unsignedBitwiseOr(const IntRange& a, const IntRange& b)
- {
- // the DiffMasks stores the mask of bits which are variable in the range.
- uinteger_t aDiffMask = getMask(a.imin.value ^ a.imax.value);
- uinteger_t bDiffMask = getMask(b.imin.value ^ b.imax.value);
- // The imax algorithm by Adam D. Ruppe.
- // http://www.digitalmars.com/pnews/read.php?server=news.digitalmars.com&group=digitalmars.D&artnum=108796
- IntRange result;
- result.imin.value = (a.imin.value & ~aDiffMask) | (b.imin.value & ~bDiffMask);
- result.imax.value = a.imax.value | b.imax.value | getMask(a.imax.value & b.imax.value);
- // Sometimes the lower bound is underestimated. The lower bound will never
- // less than the input.
- if (result.imin.value < a.imin.value)
- result.imin.value = a.imin.value;
- if (result.imin.value < b.imin.value)
- result.imin.value = b.imin.value;
- result.imin.negative = result.imax.negative = a.imin.negative || b.imin.negative;
- return result;
- }
- static IntRange unsignedBitwiseXor(const IntRange& a, const IntRange& b)
- {
- // the DiffMasks stores the mask of bits which are variable in the range.
- uinteger_t aDiffMask = getMask(a.imin.value ^ a.imax.value);
- uinteger_t bDiffMask = getMask(b.imin.value ^ b.imax.value);
- IntRange result;
- result.imin.value = (a.imin.value ^ b.imin.value) & ~(aDiffMask | bDiffMask);
- result.imax.value = (a.imax.value ^ b.imax.value) | (aDiffMask | bDiffMask);
- result.imin.negative = result.imax.negative = a.imin.negative != b.imin.negative;
- return result;
- }
-
public:
IntRange range;
@@ -3471,14 +3416,14 @@ IntRange getIntRange(Expression *e)
{
IntRange ir1 = getIntRange(e->e1);
IntRange ir2 = getIntRange(e->e2);
- range = IntRange(ir1.imin + ir2.imin, ir1.imax + ir2.imax).cast(e->type);
+ range = (ir1 + ir2).cast(e->type);
}
void visit(MinExp *e)
{
IntRange ir1 = getIntRange(e->e1);
IntRange ir2 = getIntRange(e->e2);
- range = IntRange(ir1.imin - ir2.imax, ir1.imax - ir2.imin).cast(e->type);
+ range = (ir1 - ir2).cast(e->type);
}
void visit(DivExp *e)
@@ -3486,20 +3431,7 @@ IntRange getIntRange(Expression *e)
IntRange ir1 = getIntRange(e->e1);
IntRange ir2 = getIntRange(e->e2);
- // Should we ignore the possibility of div-by-0???
- if (ir2.containsZero())
- {
- visit((Expression *)e);
- return;
- }
-
- // [a,b] / [c,d] = [min (a/c, a/d, b/c, b/d), max (a/c, a/d, b/c, b/d)]
- SignExtendedNumber bdy[4];
- bdy[0] = ir1.imin / ir2.imin;
- bdy[1] = ir1.imin / ir2.imax;
- bdy[2] = ir1.imax / ir2.imin;
- bdy[3] = ir1.imax / ir2.imax;
- range = IntRange::fromNumbers4(bdy).cast(e->type);
+ range = (ir1 / ir2).cast(e->type);
}
void visit(MulExp *e)
@@ -3507,107 +3439,38 @@ IntRange getIntRange(Expression *e)
IntRange ir1 = getIntRange(e->e1);
IntRange ir2 = getIntRange(e->e2);
- // [a,b] * [c,d] = [min (ac, ad, bc, bd), max (ac, ad, bc, bd)]
- SignExtendedNumber bdy[4];
- bdy[0] = ir1.imin * ir2.imin;
- bdy[1] = ir1.imin * ir2.imax;
- bdy[2] = ir1.imax * ir2.imin;
- bdy[3] = ir1.imax * ir2.imax;
- range = IntRange::fromNumbers4(bdy).cast(e->type);
+ range = (ir1 * ir2).cast(e->type);
}
void visit(ModExp *e)
{
- IntRange irNum = getIntRange(e->e1);
- IntRange irDen = getIntRange(e->e2).absNeg();
-
- /*
- due to the rules of D (C)'s % operator, we need to consider the cases
- separately in different range of signs.
-
- case 1. [500, 1700] % [7, 23] (numerator is always positive)
- = [0, 22]
- case 2. [-500, 1700] % [7, 23] (numerator can be negative)
- = [-22, 22]
- case 3. [-1700, -500] % [7, 23] (numerator is always negative)
- = [-22, 0]
-
- the number 22 is the maximum absolute value in the denomator's range. We
- don't care about divide by zero.
- */
+ IntRange ir1 = getIntRange(e->e1);
+ IntRange ir2 = getIntRange(e->e2);
// Modding on 0 is invalid anyway.
- if (!irDen.imin.negative)
+ if (!ir2.absNeg().imin.negative)
{
visit((Expression *)e);
return;
}
-
- ++ irDen.imin;
- irDen.imax = -irDen.imin;
-
- if (!irNum.imin.negative)
- irNum.imin.value = 0;
- else if (irNum.imin < irDen.imin)
- irNum.imin = irDen.imin;
-
- if (irNum.imax.negative)
- {
- irNum.imax.negative = false;
- irNum.imax.value = 0;
- }
- else if (irNum.imax > irDen.imax)
- irNum.imax = irDen.imax;
-
- range = irNum.cast(e->type);
+ range = (ir1 % ir2).cast(e->type);
}
void visit(AndExp *e)
{
- IntRange ir1 = getIntRange(e->e1);
- IntRange ir2 = getIntRange(e->e2);
-
- IntRange ir1neg, ir1pos, ir2neg, ir2pos;
- bool has1neg, has1pos, has2neg, has2pos;
-
- ir1.splitBySign(ir1neg, has1neg, ir1pos, has1pos);
- ir2.splitBySign(ir2neg, has2neg, ir2pos, has2pos);
-
IntRange result;
bool hasResult = false;
- if (has1pos && has2pos)
- result.unionOrAssign(unsignedBitwiseAnd(ir1pos, ir2pos), hasResult);
- if (has1pos && has2neg)
- result.unionOrAssign(unsignedBitwiseAnd(ir1pos, ir2neg), hasResult);
- if (has1neg && has2pos)
- result.unionOrAssign(unsignedBitwiseAnd(ir1neg, ir2pos), hasResult);
- if (has1neg && has2neg)
- result.unionOrAssign(unsignedBitwiseAnd(ir1neg, ir2neg), hasResult);
+ result.unionOrAssign(getIntRange(e->e1) & getIntRange(e->e2), hasResult);
+
assert(hasResult);
range = result.cast(e->type);
}
void visit(OrExp *e)
{
- IntRange ir1 = getIntRange(e->e1);
- IntRange ir2 = getIntRange(e->e2);
-
- IntRange ir1neg, ir1pos, ir2neg, ir2pos;
- bool has1neg, has1pos, has2neg, has2pos;
-
- ir1.splitBySign(ir1neg, has1neg, ir1pos, has1pos);
- ir2.splitBySign(ir2neg, has2neg, ir2pos, has2pos);
-
IntRange result;
bool hasResult = false;
- if (has1pos && has2pos)
- result.unionOrAssign(unsignedBitwiseOr(ir1pos, ir2pos), hasResult);
- if (has1pos && has2neg)
- result.unionOrAssign(unsignedBitwiseOr(ir1pos, ir2neg), hasResult);
- if (has1neg && has2pos)
- result.unionOrAssign(unsignedBitwiseOr(ir1neg, ir2pos), hasResult);
- if (has1neg && has2neg)
- result.unionOrAssign(unsignedBitwiseOr(ir1neg, ir2neg), hasResult);
+ result.unionOrAssign(getIntRange(e->e1) | getIntRange(e->e2), hasResult);
assert(hasResult);
range = result.cast(e->type);
@@ -3615,25 +3478,9 @@ IntRange getIntRange(Expression *e)
void visit(XorExp *e)
{
- IntRange ir1 = getIntRange(e->e1);
- IntRange ir2 = getIntRange(e->e2);
-
- IntRange ir1neg, ir1pos, ir2neg, ir2pos;
- bool has1neg, has1pos, has2neg, has2pos;
-
- ir1.splitBySign(ir1neg, has1neg, ir1pos, has1pos);
- ir2.splitBySign(ir2neg, has2neg, ir2pos, has2pos);
-
IntRange result;
bool hasResult = false;
- if (has1pos && has2pos)
- result.unionOrAssign(unsignedBitwiseXor(ir1pos, ir2pos), hasResult);
- if (has1pos && has2neg)
- result.unionOrAssign(unsignedBitwiseXor(ir1pos, ir2neg), hasResult);
- if (has1neg && has2pos)
- result.unionOrAssign(unsignedBitwiseXor(ir1neg, ir2pos), hasResult);
- if (has1neg && has2neg)
- result.unionOrAssign(unsignedBitwiseXor(ir1neg, ir2neg), hasResult);
+ result.unionOrAssign(getIntRange(e->e1) ^ getIntRange(e->e2), hasResult);
assert(hasResult);
range = result.cast(e->type);
@@ -3644,13 +3491,7 @@ IntRange getIntRange(Expression *e)
IntRange ir1 = getIntRange(e->e1);
IntRange ir2 = getIntRange(e->e2);
- if (ir2.imin.negative)
- ir2 = IntRange(SignExtendedNumber(0), SignExtendedNumber(64));
-
- SignExtendedNumber lower = ir1.imin << (ir1.imin.negative ? ir2.imax : ir2.imin);
- SignExtendedNumber upper = ir1.imax << (ir1.imax.negative ? ir2.imin : ir2.imax);
-
- range = IntRange(lower, upper).cast(e->type);
+ range = (ir1 << ir2).cast(e->type);
}
void visit(ShrExp *e)
@@ -3658,13 +3499,7 @@ IntRange getIntRange(Expression *e)
IntRange ir1 = getIntRange(e->e1);
IntRange ir2 = getIntRange(e->e2);
- if (ir2.imin.negative)
- ir2 = IntRange(SignExtendedNumber(0), SignExtendedNumber(64));
-
- SignExtendedNumber lower = ir1.imin >> (ir1.imin.negative ? ir2.imin : ir2.imax);
- SignExtendedNumber upper = ir1.imax >> (ir1.imax.negative ? ir2.imax : ir2.imin);
-
- range = IntRange(lower, upper).cast(e->type);
+ range = (ir1 >> ir2).cast(e->type);
}
void visit(UshrExp *e)
@@ -3672,10 +3507,7 @@ IntRange getIntRange(Expression *e)
IntRange ir1 = getIntRange(e->e1).castUnsigned(e->e1->type);
IntRange ir2 = getIntRange(e->e2);
- if (ir2.imin.negative)
- ir2 = IntRange(SignExtendedNumber(0), SignExtendedNumber(64));
-
- range = IntRange(ir1.imin >> ir2.imax, ir1.imax >> ir2.imin).cast(e->type);
+ range = (ir1 >> ir2).cast(e->type);
}
void visit(AssignExp *e)
@@ -3719,7 +3551,7 @@ IntRange getIntRange(Expression *e)
void visit(NegExp *e)
{
IntRange ir = getIntRange(e->e1);
- range = IntRange(-ir.imax, -ir.imin).cast(e->type);
+ range = (-ir).cast(e->type);
}
};
diff --git a/gcc/d/dmd/dsymbol.c b/gcc/d/dmd/dsymbol.c
index b511b79..d0678a0 100644
--- a/gcc/d/dmd/dsymbol.c
+++ b/gcc/d/dmd/dsymbol.c
@@ -1191,12 +1191,12 @@ void ScopeDsymbol::importScope(Dsymbol *s, Prot protection)
static void bitArraySet(BitArray *array, size_t idx)
{
- array->ptr[idx / (sizeof(size_t) * CHAR_BIT)] |= 1 << (idx & (sizeof(size_t) * CHAR_BIT - 1));
+ array->ptr[idx / (sizeof(size_t) * CHAR_BIT)] |= 1ULL << (idx & (sizeof(size_t) * CHAR_BIT - 1));
}
static bool bitArrayGet(BitArray *array, size_t idx)
{
- return (array->ptr[idx / (sizeof(size_t) * CHAR_BIT)] & (1 << (idx & (sizeof(size_t) * CHAR_BIT - 1)))) != 0;
+ return (array->ptr[idx / (sizeof(size_t) * CHAR_BIT)] & (1ULL << (idx & (sizeof(size_t) * CHAR_BIT - 1)))) != 0;
}
static void bitArrayLength(BitArray *array, size_t len)
diff --git a/gcc/d/dmd/intrange.c b/gcc/d/dmd/intrange.c
index 966b9a2..dd794d9 100644
--- a/gcc/d/dmd/intrange.c
+++ b/gcc/d/dmd/intrange.c
@@ -54,6 +54,26 @@ SignExtendedNumber SignExtendedNumber::max()
return SignExtendedNumber(UINT64_MAX, false);
}
+SignExtendedNumber& SignExtendedNumber::operator++()
+{
+ if (value != UINT64_MAX)
+ ++value;
+ else if (negative)
+ {
+ value = 0;
+ negative = false;
+ }
+ return *this;
+}
+
+SignExtendedNumber SignExtendedNumber::operator~() const
+{
+ if (~value == 0)
+ return SignExtendedNumber(~value);
+ else
+ return SignExtendedNumber(~value, !negative);
+}
+
SignExtendedNumber SignExtendedNumber::operator-() const
{
if (value == 0)
@@ -62,11 +82,26 @@ SignExtendedNumber SignExtendedNumber::operator-() const
return SignExtendedNumber(-value, !negative);
}
-SignExtendedNumber SignExtendedNumber::operator+(const SignExtendedNumber& a) const
+SignExtendedNumber SignExtendedNumber::operator&(const SignExtendedNumber& rhs) const
{
- uinteger_t sum = value + a.value;
- bool carry = sum < value && sum < a.value;
- if (negative != a.negative)
+ return SignExtendedNumber(value & rhs.value);
+}
+
+SignExtendedNumber SignExtendedNumber::operator|(const SignExtendedNumber& rhs) const
+{
+ return SignExtendedNumber(value | rhs.value);
+}
+
+SignExtendedNumber SignExtendedNumber::operator^(const SignExtendedNumber& rhs) const
+{
+ return SignExtendedNumber(value ^ rhs.value);
+}
+
+SignExtendedNumber SignExtendedNumber::operator+(const SignExtendedNumber& rhs) const
+{
+ uinteger_t sum = value + rhs.value;
+ bool carry = sum < value && sum < rhs.value;
+ if (negative != rhs.negative)
return SignExtendedNumber(sum, !carry);
else if (negative)
return SignExtendedNumber(carry ? sum : 0, true);
@@ -74,16 +109,15 @@ SignExtendedNumber SignExtendedNumber::operator+(const SignExtendedNumber& a) co
return SignExtendedNumber(carry ? UINT64_MAX : sum, false);
}
-SignExtendedNumber SignExtendedNumber::operator-(const SignExtendedNumber& a) const
+SignExtendedNumber SignExtendedNumber::operator-(const SignExtendedNumber& rhs) const
{
- if (a.isMinimum())
+ if (rhs.isMinimum())
return negative ? SignExtendedNumber(value, false) : max();
else
- return *this + (-a);
+ return *this + (-rhs);
}
-
-SignExtendedNumber SignExtendedNumber::operator*(const SignExtendedNumber& a) const
+SignExtendedNumber SignExtendedNumber::operator*(const SignExtendedNumber& rhs) const
{
// perform *saturated* multiplication, otherwise we may get bogus ranges
// like 0x10 * 0x10 == 0x100 == 0.
@@ -98,19 +132,19 @@ SignExtendedNumber SignExtendedNumber::operator*(const SignExtendedNumber& a) co
{
if (!negative)
return *this;
- else if (a.negative)
+ else if (rhs.negative)
return max();
else
- return a.value == 0 ? a : *this;
+ return rhs.value == 0 ? rhs : *this;
}
- else if (a.value == 0)
- return a * *this; // don't duplicate the symmetric case.
+ else if (rhs.value == 0)
+ return rhs * *this; // don't duplicate the symmetric case.
SignExtendedNumber rv;
// these are != 0 now surely.
uinteger_t tAbs = copySign(value, negative);
- uinteger_t aAbs = copySign(a.value, a.negative);
- rv.negative = negative != a.negative;
+ uinteger_t aAbs = copySign(rhs.value, rhs.negative);
+ rv.negative = negative != rhs.negative;
if (UINT64_MAX / tAbs < aAbs)
rv.value = rv.negative-1;
else
@@ -118,7 +152,7 @@ SignExtendedNumber SignExtendedNumber::operator*(const SignExtendedNumber& a) co
return rv;
}
-SignExtendedNumber SignExtendedNumber::operator/(const SignExtendedNumber& a) const
+SignExtendedNumber SignExtendedNumber::operator/(const SignExtendedNumber& rhs) const
{
/* special handling for zeros:
INT65_MIN / INT65_MIN = 1
@@ -126,15 +160,15 @@ SignExtendedNumber SignExtendedNumber::operator/(const SignExtendedNumber& a) co
+ / 0 = INT65_MAX (eh?)
- / 0 = INT65_MIN (eh?)
*/
- if (a.value == 0)
+ if (rhs.value == 0)
{
- if (a.negative)
+ if (rhs.negative)
return SignExtendedNumber(value == 0 && negative);
else
return extreme(negative);
}
- uinteger_t aAbs = copySign(a.value, a.negative);
+ uinteger_t aAbs = copySign(rhs.value, rhs.negative);
uinteger_t rvVal;
if (!isMinimum())
@@ -147,7 +181,7 @@ SignExtendedNumber SignExtendedNumber::operator/(const SignExtendedNumber& a) co
else
{
if (aAbs == 1)
- return extreme(!a.negative);
+ return extreme(!rhs.negative);
rvVal = 1ULL << 63;
aAbs >>= 1;
if (aAbs & 0xAAAAAAAAAAAAAAAAULL) rvVal >>= 1;
@@ -157,18 +191,18 @@ SignExtendedNumber SignExtendedNumber::operator/(const SignExtendedNumber& a) co
if (aAbs & 0xFFFF0000FFFF0000ULL) rvVal >>= 16;
if (aAbs & 0xFFFFFFFF00000000ULL) rvVal >>= 32;
}
- bool rvNeg = negative != a.negative;
+ bool rvNeg = negative != rhs.negative;
rvVal = copySign(rvVal, rvNeg);
return SignExtendedNumber(rvVal, rvVal != 0 && rvNeg);
}
-SignExtendedNumber SignExtendedNumber::operator%(const SignExtendedNumber& a) const
+SignExtendedNumber SignExtendedNumber::operator%(const SignExtendedNumber& rhs) const
{
- if (a.value == 0)
- return !a.negative ? a : isMinimum() ? SignExtendedNumber(0) : *this;
+ if (rhs.value == 0)
+ return !rhs.negative ? rhs : isMinimum() ? SignExtendedNumber(0) : *this;
- uinteger_t aAbs = copySign(a.value, a.negative);
+ uinteger_t aAbs = copySign(rhs.value, rhs.negative);
uinteger_t rvVal;
// a % b == sgn(a) * abs(a) % abs(b).
@@ -186,25 +220,13 @@ SignExtendedNumber SignExtendedNumber::operator%(const SignExtendedNumber& a) co
return SignExtendedNumber(rvVal, rvVal != 0 && negative);
}
-SignExtendedNumber& SignExtendedNumber::operator++()
-{
- if (value != UINT64_MAX)
- ++ value;
- else if (negative)
- {
- value = 0;
- negative = false;
- }
- return *this;
-}
-
-SignExtendedNumber SignExtendedNumber::operator<<(const SignExtendedNumber& a) const
+SignExtendedNumber SignExtendedNumber::operator<<(const SignExtendedNumber& rhs) const
{
// assume left-shift the shift-amount is always unsigned. Thus negative
// shifts will give huge result.
if (value == 0)
return *this;
- else if (a.negative)
+ else if (rhs.negative)
return extreme(negative);
uinteger_t v = copySign(value, negative);
@@ -223,21 +245,21 @@ SignExtendedNumber SignExtendedNumber::operator<<(const SignExtendedNumber& a) c
r |= (v >> 1);
uinteger_t allowableShift = 63 - r;
- if (a.value > allowableShift)
+ if (rhs.value > allowableShift)
return extreme(negative);
else
- return SignExtendedNumber(value << a.value, negative);
+ return SignExtendedNumber(value << rhs.value, negative);
}
-SignExtendedNumber SignExtendedNumber::operator>>(const SignExtendedNumber& a) const
+SignExtendedNumber SignExtendedNumber::operator>>(const SignExtendedNumber& rhs) const
{
- if (a.negative || a.value > 64)
+ if (rhs.negative || rhs.value > 63)
return negative ? SignExtendedNumber(-1, true) : SignExtendedNumber(0);
else if (isMinimum())
- return a.value == 0 ? *this : SignExtendedNumber(-1ULL << (64-a.value), true);
+ return rhs.value == 0 ? *this : SignExtendedNumber(-1ULL << (64 - rhs.value), true);
uinteger_t x = value ^ -negative;
- x >>= a.value;
+ x >>= rhs.value;
return SignExtendedNumber(x ^ -negative, negative);
}
@@ -448,6 +470,364 @@ void IntRange::splitBySign(IntRange& negRange, bool& hasNegRange,
}
}
+IntRange IntRange::operator~() const
+{
+ return IntRange(~imax, ~imin);
+}
+
+IntRange IntRange::operator-() const
+{
+ return IntRange(-imax, -imin);
+}
+
+IntRange IntRange::operator&(const IntRange& rhs) const
+{
+ // unsigned or identical sign bits
+ if ((imin.negative ^ imax.negative) != 1 && (rhs.imin.negative ^ rhs.imax.negative) != 1)
+ {
+ return IntRange(minAnd(*this, rhs), maxAnd(*this, rhs));
+ }
+
+ IntRange l = IntRange(*this);
+ IntRange r = IntRange(rhs);
+
+ // both intervals span [-1,0]
+ if ((l.imin.negative ^ l.imax.negative) == 1 && (r.imin.negative ^ r.imax.negative) == 1)
+ {
+ // cannot be larger than either l.max or r.max, set the other one to -1
+ SignExtendedNumber max = l.imax.value > r.imax.value ? l.imax : r.imax;
+
+ // only negative numbers for minimum
+ l.imax.value = -1;
+ l.imax.negative = true;
+ r.imax.value = -1;
+ r.imax.negative = true;
+
+ return IntRange(minAnd(l, r), max);
+ }
+ else
+ {
+ // only one interval spans [-1,0]
+ if ((l.imin.negative ^ l.imax.negative) == 1)
+ {
+ swap(l, r); // r spans [-1,0]
+ }
+
+ SignExtendedNumber minAndNeg = minAnd(l, IntRange(r.imin, SignExtendedNumber(-1)));
+ SignExtendedNumber minAndPos = minAnd(l, IntRange(SignExtendedNumber(0), r.imax));
+ SignExtendedNumber maxAndNeg = maxAnd(l, IntRange(r.imin, SignExtendedNumber(-1)));
+ SignExtendedNumber maxAndPos = maxAnd(l, IntRange(SignExtendedNumber(0), r.imax));
+
+ SignExtendedNumber min = minAndNeg < minAndPos ? minAndNeg : minAndPos;
+ SignExtendedNumber max = maxAndNeg > maxAndPos ? maxAndNeg : maxAndPos;
+
+ return IntRange(min, max);
+ }
+}
+
+IntRange IntRange::operator|(const IntRange& rhs) const
+{
+ // unsigned or identical sign bits:
+ if ((imin.negative ^ imax.negative) == 0 && (rhs.imin.negative ^ rhs.imax.negative) == 0)
+ {
+ return IntRange(minOr(*this, rhs), maxOr(*this, rhs));
+ }
+
+ IntRange l = IntRange(*this);
+ IntRange r = IntRange(rhs);
+
+ // both intervals span [-1,0]
+ if ((l.imin.negative ^ l.imax.negative) == 1 && (r.imin.negative ^ r.imax.negative) == 1)
+ {
+ // cannot be smaller than either l.min or r.min, set the other one to 0
+ SignExtendedNumber min = l.imin.value < r.imin.value ? l.imin : r.imin;
+
+ // only negative numbers for minimum
+ l.imin.value = 0;
+ l.imin.negative = false;
+ r.imin.value = 0;
+ r.imin.negative = false;
+
+ return IntRange(min, maxOr(l, r));
+ }
+ else
+ {
+ // only one interval spans [-1,0]
+ if ((imin.negative ^ imax.negative) == 1)
+ {
+ swap(l, r); // r spans [-1,0]
+ }
+
+ SignExtendedNumber minOrNeg = minOr(l, IntRange(r.imin, SignExtendedNumber(-1)));
+ SignExtendedNumber minOrPos = minOr(l, IntRange(SignExtendedNumber(0), r.imax));
+ SignExtendedNumber maxOrNeg = maxOr(l, IntRange(r.imin, SignExtendedNumber(-1)));
+ SignExtendedNumber maxOrPos = maxOr(l, IntRange(SignExtendedNumber(0), r.imax));
+
+ SignExtendedNumber min = minOrNeg < minOrPos ? minOrNeg : minOrPos;
+ SignExtendedNumber max = maxOrNeg > maxOrPos ? maxOrNeg : maxOrPos;
+
+ return IntRange(min, max);
+ }
+}
+
+IntRange IntRange::operator^(const IntRange& rhs) const
+{
+ return (*this & (~rhs)) | (~(*this) & rhs);
+}
+
+IntRange IntRange::operator+(const IntRange& rhs) const
+{
+ return IntRange(imin + rhs.imin, imax + rhs.imax);
+}
+
+IntRange IntRange::operator-(const IntRange& rhs) const
+{
+ return IntRange(imin - rhs.imax, imax - rhs.imin);
+}
+
+IntRange IntRange::operator*(const IntRange& rhs) const
+{
+ // [a,b] * [c,d] = [min (ac, ad, bc, bd), max (ac, ad, bc, bd)]
+ SignExtendedNumber bdy[4];
+ bdy[0] = imin * rhs.imin;
+ bdy[1] = imin * rhs.imax;
+ bdy[2] = imax * rhs.imin;
+ bdy[3] = imax * rhs.imax;
+ return IntRange::fromNumbers4(bdy);
+}
+
+IntRange IntRange::operator/(const IntRange& rhs) const
+{
+ // Handle divide by 0
+ if (rhs.imax.value == 0 && rhs.imin.value == 0)
+ return widest();
+
+ IntRange r = IntRange(rhs);
+
+ // Don't treat the whole range as divide by 0 if only one end of a range is 0.
+ // Issue 15289
+ if (r.imax.value == 0)
+ {
+ r.imax.value--;
+ }
+ else if(r.imin.value == 0)
+ {
+ r.imin.value++;
+ }
+
+ if (!imin.negative && !imax.negative && !r.imin.negative && !r.imax.negative)
+ {
+ return IntRange(imin / r.imax, imax / r.imin);
+ }
+ else
+ {
+ // [a,b] / [c,d] = [min (a/c, a/d, b/c, b/d), max (a/c, a/d, b/c, b/d)]
+ SignExtendedNumber bdy[4];
+ bdy[0] = imin / r.imin;
+ bdy[1] = imin / r.imax;
+ bdy[2] = imax / r.imin;
+ bdy[3] = imax / r.imax;
+
+ return IntRange::fromNumbers4(bdy);
+ }
+}
+
+IntRange IntRange::operator%(const IntRange& rhs) const
+{
+ IntRange irNum = *this;
+ IntRange irDen = rhs.absNeg();
+
+ /*
+ due to the rules of D (C)'s % operator, we need to consider the cases
+ separately in different range of signs.
+
+ case 1. [500, 1700] % [7, 23] (numerator is always positive)
+ = [0, 22]
+ case 2. [-500, 1700] % [7, 23] (numerator can be negative)
+ = [-22, 22]
+ case 3. [-1700, -500] % [7, 23] (numerator is always negative)
+ = [-22, 0]
+
+ the number 22 is the maximum absolute value in the denomator's range. We
+ don't care about divide by zero.
+ */
+
+ irDen.imin = irDen.imin + SignExtendedNumber(1);
+ irDen.imax = -irDen.imin;
+
+ if (!irNum.imin.negative)
+ {
+ irNum.imin.value = 0;
+ }
+ else if (irNum.imin < irDen.imin)
+ {
+ irNum.imin = irDen.imin;
+ }
+
+ if (irNum.imax.negative)
+ {
+ irNum.imax.negative = false;
+ irNum.imax.value = 0;
+ }
+ else if (irNum.imax > irDen.imax)
+ {
+ irNum.imax = irDen.imax;
+ }
+
+ return irNum;
+}
+
+IntRange IntRange::operator<<(const IntRange& rhs) const
+{
+ IntRange r = IntRange(rhs);
+ if (r.imin.negative)
+ {
+ r = IntRange(SignExtendedNumber(0), SignExtendedNumber(64));
+ }
+
+ SignExtendedNumber lower = imin << (imin.negative ? r.imax : r.imin);
+ SignExtendedNumber upper = imax << (imax.negative ? r.imin : r.imax);
+
+ return IntRange(lower, upper);
+}
+
+IntRange IntRange::operator>>(const IntRange& rhs) const
+{
+ IntRange r = IntRange(rhs);
+ if (r.imin.negative)
+ {
+ r = IntRange(SignExtendedNumber(0), SignExtendedNumber(64));
+ }
+
+ SignExtendedNumber lower = imin >> (imin.negative ? r.imin : r.imax);
+ SignExtendedNumber upper = imax >> (imax.negative ? r.imax : r.imin);
+
+ return IntRange(lower, upper);
+}
+
+SignExtendedNumber IntRange::maxOr(const IntRange& lhs, const IntRange& rhs)
+{
+ uinteger_t x = 0;
+ bool sign = false;
+ uinteger_t xorvalue = lhs.imax.value ^ rhs.imax.value;
+ uinteger_t andvalue = lhs.imax.value & rhs.imax.value;
+ IntRange lhsc = IntRange(lhs);
+ IntRange rhsc = IntRange(rhs);
+
+ // Sign bit not part of the .value so we need an extra iteration
+ if (lhsc.imax.negative ^ rhsc.imax.negative)
+ {
+ sign = true;
+ if (lhsc.imax.negative)
+ {
+ if (!lhsc.imin.negative)
+ {
+ lhsc.imin.value = 0;
+ }
+ if (!rhsc.imin.negative)
+ {
+ rhsc.imin.value = 0;
+ }
+ }
+ }
+ else if (lhsc.imin.negative & rhsc.imin.negative)
+ {
+ sign = true;
+ }
+ else if (lhsc.imax.negative & rhsc.imax.negative)
+ {
+ return SignExtendedNumber(-1, false);
+ }
+
+ for (uinteger_t d = 1ULL << (8 * sizeof(uinteger_t) - 1); d; d >>= 1)
+ {
+ if (xorvalue & d)
+ {
+ x |= d;
+ if (lhsc.imax.value & d)
+ {
+ if (~lhsc.imin.value & d)
+ {
+ lhsc.imin.value = 0;
+ }
+ }
+ else
+ {
+ if (~rhsc.imin.value & d)
+ {
+ rhsc.imin.value = 0;
+ }
+ }
+ }
+ else if (lhsc.imin.value & rhsc.imin.value & d)
+ {
+ x |= d;
+ }
+ else if (andvalue & d)
+ {
+ x |= (d << 1) - 1;
+ break;
+ }
+ }
+
+ return SignExtendedNumber(x, sign);
+}
+
+SignExtendedNumber IntRange::minOr(const IntRange& lhs, const IntRange& rhs)
+{
+ return ~maxAnd(~lhs, ~rhs);
+}
+
+SignExtendedNumber IntRange::maxAnd(const IntRange& lhs, const IntRange& rhs)
+{
+ uinteger_t x = 0;
+ bool sign = false;
+ IntRange lhsc = IntRange(lhs);
+ IntRange rhsc = IntRange(rhs);
+
+ if (lhsc.imax.negative & rhsc.imax.negative)
+ {
+ sign = true;
+ }
+
+ for (uinteger_t d = 1ULL << (8 * sizeof(uinteger_t) - 1); d; d >>= 1)
+ {
+ if (lhsc.imax.value & rhsc.imax.value & d)
+ {
+ x |= d;
+ if (~lhsc.imin.value & d)
+ {
+ lhsc.imin.value = 0;
+ }
+ if (~rhsc.imin.value & d)
+ {
+ rhsc.imin.value = 0;
+ }
+ }
+ else if (~lhsc.imin.value & d && lhsc.imax.value & d)
+ {
+ lhsc.imax.value |= d - 1;
+ }
+ else if (~rhsc.imin.value & d && rhsc.imax.value & d)
+ {
+ rhsc.imax.value |= d - 1;
+ }
+ }
+
+ return SignExtendedNumber(x, sign);
+}
+
+SignExtendedNumber IntRange::minAnd(const IntRange& lhs, const IntRange& rhs)
+{
+ return ~maxOr(~lhs, ~rhs);
+}
+
+void IntRange::swap(IntRange& a, IntRange& b)
+{
+ IntRange aux = a;
+ a = b;
+ b = aux;
+}
const IntRange& IntRange::dump(const char* funcName, Expression *e) const
{
diff --git a/gcc/d/dmd/intrange.h b/gcc/d/dmd/intrange.h
index 6911158..aee773a 100644
--- a/gcc/d/dmd/intrange.h
+++ b/gcc/d/dmd/intrange.h
@@ -60,13 +60,23 @@ struct SignExtendedNumber
bool operator<=(const SignExtendedNumber& a) const { return !(a < *this); }
bool operator>=(const SignExtendedNumber& a) const { return !(*this < a); }
+ /// Increase the sign-extended number by 1 (saturated).
+ SignExtendedNumber& operator++();
+ /// Compute the saturated complement of a sign-extended number.
+ SignExtendedNumber operator~() const;
/// Compute the saturated negation of a sign-extended number.
SignExtendedNumber operator-() const;
+ /// Compute the saturated binary and of two sign-extended number.
+ SignExtendedNumber operator&(const SignExtendedNumber&) const;
+ /// Compute the saturated binary or of two sign-extended number.
+ SignExtendedNumber operator|(const SignExtendedNumber&) const;
+ /// Compute the saturated binary xor of two sign-extended number.
+ SignExtendedNumber operator^(const SignExtendedNumber&) const;
/// Compute the saturated sum of two sign-extended number.
SignExtendedNumber operator+(const SignExtendedNumber&) const;
/// Compute the saturated difference of two sign-extended number.
- SignExtendedNumber operator-(const SignExtendedNumber& a) const;
+ SignExtendedNumber operator-(const SignExtendedNumber&) const;
/// Compute the saturated product of two sign-extended number.
SignExtendedNumber operator*(const SignExtendedNumber&) const;
/// Compute the saturated quotient of two sign-extended number.
@@ -74,9 +84,6 @@ struct SignExtendedNumber
/// Compute the saturated modulus of two sign-extended number.
SignExtendedNumber operator%(const SignExtendedNumber&) const;
- /// Increase the sign-extended number by 1 (saturated).
- SignExtendedNumber& operator++();
-
/// Compute the saturated shifts of two sign-extended number.
SignExtendedNumber operator<<(const SignExtendedNumber&) const;
SignExtendedNumber operator>>(const SignExtendedNumber&) const;
@@ -146,4 +153,25 @@ struct IntRange
/// Split the range into two nonnegative- and negative-only subintervals.
void splitBySign(IntRange& negRange, bool& hasNegRange,
IntRange& nonNegRange, bool& hasNonNegRange) const;
+
+ /// Credits to Timon Gehr maxOr, minOr, maxAnd, minAnd
+ /// https://github.com/tgehr/d-compiler/blob/master/vrange.d
+ static SignExtendedNumber maxOr(const IntRange&, const IntRange&);
+ static SignExtendedNumber minOr(const IntRange&, const IntRange&);
+ static SignExtendedNumber maxAnd(const IntRange&, const IntRange&);
+ static SignExtendedNumber minAnd(const IntRange&, const IntRange&);
+ static void swap(IntRange&, IntRange&);
+
+ IntRange operator~() const;
+ IntRange operator-() const;
+ IntRange operator&(const IntRange&) const;
+ IntRange operator|(const IntRange&) const;
+ IntRange operator^(const IntRange&) const;
+ IntRange operator+(const IntRange&) const;
+ IntRange operator-(const IntRange&) const;
+ IntRange operator*(const IntRange&) const;
+ IntRange operator/(const IntRange&) const;
+ IntRange operator%(const IntRange&) const;
+ IntRange operator<<(const IntRange&) const;
+ IntRange operator>>(const IntRange&) const;
};
diff --git a/gcc/d/dmd/mtype.c b/gcc/d/dmd/mtype.c
index dedaf7d..b35b7af 100644
--- a/gcc/d/dmd/mtype.c
+++ b/gcc/d/dmd/mtype.c
@@ -3832,6 +3832,7 @@ MATCH TypeVector::implicitConvTo(Type *to)
//printf("TypeVector::implicitConvTo(%s) from %s\n", to->toChars(), toChars());
if (this == to)
return MATCHexact;
+#ifdef IN_GCC
if (to->ty == Tvector)
{
TypeVector *tv = (TypeVector *)to;
@@ -3848,6 +3849,10 @@ MATCH TypeVector::implicitConvTo(Type *to)
// Otherwise implicitly convertible only if basetypes are.
return basetype->implicitConvTo(tv->basetype);
}
+#else
+ if (ty == to->ty)
+ return MATCHconvert;
+#endif
return MATCHnomatch;
}