mirror of
https://github.com/golang/go.git
synced 2025-05-30 19:52:53 +00:00
Finish shift implementation for ideals.
R=rsc APPROVED=rsc DELTA=65 (29 added, 17 deleted, 19 changed) OCL=31775 CL=31777
This commit is contained in:
parent
cb0a02f028
commit
2ac1528e55
@ -564,7 +564,7 @@ func (a *exprCompiler) DoBinaryExpr(x *ast.BinaryExpr) {
|
|||||||
// operand in a shift operation must be always be of
|
// operand in a shift operation must be always be of
|
||||||
// unsigned integer type or an ideal number that can
|
// unsigned integer type or an ideal number that can
|
||||||
// be safely converted into an unsigned integer type
|
// be safely converted into an unsigned integer type
|
||||||
// (§Arithmetic operators)" suggests so.
|
// (§Arithmetic operators)" suggests so and 6g agrees.
|
||||||
|
|
||||||
if !l.t.isInteger() || !(r.t.isInteger() || r.t.isIdeal()) {
|
if !l.t.isInteger() || !(r.t.isInteger() || r.t.isIdeal()) {
|
||||||
a.diagOpTypes(x.Op, origlt, origrt);
|
a.diagOpTypes(x.Op, origlt, origrt);
|
||||||
@ -580,23 +580,16 @@ func (a *exprCompiler) DoBinaryExpr(x *ast.BinaryExpr) {
|
|||||||
if r2 == nil {
|
if r2 == nil {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// If the left operand is ideal, we use the
|
|
||||||
// original right operand so we can perform
|
// If the left operand is not ideal, convert
|
||||||
// constant evaluation. Otherwise, we use the
|
// the right to not ideal.
|
||||||
// conversion.
|
|
||||||
if !l.t.isIdeal() {
|
if !l.t.isIdeal() {
|
||||||
r = r2;
|
r = r2;
|
||||||
// XXX(Spec) What is the meaning of
|
|
||||||
// "ideal >> non-ideal"? Russ says
|
|
||||||
// the ideal should be converted to
|
|
||||||
// an int. 6g says it's illegal.
|
|
||||||
l = l.convertTo(IntType);
|
|
||||||
if l == nil {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
} else if r.t.isFloat() {
|
|
||||||
// Convert it to an ideal int to
|
// If both are ideal, but the right side isn't
|
||||||
// simplify the cases
|
// an ideal int, convert it to simplify things.
|
||||||
|
if l.t.isIdeal() && !r.t.isInteger() {
|
||||||
r = r.convertTo(IdealIntType);
|
r = r.convertTo(IdealIntType);
|
||||||
if r == nil {
|
if r == nil {
|
||||||
log.Crashf("conversion to uintType succeeded, but conversion to idealIntType failed");
|
log.Crashf("conversion to uintType succeeded, but conversion to idealIntType failed");
|
||||||
@ -606,6 +599,23 @@ func (a *exprCompiler) DoBinaryExpr(x *ast.BinaryExpr) {
|
|||||||
a.diag("right operand of shift must be unsigned");
|
a.diag("right operand of shift must be unsigned");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if l.t.isIdeal() && !r.t.isIdeal() {
|
||||||
|
// XXX(Spec) What is the meaning of "ideal >>
|
||||||
|
// non-ideal"? Russ says the ideal should be
|
||||||
|
// converted to an int. 6g propagates the
|
||||||
|
// type down from assignments as a hint.
|
||||||
|
l = l.convertTo(IntType);
|
||||||
|
if l == nil {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// At this point, we should have one of three cases:
|
||||||
|
// 1) uint SHIFT uint
|
||||||
|
// 2) int SHIFT uint
|
||||||
|
// 3) ideal int SHIFT ideal int
|
||||||
|
|
||||||
a.t = l.t;
|
a.t = l.t;
|
||||||
|
|
||||||
case token.LOR, token.LAND:
|
case token.LOR, token.LAND:
|
||||||
@ -710,18 +720,30 @@ func (a *exprCompiler) DoBinaryExpr(x *ast.BinaryExpr) {
|
|||||||
a.genBinOpAndNot(l, r);
|
a.genBinOpAndNot(l, r);
|
||||||
|
|
||||||
case token.SHL:
|
case token.SHL:
|
||||||
// TODO(austin) bignum.Integer.Shl takes a uint
|
if l.t.isIdeal() {
|
||||||
if r.t.isIdeal() {
|
lv := l.asIdealInt()();
|
||||||
log.Crashf("<< ideal not implemented");
|
rv := r.asIdealInt()();
|
||||||
|
const maxShift = 99999;
|
||||||
|
if rv.Cmp(bignum.Int(maxShift)) > 0 {
|
||||||
|
a.diag("left shift by %v; exceeds implementation limit of %v", rv, maxShift);
|
||||||
|
a.t = nil;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
val := lv.Shl(uint(rv.Value()));
|
||||||
|
a.evalIdealInt = func() *bignum.Integer { return val };
|
||||||
|
} else {
|
||||||
a.genBinOpShl(l, r);
|
a.genBinOpShl(l, r);
|
||||||
|
}
|
||||||
|
|
||||||
case token.SHR:
|
case token.SHR:
|
||||||
// TODO(austin) bignum.Integer.Shr takes a uint
|
if l.t.isIdeal() {
|
||||||
if r.t.isIdeal() {
|
lv := l.asIdealInt()();
|
||||||
log.Crashf(">> ideal not implemented");
|
rv := r.asIdealInt()();
|
||||||
}
|
val := lv.Shr(uint(rv.Value()));
|
||||||
|
a.evalIdealInt = func() *bignum.Integer { return val };
|
||||||
|
} else {
|
||||||
a.genBinOpShr(l, r);
|
a.genBinOpShr(l, r);
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
log.Crashf("Compilation of binary op %v not implemented", x.Op);
|
log.Crashf("Compilation of binary op %v not implemented", x.Op);
|
||||||
@ -1131,11 +1153,6 @@ func (a *exprCompiler) genBinOpShl(l *exprCompiler, r *exprCompiler) {
|
|||||||
lf := l.asInt();
|
lf := l.asInt();
|
||||||
rf := r.asUint();
|
rf := r.asUint();
|
||||||
a.evalInt = func(f *Frame) int64 { return lf(f) << rf(f) };
|
a.evalInt = func(f *Frame) int64 { return lf(f) << rf(f) };
|
||||||
// case *idealIntType:
|
|
||||||
// lf := l.asIdealInt();
|
|
||||||
// rf := r.asIdealInt();
|
|
||||||
// val := lf().Shl(rf());
|
|
||||||
// a.evalIdealInt = func() *bignum.Integer { return val };
|
|
||||||
default:
|
default:
|
||||||
log.Crashf("unexpected left operand type %v at %v", l.t.literal(), a.pos);
|
log.Crashf("unexpected left operand type %v at %v", l.t.literal(), a.pos);
|
||||||
}
|
}
|
||||||
@ -1151,11 +1168,6 @@ func (a *exprCompiler) genBinOpShr(l *exprCompiler, r *exprCompiler) {
|
|||||||
lf := l.asInt();
|
lf := l.asInt();
|
||||||
rf := r.asUint();
|
rf := r.asUint();
|
||||||
a.evalInt = func(f *Frame) int64 { return lf(f) >> rf(f) };
|
a.evalInt = func(f *Frame) int64 { return lf(f) >> rf(f) };
|
||||||
// case *idealIntType:
|
|
||||||
// lf := l.asIdealInt();
|
|
||||||
// rf := r.asIdealInt();
|
|
||||||
// val := lf().Shr(rf());
|
|
||||||
// a.evalIdealInt = func() *bignum.Integer { return val };
|
|
||||||
default:
|
default:
|
||||||
log.Crashf("unexpected left operand type %v at %v", l.t.literal(), a.pos);
|
log.Crashf("unexpected left operand type %v at %v", l.t.literal(), a.pos);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user