]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: add intrinsic for reading caller's pc
authorDavid Chase <drchase@google.com>
Mon, 24 Oct 2016 14:25:05 +0000 (10:25 -0400)
committerDavid Chase <drchase@google.com>
Fri, 22 Sep 2017 18:37:03 +0000 (18:37 +0000)
First step towards removing the mandatory argument for
getcallerpc, which solves certain problems for the runtime.
This might also slightly improve performance.

Intrinsic enabled on 386, amd64, amd64p32,
runtime asm implementation removed on those architectures.

Now-superfluous argument remains in getcallerpc signature
(for a future CL; non-386/amd64 asm funcs ignore it).

Added getcallerpc to the "not a real function" test
in dcl.go, that story is a little odd with respect to
unexported functions but that is not this CL.

Fixes #17327.

Change-Id: I5df1ad91f27ee9ac1f0dd88fa48f1329d6306c3e
Reviewed-on: https://go-review.googlesource.com/31851
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
16 files changed:
src/cmd/compile/internal/amd64/ssa.go
src/cmd/compile/internal/gc/dcl.go
src/cmd/compile/internal/gc/ssa.go
src/cmd/compile/internal/ssa/gen/386.rules
src/cmd/compile/internal/ssa/gen/386Ops.go
src/cmd/compile/internal/ssa/gen/AMD64.rules
src/cmd/compile/internal/ssa/gen/AMD64Ops.go
src/cmd/compile/internal/ssa/gen/genericOps.go
src/cmd/compile/internal/ssa/opGen.go
src/cmd/compile/internal/ssa/rewrite386.go
src/cmd/compile/internal/ssa/rewriteAMD64.go
src/cmd/compile/internal/x86/ssa.go
src/runtime/asm_386.s
src/runtime/asm_amd64.s
src/runtime/asm_amd64p32.s
src/runtime/stubs.go

index 8c92f07320036bf18ea31a452563b767cd6cf192..22e69aa51488a54c11db826ce625024a85815363 100644 (file)
@@ -795,6 +795,15 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
                }
        case ssa.OpAMD64CALLstatic, ssa.OpAMD64CALLclosure, ssa.OpAMD64CALLinter:
                s.Call(v)
+
+       case ssa.OpAMD64LoweredGetCallerPC:
+               p := s.Prog(x86.AMOVQ)
+               p.From.Type = obj.TYPE_MEM
+               p.From.Offset = -8 // PC is stored 8 bytes below first parameter.
+               p.From.Name = obj.NAME_PARAM
+               p.To.Type = obj.TYPE_REG
+               p.To.Reg = v.Reg()
+
        case ssa.OpAMD64NEGQ, ssa.OpAMD64NEGL,
                ssa.OpAMD64BSWAPQ, ssa.OpAMD64BSWAPL,
                ssa.OpAMD64NOTQ, ssa.OpAMD64NOTL:
