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 5package ir 6 7import ( 8 "cmd/compile/internal/base" 9 "cmd/internal/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. 20func 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. 37func 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} 79