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]pkgbits.Index
43 decls map[*types.Sym]pkgbits.Index
44 bodies map[*types.Sym]pkgbits.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 pkgbits.Index) pkgbits.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 pkgbits.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 pkgbits.Index) pkgbits.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 pkgbits.Index) pkgbits.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 pkgbits.Index) pkgbits.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 pkgbits.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 }
282
283
284 w.Bool(true)
285
286
287
288
289 w.Uint64(uint64(name.Func.ABI))
290
291
292 for _, f := range name.Type().RecvParams() {
293 w.String(f.Note)
294 }
295
296 if inl := name.Func.Inl; w.Bool(inl != nil) {
297 w.Len(int(inl.Cost))
298 w.Bool(inl.CanDelayResults)
299 if buildcfg.Experiment.NewInliner {
300 w.String(inl.Properties)
301 }
302 }
303
304 w.Sync(pkgbits.SyncEOF)
305 }
306
307 func (l *linker) relocTypeExt(w *pkgbits.Encoder, name *ir.Name) {
308 w.Sync(pkgbits.SyncTypeExt)
309
310 typ := name.Type()
311
312 l.pragmaFlag(w, name.Pragma())
313
314
315 l.lsymIdx(w, "", reflectdata.TypeLinksym(typ))
316 l.lsymIdx(w, "", reflectdata.TypeLinksym(typ.PtrTo()))
317
318 if typ.Kind() != types.TINTER {
319 for _, method := range typ.Methods() {
320 l.relocFuncExt(w, method.Nname.(*ir.Name))
321 }
322 }
323 }
324
325 func (l *linker) relocVarExt(w *pkgbits.Encoder, name *ir.Name) {
326 w.Sync(pkgbits.SyncVarExt)
327 l.linkname(w, name)
328 }
329
330 func (l *linker) linkname(w *pkgbits.Encoder, name *ir.Name) {
331 w.Sync(pkgbits.SyncLinkname)
332
333 linkname := name.Sym().Linkname
334 if !l.lsymIdx(w, linkname, name.Linksym()) {
335 w.String(linkname)
336 }
337 }
338
339 func (l *linker) lsymIdx(w *pkgbits.Encoder, linkname string, lsym *obj.LSym) bool {
340 if lsym.PkgIdx > goobj.PkgIdxSelf || (lsym.PkgIdx == goobj.PkgIdxInvalid && !lsym.Indexed()) || linkname != "" {
341 w.Int64(-1)
342 return false
343 }
344
345
346
347 w.Int64(int64(lsym.SymIdx))
348 return true
349 }
350
View as plain text