github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/compile/internal/types/sym.go (about) 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 "github.com/gagliardetto/golang-go/cmd/internal/obj" 9 "github.com/gagliardetto/golang-go/cmd/internal/src" 10 "unicode" 11 "unicode/utf8" 12 ) 13 14 // Sym represents an object name in a segmented (pkg, name) namespace. 15 // Most commonly, this is a Go identifier naming an object declared within a package, 16 // but Syms are also used to name internal 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 // 23 // Ideally, Sym should be used for representing Go language constructs, 24 // while cmd/internal/obj.LSym is used for representing emitted artifacts. 25 // 26 // NOTE: In practice, things can be messier than the description above 27 // for various reasons (historical, convenience). 28 type Sym struct { 29 Importdef *Pkg // where imported definition was found 30 Linkname string // link name 31 32 Pkg *Pkg 33 Name string // object name 34 35 // saved and restored by dcopy 36 Def *Node // definition: ONAME OTYPE OPACK or OLITERAL 37 Block int32 // blocknumber to catch redeclaration 38 Lastlineno src.XPos // last declaration for diagnostic 39 40 flags bitset8 41 Label *Node // corresponding label (ephemeral) 42 Origpkg *Pkg // original package for . import 43 } 44 45 const ( 46 symOnExportList = 1 << iota // added to exportlist (no need to add again) 47 symUniq 48 symSiggen // type symbol has been generated 49 symAsm // on asmlist, for writing to -asmhdr 50 symFunc // function symbol; uses internal ABI 51 ) 52 53 func (sym *Sym) OnExportList() bool { return sym.flags&symOnExportList != 0 } 54 func (sym *Sym) Uniq() bool { return sym.flags&symUniq != 0 } 55 func (sym *Sym) Siggen() bool { return sym.flags&symSiggen != 0 } 56 func (sym *Sym) Asm() bool { return sym.flags&symAsm != 0 } 57 func (sym *Sym) Func() bool { return sym.flags&symFunc != 0 } 58 59 func (sym *Sym) SetOnExportList(b bool) { sym.flags.set(symOnExportList, b) } 60 func (sym *Sym) SetUniq(b bool) { sym.flags.set(symUniq, b) } 61 func (sym *Sym) SetSiggen(b bool) { sym.flags.set(symSiggen, b) } 62 func (sym *Sym) SetAsm(b bool) { sym.flags.set(symAsm, b) } 63 func (sym *Sym) SetFunc(b bool) { sym.flags.set(symFunc, b) } 64 65 func (sym *Sym) IsBlank() bool { 66 return sym != nil && sym.Name == "_" 67 } 68 69 func (sym *Sym) LinksymName() string { 70 if sym.IsBlank() { 71 return "_" 72 } 73 if sym.Linkname != "" { 74 return sym.Linkname 75 } 76 return sym.Pkg.Prefix + "." + sym.Name 77 } 78 79 func (sym *Sym) Linksym() *obj.LSym { 80 if sym == nil { 81 return nil 82 } 83 initPkg := func(r *obj.LSym) { 84 if sym.Linkname != "" { 85 r.Pkg = "_" 86 } else { 87 r.Pkg = sym.Pkg.Prefix 88 } 89 } 90 if sym.Func() { 91 // This is a function symbol. Mark it as "internal ABI". 92 return Ctxt.LookupABIInit(sym.LinksymName(), obj.ABIInternal, initPkg) 93 } 94 return Ctxt.LookupInit(sym.LinksymName(), initPkg) 95 } 96 97 // Less reports whether symbol a is ordered before symbol b. 98 // 99 // Symbols are ordered exported before non-exported, then by name, and 100 // finally (for non-exported symbols) by package height and path. 101 // 102 // Ordering by package height is necessary to establish a consistent 103 // ordering for non-exported names with the same spelling but from 104 // different packages. We don't necessarily know the path for the 105 // package being compiled, but by definition it will have a height 106 // greater than any other packages seen within the compilation unit. 107 // For more background, see issue #24693. 108 func (a *Sym) Less(b *Sym) bool { 109 if a == b { 110 return false 111 } 112 113 // Exported symbols before non-exported. 114 ea := IsExported(a.Name) 115 eb := IsExported(b.Name) 116 if ea != eb { 117 return ea 118 } 119 120 // Order by name and then (for non-exported names) by package 121 // height and path. 122 if a.Name != b.Name { 123 return a.Name < b.Name 124 } 125 if !ea { 126 if a.Pkg.Height != b.Pkg.Height { 127 return a.Pkg.Height < b.Pkg.Height 128 } 129 return a.Pkg.Path < b.Pkg.Path 130 } 131 return false 132 } 133 134 // IsExported reports whether name is an exported Go symbol (that is, 135 // whether it begins with an upper-case letter). 136 func IsExported(name string) bool { 137 if r := name[0]; r < utf8.RuneSelf { 138 return 'A' <= r && r <= 'Z' 139 } 140 r, _ := utf8.DecodeRuneInString(name) 141 return unicode.IsUpper(r) 142 }