diff --git a/format/format.go b/format/format.go index 4cca4c1..882292c 100644 --- a/format/format.go +++ b/format/format.go @@ -226,7 +226,7 @@ func normalizeSpacing(outs []outLine) string { switch prev := outs[j-1]; { case prev.kind == kBlank, prev.kind == kLabel: continue // already separated, or stacked labels - case prev.kind == kDirective && strings.HasPrefix(prev.text, "TEXT"): + case prev.kind == kDirective && strings.HasPrefix(prev.text, "TEXT") && ol.kind == kLabel: continue // the function's first label } insert[j] = true diff --git a/format/format_test.go b/format/format_test.go index a48759c..a94f56c 100644 --- a/format/format_test.go +++ b/format/format_test.go @@ -285,6 +285,31 @@ func TestFlagListRoundTrip(t *testing.T) { } } +// TestDirectiveShapesRoundTrip pins the directive shapes the corpus and the +// runtime write around GLOBL and DATA: each formats to itself, because the +// offset, width and flag spellings are load-bearing operand text. An empty +// TEXT body followed by another declaration keeps the one-blank rule of any +// new block, the previous function having no first label to carry it. +func TestDirectiveShapesRoundTrip(t *testing.T) { + for _, in := range []string{ + "TEXT ·f(SB), NOSPLIT, $0\n", + "TEXT ·f(SB), NOSPLIT, $0\n\nTEXT ·g(SB), NOSPLIT, $0\n\tRET\n", + "GLOBL divtab<>(SB), RODATA, $64\nDATA divtab<>+0x00(SB)/4, $0xf4f8fcff\nDATA divtab<>+0x04(SB)/4, $0xe6eaedf0\n", + "DATA d<>+0(SB)/8, $-1\nDATA d<>+8(SB)/8, $0xFFFFFFFFFFFFFFFF\n\nGLOBL d<>(SB), $16\n", + "GLOBL ·x(SB), $8\n", + "GLOBL ·x(SB), 8, $8\n", + "DATA d<>+0(SB)/4, $1\n\nGLOBL d<>(SB), RODATA, $4\n", + } { + if got := Source(in); got != in { + t.Errorf("formatting %q:\n got %q", in, got) + continue + } + if _, errs := parser.Parse("in.s", in); len(errs) > 0 { + t.Errorf("%q does not parse: %v", in, errs) + } + } +} + // TestCRLFInputIsNormalisedToLF checks that a CRLF file comes out with // uniform LF endings: a // comment must not carry its line's trailing \r // into the output.