From: Robert Griesemer Date: Thu, 8 Dec 2016 00:02:42 +0000 (-0800) Subject: [dev.inline] cmd/internal/src: make Pos implementation abstract X-Git-Tag: go1.9beta1~1833^2~21 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=82d0caea2c5041a0d0260ff5ec7f7b61ee2bb0af;p=gostls13.git [dev.inline] cmd/internal/src: make Pos implementation abstract Adjust cmd/compile accordingly. This will make it easier to replace the underlying implementation. Change-Id: I33645850bb18c839b24785b6222a9e028617addb Reviewed-on: https://go-review.googlesource.com/34133 Reviewed-by: David Lazar --- diff --git a/src/cmd/compile/fmt_test.go b/src/cmd/compile/fmt_test.go index 2490e37e24..1a648084f7 100644 --- a/src/cmd/compile/fmt_test.go +++ b/src/cmd/compile/fmt_test.go @@ -654,7 +654,6 @@ var knownFormats = map[string]string{ "cmd/compile/internal/syntax.token %q": "", "cmd/compile/internal/syntax.token %s": "", "cmd/internal/obj.As %v": "", - "cmd/internal/src.Pos %d": "", "error %v": "", "float64 %.2f": "", "float64 %.3f": "", diff --git a/src/cmd/compile/internal/amd64/ssa.go b/src/cmd/compile/internal/amd64/ssa.go index 3c997f20ae..98ea7cadf1 100644 --- a/src/cmd/compile/internal/amd64/ssa.go +++ b/src/cmd/compile/internal/amd64/ssa.go @@ -875,7 +875,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { p.To.Type = obj.TYPE_MEM p.To.Reg = v.Args[0].Reg() gc.AddAux(&p.To, v) - if gc.Debug_checknil != 0 && v.Line > 1 { // v.Line==1 in generated wrappers + if gc.Debug_checknil != 0 && v.Line.Line() > 1 { // v.Line.Line()==1 in generated wrappers gc.Warnl(v.Line, "generated nil check") } case ssa.OpAMD64MOVLatomicload, ssa.OpAMD64MOVQatomicload: diff --git a/src/cmd/compile/internal/arm/ssa.go b/src/cmd/compile/internal/arm/ssa.go index 5a69ed3c3b..799d395208 100644 --- a/src/cmd/compile/internal/arm/ssa.go +++ b/src/cmd/compile/internal/arm/ssa.go @@ -705,7 +705,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { gc.AddAux(&p.From, v) p.To.Type = obj.TYPE_REG p.To.Reg = arm.REGTMP - if gc.Debug_checknil != 0 && v.Line > 1 { // v.Line==1 in generated wrappers + if gc.Debug_checknil != 0 && v.Line.Line() > 1 { // v.Line.Line()==1 in generated wrappers gc.Warnl(v.Line, "generated nil check") } case ssa.OpARMLoweredZero: diff --git a/src/cmd/compile/internal/arm64/ssa.go b/src/cmd/compile/internal/arm64/ssa.go index 5670ef8e96..47976eb91b 100644 --- a/src/cmd/compile/internal/arm64/ssa.go +++ b/src/cmd/compile/internal/arm64/ssa.go @@ -690,7 +690,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { gc.AddAux(&p.From, v) p.To.Type = obj.TYPE_REG p.To.Reg = arm64.REGTMP - if gc.Debug_checknil != 0 && v.Line > 1 { // v.Line==1 in generated wrappers + if gc.Debug_checknil != 0 && v.Line.Line() > 1 { // v.Line==1 in generated wrappers gc.Warnl(v.Line, "generated nil check") } case ssa.OpVarDef: diff --git a/src/cmd/compile/internal/gc/alg.go b/src/cmd/compile/internal/gc/alg.go index 8113710e39..50b75aa09f 100644 --- a/src/cmd/compile/internal/gc/alg.go +++ b/src/cmd/compile/internal/gc/alg.go @@ -4,7 +4,10 @@ package gc -import "fmt" +import ( + "cmd/internal/src" + "fmt" +) // AlgKind describes the kind of algorithms used for comparing and // hashing a Type. @@ -186,7 +189,7 @@ func genhash(sym *Sym, t *Type) { fmt.Printf("genhash %v %v\n", sym, t) } - lineno = 1 // less confusing than end of input + lineno = src.MakePos(1) // less confusing than end of input dclcontext = PEXTERN markdcl() @@ -362,7 +365,7 @@ func geneq(sym *Sym, t *Type) { fmt.Printf("geneq %v %v\n", sym, t) } - lineno = 1 // less confusing than end of input + lineno = src.MakePos(1) // less confusing than end of input dclcontext = PEXTERN markdcl() diff --git a/src/cmd/compile/internal/gc/bexport.go b/src/cmd/compile/internal/gc/bexport.go index 1da5b699a4..c87ab9fb13 100644 --- a/src/cmd/compile/internal/gc/bexport.go +++ b/src/cmd/compile/internal/gc/bexport.go @@ -591,7 +591,7 @@ func (p *exporter) pos(n *Node) { func fileLine(n *Node) (file string, line int) { if n != nil { - file, line = Ctxt.LineHist.AbsFileLine(int(n.Lineno)) + file, line = Ctxt.LineHist.AbsFileLine(int(n.Lineno.Line())) } return } diff --git a/src/cmd/compile/internal/gc/dcl.go b/src/cmd/compile/internal/gc/dcl.go index 460764af3a..4f2254e689 100644 --- a/src/cmd/compile/internal/gc/dcl.go +++ b/src/cmd/compile/internal/gc/dcl.go @@ -114,7 +114,7 @@ func testdclstack() { // redeclare emits a diagnostic about symbol s being redeclared somewhere. func redeclare(s *Sym, where string) { - if s.Lastlineno == 0 { + if !s.Lastlineno.IsKnown() { var tmp string if s.Origpkg != nil { tmp = s.Origpkg.Path @@ -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 { - lno := src.Pos(0) // default is to leave line number alone in listtreecopy + var lno src.Pos // default is to leave line number alone in listtreecopy if len(cl) == 0 { if t != nil { yyerror("const declaration cannot have type without expression") @@ -719,7 +719,7 @@ func checkembeddedtype(t *Type) { if t.IsPtr() || t.IsUnsafePtr() { yyerror("embedded type cannot be a pointer") - } else if t.Etype == TFORW && t.ForwardType().Embedlineno == 0 { + } else if t.Etype == TFORW && !t.ForwardType().Embedlineno.IsKnown() { t.ForwardType().Embedlineno = lineno } } @@ -1355,7 +1355,7 @@ func checknowritebarrierrec() { visitBottomUp(xtop, func(list []*Node, recursive bool) { // Functions with write barriers have depth 0. for _, n := range list { - if n.Func.WBLineno != 0 && n.Func.Pragma&Yeswritebarrierrec == 0 { + if n.Func.WBLineno.IsKnown() && n.Func.Pragma&Yeswritebarrierrec == 0 { c.best[n] = nowritebarrierrecCall{target: nil, depth: 0, lineno: n.Func.WBLineno} } } @@ -1373,7 +1373,7 @@ func checknowritebarrierrec() { // yeswritebarrierrec function. continue } - if n.Func.WBLineno == 0 { + if !n.Func.WBLineno.IsKnown() { c.curfn = n c.visitcodelist(n.Nbody) } diff --git a/src/cmd/compile/internal/gc/fmt.go b/src/cmd/compile/internal/gc/fmt.go index fffce440bc..53889be531 100644 --- a/src/cmd/compile/internal/gc/fmt.go +++ b/src/cmd/compile/internal/gc/fmt.go @@ -283,8 +283,8 @@ func (n *Node) jconv(s fmt.State, flag FmtFlag) { fmt.Fprintf(s, " g(%d)", n.Name.Vargen) } - if n.Lineno != 0 { - fmt.Fprintf(s, " l(%d)", n.Lineno) + if n.Lineno.IsKnown() { + fmt.Fprintf(s, " l(%d)", n.Lineno.Line()) } if c == 0 && n.Xoffset != BADWIDTH { diff --git a/src/cmd/compile/internal/gc/gsubr.go b/src/cmd/compile/internal/gc/gsubr.go index c2784cd6af..3a3effec2f 100644 --- a/src/cmd/compile/internal/gc/gsubr.go +++ b/src/cmd/compile/internal/gc/gsubr.go @@ -40,12 +40,12 @@ func Prog(as obj.As) *obj.Prog { Clearp(pc) p.Link = pc - if lineno == 0 && Debug['K'] != 0 { - Warn("prog: line 0") + if !lineno.IsKnown() && Debug['K'] != 0 { + Warn("prog: unknown position (line 0)") } p.As = as - p.Lineno = int32(lineno) // TODO(gri) fix this + p.Lineno = int32(lineno.Line()) // TODO(gri) fix this return p } diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go index bdca1b1d76..1fe25fa15e 100644 --- a/src/cmd/compile/internal/gc/inl.go +++ b/src/cmd/compile/internal/gc/inl.go @@ -1029,7 +1029,7 @@ func setlno(n *Node, lno src.Pos) { } // don't clobber names, unless they're freshly synthesized - if n.Op != ONAME || n.Lineno == 0 { + if n.Op != ONAME || !n.Lineno.IsKnown() { n.Lineno = lno } diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index 4ed7f1c5dc..0fdb862c28 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -300,7 +300,7 @@ func Main() { blockgen = 1 dclcontext = PEXTERN nerrors = 0 - lexlineno = 1 + lexlineno = src.MakePos(1) timings.Start("fe", "loadsys") loadsys() @@ -320,11 +320,11 @@ func Main() { // Instead of converting EOF into '\n' in getc and count it as an extra line // for the line history to work, and which then has to be corrected elsewhere, // just add a line here. - lexlineno++ + lexlineno = src.MakePos(lexlineno.Line() + 1) linehistpop() } timings.Stop() - timings.AddEvent(int64(lexlineno-lexlineno0), "lines") + timings.AddEvent(int64(lexlineno.Line()-lexlineno0.Line()), "lines") testdclstack() mkpackage(localpkg.Name) // final import not used checks diff --git a/src/cmd/compile/internal/gc/noder.go b/src/cmd/compile/internal/gc/noder.go index 8d3babc544..e52b0c7511 100644 --- a/src/cmd/compile/internal/gc/noder.go +++ b/src/cmd/compile/internal/gc/noder.go @@ -22,7 +22,7 @@ func parseFile(filename string) { } defer src.Close() - p := noder{baseline: lexlineno} + p := noder{baseline: lexlineno.Line()} file, _ := syntax.Parse(src, p.error, p.pragma, 0) // errors are tracked via p.error p.file(file) @@ -40,7 +40,7 @@ func parseFile(filename string) { // noder transforms package syntax's AST into a Nod tree. type noder struct { - baseline src.Pos + baseline int32 linknames []int // tracks //go:linkname lines } @@ -50,7 +50,7 @@ func (p *noder) file(file *syntax.File) { xtop = append(xtop, p.decls(file.DeclList)...) - lexlineno = p.baseline + src.Pos(file.Lines) - 1 + lexlineno = src.MakePos(p.baseline + int32(file.Lines) - 1) lineno = lexlineno } @@ -231,7 +231,7 @@ func (p *noder) funcDecl(fun *syntax.FuncDecl) *Node { yyerror("can only use //go:noescape with external func implementations") } f.Func.Pragma = pragma - lineno = p.baseline + src.Pos(fun.EndLine) - 1 + lineno = src.MakePos(p.baseline + int32(fun.EndLine) - 1) f.Func.Endlineno = lineno funcbody(f) @@ -357,14 +357,14 @@ func (p *noder) expr(expr syntax.Expr) *Node { l[i] = p.wrapname(expr.ElemList[i], e) } n.List.Set(l) - lineno = p.baseline + src.Pos(expr.EndLine) - 1 + lineno = src.MakePos(p.baseline + int32(expr.EndLine) - 1) 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 = p.baseline + src.Pos(expr.EndLine) - 1 + lineno = src.MakePos(p.baseline + int32(expr.EndLine) - 1) return p.setlineno(expr, closurebody(body)) case *syntax.ParenExpr: return p.nod(expr, OPAREN, p.expr(expr.X), nil) @@ -986,12 +986,12 @@ func (p *noder) nod(orig syntax.Node, op Op, left, right *Node) *Node { } func (p *noder) setlineno(src_ syntax.Node, dst *Node) *Node { - l := src.Pos(src_.Line()) + l := src_.Line() if l == 0 { // TODO(mdempsky): Shouldn't happen. Fix package syntax. return dst } - dst.Lineno = p.baseline + l - 1 + dst.Lineno = src.MakePos(p.baseline + int32(l) - 1) return dst } @@ -999,24 +999,24 @@ func (p *noder) lineno(n syntax.Node) { if n == nil { return } - l := src.Pos(n.Line()) + l := n.Line() if l == 0 { // TODO(mdempsky): Shouldn't happen. Fix package syntax. return } - lineno = p.baseline + l - 1 + lineno = src.MakePos(p.baseline + int32(l) - 1) } func (p *noder) error(err error) { line := p.baseline var msg string if err, ok := err.(syntax.Error); ok { - line += src.Pos(err.Line) - 1 + line += int32(err.Line) - 1 msg = err.Msg } else { msg = err.Error() } - yyerrorl(line, "%s", msg) + yyerrorl(src.MakePos(line), "%s", msg) } func (p *noder) pragma(pos, line int, text string) syntax.Pragma { @@ -1039,7 +1039,7 @@ func (p *noder) pragma(pos, line int, text string) syntax.Pragma { if n <= 0 { break } - lexlineno = p.baseline + src.Pos(line) + lexlineno = src.MakePos(p.baseline + int32(line)) linehistupdate(text[5:i], n) case strings.HasPrefix(text, "go:linkname "): diff --git a/src/cmd/compile/internal/gc/order.go b/src/cmd/compile/internal/gc/order.go index e3d65e5e9d..433a89d0d1 100644 --- a/src/cmd/compile/internal/gc/order.go +++ b/src/cmd/compile/internal/gc/order.go @@ -5,6 +5,7 @@ package gc import ( + "cmd/internal/src" "fmt" ) @@ -510,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, 0) + tmp1 := treecopy(n.Left, src.Pos{}) if tmp1.Op == OINDEXMAP { tmp1.Etype = 0 // now an rvalue not an lvalue } diff --git a/src/cmd/compile/internal/gc/plive.go b/src/cmd/compile/internal/gc/plive.go index a6f3735bdf..4cb829cc73 100644 --- a/src/cmd/compile/internal/gc/plive.go +++ b/src/cmd/compile/internal/gc/plive.go @@ -1254,7 +1254,7 @@ func livenessepilogue(lv *Liveness) { if !n.Name.Needzero { n.Name.Needzero = true if debuglive >= 1 { - Warnl(src.Pos(p.Lineno), "%v: %L is ambiguously live", Curfn.Func.Nname, n) + Warnl(src.MakePos(p.Lineno), "%v: %L is ambiguously live", Curfn.Func.Nname, n) } } } @@ -1345,7 +1345,7 @@ func livenessepilogue(lv *Liveness) { } n := lv.vars[j] if n.Class != PPARAM { - yyerrorl(src.Pos(p.Lineno), "internal error: %v %L recorded as live on entry, p.Pc=%v", Curfn.Func.Nname, n, p.Pc) + yyerrorl(src.MakePos(p.Lineno), "internal error: %v %L recorded as live on entry, p.Pc=%v", Curfn.Func.Nname, n, p.Pc) } } } diff --git a/src/cmd/compile/internal/gc/racewalk.go b/src/cmd/compile/internal/gc/racewalk.go index bfb82b91b2..f4a02f3553 100644 --- a/src/cmd/compile/internal/gc/racewalk.go +++ b/src/cmd/compile/internal/gc/racewalk.go @@ -5,6 +5,7 @@ package gc import ( + "cmd/internal/src" "fmt" "strings" ) @@ -495,7 +496,7 @@ func callinstr(np **Node, init *Nodes, wr int, skip int) bool { *np = n } - n = treecopy(n, 0) + n = treecopy(n, src.Pos{}) makeaddable(n) var f *Node if flag_msan { diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 8df8adee59..ae0f49bd63 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -54,7 +54,7 @@ func buildssa(fn *Node) *ssa.Func { s.noWB = true } defer func() { - if s.WBLineno != 0 { + if s.WBLineno.IsKnown() { fn.Func.WBLineno = s.WBLineno } }() @@ -332,12 +332,12 @@ func (s *state) endBlock() *ssa.Block { // pushLine pushes a line number on the line number stack. func (s *state) pushLine(line src.Pos) { - if line == 0 { + if !line.IsKnown() { // the frontend may emit node with line number missing, // use the parent line number in this case. line = s.peekLine() if Debug['K'] != 0 { - Warn("buildssa: line 0") + Warn("buildssa: unknown position (line 0)") } } s.line = append(s.line, line) @@ -3263,7 +3263,7 @@ func canSSAType(t *Type) bool { func (s *state) exprPtr(n *Node, bounded bool, lineno src.Pos) *ssa.Value { p := s.expr(n) if bounded || n.NonNil { - if s.f.Config.Debug_checknil() && lineno > 1 { + if s.f.Config.Debug_checknil() && lineno.Line() > 1 { s.f.Config.Warnl(lineno, "removed nil check") } return p @@ -3426,7 +3426,7 @@ func (s *state) insertWBmove(t *Type, left, right *ssa.Value, line src.Pos, righ if s.noWB { s.Error("write barrier prohibited") } - if s.WBLineno == 0 { + if !s.WBLineno.IsKnown() { s.WBLineno = left.Line } @@ -3467,7 +3467,7 @@ func (s *state) insertWBstore(t *Type, left, right *ssa.Value, line src.Pos, ski if s.noWB { s.Error("write barrier prohibited") } - if s.WBLineno == 0 { + if !s.WBLineno.IsKnown() { s.WBLineno = left.Line } s.storeTypeScalars(t, left, right, skip) diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go index 49bb92beac..f4a5cc97d9 100644 --- a/src/cmd/compile/internal/gc/subr.go +++ b/src/cmd/compile/internal/gc/subr.go @@ -56,7 +56,7 @@ func adderr(line src.Pos, format string, args ...interface{}) { type byLineno []Error func (x byLineno) Len() int { return len(x) } -func (x byLineno) Less(i, j int) bool { return x[i].lineno < x[j].lineno } +func (x byLineno) Less(i, j int) bool { return x[i].lineno.Before(x[j].lineno) } func (x byLineno) Swap(i, j int) { x[i], x[j] = x[j], x[i] } // flusherrors sorts errors seen so far by line number, prints them to stdout, @@ -87,7 +87,7 @@ func hcrash() { } func linestr(line src.Pos) string { - return Ctxt.Line(int(line)) + return Ctxt.Line(int(line.Line())) } // lasterror keeps track of the most recently issued error. @@ -184,21 +184,21 @@ func linehistpush(file string) { if Debug['i'] != 0 { fmt.Printf("import %s at line %v\n", file, linestr(lexlineno)) } - Ctxt.LineHist.Push(int(lexlineno), file) + Ctxt.LineHist.Push(int(lexlineno.Line()), file) } func linehistpop() { if Debug['i'] != 0 { fmt.Printf("end of import at line %v\n", linestr(lexlineno)) } - Ctxt.LineHist.Pop(int(lexlineno)) + Ctxt.LineHist.Pop(int(lexlineno.Line())) } func linehistupdate(file string, off int) { if Debug['i'] != 0 { fmt.Printf("line %s at line %v\n", file, linestr(lexlineno)) } - Ctxt.LineHist.Update(int(lexlineno), file, off) + Ctxt.LineHist.Update(int(lexlineno.Line()), file, off) } func setlineno(n *Node) src.Pos { @@ -216,9 +216,9 @@ func setlineno(n *Node) src.Pos { default: lineno = n.Lineno - if lineno == 0 { + if !lineno.IsKnown() { if Debug['K'] != 0 { - Warn("setlineno: line 0") + Warn("setlineno: unknown position (line 0)") } lineno = lno } @@ -488,7 +488,7 @@ func treecopy(n *Node, lineno src.Pos) *Node { m.Left = treecopy(n.Left, lineno) m.Right = treecopy(n.Right, lineno) m.List.Set(listtreecopy(n.List.Slice(), lineno)) - if lineno != 0 { + if lineno.IsKnown() { m.Lineno = lineno } if m.Name != nil && n.Op != ODCLFIELD { @@ -504,7 +504,7 @@ func treecopy(n *Node, lineno src.Pos) *Node { // so that all the copies of this const definition // don't have the same iota value. m := *n - if lineno != 0 { + if lineno.IsKnown() { m.Lineno = lineno } m.SetIota(iota_) @@ -1714,7 +1714,7 @@ func genwrapper(rcvr *Type, method *Field, newnam *Sym, iface int) { fmt.Printf("genwrapper rcvrtype=%v method=%v newnam=%v\n", rcvr, method, newnam) } - lexlineno++ + lexlineno = src.MakePos(lexlineno.Line() + 1) lineno = lexlineno if genwrapper_linehistdone == 0 { // All the wrappers can share the same linehist entry. diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go index 27bb6ed954..8da07c4ccd 100644 --- a/src/cmd/compile/internal/gc/typecheck.go +++ b/src/cmd/compile/internal/gc/typecheck.go @@ -3548,7 +3548,7 @@ func copytype(n *Node, t *Type) { // Double-check use of type as embedded type. lno := lineno - if embedlineno != 0 { + if embedlineno.IsKnown() { lineno = embedlineno if t.IsPtr() || t.IsUnsafePtr() { yyerror("embedded type cannot be a pointer") @@ -3629,7 +3629,7 @@ func typecheckdef(n *Node) *Node { if n.Op == ONONAME { if !n.Diag { n.Diag = true - if n.Lineno != 0 { + if n.Lineno.IsKnown() { lineno = n.Lineno } diff --git a/src/cmd/compile/internal/gc/util.go b/src/cmd/compile/internal/gc/util.go index bb5cede5a6..adc8518bf4 100644 --- a/src/cmd/compile/internal/gc/util.go +++ b/src/cmd/compile/internal/gc/util.go @@ -11,7 +11,7 @@ import ( ) func (n *Node) Line() string { - return Ctxt.LineHist.LineString(int(n.Lineno)) + return Ctxt.LineHist.LineString(int(n.Lineno.Line())) } var atExitFuncs []func() diff --git a/src/cmd/compile/internal/mips/ssa.go b/src/cmd/compile/internal/mips/ssa.go index aef1f90969..15ff16aa12 100644 --- a/src/cmd/compile/internal/mips/ssa.go +++ b/src/cmd/compile/internal/mips/ssa.go @@ -796,7 +796,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { gc.AddAux(&p.From, v) p.To.Type = obj.TYPE_REG p.To.Reg = mips.REGTMP - if gc.Debug_checknil != 0 && v.Line > 1 { // v.Line==1 in generated wrappers + if gc.Debug_checknil != 0 && v.Line.Line() > 1 { // v.Line==1 in generated wrappers gc.Warnl(v.Line, "generated nil check") } case ssa.OpMIPSFPFlagTrue, diff --git a/src/cmd/compile/internal/mips64/ssa.go b/src/cmd/compile/internal/mips64/ssa.go index 1432c6ceea..d6c00d1a50 100644 --- a/src/cmd/compile/internal/mips64/ssa.go +++ b/src/cmd/compile/internal/mips64/ssa.go @@ -548,7 +548,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { gc.AddAux(&p.From, v) p.To.Type = obj.TYPE_REG p.To.Reg = mips.REGTMP - if gc.Debug_checknil != 0 && v.Line > 1 { // v.Line==1 in generated wrappers + if gc.Debug_checknil != 0 && v.Line.Line() > 1 { // v.Line==1 in generated wrappers gc.Warnl(v.Line, "generated nil check") } case ssa.OpVarDef: diff --git a/src/cmd/compile/internal/ppc64/ssa.go b/src/cmd/compile/internal/ppc64/ssa.go index 8387692f86..3f36096565 100644 --- a/src/cmd/compile/internal/ppc64/ssa.go +++ b/src/cmd/compile/internal/ppc64/ssa.go @@ -803,7 +803,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { gc.AddAux(&p.From, v) p.To.Type = obj.TYPE_REG p.To.Reg = ppc64.REGTMP - if gc.Debug_checknil != 0 && v.Line > 1 { // v.Line==1 in generated wrappers + if gc.Debug_checknil != 0 && v.Line.Line() > 1 { // v.Line==1 in generated wrappers gc.Warnl(v.Line, "generated nil check") } diff --git a/src/cmd/compile/internal/s390x/ssa.go b/src/cmd/compile/internal/s390x/ssa.go index e2d3c2849b..61bf228d09 100644 --- a/src/cmd/compile/internal/s390x/ssa.go +++ b/src/cmd/compile/internal/s390x/ssa.go @@ -570,7 +570,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { gc.AddAux(&p.From, v) p.To.Type = obj.TYPE_REG p.To.Reg = s390x.REGTMP - if gc.Debug_checknil != 0 && v.Line > 1 { // v.Line==1 in generated wrappers + if gc.Debug_checknil != 0 && v.Line.Line() > 1 { // v.Line==1 in generated wrappers gc.Warnl(v.Line, "generated nil check") } case ssa.OpS390XMVC: diff --git a/src/cmd/compile/internal/ssa/compile.go b/src/cmd/compile/internal/ssa/compile.go index b9ec7eb6b7..6fe731d1a3 100644 --- a/src/cmd/compile/internal/ssa/compile.go +++ b/src/cmd/compile/internal/ssa/compile.go @@ -5,6 +5,7 @@ package ssa import ( + "cmd/internal/src" "fmt" "log" "os" @@ -128,7 +129,7 @@ func (f *Func) dumpFile(phaseName string) { fi, err := os.Create(fname) if err != nil { - f.Config.Warnl(0, "Unable to create after-phase dump file %s", fname) + f.Config.Warnl(src.Pos{}, "Unable to create after-phase dump file %s", fname) return } diff --git a/src/cmd/compile/internal/ssa/config.go b/src/cmd/compile/internal/ssa/config.go index 031925e2fd..3cb9d9edb0 100644 --- a/src/cmd/compile/internal/ssa/config.go +++ b/src/cmd/compile/internal/ssa/config.go @@ -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(0, "arch %s not implemented", arch) + fe.Fatalf(src.Pos{}, "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(0, "Environment variable GO_SSA_PHI_LOC_CUTOFF (value '%s') did not parse as a number", ev) + fe.Fatalf(src.Pos{}, "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,7 +332,7 @@ 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(0, "NewFunc called without previous Free") + c.Fatalf(src.Pos{}, "NewFunc called without previous Free") } f := &Func{Config: c, NamedValues: map[LocalSlot][]*Value{}} c.curFunc = f @@ -357,7 +357,7 @@ func (c *Config) logDebugHashMatch(evname, name string) { var ok error file, ok = os.Create(tmpfile) if ok != nil { - c.Fatalf(0, "Could not open hash-testing logfile %s", tmpfile) + c.Fatalf(src.Pos{}, "Could not open hash-testing logfile %s", tmpfile) } } c.logfiles[evname] = file diff --git a/src/cmd/compile/internal/ssa/deadstore.go b/src/cmd/compile/internal/ssa/deadstore.go index 89ab17a427..0a4862be94 100644 --- a/src/cmd/compile/internal/ssa/deadstore.go +++ b/src/cmd/compile/internal/ssa/deadstore.go @@ -4,6 +4,8 @@ package ssa +import "cmd/internal/src" + // dse does dead-store elimination on the Function. // Dead stores are those which are unconditionally followed by // another store to the same location, with no intervening load. @@ -111,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), 0) + shadowed.set(v.Args[0].ID, int32(sz), src.Pos{}) } } // walk to previous store diff --git a/src/cmd/compile/internal/ssa/func_test.go b/src/cmd/compile/internal/ssa/func_test.go index 7136d8fb08..81f1c33cde 100644 --- a/src/cmd/compile/internal/ssa/func_test.go +++ b/src/cmd/compile/internal/ssa/func_test.go @@ -37,6 +37,7 @@ package ssa // the parser can be used instead of Fun. import ( + "cmd/internal/src" "fmt" "reflect" "testing" @@ -154,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(0, valu.op, valu.t, valu.auxint, valu.aux) + values[valu.name] = b.NewValue0IA(src.Pos{}, valu.op, valu.t, valu.auxint, valu.aux) } } // Connect the blocks together and specify control values. @@ -428,12 +429,12 @@ func TestConstCache(t *testing.T) { Bloc("entry", Valu("mem", OpInitMem, TypeMem, 0, nil), Exit("mem"))) - v1 := f.f.ConstBool(0, TypeBool, false) - v2 := f.f.ConstBool(0, TypeBool, true) + v1 := f.f.ConstBool(src.Pos{}, TypeBool, false) + v2 := f.f.ConstBool(src.Pos{}, TypeBool, true) f.f.freeValue(v1) f.f.freeValue(v2) - v3 := f.f.ConstBool(0, TypeBool, false) - v4 := f.f.ConstBool(0, TypeBool, true) + v3 := f.f.ConstBool(src.Pos{}, TypeBool, false) + v4 := f.f.ConstBool(src.Pos{}, TypeBool, true) if v3.AuxInt != 0 { t.Errorf("expected %s to have auxint of 0\n", v3.LongString()) } diff --git a/src/cmd/compile/internal/ssa/html.go b/src/cmd/compile/internal/ssa/html.go index 316fd2aa25..355dc75e75 100644 --- a/src/cmd/compile/internal/ssa/html.go +++ b/src/cmd/compile/internal/ssa/html.go @@ -6,6 +6,7 @@ package ssa import ( "bytes" + "cmd/internal/src" "fmt" "html" "io" @@ -20,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(0, "%v", err) + logger.Fatalf(src.Pos{}, "%v", err) } html := HTMLWriter{File: out, Logger: logger} html.start(funcname) @@ -328,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(0, "%v", err) + w.Fatalf(src.Pos{}, "%v", err) } } func (w *HTMLWriter) WriteString(s string) { if _, err := w.File.WriteString(s); err != nil { - w.Fatalf(0, "%v", err) + w.Fatalf(src.Pos{}, "%v", err) } } diff --git a/src/cmd/compile/internal/ssa/nilcheck.go b/src/cmd/compile/internal/ssa/nilcheck.go index eb2d297f80..6345332ac1 100644 --- a/src/cmd/compile/internal/ssa/nilcheck.go +++ b/src/cmd/compile/internal/ssa/nilcheck.go @@ -101,7 +101,7 @@ func nilcheckelim(f *Func) { // This is a redundant implicit nil check. // Logging in the style of the former compiler -- and omit line 1, // which is usually in generated code. - if f.Config.Debug_checknil() && v.Line > 1 { + if f.Config.Debug_checknil() && v.Line.Line() > 1 { f.Config.Warnl(v.Line, "removed nil check") } v.reset(OpUnknown) @@ -147,7 +147,7 @@ func nilcheckelim2(f *Func) { for i := len(b.Values) - 1; i >= 0; i-- { v := b.Values[i] if opcodeTable[v.Op].nilCheck && unnecessary.contains(v.Args[0].ID) { - if f.Config.Debug_checknil() && int(v.Line) > 1 { + if f.Config.Debug_checknil() && v.Line.Line() > 1 { f.Config.Warnl(v.Line, "removed nil check") } v.reset(OpUnknown) diff --git a/src/cmd/compile/internal/ssa/regalloc.go b/src/cmd/compile/internal/ssa/regalloc.go index 9eecbdf57c..db68dda4d9 100644 --- a/src/cmd/compile/internal/ssa/regalloc.go +++ b/src/cmd/compile/internal/ssa/regalloc.go @@ -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(0, "arch %s not implemented", s.f.Config.arch) + s.f.Config.fe.Fatalf(src.Pos{}, "arch %s not implemented", s.f.Config.arch) } } if s.f.Config.nacl { @@ -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, 0) // don't care the line number of the source + e.set(&e.s.registers[x.r], x.v.ID, x.c, false, src.Pos{}) // don't care the line number 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, 0) // don't care the line number of the source + e.set(e.s.f.getHome(spillID), v.ID, spill, false, src.Pos{}) // don't care the line number of the source } // Figure out all the destinations we need. diff --git a/src/cmd/compile/internal/ssa/rewritegeneric.go b/src/cmd/compile/internal/ssa/rewritegeneric.go index 1a2eacccf8..0d582436ae 100644 --- a/src/cmd/compile/internal/ssa/rewritegeneric.go +++ b/src/cmd/compile/internal/ssa/rewritegeneric.go @@ -6526,7 +6526,7 @@ func rewriteValuegeneric_OpNilCheck(v *Value, config *Config) bool { return true } // match: (NilCheck (Load (OffPtr [c] (SP)) mem) mem) - // cond: mem.Op == OpStaticCall && isSameSym(mem.Aux, "runtime.newobject") && c == config.ctxt.FixedFrameSize() + config.RegSize && warnRule(config.Debug_checknil() && int(v.Line) > 1, v, "removed nil check") + // cond: mem.Op == OpStaticCall && isSameSym(mem.Aux, "runtime.newobject") && c == config.ctxt.FixedFrameSize() + config.RegSize && warnRule(config.Debug_checknil() && v.Line.Line() > 1, v, "removed nil check") // result: (Invalid) for { v_0 := v.Args[0] @@ -6546,14 +6546,14 @@ func rewriteValuegeneric_OpNilCheck(v *Value, config *Config) bool { if mem != v.Args[1] { break } - if !(mem.Op == OpStaticCall && isSameSym(mem.Aux, "runtime.newobject") && c == config.ctxt.FixedFrameSize()+config.RegSize && warnRule(config.Debug_checknil() && int(v.Line) > 1, v, "removed nil check")) { + if !(mem.Op == OpStaticCall && isSameSym(mem.Aux, "runtime.newobject") && c == config.ctxt.FixedFrameSize()+config.RegSize && warnRule(config.Debug_checknil() && v.Line.Line() > 1, v, "removed nil check")) { break } v.reset(OpInvalid) return true } // match: (NilCheck (OffPtr (Load (OffPtr [c] (SP)) mem)) mem) - // cond: mem.Op == OpStaticCall && isSameSym(mem.Aux, "runtime.newobject") && c == config.ctxt.FixedFrameSize() + config.RegSize && warnRule(config.Debug_checknil() && int(v.Line) > 1, v, "removed nil check") + // cond: mem.Op == OpStaticCall && isSameSym(mem.Aux, "runtime.newobject") && c == config.ctxt.FixedFrameSize() + config.RegSize && warnRule(config.Debug_checknil() && v.Line.Line() > 1, v, "removed nil check") // result: (Invalid) for { v_0 := v.Args[0] @@ -6577,7 +6577,7 @@ func rewriteValuegeneric_OpNilCheck(v *Value, config *Config) bool { if mem != v.Args[1] { break } - if !(mem.Op == OpStaticCall && isSameSym(mem.Aux, "runtime.newobject") && c == config.ctxt.FixedFrameSize()+config.RegSize && warnRule(config.Debug_checknil() && int(v.Line) > 1, v, "removed nil check")) { + if !(mem.Op == OpStaticCall && isSameSym(mem.Aux, "runtime.newobject") && c == config.ctxt.FixedFrameSize()+config.RegSize && warnRule(config.Debug_checknil() && v.Line.Line() > 1, v, "removed nil check")) { break } v.reset(OpInvalid) diff --git a/src/cmd/compile/internal/ssa/schedule.go b/src/cmd/compile/internal/ssa/schedule.go index f2a89d82d8..69c5cccd73 100644 --- a/src/cmd/compile/internal/ssa/schedule.go +++ b/src/cmd/compile/internal/ssa/schedule.go @@ -47,7 +47,7 @@ func (h ValHeap) Less(i, j int) bool { return c > 0 // higher score comes later. } if x.Line != y.Line { // Favor in-order line stepping - return x.Line > y.Line + return x.Line.After(y.Line) } if x.Op != OpPhi { if c := len(x.Args) - len(y.Args); c != 0 { diff --git a/src/cmd/compile/internal/ssa/sparsemap.go b/src/cmd/compile/internal/ssa/sparsemap.go index 3bc4eb9d78..d2a07e2534 100644 --- a/src/cmd/compile/internal/ssa/sparsemap.go +++ b/src/cmd/compile/internal/ssa/sparsemap.go @@ -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, 0}) + s.dense = append(s.dense, sparseEntry{k, 1 << v, src.Pos{}}) s.sparse[k] = int32(len(s.dense)) - 1 } diff --git a/src/cmd/compile/internal/ssa/stackalloc.go b/src/cmd/compile/internal/ssa/stackalloc.go index dc2fd7d33b..599dc934f1 100644 --- a/src/cmd/compile/internal/ssa/stackalloc.go +++ b/src/cmd/compile/internal/ssa/stackalloc.go @@ -6,7 +6,10 @@ package ssa -import "fmt" +import ( + "cmd/internal/src" + "fmt" +) type stackAllocState struct { f *Func @@ -37,7 +40,7 @@ func newStackAllocState(f *Func) *stackAllocState { return new(stackAllocState) } if s.f != nil { - f.Config.Fatalf(0, "newStackAllocState called without previous free") + f.Config.Fatalf(src.Pos{}, "newStackAllocState called without previous free") } return s } diff --git a/src/cmd/compile/internal/x86/ssa.go b/src/cmd/compile/internal/x86/ssa.go index 21be63426a..52c3eebb20 100644 --- a/src/cmd/compile/internal/x86/ssa.go +++ b/src/cmd/compile/internal/x86/ssa.go @@ -788,7 +788,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { p.To.Type = obj.TYPE_MEM p.To.Reg = v.Args[0].Reg() gc.AddAux(&p.To, v) - if gc.Debug_checknil != 0 && v.Line > 1 { // v.Line==1 in generated wrappers + if gc.Debug_checknil != 0 && v.Line.Line() > 1 { // v.Line==1 in generated wrappers gc.Warnl(v.Line, "generated nil check") } case ssa.Op386FCHS: diff --git a/src/cmd/internal/src/src.go b/src/cmd/internal/src/src.go index 2c3aef9efe..8691a9aa74 100644 --- a/src/cmd/internal/src/src.go +++ b/src/cmd/internal/src/src.go @@ -5,7 +5,25 @@ // Package src implements source positions. package src +// Implementation note: This is a thin abstraction over +// the historic representation of source positions via +// global line numbers. The abstraction will make it +// easier to replace this implementation, eventually. + // A Pos represents a source position. -// It is an index into the global line table, which -// maps a Pos to a file name and source line number. -type Pos int32 +// The zero value for a Pos is a valid unknown position. +type Pos struct { + // line is an index into the global line table, which maps + // the corresponding Pos to a file name and source line number. + line int32 +} + +// MakePos creates a new Pos from a line index. +// It requires intimate knowledge of the underlying +// implementation and should be used with caution. +func MakePos(line int32) Pos { return Pos{line} } + +func (p Pos) IsKnown() bool { return p.line != 0 } +func (p Pos) Line() int32 { return p.line } +func (p Pos) Before(q Pos) bool { return p.line < q.line } +func (p Pos) After(q Pos) bool { return p.line > q.line }