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