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