]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.inline] cmd/internal/src: introduce compact source position representation
authorRobert Griesemer <gri@golang.org>
Fri, 16 Dec 2016 01:17:01 +0000 (17:17 -0800)
committerRobert Griesemer <gri@golang.org>
Mon, 9 Jan 2017 22:43:22 +0000 (22:43 +0000)
XPos is a compact (8 instead of 16 bytes on a 64bit machine) source
position representation. There is a 1:1 correspondence between each
XPos and each regular Pos, translated via a global table.

In some sense this brings back the LineHist, though positions can
track line and column information; there is a O(1) translation
between the representations (no binary search), and the translation
is factored out.

The size increase with the prior change is brought down again and
the compiler speed is in line with the master repo (measured on
the same "quiet" machine as for prior change):

name       old time/op     new time/op     delta
Template       256ms ± 1%      262ms ± 2%    ~             (p=0.063 n=5+4)
Unicode        132ms ± 1%      135ms ± 2%    ~             (p=0.063 n=5+4)
GoTypes        891ms ± 1%      871ms ± 1%  -2.28%          (p=0.016 n=5+4)
Compiler       3.84s ± 2%      3.89s ± 2%    ~             (p=0.413 n=5+4)
MakeBash       47.1s ± 1%      46.2s ± 2%    ~             (p=0.095 n=5+5)

name       old user-ns/op  new user-ns/op  delta
Template        309M ± 1%       314M ± 2%    ~             (p=0.111 n=5+4)
Unicode         165M ± 1%       172M ± 9%    ~             (p=0.151 n=5+5)
GoTypes        1.14G ± 2%      1.12G ± 1%    ~             (p=0.063 n=5+4)
Compiler       5.00G ± 1%      4.96G ± 1%    ~             (p=0.286 n=5+4)

Change-Id: Icc570cc60ab014d8d9af6976f1f961ab8828cc47
Reviewed-on: https://go-review.googlesource.com/34506
Run-TryBot: Robert Griesemer <gri@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>

42 files changed:
src/cmd/asm/internal/asm/parse.go
src/cmd/compile/internal/gc/alg.go
src/cmd/compile/internal/gc/bexport.go
src/cmd/compile/internal/gc/const.go
src/cmd/compile/internal/gc/dcl.go
src/cmd/compile/internal/gc/go.go
src/cmd/compile/internal/gc/inl.go
src/cmd/compile/internal/gc/lex.go
src/cmd/compile/internal/gc/main.go
src/cmd/compile/internal/gc/noder.go
src/cmd/compile/internal/gc/order.go
src/cmd/compile/internal/gc/pgen.go
src/cmd/compile/internal/gc/phi.go
src/cmd/compile/internal/gc/racewalk.go
src/cmd/compile/internal/gc/sizeof_test.go
src/cmd/compile/internal/gc/ssa.go
src/cmd/compile/internal/gc/subr.go
src/cmd/compile/internal/gc/syntax.go
src/cmd/compile/internal/gc/type.go
src/cmd/compile/internal/gc/typecheck.go
src/cmd/compile/internal/ssa/block.go
src/cmd/compile/internal/ssa/compile.go
src/cmd/compile/internal/ssa/config.go
src/cmd/compile/internal/ssa/deadstore.go
src/cmd/compile/internal/ssa/export_test.go
src/cmd/compile/internal/ssa/func.go
src/cmd/compile/internal/ssa/func_test.go
src/cmd/compile/internal/ssa/html.go
src/cmd/compile/internal/ssa/regalloc.go
src/cmd/compile/internal/ssa/sizeof_test.go
src/cmd/compile/internal/ssa/sparsemap.go
src/cmd/compile/internal/ssa/stackalloc.go
src/cmd/compile/internal/ssa/value.go
src/cmd/compile/internal/ssa/writebarrier.go
src/cmd/internal/obj/line.go
src/cmd/internal/obj/line_test.go
src/cmd/internal/obj/link.go
src/cmd/internal/obj/sizeof_test.go
src/cmd/internal/obj/util.go
src/cmd/internal/src/pos.go
src/cmd/internal/src/xpos.go [new file with mode: 0644]
src/cmd/internal/src/xpos_test.go [new file with mode: 0644]

index 4b971e7119ff06eb5ec96589aa2fdecd6aff6239..4e23e7743cfffa5556d0e212b7bc4d2f4e088f3e 100644 (file)
@@ -85,8 +85,8 @@ func (p *Parser) errorf(format string, args ...interface{}) {
        }
 }
 
