aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/ssa
diff options
context:
space:
mode:
authorHeschi Kreinick <heschi@google.com>2017-07-21 18:28:06 -0400
committerHeschi Kreinick <heschi@google.com>2017-07-26 18:39:39 +0000
commit2d57d94ac314fd32529b1b2a92a086cb2dce0057 (patch)
tree45cd9a578da59a9953443ee9c1f4121f24a8d9fa /src/cmd/compile/internal/ssa
parent788aa88cd0c63b75d49a54592e2a467c6183256f (diff)
downloadgo-2d57d94ac314fd32529b1b2a92a086cb2dce0057.tar.gz
go-2d57d94ac314fd32529b1b2a92a086cb2dce0057.zip
[dev.debug] cmd/compile: track variable decomposition in LocalSlot
When the compiler decomposes a user variable, track its origin so that it can be recomposed during DWARF generation. Change-Id: Ia71c7f8e7f4d65f0652f1c97b0dda5d9cad41936 Reviewed-on: https://go-review.googlesource.com/50878 Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
Diffstat (limited to 'src/cmd/compile/internal/ssa')
-rw-r--r--src/cmd/compile/internal/ssa/export_test.go22
-rw-r--r--src/cmd/compile/internal/ssa/location.go26
-rw-r--r--src/cmd/compile/internal/ssa/regalloc.go4
-rw-r--r--src/cmd/compile/internal/ssa/sizeof_test.go1
-rw-r--r--src/cmd/compile/internal/ssa/stackalloc.go2
5 files changed, 38 insertions, 17 deletions
diff --git a/src/cmd/compile/internal/ssa/export_test.go b/src/cmd/compile/internal/ssa/export_test.go
index 3bb67a951b..54cd96beaa 100644
--- a/src/cmd/compile/internal/ssa/export_test.go
+++ b/src/cmd/compile/internal/ssa/export_test.go
@@ -82,33 +82,33 @@ func (DummyFrontend) Auto(pos src.XPos, t *types.Type) GCNode {
return &DummyAuto{t: t, s: "aDummyAuto"}
}
func (d DummyFrontend) SplitString(s LocalSlot) (LocalSlot, LocalSlot) {
- return LocalSlot{s.N, dummyTypes.BytePtr, s.Off}, LocalSlot{s.N, dummyTypes.Int, s.Off + 8}
+ return LocalSlot{N: s.N, Type: dummyTypes.BytePtr, Off: s.Off}, LocalSlot{N: s.N, Type: dummyTypes.Int, Off: s.Off + 8}
}
func (d DummyFrontend) SplitInterface(s LocalSlot) (LocalSlot, LocalSlot) {
- return LocalSlot{s.N, dummyTypes.BytePtr, s.Off}, LocalSlot{s.N, dummyTypes.BytePtr, s.Off + 8}
+ return LocalSlot{N: s.N, Type: dummyTypes.BytePtr, Off: s.Off}, LocalSlot{N: s.N, Type: dummyTypes.BytePtr, Off: s.Off + 8}
}
func (d DummyFrontend) SplitSlice(s LocalSlot) (LocalSlot, LocalSlot, LocalSlot) {
- return LocalSlot{s.N, s.Type.ElemType().PtrTo(), s.Off},
- LocalSlot{s.N, dummyTypes.Int, s.Off + 8},
- LocalSlot{s.N, dummyTypes.Int, s.Off + 16}
+ return LocalSlot{N: s.N, Type: s.Type.ElemType().PtrTo(), Off: s.Off},
+ LocalSlot{N: s.N, Type: dummyTypes.Int, Off: s.Off + 8},
+ LocalSlot{N: s.N, Type: dummyTypes.Int, Off: s.Off + 16}
}
func (d DummyFrontend) SplitComplex(s LocalSlot) (LocalSlot, LocalSlot) {
if s.Type.Size() == 16 {
- return LocalSlot{s.N, dummyTypes.Float64, s.Off}, LocalSlot{s.N, dummyTypes.Float64, s.Off + 8}
+ return LocalSlot{N: s.N, Type: dummyTypes.Float64, Off: s.Off}, LocalSlot{N: s.N, Type: dummyTypes.Float64, Off: s.Off + 8}
}
- return LocalSlot{s.N, dummyTypes.Float32, s.Off}, LocalSlot{s.N, dummyTypes.Float32, s.Off + 4}
+ return LocalSlot{N: s.N, Type: dummyTypes.Float32, Off: s.Off}, LocalSlot{N: s.N, Type: dummyTypes.Float32, Off: s.Off + 4}
}
func (d DummyFrontend) SplitInt64(s LocalSlot) (LocalSlot, LocalSlot) {
if s.Type.IsSigned() {
- return LocalSlot{s.N, dummyTypes.Int32, s.Off + 4}, LocalSlot{s.N, dummyTypes.UInt32, s.Off}
+ return LocalSlot{N: s.N, Type: dummyTypes.Int32, Off: s.Off + 4}, LocalSlot{N: s.N, Type: dummyTypes.UInt32, Off: s.Off}
}
- return LocalSlot{s.N, dummyTypes.UInt32, s.Off + 4}, LocalSlot{s.N, dummyTypes.UInt32, s.Off}
+ return LocalSlot{N: s.N, Type: dummyTypes.UInt32, Off: s.Off + 4}, LocalSlot{N: s.N, Type: dummyTypes.UInt32, Off: s.Off}
}
func (d DummyFrontend) SplitStruct(s LocalSlot, i int) LocalSlot {
- return LocalSlot{s.N, s.Type.FieldType(i), s.Off + s.Type.FieldOff(i)}
+ return LocalSlot{N: s.N, Type: s.Type.FieldType(i), Off: s.Off + s.Type.FieldOff(i)}
}
func (d DummyFrontend) SplitArray(s LocalSlot) LocalSlot {
- return LocalSlot{s.N, s.Type.ElemType(), s.Off}
+ return LocalSlot{N: s.N, Type: s.Type.ElemType(), Off: s.Off}
}
func (DummyFrontend) Line(_ src.XPos) string {
return "unknown.go:0"
diff --git a/src/cmd/compile/internal/ssa/location.go b/src/cmd/compile/internal/ssa/location.go
index 41b48947aa..70afa47e9d 100644
--- a/src/cmd/compile/internal/ssa/location.go
+++ b/src/cmd/compile/internal/ssa/location.go
@@ -26,12 +26,32 @@ func (r *Register) Name() string {
return r.name
}
-// A LocalSlot is a location in the stack frame.
-// It is (possibly a subpiece of) a PPARAM, PPARAMOUT, or PAUTO ONAME node.
+// A LocalSlot is a location in the stack frame, which identifies and stores
+// part or all of a PPARAM, PPARAMOUT, or PAUTO ONAME node.
+// It can represent a whole variable, part of a larger stack slot, or part of a
+// variable that has been decomposed into multiple stack slots.
+// As an example, a string could have the following configurations:
+//
+// stack layout LocalSlots
+//
+// Optimizations are disabled. s is on the stack and represented in its entirety.
+// [ ------- s string ---- ] { N: s, Type: string, Off: 0 }
+//
+// s was not decomposed, but the SSA operates on its parts individually, so
+// there is a LocalSlot for each of its fields that points into the single stack slot.
+// [ ------- s string ---- ] { N: s, Type: *uint8, Off: 0 }, {N: s, Type: int, Off: 8}
+//
+// s was decomposed. Each of its fields is in its own stack slot and has its own LocalSLot.
+// [ ptr *uint8 ] [ len int] { N: ptr, Type: *uint8, Off: 0, SplitOf: parent, SplitOffset: 0},
+// { N: len, Type: int, Off: 0, SplitOf: parent, SplitOffset: 8}
+// parent = &{N: s, Type: string}
type LocalSlot struct {
- N GCNode // an ONAME *gc.Node representing a variable on the stack
+ N GCNode // an ONAME *gc.Node representing a stack location.
Type *types.Type // type of slot
Off int64 // offset of slot in N
+
+ SplitOf *LocalSlot // slot is a decomposition of SplitOf
+ SplitOffset int64 // .. at this offset.
}
func (s LocalSlot) Name() string {
diff --git a/src/cmd/compile/internal/ssa/regalloc.go b/src/cmd/compile/internal/ssa/regalloc.go
index 137e5fc4c2..e297e6bce7 100644
--- a/src/cmd/compile/internal/ssa/regalloc.go
+++ b/src/cmd/compile/internal/ssa/regalloc.go
@@ -2118,8 +2118,8 @@ func (e *edgeState) findRegFor(typ *types.Type) Location {
// Allocate a temp location to spill a register to.
// The type of the slot is immaterial - it will not be live across
// any safepoint. Just use a type big enough to hold any register.
- t := LocalSlot{e.s.f.fe.Auto(c.Pos, types.Int64), types.Int64, 0}
- // TODO: reuse these slots.
+ t := LocalSlot{N: e.s.f.fe.Auto(c.Pos, types.Int64), Type: types.Int64}
+ // TODO: reuse these slots. They'll need to be erased first.
e.set(t, vid, x, false, c.Pos)
if e.s.f.pass.debug > regDebug {
fmt.Printf(" SPILL %s->%s %s\n", r.Name(), t.Name(), x.LongString())
diff --git a/src/cmd/compile/internal/ssa/sizeof_test.go b/src/cmd/compile/internal/ssa/sizeof_test.go
index 9fab7b664f..f8bbed91b4 100644
--- a/src/cmd/compile/internal/ssa/sizeof_test.go
+++ b/src/cmd/compile/internal/ssa/sizeof_test.go
@@ -24,6 +24,7 @@ func TestSizeof(t *testing.T) {
}{
{Value{}, 68, 112},
{Block{}, 152, 288},
+ {LocalSlot{}, 32, 48},
{valState{}, 28, 40},
}
diff --git a/src/cmd/compile/internal/ssa/stackalloc.go b/src/cmd/compile/internal/ssa/stackalloc.go
index 3b44986eee..341bb7b871 100644
--- a/src/cmd/compile/internal/ssa/stackalloc.go
+++ b/src/cmd/compile/internal/ssa/stackalloc.go
@@ -151,7 +151,7 @@ func (s *stackAllocState) stackalloc() {
if v.Op != OpArg {
continue
}
- loc := LocalSlot{v.Aux.(GCNode), v.Type, v.AuxInt}
+ loc := LocalSlot{N: v.Aux.(GCNode), Type: v.Type, Off: v.AuxInt}
if f.pass.debug > stackDebug {
fmt.Printf("stackalloc %s to %s\n", v, loc.Name())
}