index 66caf2d943c3c814cdbf886ba933cf9e867118dd..cf91f537099b28fe8dd6a35659be93807ab1fd70 100644 (file)
@@ -1077,9 +1077,9 @@ func makefuncsym(s *types.Sym) {
        if s.IsBlank() {
                return
        }
-       if compiling_runtime && (s.Name == "getg" || s.Name == "getclosureptr") {
-               // runtime.getg() and getclosureptr are not real functions and so do not
-               // get funcsyms.
+       if compiling_runtime && (s.Name == "getg" || s.Name == "getclosureptr" || s.Name == "getcallerpc") {
+               // runtime.getg(), getclosureptr(), and getcallerpc() are
+               // not real functions and so do not get funcsyms.
                return
        }
        if _, existed := s.Pkg.LookupOK(funcsymname(s)); !existed {
index 94446d88e4ec01f040c3f7da6e207dcc581466c6..1a960497abc33ff3379e80d9e5f17207ee08f1d9 100644 (file)
@@ -2584,6 +2584,11 @@ func init() {
                },
                all...)
 
+       addF("runtime", "getcallerpc",
+               func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
+                       return s.newValue0(ssa.OpGetCallerPC, s.f.Config.Types.Uintptr)
+               }, sys.AMD64, sys.I386)
+
        /******** runtime/internal/sys ********/
        addF("runtime/internal/sys", "Ctz32",
                func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
@@ -2614,7 +2619,6 @@ func init() {
                        return s.newValue1(ssa.OpSelect0, types.Types[TUINT32], v)
                },
                sys.AMD64, sys.ARM64, sys.S390X, sys.MIPS, sys.PPC64)
-
        addF("runtime/internal/atomic", "Load64",
                func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
                        v := s.newValue2(ssa.OpAtomicLoad64, types.NewTuple(types.Types[TUINT64], types.TypeMem), args[0], s.mem())
index 49fcd365302354f2966ef6d620796179b1c1f3ff..c961c0f7206c33f24ec67119385af901a9141ff4 100644 (file)
 (NilCheck ptr mem) -> (LoweredNilCheck ptr mem)
 (GetG mem) -> (LoweredGetG mem)
 (GetClosurePtr) -> (LoweredGetClosurePtr)
+(GetCallerPC) -> (LoweredGetCallerPC)
 (Addr {sym} base) -> (LEAL {sym} base)
 
 // block rewrites
index 25f3931c20629e9afb55b35c1a4e88b8bb7be790..bea80fd47d6ce3ccd1797545f08f09a2e94e6d28 100644 (file)
@@ -440,6 +440,11 @@ func init() {
                // and sorts it to the very beginning of the block to prevent other
                // use of DX (the closure pointer)
                {name: "LoweredGetClosurePtr", reg: regInfo{outputs: []regMask{buildReg("DX")}}},
+               // LoweredGetCallerPC evaluates to the PC to which its "caller" will return.
+               // I.e., if f calls g "calls" getcallerpc,
+               // the result should be the PC within f that g will return to.
+               // See runtime/stubs.go for a more detailed discussion.
+               {name: "LoweredGetCallerPC", reg: gp01},
                //arg0=ptr,arg1=mem, returns void.  Faults if ptr is nil.
                {name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{gpsp}}, clobberFlags: true, nilCheck: true, faultOnNilArg0: true},
 
index e4321cbbcb9c4b9fbcf91ccf553a0c24104d7ec0..724b921e8222e67d9db4e7df32d6fe726f78224a 100644 (file)
 (NilCheck ptr mem) -> (LoweredNilCheck ptr mem)
 (GetG mem) -> (LoweredGetG mem)
 (GetClosurePtr) -> (LoweredGetClosurePtr)
+(GetCallerPC) -> (LoweredGetCallerPC)
 (Addr {sym} base) && config.PtrSize == 8 -> (LEAQ {sym} base)
 (Addr {sym} base) && config.PtrSize == 4 -> (LEAL {sym} base)
 
index 8390fd0c88126168a735ae8bc93f1e30acce602d..51dc3d33ee4cb566d6b112d0bd9d6f130a9f4353 100644 (file)
@@ -540,6 +540,11 @@ func init() {
                // and sorts it to the very beginning of the block to prevent other
                // use of DX (the closure pointer)
                {name: "LoweredGetClosurePtr", reg: regInfo{outputs: []regMask{buildReg("DX")}}},
+               // LoweredGetCallerPC evaluates to the PC to which its "caller" will return.
+               // I.e., if f calls g "calls" getcallerpc,
+               // the result should be the PC within f that g will return to.
+               // See runtime/stubs.go for a more detailed discussion.
+               {name: "LoweredGetCallerPC", reg: gp01},
                //arg0=ptr,arg1=mem, returns void.  Faults if ptr is nil.
                {name: "LoweredNilCheck", argLength: 2, reg: regInfo{inputs: []regMask{gpsp}}, clobberFlags: true, nilCheck: true, faultOnNilArg0: true},
 
index 2967d2994142751978bfecf8f640f086e8406e5f..bec7ef97d56cc282ff86498365f8d5ed4ddb7e83 100644 (file)
@@ -378,6 +378,7 @@ var genericOps = []opData{
        // Pseudo-ops
        {name: "GetG", argLength: 1}, // runtime.getg() (read g pointer). arg0=mem
        {name: "GetClosurePtr"},      // get closure pointer from dedicated register
+       {name: "GetCallerPC"},        // for getcallerpc intrinsic
 
        // Indexing operations
        {name: "PtrIndex", argLength: 2},             // arg0=ptr, arg1=index. Computes ptr+sizeof(*v.type)*index, where index is extended to ptrwidth type
index 1f0138b610adda9007191d69d0fd91401a6bf273..39b9be3e116168fa2c7b20daddaec4507b4e2465 100644 (file)
@@ -396,6 +396,7 @@ const (
        Op386InvertFlags
        Op386LoweredGetG
        Op386LoweredGetClosurePtr
+       Op386LoweredGetCallerPC
        Op386LoweredNilCheck
        Op386MOVLconvert
        Op386FlagEQ
@@ -653,6 +654,7 @@ const (
        OpAMD64InvertFlags
        OpAMD64LoweredGetG
        OpAMD64LoweredGetClosurePtr
+       OpAMD64LoweredGetCallerPC
        OpAMD64LoweredNilCheck
        OpAMD64MOVQconvert
        OpAMD64MOVLconvert
@@ -1905,6 +1907,7 @@ const (
        OpNilCheck
        OpGetG
        OpGetClosurePtr
+       OpGetCallerPC
        OpPtrIndex
        OpOffPtr
        OpSliceMake
@@ -4286,6 +4289,15 @@ var opcodeTable = [...]opInfo{
                        },
                },
        },
+       {
+               name:   "LoweredGetCallerPC",
+               argLen: 0,
+               reg: regInfo{
+                       outputs: []outputInfo{
+                               {0, 239}, // AX CX DX BX BP SI DI
+                       },
+               },
+       },
        {
                name:           "LoweredNilCheck",
                argLen:         2,
@@ -7914,6 +7926,15 @@ var opcodeTable = [...]opInfo{
                        },
                },
        },
+       {
+               name:   "LoweredGetCallerPC",
+               argLen: 0,
+               reg: regInfo{
+                       outputs: []outputInfo{
+                               {0, 65519}, // AX CX DX BX BP SI DI R8 R9 R10 R11 R12 R13 R14 R15
+                       },
+               },
+       },
        {
                name:           "LoweredNilCheck",
                argLen:         2,
@@ -22834,6 +22855,11 @@ var opcodeTable = [...]opInfo{
                argLen:  0,
                generic: true,
        },
+       {
+               name:    "GetCallerPC",
+               argLen:  0,
+               generic: true,
+       },
        {
                name:    "PtrIndex",
                argLen:  2,
index 6726dbd0f5667acf903470aea7fedf05c0e10fa9..b363dd3f18299e27c724eb898c56cb06940bee67 100644 (file)
@@ -329,6 +329,8 @@ func rewriteValue386(v *Value) bool {
                return rewriteValue386_OpGeq8_0(v)
        case OpGeq8U:
                return rewriteValue386_OpGeq8U_0(v)
+       case OpGetCallerPC:
+               return rewriteValue386_OpGetCallerPC_0(v)
        case OpGetClosurePtr:
                return rewriteValue386_OpGetClosurePtr_0(v)
        case OpGetG:
@@ -15052,6 +15054,15 @@ func rewriteValue386_OpGeq8U_0(v *Value) bool {
                return true
        }
 }
+func rewriteValue386_OpGetCallerPC_0(v *Value) bool {
+       // match: (GetCallerPC)
+       // cond:
+       // result: (LoweredGetCallerPC)
+       for {
+               v.reset(Op386LoweredGetCallerPC)
+               return true
+       }
+}
 func rewriteValue386_OpGetClosurePtr_0(v *Value) bool {
        // match: (GetClosurePtr)
        // cond:
index 01d2f883c61ab555895ac34d8537eb9b8d02d851..60d68db23d37545b990b6d0f44e1f6886f58f41e 100644 (file)
@@ -563,6 +563,8 @@ func rewriteValueAMD64(v *Value) bool {
                return rewriteValueAMD64_OpGeq8_0(v)
        case OpGeq8U:
                return rewriteValueAMD64_OpGeq8U_0(v)
+       case OpGetCallerPC:
+               return rewriteValueAMD64_OpGetCallerPC_0(v)
        case OpGetClosurePtr:
                return rewriteValueAMD64_OpGetClosurePtr_0(v)
        case OpGetG:
@@ -40851,6 +40853,15 @@ func rewriteValueAMD64_OpGeq8U_0(v *Value) bool {
                return true
        }
 }
+func rewriteValueAMD64_OpGetCallerPC_0(v *Value) bool {
+       // match: (GetCallerPC)
+       // cond:
+       // result: (LoweredGetCallerPC)
+       for {
+               v.reset(OpAMD64LoweredGetCallerPC)
+               return true
+       }
+}
 func rewriteValueAMD64_OpGetClosurePtr_0(v *Value) bool {
        // match: (GetClosurePtr)
        // cond:
index ca430d681be834b8d4851b815a50b4d595927c17..12cbac63bb318d20530294ba42c40e55718c2114 100644 (file)
@@ -666,6 +666,15 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
                        q.To.Type = obj.TYPE_REG
                        q.To.Reg = r
                }
+
+       case ssa.Op386LoweredGetCallerPC:
+               p := s.Prog(x86.AMOVL)
+               p.From.Type = obj.TYPE_MEM
+               p.From.Offset = -4 // PC is stored 4 bytes below first parameter.
+               p.From.Name = obj.NAME_PARAM
+               p.To.Type = obj.TYPE_REG
+               p.To.Reg = v.Reg()
+
        case ssa.Op386CALLstatic, ssa.Op386CALLclosure, ssa.Op386CALLinter:
                s.Call(v)
        case ssa.Op386NEGL,
index 76758686e52508fd6e9a2ffccae9144dc053bf86..f3b927f0b7001f0d64df70522c1669285258bccb 100644 (file)
@@ -849,12 +849,6 @@ TEXT runtime·stackcheck(SB), NOSPLIT, $0-0
        INT     $3
        RET
 
-TEXT runtime·getcallerpc(SB),NOSPLIT,$4-8
-       MOVL    argp+0(FP),AX           // addr of first arg
-       MOVL    -4(AX),AX               // get calling pc
-       MOVL    AX, ret+4(FP)
-       RET
-
 // func cputicks() int64
 TEXT runtime·cputicks(SB),NOSPLIT,$0-8
        CMPB    runtime·support_sse2(SB), $1
index f99227679410aaf7438adbfc0475b5cc4ad2cd8f..d87f454e03943b7774ba3cef1491257d85c53b28 100644 (file)
@@ -833,12 +833,6 @@ TEXT runtime·stackcheck(SB), NOSPLIT, $0-0
        INT     $3
        RET
 
-TEXT runtime·getcallerpc(SB),NOSPLIT,$8-16
-       MOVQ    argp+0(FP),AX           // addr of first arg
-       MOVQ    -8(AX),AX               // get calling pc
-       MOVQ    AX, ret+8(FP)
-       RET
-
 // func cputicks() int64
 TEXT runtime·cputicks(SB),NOSPLIT,$0-0
        CMPB    runtime·lfenceBeforeRdtsc(SB), $1
index 6777ad03b9793f4c7aad39dacdbbaf106bb35354..c80a563bdac1c01b34143d2e6b068ef656fd5ec5 100644 (file)
@@ -559,12 +559,6 @@ TEXT runtime·stackcheck(SB), NOSPLIT, $0-0
        MOVL    0, AX
        RET
 
-TEXT runtime·getcallerpc(SB),NOSPLIT,$8-12
-       MOVL    argp+0(FP),AX           // addr of first arg
-       MOVL    -8(AX),AX               // get calling pc
-       MOVL    AX, ret+8(FP)
-       RET
-
 // int64 runtime·cputicks(void)
 TEXT runtime·cputicks(SB),NOSPLIT,$0-0
        RDTSC
index 331fc0d518b76aa321f4e0bad57e9924e7126434..65f1695ec4766e3b53ba62b97deb9dcdb782e6c6 100644 (file)
@@ -200,7 +200,9 @@ func publicationBarrier()
 // getcallersp returns the stack pointer (SP) of its caller's caller.
 // For both, the argp must be a pointer to the caller's first function argument.
 // The implementation may or may not use argp, depending on
-// the architecture.
+// the architecture. The implementation may be a compiler
+// intrinsic; there is not necessarily code implementing this
+// on every platform.
 //
 // For example:
 //