aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/ssa/op.go
diff options
context:
space:
mode:
authorJeremy Faller <jeremy@golang.org>2020-09-30 17:57:14 -0400
committerJeremy Faller <jeremy@golang.org>2020-09-30 18:00:58 -0400
commit91e4d2d57bc341dd82c98247117114c851380aef (patch)
tree15a2d023cdc63543cf8a6e99f8a561c0a0459000 /src/cmd/compile/internal/ssa/op.go
parentc863e14a6c15e174ac0979ddd7f9530d6a4ec9cc (diff)
parent846dce9d05f19a1f53465e62a304dea21b99f910 (diff)
downloadgo-91e4d2d57bc341dd82c98247117114c851380aef.tar.gz
go-91e4d2d57bc341dd82c98247117114c851380aef.zip
[dev.link] Merge branch 'master' into dev.link
2 conflicts, that make sense. src/cmd/internal/obj/objfile.go src/cmd/link/internal/loader/loader.go Change-Id: Ib224e2d248cb568fa1e888af79dd908b2f5e05ff
Diffstat (limited to 'src/cmd/compile/internal/ssa/op.go')
-rw-r--r--src/cmd/compile/internal/ssa/op.go128
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))