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/ssa"
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.CurFunc != nil {
35 base.FatalfAt(fn.Pos(), "enqueueFunc %v inside %v", fn, ir.CurFunc)
36 }
37
38 if ir.FuncName(fn) == "_" {
39
40
41 return
42 }
43
44 if fn.IsClosure() {
45 return
46 }
47
48 if ssagen.CreateWasmImportWrapper(fn) {
49 return
50 }
51
52 if len(fn.Body) == 0 {
53 if ir.IsIntrinsicSym(fn.Sym()) && fn.Sym().Linkname == "" && !symABIs.HasDef(fn.Sym()) {
54
55
56
57
58 ssagen.GenIntrinsicBody(fn)
59 } else {
60
61 ir.InitLSym(fn, false)
62 types.CalcSize(fn.Type())
63 a := ssagen.AbiForBodylessFuncStackMap(fn)
64 abiInfo := a.ABIAnalyzeFuncType(fn.Type())
65 if fn.ABI == obj.ABI0 {
66
67
68
69
70 liveness.WriteFuncMap(fn, abiInfo)
71
72 x := ssagen.EmitArgInfo(fn, abiInfo)
73 objw.Global(x, int32(len(x.P)), obj.RODATA|obj.LOCAL)
74 }
75 return
76 }
77 }
78
79 errorsBefore := base.Errors()
80
81 todo := []*ir.Func{fn}
82 for len(todo) > 0 {
83 next := todo[len(todo)-1]
84 todo = todo[:len(todo)-1]
85
86 prepareFunc(next)
87 todo = append(todo, next.Closures...)
88 }
89
90 if base.Errors() > errorsBefore {
91 return
92 }
93
94
95
96 compilequeue = append(compilequeue, fn)
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 ir.CurFunc = fn
124 walk.Walk(fn)
125 if ir.MatchAstDump(fn, "walk") {
126 ir.AstDump(fn, "walk, "+ir.FuncName(fn))
127 }
128 ir.CurFunc = nil
129
130 base.Ctxt.DwTextCount++
131 }
132
133
134
135
136 func compileFunctions(profile *pgoir.Profile) {
137 if race.Enabled {
138
139 tmp := make([]*ir.Func, len(compilequeue))
140 perm := rand.Perm(len(compilequeue))
141 for i, v := range perm {
142 tmp[v] = compilequeue[i]
143 }
144 copy(compilequeue, tmp)
145 } else {
146
147
148
149
150
151 slices.SortFunc(compilequeue, func(a, b *ir.Func) int {
152 return cmp.Compare(a.NumPreWalkNodes, b.NumPreWalkNodes)
153 })
154 }
155
156 var mu sync.Mutex
157 var wg sync.WaitGroup
158 mu.Lock()
159
160 for workerId := range base.Flag.LowerC {
161
162
163 wg.Add(1)
164 go func() {
165 defer wg.Done()
166 var closures []*ir.Func
167 for {
168 mu.Lock()
169 compilequeue = append(compilequeue, closures...)
170 remaining := len(compilequeue)
171 if remaining == 0 {
172 mu.Unlock()
173 return
174 }
175 fn := compilequeue[len(compilequeue)-1]
176 compilequeue = compilequeue[:len(compilequeue)-1]
177 mu.Unlock()
178 ssagen.Compile(fn, workerId, profile)
179 closures = fn.Closures
180 }
181 }()
182 }
183
184 types.CalcSizeDisabled = true
185 base.Ctxt.InParallel = true
186
187 mu.Unlock()
188 wg.Wait()
189 compilequeue = nil
190
191 base.Ctxt.InParallel = false
192 types.CalcSizeDisabled = false
193
194 ssa.PostCompile()
195 }
196
View as plain text