1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package ir
import (
"cmd/compile/internal/base"
"cmd/internal/obj"
)
// InitLSym defines f's obj.LSym and initializes it based on the
// properties of f. This includes setting the symbol flags and ABI and
// creating and initializing related DWARF symbols.
//
// InitLSym must be called exactly once per function and must be
// called for both functions with bodies and functions without bodies.
// For body-less functions, we only create the LSym; for functions
// with bodies call a helper to setup up / populate the LSym.
func InitLSym(f *Func, hasBody bool) {
if f.LSym != nil {
base.FatalfAt(f.Pos(), "InitLSym called twice on %v", f)
}
if nam := f.Nname; !IsBlank(nam) {
f.LSym = nam.LinksymABI(f.ABI)
if f.Pragma&Systemstack != 0 {
f.LSym.Set(obj.AttrCFunc, true)
}
}
if hasBody {
setupTextLSym(f, 0)
}
}
// setupTextLSym initializes the LSym for a with-body text symbol.
func setupTextLSym(f *Func, flag int) {
if f.Dupok() {
flag |= obj.DUPOK
}
if f.Wrapper() {
flag |= obj.WRAPPER
}
if f.ABIWrapper() {
flag |= obj.ABIWRAPPER
}
if f.Needctxt() {
flag |= obj.NEEDCTXT
}
if f.Pragma&Nosplit != 0 {
flag |= obj.NOSPLIT
}
if f.IsPackageInit() {
flag |= obj.PKGINIT
}
// Clumsy but important.
// For functions that could be on the path of invoking a deferred
// function that can recover (runtime.reflectcall, reflect.callReflect,
// and reflect.callMethod), we want the panic+recover special handling.
// See test/recover.go for test cases and src/reflect/value.go
// for the actual functions being considered.
//
// runtime.reflectcall is an assembly function which tailcalls
// WRAPPER functions (runtime.callNN). Its ABI wrapper needs WRAPPER
// flag as well.
fnname := f.Sym().Name
if base.Ctxt.Pkgpath == "runtime" && fnname == "reflectcall" {
flag |= obj.WRAPPER
} else if base.Ctxt.Pkgpath == "reflect" {
switch fnname {
case "callReflect", "callMethod":
flag |= obj.WRAPPER
}
}
base.Ctxt.InitTextSym(f.LSym, flag, f.Pos())
}
|