1
2
3
4
5 package gc
6
7 import (
8 "cmp"
9 "internal/race"
10 "math/rand"
11 "slices"
12 "sync"
13
14 "cmd/compile/internal/base"
15 "cmd/compile/internal/ir"
16 "cmd/compile/internal/liveness"
17 "cmd/compile/internal/objw"
18 "cmd/compile/internal/pgoir"
19 "cmd/compile/internal/ssacompile"
20 "cmd/compile/internal/ssagen"
21 "cmd/compile/internal/staticinit"
22 "cmd/compile/internal/types"
23 "cmd/compile/internal/walk"
24 "cmd/internal/obj"
25 )
26
27
28
29 var (
30 compilequeue []*ir.Func
31 )
32
33 func enqueueFunc(fn *ir.Func, symABIs *ssagen.SymABIs) {
34 if ir.FuncName(fn) == "_" {
35
36
37 return
38 }
39
40 if fn.IsClosure() {
41 return
42 }
43
44 if ssagen.CreateWasmImportWrapper(fn) {
45 return
46 }
47
48 if len(fn.Body) == 0 {
49 if needsIntrinsicBody(fn, symABIs) {
50
51
52
53
54 ssagen.GenIntrinsicBody(fn)
55 } else {
56
57 ir.InitLSym(fn, false)
58 types.CalcSize(fn.Type())
59 a := ssagen.AbiForBodylessFuncStackMap(fn)
60 abiInfo := a.ABIAnalyzeFuncType(fn.Type())
61 if fn.ABI == obj.ABI0 {
62
63
64
65
66 liveness.WriteFuncMap(fn, abiInfo)
67
68 x := ssagen.EmitArgInfo(fn, abiInfo)
69 objw.Global(x, int32(len(x.P)), obj.RODATA|obj.LOCAL)
70 }
71 return
72 }
73 }
74
75 errorsBefore := base.Errors()
76
77 todo := []*ir.Func{fn}
78 for len(todo) > 0 {
79 next := todo[len(todo)-1]
80 todo = todo[:len(todo)-1]
81
82 prepareFunc(next)
83 todo = append(todo, next.Closures...)
84 }
85
86 if base.Errors() > errorsBefore {
87 return
88 }
89
90
91
92 compilequeue = append(compilequeue, fn)
93 }
94
95 func needsIntrinsicBody(fn *ir.Func, symABIs *ssagen.SymABIs) bool {
96 return len(fn.Body) == 0 && ir.IsIntrinsicSym(fn.Sym()) && fn.Sym().Linkname == "" && !symABIs.HasDef(fn.Sym())
97 }
98
99
100
101 func prepareFunc(fn *ir.Func) {
102
103
104
105 ir.InitLSym(fn, true)
106
107
108
109 if staticinit.MapInitToVar != nil {
110 if _, ok := staticinit.MapInitToVar[fn]; ok {
111 ssagen.RegisterMapInitLsym(fn.Linksym())
112 }
113 }
114
115
116 types.CalcSize(fn.Type())
117
118
119
120
121 ssagen.GenWasmExportWrapper(fn)
122
123 walk.Walk(fn)
124 if ir.MatchAstDump(fn, "walk") {
125 ir.AstDump(fn, "walk, "+ir.FuncName(fn))
126 }
127
128 base.Ctxt.DwTextCount++
129 }
130
131
132
133
134 func compileFunctions(profile *pgoir.Profile) {
135 if race.Enabled {
136
137 tmp := make([]*ir.Func, len(compilequeue))
138 perm := rand.Perm(len(compilequeue))
139 for i, v := range perm {
140 tmp[v] = compilequeue[i]
141 }
142 copy(compilequeue, tmp)
143 } else {
144
145
146
147
148
149 slices.SortFunc(compilequeue, func(a, b *ir.Func) int {
150 return cmp.Compare(a.NumPreWalkNodes, b.NumPreWalkNodes)
151 })
152 }
153
154 var mu sync.Mutex
155 var wg sync.WaitGroup
156 mu.Lock()
157
158 for workerId := range base.Flag.LowerC {
159 wg.Go(func() {
160 var closures []*ir.Func
161 for {
162 mu.Lock()
163 compilequeue = append(compilequeue, closures...)
164 remaining := len(compilequeue)
165 if remaining == 0 {
166 mu.Unlock()
167 return
168 }
169 fn := compilequeue[len(compilequeue)-1]
170 compilequeue = compilequeue[:len(compilequeue)-1]
171 mu.Unlock()
172 ssagen.Compile(ssacompile.Compiler{}, fn, workerId, profile)
173 closures = fn.Closures
174
175
176 fn.Body = nil
177 fn.Dcl = nil
178 fn.ClosureVars = nil
179
180
181 if !fn.LSym.WasInlined() {
182 fn.DebugInfo = nil
183 }
184 }
185 })
186 }
187
188 types.CalcSizeDisabled = true
189 base.Ctxt.InParallel = true
190
191 mu.Unlock()
192 wg.Wait()
193 compilequeue = nil
194
195 base.Ctxt.InParallel = false
196 types.CalcSizeDisabled = false
197
198 ssacompile.PostCompile()
199 }
200
View as plain text