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-28 10:47:24 -07:00
|
|
|
import "log"
|
|
|
|
|
|
2015-03-23 17:02:11 -07:00
|
|
|
//go:generate go run rulegen/rulegen.go rulegen/lower_amd64.rules lowerAmd64 lowerAmd64.go
|
|
|
|
|
|
|
|
|
|
// convert to machine-dependent ops
|
|
|
|
|
func lower(f *Func) {
|
|
|
|
|
// repeat rewrites until we find no more rewrites
|
2015-04-15 15:51:25 -07:00
|
|
|
applyRewrite(f, f.Config.lower)
|
2015-03-23 17:02:11 -07:00
|
|
|
|
2015-05-28 10:47:24 -07:00
|
|
|
// Check for unlowered opcodes, fail if we find one.
|
|
|
|
|
for _, b := range f.Blocks {
|
|
|
|
|
for _, v := range b.Values {
|
|
|
|
|
if v.Op < OpGenericEnd && v.Op != OpFP && v.Op != OpSP && v.Op != OpArg && v.Op != OpCopy && v.Op != OpPhi {
|
|
|
|
|
log.Panicf("%s not lowered", v.LongString())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-03-23 17:02:11 -07:00
|
|
|
|
|
|
|
|
// additional pass for 386/amd64, link condition codes directly to blocks
|
|
|
|
|
// TODO: do generically somehow? Special "block" rewrite rules?
|
|
|
|
|
for _, b := range f.Blocks {
|
2015-05-18 16:44:20 -07:00
|
|
|
for {
|
|
|
|
|
switch b.Kind {
|
|
|
|
|
case BlockIf:
|
|
|
|
|
switch b.Control.Op {
|
|
|
|
|
case OpSETL:
|
|
|
|
|
b.Kind = BlockLT
|
|
|
|
|
b.Control = b.Control.Args[0]
|
|
|
|
|
continue
|
|
|
|
|
case OpSETNE:
|
|
|
|
|
b.Kind = BlockNE
|
|
|
|
|
b.Control = b.Control.Args[0]
|
|
|
|
|
continue
|
|
|
|
|
case OpSETB:
|
|
|
|
|
b.Kind = BlockULT
|
|
|
|
|
b.Control = b.Control.Args[0]
|
|
|
|
|
continue
|
|
|
|
|
case OpMOVBload:
|
|
|
|
|
b.Kind = BlockNE
|
|
|
|
|
b.Control = b.NewValue2(OpTESTB, TypeFlags, nil, b.Control, b.Control)
|
|
|
|
|
continue
|
|
|
|
|
// TODO: others
|
|
|
|
|
}
|
|
|
|
|
case BlockLT:
|
|
|
|
|
if b.Control.Op == OpInvertFlags {
|
|
|
|
|
b.Kind = BlockGT
|
|
|
|
|
b.Control = b.Control.Args[0]
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
case BlockGT:
|
|
|
|
|
if b.Control.Op == OpInvertFlags {
|
|
|
|
|
b.Kind = BlockLT
|
|
|
|
|
b.Control = b.Control.Args[0]
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
case BlockLE:
|
|
|
|
|
if b.Control.Op == OpInvertFlags {
|
|
|
|
|
b.Kind = BlockGE
|
|
|
|
|
b.Control = b.Control.Args[0]
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
case BlockGE:
|
|
|
|
|
if b.Control.Op == OpInvertFlags {
|
|
|
|
|
b.Kind = BlockLE
|
|
|
|
|
b.Control = b.Control.Args[0]
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
case BlockULT:
|
|
|
|
|
if b.Control.Op == OpInvertFlags {
|
|
|
|
|
b.Kind = BlockUGT
|
|
|
|
|
b.Control = b.Control.Args[0]
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
case BlockUGT:
|
|
|
|
|
if b.Control.Op == OpInvertFlags {
|
|
|
|
|
b.Kind = BlockULT
|
|
|
|
|
b.Control = b.Control.Args[0]
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
case BlockULE:
|
|
|
|
|
if b.Control.Op == OpInvertFlags {
|
|
|
|
|
b.Kind = BlockUGE
|
|
|
|
|
b.Control = b.Control.Args[0]
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
case BlockUGE:
|
|
|
|
|
if b.Control.Op == OpInvertFlags {
|
|
|
|
|
b.Kind = BlockULE
|
|
|
|
|
b.Control = b.Control.Args[0]
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
case BlockEQ:
|
|
|
|
|
if b.Control.Op == OpInvertFlags {
|
|
|
|
|
b.Control = b.Control.Args[0]
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
case BlockNE:
|
|
|
|
|
if b.Control.Op == OpInvertFlags {
|
|
|
|
|
b.Control = b.Control.Args[0]
|
|
|
|
|
continue
|
|
|
|
|
}
|
2015-03-23 17:02:11 -07:00
|
|
|
}
|
2015-05-18 16:44:20 -07:00
|
|
|
break
|
2015-03-23 17:02:11 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|