diff options
Diffstat (limited to 'src/cmd/compile/internal/ssa/op.go')
-rw-r--r-- | src/cmd/compile/internal/ssa/op.go | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/ssa/op.go b/src/cmd/compile/internal/ssa/op.go index 063998c6a1..9b45dd53c7 100644 --- a/src/cmd/compile/internal/ssa/op.go +++ b/src/cmd/compile/internal/ssa/op.go @@ -5,6 +5,7 @@ package ssa import ( + "cmd/compile/internal/types" "cmd/internal/obj" "fmt" ) @@ -67,6 +68,124 @@ type regInfo struct { type auxType int8 +type Param struct { + Type *types.Type + Offset int32 // TODO someday this will be a register +} + +type AuxCall struct { + Fn *obj.LSym + args []Param // Includes receiver for method calls. Does NOT include hidden closure pointer. + results []Param +} + +// ResultForOffset returns the index of the result at a particular offset among the results +// This does not include the mem result for the call opcode. +func (a *AuxCall) ResultForOffset(offset int64) int64 { + which := int64(-1) + for i := int64(0); i < a.NResults(); i++ { // note aux NResults does not include mem result. + if a.OffsetOfResult(i) == offset { + which = i + break + } + } + return which +} + +// OffsetOfResult returns the SP offset of result which (indexed 0, 1, etc). +func (a *AuxCall) OffsetOfResult(which int64) int64 { + return int64(a.results[which].Offset) +} + +// OffsetOfArg returns the SP offset of argument which (indexed 0, 1, etc). +func (a *AuxCall) OffsetOfArg(which int64) int64 { + return int64(a.args[which].Offset) +} + +// TypeOfResult returns the type of result which (indexed 0, 1, etc). +func (a *AuxCall) TypeOfResult(which int64) *types.Type { + return a.results[which].Type +} + +// TypeOfArg returns the type of argument which (indexed 0, 1, etc). +func (a *AuxCall) TypeOfArg(which int64) *types.Type { + return a.args[which].Type +} + +// SizeOfResult returns the size of result which (indexed 0, 1, etc). +func (a *AuxCall) SizeOfResult(which int64) int64 { + return a.TypeOfResult(which).Width +} + +// SizeOfArg returns the size of argument which (indexed 0, 1, etc). +func (a *AuxCall) SizeOfArg(which int64) int64 { + return a.TypeOfArg(which).Width +} + +// NResults returns the number of results +func (a *AuxCall) NResults() int64 { + return int64(len(a.results)) +} + +// NArgs returns the number of arguments +func (a *AuxCall) NArgs() int64 { + return int64(len(a.args)) +} + +// String returns +// "AuxCall{<fn>(<args>)}" if len(results) == 0; +// "AuxCall{<fn>(<args>)<results[0]>}" if len(results) == 1; +// "AuxCall{<fn>(<args>)(<results>)}" otherwise. +func (a *AuxCall) String() string { + var fn string + if a.Fn == nil { + fn = "AuxCall{nil" // could be interface/closure etc. + } else { + fn = fmt.Sprintf("AuxCall{%v", a.Fn) + } + + if len(a.args) == 0 { + fn += "()" + } else { + s := "(" + for _, arg := range a.args { + fn += fmt.Sprintf("%s[%v,%v]", s, arg.Type, arg.Offset) + s = "," + } + fn += ")" + } + + if len(a.results) > 0 { // usual is zero or one; only some RT calls have more than one. + if len(a.results) == 1 { + fn += fmt.Sprintf("[%v,%v]", a.results[0].Type, a.results[0].Offset) + } else { + s := "(" + for _, result := range a.results { + fn += fmt.Sprintf("%s[%v,%v]", s, result.Type, result.Offset) + s = "," + } + fn += ")" + } + } + + return fn + "}" +} + +// StaticAuxCall returns an AuxCall for a static call. +func StaticAuxCall(sym *obj.LSym, args []Param, results []Param) *AuxCall { + return &AuxCall{Fn: sym, args: args, results: results} +} + +// InterfaceAuxCall returns an AuxCall for an interface call. +func InterfaceAuxCall(args []Param, results []Param) *AuxCall { + return &AuxCall{Fn: nil, args: args, results: results} +} + +// ClosureAuxCall returns an AuxCall for a closure call. +func ClosureAuxCall(args []Param, results []Param) *AuxCall { + return &AuxCall{Fn: nil, args: args, results: results} +} + const ( auxNone auxType = iota auxBool // auxInt is 0/1 for false/true @@ -85,6 +204,8 @@ const ( auxTyp // aux is a type auxTypSize // aux is a type, auxInt is a size, must have Aux.(Type).Size() == AuxInt auxCCop // aux is a ssa.Op that represents a flags-to-bool conversion (e.g. LessThan) + auxCall // aux is a *ssa.AuxCall + auxCallOff // aux is a *ssa.AuxCall, AuxInt is int64 param (in+out) size // architecture specific aux types auxARM64BitField // aux is an arm64 bitfield lsb and width packed into auxInt @@ -176,6 +297,13 @@ func makeValAndOff32(val, off int32) ValAndOff { return ValAndOff(int64(val)<<32 + int64(uint32(off))) } +func makeValAndOff64(val, off int64) ValAndOff { + if !validValAndOff(val, off) { + panic("invalid makeValAndOff64") + } + return ValAndOff(val<<32 + int64(uint32(off))) +} + func (x ValAndOff) canAdd(off int64) bool { newoff := x.Off() + off return newoff == int64(int32(newoff)) |