summaryrefslogtreecommitdiffstats
path: root/src/cmd/compile/internal/ir/abi.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/compile/internal/ir/abi.go')
-rw-r--r--src/cmd/compile/internal/ir/abi.go78
1 files changed, 78 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/ir/abi.go b/src/cmd/compile/internal/ir/abi.go
new file mode 100644
index 0000000..ebe0fbf
--- /dev/null
+++ b/src/cmd/compile/internal/ir/abi.go
@@ -0,0 +1,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())
+}