Skip to content

Commit f20944d

Browse files
committed
cmd/compile: set/unset base register for better assembly print
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 <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: David Chase <[email protected]>
1 parent 623e2c4 commit f20944d

File tree

11 files changed

+128
-6
lines changed

11 files changed

+128
-6
lines changed

src/cmd/compile/internal/arm/ssa.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
464464
case ssa.OpARMMOVWaddr:
465465
p := s.Prog(arm.AMOVW)
466466
p.From.Type = obj.TYPE_ADDR
467+
p.From.Reg = v.Args[0].Reg()
467468
p.To.Type = obj.TYPE_REG
468469
p.To.Reg = v.Reg()
469470

@@ -485,7 +486,6 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
485486
case nil:
486487
// No sym, just MOVW $off(SP), R
487488
wantreg = "SP"
488-
p.From.Reg = arm.REGSP
489489
p.From.Offset = v.AuxInt
490490
}
491491
if reg := v.Args[0].RegName(); reg != wantreg {

src/cmd/compile/internal/arm64/ssa.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
260260
case ssa.OpARM64MOVDaddr:
261261
p := s.Prog(arm64.AMOVD)
262262
p.From.Type = obj.TYPE_ADDR
263+
p.From.Reg = v.Args[0].Reg()
263264
p.To.Type = obj.TYPE_REG
264265
p.To.Reg = v.Reg()
265266

@@ -281,7 +282,6 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
281282
case nil:
282283
// No sym, just MOVD $off(SP), R
283284
wantreg = "SP"
284-
p.From.Reg = arm64.REGSP
285285
p.From.Offset = v.AuxInt
286286
}
287287
if reg := v.Args[0].RegName(); reg != wantreg {

src/cmd/compile/internal/gc/asm_test.go

+23-1
Original file line numberDiff line numberDiff line change
@@ -898,6 +898,17 @@ var linuxAMD64Tests = []*asmTest{
898898
}`,
899899
[]string{"\tCMPL\t[A-Z]"},
900900
},
901+
{
902+
// make sure assembly output has matching offset and base register.
903+
`
904+
func f72(a, b int) int {
905+
var x [16]byte // use some frame
906+
_ = x
907+
return b
908+
}
909+
`,
910+
[]string{"b\\+40\\(SP\\)"},
911+
},
901912
}
902913

903914
var linux386Tests = []*asmTest{
@@ -1302,6 +1313,17 @@ var linuxARMTests = []*asmTest{
13021313
`,
13031314
[]string{"\tCLZ\t"},
13041315
},
1316+
{
1317+
// make sure assembly output has matching offset and base register.
1318+
`
1319+
func f13(a, b int) int {
1320+
var x [16]byte // use some frame
1321+
_ = x
1322+
return b
1323+
}
1324+
`,
1325+
[]string{"b\\+4\\(FP\\)"},
1326+
},
13051327
}
13061328

