Source file src/cmd/compile/internal/types/alg.go

     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  
     5  package types
     6  
     7  import "cmd/compile/internal/base"
     8  
     9  // AlgKind describes the kind of algorithms used for comparing and
    10  // hashing a Type.
    11  type AlgKind int8
    12  
    13  //go:generate stringer -type AlgKind -trimprefix A alg.go
    14  
    15  const (
    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.
    38  var 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.
    42  func (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.
    54  func 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.
    61  func TypeHasNoAlg(t *Type) bool {
    62  	return AlgType(t) == ANOALG
    63  }
    64  
    65  // IsComparable reports whether t is a comparable type.
    66  func 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.
    72  func 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.
    83  func 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  

View as plain text