1
2
3
4
5
6
7 package noder
8
9 import (
10 "bytes"
11 "fmt"
12 "internal/goversion"
13 "io"
14 "runtime"
15 "sort"
16
17 "cmd/compile/internal/base"
18 "cmd/compile/internal/inline"
19 "cmd/compile/internal/ir"
20 "cmd/compile/internal/typecheck"
21 "cmd/compile/internal/types"
22 "cmd/compile/internal/types2"
23 "cmd/internal/src"
24 )
25
26
27
28
29 var localPkgReader *pkgReader
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72 func unified(noders []*noder) {
73 inline.NewInline = InlineCall
74
75 if !quirksMode() {
76 writeNewExportFunc = writeNewExport
77 } else if base.Flag.G != 0 {
78 base.Errorf("cannot use -G and -d=quirksmode together")
79 }
80
81 newReadImportFunc = func(data string, pkg1 *types.Pkg, ctxt *types2.Context, packages map[string]*types2.Package) (pkg2 *types2.Package, err error) {
82 pr := newPkgDecoder(pkg1.Path, data)
83
84
85 readPackage(newPkgReader(pr), pkg1)
86 pkg2 = readPackage2(ctxt, packages, pr)
87 return
88 }
89
90 data := writePkgStub(noders)
91
92
93
94
95
96 base.Flag.Lang = fmt.Sprintf("go1.%d", goversion.Version)
97 types.ParseLangFlag()
98
99 assert(types.LocalPkg.Path == "")
100 types.LocalPkg.Height = 0
101 target := typecheck.Target
102
103 typecheck.TypecheckAllowed = true
104
105 localPkgReader = newPkgReader(newPkgDecoder(types.LocalPkg.Path, data))
106 readPackage(localPkgReader, types.LocalPkg)
107
108 r := localPkgReader.newReader(relocMeta, privateRootIdx, syncPrivate)
109 r.pkgInit(types.LocalPkg, target)
110
111
112
113
114 for i, ndecls := 0, len(target.Decls); i < ndecls; i++ {
115 switch n := target.Decls[i]; n.Op() {
116 case ir.OAS, ir.OAS2:
117 target.Decls[i] = typecheck.Stmt(n)
118 }
119 }
120
121
122 for len(todoBodies) > 0 {
123
124
125 fn := todoBodies[len(todoBodies)-1]
126 todoBodies = todoBodies[:len(todoBodies)-1]
127
128 pri, ok := bodyReader[fn]
129 assert(ok)
130 pri.funcBody(fn)
131
132
133
134 if fn.OClosure == nil && len(pri.dict.targs) != 0 {
135 target.Decls = append(target.Decls, fn)
136 }
137 }
138 todoBodies = nil
139 todoBodiesDone = true
140
141
142 for _, n := range target.Decls {
143 if n.Typecheck() == 0 {
144 base.FatalfAt(n.Pos(), "missed typecheck: %v", n)
145 }
146
147
148
149 if fn, ok := n.(*ir.Func); ok && len(fn.Body) != 0 {
150 if stmt := fn.Body[0]; stmt.Typecheck() == 0 {
151 base.FatalfAt(stmt.Pos(), "missed typecheck: %v", stmt)
152 }
153 }
154 }
155
156 base.ExitIfErrors()
157 }
158
159
160
161
162 func writePkgStub(noders []*noder) string {
163 m, pkg, info := checkFiles(noders)
164
165 pw := newPkgWriter(m, pkg, info)
166
167 pw.collectDecls(noders)
168
169 publicRootWriter := pw.newWriter(relocMeta, syncPublic)
170 privateRootWriter := pw.newWriter(relocMeta, syncPrivate)
171
172 assert(publicRootWriter.idx == publicRootIdx)
173 assert(privateRootWriter.idx == privateRootIdx)
174
175 {
176 w := publicRootWriter
177 w.pkg(pkg)
178 w.bool(false)
179
180 scope := pkg.Scope()
181 names := scope.Names()
182 w.len(len(names))
183 for _, name := range scope.Names() {
184 w.obj(scope.Lookup(name), nil)
185 }
186
187 w.sync(syncEOF)
188 w.flush()
189 }
190
191 {
192 w := privateRootWriter
193 w.pkgInit(noders)
194 w.flush()
195 }
196
197 var sb bytes.Buffer
198 pw.dump(&sb)
199
200
201
202 freePackage(pkg)
203
204 return sb.String()
205 }
206
207
208 func freePackage(pkg *types2.Package) {
209
210
211
212
213
214
215 if base.CompilerBootstrap {
216 return
217 }
218
219
220 done := make(chan struct{})
221 runtime.SetFinalizer(pkg, func(*types2.Package) { close(done) })
222
223
224
225 *pkg = types2.Package{}
226
227
228
229 for i := 0; i < 10; i++ {
230 select {
231 case <-done:
232 return
233 default:
234 runtime.GC()
235 }
236 }
237
238 base.Fatalf("package never finalized")
239 }
240
241 func readPackage(pr *pkgReader, importpkg *types.Pkg) {
242 r := pr.newReader(relocMeta, publicRootIdx, syncPublic)
243
244 pkg := r.pkg()
245 assert(pkg == importpkg)
246
247 if r.bool() {
248 sym := pkg.Lookup(".inittask")
249 task := ir.NewNameAt(src.NoXPos, sym)
250 task.Class = ir.PEXTERN
251 sym.Def = task
252 }
253
254 for i, n := 0, r.len(); i < n; i++ {
255 r.sync(syncObject)
256 assert(!r.bool())
257 idx := r.reloc(relocObj)
258 assert(r.len() == 0)
259
260 path, name, code := r.p.peekObj(idx)
261 if code != objStub {
262 objReader[types.NewPkg(path, "").Lookup(name)] = pkgReaderIndex{pr, idx, nil}
263 }
264 }
265 }
266
267 func writeNewExport(out io.Writer) {
268 l := linker{
269 pw: newPkgEncoder(),
270
271 pkgs: make(map[string]int),
272 decls: make(map[*types.Sym]int),
273 }
274
275 publicRootWriter := l.pw.newEncoder(relocMeta, syncPublic)
276 assert(publicRootWriter.idx == publicRootIdx)
277
278 var selfPkgIdx int
279
280 {
281 pr := localPkgReader
282 r := pr.newDecoder(relocMeta, publicRootIdx, syncPublic)
283
284 r.sync(syncPkg)
285 selfPkgIdx = l.relocIdx(pr, relocPkg, r.reloc(relocPkg))
286
287 r.bool()
288
289 for i, n := 0, r.len(); i < n; i++ {
290 r.sync(syncObject)
291 assert(!r.bool())
292 idx := r.reloc(relocObj)
293 assert(r.len() == 0)
294
295 xpath, xname, xtag := pr.peekObj(idx)
296 assert(xpath == pr.pkgPath)
297 assert(xtag != objStub)
298
299 if types.IsExported(xname) {
300 l.relocIdx(pr, relocObj, idx)
301 }
302 }
303
304 r.sync(syncEOF)
305 }
306
307 {
308 var idxs []int
309 for _, idx := range l.decls {
310 idxs = append(idxs, idx)
311 }
312 sort.Ints(idxs)
313
314 w := publicRootWriter
315
316 w.sync(syncPkg)
317 w.reloc(relocPkg, selfPkgIdx)
318
319 w.bool(typecheck.Lookup(".inittask").Def != nil)
320
321 w.len(len(idxs))
322 for _, idx := range idxs {
323 w.sync(syncObject)
324 w.bool(false)
325 w.reloc(relocObj, idx)
326 w.len(0)
327 }
328
329 w.sync(syncEOF)
330 w.flush()
331 }
332
333 l.pw.dump(out)
334 }
335
View as plain text