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