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 interface{}
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
319 return pkg.Path + "." + s.Name
320 }
321
322
323
324 func LinkFuncName(f *Func) string {
325 if f == nil || f.Nname == nil {
326 return "<nil>"
327 }
328 s := f.Sym()
329 pkg := s.Pkg
330
331 return objabi.PathToPrefix(pkg.Path) + "." + s.Name
332 }
333
334
335
336 func ParseLinkFuncName(name string) (pkg, sym string, err error) {
337 pkg, sym = splitPkg(name)
338 if pkg == "" {
339 return "", "", fmt.Errorf("no package path in name")
340 }
341
342 pkg, err = objabi.PrefixToPath(pkg)
343 if err != nil {
344 return "", "", fmt.Errorf("malformed package path: %v", err)
345 }
346
347 return pkg, sym, nil
348 }
349
350
351 func modPathOK(r rune) bool {
352 if r < utf8.RuneSelf {
353 return r == '-' || r == '.' || r == '_' || r == '~' ||
354 '0' <= r && r <= '9' ||
355 'A' <= r && r <= 'Z' ||
356 'a' <= r && r <= 'z'
357 }
358 return false
359 }
360
361 func escapedImportPathOK(r rune) bool {
362 return modPathOK(r) || r == '+' || r == '/' || r == '%'
363 }
364
365
366
367 func splitPkg(name string) (pkgpath, sym string) {
368
369
370
371 lastSlashIdx := 0
372 for i, r := range name {
373
374
375
376
377
378 if !escapedImportPathOK(r) {
379 break
380 }
381 if r == '/' {
382 lastSlashIdx = i
383 }
384 }
385 for i := lastSlashIdx; i < len(name); i++ {
386 r := name[i]
387 if r == '.' {
388 return name[:i], name[i+1:]
389 }
390 }
391
392 return "", name
393 }
394
395 var CurFunc *Func
396
397
398
399
400 func WithFunc(curfn *Func, do func()) {
401 oldfn, oldpos := CurFunc, base.Pos
402 defer func() { CurFunc, base.Pos = oldfn, oldpos }()
403
404 CurFunc, base.Pos = curfn, curfn.Pos()
405 do()
406 }
407
408 func FuncSymName(s *types.Sym) string {
409 return s.Name + "·f"
410 }
411
412
413
414 func ClosureDebugRuntimeCheck(clo *ClosureExpr) {
415 if base.Debug.Closure > 0 {
416 if clo.Esc() == EscHeap {
417 base.WarnfAt(clo.Pos(), "heap closure, captured vars = %v", clo.Func.ClosureVars)
418 } else {
419 base.WarnfAt(clo.Pos(), "stack closure, captured vars = %v", clo.Func.ClosureVars)
420 }
421 }
422 if base.Flag.CompilingRuntime && clo.Esc() == EscHeap && !clo.IsGoWrap {
423 base.ErrorfAt(clo.Pos(), 0, "heap-allocated closure %s, not allowed in runtime", FuncName(clo.Func))
424 }
425 }
426
427
428 var globClosgen int32
429
430
431 func closureName(outerfn *Func, pos src.XPos, why Op) *types.Sym {
432 if outerfn.OClosure != nil && outerfn.OClosure.Func.RangeParent != nil {
433 outerfn = outerfn.OClosure.Func.RangeParent
434 }
435 pkg := types.LocalPkg
436 outer := "glob."
437 var suffix string = "."
438 switch why {
439 default:
440 base.FatalfAt(pos, "closureName: bad Op: %v", why)
441 case OCLOSURE:
442 if outerfn.OClosure == nil {
443 suffix = ".func"
444 }
445 case ORANGE:
446 suffix = "-range"
447 case OGO:
448 suffix = ".gowrap"
449 case ODEFER:
450 suffix = ".deferwrap"
451 }
452 gen := &globClosgen
453
454
455
456
457 if !IsBlank(outerfn.Nname) {
458 pkg = outerfn.Sym().Pkg
459 outer = FuncName(outerfn)
460
461 switch why {
462 case OCLOSURE:
463 gen = &outerfn.funcLitGen
464 case ORANGE:
465 gen = &outerfn.rangeLitGen
466 default:
467 gen = &outerfn.goDeferGen
468 }
469 }
470
471
472
473
474 if inlIndex := base.Ctxt.InnermostPos(pos).Base().InliningIndex(); inlIndex >= 0 {
475 names := []string{outer}
476 base.Ctxt.InlTree.AllParents(inlIndex, func(call obj.InlinedCall) {
477 names = append(names, call.Name)
478 })
479 outer = strings.Join(names, ".")
480 }
481
482 *gen++
483 return pkg.Lookup(fmt.Sprintf("%s%s%d", outer, suffix, *gen))
484 }
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501 func NewClosureFunc(fpos, cpos src.XPos, why Op, typ *types.Type, outerfn *Func, pkg *Package) *Func {
502 if outerfn == nil {
503 base.FatalfAt(fpos, "outerfn is nil")
504 }
505
506 fn := NewFunc(fpos, fpos, closureName(outerfn, cpos, why), typ)
507 fn.SetDupok(outerfn.Dupok())
508
509 clo := &ClosureExpr{Func: fn}
510 clo.op = OCLOSURE
511 clo.pos = cpos
512 clo.SetType(typ)
513 clo.SetTypecheck(1)
514 if why == ORANGE {
515 clo.Func.RangeParent = outerfn
516 if outerfn.OClosure != nil && outerfn.OClosure.Func.RangeParent != nil {
517 clo.Func.RangeParent = outerfn.OClosure.Func.RangeParent
518 }
519 }
520 fn.OClosure = clo
521
522 fn.Nname.Defn = fn
523 pkg.Funcs = append(pkg.Funcs, fn)
524 fn.ClosureParent = outerfn
525
526 return fn
527 }
528
529
530 func IsFuncPCIntrinsic(n *CallExpr) bool {
531 if n.Op() != OCALLFUNC || n.Fun.Op() != ONAME {
532 return false
533 }
534 fn := n.Fun.(*Name).Sym()
535 return (fn.Name == "FuncPCABI0" || fn.Name == "FuncPCABIInternal") &&
536 fn.Pkg.Path == "internal/abi"
537 }
538
539
540
541
542
543
544 func IsIfaceOfFunc(n Node) *Func {
545 if n, ok := n.(*ConvExpr); ok && n.Op() == OCONVIFACE {
546 if name, ok := n.X.(*Name); ok && name.Op() == ONAME && name.Class == PFUNC {
547 return name.Func
548 }
549 }
550 return nil
551 }
552
553
554
555
556
557
558
559
560
561
562 func FuncPC(pos src.XPos, n Node, wantABI obj.ABI) Node {
563 if !n.Type().IsInterface() {
564 base.ErrorfAt(pos, 0, "internal/abi.FuncPC%s expects an interface value, got %v", wantABI, n.Type())
565 }
566
567 if fn := IsIfaceOfFunc(n); fn != nil {
568 name := fn.Nname
569 abi := fn.ABI
570 if abi != wantABI {
571 base.ErrorfAt(pos, 0, "internal/abi.FuncPC%s expects an %v function, %s is defined as %v", wantABI, wantABI, name.Sym().Name, abi)
572 }
573 var e Node = NewLinksymExpr(pos, name.LinksymABI(abi), types.Types[types.TUINTPTR])
574 e = NewAddrExpr(pos, e)
575 e.SetType(types.Types[types.TUINTPTR].PtrTo())
576 e = NewConvExpr(pos, OCONVNOP, types.Types[types.TUINTPTR], e)
577 e.SetTypecheck(1)
578 return e
579 }
580
581
582 if wantABI != obj.ABIInternal {
583 base.ErrorfAt(pos, 0, "internal/abi.FuncPC%s does not accept func expression, which is ABIInternal", wantABI)
584 }
585 var e Node = NewUnaryExpr(pos, OIDATA, n)
586 e.SetType(types.Types[types.TUINTPTR].PtrTo())
587 e.SetTypecheck(1)
588 e = NewStarExpr(pos, e)
589 e.SetType(types.Types[types.TUINTPTR])
590 e.SetTypecheck(1)
591 return e
592 }
593
594
595
596
597
598
599 func (fn *Func) DeclareParams(setNname bool) {
600 if fn.Dcl != nil {
601 base.FatalfAt(fn.Pos(), "%v already has Dcl", fn)
602 }
603
604 declareParams := func(params []*types.Field, ctxt Class, prefix string, offset int) {
605 for i, param := range params {
606 sym := param.Sym
607 if sym == nil || sym.IsBlank() {
608 sym = fn.Sym().Pkg.LookupNum(prefix, i)
609 }
610
611 name := NewNameAt(param.Pos, sym, param.Type)
612 name.Class = ctxt
613 name.Curfn = fn
614 fn.Dcl[offset+i] = name
615
616 if setNname {
617 param.Nname = name
618 }
619 }
620 }
621
622 sig := fn.Type()
623 params := sig.RecvParams()
624 results := sig.Results()
625
626 fn.Dcl = make([]*Name, len(params)+len(results))
627 declareParams(params, PPARAM, "~p", 0)
628 declareParams(results, PPARAMOUT, "~r", len(params))
629 }
630
View as plain text