aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cmd/internal/obj/objfile.go15
-rw-r--r--src/cmd/internal/obj/util.go167
-rw-r--r--src/cmd/internal/src/pos.go40
-rw-r--r--src/cmd/internal/src/pos_test.go6
4 files changed, 134 insertions, 94 deletions
diff --git a/src/cmd/internal/obj/objfile.go b/src/cmd/internal/obj/objfile.go
index cb6b709066..2b0c45d6b2 100644
--- a/src/cmd/internal/obj/objfile.go
+++ b/src/cmd/internal/obj/objfile.go
@@ -13,6 +13,7 @@ import (
"cmd/internal/objabi"
"cmd/internal/sys"
"fmt"
+ "io"
"log"
"path/filepath"
"sort"
@@ -262,13 +263,13 @@ func (ctxt *Link) writeSymDebugNamed(s *LSym, name string) {
fmt.Fprintf(ctxt.Bso, "\n")
if s.Type == objabi.STEXT {
for p := s.Func.Text; p != nil; p = p.Link {
- var s string
+ fmt.Fprintf(ctxt.Bso, "\t%#04x ", uint(int(p.Pc)))
if ctxt.Debugasm > 1 {
- s = p.String()
+ io.WriteString(ctxt.Bso, p.String())
} else {
- s = p.InnermostString()
+ p.InnermostString(ctxt.Bso)
}
- fmt.Fprintf(ctxt.Bso, "\t%#04x %s\n", uint(int(p.Pc)), s)
+ fmt.Fprintln(ctxt.Bso)
}
}
for i := 0; i < len(s.P); i += 16 {
@@ -283,11 +284,11 @@ func (ctxt *Link) writeSymDebugNamed(s *LSym, name string) {
fmt.Fprintf(ctxt.Bso, " ")
for j = i; j < i+16 && j < len(s.P); j++ {
c := int(s.P[j])
+ b := byte('.')
if ' ' <= c && c <= 0x7e {
- fmt.Fprintf(ctxt.Bso, "%c", c)
- } else {
- fmt.Fprintf(ctxt.Bso, ".")
+ b = byte(c)
}
+ ctxt.Bso.WriteByte(b)
}
fmt.Fprintf(ctxt.Bso, "\n")
diff --git a/src/cmd/internal/obj/util.go b/src/cmd/internal/obj/util.go
index 46d662c6c8..d020026445 100644
--- a/src/cmd/internal/obj/util.go
+++ b/src/cmd/internal/obj/util.go
@@ -8,6 +8,7 @@ import (
"bytes"
"cmd/internal/objabi"
"fmt"
+ "io"
"strings"
)
@@ -17,8 +18,8 @@ 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)
+func (p *Prog) InnermostLine(w io.Writer) {
+ p.Ctxt.InnermostPos(p.Pos).WriteTo(w, false, true)
}
// InnermostLineNumber returns a string containing the line number for the
@@ -121,45 +122,61 @@ func (p *Prog) String() string {
return fmt.Sprintf("%.5d (%v)\t%s", p.Pc, p.Line(), p.InstructionString())
}
-func (p *Prog) InnermostString() string {
+func (p *Prog) InnermostString(w io.Writer) {
if p == nil {
- return "<nil Prog>"
+ io.WriteString(w, "<nil Prog>")
+ return
}
if p.Ctxt == nil {
- return "<Prog without ctxt>"
+ io.WriteString(w, "<Prog without ctxt>")
+ return
}
- return fmt.Sprintf("%.5d (%v)\t%s", p.Pc, p.InnermostLine(), p.InstructionString())
+ fmt.Fprintf(w, "%.5d (", p.Pc)
+ p.InnermostLine(w)
+ io.WriteString(w, ")\t")
+ p.WriteInstructionString(w)
}
// InstructionString returns a string representation of the instruction without preceding
// program counter or file and line number.
func (p *Prog) InstructionString() string {
+ buf := new(bytes.Buffer)
+ p.WriteInstructionString(buf)
+ return buf.String()
+}
+
+// WriteInstructionString writes a string representation of the instruction without preceding
+// program counter or file and line number.
+func (p *Prog) WriteInstructionString(w io.Writer) {
if p == nil {
- return "<nil Prog>"
+ io.WriteString(w, "<nil Prog>")
+ return
}
if p.Ctxt == nil {
- return "<Prog without ctxt>"
+ io.WriteString(w, "<Prog without ctxt>")
+ return
}
sc := CConv(p.Scond)
- var buf bytes.Buffer
-
- fmt.Fprintf(&buf, "%v%s", p.As, sc)
+ io.WriteString(w, p.As.String())
+ io.WriteString(w, sc)
sep := "\t"
if p.From.Type != TYPE_NONE {
- fmt.Fprintf(&buf, "%s%v", sep, Dconv(p, &p.From))
+ io.WriteString(w, sep)
+ WriteDconv(w, p, &p.From)
sep = ", "
}
if p.Reg != REG_NONE {
// Should not happen but might as well show it if it does.
- fmt.Fprintf(&buf, "%s%v", sep, Rconv(int(p.Reg)))
+ fmt.Fprintf(w, "%s%v", sep, Rconv(int(p.Reg)))
sep = ", "
}
for i := range p.RestArgs {
- fmt.Fprintf(&buf, "%s%v", sep, Dconv(p, &p.RestArgs[i]))
+ io.WriteString(w, sep)
+ WriteDconv(w, p, &p.RestArgs[i])
sep = ", "
}
@@ -170,17 +187,17 @@ func (p *Prog) InstructionString() string {
// TEXT foo(SB), $0
s := p.From.Sym.Attribute.TextAttrString()
if s != "" {
- fmt.Fprintf(&buf, "%s%s", sep, s)
+ fmt.Fprintf(w, "%s%s", sep, s)
sep = ", "
}
}
if p.To.Type != TYPE_NONE {
- fmt.Fprintf(&buf, "%s%v", sep, Dconv(p, &p.To))
+ io.WriteString(w, sep)
+ WriteDconv(w, p, &p.To)
}
if p.RegTo2 != REG_NONE {
- fmt.Fprintf(&buf, "%s%v", sep, Rconv(int(p.RegTo2)))
+ fmt.Fprintf(w, "%s%v", sep, Rconv(int(p.RegTo2)))
}
- return buf.String()
}
func (ctxt *Link) NewProg() *Prog {
@@ -194,16 +211,20 @@ func (ctxt *Link) CanReuseProgs() bool {
}
func Dconv(p *Prog, a *Addr) string {
- var str string
+ buf := new(bytes.Buffer)
+ WriteDconv(buf, p, a)
+ return buf.String()
+}
+func WriteDconv(w io.Writer, p *Prog, a *Addr) {
switch a.Type {
default:
- str = fmt.Sprintf("type=%d", a.Type)
+ fmt.Fprintf(w, "type=%d", a.Type)
case TYPE_NONE:
- str = ""
if a.Name != NAME_NONE || a.Reg != 0 || a.Sym != nil {
- str = fmt.Sprintf("%v(%v)(NONE)", Mconv(a), Rconv(int(a.Reg)))
+ a.WriteNameTo(w)
+ fmt.Fprintf(w, "(%v)(NONE)", Rconv(int(a.Reg)))
}
case TYPE_REG:
@@ -212,71 +233,75 @@ func Dconv(p *Prog, a *Addr) string {
// where the $1 is included in the p->to Addr.
// Move into a new field.
if a.Offset != 0 && (a.Reg < RBaseARM64 || a.Reg >= RBaseMIPS) {
- str = fmt.Sprintf("$%d,%v", a.Offset, Rconv(int(a.Reg)))
- break
+ fmt.Fprintf(w, "$%d,%v", a.Offset, Rconv(int(a.Reg)))
+ return
}
- str = Rconv(int(a.Reg))
if a.Name != NAME_NONE || a.Sym != nil {
- str = fmt.Sprintf("%v(%v)(REG)", Mconv(a), Rconv(int(a.Reg)))
+ a.WriteNameTo(w)
+ fmt.Fprintf(w, "(%v)(REG)", Rconv(int(a.Reg)))
+ } else {
+ io.WriteString(w, Rconv(int(a.Reg)))
}
if (RBaseARM64+1<<10+1<<9) /* arm64.REG_ELEM */ <= a.Reg &&
a.Reg < (RBaseARM64+1<<11) /* arm64.REG_ELEM_END */ {
- str += fmt.Sprintf("[%d]", a.Index)
+ fmt.Fprintf(w, "[%d]", a.Index)
}
case TYPE_BRANCH:
if a.Sym != nil {
- str = fmt.Sprintf("%s(SB)", a.Sym.Name)
+ fmt.Fprintf(w, "%s(SB)", a.Sym.Name)
} else if p != nil && p.Pcond != nil {
- str = fmt.Sprint(p.Pcond.Pc)
+ fmt.Fprint(w, p.Pcond.Pc)
} else if a.Val != nil {
- str = fmt.Sprint(a.Val.(*Prog).Pc)
+ fmt.Fprint(w, a.Val.(*Prog).Pc)
} else {
- str = fmt.Sprintf("%d(PC)", a.Offset)
+ fmt.Fprintf(w, "%d(PC)", a.Offset)
}
case TYPE_INDIR:
- str = fmt.Sprintf("*%s", Mconv(a))
+ io.WriteString(w, "*")
+ a.WriteNameTo(w)
case TYPE_MEM:
- str = Mconv(a)
+ a.WriteNameTo(w)
if a.Index != REG_NONE {
if a.Scale == 0 {
// arm64 shifted or extended register offset, scale = 0.
- str += fmt.Sprintf("(%v)", Rconv(int(a.Index)))
+ fmt.Fprintf(w, "(%v)", Rconv(int(a.Index)))
} else {
- str += fmt.Sprintf("(%v*%d)", Rconv(int(a.Index)), int(a.Scale))
+ fmt.Fprintf(w, "(%v*%d)", Rconv(int(a.Index)), int(a.Scale))
}
}
case TYPE_CONST:
+ io.WriteString(w, "$")
+ a.WriteNameTo(w)
if a.Reg != 0 {
- str = fmt.Sprintf("$%v(%v)", Mconv(a), Rconv(int(a.Reg)))
- } else {
- str = fmt.Sprintf("$%v", Mconv(a))
+ fmt.Fprintf(w, "(%v)", Rconv(int(a.Reg)))
}
case TYPE_TEXTSIZE:
if a.Val.(int32) == objabi.ArgsSizeUnknown {
- str = fmt.Sprintf("$%d", a.Offset)
+ fmt.Fprintf(w, "$%d", a.Offset)
} else {
- str = fmt.Sprintf("$%d-%d", a.Offset, a.Val.(int32))
+ fmt.Fprintf(w, "$%d-%d", a.Offset, a.Val.(int32))
}
case TYPE_FCONST:
- str = fmt.Sprintf("%.17g", a.Val.(float64))
+ str := fmt.Sprintf("%.17g", a.Val.(float64))
// Make sure 1 prints as 1.0
if !strings.ContainsAny(str, ".e") {
str += ".0"
}
- str = fmt.Sprintf("$(%s)", str)
+ fmt.Fprintf(w, "$(%s)", str)
case TYPE_SCONST:
- str = fmt.Sprintf("$%q", a.Val.(string))
+ fmt.Fprintf(w, "$%q", a.Val.(string))
case TYPE_ADDR:
- str = fmt.Sprintf("$%s", Mconv(a))
+ io.WriteString(w, "$")
+ a.WriteNameTo(w)
case TYPE_SHIFT:
v := int(a.Offset)
@@ -285,49 +310,45 @@ func Dconv(p *Prog, a *Addr) string {
case "arm":
op := ops[((v>>5)&3)<<1:]
if v&(1<<4) != 0 {
- str = fmt.Sprintf("R%d%c%cR%d", v&15, op[0], op[1], (v>>8)&15)
+ fmt.Fprintf(w, "R%d%c%cR%d", v&15, op[0], op[1], (v>>8)&15)
} else {
- str = fmt.Sprintf("R%d%c%c%d", v&15, op[0], op[1], (v>>7)&31)
+ fmt.Fprintf(w, "R%d%c%c%d", v&15, op[0], op[1], (v>>7)&31)
}
if a.Reg != 0 {
- str += fmt.Sprintf("(%v)", Rconv(int(a.Reg)))
+ fmt.Fprintf(w, "(%v)", Rconv(int(a.Reg)))
}
case "arm64":
op := ops[((v>>22)&3)<<1:]
r := (v >> 16) & 31
- str = fmt.Sprintf("%s%c%c%d", Rconv(r+RBaseARM64), op[0], op[1], (v>>10)&63)
+ fmt.Fprintf(w, "%s%c%c%d", Rconv(r+RBaseARM64), op[0], op[1], (v>>10)&63)
default:
panic("TYPE_SHIFT is not supported on " + objabi.GOARCH)
}
case TYPE_REGREG:
- str = fmt.Sprintf("(%v, %v)", Rconv(int(a.Reg)), Rconv(int(a.Offset)))
+ fmt.Fprintf(w, "(%v, %v)", Rconv(int(a.Reg)), Rconv(int(a.Offset)))
case TYPE_REGREG2:
- str = fmt.Sprintf("%v, %v", Rconv(int(a.Offset)), Rconv(int(a.Reg)))
+ fmt.Fprintf(w, "%v, %v", Rconv(int(a.Offset)), Rconv(int(a.Reg)))
case TYPE_REGLIST:
- str = RLconv(a.Offset)
+ io.WriteString(w, RLconv(a.Offset))
}
-
- return str
}
-func Mconv(a *Addr) string {
- var str string
-
+func (a *Addr) WriteNameTo(w io.Writer) {
switch a.Name {
default:
- str = fmt.Sprintf("name=%d", a.Name)
+ fmt.Fprintf(w, "name=%d", a.Name)
case NAME_NONE:
switch {
case a.Reg == REG_NONE:
- str = fmt.Sprint(a.Offset)
+ fmt.Fprint(w, a.Offset)
case a.Offset == 0:
- str = fmt.Sprintf("(%v)", Rconv(int(a.Reg)))
+ fmt.Fprintf(w, "(%v)", Rconv(int(a.Reg)))
case a.Offset != 0:
- str = fmt.Sprintf("%d(%v)", a.Offset, Rconv(int(a.Reg)))
+ fmt.Fprintf(w, "%d(%v)", a.Offset, Rconv(int(a.Reg)))
}
// Note: a.Reg == REG_NONE encodes the default base register for the NAME_ type.
@@ -337,9 +358,9 @@ func Mconv(a *Addr) string {
reg = Rconv(int(a.Reg))
}
if a.Sym != nil {
- str = fmt.Sprintf("%s%s(%s)", a.Sym.Name, offConv(a.Offset), reg)
+ fmt.Fprintf(w, "%s%s(%s)", a.Sym.Name, offConv(a.Offset), reg)
} else {
- str = fmt.Sprintf("%s(%s)", offConv(a.Offset), reg)
+ fmt.Fprintf(w, "%s(%s)", offConv(a.Offset), reg)
}
case NAME_GOTREF:
@@ -348,9 +369,9 @@ func Mconv(a *Addr) string {
reg = Rconv(int(a.Reg))
}
if a.Sym != nil {
- str = fmt.Sprintf("%s%s@GOT(%s)", a.Sym.Name, offConv(a.Offset), reg)
+ fmt.Fprintf(w, "%s%s@GOT(%s)", a.Sym.Name, offConv(a.Offset), reg)
} else {
- str = fmt.Sprintf("%s@GOT(%s)", offConv(a.Offset), reg)
+ fmt.Fprintf(w, "%s@GOT(%s)", offConv(a.Offset), reg)
}
case NAME_STATIC:
@@ -359,9 +380,9 @@ func Mconv(a *Addr) string {
reg = Rconv(int(a.Reg))
}
if a.Sym != nil {
- str = fmt.Sprintf("%s<>%s(%s)", a.Sym.Name, offConv(a.Offset), reg)
+ fmt.Fprintf(w, "%s<>%s(%s)", a.Sym.Name, offConv(a.Offset), reg)
} else {
- str = fmt.Sprintf("<>%s(%s)", offConv(a.Offset), reg)
+ fmt.Fprintf(w, "<>%s(%s)", offConv(a.Offset), reg)
}
case NAME_AUTO:
@@ -370,9 +391,9 @@ func Mconv(a *Addr) string {
reg = Rconv(int(a.Reg))
}
if a.Sym != nil {
- str = fmt.Sprintf("%s%s(%s)", a.Sym.Name, offConv(a.Offset), reg)
+ fmt.Fprintf(w, "%s%s(%s)", a.Sym.Name, offConv(a.Offset), reg)
} else {
- str = fmt.Sprintf("%s(%s)", offConv(a.Offset), reg)
+ fmt.Fprintf(w, "%s(%s)", offConv(a.Offset), reg)
}
case NAME_PARAM:
@@ -381,9 +402,9 @@ func Mconv(a *Addr) string {
reg = Rconv(int(a.Reg))
}
if a.Sym != nil {
- str = fmt.Sprintf("%s%s(%s)", a.Sym.Name, offConv(a.Offset), reg)
+ fmt.Fprintf(w, "%s%s(%s)", a.Sym.Name, offConv(a.Offset), reg)
} else {
- str = fmt.Sprintf("%s(%s)", offConv(a.Offset), reg)
+ fmt.Fprintf(w, "%s(%s)", offConv(a.Offset), reg)
}
case NAME_TOCREF:
reg := "SB"
@@ -391,13 +412,11 @@ func Mconv(a *Addr) string {
reg = Rconv(int(a.Reg))
}
if a.Sym != nil {
- str = fmt.Sprintf("%s%s(%s)", a.Sym.Name, offConv(a.Offset), reg)
+ fmt.Fprintf(w, "%s%s(%s)", a.Sym.Name, offConv(a.Offset), reg)
} else {
- str = fmt.Sprintf("%s(%s)", offConv(a.Offset), reg)
+ fmt.Fprintf(w, "%s(%s)", offConv(a.Offset), reg)
}
-
}
- return str
}
func offConv(off int64) string {
diff --git a/src/cmd/internal/src/pos.go b/src/cmd/internal/src/pos.go
index 861d9188b1..b6816a56e0 100644
--- a/src/cmd/internal/src/pos.go
+++ b/src/cmd/internal/src/pos.go
@@ -7,8 +7,9 @@
package src
import (
+ "bytes"
"fmt"
- "strconv"
+ "io"
)
// A Pos encodes a source position consisting of a (line, column) number pair
@@ -129,13 +130,22 @@ func (p Pos) String() string {
// shown as well, as in "filename:line[origfile:origline:origcolumn] if
// showOrig is set.
func (p Pos) Format(showCol, showOrig bool) string {
+ buf := new(bytes.Buffer)
+ p.WriteTo(buf, showCol, showOrig)
+ return buf.String()
+}
+
+// WriteTo a position to w, formatted as Format does.
+func (p Pos) WriteTo(w io.Writer, showCol, showOrig bool) {
if !p.IsKnown() {
- return "<unknown line number>"
+ io.WriteString(w, "<unknown line number>")
+ return
}
if b := p.base; b == b.Pos().base {
// base is file base (incl. nil)
- return format(p.Filename(), p.Line(), p.Col(), showCol)
+ format(w, p.Filename(), p.Line(), p.Col(), showCol)
+ return
}
// base is relative
@@ -146,22 +156,32 @@ func (p Pos) Format(showCol, showOrig bool) string {
// that's provided via a line directive).
// TODO(gri) This may not be true if we have an inlining base.
// We may want to differentiate at some point.
- s := format(p.RelFilename(), p.RelLine(), p.RelCol(), showCol)
+ format(w, p.RelFilename(), p.RelLine(), p.RelCol(), showCol)
if showOrig {
- s += "[" + format(p.Filename(), p.Line(), p.Col(), showCol) + "]"
+ io.WriteString(w, "[")
+ format(w, p.Filename(), p.Line(), p.Col(), showCol)
+ io.WriteString(w, "]")
}
- return s
}
// format formats a (filename, line, col) tuple as "filename:line" (showCol
// is false or col == 0) or "filename:line:column" (showCol is true and col != 0).
-func format(filename string, line, col uint, showCol bool) string {
- s := filename + ":" + strconv.FormatUint(uint64(line), 10)
+func format(w io.Writer, filename string, line, col uint, showCol bool) {
+ io.WriteString(w, filename)
+ io.WriteString(w, ":")
+ fmt.Fprint(w, line)
// col == 0 and col == colMax are interpreted as unknown column values
if showCol && 0 < col && col < colMax {
- s += ":" + strconv.FormatUint(uint64(col), 10)
+ io.WriteString(w, ":")
+ fmt.Fprint(w, col)
}
- return s
+}
+
+// formatstr wraps format to return a string.
+func formatstr(filename string, line, col uint, showCol bool) string {
+ buf := new(bytes.Buffer)
+ format(buf, filename, line, col, showCol)
+ return buf.String()
}
// ----------------------------------------------------------------------------
diff --git a/src/cmd/internal/src/pos_test.go b/src/cmd/internal/src/pos_test.go
index d6131bab4c..d4cd0e7ff1 100644
--- a/src/cmd/internal/src/pos_test.go
+++ b/src/cmd/internal/src/pos_test.go
@@ -147,7 +147,7 @@ func TestLico(t *testing.T) {
{makeLico(lineMax+1, colMax+1), fmt.Sprintf(":%d", lineMax), lineMax, 0},
} {
x := test.x
- if got := format("", x.Line(), x.Col(), true); got != test.string {
+ if got := formatstr("", x.Line(), x.Col(), true); got != test.string {
t.Errorf("%s: got %q", test.string, got)
}
}
@@ -179,7 +179,7 @@ func TestIsStmt(t *testing.T) {
{makeLico(lineMax+1, colMax+1).withNotStmt(), fmt.Sprintf(":%d", lineMax) + not, lineMax, 0},
} {
x := test.x
- if got := format("", x.Line(), x.Col(), true) + fmt.Sprintf(":%d", x.IsStmt()); got != test.string {
+ if got := formatstr("", x.Line(), x.Col(), true) + fmt.Sprintf(":%d", x.IsStmt()); got != test.string {
t.Errorf("%s: got %q", test.string, got)
}
}
@@ -219,7 +219,7 @@ func TestLogue(t *testing.T) {
{makeLico(lineMax, 1).withXlogue(PosEpilogueBegin), fmt.Sprintf(":%d:1", lineMax) + defs + epi, lineMax, 1},
} {
x := test.x
- if got := format("", x.Line(), x.Col(), true) + fmt.Sprintf(":%d:%d", x.IsStmt(), x.Xlogue()); got != test.string {
+ if got := formatstr("", x.Line(), x.Col(), true) + fmt.Sprintf(":%d:%d", x.IsStmt(), x.Xlogue()); got != test.string {
t.Errorf("%d: %s: got %q", i, test.string, got)
}
}