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