2015-03-23 17:02:11 -07:00
|
|
|
// 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
|
|
|
|
|
|
2015-05-18 16:44:20 -07:00
|
|
|
import "log"
|
2015-03-23 17:02:11 -07:00
|
|
|
|
2015-05-27 14:52:22 -07:00
|
|
|
func applyRewrite(f *Func, rb func(*Block) bool, rv func(*Value, *Config) bool) {
|
2015-03-23 17:02:11 -07:00
|
|
|
// repeat rewrites until we find no more rewrites
|
2015-05-28 16:45:33 -07:00
|
|
|
var curb *Block
|
2015-04-15 15:51:25 -07:00
|
|
|
var curv *Value
|
|
|
|
|
defer func() {
|
2015-05-28 16:45:33 -07:00
|
|
|
if curb != nil {
|
2015-06-02 09:16:22 -07:00
|
|
|
log.Printf("panic during rewrite of block %s\n", curb.LongString())
|
2015-05-28 16:45:33 -07:00
|
|
|
}
|
2015-04-15 15:51:25 -07:00
|
|
|
if curv != nil {
|
2015-06-02 09:16:22 -07:00
|
|
|
log.Printf("panic during rewrite of value %s\n", curv.LongString())
|
2015-05-27 14:52:22 -07:00
|
|
|
panic("rewrite failed")
|
2015-04-15 15:51:25 -07:00
|
|
|
// TODO(khr): print source location also
|
|
|
|
|
}
|
|
|
|
|
}()
|
2015-05-27 14:52:22 -07:00
|
|
|
config := f.Config
|
2015-03-23 17:02:11 -07:00
|
|
|
for {
|
|
|
|
|
change := false
|
|
|
|
|
for _, b := range f.Blocks {
|
2015-05-28 16:45:33 -07:00
|
|
|
if b.Control != nil && b.Control.Op == OpCopy {
|
|
|
|
|
for b.Control.Op == OpCopy {
|
|
|
|
|
b.Control = b.Control.Args[0]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
curb = b
|
|
|
|
|
if rb(b) {
|
|
|
|
|
change = true
|
|
|
|
|
}
|
|
|
|
|
curb = nil
|
2015-03-23 17:02:11 -07:00
|
|
|
for _, v := range b.Values {
|
2015-05-18 16:44:20 -07:00
|
|
|
// 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
|
2015-04-15 15:51:25 -07:00
|
|
|
curv = v
|
2015-05-27 14:52:22 -07:00
|
|
|
if rv(v, config) {
|
2015-03-23 17:02:11 -07:00
|
|
|
change = true
|
|
|
|
|
}
|
2015-05-28 16:45:33 -07:00
|
|
|
curv = nil
|
2015-03-23 17:02:11 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if !change {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Common functions called from rewriting rules
|
|
|
|
|
|
|
|
|
|
func is64BitInt(t Type) bool {
|
2015-04-15 15:51:25 -07:00
|
|
|
return t.Size() == 8 && t.IsInteger()
|
2015-03-23 17:02:11 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func is32BitInt(t Type) bool {
|
2015-04-15 15:51:25 -07:00
|
|
|
return t.Size() == 4 && t.IsInteger()
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-14 11:38:46 -07:00
|
|
|
func is16BitInt(t Type) bool {
|
|
|
|
|
return t.Size() == 2 && t.IsInteger()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func is8BitInt(t Type) bool {
|
|
|
|
|
return t.Size() == 1 && t.IsInteger()
|
|
|
|
|
}
|
|
|
|
|
|
2015-04-15 15:51:25 -07:00
|
|
|
func isPtr(t Type) bool {
|
|
|
|
|
return t.IsPtr()
|
2015-03-23 17:02:11 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func isSigned(t Type) bool {
|
2015-04-15 15:51:25 -07:00
|
|
|
return t.IsSigned()
|
2015-03-26 10:49:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func typeSize(t Type) int64 {
|
2015-04-15 15:51:25 -07:00
|
|
|
return t.Size()
|
2015-03-23 17:02:11 -07:00
|
|
|
}
|
2015-05-18 16:44:20 -07:00
|
|
|
|
2015-06-11 21:29:25 -07:00
|
|
|
// addOff adds two int64 offsets. Fails if wraparound happens.
|
|
|
|
|
func addOff(x, y int64) int64 {
|
2015-05-18 16:44:20 -07:00
|
|
|
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
|
|
|
|
|
}
|