cmd/compile: add AMD64 parameter register defs, Arg ops, plumb to ssa.Config

This is partial plumbing recycled from the original register abi test work;
these are the parts that translate easily.  Some other bits are deferred till
later when they are ready to be used.

For #40724.

Change-Id: Ica8c55a4526793446189725a2bc3839124feb38f
Reviewed-on: https://go-review.googlesource.com/c/go/+/260539
Trust: David Chase <drchase@google.com>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
David Chase 2020-10-07 09:44:16 -04:00
parent 42cd40ee74
commit 74cac8d479
7 changed files with 141 additions and 50 deletions

View file

@ -5,6 +5,7 @@
package ssa package ssa
import ( import (
"cmd/compile/internal/abi"
"cmd/compile/internal/base" "cmd/compile/internal/base"
"cmd/compile/internal/ir" "cmd/compile/internal/ir"
"cmd/compile/internal/types" "cmd/compile/internal/types"
@ -21,29 +22,33 @@ type Config struct {
PtrSize int64 // 4 or 8; copy of cmd/internal/sys.Arch.PtrSize PtrSize int64 // 4 or 8; copy of cmd/internal/sys.Arch.PtrSize
RegSize int64 // 4 or 8; copy of cmd/internal/sys.Arch.RegSize RegSize int64 // 4 or 8; copy of cmd/internal/sys.Arch.RegSize
Types Types Types Types
lowerBlock blockRewriter // lowering function lowerBlock blockRewriter // lowering function
lowerValue valueRewriter // lowering function lowerValue valueRewriter // lowering function
splitLoad valueRewriter // function for splitting merged load ops; only used on some architectures splitLoad valueRewriter // function for splitting merged load ops; only used on some architectures
registers []Register // machine registers registers []Register // machine registers
gpRegMask regMask // general purpose integer register mask gpRegMask regMask // general purpose integer register mask
fpRegMask regMask // floating point register mask fpRegMask regMask // floating point register mask
fp32RegMask regMask // floating point register mask fp32RegMask regMask // floating point register mask
fp64RegMask regMask // floating point register mask fp64RegMask regMask // floating point register mask
specialRegMask regMask // special register mask specialRegMask regMask // special register mask
GCRegMap []*Register // garbage collector register map, by GC register index intParamRegs []int8 // register numbers of integer param (in/out) registers
FPReg int8 // register number of frame pointer, -1 if not used floatParamRegs []int8 // register numbers of floating param (in/out) registers
LinkReg int8 // register number of link register if it is a general purpose register, -1 if not used ABI1 *abi.ABIConfig // "ABIInternal" under development // TODO change comment when this becomes current
hasGReg bool // has hardware g register ABI0 *abi.ABIConfig
ctxt *obj.Link // Generic arch information GCRegMap []*Register // garbage collector register map, by GC register index
optimize bool // Do optimization FPReg int8 // register number of frame pointer, -1 if not used
noDuffDevice bool // Don't use Duff's device LinkReg int8 // register number of link register if it is a general purpose register, -1 if not used
useSSE bool // Use SSE for non-float operations hasGReg bool // has hardware g register
useAvg bool // Use optimizations that need Avg* operations ctxt *obj.Link // Generic arch information
useHmul bool // Use optimizations that need Hmul* operations optimize bool // Do optimization
SoftFloat bool // noDuffDevice bool // Don't use Duff's device
Race bool // race detector enabled useSSE bool // Use SSE for non-float operations
BigEndian bool // useAvg bool // Use optimizations that need Avg* operations
UseFMA bool // Use hardware FMA operation useHmul bool // Use optimizations that need Hmul* operations
SoftFloat bool //
Race bool // race detector enabled
BigEndian bool //
UseFMA bool // Use hardware FMA operation
} }
type ( type (
@ -195,6 +200,8 @@ func NewConfig(arch string, types Types, ctxt *obj.Link, optimize bool) *Config
c.gpRegMask = gpRegMaskAMD64 c.gpRegMask = gpRegMaskAMD64
c.fpRegMask = fpRegMaskAMD64 c.fpRegMask = fpRegMaskAMD64
c.specialRegMask = specialRegMaskAMD64 c.specialRegMask = specialRegMaskAMD64
c.intParamRegs = paramIntRegAMD64
c.floatParamRegs = paramFloatRegAMD64
c.FPReg = framepointerRegAMD64 c.FPReg = framepointerRegAMD64
c.LinkReg = linkRegAMD64 c.LinkReg = linkRegAMD64
c.hasGReg = base.Flag.ABIWrap c.hasGReg = base.Flag.ABIWrap
@ -326,6 +333,9 @@ func NewConfig(arch string, types Types, ctxt *obj.Link, optimize bool) *Config
c.useSSE = true c.useSSE = true
c.UseFMA = true c.UseFMA = true
c.ABI0 = abi.NewABIConfig(0, 0)
c.ABI1 = abi.NewABIConfig(len(c.intParamRegs), len(c.floatParamRegs))
// On Plan 9, floating point operations are not allowed in note handler. // On Plan 9, floating point operations are not allowed in note handler.
if objabi.GOOS == "plan9" { if objabi.GOOS == "plan9" {
// Don't use FMA on Plan 9 // Don't use FMA on Plan 9

View file

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build ignore
// +build ignore // +build ignore
package main package main
@ -929,16 +930,18 @@ func init() {
} }
archs = append(archs, arch{ archs = append(archs, arch{
name: "AMD64", name: "AMD64",
pkg: "cmd/internal/obj/x86", pkg: "cmd/internal/obj/x86",
genfile: "../../amd64/ssa.go", genfile: "../../amd64/ssa.go",
ops: AMD64ops, ops: AMD64ops,
blocks: AMD64blocks, blocks: AMD64blocks,
regnames: regNamesAMD64, regnames: regNamesAMD64,
gpregmask: gp, ParamIntRegNames: "AX BX CX DI SI R8 R9 R10 R11",
fpregmask: fp, ParamFloatRegNames: "X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 X10 X11 X12 X13 X14",
specialregmask: x15, gpregmask: gp,
framepointerreg: int8(num["BP"]), fpregmask: fp,
linkreg: -1, // not used specialregmask: x15,
framepointerreg: int8(num["BP"]),
linkreg: -1, // not used
}) })
} }

View file

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build ignore
// +build ignore // +build ignore
package main package main
@ -332,6 +333,11 @@ var genericOps = []opData{
{name: "InitMem", zeroWidth: true}, // memory input to the function. {name: "InitMem", zeroWidth: true}, // memory input to the function.
{name: "Arg", aux: "SymOff", symEffect: "Read", zeroWidth: true}, // argument to the function. aux=GCNode of arg, off = offset in that arg. {name: "Arg", aux: "SymOff", symEffect: "Read", zeroWidth: true}, // argument to the function. aux=GCNode of arg, off = offset in that arg.
// Like Arg, these are generic ops that survive lowering. AuxInt is a register index, and the actual output register for each index is defined by the architecture.
// AuxInt = integer argument index (not a register number). ABI-specified spill loc obtained from function
{name: "ArgIntReg", aux: "Int8", zeroWidth: true}, // argument to the function in an int reg.
{name: "ArgFloatReg", aux: "Int8", zeroWidth: true}, // argument to the function in a float reg.
// The address of a variable. arg0 is the base pointer. // The address of a variable. arg0 is the base pointer.
// If the variable is a global, the base pointer will be SB and // If the variable is a global, the base pointer will be SB and
// the Aux field will be a *obj.LSym. // the Aux field will be a *obj.LSym.

View file

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
//go:build ignore
// +build ignore // +build ignore
// The gen command generates Go code (in the parent directory) for all // The gen command generates Go code (in the parent directory) for all
@ -30,21 +31,23 @@ import (
// apart from type names, and avoid awkward func parameters like "arch arch". // apart from type names, and avoid awkward func parameters like "arch arch".
type arch struct { type arch struct {
name string name string
pkg string // obj package to import for this arch. pkg string // obj package to import for this arch.
genfile string // source file containing opcode code generation. genfile string // source file containing opcode code generation.
ops []opData ops []opData
blocks []blockData blocks []blockData
regnames []string regnames []string
gpregmask regMask ParamIntRegNames string
fpregmask regMask ParamFloatRegNames string
fp32regmask regMask gpregmask regMask
fp64regmask regMask fpregmask regMask
specialregmask regMask fp32regmask regMask
framepointerreg int8 fp64regmask regMask
linkreg int8 specialregmask regMask
generic bool framepointerreg int8
imports []string linkreg int8
generic bool
imports []string
} }
type opData struct { type opData struct {
@ -412,7 +415,9 @@ func genOp() {
} }
fmt.Fprintf(w, "var registers%s = [...]Register {\n", a.name) fmt.Fprintf(w, "var registers%s = [...]Register {\n", a.name)
var gcRegN int var gcRegN int
num := map[string]int8{}
for i, r := range a.regnames { for i, r := range a.regnames {
num[r] = int8(i)
pkg := a.pkg[len("cmd/internal/obj/"):] pkg := a.pkg[len("cmd/internal/obj/"):]
var objname string // name in cmd/internal/obj/$ARCH var objname string // name in cmd/internal/obj/$ARCH
switch r { switch r {
@ -435,11 +440,38 @@ func genOp() {
} }
fmt.Fprintf(w, " {%d, %s, %d, \"%s\"},\n", i, objname, gcRegIdx, r) fmt.Fprintf(w, " {%d, %s, %d, \"%s\"},\n", i, objname, gcRegIdx, r)
} }
parameterRegisterList := func(paramNamesString string) []int8 {
paramNamesString = strings.TrimSpace(paramNamesString)
if paramNamesString == "" {
return nil
}
paramNames := strings.Split(paramNamesString, " ")
var paramRegs []int8
for _, regName := range paramNames {
if regName == "" {
// forgive extra spaces
continue
}
if regNum, ok := num[regName]; ok {
paramRegs = append(paramRegs, regNum)
delete(num, regName)
} else {
log.Fatalf("parameter register %s for architecture %s not a register name (or repeated in parameter list)", regName, a.name)
}
}
return paramRegs
}
paramIntRegs := parameterRegisterList(a.ParamIntRegNames)
paramFloatRegs := parameterRegisterList(a.ParamFloatRegNames)
if gcRegN > 32 { if gcRegN > 32 {
// Won't fit in a uint32 mask. // Won't fit in a uint32 mask.
log.Fatalf("too many GC registers (%d > 32) on %s", gcRegN, a.name) log.Fatalf("too many GC registers (%d > 32) on %s", gcRegN, a.name)
} }
fmt.Fprintln(w, "}") fmt.Fprintln(w, "}")
fmt.Fprintf(w, "var paramIntReg%s = %#v\n", a.name, paramIntRegs)
fmt.Fprintf(w, "var paramFloatReg%s = %#v\n", a.name, paramFloatRegs)
fmt.Fprintf(w, "var gpRegMask%s = regMask(%d)\n", a.name, a.gpregmask) fmt.Fprintf(w, "var gpRegMask%s = regMask(%d)\n", a.name, a.gpregmask)
fmt.Fprintf(w, "var fpRegMask%s = regMask(%d)\n", a.name, a.fpregmask) fmt.Fprintf(w, "var fpRegMask%s = regMask(%d)\n", a.name, a.fpregmask)
if a.fp32regmask != 0 { if a.fp32regmask != 0 {

View file

@ -79,6 +79,7 @@ type AuxCall struct {
Fn *obj.LSym Fn *obj.LSym
args []Param // Includes receiver for method calls. Does NOT include hidden closure pointer. args []Param // Includes receiver for method calls. Does NOT include hidden closure pointer.
results []Param results []Param
reg *regInfo // regInfo for this call // TODO for now nil means ignore
} }
// ResultForOffset returns the index of the result at a particular offset among the results // ResultForOffset returns the index of the result at a particular offset among the results
@ -186,16 +187,19 @@ func (a *AuxCall) String() string {
// StaticAuxCall returns an AuxCall for a static call. // StaticAuxCall returns an AuxCall for a static call.
func StaticAuxCall(sym *obj.LSym, args []Param, results []Param) *AuxCall { func StaticAuxCall(sym *obj.LSym, args []Param, results []Param) *AuxCall {
// TODO Create regInfo for AuxCall
return &AuxCall{Fn: sym, args: args, results: results} return &AuxCall{Fn: sym, args: args, results: results}
} }
// InterfaceAuxCall returns an AuxCall for an interface call. // InterfaceAuxCall returns an AuxCall for an interface call.
func InterfaceAuxCall(args []Param, results []Param) *AuxCall { func InterfaceAuxCall(args []Param, results []Param) *AuxCall {
// TODO Create regInfo for AuxCall
return &AuxCall{Fn: nil, args: args, results: results} return &AuxCall{Fn: nil, args: args, results: results}
} }
// ClosureAuxCall returns an AuxCall for a closure call. // ClosureAuxCall returns an AuxCall for a closure call.
func ClosureAuxCall(args []Param, results []Param) *AuxCall { func ClosureAuxCall(args []Param, results []Param) *AuxCall {
// TODO Create regInfo for AuxCall
return &AuxCall{Fn: nil, args: args, results: results} return &AuxCall{Fn: nil, args: args, results: results}
} }

View file

@ -2747,6 +2747,8 @@ const (
OpConstSlice OpConstSlice
OpInitMem OpInitMem
OpArg OpArg
OpArgIntReg
OpArgFloatReg
OpAddr OpAddr
OpLocalAddr OpLocalAddr
OpSP OpSP
@ -35253,6 +35255,20 @@ var opcodeTable = [...]opInfo{
symEffect: SymRead, symEffect: SymRead,
generic: true, generic: true,
}, },
{
name: "ArgIntReg",
auxType: auxInt8,
argLen: 0,
zeroWidth: true,
generic: true,
},
{
name: "ArgFloatReg",
auxType: auxInt8,
argLen: 0,
zeroWidth: true,
generic: true,
},
{ {
name: "Addr", name: "Addr",
auxType: auxSym, auxType: auxSym,
@ -36141,6 +36157,8 @@ var registers386 = [...]Register{
{15, x86.REG_X7, -1, "X7"}, {15, x86.REG_X7, -1, "X7"},
{16, 0, -1, "SB"}, {16, 0, -1, "SB"},
} }
var paramIntReg386 = []int8(nil)
var paramFloatReg386 = []int8(nil)
var gpRegMask386 = regMask(239) var gpRegMask386 = regMask(239)
var fpRegMask386 = regMask(65280) var fpRegMask386 = regMask(65280)
var specialRegMask386 = regMask(0) var specialRegMask386 = regMask(0)
@ -36181,6 +36199,8 @@ var registersAMD64 = [...]Register{
{31, x86.REG_X15, -1, "X15"}, {31, x86.REG_X15, -1, "X15"},
{32, 0, -1, "SB"}, {32, 0, -1, "SB"},
} }
var paramIntRegAMD64 = []int8{0, 3, 1, 7, 6, 8, 9, 10, 11}
var paramFloatRegAMD64 = []int8{16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30}
var gpRegMaskAMD64 = regMask(49135) var gpRegMaskAMD64 = regMask(49135)
var fpRegMaskAMD64 = regMask(2147418112) var fpRegMaskAMD64 = regMask(2147418112)
var specialRegMaskAMD64 = regMask(2147483648) var specialRegMaskAMD64 = regMask(2147483648)
@ -36221,6 +36241,8 @@ var registersARM = [...]Register{
{31, arm.REG_F15, -1, "F15"}, {31, arm.REG_F15, -1, "F15"},
{32, 0, -1, "SB"}, {32, 0, -1, "SB"},
} }
var paramIntRegARM = []int8(nil)
var paramFloatRegARM = []int8(nil)
var gpRegMaskARM = regMask(21503) var gpRegMaskARM = regMask(21503)
var fpRegMaskARM = regMask(4294901760) var fpRegMaskARM = regMask(4294901760)
var specialRegMaskARM = regMask(0) var specialRegMaskARM = regMask(0)
@ -36292,6 +36314,8 @@ var registersARM64 = [...]Register{
{62, arm64.REG_F31, -1, "F31"}, {62, arm64.REG_F31, -1, "F31"},
{63, 0, -1, "SB"}, {63, 0, -1, "SB"},
} }
var paramIntRegARM64 = []int8(nil)
var paramFloatRegARM64 = []int8(nil)
var gpRegMaskARM64 = regMask(670826495) var gpRegMaskARM64 = regMask(670826495)
var fpRegMaskARM64 = regMask(9223372034707292160) var fpRegMaskARM64 = regMask(9223372034707292160)
var specialRegMaskARM64 = regMask(0) var specialRegMaskARM64 = regMask(0)
@ -36347,6 +36371,8 @@ var registersMIPS = [...]Register{
{46, mips.REG_LO, -1, "LO"}, {46, mips.REG_LO, -1, "LO"},
{47, 0, -1, "SB"}, {47, 0, -1, "SB"},
} }
var paramIntRegMIPS = []int8(nil)
var paramFloatRegMIPS = []int8(nil)
var gpRegMaskMIPS = regMask(335544318) var gpRegMaskMIPS = regMask(335544318)
var fpRegMaskMIPS = regMask(35183835217920) var fpRegMaskMIPS = regMask(35183835217920)
var specialRegMaskMIPS = regMask(105553116266496) var specialRegMaskMIPS = regMask(105553116266496)
@ -36417,6 +36443,8 @@ var registersMIPS64 = [...]Register{
{61, mips.REG_LO, -1, "LO"}, {61, mips.REG_LO, -1, "LO"},
{62, 0, -1, "SB"}, {62, 0, -1, "SB"},
} }
var paramIntRegMIPS64 = []int8(nil)
var paramFloatRegMIPS64 = []int8(nil)
var gpRegMaskMIPS64 = regMask(167772158) var gpRegMaskMIPS64 = regMask(167772158)
var fpRegMaskMIPS64 = regMask(1152921504338411520) var fpRegMaskMIPS64 = regMask(1152921504338411520)
var specialRegMaskMIPS64 = regMask(3458764513820540928) var specialRegMaskMIPS64 = regMask(3458764513820540928)
@ -36488,6 +36516,8 @@ var registersPPC64 = [...]Register{
{62, ppc64.REG_F30, -1, "F30"}, {62, ppc64.REG_F30, -1, "F30"},
{63, ppc64.REG_F31, -1, "F31"}, {63, ppc64.REG_F31, -1, "F31"},
} }
var paramIntRegPPC64 = []int8(nil)
var paramFloatRegPPC64 = []int8(nil)
var gpRegMaskPPC64 = regMask(1073733624) var gpRegMaskPPC64 = regMask(1073733624)
var fpRegMaskPPC64 = regMask(576460743713488896) var fpRegMaskPPC64 = regMask(576460743713488896)
var specialRegMaskPPC64 = regMask(0) var specialRegMaskPPC64 = regMask(0)
@ -36559,6 +36589,8 @@ var registersRISCV64 = [...]Register{
{62, riscv.REG_F31, -1, "F31"}, {62, riscv.REG_F31, -1, "F31"},
{63, 0, -1, "SB"}, {63, 0, -1, "SB"},
} }
var paramIntRegRISCV64 = []int8(nil)
var paramFloatRegRISCV64 = []int8(nil)
var gpRegMaskRISCV64 = regMask(1006632948) var gpRegMaskRISCV64 = regMask(1006632948)
var fpRegMaskRISCV64 = regMask(9223372034707292160) var fpRegMaskRISCV64 = regMask(9223372034707292160)
var specialRegMaskRISCV64 = regMask(0) var specialRegMaskRISCV64 = regMask(0)
@ -36599,6 +36631,8 @@ var registersS390X = [...]Register{
{31, s390x.REG_F15, -1, "F15"}, {31, s390x.REG_F15, -1, "F15"},
{32, 0, -1, "SB"}, {32, 0, -1, "SB"},
} }
var paramIntRegS390X = []int8(nil)
var paramFloatRegS390X = []int8(nil)
var gpRegMaskS390X = regMask(23551) var gpRegMaskS390X = regMask(23551)
var fpRegMaskS390X = regMask(4294901760) var fpRegMaskS390X = regMask(4294901760)
var specialRegMaskS390X = regMask(0) var specialRegMaskS390X = regMask(0)
@ -36657,6 +36691,8 @@ var registersWasm = [...]Register{
{49, wasm.REGG, -1, "g"}, {49, wasm.REGG, -1, "g"},
{50, 0, -1, "SB"}, {50, 0, -1, "SB"},
} }
var paramIntRegWasm = []int8(nil)
var paramFloatRegWasm = []int8(nil)
var gpRegMaskWasm = regMask(65535) var gpRegMaskWasm = regMask(65535)
var fpRegMaskWasm = regMask(281474976645120) var fpRegMaskWasm = regMask(281474976645120)
var fp32RegMaskWasm = regMask(4294901760) var fp32RegMaskWasm = regMask(4294901760)

View file

@ -112,7 +112,7 @@ const (
stackDebug = 0 stackDebug = 0
stackFromSystem = 0 // allocate stacks from system memory instead of the heap stackFromSystem = 0 // allocate stacks from system memory instead of the heap
stackFaultOnFree = 0 // old stacks are mapped noaccess to detect use after free stackFaultOnFree = 0 // old stacks are mapped noaccess to detect use after free
stackPoisonCopy = 0 // fill stack that should not be accessed with garbage, to detect bad dereferences during copy stackPoisonCopy = 1 // fill stack that should not be accessed with garbage, to detect bad dereferences during copy
stackNoCache = 0 // disable per-P small stack caches stackNoCache = 0 // disable per-P small stack caches
// check the BP links during traceback. // check the BP links during traceback.