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