-func (p *Parser) pos() src.Pos {
-       return src.MakePos(p.lex.Base(), uint(p.lineNum), 0)
+func (p *Parser) pos() src.XPos {
+       return p.ctxt.PosTable.XPos(src.MakePos(p.lex.Base(), uint(p.lineNum), 0))
 }
 
 func (p *Parser) Parse() (*obj.Prog, bool) {
index 3c71cea33a150576698d6916b5849dbae32b09af..09216fdd83d516758ed6a8269085a433ef56d000 100644 (file)
@@ -4,10 +4,7 @@
 
 package gc
 
-import (
-       "cmd/internal/src"
-       "fmt"
-)
+import "fmt"
 
 // AlgKind describes the kind of algorithms used for comparing and
 // hashing a Type.
@@ -189,7 +186,7 @@ func genhash(sym *Sym, t *Type) {
                fmt.Printf("genhash %v %v\n", sym, t)
        }
 
-       lineno = src.MakePos(nil, 1, 0) // less confusing than end of input
+       lineno = MakePos(nil, 1, 0) // less confusing than end of input
        dclcontext = PEXTERN
        markdcl()
 
@@ -365,7 +362,7 @@ func geneq(sym *Sym, t *Type) {
                fmt.Printf("geneq %v %v\n", sym, t)
        }
 
-       lineno = src.MakePos(nil, 1, 0) // less confusing than end of input
+       lineno = MakePos(nil, 1, 0) // less confusing than end of input
        dclcontext = PEXTERN
        markdcl()
 
index dbf2d6e1668f13d5081858b11c9b7e27f8167e29..ab86c3a52387f618a15a196741e5abf73a343515 100644 (file)
@@ -591,8 +591,9 @@ func (p *exporter) pos(n *Node) {
 
 func fileLine(n *Node) (file string, line int) {
        if n != nil {
-               file = n.Pos.AbsFilename()
-               line = int(n.Pos.Line())
+               pos := Ctxt.PosTable.Pos(n.Pos)
+               file = pos.AbsFilename()
+               line = int(pos.Line())
        }
        return
 }
index 0575b0f789259dc3d7d5824502a7f9f4273f4478..a2146ebef17d48fc95b1a10e4c52df6fe3a89b00 100644 (file)
@@ -679,7 +679,7 @@ func evconst(n *Node) {
 
        nr := n.Right
        var rv Val
-       var lno src.Pos
+       var lno src.XPos
        var wr EType
        var v Val
        var norig *Node
index 51a4924ffc1fde90b2d19d076628b3b1f0ffe5ee..8af78c156af3fa442b1b7e2db489145270c4278f 100644 (file)
@@ -288,7 +288,7 @@ func variter(vl []*Node, t *Node, el []*Node) []*Node {
 // declare constants from grammar
 // new_name_list [[type] = expr_list]
 func constiter(vl []*Node, t *Node, cl []*Node) []*Node {
-       var lno src.Pos // default is to leave line number alone in listtreecopy
+       var lno src.XPos // default is to leave line number alone in listtreecopy
        if len(cl) == 0 {
                if t != nil {
                        yyerror("const declaration cannot have type without expression")
@@ -1345,7 +1345,7 @@ type nowritebarrierrecChecker struct {
 type nowritebarrierrecCall struct {
        target *Node
        depth  int
-       lineno src.Pos
+       lineno src.XPos
 }
 
 func checknowritebarrierrec() {
index f54d058ebba76a7c415d37b801eab854d62fd4bd..3d4b511109bf9d2fdd3bf7d3122a94ec59a68fdb 100644 (file)
@@ -43,10 +43,10 @@ type Sym struct {
 
        // saved and restored by dcopy
        Pkg        *Pkg
-       Name       string  // object name
-       Def        *Node   // definition: ONAME OTYPE OPACK or OLITERAL
-       Block      int32   // blocknumber to catch redeclaration
-       Lastlineno src.Pos // last declaration for diagnostic
+       Name       string   // object name
+       Def        *Node    // definition: ONAME OTYPE OPACK or OLITERAL
+       Block      int32    // blocknumber to catch redeclaration
+       Lastlineno src.XPos // last declaration for diagnostic
 
        Label   *Node // corresponding label (ephemeral)
        Origpkg *Pkg  // original package for . import
index b5f1cbd3107693f303356ef5f1065775bc17889a..9912cf5aa04fcdc89345edf0acaa467be37fa820 100644 (file)
@@ -1017,13 +1017,13 @@ func (subst *inlsubst) node(n *Node) *Node {
 }
 
 // Plaster over linenumbers
-func setlnolist(ll Nodes, lno src.Pos) {
+func setlnolist(ll Nodes, lno src.XPos) {
        for _, n := range ll.Slice() {
                setlno(n, lno)
        }
 }
 
-func setlno(n *Node, lno src.Pos) {
+func setlno(n *Node, lno src.XPos) {
        if n == nil {
                return
        }
index f92387036bf1869f0599b33f2d3802f75f7c0867..5ff55d7c836c9f4dde4eee3a6065b9d138c9341c 100644 (file)
@@ -14,7 +14,11 @@ import (
 
 // lineno is the source position at the start of the most recently lexed token.
 // TODO(gri) rename and eventually remove
-var lineno src.Pos
+var lineno src.XPos
+
+func MakePos(base *src.PosBase, line, col uint) src.XPos {
+       return Ctxt.PosTable.XPos(src.MakePos(base, line, col))
+}
 
 func isSpace(c rune) bool {
        return c == ' ' || c == '\t' || c == '\n' || c == '\r'
index aa917c735ba6e762dfd2598bdc0991db8a19202a..a1559587692a306aa1c6a41145d3cc00b3bca65e 100644 (file)
@@ -871,7 +871,7 @@ func importfile(f *Val, indent []byte) {
        }
 }
 
-func pkgnotused(lineno src.Pos, path string, name string) {
+func pkgnotused(lineno src.XPos, path string, name string) {
        // If the package was imported with a name other than the final
        // import path element, show it explicitly in the error message.
        // Note that this handles both renamed imports and imports of
index 7376814b433e5d3ffac63c19ffd0cf22c737c7ae..d7e3023102aa52c5cbb60b626aebd85d38e06ee4 100644 (file)
@@ -69,7 +69,7 @@ func (p *noder) file(file *syntax.File) {
        // for fninit and set lineno to NoPos here.
        // TODO(gri) fix this once we switched permanently to the new
        // position information.
-       lineno = src.MakePos(file.Pos().Base(), uint(file.Lines), 0)
+       lineno = MakePos(file.Pos().Base(), uint(file.Lines), 0)
 }
 
 func (p *noder) decls(decls []syntax.Decl) (l []*Node) {
@@ -249,7 +249,7 @@ func (p *noder) funcDecl(fun *syntax.FuncDecl) *Node {
                yyerror("can only use //go:noescape with external func implementations")
        }
        f.Func.Pragma = pragma
-       lineno = src.MakePos(fun.Pos().Base(), fun.EndLine, 0)
+       lineno = MakePos(fun.Pos().Base(), fun.EndLine, 0)
        f.Func.Endlineno = lineno
 
        funcbody(f)
@@ -375,14 +375,14 @@ func (p *noder) expr(expr syntax.Expr) *Node {
                        l[i] = p.wrapname(expr.ElemList[i], e)
                }
                n.List.Set(l)
-               lineno = src.MakePos(expr.Pos().Base(), expr.EndLine, 0)
+               lineno = MakePos(expr.Pos().Base(), expr.EndLine, 0)
                return n
        case *syntax.KeyValueExpr:
                return p.nod(expr, OKEY, p.expr(expr.Key), p.wrapname(expr.Value, p.expr(expr.Value)))
        case *syntax.FuncLit:
                closurehdr(p.typeExpr(expr.Type))
                body := p.stmts(expr.Body)
-               lineno = src.MakePos(expr.Pos().Base(), expr.EndLine, 0)
+               lineno = MakePos(expr.Pos().Base(), expr.EndLine, 0)
                return p.setlineno(expr, closurebody(body))
        case *syntax.ParenExpr:
                return p.nod(expr, OPAREN, p.expr(expr.X), nil)
@@ -1009,7 +1009,7 @@ func (p *noder) setlineno(src_ syntax.Node, dst *Node) *Node {
                // TODO(mdempsky): Shouldn't happen. Fix package syntax.
                return dst
        }
-       dst.Pos = pos
+       dst.Pos = Ctxt.PosTable.XPos(pos)
        return dst
 }
 
@@ -1022,12 +1022,12 @@ func (p *noder) lineno(n syntax.Node) {
                // TODO(mdempsky): Shouldn't happen. Fix package syntax.
                return
        }
-       lineno = pos
+       lineno = Ctxt.PosTable.XPos(pos)
 }
 
 func (p *noder) error(err error) {
        e := err.(syntax.Error)
-       yyerrorl(e.Pos, "%s", e.Msg)
+       yyerrorl(Ctxt.PosTable.XPos(e.Pos), "%s", e.Msg)
 }
 
 func (p *noder) pragma(pos src.Pos, text string) syntax.Pragma {
index 7edb1eaa9dd6de38241fadb443ffbb4090ade5a3..616945685c33e39b7a4d7cde5b181a57abc3dff5 100644 (file)
@@ -511,7 +511,7 @@ func orderstmt(n *Node, order *Order) {
 
                n.Left = orderexpr(n.Left, order, nil)
                n.Left = ordersafeexpr(n.Left, order)
-               tmp1 := treecopy(n.Left, src.NoPos)
+               tmp1 := treecopy(n.Left, src.NoXPos)
                if tmp1.Op == OINDEXMAP {
                        tmp1.Etype = 0 // now an rvalue not an lvalue
                }
index d76d7d845e592c2cfd55ed2c8b662c9a7ad14fbf..8d17536269bf2754a0e8a330ef04728df4d99ff3 100644 (file)
@@ -312,7 +312,7 @@ func compile(fn *Node) {
                assertI2I2 = Sysfunc("assertI2I2")
        }
 
-       defer func(lno src.Pos) {
+       defer func(lno src.XPos) {
                lineno = lno
        }(setlineno(fn))
 
index 330d6b4526bb789c1ca22cb965bb9cc7956cd283..540e144c381068ade63aeb015dcab6cdbaaca593 100644 (file)
@@ -500,7 +500,7 @@ loop:
 }
 
 // lookupVarOutgoing finds the variable's value at the end of block b.
-func (s *simplePhiState) lookupVarOutgoing(b *ssa.Block, t ssa.Type, var_ *Node, line src.Pos) *ssa.Value {
+func (s *simplePhiState) lookupVarOutgoing(b *ssa.Block, t ssa.Type, var_ *Node, line src.XPos) *ssa.Value {
        for {
                if v := s.defvars[b.ID][var_]; v != nil {
                        return v
index 088fa78e1da55c5590575ec911dc9498ef75a341..671ed1eed7ada152114e688e404af21e41404b61 100644 (file)
@@ -496,7 +496,7 @@ func callinstr(np **Node, init *Nodes, wr int, skip int) bool {
                        *np = n
                }
 
-               n = treecopy(n, src.NoPos)
+               n = treecopy(n, src.NoXPos)
                makeaddable(n)
                var f *Node
                if flag_msan {
index d8964fd1d0c4072f6c4676e1db14866879709800..b2239c3526c3f75d54ec326e8bcd913a1556cf38 100644 (file)
@@ -22,14 +22,14 @@ func TestSizeof(t *testing.T) {
                _32bit uintptr     // size on 32bit platforms
                _64bit uintptr     // size on 64bit platforms
        }{
-               {Func{}, 100, 184},
+               {Func{}, 100, 168},
                {Name{}, 44, 72},
                {Param{}, 24, 48},
-               {Node{}, 96, 160},
-               {Sym{}, 64, 128},
-               {Type{}, 64, 112},
+               {Node{}, 96, 152},
+               {Sym{}, 64, 120},
+               {Type{}, 64, 104},
                {MapType{}, 20, 40},
-               {ForwardType{}, 20, 40},
+               {ForwardType{}, 20, 32},
                {FuncType{}, 28, 48},
                {StructType{}, 12, 24},
                {InterType{}, 4, 8},
index 4cdc8696061e05f71df9e5a0fd77b45f340bd9b3..ef60ad7acceeade9dba4fcceaea7992b09839e4c 100644 (file)
@@ -229,7 +229,7 @@ type state struct {
        sb       *ssa.Value
 
        // line number stack. The current line number is top of stack
-       line []src.Pos
+       line []src.XPos
 
        // list of panic calls by function name and line number.
        // Used to deduplicate panic calls.
@@ -243,12 +243,12 @@ type state struct {
 
        cgoUnsafeArgs bool
        noWB          bool
-       WBPos         src.Pos // line number of first write barrier. 0=no write barriers
+       WBPos         src.XPos // line number of first write barrier. 0=no write barriers
 }
 
 type funcLine struct {
        f    *Node
-       line src.Pos
+       line src.XPos
 }
 
 type ssaLabel struct {
@@ -282,7 +282,7 @@ func (s *state) label(sym *Sym) *ssaLabel {
 func (s *state) Logf(msg string, args ...interface{})   { s.config.Logf(msg, args...) }
 func (s *state) Log() bool                              { return s.config.Log() }
 func (s *state) Fatalf(msg string, args ...interface{}) { s.config.Fatalf(s.peekPos(), msg, args...) }
-func (s *state) Warnl(pos src.Pos, msg string, args ...interface{}) {
+func (s *state) Warnl(pos src.XPos, msg string, args ...interface{}) {
        s.config.Warnl(pos, msg, args...)
 }
 func (s *state) Debug_checknil() bool { return s.config.Debug_checknil() }
@@ -331,7 +331,7 @@ func (s *state) endBlock() *ssa.Block {
 }
 
 // pushLine pushes a line number on the line number stack.
-func (s *state) pushLine(line src.Pos) {
+func (s *state) pushLine(line src.XPos) {
        if !line.IsKnown() {
                // the frontend may emit node with line number missing,
                // use the parent line number in this case.
@@ -349,7 +349,7 @@ func (s *state) popLine() {
 }
 
 // peekPos peeks the top of the line number stack.
-func (s *state) peekPos() src.Pos {
+func (s *state) peekPos() src.XPos {
        return s.line[len(s.line)-1]
 }
 
@@ -2361,7 +2361,7 @@ const (
 // If deref is true, rightIsVolatile reports whether right points to volatile (clobbered by a call) storage.
 // Include a write barrier if wb is true.
 // skip indicates assignments (at the top level) that can be avoided.
-func (s *state) assign(left *Node, right *ssa.Value, wb, deref bool, line src.Pos, skip skipMask, rightIsVolatile bool) {
+func (s *state) assign(left *Node, right *ssa.Value, wb, deref bool, line src.XPos, skip skipMask, rightIsVolatile bool) {
        if left.Op == ONAME && isblank(left) {
                return
        }
@@ -3260,7 +3260,7 @@ func canSSAType(t *Type) bool {
 }
 
 // exprPtr evaluates n to a pointer and nil-checks it.
-func (s *state) exprPtr(n *Node, bounded bool, lineno src.Pos) *ssa.Value {
+func (s *state) exprPtr(n *Node, bounded bool, lineno src.XPos) *ssa.Value {
        p := s.expr(n)
        if bounded || n.NonNil {
                if s.f.Config.Debug_checknil() && lineno.Line() > 1 {
@@ -3408,7 +3408,7 @@ func (s *state) rtcall(fn *Node, returns bool, results []*Type, args ...*ssa.Val
 // insertWBmove inserts the assignment *left = *right including a write barrier.
 // t is the type being assigned.
 // If right == nil, then we're zeroing *left.
-func (s *state) insertWBmove(t *Type, left, right *ssa.Value, line src.Pos, rightIsVolatile bool) {
+func (s *state) insertWBmove(t *Type, left, right *ssa.Value, line src.XPos, rightIsVolatile bool) {
        // if writeBarrier.enabled {
        //   typedmemmove(&t, left, right)
        // } else {
@@ -3456,7 +3456,7 @@ func (s *state) insertWBmove(t *Type, left, right *ssa.Value, line src.Pos, righ
 
 // insertWBstore inserts the assignment *left = right including a write barrier.
 // t is the type being assigned.
-func (s *state) insertWBstore(t *Type, left, right *ssa.Value, line src.Pos, skip skipMask) {
+func (s *state) insertWBstore(t *Type, left, right *ssa.Value, line src.XPos, skip skipMask) {
        // store scalar fields
        // if writeBarrier.enabled {
        //   writebarrierptr for pointer fields
@@ -4381,7 +4381,7 @@ func (s *SSAGenState) Pc() *obj.Prog {
 }
 
 // SetPos sets the current source position.
-func (s *SSAGenState) SetPos(pos src.Pos) {
+func (s *SSAGenState) SetPos(pos src.XPos) {
        lineno = pos
 }
 
@@ -4961,7 +4961,7 @@ func (e *ssaExport) CanSSA(t ssa.Type) bool {
        return canSSAType(t.(*Type))
 }
 
-func (e *ssaExport) Line(pos src.Pos) string {
+func (e *ssaExport) Line(pos src.XPos) string {
        return linestr(pos)
 }
 
@@ -4977,14 +4977,14 @@ func (e *ssaExport) Log() bool {
 }
 
 // Fatal reports a compiler error and exits.
-func (e *ssaExport) Fatalf(pos src.Pos, msg string, args ...interface{}) {
+func (e *ssaExport) Fatalf(pos src.XPos, msg string, args ...interface{}) {
        lineno = pos
        Fatalf(msg, args...)
 }
 
 // Warnl reports a "warning", which is usually flag-triggered
 // logging output for the benefit of tests.
-func (e *ssaExport) Warnl(pos src.Pos, fmt_ string, args ...interface{}) {
+func (e *ssaExport) Warnl(pos src.XPos, fmt_ string, args ...interface{}) {
        Warnl(pos, fmt_, args...)
 }
 
index 44a1ab479b824d8c717e9700938285318a58ee3b..fdad1169944c8fd1a1615db5e3811151eeb0843a 100644 (file)
@@ -21,7 +21,7 @@ import (
 )
 
 type Error struct {
-       pos src.Pos
+       pos src.XPos
        msg string
 }
 
@@ -45,7 +45,7 @@ func adderrorname(n *Node) {
        }
 }
 
-func adderr(pos src.Pos, format string, args ...interface{}) {
+func adderr(pos src.XPos, format string, args ...interface{}) {
        errors = append(errors, Error{
                pos: pos,
                msg: fmt.Sprintf("%v: %s\n", linestr(pos), fmt.Sprintf(format, args...)),
@@ -86,25 +86,27 @@ func hcrash() {
        }
 }
 
-func linestr(pos src.Pos) string {
-       return pos.String()
+func linestr(pos src.XPos) string {
+       return Ctxt.PosTable.Pos(pos).String()
 }
 
 // lasterror keeps track of the most recently issued error.
 // It is used to avoid multiple error messages on the same
 // line.
 var lasterror struct {
-       syntax src.Pos // source position of last syntax error
-       other  src.Pos // source position of last non-syntax error
-       msg    string  // error message of last non-syntax error
+       syntax src.XPos // source position of last syntax error
+       other  src.XPos // source position of last non-syntax error
+       msg    string   // error message of last non-syntax error
 }
 
 // sameline reports whether two positions a, b are on the same line.
-func sameline(a, b src.Pos) bool {
-       return a.Filename() == b.Filename() && a.Line() == b.Line()
+func sameline(a, b src.XPos) bool {
+       p := Ctxt.PosTable.Pos(a)
+       q := Ctxt.PosTable.Pos(b)
+       return p.Base() == q.Base() && p.Line() == q.Line()
 }
 
-func yyerrorl(pos src.Pos, format string, args ...interface{}) {
+func yyerrorl(pos src.XPos, format string, args ...interface{}) {
        msg := fmt.Sprintf(format, args...)
 
        if strings.HasPrefix(msg, "syntax error") {
@@ -148,7 +150,7 @@ func Warn(fmt_ string, args ...interface{}) {
        hcrash()
 }
 
-func Warnl(line src.Pos, fmt_ string, args ...interface{}) {
+func Warnl(line src.XPos, fmt_ string, args ...interface{}) {
        adderr(line, fmt_, args...)
        if Debug['m'] != 0 {
                flusherrors()
@@ -186,7 +188,7 @@ func linehistpragma(file string) {
        Ctxt.AddImport(file)
 }
 
-func setlineno(n *Node) src.Pos {
+func setlineno(n *Node) src.XPos {
        lno := lineno
        if n != nil {
                switch n.Op {
@@ -461,7 +463,7 @@ func nodbool(b bool) *Node {
 // Copies of iota ONONAME nodes are assigned the current
 // value of iota_. If pos.IsKnown(), it sets the source
 // position of newly allocated nodes to pos.
-func treecopy(n *Node, pos src.Pos) *Node {
+func treecopy(n *Node, pos src.XPos) *Node {
        if n == nil {
                return nil
        }
@@ -1697,7 +1699,7 @@ func genwrapper(rcvr *Type, method *Field, newnam *Sym, iface int) {
                fmt.Printf("genwrapper rcvrtype=%v method=%v newnam=%v\n", rcvr, method, newnam)
        }
 
-       lineno = src.MakePos(src.NewFileBase("<autogenerated>", "<autogenerated>"), 1, 0)
+       lineno = MakePos(src.NewFileBase("<autogenerated>", "<autogenerated>"), 1, 0)
 
        dclcontext = PEXTERN
        markdcl()
@@ -1968,7 +1970,7 @@ func Simsimtype(t *Type) EType {
        return et
 }
 
-func listtreecopy(l []*Node, pos src.Pos) []*Node {
+func listtreecopy(l []*Node, pos src.XPos) []*Node {
        var out []*Node
        for _, n := range l {
                out = append(out, treecopy(n, pos))
index faeb6e9027de1547721e0ff37a8bfb8ed66518a3..8be9f21df22a6efc96990c99c1a743e984f0fc2a 100644 (file)
@@ -44,7 +44,7 @@ type Node struct {
        // Possibly still more uses. If you find any, document them.
        Xoffset int64
 
-       Pos src.Pos
+       Pos src.XPos
 
        Esc uint16 // EscXXX
 
@@ -310,8 +310,8 @@ type Func struct {
 
        Label int32 // largest auto-generated label in this function
 
-       Endlineno src.Pos
-       WBPos     src.Pos // position of first write barrier
+       Endlineno src.XPos
+       WBPos     src.XPos // position of first write barrier
 
        Pragma          Pragma // go:xxx function annotations
        Dupok           bool   // duplicate definitions ok
index 2f5717a0a58776e5047d6b789e3711939dd27ef4..6143d95f576547596224e2685a055e4a3bce35ab 100644 (file)
@@ -150,9 +150,9 @@ type Type struct {
        sliceOf *Type
        ptrTo   *Type
 
-       Sym    *Sym    // symbol containing name, for named types
-       Vargen int32   // unique name for OTYPE/ONAME
-       Pos    src.Pos // position at which this type was declared, implicitly or explicitly
+       Sym    *Sym     // symbol containing name, for named types
+       Vargen int32    // unique name for OTYPE/ONAME
+       Pos    src.XPos // position at which this type was declared, implicitly or explicitly
 
        Etype      EType // kind of type
        Noalg      bool  // suppress hash and eq algorithm generation
@@ -182,8 +182,8 @@ func (t *Type) MapType() *MapType {
 
 // ForwardType contains Type fields specific to forward types.
 type ForwardType struct {
-       Copyto      []*Node // where to copy the eventual value to
-       Embedlineno src.Pos // first use of this type as an embedded type
+       Copyto      []*Node  // where to copy the eventual value to
+       Embedlineno src.XPos // first use of this type as an embedded type
 }
 
 // ForwardType returns t's extra forward-type-specific fields.
index bbbfb3e6c77214b3c1218ee074eb04d242a89a35..70d9da4b2dfb2589682aecbcebe9c0b75dc30950 100644 (file)
@@ -3500,7 +3500,7 @@ func domethod(n *Node) {
 
 type mapqueueval struct {
        n   *Node
-       lno src.Pos
+       lno src.XPos
 }
 
 // tracks the line numbers at which forward types are first used as map keys
index 0e82873e5281a0a1205b821e136f95d66d823f66..c8e04237b9cbcf763649f884ccc5059e15164386 100644 (file)
@@ -16,7 +16,7 @@ type Block struct {
        ID ID
 
        // Source position for block's control operation
-       Pos src.Pos
+       Pos src.XPos
 
        // The kind of block this is.
        Kind BlockKind
index bbc994d384918ccbd867af4c9e1bb52584ddab6e..02d74673348f76fd9d6e6194cb76334dfadf87e7 100644 (file)
@@ -129,7 +129,7 @@ func (f *Func) dumpFile(phaseName string) {
 
        fi, err := os.Create(fname)
        if err != nil {
-               f.Config.Warnl(src.NoPos, "Unable to create after-phase dump file %s", fname)
+               f.Config.Warnl(src.NoXPos, "Unable to create after-phase dump file %s", fname)
                return
        }
 
index 577e0ff68154f16cdc59d230a155b51499afefcd..1cde6c85302506146e4989871502a11b1da6aa74 100644 (file)
@@ -89,10 +89,10 @@ type Logger interface {
        Log() bool
 
        // Fatal reports a compiler error and exits.
-       Fatalf(pos src.Pos, msg string, args ...interface{})
+       Fatalf(pos src.XPos, msg string, args ...interface{})
 
        // Warnl writes compiler messages in the form expected by "errorcheck" tests
-       Warnl(pos src.Pos, fmt_ string, args ...interface{})
+       Warnl(pos src.XPos, fmt_ string, args ...interface{})
 
        // Fowards the Debug flags from gc
        Debug_checknil() bool
@@ -121,7 +121,7 @@ type Frontend interface {
        SplitInt64(LocalSlot) (LocalSlot, LocalSlot) // returns (hi, lo)
 
        // Line returns a string describing the given position.
-       Line(src.Pos) string
+       Line(src.XPos) string
 
        // AllocFrame assigns frame offsets to all live auto variables.
        AllocFrame(f *Func)
@@ -270,7 +270,7 @@ func NewConfig(arch string, fe Frontend, ctxt *obj.Link, optimize bool) *Config
                c.hasGReg = true
                c.noDuffDevice = true
        default:
-               fe.Fatalf(src.NoPos, "arch %s not implemented", arch)
+               fe.Fatalf(src.NoXPos, "arch %s not implemented", arch)
        }
        c.ctxt = ctxt
        c.optimize = optimize
@@ -310,7 +310,7 @@ func NewConfig(arch string, fe Frontend, ctxt *obj.Link, optimize bool) *Config
        if ev != "" {
                v, err := strconv.ParseInt(ev, 10, 64)
                if err != nil {
-                       fe.Fatalf(src.NoPos, "Environment variable GO_SSA_PHI_LOC_CUTOFF (value '%s') did not parse as a number", ev)
+                       fe.Fatalf(src.NoXPos, "Environment variable GO_SSA_PHI_LOC_CUTOFF (value '%s') did not parse as a number", ev)
                }
                c.sparsePhiCutoff = uint64(v) // convert -1 to maxint, for never use sparse
        }
@@ -332,19 +332,19 @@ func (c *Config) Ctxt() *obj.Link         { return c.ctxt }
 func (c *Config) NewFunc() *Func {
        // TODO(khr): should this function take name, type, etc. as arguments?
        if c.curFunc != nil {
-               c.Fatalf(src.NoPos, "NewFunc called without previous Free")
+               c.Fatalf(src.NoXPos, "NewFunc called without previous Free")
        }
        f := &Func{Config: c, NamedValues: map[LocalSlot][]*Value{}}
        c.curFunc = f
        return f
 }
 
-func (c *Config) Logf(msg string, args ...interface{})                { c.fe.Logf(msg, args...) }
-func (c *Config) Log() bool                                           { return c.fe.Log() }
-func (c *Config) Fatalf(pos src.Pos, msg string, args ...interface{}) { c.fe.Fatalf(pos, msg, args...) }
-func (c *Config) Warnl(pos src.Pos, msg string, args ...interface{})  { c.fe.Warnl(pos, msg, args...) }
-func (c *Config) Debug_checknil() bool                                { return c.fe.Debug_checknil() }
-func (c *Config) Debug_wb() bool                                      { return c.fe.Debug_wb() }
+func (c *Config) Logf(msg string, args ...interface{})                 { c.fe.Logf(msg, args...) }
+func (c *Config) Log() bool                                            { return c.fe.Log() }
+func (c *Config) Fatalf(pos src.XPos, msg string, args ...interface{}) { c.fe.Fatalf(pos, msg, args...) }
+func (c *Config) Warnl(pos src.XPos, msg string, args ...interface{})  { c.fe.Warnl(pos, msg, args...) }
+func (c *Config) Debug_checknil() bool                                 { return c.fe.Debug_checknil() }
+func (c *Config) Debug_wb() bool                                       { return c.fe.Debug_wb() }
 
 func (c *Config) logDebugHashMatch(evname, name string) {
        file := c.logfiles[evname]
@@ -355,7 +355,7 @@ func (c *Config) logDebugHashMatch(evname, name string) {
                        var ok error
                        file, ok = os.Create(tmpfile)
                        if ok != nil {
-                               c.Fatalf(src.NoPos, "Could not open hash-testing logfile %s", tmpfile)
+                               c.Fatalf(src.NoXPos, "Could not open hash-testing logfile %s", tmpfile)
                        }
                }
                c.logfiles[evname] = file
index 68bfb53c2f49c1d59546c8cbac19df24cbe74583..774fb51fc223ca247b6cd3c9e7316b22ab2cd01a 100644 (file)
@@ -113,7 +113,7 @@ func dse(f *Func) {
                                if sz > 0x7fffffff { // work around sparseMap's int32 value type
                                        sz = 0x7fffffff
                                }
-                               shadowed.set(v.Args[0].ID, int32(sz), src.NoPos)
+                               shadowed.set(v.Args[0].ID, int32(sz), src.NoXPos)
                        }
                }
                // walk to previous store
index fdb70ae3edb08b78ba7d09bd84d20a8d305a42ce..11b7658f7816c10f69522ca94071094e9e580ca3 100644 (file)
@@ -63,7 +63,7 @@ func (d DummyFrontend) SplitStruct(s LocalSlot, i int) LocalSlot {
 func (d DummyFrontend) SplitArray(s LocalSlot) LocalSlot {
        return LocalSlot{s.N, s.Type.ElemType(), s.Off}
 }
-func (DummyFrontend) Line(_ src.Pos) string {
+func (DummyFrontend) Line(_ src.XPos) string {
        return "unknown.go:0"
 }
 func (DummyFrontend) AllocFrame(f *Func) {
@@ -75,10 +75,10 @@ func (DummyFrontend) Syslook(s string) interface{} {
 func (d DummyFrontend) Logf(msg string, args ...interface{}) { d.t.Logf(msg, args...) }
 func (d DummyFrontend) Log() bool                            { return true }
 
-func (d DummyFrontend) Fatalf(_ src.Pos, msg string, args ...interface{}) { d.t.Fatalf(msg, args...) }
-func (d DummyFrontend) Warnl(_ src.Pos, msg string, args ...interface{})  { d.t.Logf(msg, args...) }
-func (d DummyFrontend) Debug_checknil() bool                              { return false }
-func (d DummyFrontend) Debug_wb() bool                                    { return false }
+func (d DummyFrontend) Fatalf(_ src.XPos, msg string, args ...interface{}) { d.t.Fatalf(msg, args...) }
+func (d DummyFrontend) Warnl(_ src.XPos, msg string, args ...interface{})  { d.t.Logf(msg, args...) }
+func (d DummyFrontend) Debug_checknil() bool                               { return false }
+func (d DummyFrontend) Debug_wb() bool                                     { return false }
 
 func (d DummyFrontend) TypeBool() Type    { return TypeBool }
 func (d DummyFrontend) TypeInt8() Type    { return TypeInt8 }
index 0acffc546e0c706c798b717e62a563f924e5f35d..e92ae329914c4c6851aa19bd479f27940811a1fc 100644 (file)
@@ -80,7 +80,7 @@ func (f *Func) retSparseSet(ss *sparseSet) {
 }
 
 // newValue allocates a new Value with the given fields and places it at the end of b.Values.
-func (f *Func) newValue(op Op, t Type, b *Block, pos src.Pos) *Value {
+func (f *Func) newValue(op Op, t Type, b *Block, pos src.XPos) *Value {
        var v *Value
        if f.freeValues != nil {
                v = f.freeValues
@@ -187,7 +187,7 @@ func (f *Func) freeBlock(b *Block) {
 }
 
 // NewValue0 returns a new value in the block with no arguments and zero aux values.
-func (b *Block) NewValue0(pos src.Pos, op Op, t Type) *Value {
+func (b *Block) NewValue0(pos src.XPos, op Op, t Type) *Value {
        v := b.Func.newValue(op, t, b, pos)
        v.AuxInt = 0
        v.Args = v.argstorage[:0]
@@ -195,7 +195,7 @@ func (b *Block) NewValue0(pos src.Pos, op Op, t Type) *Value {
 }
 
 // NewValue returns a new value in the block with no arguments and an auxint value.
-func (b *Block) NewValue0I(pos src.Pos, op Op, t Type, auxint int64) *Value {
+func (b *Block) NewValue0I(pos src.XPos, op Op, t Type, auxint int64) *Value {
        v := b.Func.newValue(op, t, b, pos)
        v.AuxInt = auxint
        v.Args = v.argstorage[:0]
@@ -203,7 +203,7 @@ func (b *Block) NewValue0I(pos src.Pos, op Op, t Type, auxint int64) *Value {
 }
 
 // NewValue returns a new value in the block with no arguments and an aux value.
-func (b *Block) NewValue0A(pos src.Pos, op Op, t Type, aux interface{}) *Value {
+func (b *Block) NewValue0A(pos src.XPos, op Op, t Type, aux interface{}) *Value {
        if _, ok := aux.(int64); ok {
                // Disallow int64 aux values. They should be in the auxint field instead.
                // Maybe we want to allow this at some point, but for now we disallow it
@@ -218,7 +218,7 @@ func (b *Block) NewValue0A(pos src.Pos, op Op, t Type, aux interface{}) *Value {
 }
 
 // NewValue returns a new value in the block with no arguments and both an auxint and aux values.
-func (b *Block) NewValue0IA(pos src.Pos, op Op, t Type, auxint int64, aux interface{}) *Value {
+func (b *Block) NewValue0IA(pos src.XPos, op Op, t Type, auxint int64, aux interface{}) *Value {
        v := b.Func.newValue(op, t, b, pos)
        v.AuxInt = auxint
        v.Aux = aux
@@ -227,7 +227,7 @@ func (b *Block) NewValue0IA(pos src.Pos, op Op, t Type, auxint int64, aux interf
 }
 
 // NewValue1 returns a new value in the block with one argument and zero aux values.
-func (b *Block) NewValue1(pos src.Pos, op Op, t Type, arg *Value) *Value {
+func (b *Block) NewValue1(pos src.XPos, op Op, t Type, arg *Value) *Value {
        v := b.Func.newValue(op, t, b, pos)
        v.AuxInt = 0
        v.Args = v.argstorage[:1]
@@ -237,7 +237,7 @@ func (b *Block) NewValue1(pos src.Pos, op Op, t Type, arg *Value) *Value {
 }
 
 // NewValue1I returns a new value in the block with one argument and an auxint value.
-func (b *Block) NewValue1I(pos src.Pos, op Op, t Type, auxint int64, arg *Value) *Value {
+func (b *Block) NewValue1I(pos src.XPos, op Op, t Type, auxint int64, arg *Value) *Value {
        v := b.Func.newValue(op, t, b, pos)
        v.AuxInt = auxint
        v.Args = v.argstorage[:1]
@@ -247,7 +247,7 @@ func (b *Block) NewValue1I(pos src.Pos, op Op, t Type, auxint int64, arg *Value)
 }
 
 // NewValue1A returns a new value in the block with one argument and an aux value.
-func (b *Block) NewValue1A(pos src.Pos, op Op, t Type, aux interface{}, arg *Value) *Value {
+func (b *Block) NewValue1A(pos src.XPos, op Op, t Type, aux interface{}, arg *Value) *Value {
        v := b.Func.newValue(op, t, b, pos)
        v.AuxInt = 0
        v.Aux = aux
@@ -258,7 +258,7 @@ func (b *Block) NewValue1A(pos src.Pos, op Op, t Type, aux interface{}, arg *Val
 }
 
 // NewValue1IA returns a new value in the block with one argument and both an auxint and aux values.
-func (b *Block) NewValue1IA(pos src.Pos, op Op, t Type, auxint int64, aux interface{}, arg *Value) *Value {
+func (b *Block) NewValue1IA(pos src.XPos, op Op, t Type, auxint int64, aux interface{}, arg *Value) *Value {
        v := b.Func.newValue(op, t, b, pos)
        v.AuxInt = auxint
        v.Aux = aux
@@ -269,7 +269,7 @@ func (b *Block) NewValue1IA(pos src.Pos, op Op, t Type, auxint int64, aux interf
 }
 
 // NewValue2 returns a new value in the block with two arguments and zero aux values.
-func (b *Block) NewValue2(pos src.Pos, op Op, t Type, arg0, arg1 *Value) *Value {
+func (b *Block) NewValue2(pos src.XPos, op Op, t Type, arg0, arg1 *Value) *Value {
        v := b.Func.newValue(op, t, b, pos)
        v.AuxInt = 0
        v.Args = v.argstorage[:2]
@@ -281,7 +281,7 @@ func (b *Block) NewValue2(pos src.Pos, op Op, t Type, arg0, arg1 *Value) *Value
 }
 
 // NewValue2I returns a new value in the block with two arguments and an auxint value.
-func (b *Block) NewValue2I(pos src.Pos, op Op, t Type, auxint int64, arg0, arg1 *Value) *Value {
+func (b *Block) NewValue2I(pos src.XPos, op Op, t Type, auxint int64, arg0, arg1 *Value) *Value {
        v := b.Func.newValue(op, t, b, pos)
        v.AuxInt = auxint
        v.Args = v.argstorage[:2]
@@ -293,7 +293,7 @@ func (b *Block) NewValue2I(pos src.Pos, op Op, t Type, auxint int64, arg0, arg1
 }
 
 // NewValue3 returns a new value in the block with three arguments and zero aux values.
-func (b *Block) NewValue3(pos src.Pos, op Op, t Type, arg0, arg1, arg2 *Value) *Value {
+func (b *Block) NewValue3(pos src.XPos, op Op, t Type, arg0, arg1, arg2 *Value) *Value {
        v := b.Func.newValue(op, t, b, pos)
        v.AuxInt = 0
        v.Args = v.argstorage[:3]
@@ -307,7 +307,7 @@ func (b *Block) NewValue3(pos src.Pos, op Op, t Type, arg0, arg1, arg2 *Value) *
 }
 
 // NewValue3I returns a new value in the block with three arguments and an auxint value.
-func (b *Block) NewValue3I(pos src.Pos, op Op, t Type, auxint int64, arg0, arg1, arg2 *Value) *Value {
+func (b *Block) NewValue3I(pos src.XPos, op Op, t Type, auxint int64, arg0, arg1, arg2 *Value) *Value {
        v := b.Func.newValue(op, t, b, pos)
        v.AuxInt = auxint
        v.Args = v.argstorage[:3]
@@ -321,7 +321,7 @@ func (b *Block) NewValue3I(pos src.Pos, op Op, t Type, auxint int64, arg0, arg1,
 }
 
 // NewValue4 returns a new value in the block with four arguments and zero aux values.
-func (b *Block) NewValue4(pos src.Pos, op Op, t Type, arg0, arg1, arg2, arg3 *Value) *Value {
+func (b *Block) NewValue4(pos src.XPos, op Op, t Type, arg0, arg1, arg2, arg3 *Value) *Value {
        v := b.Func.newValue(op, t, b, pos)
        v.AuxInt = 0
        v.Args = []*Value{arg0, arg1, arg2, arg3}
@@ -333,7 +333,7 @@ func (b *Block) NewValue4(pos src.Pos, op Op, t Type, arg0, arg1, arg2, arg3 *Va
 }
 
 // constVal returns a constant value for c.
-func (f *Func) constVal(pos src.Pos, op Op, t Type, c int64, setAux bool) *Value {
+func (f *Func) constVal(pos src.XPos, op Op, t Type, c int64, setAux bool) *Value {
        if f.constants == nil {
                f.constants = make(map[int64][]*Value)
        }
@@ -368,42 +368,42 @@ const (
 )
 
 // ConstInt returns an int constant representing its argument.
-func (f *Func) ConstBool(pos src.Pos, t Type, c bool) *Value {
+func (f *Func) ConstBool(pos src.XPos, t Type, c bool) *Value {
        i := int64(0)
        if c {
                i = 1
        }
        return f.constVal(pos, OpConstBool, t, i, true)
 }
-func (f *Func) ConstInt8(pos src.Pos, t Type, c int8) *Value {
+func (f *Func) ConstInt8(pos src.XPos, t Type, c int8) *Value {
        return f.constVal(pos, OpConst8, t, int64(c), true)
 }
-func (f *Func) ConstInt16(pos src.Pos, t Type, c int16) *Value {
+func (f *Func) ConstInt16(pos src.XPos, t Type, c int16) *Value {
        return f.constVal(pos, OpConst16, t, int64(c), true)
 }
-func (f *Func) ConstInt32(pos src.Pos, t Type, c int32) *Value {
+func (f *Func) ConstInt32(pos src.XPos, t Type, c int32) *Value {
        return f.constVal(pos, OpConst32, t, int64(c), true)
 }
-func (f *Func) ConstInt64(pos src.Pos, t Type, c int64) *Value {
+func (f *Func) ConstInt64(pos src.XPos, t Type, c int64) *Value {
        return f.constVal(pos, OpConst64, t, c, true)
 }
-func (f *Func) ConstFloat32(pos src.Pos, t Type, c float64) *Value {
+func (f *Func) ConstFloat32(pos src.XPos, t Type, c float64) *Value {
        return f.constVal(pos, OpConst32F, t, int64(math.Float64bits(float64(float32(c)))), true)
 }
-func (f *Func) ConstFloat64(pos src.Pos, t Type, c float64) *Value {
+func (f *Func) ConstFloat64(pos src.XPos, t Type, c float64) *Value {
        return f.constVal(pos, OpConst64F, t, int64(math.Float64bits(c)), true)
 }
 
-func (f *Func) ConstSlice(pos src.Pos, t Type) *Value {
+func (f *Func) ConstSlice(pos src.XPos, t Type) *Value {
        return f.constVal(pos, OpConstSlice, t, constSliceMagic, false)
 }
-func (f *Func) ConstInterface(pos src.Pos, t Type) *Value {
+func (f *Func) ConstInterface(pos src.XPos, t Type) *Value {
        return f.constVal(pos, OpConstInterface, t, constInterfaceMagic, false)
 }
-func (f *Func) ConstNil(pos src.Pos, t Type) *Value {
+func (f *Func) ConstNil(pos src.XPos, t Type) *Value {
        return f.constVal(pos, OpConstNil, t, constNilMagic, false)
 }
-func (f *Func) ConstEmptyString(pos src.Pos, t Type) *Value {
+func (f *Func) ConstEmptyString(pos src.XPos, t Type) *Value {
        v := f.constVal(pos, OpConstString, t, constEmptyStringMagic, false)
        v.Aux = ""
        return v
index 2609551f04a6d691264bc0e626f9a7494965b034..580f67717a8f96ee055eaeff6eddc6ab434a417f 100644 (file)
@@ -155,7 +155,7 @@ func Fun(c *Config, entry string, blocs ...bloc) fun {
                blocks[bloc.name] = b
                for _, valu := range bloc.valus {
                        // args are filled in the second pass.
-                       values[valu.name] = b.NewValue0IA(src.NoPos, valu.op, valu.t, valu.auxint, valu.aux)
+                       values[valu.name] = b.NewValue0IA(src.NoXPos, valu.op, valu.t, valu.auxint, valu.aux)
                }
        }
        // Connect the blocks together and specify control values.
@@ -429,12 +429,12 @@ func TestConstCache(t *testing.T) {
                Bloc("entry",
                        Valu("mem", OpInitMem, TypeMem, 0, nil),
                        Exit("mem")))
-       v1 := f.f.ConstBool(src.NoPos, TypeBool, false)
-       v2 := f.f.ConstBool(src.NoPos, TypeBool, true)
+       v1 := f.f.ConstBool(src.NoXPos, TypeBool, false)
+       v2 := f.f.ConstBool(src.NoXPos, TypeBool, true)
        f.f.freeValue(v1)
        f.f.freeValue(v2)
-       v3 := f.f.ConstBool(src.NoPos, TypeBool, false)
-       v4 := f.f.ConstBool(src.NoPos, TypeBool, true)
+       v3 := f.f.ConstBool(src.NoXPos, TypeBool, false)
+       v4 := f.f.ConstBool(src.NoXPos, TypeBool, true)
        if v3.AuxInt != 0 {
                t.Errorf("expected %s to have auxint of 0\n", v3.LongString())
        }
index b9a1f29aa487644695f322898673a5e1a92f27be..085094e3ad5617dca2cac5aa3c0c020b00de3265 100644 (file)
@@ -21,7 +21,7 @@ type HTMLWriter struct {
 func NewHTMLWriter(path string, logger Logger, funcname string) *HTMLWriter {
        out, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
        if err != nil {
-               logger.Fatalf(src.NoPos, "%v", err)
+               logger.Fatalf(src.NoXPos, "%v", err)
        }
        html := HTMLWriter{File: out, Logger: logger}
        html.start(funcname)
@@ -329,13 +329,13 @@ func (w *HTMLWriter) WriteColumn(title string, html string) {
 
 func (w *HTMLWriter) Printf(msg string, v ...interface{}) {
        if _, err := fmt.Fprintf(w.File, msg, v...); err != nil {
-               w.Fatalf(src.NoPos, "%v", err)
+               w.Fatalf(src.NoXPos, "%v", err)
        }
 }
 
 func (w *HTMLWriter) WriteString(s string) {
        if _, err := w.File.WriteString(s); err != nil {
-               w.Fatalf(src.NoPos, "%v", err)
+               w.Fatalf(src.NoXPos, "%v", err)
        }
 }
 
index 27b5624d6652c024c3ce0d78ad454bd1e11535f1..bb25debdd63fc6e4eedc043ac3ea17014effa6e1 100644 (file)
@@ -181,9 +181,9 @@ func pickReg(r regMask) register {
 }
 
 type use struct {
-       dist int32   // distance from start of the block to a use of a value
-       pos  src.Pos // source position of the use
-       next *use    // linked list of uses of a value in nondecreasing dist order
+       dist int32    // distance from start of the block to a use of a value
+       pos  src.XPos // source position of the use
+       next *use     // linked list of uses of a value in nondecreasing dist order
 }
 
 type valState struct {
@@ -288,8 +288,8 @@ type endReg struct {
 
 type startReg struct {
        r   register
-       vid ID      // pre-regalloc value needed in this register
-       pos src.Pos // source position of use of this register
+       vid ID       // pre-regalloc value needed in this register
+       pos src.XPos // source position of use of this register
 }
 
 // freeReg frees up register r. Any current user of r is kicked out.
@@ -411,7 +411,7 @@ func (s *regAllocState) allocReg(mask regMask, v *Value) register {
 // allocated register is marked nospill so the assignment cannot be
 // undone until the caller allows it by clearing nospill. Returns a
 // *Value which is either v or a copy of v allocated to the chosen register.
-func (s *regAllocState) allocValToReg(v *Value, mask regMask, nospill bool, pos src.Pos) *Value {
+func (s *regAllocState) allocValToReg(v *Value, mask regMask, nospill bool, pos src.XPos) *Value {
        vi := &s.values[v.ID]
 
        // Check if v is already in a requested register.
@@ -555,7 +555,7 @@ func (s *regAllocState) init(f *Func) {
                case "s390x":
                        // nothing to do, R10 & R11 already reserved
                default:
-                       s.f.Config.fe.Fatalf(src.NoPos, "arch %s not implemented", s.f.Config.arch)
+                       s.f.Config.fe.Fatalf(src.NoXPos, "arch %s not implemented", s.f.Config.arch)
                }
        }
        if s.f.Config.nacl {
@@ -618,7 +618,7 @@ func (s *regAllocState) init(f *Func) {
 
 // Adds a use record for id at distance dist from the start of the block.
 // All calls to addUse must happen with nonincreasing dist.
-func (s *regAllocState) addUse(id ID, dist int32, pos src.Pos) {
+func (s *regAllocState) addUse(id ID, dist int32, pos src.XPos) {
        r := s.freeUseRecords
        if r != nil {
                s.freeUseRecords = r.next
@@ -1879,17 +1879,17 @@ type edgeState struct {
 }
 
 type contentRecord struct {
-       vid   ID      // pre-regalloc value
-       c     *Value  // cached value
-       final bool    // this is a satisfied destination
-       pos   src.Pos // source position of use of the value
+       vid   ID       // pre-regalloc value
+       c     *Value   // cached value
+       final bool     // this is a satisfied destination
+       pos   src.XPos // source position of use of the value
 }
 
 type dstRecord struct {
        loc    Location // register or stack slot
        vid    ID       // pre-regalloc value it should contain
        splice **Value  // place to store reference to the generating instruction
-       pos    src.Pos  // source position of use of this location
+       pos    src.XPos // source position of use of this location
 }
 
 // setup initializes the edge state for shuffling.
@@ -1912,13 +1912,13 @@ func (e *edgeState) setup(idx int, srcReg []endReg, dstReg []startReg, stacklive
 
        // Live registers can be sources.
        for _, x := range srcReg {
-               e.set(&e.s.registers[x.r], x.v.ID, x.c, false, src.NoPos) // don't care the position of the source
+               e.set(&e.s.registers[x.r], x.v.ID, x.c, false, src.NoXPos) // don't care the position of the source
        }
        // So can all of the spill locations.
        for _, spillID := range stacklive {
                v := e.s.orig[spillID]
                spill := e.s.values[v.ID].spill
-               e.set(e.s.f.getHome(spillID), v.ID, spill, false, src.NoPos) // don't care the position of the source
+               e.set(e.s.f.getHome(spillID), v.ID, spill, false, src.NoXPos) // don't care the position of the source
        }
 
        // Figure out all the destinations we need.
@@ -2018,7 +2018,7 @@ func (e *edgeState) process() {
 
 // processDest generates code to put value vid into location loc. Returns true
 // if progress was made.
-func (e *edgeState) processDest(loc Location, vid ID, splice **Value, pos src.Pos) bool {
+func (e *edgeState) processDest(loc Location, vid ID, splice **Value, pos src.XPos) bool {
        occupant := e.contents[loc]
        if occupant.vid == vid {
                // Value is already in the correct place.
@@ -2140,7 +2140,7 @@ func (e *edgeState) processDest(loc Location, vid ID, splice **Value, pos src.Po
 }
 
 // set changes the contents of location loc to hold the given value and its cached representative.
-func (e *edgeState) set(loc Location, vid ID, c *Value, final bool, pos src.Pos) {
+func (e *edgeState) set(loc Location, vid ID, c *Value, final bool, pos src.XPos) {
        e.s.f.setHome(c, loc)
        e.erase(loc)
        e.contents[loc] = contentRecord{vid, c, final, pos}
@@ -2291,9 +2291,9 @@ func (v *Value) rematerializeable() bool {
 }
 
 type liveInfo struct {
-       ID   ID      // ID of value
-       dist int32   // # of instructions before next use
-       pos  src.Pos // source position of next use
+       ID   ID       // ID of value
+       dist int32    // # of instructions before next use
+       pos  src.XPos // source position of next use
 }
 
 // dblock contains information about desired & avoid registers at the end of a block.
index 7792318e20b232c462aed559179887b011810f99..d49c70a97b8cb53b52eb975c65fd0504b05af07e 100644 (file)
@@ -22,8 +22,8 @@ func TestSizeof(t *testing.T) {
                _32bit uintptr     // size on 32bit platforms
                _64bit uintptr     // size on 64bit platforms
        }{
-               {Value{}, 72, 128},
-               {Block{}, 152, 304},
+               {Value{}, 72, 120},
+               {Block{}, 152, 288},
        }
 
        for _, tt := range tests {
index 9fb0a7d83d0462185c7a4b66c582034b431ceb09..973ab3d43438e7d04451adde01d9f054df0ef368 100644 (file)
@@ -12,7 +12,7 @@ import "cmd/internal/src"
 type sparseEntry struct {
        key ID
        val int32
-       aux src.Pos
+       aux src.XPos
 }
 
 type sparseMap struct {
@@ -45,7 +45,7 @@ func (s *sparseMap) get(k ID) int32 {
        return -1
 }
 
-func (s *sparseMap) set(k ID, v int32, a src.Pos) {
+func (s *sparseMap) set(k ID, v int32, a src.XPos) {
        i := s.sparse[k]
        if i < int32(len(s.dense)) && s.dense[i].key == k {
                s.dense[i].val = v
@@ -66,7 +66,7 @@ func (s *sparseMap) setBit(k ID, v uint) {
                s.dense[i].val |= 1 << v
                return
        }
-       s.dense = append(s.dense, sparseEntry{k, 1 << v, src.NoPos})
+       s.dense = append(s.dense, sparseEntry{k, 1 << v, src.NoXPos})
        s.sparse[k] = int32(len(s.dense)) - 1
 }
 
index f39d7f47e48dff35bd30cb8a34183ee6f6566e97..cdc40e5a35f6f4643400764c1ac7cb24f10f9c79 100644 (file)
@@ -40,7 +40,7 @@ func newStackAllocState(f *Func) *stackAllocState {
                return new(stackAllocState)
        }
        if s.f != nil {
-               f.Config.Fatalf(src.NoPos, "newStackAllocState called without previous free")
+               f.Config.Fatalf(src.NoXPos, "newStackAllocState called without previous free")
        }
        return s
 }
index aeb8e8c7697d7c0d8bf99703755d926bf6bd2497..b9b35b1d981c9c5de8b83243fde47d96af5e8e27 100644 (file)
@@ -38,7 +38,7 @@ type Value struct {
        Block *Block
 
        // Source position
-       Pos src.Pos
+       Pos src.XPos
 
        // Use count. Each appearance in Value.Args and Block.Control counts once.
        Uses int32
index ca477c2917f1b70ae03e25aea868d70013e0dd50..fcca293402a9263d5deaa79feed0add6191335dc 100644 (file)
@@ -240,7 +240,7 @@ func writebarrier(f *Func) {
 
 // wbcall emits write barrier runtime call in b, returns memory.
 // if valIsVolatile, it moves val into temp space before making the call.
-func wbcall(pos src.Pos, b *Block, fn interface{}, typ interface{}, ptr, val, mem, sp, sb *Value, valIsVolatile bool) *Value {
+func wbcall(pos src.XPos, b *Block, fn interface{}, typ interface{}, ptr, val, mem, sp, sb *Value, valIsVolatile bool) *Value {
        config := b.Func.Config
 
        var tmp GCNode
index d1df3900cf51b026eb6c4d927a75063275dbc750..9e1f8ca6651ec138f67929625dbd557d0b4a7f24 100644 (file)
@@ -301,7 +301,8 @@ func linkgetline(ctxt *Link, lineno int32) (f *LSym, l int32) {
 }
 
 // This is modified copy of linkgetline to work from src.Pos.
-func linkgetlineFromPos(ctxt *Link, pos src.Pos) (f *LSym, l int32) {
+func linkgetlineFromPos(ctxt *Link, xpos src.XPos) (f *LSym, l int32) {
+       pos := ctxt.PosTable.Pos(xpos)
        filename := pos.AbsFilename()
        if !pos.IsKnown() || filename == "" {
                return Linklookup(ctxt, "??", HistVersion), 0
index d3a67276765b4209e19dc08d57a53cbbeefe3147..0f9585ed714d65628b7373ce05573b72e1bb6604 100644 (file)
@@ -30,7 +30,7 @@ func TestLinkgetlineFromPos(t *testing.T) {
        }
 
        for _, test := range tests {
-               f, l := linkgetlineFromPos(ctxt, test.pos)
+               f, l := linkgetlineFromPos(ctxt, ctxt.PosTable.XPos(test.pos))
                got := fmt.Sprintf("%s:%d", f.Name, l)
                if got != test.want {
                        t.Errorf("linkgetline(%v) = %q, want %q", test.pos, got, test.want)
index 6d519f048edbc802c919433e6b108856794dd7c8..b32e02daa16db2ba74b58a56211fd0cdd97568ac 100644 (file)
@@ -239,7 +239,7 @@ type Prog struct {
        Forwd  *Prog       // for x86 back end
        Rel    *Prog       // for x86, arm back ends
        Pc     int64       // for back ends or assembler: virtual or actual program counter, depending on phase
-       Pos    src.Pos     // source position of this instruction
+       Pos    src.XPos    // source position of this instruction
        Spadj  int32       // effect of instruction on stack pointer (increment or decrement amount)
        As     As          // assembler opcode
        Reg    int16       // 2nd source operand
@@ -727,6 +727,7 @@ type Link struct {
        Bso           *bufio.Writer
        Pathname      string
        Hash          map[SymVer]*LSym
+       PosTable      src.PosTable
        Imports       []string
        Plists        []*Plist
        Sym_div       *LSym
index 9cebfabd1cf7a3ce931dcb022432ac0897553fee..8051715989e8678d8310dd2f163171c5395926c5 100644 (file)
@@ -24,7 +24,7 @@ func TestSizeof(t *testing.T) {
        }{
                {Addr{}, 40, 64},
                {LSym{}, 76, 128},
-               {Prog{}, 148, 240},
+               {Prog{}, 148, 232},
        }
 
        for _, tt := range tests {
index 2dbbef3bfa26c6ced759b614cce1e591a7b02233..ec6899e67f746274f7c3067016ff6d83b3cbd056 100644 (file)
@@ -59,7 +59,7 @@ func Getgoextlinkenabled() string {
 }
 
 func (p *Prog) Line() string {
-       return p.Pos.String()
+       return p.Ctxt.PosTable.Pos(p.Pos).String()
 }
 
 var armCondCode = []string{
index 7c94c8de769e175fb45579295e11f4a8cb887583..ad124990e811e1e54c6c92e7047c17045238cb30 100644 (file)
@@ -37,6 +37,8 @@ func MakePos(base *PosBase, line, col uint) Pos {
 }
 
 // IsKnown reports whether the position p is known.
+// A position is known if it either has a non-nil
+// position base, or a non-zero line number.
 func (p Pos) IsKnown() bool {
        return p.base != nil || p.Line() != 0
 }
diff --git a/src/cmd/internal/src/xpos.go b/src/cmd/internal/src/xpos.go
new file mode 100644 (file)
index 0000000..db06707
--- /dev/null
@@ -0,0 +1,75 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This file implements the compressed encoding of source
+// positions using a lookup table.
+
+package src
+
+// XPos is a more compact representation of Pos.
+type XPos struct {
+       index int32
+       lico
+}
+
+// NoXPos is a valid unknown position.
+var NoXPos XPos
+
+// IsKnown reports whether the position p is known.
+// XPos.IsKnown() matches Pos.IsKnown() for corresponding
+// positions.
+func (p XPos) IsKnown() bool {
+       return p.index != 0 || p.Line() != 0
+}
+
+// Before reports whether the position p comes before q in the source.
+// For positions with different bases, ordering is by base index.
+func (p XPos) Before(q XPos) bool {
+       n, m := p.index, q.index
+       return n < m || n == m && p.lico < q.lico
+}
+
+// After reports whether the position p comes after q in the source.
+// For positions with different bases, ordering is by base index.
+func (p XPos) After(q XPos) bool {
+       n, m := p.index, q.index
+       return n > m || n == m && p.lico > q.lico
+}
+
+// A PosTable tracks Pos -> XPos conversions and vice versa.
+// Its zero value is a ready-to-use PosTable.
+type PosTable struct {
+       baseList []*PosBase
+       indexMap map[*PosBase]int
+}
+
+// XPos returns the corresponding XPos for the given pos,
+// adding pos to t if necessary.
+func (t *PosTable) XPos(pos Pos) XPos {
+       m := t.indexMap
+       if m == nil {
+               // Create new list and map and populate with nil
+               // base so that NoPos always gets index 0.
+               t.baseList = append(t.baseList, nil)
+               m = map[*PosBase]int{nil: 0}
+               t.indexMap = m
+       }
+       i, ok := m[pos.base]
+       if !ok {
+               i = len(t.baseList)
+               t.baseList = append(t.baseList, pos.base)
+               t.indexMap[pos.base] = i
+       }
+       return XPos{int32(i), pos.lico}
+}
+
+// Pos returns the corresponding Pos for the given p.
+// If p cannot be translated via t, the function panics.
+func (t *PosTable) Pos(p XPos) Pos {
+       var base *PosBase
+       if p.index != 0 {
+               base = t.baseList[p.index]
+       }
+       return Pos{base, p.lico}
+}
diff --git a/src/cmd/internal/src/xpos_test.go b/src/cmd/internal/src/xpos_test.go
new file mode 100644 (file)
index 0000000..274bd76
--- /dev/null
@@ -0,0 +1,67 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package src
+
+import (
+       "testing"
+       "unsafe"
+)
+
+func TestNoXPos(t *testing.T) {
+       var tab PosTable
+       if tab.Pos(NoXPos) != NoPos {
+               t.Errorf("failed to translate NoXPos to Pos using zero PosTable")
+       }
+}
+
+func TestConversion(t *testing.T) {
+       b1 := NewFileBase("b1", "b1")
+       b2 := NewFileBase("b2", "b2")
+       b3 := NewLinePragmaBase(MakePos(b1, 10, 0), "b3", 123)
+
+       var tab PosTable
+       for _, want := range []Pos{
+               NoPos,
+               MakePos(nil, 0, 0), // same table entry as NoPos
+               MakePos(b1, 0, 0),
+               MakePos(nil, 10, 20), // same table entry as NoPos
+               MakePos(b2, 10, 20),
+               MakePos(b3, 10, 20),
+               MakePos(b3, 123, 0), // same table entry as MakePos(b3, 10, 20)
+       } {
+               xpos := tab.XPos(want)
+               got := tab.Pos(xpos)
+               if got != want {
+                       t.Errorf("got %v; want %v", got, want)
+               }
+       }
+
+       if len(tab.baseList) != len(tab.indexMap) {
+               t.Errorf("table length discrepancy: %d != %d", len(tab.baseList), len(tab.indexMap))
+       }
+
+       const wantLen = 4
+       if len(tab.baseList) != wantLen {
+               t.Errorf("got table length %d; want %d", len(tab.baseList), wantLen)
+       }
+
+       if got := tab.XPos(NoPos); got != NoXPos {
+               t.Errorf("XPos(NoPos): got %v; want %v", got, NoXPos)
+       }
+
+       if tab.baseList[0] != nil || tab.indexMap[nil] != 0 {
+               t.Errorf("nil base not at index 0")
+       }
+}
+
+func TestSize(t *testing.T) {
+       var p XPos
+       if unsafe.Alignof(p) != 4 {
+               t.Errorf("alignment = %s; want 4", unsafe.Alignof(p))
+       }
+       if unsafe.Sizeof(p) != 8 {
+               t.Errorf("size = %s; want 8", unsafe.Sizeof(p))
+       }
+}