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
// 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
return n
}
-func (e ssaExport) CanSSA(t ssa.Type) bool {
+func (e *ssaExport) CanSSA(t ssa.Type) bool {
return canSSAType(t.(*Type))
}
package ssa
-import "fmt"
+import (
+ "cmd/internal/obj"
+ "fmt"
+)
type Config struct {
arch string // "amd64", etc.
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, ...
}
}
// 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":
default:
fe.Unimplementedf("arch %s not implemented", arch)
}
+ c.ctxt = ctxt
return c
}
package ssa
import (
+ "cmd/internal/obj"
"fmt"
"unsafe"
)
}
mask &^= 1<<4 | 1<<32 // don't spill SP or SB
+ mask &^= s.reserved()
// Allocate a register.
r := s.allocReg(mask)
}
// 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) {
}
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.
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)
// 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
}
// 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.
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
+}