aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Chase <drchase@google.com>2016-10-24 10:25:05 -0400
committerDavid Chase <drchase@google.com>2017-09-22 18:37:03 +0000
commit6cac100eefbe07ffd2c9bf64c9a782bf93d79081 (patch)
tree67dab0b4c4ab04efe4078d29c0b44f1f9eef4b80
parent332719f7cee2abafb3963009d44ad7cc93474707 (diff)
downloadgo-6cac100eefbe07ffd2c9bf64c9a782bf93d79081.tar.xz
cmd/compile: add intrinsic for reading caller's pc
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>
-rw-r--r--src/cmd/compile/internal/amd64/ssa.go9
-rw-r--r--src/cmd/compile/internal/gc/dcl.go6
-rw-r--r--src/cmd/compile/internal/gc/ssa.go6
-rw-r--r--src/cmd/compile/internal/ssa/gen/386.rules1
-rw-r--r--src/cmd/compile/internal/ssa/gen/386Ops.go5
-rw-r--r--src/cmd/compile/internal/ssa/gen/AMD64.rules1
-rw-r--r--src/cmd/compile/internal/ssa/gen/AMD64Ops.go5
-rw-r--r--src/cmd/compile/internal/ssa/gen/genericOps.go1
-rw-r--r--src/cmd/compile/internal/ssa/opGen.go26
-rw-r--r--src/cmd/compile/internal/ssa/rewrite386.go11
-rw-r--r--src/cmd/compile/internal/ssa/rewriteAMD64.go11
-rw-r--r--src/cmd/compile/internal/x86/ssa.go9
-rw-r--r--src/runtime/asm_386.s6
-rw-r--r--src/runtime/asm_amd64.s6
-rw-r--r--src/runtime/asm_amd64p32.s6
-rw-r--r--src/runtime/stubs.go4
16 files changed, 90 insertions, 23 deletions
diff --git a/src/cmd/compile/internal/amd64/ssa.go b/src/cmd/compile/internal/amd64/ssa.go
index 8c92f07320..22e69aa514 100644
--- a/src/cmd/compile/internal/amd64/ssa.go
+++ b/src/cmd/compile/internal/amd64/ssa.go
@@ -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:
diff --git a/src/cmd/compile/internal/gc/dcl.go b/src/cmd/compile/internal/gc/dcl.go
index 66caf2d943..cf91f53709 100644
--- a/src/cmd/compile/internal/gc/dcl.go
+++ b/src/cmd/compile/internal/gc/dcl.go
@@ -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 {
diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go
index 94446d88e4..1a960497ab 100644
--- a/src/cmd/compile/internal/gc/ssa.go
+++ b/src/cmd/compile/internal/gc/ssa.go
@@ -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())
diff --git a/src/cmd/compile/internal/ssa/gen/386.rules b/src/cmd/compile/internal/ssa/gen/386.rules
index 49fcd36530..c961c0f720 100644
--- a/src/cmd/compile/internal/ssa/gen/386.rules
+++ b/src/cmd/compile/internal/ssa/gen/386.rules
@@ -383,6 +383,7 @@
(NilCheck ptr mem) -> (LoweredNilCheck ptr mem)
(GetG mem) -> (LoweredGetG mem)
(GetClosurePtr) -> (LoweredGetClosurePtr)
+(GetCallerPC) -> (LoweredGetCallerPC)
(Addr {sym} base) -> (LEAL {sym} base)
// block rewrites
diff --git a/src/cmd/compile/internal/ssa/gen/386Ops.go b/src/cmd/compile/internal/ssa/gen/386Ops.go
index 25f3931c20..bea80fd47d 100644
--- a/src/cmd/compile/internal/ssa/gen/386Ops.go
+++ b/src/cmd/compile/internal/ssa/gen/386Ops.go
@@ -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},
diff --git a/src/cmd/compile/internal/ssa/gen/AMD64.rules b/src/cmd/compile/internal/ssa/gen/AMD64.rules
index e4321cbbcb..724b921e82 100644
--- a/src/cmd/compile/internal/ssa/gen/AMD64.rules
+++ b/src/cmd/compile/internal/ssa/gen/AMD64.rules
@@ -482,6 +482,7 @@
(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)
diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go
index 8390fd0c88..51dc3d33ee 100644
--- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go
+++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go
@@ -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},
diff --git a/src/cmd/compile/internal/ssa/gen/genericOps.go b/src/cmd/compile/internal/ssa/gen/genericOps.go
index 2967d29941..bec7ef97d5 100644
--- a/src/cmd/compile/internal/ssa/gen/genericOps.go
+++ b/src/cmd/compile/internal/ssa/gen/genericOps.go
@@ -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
diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go
index 1f0138b610..39b9be3e11 100644
--- a/src/cmd/compile/internal/ssa/opGen.go
+++ b/src/cmd/compile/internal/ssa/opGen.go
@@ -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
@@ -4287,6 +4290,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,
clobberFlags: true,
@@ -7915,6 +7927,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,
clobberFlags: true,
@@ -22835,6 +22856,11 @@ var opcodeTable = [...]opInfo{
generic: true,
},
{
+ name: "GetCallerPC",
+ argLen: 0,
+ generic: true,
+ },
+ {
name: "PtrIndex",
argLen: 2,
generic: true,
diff --git a/src/cmd/compile/internal/ssa/rewrite386.go b/src/cmd/compile/internal/ssa/rewrite386.go
index 6726dbd0f5..b363dd3f18 100644
--- a/src/cmd/compile/internal/ssa/rewrite386.go
+++ b/src/cmd/compile/internal/ssa/rewrite386.go
@@ -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:
diff --git a/src/cmd/compile/internal/ssa/rewriteAMD64.go b/src/cmd/compile/internal/ssa/rewriteAMD64.go
index 01d2f883c6..60d68db23d 100644
--- a/src/cmd/compile/internal/ssa/rewriteAMD64.go
+++ b/src/cmd/compile/internal/ssa/rewriteAMD64.go
@@ -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:
diff --git a/src/cmd/compile/internal/x86/ssa.go b/src/cmd/compile/internal/x86/ssa.go
index ca430d681b..12cbac63bb 100644
--- a/src/cmd/compile/internal/x86/ssa.go
+++ b/src/cmd/compile/internal/x86/ssa.go
@@ -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,
diff --git a/src/runtime/asm_386.s b/src/runtime/asm_386.s
index 76758686e5..f3b927f0b7 100644
--- a/src/runtime/asm_386.s
+++ b/src/runtime/asm_386.s
@@ -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
diff --git a/src/runtime/asm_amd64.s b/src/runtime/asm_amd64.s
index f992276794..d87f454e03 100644
--- a/src/runtime/asm_amd64.s
+++ b/src/runtime/asm_amd64.s
@@ -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
diff --git a/src/runtime/asm_amd64p32.s b/src/runtime/asm_amd64p32.s
index 6777ad03b9..c80a563bda 100644
--- a/src/runtime/asm_amd64p32.s
+++ b/src/runtime/asm_amd64p32.s
@@ -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
diff --git a/src/runtime/stubs.go b/src/runtime/stubs.go
index 331fc0d518..65f1695ec4 100644
--- a/src/runtime/stubs.go
+++ b/src/runtime/stubs.go
@@ -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:
//