c65gm/internal/optimizer/debug.go

63 lines
1.7 KiB
Go

package optimizer
import "fmt"
// debugDiff produces annotated output showing original vs optimized code.
// Lines that were removed are shown with "[removed]" annotation.
func debugDiff(original, optimized []asmLine) []asmLine {
origCount := countCodeLines(original)
optCount := countCodeLines(optimized)
saved := origCount - optCount
header := fmt.Sprintf("; --- peephole: %d asm lines → %d (%d saved) ---", origCount, optCount, saved)
var result []asmLine
result = append(result, asmLine{text: header, isComment: true})
// Walk both arrays in sync. When optimized doesn't have a line
// that original has, it was removed.
oi := 0 // index into original (pre-stripped)
opi := 0 // index into optimized
for oi < len(original) {
origLine := original[oi]
if opi < len(optimized) && linesMatch(origLine, optimized[opi]) {
result = append(result, optimized[opi])
oi++
opi++
} else if !origLine.isCode {
// Non-code line that doesn't match anything — pass through
result = append(result, origLine)
oi++
} else {
// Code line in original but not in optimized → removed
result = append(result, asmLine{
text: fmt.Sprintf("; [removed] %s", origLine.text),
isComment: true,
})
oi++
}
}
// Append any remaining optimized lines (shouldn't happen in practice)
for ; opi < len(optimized); opi++ {
result = append(result, optimized[opi])
}
return result
}
// linesMatch returns true if two asmLines represent the same instruction.
func linesMatch(a, b asmLine) bool {
return a.isCode == b.isCode && a.isLabel == b.isLabel && a.isComment == b.isComment && a.text == b.text
}
func countCodeLines(lines []asmLine) int {
n := 0
for _, l := range lines {
if l.isCode {
n++
}
}
return n
}