diff options
Diffstat (limited to 'src/cmd/compile/internal/types/type.go')
-rw-r--r-- | src/cmd/compile/internal/types/type.go | 66 |
1 files changed, 59 insertions, 7 deletions
diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index a777a5fd90..5d1d5d4008 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -66,8 +66,9 @@ const ( TCHANARGS // SSA backend types - TSSA // internal types used by SSA backend (flags, memory, etc.) - TTUPLE // a pair of types, used by SSA backend + TSSA // internal types used by SSA backend (flags, memory, etc.) + TTUPLE // a pair of types, used by SSA backend + TRESULTS // multiple types; the result of calling a function or method, with a memory at the end. NTYPE ) @@ -330,6 +331,11 @@ type Tuple struct { // Any tuple with a memory type must put that memory type second. } +// Results are the output from calls that will be late-expanded. +type Results struct { + Types []*Type // Last element is memory output from call. +} + // Array contains Type fields specific to array types. type Array struct { Elem *Type // element type @@ -466,6 +472,8 @@ func New(et EType) *Type { t.Extra = new(Chan) case TTUPLE: t.Extra = new(Tuple) + case TRESULTS: + t.Extra = new(Results) } return t } @@ -512,6 +520,12 @@ func NewTuple(t1, t2 *Type) *Type { return t } +func NewResults(types []*Type) *Type { + t := New(TRESULTS) + t.Extra.(*Results).Types = types + return t +} + func newSSA(name string) *Type { t := New(TSSA) t.Extra = name @@ -688,7 +702,7 @@ func (t *Type) copy() *Type { case TARRAY: x := *t.Extra.(*Array) nt.Extra = &x - case TTUPLE, TSSA: + case TTUPLE, TSSA, TRESULTS: Fatalf("ssa types cannot be copied") } // TODO(mdempsky): Find out why this is necessary and explain. @@ -1051,6 +1065,23 @@ func (t *Type) cmp(x *Type) Cmp { } return ttup.second.Compare(xtup.second) + case TRESULTS: + xResults := x.Extra.(*Results) + tResults := t.Extra.(*Results) + xl, tl := len(xResults.Types), len(tResults.Types) + if tl != xl { + if tl < xl { + return CMPlt + } + return CMPgt + } + for i := 0; i < tl; i++ { + if c := tResults.Types[i].Compare(xResults.Types[i]); c != CMPeq { + return c + } + } + return CMPeq + case TMAP: if c := t.Key().cmp(x.Key()); c != CMPeq { return c @@ -1305,6 +1336,9 @@ func (t *Type) FieldType(i int) *Type { panic("bad tuple index") } } + if t.Etype == TRESULTS { + return t.Extra.(*Results).Types[i] + } return t.Field(i).Type } func (t *Type) FieldOff(i int) int64 { @@ -1382,11 +1416,20 @@ func (t *Type) ChanDir() ChanDir { } func (t *Type) IsMemory() bool { - return t == TypeMem || t.Etype == TTUPLE && t.Extra.(*Tuple).second == TypeMem + if t == TypeMem || t.Etype == TTUPLE && t.Extra.(*Tuple).second == TypeMem { + return true + } + if t.Etype == TRESULTS { + if types := t.Extra.(*Results).Types; len(types) > 0 && types[len(types)-1] == TypeMem { + return true + } + } + return false } -func (t *Type) IsFlags() bool { return t == TypeFlags } -func (t *Type) IsVoid() bool { return t == TypeVoid } -func (t *Type) IsTuple() bool { return t.Etype == TTUPLE } +func (t *Type) IsFlags() bool { return t == TypeFlags } +func (t *Type) IsVoid() bool { return t == TypeVoid } +func (t *Type) IsTuple() bool { return t.Etype == TTUPLE } +func (t *Type) IsResults() bool { return t.Etype == TRESULTS } // IsUntyped reports whether t is an untyped type. func (t *Type) IsUntyped() bool { @@ -1431,6 +1474,15 @@ func (t *Type) HasPointers() bool { case TTUPLE: ttup := t.Extra.(*Tuple) return ttup.first.HasPointers() || ttup.second.HasPointers() + + case TRESULTS: + types := t.Extra.(*Results).Types + for _, et := range types { + if et.HasPointers() { + return true + } + } + return false } return true |