1
2
3
4
5 package noder
6
7 import (
8 "internal/buildcfg"
9 "internal/pkgbits"
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
33
34
35
36
37
38
39 type linker struct {
40 pw pkgbits.PkgEncoder
41
42 pkgs map[string]index
43 decls map[*types.Sym]index
44 bodies map[*types.Sym]index
45 }
46
47
48
49
50 func (l *linker) relocAll(pr *pkgReader, relocs []pkgbits.RelocEnt) []pkgbits.RelocEnt {
51 res := make([]pkgbits.RelocEnt, len(relocs))
52 for i, rent := range relocs {
53 rent.Idx = l.relocIdx(pr, rent.Kind, rent.Idx)
54 res[i] = rent
55 }
56 return res
57 }
58
59
60
61 func (l *linker) relocIdx(pr *pkgReader, k pkgbits.RelocKind, idx index) index {
62 assert(pr != nil)
63
64 absIdx := pr.AbsIdx(k, idx)
65
66 if newidx := pr.newindex[absIdx]; newidx != 0 {
67 return ^newidx
68 }
69
70 var newidx index
71 switch k {
72 case pkgbits.RelocString:
73 newidx = l.relocString(pr, idx)
74 case pkgbits.RelocPkg:
75 newidx = l.relocPkg(pr, idx)
76 case pkgbits.RelocObj:
77 newidx = l.relocObj(pr, idx)
78
79 default:
80
81
82
83
84
85
86 w := l.pw.NewEncoderRaw(k)
87 l.relocCommon(pr, &w, k, idx)
88 newidx = w.Idx
89 }
90
91 pr.newindex[absIdx] = ^newidx
92
93 return newidx
94 }
95
96
97
98 func (l *linker) relocString(pr *pkgReader, idx index) index {
99 return l.pw.StringIdx(pr.StringIdx(idx))
100 }
101
102
103
104
105
106
107
108
109 func (l *linker) relocPkg(pr *pkgReader, idx index) index {
110 path := pr.PeekPkgPath(idx)
111
112 if newidx, ok := l.pkgs[path]; ok {
113 return newidx
114 }
115
116 r := pr.NewDecoder(pkgbits.RelocPkg, idx, pkgbits.SyncPkgDef)
117 w := l.pw.NewEncoder(pkgbits.RelocPkg, pkgbits.SyncPkgDef)
118 l.pkgs[path] = w.Idx
119
120
121
122
123
124 w.Relocs = l.relocAll(pr, r.Relocs)
125
126 _ = r.String()
127 w.String(path)
128
129 io.Copy(&w.Data, &r.Data)
130
131 return w.Flush()
132 }
133
134
135
136
137 func (l *linker) relocObj(pr *pkgReader, idx index) index {
138 path, name, tag := pr.PeekObj(idx)
139 sym := types.NewPkg(path, "").Lookup(name)
140
141 if newidx, ok := l.decls[sym]; ok {
142 return newidx
143 }
144
145 if tag == pkgbits.ObjStub && path != "builtin" && path != "unsafe" {
146 pri, ok := objReader[sym]
147 if !ok {
148 base.Fatalf("missing reader for %q.%v", path, name)
149 }
150 assert(ok)
151
152 pr = pri.pr
153 idx = pri.idx
154
155 path2, name2, tag2 := pr.PeekObj(idx)
156 sym2 := types.NewPkg(path2, "").Lookup(name2)
157 assert(sym == sym2)
158 assert(tag2 != pkgbits.ObjStub)
159 }
160
161 w := l.pw.NewEncoderRaw(pkgbits.RelocObj)
162 wext := l.pw.NewEncoderRaw(pkgbits.RelocObjExt)
163 wname := l.pw.NewEncoderRaw(pkgbits.RelocName)
164 wdict := l.pw.NewEncoderRaw(pkgbits.RelocObjDict)
165
166 l.decls[sym] = w.Idx
167 assert(wext.Idx == w.Idx)
168 assert(wname.Idx == w.Idx)
169 assert(wdict.Idx == w.Idx)
170
171 l.relocCommon(pr, &w, pkgbits.RelocObj, idx)
172 l.relocCommon(pr, &wname, pkgbits.RelocName, idx)
173 l.relocCommon(pr, &wdict, pkgbits.RelocObjDict, idx)
174
175
176
177 obj, _ := sym.Def.(*ir.Name)
178 local := sym.Pkg == types.LocalPkg
179
180 if local && obj != nil {
181 wext.Sync(pkgbits.SyncObject1)
182 switch tag {
183 case pkgbits.ObjFunc:
184 l.relocFuncExt(&wext, obj)
185 case pkgbits.ObjType:
186 l.relocTypeExt(&wext, obj)
187 case pkgbits.ObjVar:
188 l.relocVarExt(&wext, obj)
189 }
190 wext.Flush()
191 } else {
192 l.relocCommon(pr, &wext, pkgbits.RelocObjExt, idx)
193 }
194
195
196
197 if obj != nil {
198 if obj.Op() == ir.ONAME && obj.Class == ir.PFUNC {
199 l.exportBody(obj, local)
200 }
201
202 if obj.Op() == ir.OTYPE && !obj.Alias() {
203 if typ := obj.Type(); !typ.IsInterface() {
204 for _, method := range typ.Methods() {
205 l.exportBody(method.Nname.(*ir.Name), local)
206 }
207 }
208 }
209 }
210
211 return w.Idx
212 }
213
214
215
216
217
218
219 func (l *linker) exportBody(obj *ir.Name, local bool) {
220 assert(obj.Op() == ir.ONAME && obj.Class == ir.PFUNC)
221
222 fn := obj.Func
223 if fn.Inl == nil {
224 return
225 }
226
227
228
229
230
231
232
233
234
235
236 exportBody := local || fn.Inl.HaveDcl
237 if !exportBody {
238 return
239 }
240
241 sym := obj.Sym()
242 if _, ok := l.bodies[sym]; ok {
243
244 base.AssertfAt(obj.Type().Recv() != nil, obj.Pos(), "expected method: %v", obj)
245 return
246 }
247
248 pri, ok := bodyReaderFor(fn)
249 assert(ok)
250 l.bodies[sym] = l.relocIdx(pri.pr, pkgbits.RelocBody, pri.idx)
251 }
252
253
254
255 func (l *linker) relocCommon(pr *pkgReader, w *pkgbits.Encoder, k pkgbits.RelocKind, idx index) {
256 r := pr.NewDecoderRaw(k, idx)
257 w.Relocs = l.relocAll(pr, r.Relocs)
258 io.Copy(&w.Data, &r.Data)
259 w.Flush()
260 }
261
262 func (l *linker) pragmaFlag(w *pkgbits.Encoder, pragma ir.PragmaFlag) {
263 w.Sync(pkgbits.SyncPragma)
264 w.Int(int(pragma))
265 }
266
267 func (l *linker) relocFuncExt(w *pkgbits.Encoder, name *ir.Name) {
268 w.Sync(pkgbits.SyncFuncExt)
269
270 l.pragmaFlag(w, name.Func.Pragma)
271 l.linkname(w, name)
272
273 if buildcfg.GOARCH == "wasm" {
274 if name.Func.WasmImport != nil {
275 w.String(name.Func.WasmImport.Module)
276 w.String(name.Func.WasmImport.Name)
277 } else {
278 w.String("")
279 w.String("")
280 }
281 if name.Func.WasmExport != nil {
282 w.String(name.Func.WasmExport.Name)
283 } else {
284 w.String("")
285 }
286 }
287
288
289 w.Bool(true)
290
291
292
293
294 w.Uint64(uint64(name.Func.ABI))
295
296
297 for _, f := range name.Type().RecvParams() {
298 w.String(f.Note)
299 }
300
301 if inl := name.Func.Inl; w.Bool(inl != nil) {
302 w.Len(int(inl.Cost))
303 w.Bool(inl.CanDelayResults)
304 if buildcfg.Experiment.NewInliner {
305 w.String(inl.Properties)
306 }
307 }
308
309 w.Sync(pkgbits.SyncEOF)
310 }
311
312 func (l *linker) relocTypeExt(w *pkgbits.Encoder, name *ir.Name) {
313 w.Sync(pkgbits.SyncTypeExt)
314
315 typ := name.Type()
316
317 l.pragmaFlag(w, name.Pragma())
318
319
320 l.lsymIdx(w, "", reflectdata.TypeLinksym(typ))
321 l.lsymIdx(w, "", reflectdata.TypeLinksym(typ.PtrTo()))
322
323 if typ.Kind() != types.TINTER {
324 for _, method := range typ.Methods() {
325 l.relocFuncExt(w, method.Nname.(*ir.Name))
326 }
327 }
328 }
329
330 func (l *linker) relocVarExt(w *pkgbits.Encoder, name *ir.Name) {
331 w.Sync(pkgbits.SyncVarExt)
332 l.linkname(w, name)
333 }
334
335 func (l *linker) linkname(w *pkgbits.Encoder, name *ir.Name) {
336 w.Sync(pkgbits.SyncLinkname)
337
338 linkname := name.Sym().Linkname
339 if !l.lsymIdx(w, linkname, name.Linksym()) {
340 w.String(linkname)
341 }
342 }
343
344 func (l *linker) lsymIdx(w *pkgbits.Encoder, linkname string, lsym *obj.LSym) bool {
345 if lsym.PkgIdx > goobj.PkgIdxSelf || (lsym.PkgIdx == goobj.PkgIdxInvalid && !lsym.Indexed()) || linkname != "" {
346 w.Int64(-1)
347 return false
348 }
349
350
351
352 w.Int64(int64(lsym.SymIdx))
353 return true
354 }
355
View as plain text