// 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 int8 //go:generate stringer -type AlgKind -trimprefix A alg.go const ( AUNK AlgKind = iota ANOEQ // Types cannot be compared ANOALG // implies ANOEQ, and in addition has a part that is marked Noalg AMEM // Type can be compared/hashed as regular memory. AMEM0 // Specific subvariants of AMEM (TODO: move to ../reflectdata?) AMEM8 AMEM16 AMEM32 AMEM64 AMEM128 ASTRING AINTER ANILINTER AFLOAT32 AFLOAT64 ACPLX64 ACPLX128 ASPECIAL // Type needs special comparison/hashing functions. ) // Most kinds are priority 0. Higher numbers are higher priority, in that // the higher priority kinds override lower priority kinds. var algPriority = [ASPECIAL + 1]int8{ASPECIAL: 1, ANOEQ: 2, ANOALG: 3, AMEM: -1} // setAlg sets the algorithm type of t to a, if it is of higher // priority to the current algorithm type. func (t *Type) setAlg(a AlgKind) { if t.alg == AUNK { base.Fatalf("setAlg(%v,%s) starting with unknown priority", t, a) } if algPriority[a] > algPriority[t.alg] { t.alg = a } else if a != t.alg && algPriority[a] == algPriority[t.alg] { base.Fatalf("ambiguous priority %s and %s", a, t.alg) } } // AlgType returns the AlgKind used for comparing and hashing Type t. func AlgType(t *Type) AlgKind { CalcSize(t) return t.alg } // 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 { return AlgType(t) == ANOALG } // IsComparable reports whether t is a comparable type. func IsComparable(t *Type) bool { a := AlgType(t) return a != ANOEQ && a != ANOALG } // IncomparableField returns an incomparable Field of struct Type t, if any. func IncomparableField(t *Type) *Field { for _, f := range t.Fields() { 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 }