1// Copyright 2016 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package types 6 7import "cmd/compile/internal/base" 8 9// AlgKind describes the kind of algorithms used for comparing and 10// hashing a Type. 11type AlgKind int8 12 13//go:generate stringer -type AlgKind -trimprefix A alg.go 14 15const ( 16 AUNK AlgKind = iota 17 ANOEQ // Types cannot be compared 18 ANOALG // implies ANOEQ, and in addition has a part that is marked Noalg 19 AMEM // Type can be compared/hashed as regular memory. 20 AMEM0 // Specific subvariants of AMEM (TODO: move to ../reflectdata?) 21 AMEM8 22 AMEM16 23 AMEM32 24 AMEM64 25 AMEM128 26 ASTRING 27 AINTER 28 ANILINTER 29 AFLOAT32 30 AFLOAT64 31 ACPLX64 32 ACPLX128 33 ASPECIAL // Type needs special comparison/hashing functions. 34) 35 36// Most kinds are priority 0. Higher numbers are higher priority, in that 37// the higher priority kinds override lower priority kinds. 38var algPriority = [ASPECIAL + 1]int8{ASPECIAL: 1, ANOEQ: 2, ANOALG: 3, AMEM: -1} 39 40// setAlg sets the algorithm type of t to a, if it is of higher 41// priority to the current algorithm type. 42func (t *Type) setAlg(a AlgKind) { 43 if t.alg == AUNK { 44 base.Fatalf("setAlg(%v,%s) starting with unknown priority", t, a) 45 } 46 if algPriority[a] > algPriority[t.alg] { 47 t.alg = a 48 } else if a != t.alg && algPriority[a] == algPriority[t.alg] { 49 base.Fatalf("ambiguous priority %s and %s", a, t.alg) 50 } 51} 52 53// AlgType returns the AlgKind used for comparing and hashing Type t. 54func AlgType(t *Type) AlgKind { 55 CalcSize(t) 56 return t.alg 57} 58 59// TypeHasNoAlg reports whether t does not have any associated hash/eq 60// algorithms because t, or some component of t, is marked Noalg. 61func TypeHasNoAlg(t *Type) bool { 62 return AlgType(t) == ANOALG 63} 64 65// IsComparable reports whether t is a comparable type. 66func IsComparable(t *Type) bool { 67 a := AlgType(t) 68 return a != ANOEQ && a != ANOALG 69} 70 71// IncomparableField returns an incomparable Field of struct Type t, if any. 72func IncomparableField(t *Type) *Field { 73 for _, f := range t.Fields() { 74 if !IsComparable(f.Type) { 75 return f 76 } 77 } 78 return nil 79} 80 81// IsPaddedField reports whether the i'th field of struct type t is followed 82// by padding. 83func IsPaddedField(t *Type, i int) bool { 84 if !t.IsStruct() { 85 base.Fatalf("IsPaddedField called non-struct %v", t) 86 } 87 end := t.width 88 if i+1 < t.NumFields() { 89 end = t.Field(i + 1).Offset 90 } 91 return t.Field(i).End() != end 92} 93