mirror of
https://github.com/golang/go
synced 2024-11-24 04:00:13 -07:00
[dev.cc] cmd/asm: delete overflow checking, make labels function-scoped
The overflow checking was causing more problems than it was avoiding, so get rid of it. But because arithmetic is done with uint64s, to simplify dealing with large constants, complain about right shift and divide with huge numbers to avoid ambiguity about signed shifts. Change-Id: I5b5ea55d8e8c02846605f4a3f8fd7a176b1e962b Reviewed-on: https://go-review.googlesource.com/3531 Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
parent
36e5f4d53f
commit
b528063099
@ -153,6 +153,11 @@ func (p *Parser) asmText(word string, operands [][]lex.Token) {
|
|||||||
p.errorf("expect two or three operands for TEXT")
|
p.errorf("expect two or three operands for TEXT")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Labels are function scoped. Patch existing labels and
|
||||||
|
// create a new label space for this TEXT.
|
||||||
|
p.patch()
|
||||||
|
p.labels = make(map[string]*obj.Prog)
|
||||||
|
|
||||||
// Operand 0 is the symbol name in the form foo(SB).
|
// Operand 0 is the symbol name in the form foo(SB).
|
||||||
// That means symbol plus indirect on SB and no offset.
|
// That means symbol plus indirect on SB and no offset.
|
||||||
nameAddr := p.address(operands[0])
|
nameAddr := p.address(operands[0])
|
||||||
@ -219,6 +224,7 @@ func (p *Parser) asmText(word string, operands [][]lex.Token) {
|
|||||||
Index: uint8(p.arch.D_NONE),
|
Index: uint8(p.arch.D_NONE),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encoding of frameSize and argSize depends on architecture.
|
// Encoding of frameSize and argSize depends on architecture.
|
||||||
switch p.arch.Thechar {
|
switch p.arch.Thechar {
|
||||||
case '6':
|
case '6':
|
||||||
@ -231,6 +237,7 @@ func (p *Parser) asmText(word string, operands [][]lex.Token) {
|
|||||||
default:
|
default:
|
||||||
p.errorf("internal error: can't encode TEXT $arg-frame")
|
p.errorf("internal error: can't encode TEXT $arg-frame")
|
||||||
}
|
}
|
||||||
|
|
||||||
p.append(prog, true)
|
p.append(prog, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -493,6 +500,7 @@ func (p *Parser) patch() {
|
|||||||
p.branch(patch.prog, targetProg)
|
p.branch(patch.prog, targetProg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
p.toPatch = p.toPatch[:0]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Parser) branch(jmp, target *obj.Prog) {
|
func (p *Parser) branch(jmp, target *obj.Prog) {
|
||||||
|
@ -1,129 +0,0 @@
|
|||||||
// Copyright 2015 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package asm
|
|
||||||
|
|
||||||
/*
|
|
||||||
Tested with uint8s like this:
|
|
||||||
|
|
||||||
for a := 0; a <= 255; a++ {
|
|
||||||
for b := 0; b <= 127; b++ {
|
|
||||||
ovfl := a+b != int(uint8(a)+uint8(b))
|
|
||||||
if addOverflows(uint8(a), uint8(b)) != ovfl {
|
|
||||||
fmt.Printf("%d+%d fails\n", a, b)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for a := 0; a <= 255; a++ {
|
|
||||||
for b := 0; b <= 127; b++ {
|
|
||||||
ovfl := a-b != int(uint8(a)-uint8(b))
|
|
||||||
if subOverflows(uint8(a), uint8(b)) != ovfl {
|
|
||||||
fmt.Printf("%d-%d fails\n", a, b)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for a := 0; a <= 255; a++ {
|
|
||||||
for b := 0; b <= 255; b++ {
|
|
||||||
ovfl := a*b != int(uint8(a)*uint8(b))
|
|
||||||
if mulOverflows(uint8(a), uint8(b)) != ovfl {
|
|
||||||
fmt.Printf("%d*%d fails\n", a, b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
overflow := func(a, b int) bool {
|
|
||||||
for ; b > 0; b-- {
|
|
||||||
a <<= 1
|
|
||||||
if a >= 256 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for a := 0; a <= 255; a++ {
|
|
||||||
for b := 0; b <= 255; b++ {
|
|
||||||
ovfl := overflow(a, b)
|
|
||||||
if shiftOverflows(uint8(a), uint8(b)) != ovfl {
|
|
||||||
fmt.Printf("%d<<%d fails\n", a, b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
func addOverflows(a, b uint64) bool {
|
|
||||||
return a+b < a
|
|
||||||
}
|
|
||||||
|
|
||||||
func subOverflows(a, b uint64) bool {
|
|
||||||
return a-b > a
|
|
||||||
}
|
|
||||||
|
|
||||||
func mulOverflows(a, b uint64) bool {
|
|
||||||
if a <= 1 || b <= 1 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
c := a * b
|
|
||||||
return c/b != a
|
|
||||||
}
|
|
||||||
|
|
||||||
func shiftOverflows(a, b uint64) bool {
|
|
||||||
c := a << b
|
|
||||||
return c>>b != a
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
For the record, signed overflow:
|
|
||||||
|
|
||||||
const mostNegative = -(mostPositive + 1)
|
|
||||||
const mostPositive = 1<<63 - 1
|
|
||||||
|
|
||||||
func signedAddOverflows(a, b int64) bool {
|
|
||||||
if (a >= 0) != (b >= 0) {
|
|
||||||
// Different signs cannot overflow.
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if a >= 0 {
|
|
||||||
// Both are positive.
|
|
||||||
return a+b < 0
|
|
||||||
}
|
|
||||||
return a+b >= 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func signedSubOverflows(a, b int64) bool {
|
|
||||||
if (a >= 0) == (b >= 0) {
|
|
||||||
// Same signs cannot overflow.
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if a >= 0 {
|
|
||||||
// a positive, b negative.
|
|
||||||
return a-b < 0
|
|
||||||
}
|
|
||||||
return a-b >= 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func signedMulOverflows(a, b int64) bool {
|
|
||||||
if a == 0 || b == 0 || a == 1 || b == 1 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if a == mostNegative || b == mostNegative {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
c := a * b
|
|
||||||
return c/b != a
|
|
||||||
}
|
|
||||||
|
|
||||||
func signedShiftOverflows(a, b int64) bool {
|
|
||||||
// Avoid right shift of a negative number.
|
|
||||||
if a >= 0 {
|
|
||||||
c := a << b
|
|
||||||
return c>>b != a
|
|
||||||
}
|
|
||||||
// Otherwise it's negative, so we complement, which
|
|
||||||
// puts zeros at the top.
|
|
||||||
a = ^a
|
|
||||||
c := a << b
|
|
||||||
return c>>b != a
|
|
||||||
}
|
|
||||||
*/
|
|
@ -360,11 +360,7 @@ func (p *Parser) expr() uint64 {
|
|||||||
switch p.peek() {
|
switch p.peek() {
|
||||||
case '+':
|
case '+':
|
||||||
p.next()
|
p.next()
|
||||||
x := p.term()
|
value += p.term()
|
||||||
if addOverflows(x, value) {
|
|
||||||
p.errorf("overflow in %d+%d", value, x)
|
|
||||||
}
|
|
||||||
value += x
|
|
||||||
case '-':
|
case '-':
|
||||||
p.next()
|
p.next()
|
||||||
value -= p.term()
|
value -= p.term()
|
||||||
@ -408,13 +404,12 @@ func (p *Parser) term() uint64 {
|
|||||||
switch p.peek() {
|
switch p.peek() {
|
||||||
case '*':
|
case '*':
|
||||||
p.next()
|
p.next()
|
||||||
x := p.factor()
|
value *= p.factor()
|
||||||
if mulOverflows(value, x) {
|
|
||||||
p.errorf("%d * %d overflows", value, x)
|
|
||||||
}
|
|
||||||
value *= x
|
|
||||||
case '/':
|
case '/':
|
||||||
p.next()
|
p.next()
|
||||||
|
if value&(1<<63) != 0 {
|
||||||
|
p.errorf("divide with high bit set")
|
||||||
|
}
|
||||||
value /= p.factor()
|
value /= p.factor()
|
||||||
case '%':
|
case '%':
|
||||||
p.next()
|
p.next()
|
||||||
@ -425,9 +420,6 @@ func (p *Parser) term() uint64 {
|
|||||||
if int64(shift) < 0 {
|
if int64(shift) < 0 {
|
||||||
p.errorf("negative left shift %d", shift)
|
p.errorf("negative left shift %d", shift)
|
||||||
}
|
}
|
||||||
if shiftOverflows(value, shift) {
|
|
||||||
p.errorf("%d << %d overflows", value, shift)
|
|
||||||
}
|
|
||||||
return value << shift
|
return value << shift
|
||||||
case lex.RSH:
|
case lex.RSH:
|
||||||
p.next()
|
p.next()
|
||||||
@ -435,6 +427,9 @@ func (p *Parser) term() uint64 {
|
|||||||
if shift < 0 {
|
if shift < 0 {
|
||||||
p.errorf("negative right shift %d", shift)
|
p.errorf("negative right shift %d", shift)
|
||||||
}
|
}
|
||||||
|
if shift > 0 && value&(1<<63) != 0 {
|
||||||
|
p.errorf("right shift with high bit set")
|
||||||
|
}
|
||||||
value >>= uint(shift)
|
value >>= uint(shift)
|
||||||
case '&':
|
case '&':
|
||||||
p.next()
|
p.next()
|
||||||
|
Loading…
Reference in New Issue
Block a user