13071329
var linuxARM64Tests = []*asmTest{
@@ -1473,7 +1495,7 @@ var linuxARM64Tests = []*asmTest{
14731495
return
14741496
}
14751497
`,
1476-
[]string{"\tMOVD\t\"\"\\.a\\+[0-9]+\\(RSP\\), R[0-9]+", "\tMOVD\tR[0-9]+, \"\"\\.b\\+[0-9]+\\(RSP\\)"},
1498+
[]string{"\tMOVD\t\"\"\\.a\\+[0-9]+\\(FP\\), R[0-9]+", "\tMOVD\tR[0-9]+, \"\"\\.b\\+[0-9]+\\(FP\\)"},
14771499
},
14781500
}
14791501

src/cmd/compile/internal/mips/ssa.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
273273
case ssa.OpMIPSMOVWaddr:
274274
p := s.Prog(mips.AMOVW)
275275
p.From.Type = obj.TYPE_ADDR
276+
p.From.Reg = v.Args[0].Reg()
276277
var wantreg string
277278
// MOVW $sym+off(base), R
278279
// the assembler expands it as the following:
@@ -291,7 +292,6 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
291292
case nil:
292293
// No sym, just MOVW $off(SP), R
293294
wantreg = "SP"
294-
p.From.Reg = mips.REGSP
295295
p.From.Offset = v.AuxInt
296296
}
297297
if reg := v.Args[0].RegName(); reg != wantreg {

src/cmd/compile/internal/mips64/ssa.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
247247
case ssa.OpMIPS64MOVVaddr:
248248
p := s.Prog(mips.AMOVV)
249249
p.From.Type = obj.TYPE_ADDR
250+
p.From.Reg = v.Args[0].Reg()
250251
var wantreg string
251252
// MOVV $sym+off(base), R
252253
// the assembler expands it as the following:
@@ -265,7 +266,6 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
265266
case nil:
266267
// No sym, just MOVV $off(SP), R
267268
wantreg = "SP"
268-
p.From.Reg = mips.REGSP
269269
p.From.Offset = v.AuxInt
270270
}
271271
if reg := v.Args[0].RegName(); reg != wantreg {

src/cmd/compile/internal/ppc64/ssa.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
638638
case ssa.OpPPC64MOVDaddr:
639639
p := s.Prog(ppc64.AMOVD)
640640
p.From.Type = obj.TYPE_ADDR
641+
p.From.Reg = v.Args[0].Reg()
641642
p.To.Type = obj.TYPE_REG
642643
p.To.Reg = v.Reg()
643644

@@ -660,7 +661,6 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
660661
case nil:
661662
// No sym, just MOVD $off(SP), R
662663
wantreg = "SP"
663-
p.From.Reg = ppc64.REGSP
664664
p.From.Offset = v.AuxInt
665665
}
666666
if reg := v.Args[0].RegName(); reg != wantreg {

src/cmd/internal/obj/arm/asm5.go

+20
Original file line numberDiff line numberDiff line change
@@ -1167,6 +1167,11 @@ func (c *ctxt5) aclass(a *obj.Addr) int {
11671167
return C_ADDR
11681168

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

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

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

12911306
case obj.NAME_PARAM:
1307+
if a.Reg == REGSP {
1308+
// unset base register for better printing, since
1309+
// a.Offset is still relative to pseudo-FP.
1310+
a.Reg = obj.REG_NONE
1311+
}
12921312
c.instoffset = c.autosize + a.Offset + 4
12931313
return c.aconsize()
12941314
}

src/cmd/internal/obj/arm64/asm7.go

+20
Original file line numberDiff line numberDiff line change
@@ -1149,10 +1149,20 @@ func (c *ctxt7) aclass(a *obj.Addr) int {
11491149
return C_GOTADDR
11501150

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

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

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

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

12341249
case obj.NAME_PARAM:
1250+
if a.Reg == REGSP {
1251+
// unset base register for better printing, since
1252+
// a.Offset is still relative to pseudo-FP.
1253+
a.Reg = obj.REG_NONE
1254+
}
12351255
c.instoffset = int64(c.autosize) + a.Offset + 8
12361256
goto aconsize
12371257
}

src/cmd/internal/obj/mips/asm0.go

+20
Original file line numberDiff line numberDiff line change
@@ -556,13 +556,23 @@ func (c *ctxt0) aclass(a *obj.Addr) int {
556556
return C_LEXT
557557

558558
case obj.NAME_AUTO:
559+
if a.Reg == REGSP {
560+
// unset base register for better printing, since
561+
// a.Offset is still relative to pseudo-SP.
562+
a.Reg = obj.REG_NONE
563+
}
559564
c.instoffset = int64(c.autosize) + a.Offset
560565
if c.instoffset >= -BIG && c.instoffset < BIG {
561566
return C_SAUTO
562567
}
563568
return C_LAUTO
564569

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

618628
case obj.NAME_AUTO:
629+
if a.Reg == REGSP {
630+
// unset base register for better printing, since
631+
// a.Offset is still relative to pseudo-SP.
632+
a.Reg = obj.REG_NONE
633+
}
619634
c.instoffset = int64(c.autosize) + a.Offset
620635
if c.instoffset >= -BIG && c.instoffset < BIG {
621636
return C_SACON
622637
}
623638
return C_LACON
624639

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

src/cmd/internal/obj/ppc64/asm9.go

+20
Original file line numberDiff line numberDiff line change
@@ -758,13 +758,23 @@ func (c *ctxt9) aclass(a *obj.Addr) int {
758758
return C_GOTADDR
759759

760760
case obj.NAME_AUTO:
761+
if a.Reg == REGSP {
762+
// unset base register for better printing, since
763+
// a.Offset is still relative to pseudo-SP.
764+
a.Reg = obj.REG_NONE
765+
}
761766
c.instoffset = int64(c.autosize) + a.Offset
762767
if c.instoffset >= -BIG && c.instoffset < BIG {
763768
return C_SAUTO
764769
}
765770
return C_LAUTO
766771

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

819829
case obj.NAME_AUTO:
830+
if a.Reg == REGSP {
831+
// unset base register for better printing, since
832+
// a.Offset is still relative to pseudo-SP.
833+
a.Reg = obj.REG_NONE
834+
}
820835
c.instoffset = int64(c.autosize) + a.Offset
821836
if c.instoffset >= -BIG && c.instoffset < BIG {
822837
return C_SACON
823838
}
824839
return C_LACON
825840

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

src/cmd/internal/obj/s390x/asmz.go

+20
Original file line numberDiff line numberDiff line change
@@ -505,13 +505,23 @@ func (c *ctxtz) aclass(a *obj.Addr) int {
505505
return C_GOTADDR
506506

507507
case obj.NAME_AUTO:
508+
if a.Reg == REGSP {
509+
// unset base register for better printing, since
510+
// a.Offset is still relative to pseudo-SP.
511+
a.Reg = obj.REG_NONE
512+
}
508513
c.instoffset = int64(c.autosize) + a.Offset
509514
if c.instoffset >= -BIG && c.instoffset < BIG {
510515
return C_SAUTO
511516
}
512517
return C_LAUTO
513518

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

569579
case obj.NAME_AUTO:
580+
if a.Reg == REGSP {
581+
// unset base register for better printing, since
582+
// a.Offset is still relative to pseudo-SP.
583+
a.Reg = obj.REG_NONE
584+
}
570585
c.instoffset = int64(c.autosize) + a.Offset
571586
if c.instoffset >= -BIG && c.instoffset < BIG {
572587
return C_SACON
573588
}
574589
return C_LACON
575590

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

0 commit comments

Comments
 (0)