1
2
3
4
5 package ir
6
7 import (
8 "cmd/compile/internal/base"
9 "cmd/compile/internal/types"
10 "cmd/internal/obj"
11 "cmd/internal/objabi"
12 "cmd/internal/src"
13 "fmt"
14 "strings"
15 "unicode/utf8"
16 )
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 type Func struct {
54
55
56 miniNode
57 Body Nodes
58
59 Nname *Name
60 OClosure *ClosureExpr
61
62
63
64
65
66
67 Dcl []*Name
68
69
70
71
72
73
74
75 ClosureVars []*Name
76
77
78
79 Closures []*Func
80
81
82 ClosureParent *Func
83
84
85
86
87 Parents []ScopeID
88
89
90 Marks []Mark
91
92 FieldTrack map[*obj.LSym]struct{}
93 DebugInfo any
94 LSym *obj.LSym
95
96 Inl *Inline
97
98
99
100 RangeParent *Func
101
102
103
104
105
106
107
108 funcLitGen int32
109 rangeLitGen int32
110 goDeferGen int32
111
112 Label int32
113
114 Endlineno src.XPos
115 WBPos src.XPos
116
117 Pragma PragmaFlag
118
119 flags bitset16
120
121
122
123
124
125
126
127
128 ABI obj.ABI
129
130
131
132
133 ABIRefs obj.ABISet
134
135 NumDefers int32
136 NumReturns int32
137
138
139
140
141 NWBRCalls *[]SymAndPos
142
143
144
145 WrappedFunc *Func
146
147
148
149 WasmImport *WasmImport
150
151
152 WasmExport *WasmExport
153 }
154
155
156 type WasmImport struct {
157 Module string
158 Name string
159 }
160
161
162 type WasmExport struct {
163 Name string
164 }
165
166
167
168
169
170
171
172
173 func NewFunc(fpos, npos src.XPos, sym *types.Sym, typ *types.Type) *Func {
174 name := NewNameAt(npos, sym, typ)
175 name.Class = PFUNC
176 sym.SetFunc(true)
177
178 fn := &Func{Nname: name}
179 fn.pos = fpos
180 fn.op = ODCLFUNC
181
182
183 fn.ABI = obj.ABIInternal
184 fn.SetTypecheck(1)
185
186 name.Func = fn
187
188 return fn
189 }
190
191 func (f *Func) isStmt() {}
192
193 func (n *Func) copy() Node { panic(n.no("copy")) }
194 func (n *Func) doChildren(do func(Node) bool) bool { return doNodes(n.Body, do) }
195 func (n *Func) doChildrenWithHidden(do func(Node) bool) bool { return doNodes(n.Body, do) }
196 func (n *Func) editChildren(edit func(Node) Node) { editNodes(n.Body, edit) }
197 func (n *Func) editChildrenWithHidden(edit func(Node) Node) { editNodes(n.Body, edit) }
198
199 func (f *Func) Type() *types.Type { return f.Nname.Type() }
200 func (f *Func) Sym() *types.Sym { return f.Nname.Sym() }
201 func (f *Func) Linksym() *obj.LSym { return f.Nname.Linksym() }
202 func (f *Func) LinksymABI(abi obj.ABI) *obj.LSym { return f.Nname.LinksymABI(abi) }
203
204
205 type Inline struct {
206 Cost int32
207
208
209
210
211
212 Dcl []*Name
213 HaveDcl bool
214
215
216
217 Properties string
218
219
220
221
222 CanDelayResults bool
223 }
224
225
226 type Mark struct {
227
228
229 Pos src.XPos
230
231
232 Scope ScopeID
233 }
234
235
236 type ScopeID int32
237
238 const (
239 funcDupok = 1 << iota
240 funcWrapper
241 funcABIWrapper
242 funcNeedctxt
243 funcHasDefer
244 funcNilCheckDisabled
245 funcInlinabilityChecked
246 funcNeverReturns
247 funcOpenCodedDeferDisallowed
248 funcClosureResultsLost
249 funcPackageInit
250 )
251
252 type SymAndPos struct {
253 Sym *obj.LSym
254 Pos src.XPos
255 }
256
257 func (f *Func) Dupok() bool { return f.flags&funcDupok != 0 }
258 func (f *Func) Wrapper() bool { return f.flags&funcWrapper != 0 }
259 func (f *Func) ABIWrapper() bool { return f.flags&funcABIWrapper != 0 }
260 func (f *Func) Needctxt() bool { return f.flags&funcNeedctxt != 0 }
261 func (f *Func) HasDefer() bool { return f.flags&funcHasDefer != 0 }
262 func (f *Func) NilCheckDisabled() bool { return f.flags&funcNilCheckDisabled != 0 }
263 func (f *Func) InlinabilityChecked() bool { return f.flags&funcInlinabilityChecked != 0 }
264 func (f *Func) NeverReturns() bool { return f.flags&funcNeverReturns != 0 }
265 func (f *Func) OpenCodedDeferDisallowed() bool { return f.flags&funcOpenCodedDeferDisallowed != 0 }
266 func (f *Func) ClosureResultsLost() bool { return f.flags&funcClosureResultsLost != 0 }
267 func (f *Func) IsPackageInit() bool { return f.flags&funcPackageInit != 0 }
268
269 func (f *Func) SetDupok(b bool) { f.flags.set(funcDupok, b) }
270 func (f *Func) SetWrapper(b bool) { f.flags.set(funcWrapper, b) }
271 func (f *Func) SetABIWrapper(b bool) { f.flags.set(funcABIWrapper, b) }
272 func (f *Func) SetNeedctxt(b bool) { f.flags.set(funcNeedctxt, b) }
273 func (f *Func) SetHasDefer(b bool) { f.flags.set(funcHasDefer, b) }
274 func (f *Func) SetNilCheckDisabled(b bool) { f.flags.set(funcNilCheckDisabled, b) }
275 func (f *Func) SetInlinabilityChecked(b bool) { f.flags.set(funcInlinabilityChecked, b) }
276 func (f *Func) SetNeverReturns(b bool) { f.flags.set(funcNeverReturns, b) }
277 func (f *Func) SetOpenCodedDeferDisallowed(b bool) { f.flags.set(funcOpenCodedDeferDisallowed, b) }
278 func (f *Func) SetClosureResultsLost(b bool) { f.flags.set(funcClosureResultsLost, b) }
279 func (f *Func) SetIsPackageInit(b bool) { f.flags.set(funcPackageInit, b) }
280
281 func (f *Func) SetWBPos(pos src.XPos) {
282 if base.Debug.WB != 0 {
283 base.WarnfAt(pos, "write barrier")
284 }
285 if !f.WBPos.IsKnown() {
286 f.WBPos = pos
287 }
288 }
289
290
291 func (f *Func) IsClosure() bool {
292 if f.OClosure == nil {
293 return false
294 }
295 return len(f.ClosureVars) > 0
296 }
297
298
299 func FuncName(f *Func) string {
300 if f == nil || f.Nname == nil {
301 return "<nil>"
302 }
303 return f.Sym().Name
304 }
305
306
307
308
309
310
311
312 func PkgFuncName(f *Func) string {
313 if f == nil || f.Nname == nil {
314 return "<nil>"
315 }
316 s := f.Sym()
317 pkg := s.Pkg
318 if pkg == nil {
319 return "<nil>." + s.Name
320 }
321 return pkg.Path + "." + s.Name
322 }
323
324
325
326 func LinkFuncName(f *Func) string {
327 if f == nil || f.Nname == nil {
328 return "<nil>"
329 }
330 s := f.Sym()
331 pkg := s.Pkg
332
333 return objabi.PathToPrefix(pkg.Path) + "." + s.Name
334 }
335
336
337
338 func ParseLinkFuncName(name string) (pkg, sym string, err error) {
339 pkg, sym = splitPkg(name)
340 if pkg == "" {
341 return "", "", fmt.Errorf("no package path in name")
342 }
343
344 pkg, err = objabi.PrefixToPath(pkg)
345 if err != nil {
346 return "", "", fmt.Errorf("malformed package path: %v", err)
347 }
348
349 return pkg, sym, nil
350 }
351
352
353 func modPathOK(r rune) bool {
354 if r < utf8.RuneSelf {
355 return r == '-' || r == '.' || r == '_' || r == '~' ||
356 '0' <= r && r <= '9' ||
357 'A' <= r && r <= 'Z' ||
358 'a' <= r && r <= 'z'
359 }
360 return false
361 }
362
363 func escapedImportPathOK(r rune) bool {
364 return modPathOK(r) || r == '+' || r == '/' || r == '%'
365 }
366
367
368
369 func splitPkg(name string) (pkgpath, sym string) {
370
371
372
373 lastSlashIdx := 0
374 for i, r := range name {
375
376
377
378
379
380 if !escapedImportPathOK(r) {
381 break
382 }
383 if r == '/' {
384 lastSlashIdx = i
385 }
386 }
387 for i := lastSlashIdx; i < len(name); i++ {
388 r := name[i]
389 if r == '.' {
390 return name[:i], name[i+1:]
391 }
392 }
393
394 return "", name
395 }
396
397 var CurFunc *Func
398
399
400
401
402 func WithFunc(curfn *Func, do func()) {
403 oldfn, oldpos := CurFunc, base.Pos
404 defer func() { CurFunc, base.Pos = oldfn, oldpos }()
405
406 CurFunc, base.Pos = curfn, curfn.Pos()
407 do()
408 }
409
410 func FuncSymName(s *types.Sym) string {
411 return s.Name + "·f"
412 }
413
414
415
416 func ClosureDebugRuntimeCheck(clo *ClosureExpr) {
417 if base.Debug.Closure > 0 {
418 if clo.Esc() == EscHeap {
419 base.WarnfAt(clo.Pos(), "heap closure, captured vars = %v", clo.Func.ClosureVars)
420 } else {
421 base.WarnfAt(clo.Pos(), "stack closure, captured vars = %v", clo.Func.ClosureVars)
422 }
423 }
424 if base.Flag.CompilingRuntime && clo.Esc() == EscHeap && !clo.IsGoWrap {
425 base.ErrorfAt(clo.Pos(), 0, "heap-allocated closure %s, not allowed in runtime", FuncName(clo.Func))
426 }
427 }
428
429
430 var globClosgen int32
431
432
433 func closureName(outerfn *Func, pos src.XPos, why Op) *types.Sym {
434 if outerfn.OClosure != nil && outerfn.OClosure.Func.RangeParent != nil {
435 outerfn = outerfn.OClosure.Func.RangeParent
436 }
437 pkg := types.LocalPkg
438 outer := "glob."
439 var suffix string = "."
440 switch why {
441 default:
442 base.FatalfAt(pos, "closureName: bad Op: %v", why)
443 case OCLOSURE:
444 if outerfn.OClosure == nil {
445 suffix = ".func"
446 }
447 case ORANGE:
448 suffix = "-range"
449 case OGO:
450 suffix = ".gowrap"
451 case ODEFER:
452 suffix = ".deferwrap"
453 }
454 gen := &globClosgen
455
456
457
458
459 if !IsBlank(outerfn.Nname) {
460 pkg = outerfn.Sym().Pkg
461 outer = FuncName(outerfn)
462
463 switch why {
464 case OCLOSURE:
465 gen = &outerfn.funcLitGen
466 case ORANGE:
467 gen = &outerfn.rangeLitGen
468 default:
469 gen = &outerfn.goDeferGen
470 }
471 }
472
473
474
475
476 if inlIndex := base.Ctxt.InnermostPos(pos).Base().InliningIndex(); inlIndex >= 0 {
477 names := []string{outer}
478 base.Ctxt.InlTree.AllParents(inlIndex, func(call obj.InlinedCall) {
479 names = append(names, call.Name)
480 })
481 outer = strings.Join(names, ".")
482 }
483
484 *gen++
485 return pkg.Lookup(fmt.Sprintf("%s%s%d", outer, suffix, *gen))
486 }
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503 func NewClosureFunc(fpos, cpos src.XPos, why Op, typ *types.Type, outerfn *Func, pkg *Package) *Func {
504 if outerfn == nil {
505 base.FatalfAt(fpos, "outerfn is nil")
506 }
507
508 fn := NewFunc(fpos, fpos, closureName(outerfn, cpos, why), typ)
509 fn.SetDupok(outerfn.Dupok())
510
511 clo := &ClosureExpr{Func: fn}
512 clo.op = OCLOSURE
513 clo.pos = cpos
514 clo.SetType(typ)
515 clo.SetTypecheck(1)
516 if why == ORANGE {
517 clo.Func.RangeParent = outerfn
518 if outerfn.OClosure != nil && outerfn.OClosure.Func.RangeParent != nil {
519 clo.Func.RangeParent = outerfn.OClosure.Func.RangeParent
520 }
521 }
522 fn.OClosure = clo
523
524 fn.Nname.Defn = fn
525 pkg.Funcs = append(pkg.Funcs, fn)
526 fn.ClosureParent = outerfn
527
528 return fn
529 }
530
531
532 func IsFuncPCIntrinsic(n *CallExpr) bool {
533 if n.Op() != OCALLFUNC || n.Fun.Op() != ONAME {
534 return false
535 }
536 fn := n.Fun.(*Name).Sym()
537 return (fn.Name == "FuncPCABI0" || fn.Name == "FuncPCABIInternal") &&
538 fn.Pkg.Path == "internal/abi"
539 }
540
541
542
543
544
545
546 func IsIfaceOfFunc(n Node) *Func {
547 if n, ok := n.(*ConvExpr); ok && n.Op() == OCONVIFACE {
548 if name, ok := n.X.(*Name); ok && name.Op() == ONAME && name.Class == PFUNC {
549 return name.Func
550 }
551 }
552 return nil
553 }
554
555
556
557
558
559
560
561
562
563
564 func FuncPC(pos src.XPos, n Node, wantABI obj.ABI) Node {
565 if !n.Type().IsInterface() {
566 base.ErrorfAt(pos, 0, "internal/abi.FuncPC%s expects an interface value, got %v", wantABI, n.Type())
567 }
568
569 if fn := IsIfaceOfFunc(n); fn != nil {
570 name := fn.Nname
571 abi := fn.ABI
572 if abi != wantABI {
573 base.ErrorfAt(pos, 0, "internal/abi.FuncPC%s expects an %v function, %s is defined as %v", wantABI, wantABI, name.Sym().Name, abi)
574 }
575 var e Node = NewLinksymExpr(pos, name.LinksymABI(abi), types.Types[types.TUINTPTR])
576 e = NewAddrExpr(pos, e)
577 e.SetType(types.Types[types.TUINTPTR].PtrTo())
578 e = NewConvExpr(pos, OCONVNOP, types.Types[types.TUINTPTR], e)
579 e.SetTypecheck(1)
580 return e
581 }
582
583
584 if wantABI != obj.ABIInternal {
585 base.ErrorfAt(pos, 0, "internal/abi.FuncPC%s does not accept func expression, which is ABIInternal", wantABI)
586 }
587 var e Node = NewUnaryExpr(pos, OIDATA, n)
588 e.SetType(types.Types[types.TUINTPTR].PtrTo())
589 e.SetTypecheck(1)
590 e = NewStarExpr(pos, e)
591 e.SetType(types.Types[types.TUINTPTR])
592 e.SetTypecheck(1)
593 return e
594 }
595
596
597
598
599
600
601 func (fn *Func) DeclareParams(setNname bool) {
602 if fn.Dcl != nil {
603 base.FatalfAt(fn.Pos(), "%v already has Dcl", fn)
604 }
605
606 declareParams := func(params []*types.Field, ctxt Class, prefix string, offset int) {
607 for i, param := range params {
608 sym := param.Sym
609 if sym == nil || sym.IsBlank() {
610 sym = fn.Sym().Pkg.LookupNum(prefix, i)
611 }
612
613 name := NewNameAt(param.Pos, sym, param.Type)
614 name.Class = ctxt
615 name.Curfn = fn
616 fn.Dcl[offset+i] = name
617
618 if setNname {
619 param.Nname = name
620 }
621 }
622 }
623
624 sig := fn.Type()
625 params := sig.RecvParams()
626 results := sig.Results()
627
628 fn.Dcl = make([]*Name, len(params)+len(results))
629 declareParams(params, PPARAM, "~p", 0)
630 declareParams(results, PPARAMOUT, "~r", len(params))
631 }
632
633
634 func ContainsClosure(f, c *Func) bool {
635
636 if f == c || c.OClosure == nil {
637 return false
638 }
639
640 for p := c.ClosureParent; p != nil; p = p.ClosureParent {
641 if p == f {
642 return true
643 }
644 }
645 return false
646 }
647
View as plain text