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

     1  // Copyright 2026 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 (
     8  	"cmd/compile/internal/base"
     9  	"internal/abi"
    10  	"strings"
    11  	"sync"
    12  )
    13  
    14  // tflagComputed is set in the high bit of Type.tflag once the low
    15  // bits hold a valid abi.TFlag. abi.TFlag itself uses only the low 6.
    16  const tflagComputed uint8 = 1 << 7
    17  
    18  var tflagMu sync.Mutex
    19  
    20  // TFlag returns the abi.TFlag value for t's runtime type. Callers
    21  // must have run typecheck.CalcMethods on ReceiverBaseType(t).
    22  func (t *Type) TFlag() abi.TFlag {
    23  	tflagMu.Lock()
    24  	defer tflagMu.Unlock()
    25  	if t.tflag&tflagComputed != 0 {
    26  		return abi.TFlag(t.tflag &^ tflagComputed)
    27  	}
    28  	tflag := computeTFlag(t)
    29  	t.tflag = uint8(tflag) | tflagComputed
    30  	return tflag
    31  }
    32  
    33  func computeTFlag(t *Type) abi.TFlag {
    34  	var tflag abi.TFlag
    35  	if hasUncommon(t) {
    36  		tflag |= abi.TFlagUncommon
    37  	}
    38  	if t.Sym() != nil && t.Sym().Name != "" {
    39  		tflag |= abi.TFlagNamed
    40  	}
    41  	if t.alg == AMEM {
    42  		tflag |= abi.TFlagRegularMemory
    43  	}
    44  	if PtrDataSize(t)/int64(PtrSize) > abi.MaxPtrmaskBytes*8 {
    45  		tflag |= abi.TFlagGCMaskOnDemand
    46  	}
    47  	if !strings.HasPrefix(t.NameString(), "*") {
    48  		tflag |= abi.TFlagExtraStar
    49  	}
    50  	if IsDirectIface(t) {
    51  		tflag |= abi.TFlagDirectIface
    52  	}
    53  	return tflag
    54  }
    55  
    56  // hasUncommon reports whether t needs an abi.UncommonType.
    57  // See TFlag for the precondition.
    58  func hasUncommon(t *Type) bool {
    59  	if t.Sym() != nil {
    60  		return true
    61  	}
    62  	if t.HasShape() {
    63  		return false
    64  	}
    65  	mt := ReceiverBaseType(t)
    66  	if mt == nil {
    67  		return false
    68  	}
    69  	if !mt.MethodsComputed() {
    70  		base.Fatalf("hasUncommon: methods not computed on %v", mt)
    71  	}
    72  	for _, f := range mt.AllMethods() {
    73  		if f.Nointerface() {
    74  			continue
    75  		}
    76  		if !IsMethodApplicable(t, f) {
    77  			continue
    78  		}
    79  		return true
    80  	}
    81  	return false
    82  }
    83  

View as plain text