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