]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/compile/internal/types/pkg.go
cmd/compile: remove vestigial importpath symbol logic
[gostls13.git] / src / cmd / compile / internal / types / pkg.go
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/objabi"
10         "fmt"
11         "strconv"
12         "sync"
13 )
14
15 // pkgMap maps a package path to a package.
16 var pkgMap = make(map[string]*Pkg)
17
18 type Pkg struct {
19         Path    string // string literal used in import statement, e.g. "runtime/internal/sys"
20         Name    string // package name, e.g. "sys"
21         Prefix  string // escaped path for use in symbol table
22         Syms    map[string]*Sym
23         Pathsym *obj.LSym
24
25         Direct bool // imported directly
26 }
27
28 // NewPkg returns a new Pkg for the given package path and name.
29 // Unless name is the empty string, if the package exists already,
30 // the existing package name and the provided name must match.
31 func NewPkg(path, name string) *Pkg {
32         if p := pkgMap[path]; p != nil {
33                 if name != "" && p.Name != name {
34                         panic(fmt.Sprintf("conflicting package names %s and %s for path %q", p.Name, name, path))
35                 }
36                 return p
37         }
38
39         p := new(Pkg)
40         p.Path = path
41         p.Name = name
42         if path == "go.shape" {
43                 // Don't escape "go.shape", since it's not needed (it's a builtin
44                 // package), and we don't want escape codes showing up in shape type
45                 // names, which also appear in names of function/method
46                 // instantiations.
47                 p.Prefix = path
48         } else {
49                 p.Prefix = objabi.PathToPrefix(path)
50         }
51         p.Syms = make(map[string]*Sym)
52         pkgMap[path] = p
53
54         return p
55 }
56
57 var nopkg = &Pkg{
58         Syms: make(map[string]*Sym),
59 }
60
61 func (pkg *Pkg) Lookup(name string) *Sym {
62         s, _ := pkg.LookupOK(name)
63         return s
64 }
65
66 // LookupOK looks up name in pkg and reports whether it previously existed.
67 func (pkg *Pkg) LookupOK(name string) (s *Sym, existed bool) {
68         // TODO(gri) remove this check in favor of specialized lookup
69         if pkg == nil {
70                 pkg = nopkg
71         }
72         if s := pkg.Syms[name]; s != nil {
73                 return s, true
74         }
75
76         s = &Sym{
77                 Name: name,
78                 Pkg:  pkg,
79         }
80         pkg.Syms[name] = s
81         return s, false
82 }
83
84 func (pkg *Pkg) LookupBytes(name []byte) *Sym {
85         // TODO(gri) remove this check in favor of specialized lookup
86         if pkg == nil {
87                 pkg = nopkg
88         }
89         if s := pkg.Syms[string(name)]; s != nil {
90                 return s
91         }
92         str := InternString(name)
93         return pkg.Lookup(str)
94 }
95
96 // LookupNum looks up the symbol starting with prefix and ending with
97 // the decimal n. If prefix is too long, LookupNum panics.
98 func (pkg *Pkg) LookupNum(prefix string, n int) *Sym {
99         var buf [20]byte // plenty long enough for all current users
100         copy(buf[:], prefix)
101         b := strconv.AppendInt(buf[:len(prefix)], int64(n), 10)
102         return pkg.LookupBytes(b)
103 }
104
105 var (
106         internedStringsmu sync.Mutex // protects internedStrings
107         internedStrings   = map[string]string{}
108 )
109
110 func InternString(b []byte) string {
111         internedStringsmu.Lock()
112         s, ok := internedStrings[string(b)] // string(b) here doesn't allocate
113         if !ok {
114                 s = string(b)
115                 internedStrings[s] = s
116         }
117         internedStringsmu.Unlock()
118         return s
119 }
120
121 // CleanroomDo invokes f in an environment with no preexisting packages.
122 // For testing of import/export only.
123 func CleanroomDo(f func()) {
124         saved := pkgMap
125         pkgMap = make(map[string]*Pkg)
126         f()
127         pkgMap = saved
128 }