1
2
3
4
5 package gc
6
7 import (
8 "bufio"
9 "bytes"
10 "cmd/compile/internal/base"
11 "cmd/compile/internal/bloop"
12 "cmd/compile/internal/coverage"
13 "cmd/compile/internal/deadlocals"
14 "cmd/compile/internal/dwarfgen"
15 "cmd/compile/internal/escape"
16 "cmd/compile/internal/inline"
17 "cmd/compile/internal/inline/interleaved"
18 "cmd/compile/internal/ir"
19 "cmd/compile/internal/logopt"
20 "cmd/compile/internal/loopvar"
21 "cmd/compile/internal/noder"
22 "cmd/compile/internal/pgoir"
23 "cmd/compile/internal/pkginit"
24 "cmd/compile/internal/reflectdata"
25 "cmd/compile/internal/rewriteresults"
26 "cmd/compile/internal/rttype"
27 "cmd/compile/internal/slice"
28 "cmd/compile/internal/ssacompile"
29 "cmd/compile/internal/ssagen"
30 "cmd/compile/internal/staticinit"
31 "cmd/compile/internal/stats"
32 "cmd/compile/internal/typecheck"
33 "cmd/compile/internal/types"
34 "cmd/internal/dwarf"
35 "cmd/internal/obj"
36 "cmd/internal/objabi"
37 "cmd/internal/src"
38 "cmd/internal/telemetry/counter"
39 "flag"
40 "fmt"
41 "internal/buildcfg"
42 "log"
43 "os"
44 "runtime"
45 )
46
47
48
49
50
51 func handlePanic() {
52 ir.CloseHTMLWriters()
53 noder.CloseHTMLWriters()
54 if err := recover(); err != nil {
55 if err == "-h" {
56
57
58 panic(err)
59 }
60 base.Fatalf("panic: %v", err)
61 }
62 }
63
64
65
66
67 func Main(archInit func(*ssagen.ArchInfo)) {
68 base.Timer.Start("fe", "init")
69 counter.Open()
70 counter.Inc("compile/invocations")
71
72 defer handlePanic()
73
74 archInit(&ssagen.Arch)
75
76 base.Ctxt = obj.Linknew(ssagen.Arch.LinkArch)
77 base.Ctxt.DiagFunc = base.Diagf
78 base.Ctxt.DiagFlush = base.FlushErrors
79 base.Ctxt.Bso = bufio.NewWriter(os.Stdout)
80
81
82
83
84
85 base.Ctxt.UseBASEntries = base.Ctxt.Headtype != objabi.Hdarwin
86
87 base.DebugSSA = ssacompile.PhaseOption
88 base.ParseFlags()
89
90 if flagGCStart := base.Debug.GCStart; flagGCStart > 0 ||
91 os.Getenv("GOGC") == "" && os.Getenv("GOMEMLIMIT") == "" && base.Flag.LowerC != 1 {
92 startHeapMB := int64(128)
93 if flagGCStart > 0 {
94 startHeapMB = int64(flagGCStart)
95 }
96 base.AdjustStartingHeap(uint64(startHeapMB)<<20, 0, 0, 0, base.Debug.GCAdjust == 1)
97 }
98
99 types.LocalPkg = types.NewPkg(base.Ctxt.Pkgpath, "")
100
101
102 types.BuiltinPkg = types.NewPkg("go.builtin", "")
103 types.BuiltinPkg.Prefix = "go:builtin"
104
105
106 types.UnsafePkg = types.NewPkg("unsafe", "unsafe")
107
108
109
110
111
112
113 ir.Pkgs.Runtime = types.NewPkg("go.runtime", "runtime")
114 ir.Pkgs.Runtime.Prefix = "runtime"
115
116
117
118 ir.Pkgs.InternalMaps = types.NewPkg("go.internal/runtime/maps", "internal/runtime/maps")
119 ir.Pkgs.InternalMaps.Prefix = "internal/runtime/maps"
120
121
122 ir.Pkgs.Itab = types.NewPkg("go.itab", "go.itab")
123 ir.Pkgs.Itab.Prefix = "go:itab"
124
125
126 ir.Pkgs.Go = types.NewPkg("go", "")
127
128
129 ir.Pkgs.Coverage = types.NewPkg("go.coverage", "runtime/coverage")
130 ir.Pkgs.Coverage.Prefix = "runtime/coverage"
131
132
133
134
135 dwarfgen.RecordFlags("B", "N", "l", "msan", "race", "asan", "shared", "dynlink", "dwarf", "dwarflocationlists", "dwarfbasentries", "smallframes", "spectre")
136
137 if !base.EnableTrace && base.Flag.LowerT {
138 log.Fatalf("compiler not built with support for -t")
139 }
140
141
142
143
144
145 if base.Flag.LowerL <= 1 {
146 base.Flag.LowerL = 1 - base.Flag.LowerL
147 }
148
149 if base.Flag.SmallFrames {
150 ir.MaxStackVarSize = 64 * 1024
151 ir.MaxImplicitStackVarSize = 16 * 1024
152 }
153
154 if base.Flag.Dwarf {
155 base.Ctxt.DebugInfo = dwarfgen.Info
156 base.Ctxt.GenAbstractFunc = dwarfgen.AbstractFunc
157 base.Ctxt.DwFixups = obj.NewDwarfFixupTable(base.Ctxt)
158 } else {
159
160 base.Flag.GenDwarfInl = 0
161 base.Ctxt.Flag_locationlists = false
162 }
163 if base.Ctxt.Flag_locationlists && len(base.Ctxt.Arch.DWARFRegisters) == 0 {
164 log.Fatalf("location lists requested but register mapping not available on %v", base.Ctxt.Arch.Name)
165 }
166
167 types.ParseLangFlag()
168
169 symABIs := ssagen.NewSymABIs()
170 if base.Flag.SymABIs != "" {
171 symABIs.ReadSymABIs(base.Flag.SymABIs)
172 }
173
174 if objabi.LookupPkgSpecial(base.Ctxt.Pkgpath).NoInstrument {
175 base.Flag.Race = false
176 base.Flag.MSan = false
177 base.Flag.ASan = false
178 }
179
180 ssagen.Arch.LinkArch.Init(base.Ctxt)
181 startProfile()
182 if base.Flag.Race || base.Flag.MSan || base.Flag.ASan {
183 base.Flag.Cfg.Instrumenting = true
184 }
185 if base.Flag.Dwarf {
186 dwarf.EnableLogging(base.Debug.DwarfInl != 0)
187 }
188 if base.Debug.SoftFloat != 0 {
189 ssagen.Arch.SoftFloat = true
190 }
191
192 if base.Flag.JSON != "" {
193 logopt.LogJsonOption(base.Flag.JSON)
194 }
195
196 ir.EscFmt = escape.Fmt
197 ir.IsIntrinsicCall = ssagen.IsIntrinsicCall
198 ir.IsIntrinsicSym = ssagen.IsIntrinsicSym
199 inline.SSADumpInline = ssagen.DumpInline
200 ssagen.InitEnv()
201
202 types.PtrSize = ssagen.Arch.LinkArch.PtrSize
203 types.RegSize = ssagen.Arch.LinkArch.RegSize
204 types.MaxWidth = ssagen.Arch.MAXWIDTH
205
206 typecheck.Target = new(ir.Package)
207
208 base.AutogeneratedPos = makePos(src.NewFileBase("<autogenerated>", "<autogenerated>"), 1, 0)
209
210 typecheck.InitUniverse()
211 typecheck.InitRuntime()
212 rttype.Init()
213
214
215
216
217 ssagen.InitTables()
218
219
220 noder.LoadPackage(flag.Args())
221
222
223
224
225 if base.Ctxt.Pkgpath == obj.UnlinkablePkg && types.LocalPkg.Name == "main" {
226 base.Ctxt.Pkgpath = "main"
227 types.LocalPkg.Path = "main"
228 types.LocalPkg.Prefix = "main"
229 }
230
231 dwarfgen.RecordPackageName()
232
233
234 ssagen.InitConfig(ssacompile.NewConfig(ssagen.Arch.SoftFloat))
235
236
237 coverage.Fixup()
238
239
240 base.Timer.Start("fe", "pgo-load-profile")
241 var profile *pgoir.Profile
242 if base.Flag.PgoProfile != "" {
243 var err error
244 profile, err = pgoir.New(base.Flag.PgoProfile)
245 if err != nil {
246 log.Fatalf("%s: PGO error: %v", base.Flag.PgoProfile, err)
247 }
248 }
249
250 for _, fn := range typecheck.Target.Funcs {
251 if ir.MatchAstDump(fn, "start") {
252 ir.AstDump(fn, "start, "+ir.FuncName(fn))
253 }
254 }
255
256
257 bloop.Walk(typecheck.Target)
258
259
260 base.Timer.Start("fe", "devirtualize-and-inline")
261 interleaved.DevirtualizeAndInlinePackage(typecheck.Target, profile)
262
263 for _, fn := range typecheck.Target.Funcs {
264 if ir.MatchAstDump(fn, "devirtualize-and-inline") {
265 ir.AstDump(fn, "devirtualize-and-inline, "+ir.FuncName(fn))
266 }
267 }
268
269 noder.MakeWrappers(typecheck.Target)
270
271
272 var transformed []loopvar.VarAndLoop
273 for _, fn := range typecheck.Target.Funcs {
274 transformed = append(transformed, loopvar.ForCapture(fn)...)
275 }
276
277
278 pkginit.MakeTask()
279
280
281
282 symABIs.GenABIWrappers()
283
284
285
286 preassignSymIdxs(symABIs)
287
288 deadlocals.Funcs(typecheck.Target.Funcs)
289
290
291
292
293
294
295
296
297
298 base.Timer.Start("fe", "escapes")
299 escape.Funcs(typecheck.Target.Funcs)
300
301 rewriteresults.Funcs(typecheck.Target.Funcs)
302
303 slice.Funcs(typecheck.Target.Funcs)
304
305 loopvar.LogTransformations(transformed)
306
307
308
309
310
311 if base.Flag.CompilingRuntime {
312 ssagen.EnableNoWriteBarrierRecCheck()
313 }
314
315 base.Timer.Start("fe", "dumpexport")
316 dumpexport()
317
318 reflectdata.WriteBasicTypes()
319
320
321
322
323
324 base.Timer.Start("be", "compilefuncs")
325 for nextFunc, nextExtern := 0, 0; ; {
326 reflectdata.WriteRuntimeTypes()
327
328 if nextExtern < len(typecheck.Target.Externs) {
329 switch n := typecheck.Target.Externs[nextExtern]; n.Op() {
330 case ir.ONAME:
331 dumpGlobal(n)
332 case ir.OLITERAL:
333 dumpGlobalConst(n)
334 case ir.OTYPE:
335 reflectdata.NeedRuntimeType(n.Type())
336 }
337 nextExtern++
338 continue
339 }
340
341 if nextFunc < len(typecheck.Target.Funcs) {
342 enqueueFunc(typecheck.Target.Funcs[nextFunc], symABIs)
343 nextFunc++
344 continue
345 }
346
347
348
349
350 if len(compilequeue) != 0 {
351 compileFunctions(profile)
352 continue
353 }
354
355
356
357
358
359
360
361
362
363 if base.Ctxt.DwFixups != nil {
364 base.Ctxt.DwFixups.Finalize(base.Ctxt.Pkgpath, base.Debug.DwarfInl != 0)
365 base.Ctxt.DwFixups = nil
366 base.Flag.GenDwarfInl = 0
367 continue
368 }
369
370 break
371 }
372
373 if base.Flag.Stats {
374 s := new(stats.Stats)
375 for _, fn := range typecheck.Target.Funcs {
376 s.Merge(fn.Stats)
377 }
378 s.Print()
379 }
380
381 base.Timer.AddEvent(int64(len(typecheck.Target.Funcs)), "funcs")
382
383 if base.Flag.CompilingRuntime {
384
385 ssagen.NoWriteBarrierRecCheck()
386 }
387
388
389 if base.Debug.WrapGlobalMapCtl != 1 {
390 staticinit.AddKeepRelocations()
391 }
392
393
394 base.Timer.Start("be", "dumpobj")
395 dumpdata()
396 base.Ctxt.NumberSyms()
397 dumpobj()
398 if base.Flag.AsmHdr != "" {
399 dumpasmhdr()
400 }
401
402 ssagen.CheckLargeStacks()
403
404 if len(compilequeue) != 0 {
405 base.Fatalf("%d uncompiled functions", len(compilequeue))
406 }
407
408 logopt.FlushLoggedOpts(base.Ctxt, base.Ctxt.Pkgpath)
409 base.ExitIfErrors()
410
411 base.FlushErrors()
412 base.Timer.Stop()
413
414 if base.Flag.Bench != "" {
415 if err := writebench(base.Flag.Bench); err != nil {
416 log.Fatalf("cannot write benchmark data: %v", err)
417 }
418 }
419 }
420
421 func writebench(filename string) error {
422 f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
423 if err != nil {
424 return err
425 }
426
427 var buf bytes.Buffer
428 fmt.Fprintln(&buf, "commit:", buildcfg.Version)
429 fmt.Fprintln(&buf, "goos:", runtime.GOOS)
430 fmt.Fprintln(&buf, "goarch:", runtime.GOARCH)
431 base.Timer.Write(&buf, "BenchmarkCompile:"+base.Ctxt.Pkgpath+":")
432
433 n, err := f.Write(buf.Bytes())
434 if err != nil {
435 return err
436 }
437 if n != buf.Len() {
438 panic("bad writer")
439 }
440
441 return f.Close()
442 }
443
444 func makePos(b *src.PosBase, line, col uint) src.XPos {
445 return base.Ctxt.PosTable.XPos(src.MakePos(b, line, col))
446 }
447
View as plain text