Skip to content

Commit

Permalink
cmd/compile: set/unset base register for better assembly print
Browse files Browse the repository at this point in the history
For address of an auto or arg, on all non-x86 architectures
the assembler backend encodes the actual SP offset in the
instruction but leaves the offset in Prog unchanged. When the
assembly is printed in compile -S, it shows an offset
relative to pseudo FP/SP with an actual hardware SP base
register (e.g. R13 on ARM). This is confusing. Unset the
base register if it is indeed SP, so the assembly output is
consistent. If the base register isn't SP, it should be an
error and the error output contains the actual base register.

For address loading instructions, the base register isn't set
in the compiler on non-x86 architectures. Set it. Normally it
is SP and will be unset in the change mentioned above for
printing. If it is not, it will be an error and the error
output contains the actual base register.

No change in generated binary, only printed assembly. Passes
"go build -a -toolexec 'toolstash -cmp' std cmd" on all
architectures.

Fixes #21064.

Change-Id: Ifafe8d5f9b437efbe824b63b3cbc2f5f6cdc1fd5
Reviewed-on: https://go-review.googlesource.com/49432
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
  • Loading branch information
cherrymui committed Aug 2, 2017
1 parent 623e2c4 commit f20944d
Show file tree
Hide file tree
Showing 11 changed files with 128 additions and 6 deletions.
2 changes: 1 addition & 1 deletion src/cmd/compile/internal/arm/ssa.go
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
case ssa.OpARMMOVWaddr:
p := s.Prog(arm.AMOVW)
p.From.Type = obj.TYPE_ADDR
p.From.Reg = v.Args[0].Reg()
p.To.Type = obj.TYPE_REG
p.To.Reg = v.Reg()

Expand All @@ -485,7 +486,6 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
case nil:
// No sym, just MOVW $off(SP), R
wantreg = "SP"
p.From.Reg = arm.REGSP
p.From.Offset = v.AuxInt
}
if reg := v.Args[0].RegName(); reg != wantreg {
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/compile/internal/arm64/ssa.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
case ssa.OpARM64MOVDaddr:
p := s.Prog(arm64.AMOVD)
p.From.Type = obj.TYPE_ADDR
p.From.Reg = v.Args[0].Reg()
p.To.Type = obj.TYPE_REG
p.To.Reg = v.Reg()

Expand All @@ -281,7 +282,6 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
case nil:
// No sym, just MOVD $off(SP), R
wantreg = "SP"
p.From.Reg = arm64.REGSP
p.From.Offset = v.AuxInt
}
if reg := v.Args[0].RegName(); reg != wantreg {
Expand Down
24 changes: 23 additions & 1 deletion src/cmd/compile/internal/gc/asm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -898,6 +898,17 @@ var linuxAMD64Tests = []*asmTest{
}`,
[]string{"\tCMPL\t[A-Z]"},
},
{
// make sure assembly output has matching offset and base register.
`
func f72(a, b int) int {
var x [16]byte // use some frame
_ = x
return b
}
`,
[]string{"b\\+40\\(SP\\)"},
},
}

var linux386Tests = []*asmTest{
Expand Down Expand Up @@ -1302,6 +1313,17 @@ var linuxARMTests = []*asmTest{
`,
[]string{"\tCLZ\t"},
},
{
// make sure assembly output has matching offset and base register.
`
func f13(a, b int) int {
var x [16]byte // use some frame
_ = x
return b
}
`,
[]string{"b\\+4\\(FP\\)"},
},
}

