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