tests/fixedbugs: regression test for issue 100 (#129)
Adds a regression test based on klauspost/compress#186. This necessitated some related changes: * Mark "RET" as a terminal instruction * printer refactor to maintain compatibility with asmfmt * Tweaks to other regression tests to ensure they are run correctly in CI Updates #100 #65 #8
This commit is contained in:
committed by
GitHub
parent
5a144d9b53
commit
e089a6c93c
@@ -1,10 +1,8 @@
|
||||
package printer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/mmcloughlin/avo/internal/prnt"
|
||||
"github.com/mmcloughlin/avo/ir"
|
||||
@@ -17,6 +15,9 @@ const dot = "\u00b7"
|
||||
type goasm struct {
|
||||
cfg Config
|
||||
prnt.Generator
|
||||
|
||||
instructions []*ir.Instruction
|
||||
clear bool
|
||||
}
|
||||
|
||||
// NewGoAsm constructs a printer for writing Go assembly files.
|
||||
@@ -87,31 +88,21 @@ func (p *goasm) function(f *ir.Function) {
|
||||
}
|
||||
p.Printf(", %s\n", textsize(f))
|
||||
|
||||
w := p.tabwriter()
|
||||
clear := true
|
||||
flush := func() {
|
||||
w.Flush()
|
||||
w = p.tabwriter()
|
||||
if !clear {
|
||||
p.NL()
|
||||
clear = true
|
||||
}
|
||||
}
|
||||
p.clear = true
|
||||
for _, node := range f.Nodes {
|
||||
switch n := node.(type) {
|
||||
case *ir.Instruction:
|
||||
leader := []byte{tabwriter.Escape, '\t', tabwriter.Escape}
|
||||
fmt.Fprint(w, string(leader)+n.Opcode)
|
||||
if len(n.Operands) > 0 {
|
||||
fmt.Fprintf(w, "\t%s", joinOperands(n.Operands))
|
||||
p.instruction(n)
|
||||
if n.IsTerminal || n.IsUnconditionalBranch() {
|
||||
p.flush()
|
||||
}
|
||||
fmt.Fprint(w, "\n")
|
||||
clear = false
|
||||
case ir.Label:
|
||||
flush()
|
||||
p.flush()
|
||||
p.ensureclear()
|
||||
p.Printf("%s:\n", n)
|
||||
case *ir.Comment:
|
||||
flush()
|
||||
p.flush()
|
||||
p.ensureclear()
|
||||
for _, line := range n.Lines {
|
||||
p.Printf("\t// %s\n", line)
|
||||
}
|
||||
@@ -119,11 +110,45 @@ func (p *goasm) function(f *ir.Function) {
|
||||
panic("unexpected node type")
|
||||
}
|
||||
}
|
||||
w.Flush()
|
||||
p.flush()
|
||||
}
|
||||
|
||||
func (p *goasm) tabwriter() *tabwriter.Writer {
|
||||
return tabwriter.NewWriter(p.Raw(), 4, 4, 1, ' ', tabwriter.StripEscape)
|
||||
func (p *goasm) instruction(i *ir.Instruction) {
|
||||
p.instructions = append(p.instructions, i)
|
||||
p.clear = false
|
||||
}
|
||||
|
||||
func (p *goasm) flush() {
|
||||
if len(p.instructions) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// Determine instruction width. Instructions with no operands are not
|
||||
// considered in this calculation.
|
||||
width := 0
|
||||
for _, i := range p.instructions {
|
||||
if len(i.Operands) > 0 && len(i.Opcode) > width {
|
||||
width = len(i.Opcode)
|
||||
}
|
||||
}
|
||||
|
||||
// Output instruction block.
|
||||
for _, i := range p.instructions {
|
||||
if len(i.Operands) > 0 {
|
||||
p.Printf("\t%-*s%s\n", width+1, i.Opcode, joinOperands(i.Operands))
|
||||
} else {
|
||||
p.Printf("\t%s\n", i.Opcode)
|
||||
}
|
||||
}
|
||||
|
||||
p.instructions = nil
|
||||
}
|
||||
|
||||
func (p *goasm) ensureclear() {
|
||||
if !p.clear {
|
||||
p.NL()
|
||||
p.clear = true
|
||||
}
|
||||
}
|
||||
|
||||
func (p *goasm) global(g *ir.Global) {
|
||||
|
||||
@@ -81,3 +81,27 @@ func TestConstraints(t *testing.T) {
|
||||
"",
|
||||
})
|
||||
}
|
||||
|
||||
func TestAlignmentNoOperands(t *testing.T) {
|
||||
ctx := build.NewContext()
|
||||
ctx.Function("alignment")
|
||||
ctx.SignatureExpr("func()")
|
||||
ctx.ADDQ(reg.RAX, reg.RBX)
|
||||
ctx.VMOVDQU(reg.Y4, reg.Y11)
|
||||
ctx.VZEROUPPER()
|
||||
ctx.ADDQ(reg.R9, reg.R13)
|
||||
ctx.RET()
|
||||
|
||||
AssertPrintsLines(t, ctx, printer.NewGoAsm, []string{
|
||||
"// Code generated by avo. DO NOT EDIT.",
|
||||
"",
|
||||
"// func alignment()",
|
||||
"TEXT ·alignment(SB), $0",
|
||||
"\tADDQ AX, BX",
|
||||
"\tVMOVDQU Y4, Y11",
|
||||
"\tVZEROUPPER", // instruction with no alignment doesn't affect width
|
||||
"\tADDQ R9, R13", // retains alignment from above
|
||||
"\tRET",
|
||||
"",
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user