var linuxARM64Tests = []*asmTest{
Expand Down Expand Up @@ -1473,7 +1495,7 @@ var linuxARM64Tests = []*asmTest{
return
}
`,
[]string{"\tMOVD\t\"\"\\.a\\+[0-9]+\\(RSP\\), R[0-9]+", "\tMOVD\tR[0-9]+, \"\"\\.b\\+[0-9]+\\(RSP\\)"},
[]string{"\tMOVD\t\"\"\\.a\\+[0-9]+\\(FP\\), R[0-9]+", "\tMOVD\tR[0-9]+, \"\"\\.b\\+[0-9]+\\(FP\\)"},
},
}

Expand Down
2 changes: 1 addition & 1 deletion src/cmd/compile/internal/mips/ssa.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
case ssa.OpMIPSMOVWaddr:
p := s.Prog(mips.AMOVW)
p.From.Type = obj.TYPE_ADDR
p.From.Reg = v.Args[0].Reg()
var wantreg string
// MOVW $sym+off(base), R
// the assembler expands it as the following:
Expand All @@ -291,7 +292,6 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
case nil:
// No sym, just MOVW $off(SP), R
wantreg = "SP"
p.From.Reg = mips.REGSP
p.From.Offset = v.AuxInt
}
if reg := v.Args[0].RegName(); reg != wantreg {
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/compile/internal/mips64/ssa.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
case ssa.OpMIPS64MOVVaddr:
p := s.Prog(mips.AMOVV)
p.From.Type = obj.TYPE_ADDR
p.From.Reg = v.Args[0].Reg()
var wantreg string
// MOVV $sym+off(base), R
// the assembler expands it as the following:
Expand All @@ -265,7 +266,6 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
case nil:
// No sym, just MOVV $off(SP), R
wantreg = "SP"
p.From.Reg = mips.REGSP
p.From.Offset = v.AuxInt
}
if reg := v.Args[0].RegName(); reg != wantreg {
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/compile/internal/ppc64/ssa.go
Original file line number Diff line number Diff line change
Expand Up @@ -638,6 +638,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
case ssa.OpPPC64MOVDaddr:
p := s.Prog(ppc64.AMOVD)
p.From.Type = obj.TYPE_ADDR
p.From.Reg = v.Args[0].Reg()
p.To.Type = obj.TYPE_REG
p.To.Reg = v.Reg()

Expand All @@ -660,7 +661,6 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
case nil:
// No sym, just MOVD $off(SP), R
wantreg = "SP"
p.From.Reg = ppc64.REGSP
p.From.Offset = v.AuxInt
}
if reg := v.Args[0].RegName(); reg != wantreg {
Expand Down
20 changes: 20 additions & 0 deletions src/cmd/internal/obj/arm/asm5.go
Original file line number Diff line number Diff line change
Expand Up @@ -1167,6 +1167,11 @@ func (c *ctxt5) aclass(a *obj.Addr) int {
return C_ADDR

case obj.NAME_AUTO:
if a.Reg == REGSP {
// unset base register for better printing, since
// a.Offset is still relative to pseudo-SP.
a.Reg = obj.REG_NONE
}
c.instoffset = c.autosize + a.Offset
if t := immaddr(int32(c.instoffset)); t != 0 {
if immhalf(int32(c.instoffset)) {
Expand All @@ -1185,6 +1190,11 @@ func (c *ctxt5) aclass(a *obj.Addr) int {
return C_LAUTO

case obj.NAME_PARAM:
if a.Reg == REGSP {
// unset base register for better printing, since
// a.Offset is still relative to pseudo-FP.
a.Reg = obj.REG_NONE
}
c.instoffset = c.autosize + a.Offset + 4
if t := immaddr(int32(c.instoffset)); t != 0 {
if immhalf(int32(c.instoffset)) {
Expand Down Expand Up @@ -1285,10 +1295,20 @@ func (c *ctxt5) aclass(a *obj.Addr) int {
return C_LCONADDR

case obj.NAME_AUTO:
if a.Reg == REGSP {
// unset base register for better printing, since
// a.Offset is still relative to pseudo-SP.
a.Reg = obj.REG_NONE
}
c.instoffset = c.autosize + a.Offset
return c.aconsize()

case obj.NAME_PARAM:
if a.Reg == REGSP {
// unset base register for better printing, since
// a.Offset is still relative to pseudo-FP.
a.Reg = obj.REG_NONE
}
c.instoffset = c.autosize + a.Offset + 4
return c.aconsize()
}
Expand Down
20 changes: 20 additions & 0 deletions src/cmd/internal/obj/arm64/asm7.go
Original file line number Diff line number Diff line change
Expand Up @@ -1149,10 +1149,20 @@ func (c *ctxt7) aclass(a *obj.Addr) int {
return C_GOTADDR

case obj.NAME_AUTO:
if a.Reg == REGSP {
// unset base register for better printing, since
// a.Offset is still relative to pseudo-SP.
a.Reg = obj.REG_NONE
}
c.instoffset = int64(c.autosize) + a.Offset
return autoclass(c.instoffset)

case obj.NAME_PARAM:
if a.Reg == REGSP {
// unset base register for better printing, since
// a.Offset is still relative to pseudo-FP.
a.Reg = obj.REG_NONE
}
c.instoffset = int64(c.autosize) + a.Offset + 8
return autoclass(c.instoffset)

Expand Down Expand Up @@ -1228,10 +1238,20 @@ func (c *ctxt7) aclass(a *obj.Addr) int {
return C_VCONADDR

case obj.NAME_AUTO:
if a.Reg == REGSP {
// unset base register for better printing, since
// a.Offset is still relative to pseudo-SP.
a.Reg = obj.REG_NONE
}
c.instoffset = int64(c.autosize) + a.Offset
goto aconsize

case obj.NAME_PARAM:
if a.Reg == REGSP {
// unset base register for better printing, since
// a.Offset is still relative to pseudo-FP.
a.Reg = obj.REG_NONE
}
c.instoffset = int64(c.autosize) + a.Offset + 8
goto aconsize
}
Expand Down
20 changes: 20 additions & 0 deletions src/cmd/internal/obj/mips/asm0.go
Original file line number Diff line number Diff line change
Expand Up @@ -556,13 +556,23 @@ func (c *ctxt0) aclass(a *obj.Addr) int {
return C_LEXT

case obj.NAME_AUTO:
if a.Reg == REGSP {
// unset base register for better printing, since
// a.Offset is still relative to pseudo-SP.
a.Reg = obj.REG_NONE
}
c.instoffset = int64(c.autosize) + a.Offset
if c.instoffset >= -BIG && c.instoffset < BIG {
return C_SAUTO
}
return C_LAUTO

case obj.NAME_PARAM:
if a.Reg == REGSP {
// unset base register for better printing, since
// a.Offset is still relative to pseudo-FP.
a.Reg = obj.REG_NONE
}
c.instoffset = int64(c.autosize) + a.Offset + c.ctxt.FixedFrameSize()
if c.instoffset >= -BIG && c.instoffset < BIG {
return C_SAUTO
Expand Down Expand Up @@ -616,13 +626,23 @@ func (c *ctxt0) aclass(a *obj.Addr) int {
return C_LECON

case obj.NAME_AUTO:
if a.Reg == REGSP {
// unset base register for better printing, since
// a.Offset is still relative to pseudo-SP.
a.Reg = obj.REG_NONE
}
c.instoffset = int64(c.autosize) + a.Offset
if c.instoffset >= -BIG && c.instoffset < BIG {
return C_SACON
}
return C_LACON

case obj.NAME_PARAM:
if a.Reg == REGSP {
// unset base register for better printing, since
// a.Offset is still relative to pseudo-FP.
a.Reg = obj.REG_NONE
}
c.instoffset = int64(c.autosize) + a.Offset + c.ctxt.FixedFrameSize()
if c.instoffset >= -BIG && c.instoffset < BIG {
return C_SACON
Expand Down
20 changes: 20 additions & 0 deletions src/cmd/internal/obj/ppc64/asm9.go
Original file line number Diff line number Diff line change
Expand Up @@ -758,13 +758,23 @@ func (c *ctxt9) aclass(a *obj.Addr) int {
return C_GOTADDR

case obj.NAME_AUTO:
if a.Reg == REGSP {
// unset base register for better printing, since
// a.Offset is still relative to pseudo-SP.
a.Reg = obj.REG_NONE
}
c.instoffset = int64(c.autosize) + a.Offset
if c.instoffset >= -BIG && c.instoffset < BIG {
return C_SAUTO
}
return C_LAUTO

case obj.NAME_PARAM:
if a.Reg == REGSP {
// unset base register for better printing, since
// a.Offset is still relative to pseudo-FP.
a.Reg = obj.REG_NONE
}
c.instoffset = int64(c.autosize) + a.Offset + c.ctxt.FixedFrameSize()
if c.instoffset >= -BIG && c.instoffset < BIG {
return C_SAUTO
Expand Down Expand Up @@ -817,13 +827,23 @@ func (c *ctxt9) aclass(a *obj.Addr) int {
return C_LCON

case obj.NAME_AUTO:
if a.Reg == REGSP {
// unset base register for better printing, since
// a.Offset is still relative to pseudo-SP.
a.Reg = obj.REG_NONE
}
c.instoffset = int64(c.autosize) + a.Offset
if c.instoffset >= -BIG && c.instoffset < BIG {
return C_SACON
}
return C_LACON

case obj.NAME_PARAM:
if a.Reg == REGSP {
// unset base register for better printing, since
// a.Offset is still relative to pseudo-FP.
a.Reg = obj.REG_NONE
}
c.instoffset = int64(c.autosize) + a.Offset + c.ctxt.FixedFrameSize()
if c.instoffset >= -BIG && c.instoffset < BIG {
return C_SACON
Expand Down
20 changes: 20 additions & 0 deletions src/cmd/internal/obj/s390x/asmz.go
Original file line number Diff line number Diff line change
Expand Up @@ -505,13 +505,23 @@ func (c *ctxtz) aclass(a *obj.Addr) int {
return C_GOTADDR

case obj.NAME_AUTO:
if a.Reg == REGSP {
// unset base register for better printing, since
// a.Offset is still relative to pseudo-SP.
a.Reg = obj.REG_NONE
}
c.instoffset = int64(c.autosize) + a.Offset
if c.instoffset >= -BIG && c.instoffset < BIG {
return C_SAUTO
}
return C_LAUTO

case obj.NAME_PARAM:
if a.Reg == REGSP {
// unset base register for better printing, since
// a.Offset is still relative to pseudo-FP.
a.Reg = obj.REG_NONE
}
c.instoffset = int64(c.autosize) + a.Offset + c.ctxt.FixedFrameSize()
if c.instoffset >= -BIG && c.instoffset < BIG {
return C_SAUTO
Expand Down Expand Up @@ -567,13 +577,23 @@ func (c *ctxtz) aclass(a *obj.Addr) int {
return C_SYMADDR

case obj.NAME_AUTO:
if a.Reg == REGSP {
// unset base register for better printing, since
// a.Offset is still relative to pseudo-SP.
a.Reg = obj.REG_NONE
}
c.instoffset = int64(c.autosize) + a.Offset
if c.instoffset >= -BIG && c.instoffset < BIG {
return C_SACON
}
return C_LACON

case obj.NAME_PARAM:
if a.Reg == REGSP {
// unset base register for better printing, since
// a.Offset is still relative to pseudo-FP.
a.Reg = obj.REG_NONE
}
c.instoffset = int64(c.autosize) + a.Offset + c.ctxt.FixedFrameSize()
if c.instoffset >= -BIG && c.instoffset < BIG {
return C_SACON
Expand Down

0 comments on commit f20944d

Please sign in to comment.