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