From b528063099adfbaea3319ca8de57eee3130c5d4c Mon Sep 17 00:00:00 2001 From: Rob Pike Date: Thu, 29 Jan 2015 12:07:50 -0800 Subject: [PATCH] [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 --- src/cmd/asm/internal/asm/asm.go | 8 ++ src/cmd/asm/internal/asm/overflow.go | 129 --------------------------- src/cmd/asm/internal/asm/parse.go | 21 ++--- 3 files changed, 16 insertions(+), 142 deletions(-) delete mode 100644 src/cmd/asm/internal/asm/overflow.go diff --git a/src/cmd/asm/internal/asm/asm.go b/src/cmd/asm/internal/asm/asm.go index 63adef271be..43085ae2568 100644 --- a/src/cmd/asm/internal/asm/asm.go +++ b/src/cmd/asm/internal/asm/asm.go @@ -153,6 +153,11 @@ func (p *Parser) asmText(word string, operands [][]lex.Token) { 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). // That means symbol plus indirect on SB and no offset. nameAddr := p.address(operands[0]) @@ -219,6 +224,7 @@ func (p *Parser) asmText(word string, operands [][]lex.Token) { Index: uint8(p.arch.D_NONE), }, } + // Encoding of frameSize and argSize depends on architecture. switch p.arch.Thechar { case '6': @@ -231,6 +237,7 @@ func (p *Parser) asmText(word string, operands [][]lex.Token) { default: p.errorf("internal error: can't encode TEXT $arg-frame") } + p.append(prog, true) } @@ -493,6 +500,7 @@ func (p *Parser) patch() { p.branch(patch.prog, targetProg) } } + p.toPatch = p.toPatch[:0] } func (p *Parser) branch(jmp, target *obj.Prog) { diff --git a/src/cmd/asm/internal/asm/overflow.go b/src/cmd/asm/internal/asm/overflow.go deleted file mode 100644 index a4292011aef..00000000000 --- a/src/cmd/asm/internal/asm/overflow.go +++ /dev/null @@ -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 -} -*/ diff --git a/src/cmd/asm/internal/asm/parse.go b/src/cmd/asm/internal/asm/parse.go index be616ec0bcc..b0f6ca9f08e 100644 --- a/src/cmd/asm/internal/asm/parse.go +++ b/src/cmd/asm/internal/asm/parse.go @@ -360,11 +360,7 @@ func (p *Parser) expr() uint64 { switch p.peek() { case '+': p.next() - x := p.term() - if addOverflows(x, value) { - p.errorf("overflow in %d+%d", value, x) - } - value += x + value += p.term() case '-': p.next() value -= p.term() @@ -408,13 +404,12 @@ func (p *Parser) term() uint64 { switch p.peek() { case '*': p.next() - x := p.factor() - if mulOverflows(value, x) { - p.errorf("%d * %d overflows", value, x) - } - value *= x + value *= p.factor() case '/': p.next() + if value&(1<<63) != 0 { + p.errorf("divide with high bit set") + } value /= p.factor() case '%': p.next() @@ -425,9 +420,6 @@ func (p *Parser) term() uint64 { if int64(shift) < 0 { p.errorf("negative left shift %d", shift) } - if shiftOverflows(value, shift) { - p.errorf("%d << %d overflows", value, shift) - } return value << shift case lex.RSH: p.next() @@ -435,6 +427,9 @@ func (p *Parser) term() uint64 { if shift < 0 { 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) case '&': p.next()