go/src/cmd/internal/ssa/rewrite.go
Keith Randall cfc2aa56b0 [dev.ssa] cmd/internal/ssa: Handle more instructions + some cleanup
Add & as an input op.  Add several output ops (loads & stores, TESTB,
LEAQglobal, branches, memcopy)

Some other small things:
- Add exprAddr to builder to generate addresses of expressions.  Use it in
  various places that had ad-hoc code.
- Separate out nil & bounds check generation to separate functions.
- Add explicit FP and SP ops so we dont need specialized *FP and *SP opcodes.
- Fix fallthrough at end of functions with no return values.
- rematerialization of more opcodes.

Change-Id: I781decfcef9770fb15f0cd6b061547f7824a2d5e
Reviewed-on: https://go-review.googlesource.com/10213
Reviewed-by: Alan Donovan <adonovan@google.com>
2015-05-27 15:53:54 +00:00

83 lines
1.6 KiB
Go

// 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 ssa
import "log"
func applyRewrite(f *Func, r func(*Value) bool) {
// repeat rewrites until we find no more rewrites
var curv *Value
defer func() {
if curv != nil {
log.Printf("panic during rewrite of %s\n", curv.LongString())
// TODO(khr): print source location also
}
}()
for {
change := false
for _, b := range f.Blocks {
for _, v := range b.Values {
// elide any copies generated during rewriting
for i, a := range v.Args {
if a.Op != OpCopy {
continue
}
for a.Op == OpCopy {
a = a.Args[0]
}
v.Args[i] = a
}
// apply rewrite function
curv = v
if r(v) {
change = true
}
}
}
if !change {
curv = nil
return
}
}
}
// Common functions called from rewriting rules
func is64BitInt(t Type) bool {
return t.Size() == 8 && t.IsInteger()
}
func is32BitInt(t Type) bool {
return t.Size() == 4 && t.IsInteger()
}
func isPtr(t Type) bool {
return t.IsPtr()
}
func isSigned(t Type) bool {
return t.IsSigned()
}
func typeSize(t Type) int64 {
return t.Size()
}
// addOff adds two offset aux values. Each should be an int64. Fails if wraparound happens.
func addOff(a, b interface{}) interface{} {
x := a.(int64)
y := b.(int64)
z := x + y
// x and y have same sign and z has a different sign => overflow
if x^y >= 0 && x^z < 0 {
log.Panicf("offset overflow %d %d\n", x, y)
}
return z
}
func inBounds(idx, len int64) bool {
return idx >= 0 && idx < len
}