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