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