]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: use innermost line number for -S
authorKeith Randall <keithr@alum.mit.edu>
Fri, 7 Dec 2018 18:00:36 +0000 (10:00 -0800)
committerKeith Randall <khr@golang.org>
Tue, 11 Dec 2018 20:24:45 +0000 (20:24 +0000)
When functions are inlined, for instructions in the inlined body, does
-S print the location of the call, or the location of the body? Right
now, we do the former. I'd like to do the latter by default, it makes
much more sense when reading disassembly. With mid-stack inlining
enabled in more cases, this quandry will come up more often.

The original behavior is still available with -S=2. Some tests
use this mode (so they can find assembly generated by a particular
source line).

This helped me with understanding what the compiler was doing
while fixing #29007.

Change-Id: Id14a3a41e1b18901e7c5e460aa4caf6d940ed064
Reviewed-on: https://go-review.googlesource.com/c/153241
Reviewed-by: David Chase <drchase@google.com>
src/cmd/asm/main.go
src/cmd/compile/internal/gc/global_test.go
src/cmd/compile/internal/gc/main.go
src/cmd/internal/obj/link.go
src/cmd/internal/obj/objfile.go
src/cmd/internal/obj/plist.go
src/cmd/internal/obj/util.go
test/run.go

index 55ae94a6de5a603ca4719cc3911ea2fd9f302d50..447d1afde3a08507a3ba13d6b97244cfd16e30fa 100644 (file)
@@ -36,7 +36,7 @@ func main() {
 
        ctxt := obj.Linknew(architecture.LinkArch)
        if *flags.PrintOut {
-               ctxt.Debugasm = true
+               ctxt.Debugasm = 1
        }
        ctxt.Flag_dynlink = *flags.Dynlink
        ctxt.Flag_shared = *flags.Shared || *flags.Dynlink
index 857cf967502cf2addf0aaf5607c14c6b2f291939..56855d797a194d506b57e40c2836ad050efbcf9f 100644 (file)
@@ -8,7 +8,6 @@ import (
        "bytes"
        "internal/testenv"
        "io/ioutil"
-       "log"
        "os"
        "os/exec"
        "path/filepath"
@@ -24,7 +23,7 @@ func TestScanfRemoval(t *testing.T) {
        // Make a directory to work in.
        dir, err := ioutil.TempDir("", "issue6853a-")
        if err != nil {
-               log.Fatalf("could not create directory: %v", err)
+               t.Fatalf("could not create directory: %v", err)
        }
        defer os.RemoveAll(dir)
 
@@ -32,7 +31,7 @@ func TestScanfRemoval(t *testing.T) {
        src := filepath.Join(dir, "test.go")
        f, err := os.Create(src)
        if err != nil {
-               log.Fatalf("could not create source file: %v", err)
+               t.Fatalf("could not create source file: %v", err)
        }
        f.Write([]byte(`
 package main
@@ -50,17 +49,17 @@ func main() {
        cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", dst, src)
        out, err := cmd.CombinedOutput()
        if err != nil {
-               log.Fatalf("could not build target: %v", err)
+               t.Fatalf("could not build target: %v", err)
        }
 
        // Check destination to see if scanf code was included.
        cmd = exec.Command(testenv.GoToolPath(t), "tool", "nm", dst)
        out, err = cmd.CombinedOutput()
        if err != nil {
-               log.Fatalf("could not read target: %v", err)
+               t.Fatalf("could not read target: %v", err)
        }
        if bytes.Contains(out, []byte("scanInt")) {
-               log.Fatalf("scanf code not removed from helloworld")
+               t.Fatalf("scanf code not removed from helloworld")
        }
 }
 
@@ -71,7 +70,7 @@ func TestDashS(t *testing.T) {
        // Make a directory to work in.
        dir, err := ioutil.TempDir("", "issue14515-")
        if err != nil {
-               log.Fatalf("could not create directory: %v", err)
+               t.Fatalf("could not create directory: %v", err)
        }
        defer os.RemoveAll(dir)
 
@@ -79,7 +78,7 @@ func TestDashS(t *testing.T) {
        src := filepath.Join(dir, "test.go")
        f, err := os.Create(src)
        if err != nil {
-               log.Fatalf("could not create source file: %v", err)
+               t.Fatalf("could not create source file: %v", err)
        }
        f.Write([]byte(`
 package main
@@ -94,7 +93,7 @@ func main() {
        cmd := exec.Command(testenv.GoToolPath(t), "build", "-gcflags", "-S", "-o", filepath.Join(dir, "test"), src)
        out, err := cmd.CombinedOutput()
        if err != nil {
-               log.Fatalf("could not build target: %v", err)
+               t.Fatalf("could not build target: %v", err)
        }
 
        patterns := []string{
index adfdd7cb376f67b41ac06e9c8bde9d8cc038dad8..f44d19b4390ef69cb0a612633c9cacd1709066fd 100644 (file)
@@ -39,7 +39,6 @@ var (
 
 var (
        Debug_append       int
-       Debug_asm          bool
        Debug_closure      int
        Debug_compilelater int
        debug_dclstack     int
@@ -195,7 +194,7 @@ func Main(archInit func(*Arch)) {
        objabi.Flagcount("K", "debug missing line numbers", &Debug['K'])
        objabi.Flagcount("L", "show full file names in error messages", &Debug['L'])
        objabi.Flagcount("N", "disable optimizations", &Debug['N'])
-       flag.BoolVar(&Debug_asm, "S", false, "print assembly listing")
+       objabi.Flagcount("S", "print assembly listing", &Debug['S'])
        objabi.AddVersionFlag() // -V
        objabi.Flagcount("W", "debug parse tree after type checking", &Debug['W'])
        flag.StringVar(&asmhdr, "asmhdr", "", "write assembly header to `file`")
@@ -265,7 +264,7 @@ func Main(archInit func(*Arch)) {
        Ctxt.Flag_dynlink = flag_dynlink
        Ctxt.Flag_optimize = Debug['N'] == 0
 
-       Ctxt.Debugasm = Debug_asm
+       Ctxt.Debugasm = Debug['S']
        Ctxt.Debugvlog = Debug_vlog
        if flagDWARF {
                Ctxt.DebugInfo = debuginfo
@@ -1330,6 +1329,7 @@ var concurrentFlagOK = [256]bool{
        'l': true, // disable inlining
        'w': true, // all printing happens before compilation
        'W': true, // all printing happens before compilation
+       'S': true, // printing disassembly happens at the end (but see concurrentBackendAllowed below)
 }
 
 func concurrentBackendAllowed() bool {
@@ -1338,9 +1338,9 @@ func concurrentBackendAllowed() bool {
                        return false
                }
        }
-       // Debug_asm by itself is ok, because all printing occurs
+       // Debug['S'] by itself is ok, because all printing occurs
        // while writing the object file, and that is non-concurrent.
-       // Adding Debug_vlog, however, causes Debug_asm to also print
+       // Adding Debug_vlog, however, causes Debug['S'] to also print
        // while flushing the plist, which happens concurrently.
        if Debug_vlog || debugstr != "" || debuglive > 0 {
                return false
index 6cff335ddfab25964c16aecc12c13f4c0678dc9d..dfecdfbb379819a033c1deb78f84eee8328d1145 100644 (file)
@@ -599,7 +599,7 @@ type Pcdata struct {
 type Link struct {
        Headtype           objabi.HeadType
        Arch               *LinkArch
-       Debugasm           bool
+       Debugasm           int
        Debugvlog          bool
        Debugpcln          string
        Flag_shared        bool
index 4fbaafe3474fc61cca458aafb64f6ab9bf82c305..49301f04d504b43b7cd3ff106f961c788e3fa472 100644 (file)
@@ -240,7 +240,13 @@ func (w *objWriter) writeSymDebug(s *LSym) {
        fmt.Fprintf(ctxt.Bso, "\n")
        if s.Type == objabi.STEXT {
                for p := s.Func.Text; p != nil; p = p.Link {
-                       fmt.Fprintf(ctxt.Bso, "\t%#04x %v\n", uint(int(p.Pc)), p)
+                       var s string
+                       if ctxt.Debugasm > 1 {
+                               s = p.String()
+                       } else {
+                               s = p.InnermostString()
+                       }
+                       fmt.Fprintf(ctxt.Bso, "\t%#04x %s\n", uint(int(p.Pc)), s)
                }
        }
        for i := 0; i < len(s.P); i += 16 {
@@ -283,7 +289,7 @@ func (w *objWriter) writeSymDebug(s *LSym) {
 
 func (w *objWriter) writeSym(s *LSym) {
        ctxt := w.ctxt
-       if ctxt.Debugasm {
+       if ctxt.Debugasm > 0 {
                w.writeSymDebug(s)
        }
 
index 6710b375f16119a8f4672a19af14bfee1ae9d3ee..9d376f739ffcb707b41ae6ac48fe4353487fd8db 100644 (file)
@@ -27,7 +27,7 @@ func Flushplist(ctxt *Link, plist *Plist, newprog ProgAlloc, myimportpath string
 
        var plink *Prog
        for p := plist.Firstpc; p != nil; p = plink {
-               if ctxt.Debugasm && ctxt.Debugvlog {
+               if ctxt.Debugasm > 0 && ctxt.Debugvlog {
                        fmt.Printf("obj: %v\n", p)
                }
                plink = p.Link
index 46c3d7b17bbd1a635cdb2f699caf1b989a1d4eb7..f1517d3d5d1dfd16eaabe968c53d26f066d688ab 100644 (file)
@@ -17,6 +17,9 @@ const REG_NONE = 0
 func (p *Prog) Line() string {
        return p.Ctxt.OutermostPos(p.Pos).Format(false, true)
 }
+func (p *Prog) InnermostLine() string {
+       return p.Ctxt.InnermostPos(p.Pos).Format(false, true)
+}
 
 // InnermostLineNumber returns a string containing the line number for the
 // innermost inlined function (if any inlining) at p's position
@@ -118,6 +121,16 @@ func (p *Prog) String() string {
        return fmt.Sprintf("%.5d (%v)\t%s", p.Pc, p.Line(), p.InstructionString())
 }
 
+func (p *Prog) InnermostString() string {
+       if p == nil {
+               return "<nil Prog>"
+       }
+       if p.Ctxt == nil {
+               return "<Prog without ctxt>"
+       }
+       return fmt.Sprintf("%.5d (%v)\t%s", p.Pc, p.InnermostLine(), p.InstructionString())
+}
+
 // InstructionString returns a string representation of the instruction without preceding
 // program counter or file and line number.
 func (p *Prog) InstructionString() string {
@@ -177,7 +190,7 @@ func (ctxt *Link) NewProg() *Prog {
 }
 
 func (ctxt *Link) CanReuseProgs() bool {
-       return !ctxt.Debugasm
+       return ctxt.Debugasm == 0
 }
 
 func Dconv(p *Prog, a *Addr) string {
index 96192937b09bce38356debdfe90feb140ada7a7b..ad38d420c9bbc8ff5abb724a7a3c56e89b2a7981 100644 (file)
@@ -642,7 +642,8 @@ func (t *test) run() {
                // against a set of regexps in comments.
                ops := t.wantedAsmOpcodes(long)
                for _, env := range ops.Envs() {
-                       cmdline := []string{"build", "-gcflags", "-S"}
+                       // -S=2 forces outermost line numbers when disassembling inlined code.
+                       cmdline := []string{"build", "-gcflags", "-S=2"}
                        cmdline = append(cmdline, flags...)
                        cmdline = append(cmdline, long)
                        cmd := exec.Command(goTool(), cmdline...)