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