1
2
3
4
5
6
7 package noder
8
9 import (
10 "io"
11
12 "cmd/compile/internal/base"
13 "cmd/compile/internal/ir"
14 "cmd/compile/internal/reflectdata"
15 "cmd/compile/internal/types"
16 "cmd/internal/goobj"
17 "cmd/internal/obj"
18 )
19
20
21
22
23
24
25
26
27
28
29
30
31
32 type linker struct {
33 pw pkgEncoder
34
35 pkgs map[string]int
36 decls map[*types.Sym]int
37 }
38
39 func (l *linker) relocAll(pr *pkgReader, relocs []relocEnt) []relocEnt {
40 res := make([]relocEnt, len(relocs))
41 for i, rent := range relocs {
42 rent.idx = l.relocIdx(pr, rent.kind, rent.idx)
43 res[i] = rent
44 }
45 return res
46 }
47
48 func (l *linker) relocIdx(pr *pkgReader, k reloc, idx int) int {
49 assert(pr != nil)
50
51 absIdx := pr.absIdx(k, idx)
52
53 if newidx := pr.newindex[absIdx]; newidx != 0 {
54 return ^newidx
55 }
56
57 var newidx int
58 switch k {
59 case relocString:
60 newidx = l.relocString(pr, idx)
61 case relocPkg:
62 newidx = l.relocPkg(pr, idx)
63 case relocObj:
64 newidx = l.relocObj(pr, idx)
65
66 default:
67
68
69
70
71
72
73 w := l.pw.newEncoderRaw(k)
74 l.relocCommon(pr, &w, k, idx)
75 newidx = w.idx
76 }
77
78 pr.newindex[absIdx] = ^newidx
79
80 return newidx
81 }
82
83 func (l *linker) relocString(pr *pkgReader, idx int) int {
84 return l.pw.stringIdx(pr.stringIdx(idx))
85 }
86
87 func (l *linker) relocPkg(pr *pkgReader, idx int) int {
88 path := pr.peekPkgPath(idx)
89
90 if newidx, ok := l.pkgs[path]; ok {
91 return newidx
92 }
93
94 r := pr.newDecoder(relocPkg, idx, syncPkgDef)
95 w := l.pw.newEncoder(relocPkg, syncPkgDef)
96 l.pkgs[path] = w.idx
97
98
99
100
101
102 w.relocs = l.relocAll(pr, r.relocs)
103
104 _ = r.string()
105 w.string(path)
106
107 io.Copy(&w.data, &r.data)
108
109 return w.flush()
110 }
111
112 func (l *linker) relocObj(pr *pkgReader, idx int) int {
113 path, name, tag := pr.peekObj(idx)
114 sym := types.NewPkg(path, "").Lookup(name)
115
116 if newidx, ok := l.decls[sym]; ok {
117 return newidx
118 }
119
120 if tag == objStub && path != "builtin" && path != "unsafe" {
121 pri, ok := objReader[sym]
122 if !ok {
123 base.Fatalf("missing reader for %q.%v", path, name)
124 }
125 assert(ok)
126
127 pr = pri.pr
128 idx = pri.idx
129
130 path2, name2, tag2 := pr.peekObj(idx)
131 sym2 := types.NewPkg(path2, "").Lookup(name2)
132 assert(sym == sym2)
133 assert(tag2 != objStub)
134 }
135
136 w := l.pw.newEncoderRaw(relocObj)
137 wext := l.pw.newEncoderRaw(relocObjExt)
138 wname := l.pw.newEncoderRaw(relocName)
139 wdict := l.pw.newEncoderRaw(relocObjDict)
140
141 l.decls[sym] = w.idx
142 assert(wext.idx == w.idx)
143 assert(wname.idx == w.idx)
144 assert(wdict.idx == w.idx)
145
146 l.relocCommon(pr, &w, relocObj, idx)
147 l.relocCommon(pr, &wname, relocName, idx)
148 l.relocCommon(pr, &wdict, relocObjDict, idx)
149
150 var obj *ir.Name
151 if path == "" {
152 var ok bool
153 obj, ok = sym.Def.(*ir.Name)
154
155
156
157
158
159 if !ok && false {
160 base.Fatalf("missing definition for %v", sym)
161 }
162 }
163
164 if obj != nil {
165 wext.sync(syncObject1)
166 switch tag {
167 case objFunc:
168 l.relocFuncExt(&wext, obj)
169 case objType:
170 l.relocTypeExt(&wext, obj)
171 case objVar:
172 l.relocVarExt(&wext, obj)
173 }
174 wext.flush()
175 } else {
176 l.relocCommon(pr, &wext, relocObjExt, idx)
177 }
178
179 return w.idx
180 }
181
182 func (l *linker) relocCommon(pr *pkgReader, w *encoder, k reloc, idx int) {
183 r := pr.newDecoderRaw(k, idx)
184 w.relocs = l.relocAll(pr, r.relocs)
185 io.Copy(&w.data, &r.data)
186 w.flush()
187 }
188
189 func (l *linker) pragmaFlag(w *encoder, pragma ir.PragmaFlag) {
190 w.sync(syncPragma)
191 w.int(int(pragma))
192 }
193
194 func (l *linker) relocFuncExt(w *encoder, name *ir.Name) {
195 w.sync(syncFuncExt)
196
197 l.pragmaFlag(w, name.Func.Pragma)
198 l.linkname(w, name)
199
200
201 w.bool(true)
202
203
204
205
206 w.uint64(uint64(name.Func.ABI))
207
208
209 for _, fs := range &types.RecvsParams {
210 for _, f := range fs(name.Type()).FieldSlice() {
211 w.string(f.Note)
212 }
213 }
214
215 if inl := name.Func.Inl; w.bool(inl != nil) {
216 w.len(int(inl.Cost))
217 w.bool(inl.CanDelayResults)
218
219 pri, ok := bodyReader[name.Func]
220 assert(ok)
221 w.reloc(relocBody, l.relocIdx(pri.pr, relocBody, pri.idx))
222 }
223
224 w.sync(syncEOF)
225 }
226
227 func (l *linker) relocTypeExt(w *encoder, name *ir.Name) {
228 w.sync(syncTypeExt)
229
230 typ := name.Type()
231
232 l.pragmaFlag(w, name.Pragma())
233
234
235 l.lsymIdx(w, "", reflectdata.TypeLinksym(typ))
236 l.lsymIdx(w, "", reflectdata.TypeLinksym(typ.PtrTo()))
237
238 if typ.Kind() != types.TINTER {
239 for _, method := range typ.Methods().Slice() {
240 l.relocFuncExt(w, method.Nname.(*ir.Name))
241 }
242 }
243 }
244
245 func (l *linker) relocVarExt(w *encoder, name *ir.Name) {
246 w.sync(syncVarExt)
247 l.linkname(w, name)
248 }
249
250 func (l *linker) linkname(w *encoder, name *ir.Name) {
251 w.sync(syncLinkname)
252
253 linkname := name.Sym().Linkname
254 if !l.lsymIdx(w, linkname, name.Linksym()) {
255 w.string(linkname)
256 }
257 }
258
259 func (l *linker) lsymIdx(w *encoder, linkname string, lsym *obj.LSym) bool {
260 if lsym.PkgIdx > goobj.PkgIdxSelf || (lsym.PkgIdx == goobj.PkgIdxInvalid && !lsym.Indexed()) || linkname != "" {
261 w.int64(-1)
262 return false
263 }
264
265
266
267 w.int64(int64(lsym.SymIdx))
268 return true
269 }
270
271
272
273
274
275
276 func (pr *pkgDecoder) peekPkgPath(idx int) string {
277 r := pr.newDecoder(relocPkg, idx, syncPkgDef)
278 path := r.string()
279 if path == "" {
280 path = pr.pkgPath
281 }
282 return path
283 }
284
285 func (pr *pkgDecoder) peekObj(idx int) (string, string, codeObj) {
286 r := pr.newDecoder(relocName, idx, syncObject1)
287 r.sync(syncSym)
288 r.sync(syncPkg)
289 path := pr.peekPkgPath(r.reloc(relocPkg))
290 name := r.string()
291 assert(name != "")
292
293 tag := codeObj(r.code(syncCodeObj))
294
295 return path, name, tag
296 }
297
View as plain text