Commit 7d612469 authored by Keith Randall's avatar Keith Randall

[dev.ssa] cmd/compile: implement reserved registers

BP for framepointer experiment
R15 for dynamic linking

Change-Id: I28e48be461d04a4d5c9b013f48fce5c0e58d6a08
Reviewed-on: https://go-review.googlesource.com/16231
Run-TryBot: Todd Neal <todd@tneal.org>
Reviewed-by: 's avatarTodd Neal <todd@tneal.org>
parent f206b16f
......@@ -41,7 +41,7 @@ func buildssa(fn *Node) (ssafn *ssa.Func, usessa bool) {
var e ssaExport
e.log = usessa
s.config = ssa.NewConfig(Thearch.Thestring, &e)
s.config = ssa.NewConfig(Thearch.Thestring, &e, Ctxt)
s.f = s.config.NewFunc()
s.f.Name = name
s.exitCode = fn.Func.Exit
......@@ -239,7 +239,7 @@ type state struct {
// symbols for PEXTERN, PAUTO and PPARAMOUT variables so they can be reused.
varsyms map[*Node]interface{}
// starting values. Memory, frame pointer, and stack pointer
// starting values. Memory, stack pointer, and globals pointer
startmem *ssa.Value
sp *ssa.Value
sb *ssa.Value
......@@ -4367,7 +4367,7 @@ func (e *ssaExport) Auto(t ssa.Type) fmt.Stringer {
return n
}
func (e ssaExport) CanSSA(t ssa.Type) bool {
func (e *ssaExport) CanSSA(t ssa.Type) bool {
return canSSAType(t.(*Type))
}
......
......@@ -4,7 +4,10 @@
package ssa
import "fmt"
import (
"cmd/internal/obj"
"fmt"
)
type Config struct {
arch string // "amd64", etc.
......@@ -14,6 +17,7 @@ type Config struct {
lowerValue func(*Value, *Config) bool // lowering function
fe Frontend // callbacks into compiler frontend
HTML *HTMLWriter // html writer, for debugging
ctxt *obj.Link // Generic arch information
// TODO: more stuff. Compiler flags of interest, ...
}
......@@ -63,7 +67,7 @@ type Frontend interface {
}
// NewConfig returns a new configuration object for the given architecture.
func NewConfig(arch string, fe Frontend) *Config {
func NewConfig(arch string, fe Frontend, ctxt *obj.Link) *Config {
c := &Config{arch: arch, fe: fe}
switch arch {
case "amd64":
......@@ -79,6 +83,7 @@ func NewConfig(arch string, fe Frontend) *Config {
default:
fe.Unimplementedf("arch %s not implemented", arch)
}
c.ctxt = ctxt
return c
}
......
......@@ -100,6 +100,7 @@
package ssa
import (
"cmd/internal/obj"
"fmt"
"unsafe"
)
......@@ -386,6 +387,7 @@ func (s *regAllocState) allocValToReg(v *Value, mask regMask, nospill bool) *Val
}
mask &^= 1<<4 | 1<<32 // don't spill SP or SB
mask &^= s.reserved()
// Allocate a register.
r := s.allocReg(mask)
......@@ -568,11 +570,14 @@ func (s *regAllocState) setState(state []regState) {
}
// compatRegs returns the set of registers which can store v.
func (v *Value) compatRegs() regMask {
func (s *regAllocState) compatRegs(v *Value) regMask {
var m regMask
if v.Type.IsFloat() {
return 0xffff << 16 // X0-X15
m = 0xffff << 16 // X0-X15
} else {
m = 0xffef << 0 // AX-R15, except SP
}
return 0xffef << 0 // AX-R15, except SP
return m &^ s.reserved()
}
func (s *regAllocState) regalloc(f *Func) {
......@@ -686,7 +691,7 @@ func (s *regAllocState) regalloc(f *Func) {
}
r := phiRegs[i]
if r == noRegister {
m := v.compatRegs() & ^s.used
m := s.compatRegs(v) & ^s.used
if m == 0 {
// stack-based phi
// Spills will be inserted in all the predecessors below.
......@@ -774,7 +779,7 @@ func (s *regAllocState) regalloc(f *Func) {
var r register
var mask regMask
if len(regspec.outputs) > 0 {
mask = regspec.outputs[0]
mask = regspec.outputs[0] &^ s.reserved()
}
if mask != 0 {
r = s.allocReg(mask)
......@@ -876,7 +881,7 @@ func (s *regAllocState) regalloc(f *Func) {
// This stack-based phi is the argument of some other
// phi in this block. We must make a copy of its
// value so that we don't clobber it prematurely.
c := s.allocValToReg(v, v.compatRegs(), false)
c := s.allocValToReg(v, s.compatRegs(v), false)
d := p.NewValue1(v.Line, OpStoreReg, v.Type, c)
s.values[v.ID].spill2 = d
}
......@@ -888,7 +893,7 @@ func (s *regAllocState) regalloc(f *Func) {
// If already in a register, use that. If not, pick a compatible
// register.
w := v.Args[i]
c := s.allocValToReg(w, w.compatRegs(), false)
c := s.allocValToReg(w, s.compatRegs(w), false)
v.Args[i] = p.NewValue1(v.Line, OpStoreReg, v.Type, c)
}
// Figure out what value goes in each register.
......@@ -1111,3 +1116,15 @@ func (f *Func) live() [][][]ID {
return live
}
// reserved returns a mask of reserved registers.
func (s *regAllocState) reserved() regMask {
var m regMask
if obj.Framepointer_enabled != 0 {
m |= 1 << 5 // BP
}
if s.f.Config.ctxt.Flag_dynlink {
m |= 1 << 15 // R15
}
return m
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment