2022-09-09 16:23:39 -04:00
|
|
|
// 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)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-02 03:36:51 +00:00
|
|
|
// setupTextLSym initializes the LSym for a with-body text symbol.
|
2022-09-09 16:23:39 -04:00
|
|
|
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.ReflectMethod() {
|
|
|
|
|
flag |= obj.REFLECTMETHOD
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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)
|
|
|
|
|
}
|