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

Documentation: cmd/compile/internal/types

     1  // Copyright 2017 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/internal/obj"
     9  	"cmd/internal/src"
    10  	"unicode"
    11  	"unicode/utf8"
    12  )
    13  
    14  // Sym represents an object name. Most commonly, this is a Go identifier naming
    15  // an object declared within a package, but Syms are also used to name internal
    16  // synthesized objects.
    17  //
    18  // As an exception, field and method names that are exported use the Sym
    19  // associated with localpkg instead of the package that declared them. This
    20  // allows using Sym pointer equality to test for Go identifier uniqueness when
    21  // handling selector expressions.
    22  type Sym struct {
    23  	Importdef *Pkg   // where imported definition was found
    24  	Linkname  string // link name
    25  
    26  	Pkg  *Pkg
    27  	Name string // object name
    28  
    29  	// saved and restored by dcopy
    30  	Def        *Node    // definition: ONAME OTYPE OPACK or OLITERAL
    31  	Block      int32    // blocknumber to catch redeclaration
    32  	Lastlineno src.XPos // last declaration for diagnostic
    33  
    34  	flags   bitset8
    35  	Label   *Node // corresponding label (ephemeral)
    36  	Origpkg *Pkg  // original package for . import
    37  }
    38  
    39  const (
    40  	symOnExportList = 1 << iota // added to exportlist (no need to add again)
    41  	symUniq
    42  	symSiggen // type symbol has been generated
    43  	symAsm    // on asmlist, for writing to -asmhdr
    44  	symAlgGen // algorithm table has been generated
    45  	symFunc   // function symbol; uses internal ABI
    46  )
    47  
    48  func (sym *Sym) OnExportList() bool { return sym.flags&symOnExportList != 0 }
    49  func (sym *Sym) Uniq() bool         { return sym.flags&symUniq != 0 }
    50  func (sym *Sym) Siggen() bool       { return sym.flags&symSiggen != 0 }
    51  func (sym *Sym) Asm() bool          { return sym.flags&symAsm != 0 }
    52  func (sym *Sym) AlgGen() bool       { return sym.flags&symAlgGen != 0 }
    53  func (sym *Sym) Func() bool         { return sym.flags&symFunc != 0 }
    54  
    55  func (sym *Sym) SetOnExportList(b bool) { sym.flags.set(symOnExportList, b) }
    56  func (sym *Sym) SetUniq(b bool)         { sym.flags.set(symUniq, b) }
    57  func (sym *Sym) SetSiggen(b bool)       { sym.flags.set(symSiggen, b) }
    58  func (sym *Sym) SetAsm(b bool)          { sym.flags.set(symAsm, b) }
    59  func (sym *Sym) SetAlgGen(b bool)       { sym.flags.set(symAlgGen, b) }
    60  func (sym *Sym) SetFunc(b bool)         { sym.flags.set(symFunc, b) }
    61  
    62  func (sym *Sym) IsBlank() bool {
    63  	return sym != nil && sym.Name == "_"
    64  }
    65  
    66  func (sym *Sym) LinksymName() string {
    67  	if sym.IsBlank() {
    68  		return "_"
    69  	}
    70  	if sym.Linkname != "" {
    71  		return sym.Linkname
    72  	}
    73  	return sym.Pkg.Prefix + "." + sym.Name
    74  }
    75  
    76  func (sym *Sym) Linksym() *obj.LSym {
    77  	if sym == nil {
    78  		return nil
    79  	}
    80  	if sym.Func() {
    81  		// This is a function symbol. Mark it as "internal ABI".
    82  		return Ctxt.LookupABI(sym.LinksymName(), obj.ABIInternal)
    83  	}
    84  	return Ctxt.Lookup(sym.LinksymName())
    85  }
    86  
    87  // Less reports whether symbol a is ordered before symbol b.
    88  //
    89  // Symbols are ordered exported before non-exported, then by name, and
    90  // finally (for non-exported symbols) by package height and path.
    91  //
    92  // Ordering by package height is necessary to establish a consistent
    93  // ordering for non-exported names with the same spelling but from
    94  // different packages. We don't necessarily know the path for the
    95  // package being compiled, but by definition it will have a height
    96  // greater than any other packages seen within the compilation unit.
    97  // For more background, see issue #24693.
    98  func (a *Sym) Less(b *Sym) bool {
    99  	if a == b {
   100  		return false
   101  	}
   102  
   103  	// Exported symbols before non-exported.
   104  	ea := IsExported(a.Name)
   105  	eb := IsExported(b.Name)
   106  	if ea != eb {
   107  		return ea
   108  	}
   109  
   110  	// Order by name and then (for non-exported names) by package
   111  	// height and path.
   112  	if a.Name != b.Name {
   113  		return a.Name < b.Name
   114  	}
   115  	if !ea {
   116  		if a.Pkg.Height != b.Pkg.Height {
   117  			return a.Pkg.Height < b.Pkg.Height
   118  		}
   119  		return a.Pkg.Path < b.Pkg.Path
   120  	}
   121  	return false
   122  }
   123  
   124  // IsExported reports whether name is an exported Go symbol (that is,
   125  // whether it begins with an upper-case letter).
   126  func IsExported(name string) bool {
   127  	if r := name[0]; r < utf8.RuneSelf {
   128  		return 'A' <= r && r <= 'Z'
   129  	}
   130  	r, _ := utf8.DecodeRuneInString(name)
   131  	return unicode.IsUpper(r)
   132  }
   133  

View as plain text