]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.ssa] cmd/compile: implement reserved registers
authorKeith Randall <khr@golang.org>
Thu, 22 Oct 2015 20:07:38 +0000 (13:07 -0700)
committerKeith Randall <khr@golang.org>
Fri, 23 Oct 2015 04:14:06 +0000 (04:14 +0000)
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: Todd Neal <todd@tneal.org>
src/cmd/compile/internal/gc/ssa.go
src/cmd/compile/internal/ssa/config.go
src/cmd/compile/internal/ssa/regalloc.go

index 918d71ca6d7a700e6e731bb57edc5609f46a1ba1..64391b0fca4c0d2cbb1fb96160bb8bb09ebb6727 100644 (file)
@@ -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))
 }
 
index c935a2b83eccbda2eadaf20b74cf14f091deb3e4..efb8b146a1f345a6140635dac58fc3f4176bb6db 100644 (file)
@@ -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
 }
index abbb540a7e9848126798ad149c70553f3f18f804..d42b14a984318c0b184870ff7f79ff8e1c4ad599 100644 (file)
 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
+}