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