Source file src/cmd/compile/internal/ir/abi.go

     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  	"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.
    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  }
    79  

View as plain text