From 7d6124697223ecf9d5ce21221377da2b9c7fd9f3 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Thu, 22 Oct 2015 13:07:38 -0700 Subject: [PATCH] [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 Reviewed-by: Todd Neal --- src/cmd/compile/internal/gc/ssa.go | 6 ++--- src/cmd/compile/internal/ssa/config.go | 9 +++++-- src/cmd/compile/internal/ssa/regalloc.go | 31 ++++++++++++++++++------ 3 files changed, 34 insertions(+), 12 deletions(-) diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 918d71ca6d..64391b0fca 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -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)) } diff --git a/src/cmd/compile/internal/ssa/config.go b/src/cmd/compile/internal/ssa/config.go index c935a2b83e..efb8b146a1 100644 --- a/src/cmd/compile/internal/ssa/config.go +++ b/src/cmd/compile/internal/ssa/config.go @@ -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 } diff --git a/src/cmd/compile/internal/ssa/regalloc.go b/src/cmd/compile/internal/ssa/regalloc.go index abbb540a7e..d42b14a984 100644 --- a/src/cmd/compile/internal/ssa/regalloc.go +++ b/src/cmd/compile/internal/ssa/regalloc.go @@ -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 +} -- 2.48.1