fn.Pkg.Path == "internal/abi"
}
+// IsIfaceOfFunc inspects whether n is an interface conversion from a direct
+// reference of a func. If so, it returns referenced Func; otherwise nil.
+//
+// This is only usable before walk.walkConvertInterface, which converts to an
+// OMAKEFACE.
+func IsIfaceOfFunc(n Node) *Func {
+ if n, ok := n.(*ConvExpr); ok && n.Op() == OCONVIFACE {
+ if name, ok := n.X.(*Name); ok && name.Op() == ONAME && name.Class == PFUNC {
+ return name.Func
+ }
+ }
+ return nil
+}
+
+// FuncPC returns a uintptr-typed expression that evaluates to the PC of a
+// function as uintptr, as returned by internal/abi.FuncPC{ABI0,ABIInternal}.
+//
+// n should be a Node of an interface type, as is passed to
+// internal/abi.FuncPC{ABI0,ABIInternal}.
+//
+// TODO(prattmic): Since n is simply an interface{} there is no assertion that
+// it is actually a function at all. Perhaps we should emit a runtime type
+// assertion?
+func FuncPC(pos src.XPos, n Node, wantABI obj.ABI) Node {
+ if !n.Type().IsInterface() {
+ base.ErrorfAt(pos, 0, "internal/abi.FuncPC%s expects an interface value, got %v", wantABI, n.Type())
+ }
+
+ if fn := IsIfaceOfFunc(n); fn != nil {
+ name := fn.Nname
+ abi := fn.ABI
+ if abi != wantABI {
+ base.ErrorfAt(pos, 0, "internal/abi.FuncPC%s expects an %v function, %s is defined as %v", wantABI, wantABI, name.Sym().Name, abi)
+ }
+ var e Node = NewLinksymExpr(pos, name.Sym().LinksymABI(abi), types.Types[types.TUINTPTR])
+ e = NewAddrExpr(pos, e)
+ e.SetType(types.Types[types.TUINTPTR].PtrTo())
+ e = NewConvExpr(pos, OCONVNOP, types.Types[types.TUINTPTR], e)
+ e.SetTypecheck(1)
+ return e
+ }
+ // fn is not a defined function. It must be ABIInternal.
+ // Read the address from func value, i.e. *(*uintptr)(idata(fn)).
+ if wantABI != obj.ABIInternal {
+ base.ErrorfAt(pos, 0, "internal/abi.FuncPC%s does not accept func expression, which is ABIInternal", wantABI)
+ }
+ var e Node = NewUnaryExpr(pos, OIDATA, n)
+ e.SetType(types.Types[types.TUINTPTR].PtrTo())
+ e.SetTypecheck(1)
+ e = NewStarExpr(pos, e)
+ e.SetType(types.Types[types.TUINTPTR])
+ e.SetTypecheck(1)
+ return e
+}
+
// DeclareParams creates Names for all of the parameters in fn's
// signature and adds them to fn.Dcl.
//