aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/types/alg.go
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2020-12-23 00:08:03 -0500
committerRuss Cox <rsc@golang.org>2020-12-23 06:38:01 +0000
commit9ee309255a94499c6f4e6d3ac7653b5eeb4ae7b7 (patch)
tree3a166c8ebba0ca3a374fb126fd58e7b74758ed3a /src/cmd/compile/internal/types/alg.go
parentead4957892bc1975d9cc9c32777733c67e5a885e (diff)
downloadgo-9ee309255a94499c6f4e6d3ac7653b5eeb4ae7b7.tar.gz
go-9ee309255a94499c6f4e6d3ac7653b5eeb4ae7b7.zip
[dev.regabi] cmd/compile: move helpers into package types [generated]
[git-generate] cd src/cmd/compile/internal/gc rf ' # Type hash (formatting). mv typehash TypeHash mv TypeHash fmt.go # Method sorting. mv methcmp MethodsByName mv MethodsByName MethodsByName.Len MethodsByName.Swap \ MethodsByName.Less sort.go # Move version check into types. # A little surprising, but its keyed off the types.Pkg. ex { import "cmd/compile/internal/types" var p *types.Pkg var major, minor int langSupported(major, minor, p) -> AllowsGoVersion(p, major, minor) } rm langSupported mv checkLang ParseLangFlag mv lang langWant AllowsGoVersion ParseLangFlag \ parseLang currentLang goVersionRE goversion.go mv testdclstack CheckDclstack mv CheckDclstack scope.go mv algtype1 AlgType mv isComplex IsComplex mv isFloat IsFloat mv isInt IsInt mv issimple IsSimple mv okforcmp IsOrdered mv floatForComplex FloatForComplex mv complexForFloat ComplexForFloat mv isdirectiface IsDirectIface mv isifacemethod IsInterfaceMethod mv isMethodApplicable IsMethodApplicable mv ispaddedfield IsPaddedField mv isRuntimePkg IsRuntimePkg mv isReflectPkg IsReflectPkg mv methtype ReceiverBaseType mv typesymname TypeSymName mv typesym TypeSym mv typeLookup TypeSymLookup mv IsAlias IsDotAlias mv isreflexive IsReflexive mv simtype SimType # The type1.go here is to avoid an undiagnosed bug in rf # that does not get the follow-up typechecking right if we # move directly to type.go during the mv into package types below. mv \ IsInt IsOrdered IsReflexive \ IsDirectIface IsInterfaceMethod IsMethodApplicable IsPaddedField \ IsRuntimePkg IsReflectPkg ReceiverBaseType \ FloatForComplex ComplexForFloat \ TypeSym TypeSymLookup TypeSymName \ typepkg SimType \ type1.go # The alg1.go here is because we are only moving part of alg.go. mv typeHasNoAlg TypeHasNoAlg mv AlgKind ANOEQ AlgType TypeHasNoAlg IsComparable IncomparableField IsPaddedField alg1.go mv IsDotAlias pkg.go mv alg1.go algkind_string.go fmt.go goversion.go pkg.go \ CheckDclstack \ # scope.go sort.go type1.go \ cmd/compile/internal/types ' cd ../types rf ' mv IsDclstackValid isDclstackValid mv alg1.go alg.go mv type1.go type.go ' Change-Id: I8bd53b21c7bdd1770e1b525de32f136833e84c9d Reviewed-on: https://go-review.googlesource.com/c/go/+/279307 Trust: Russ Cox <rsc@golang.org> Run-TryBot: Russ Cox <rsc@golang.org> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Diffstat (limited to 'src/cmd/compile/internal/types/alg.go')
-rw-r--r--src/cmd/compile/internal/types/alg.go173
1 files changed, 173 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/types/alg.go b/src/cmd/compile/internal/types/alg.go
new file mode 100644
index 0000000000..14200e0d16
--- /dev/null
+++ b/src/cmd/compile/internal/types/alg.go
@@ -0,0 +1,173 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package types
+
+import "cmd/compile/internal/base"
+
+// AlgKind describes the kind of algorithms used for comparing and
+// hashing a Type.
+type AlgKind int
+
+//go:generate stringer -type AlgKind -trimprefix A
+
+const (
+ // These values are known by runtime.
+ ANOEQ AlgKind = iota
+ AMEM0
+ AMEM8
+ AMEM16
+ AMEM32
+ AMEM64
+ AMEM128
+ ASTRING
+ AINTER
+ ANILINTER
+ AFLOAT32
+ AFLOAT64
+ ACPLX64
+ ACPLX128
+
+ // Type can be compared/hashed as regular memory.
+ AMEM AlgKind = 100
+
+ // Type needs special comparison/hashing functions.
+ ASPECIAL AlgKind = -1
+)
+
+// AlgType returns the AlgKind used for comparing and hashing Type t.
+// If it returns ANOEQ, it also returns the component type of t that
+// makes it incomparable.
+func AlgType(t *Type) (AlgKind, *Type) {
+ if t.Broke() {
+ return AMEM, nil
+ }
+ if t.Noalg() {
+ return ANOEQ, t
+ }
+
+ switch t.Kind() {
+ case TANY, TFORW:
+ // will be defined later.
+ return ANOEQ, t
+
+ case TINT8, TUINT8, TINT16, TUINT16,
+ TINT32, TUINT32, TINT64, TUINT64,
+ TINT, TUINT, TUINTPTR,
+ TBOOL, TPTR,
+ TCHAN, TUNSAFEPTR:
+ return AMEM, nil
+
+ case TFUNC, TMAP:
+ return ANOEQ, t
+
+ case TFLOAT32:
+ return AFLOAT32, nil
+
+ case TFLOAT64:
+ return AFLOAT64, nil
+
+ case TCOMPLEX64:
+ return ACPLX64, nil
+
+ case TCOMPLEX128:
+ return ACPLX128, nil
+
+ case TSTRING:
+ return ASTRING, nil
+
+ case TINTER:
+ if t.IsEmptyInterface() {
+ return ANILINTER, nil
+ }
+ return AINTER, nil
+
+ case TSLICE:
+ return ANOEQ, t
+
+ case TARRAY:
+ a, bad := AlgType(t.Elem())
+ switch a {
+ case AMEM:
+ return AMEM, nil
+ case ANOEQ:
+ return ANOEQ, bad
+ }
+
+ switch t.NumElem() {
+ case 0:
+ // We checked above that the element type is comparable.
+ return AMEM, nil
+ case 1:
+ // Single-element array is same as its lone element.
+ return a, nil
+ }
+
+ return ASPECIAL, nil
+
+ case TSTRUCT:
+ fields := t.FieldSlice()
+
+ // One-field struct is same as that one field alone.
+ if len(fields) == 1 && !fields[0].Sym.IsBlank() {
+ return AlgType(fields[0].Type)
+ }
+
+ ret := AMEM
+ for i, f := range fields {
+ // All fields must be comparable.
+ a, bad := AlgType(f.Type)
+ if a == ANOEQ {
+ return ANOEQ, bad
+ }
+
+ // Blank fields, padded fields, fields with non-memory
+ // equality need special compare.
+ if a != AMEM || f.Sym.IsBlank() || IsPaddedField(t, i) {
+ ret = ASPECIAL
+ }
+ }
+
+ return ret, nil
+ }
+
+ base.Fatalf("algtype1: unexpected type %v", t)
+ return 0, nil
+}
+
+// TypeHasNoAlg reports whether t does not have any associated hash/eq
+// algorithms because t, or some component of t, is marked Noalg.
+func TypeHasNoAlg(t *Type) bool {
+ a, bad := AlgType(t)
+ return a == ANOEQ && bad.Noalg()
+}
+
+// IsComparable reports whether t is a comparable type.
+func IsComparable(t *Type) bool {
+ a, _ := AlgType(t)
+ return a != ANOEQ
+}
+
+// IncomparableField returns an incomparable Field of struct Type t, if any.
+func IncomparableField(t *Type) *Field {
+ for _, f := range t.FieldSlice() {
+ if !IsComparable(f.Type) {
+ return f
+ }
+ }
+ return nil
+}
+
+// IsPaddedField reports whether the i'th field of struct type t is followed
+// by padding.
+func IsPaddedField(t *Type, i int) bool {
+ if !t.IsStruct() {
+ base.Fatalf("ispaddedfield called non-struct %v", t)
+ }
+ end := t.Width
+ if i+1 < t.NumFields() {
+ end = t.Field(i + 1).Offset
+ }
+ return t.Field(i).End() != end
+}