mirror of
https://github.com/golang/go
synced 2024-11-12 00:20:22 -07:00
[dev.inline] cmd/internal/src: introduce compact source position representation
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>
This commit is contained in:
parent
4808fc4443
commit
472c792e0a
@ -85,8 +85,8 @@ func (p *Parser) errorf(format string, args ...interface{}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Parser) pos() src.Pos {
|
func (p *Parser) pos() src.XPos {
|
||||||
return src.MakePos(p.lex.Base(), uint(p.lineNum), 0)
|
return p.ctxt.PosTable.XPos(src.MakePos(p.lex.Base(), uint(p.lineNum), 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Parser) Parse() (*obj.Prog, bool) {
|
func (p *Parser) Parse() (*obj.Prog, bool) {
|
||||||
|
@ -4,10 +4,7 @@
|
|||||||
|
|
||||||
package gc
|
package gc
|
||||||
|
|
||||||
import (
|
import "fmt"
|
||||||
"cmd/internal/src"
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// AlgKind describes the kind of algorithms used for comparing and
|
// AlgKind describes the kind of algorithms used for comparing and
|
||||||
// hashing a Type.
|
// hashing a Type.
|
||||||
@ -189,7 +186,7 @@ func genhash(sym *Sym, t *Type) {
|
|||||||
fmt.Printf("genhash %v %v\n", sym, t)
|
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
|
dclcontext = PEXTERN
|
||||||
markdcl()
|
markdcl()
|
||||||
|
|
||||||
@ -365,7 +362,7 @@ func geneq(sym *Sym, t *Type) {
|
|||||||
fmt.Printf("geneq %v %v\n", sym, t)
|
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
|
dclcontext = PEXTERN
|
||||||
markdcl()
|
markdcl()
|
||||||
|
|
||||||
|
@ -591,8 +591,9 @@ func (p *exporter) pos(n *Node) {
|
|||||||
|
|
||||||
func fileLine(n *Node) (file string, line int) {
|
func fileLine(n *Node) (file string, line int) {
|
||||||
if n != nil {
|
if n != nil {
|
||||||
file = n.Pos.AbsFilename()
|
pos := Ctxt.PosTable.Pos(n.Pos)
|
||||||
line = int(n.Pos.Line())
|
file = pos.AbsFilename()
|
||||||
|
line = int(pos.Line())
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -679,7 +679,7 @@ func evconst(n *Node) {
|
|||||||
|
|
||||||
nr := n.Right
|
nr := n.Right
|
||||||
var rv Val
|
var rv Val
|
||||||
var lno src.Pos
|
var lno src.XPos
|
||||||
var wr EType
|
var wr EType
|
||||||
var v Val
|
var v Val
|
||||||
var norig *Node
|
var norig *Node
|
||||||
|
@ -288,7 +288,7 @@ func variter(vl []*Node, t *Node, el []*Node) []*Node {
|
|||||||
// declare constants from grammar
|
// declare constants from grammar
|
||||||
// new_name_list [[type] = expr_list]
|
// new_name_list [[type] = expr_list]
|
||||||
func constiter(vl []*Node, t *Node, cl []*Node) []*Node {
|
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 len(cl) == 0 {
|
||||||
if t != nil {
|
if t != nil {
|
||||||
yyerror("const declaration cannot have type without expression")
|
yyerror("const declaration cannot have type without expression")
|
||||||
@ -1345,7 +1345,7 @@ type nowritebarrierrecChecker struct {
|
|||||||
type nowritebarrierrecCall struct {
|
type nowritebarrierrecCall struct {
|
||||||
target *Node
|
target *Node
|
||||||
depth int
|
depth int
|
||||||
lineno src.Pos
|
lineno src.XPos
|
||||||
}
|
}
|
||||||
|
|
||||||
func checknowritebarrierrec() {
|
func checknowritebarrierrec() {
|
||||||
|
@ -43,10 +43,10 @@ type Sym struct {
|
|||||||
|
|
||||||
// saved and restored by dcopy
|
// saved and restored by dcopy
|
||||||
Pkg *Pkg
|
Pkg *Pkg
|
||||||
Name string // object name
|
Name string // object name
|
||||||
Def *Node // definition: ONAME OTYPE OPACK or OLITERAL
|
Def *Node // definition: ONAME OTYPE OPACK or OLITERAL
|
||||||
Block int32 // blocknumber to catch redeclaration
|
Block int32 // blocknumber to catch redeclaration
|
||||||
Lastlineno src.Pos // last declaration for diagnostic
|
Lastlineno src.XPos // last declaration for diagnostic
|
||||||
|
|
||||||
Label *Node // corresponding label (ephemeral)
|
Label *Node // corresponding label (ephemeral)
|
||||||
Origpkg *Pkg // original package for . import
|
Origpkg *Pkg // original package for . import
|
||||||
|
@ -1017,13 +1017,13 @@ func (subst *inlsubst) node(n *Node) *Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Plaster over linenumbers
|
// Plaster over linenumbers
|
||||||
func setlnolist(ll Nodes, lno src.Pos) {
|
func setlnolist(ll Nodes, lno src.XPos) {
|
||||||
for _, n := range ll.Slice() {
|
for _, n := range ll.Slice() {
|
||||||
setlno(n, lno)
|
setlno(n, lno)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func setlno(n *Node, lno src.Pos) {
|
func setlno(n *Node, lno src.XPos) {
|
||||||
if n == nil {
|
if n == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,11 @@ import (
|
|||||||
|
|
||||||
// lineno is the source position at the start of the most recently lexed token.
|
// lineno is the source position at the start of the most recently lexed token.
|
||||||
// TODO(gri) rename and eventually remove
|
// 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 {
|
func isSpace(c rune) bool {
|
||||||
return c == ' ' || c == '\t' || c == '\n' || c == '\r'
|
return c == ' ' || c == '\t' || c == '\n' || c == '\r'
|
||||||
|
@ -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
|
// If the package was imported with a name other than the final
|
||||||
// import path element, show it explicitly in the error message.
|
// import path element, show it explicitly in the error message.
|
||||||
// Note that this handles both renamed imports and imports of
|
// Note that this handles both renamed imports and imports of
|
||||||
|
@ -69,7 +69,7 @@ func (p *noder) file(file *syntax.File) {
|
|||||||
// for fninit and set lineno to NoPos here.
|
// for fninit and set lineno to NoPos here.
|
||||||
// TODO(gri) fix this once we switched permanently to the new
|
// TODO(gri) fix this once we switched permanently to the new
|
||||||
// position information.
|
// 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) {
|
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")
|
yyerror("can only use //go:noescape with external func implementations")
|
||||||
}
|
}
|
||||||
f.Func.Pragma = pragma
|
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
|
f.Func.Endlineno = lineno
|
||||||
|
|
||||||
funcbody(f)
|
funcbody(f)
|
||||||
@ -375,14 +375,14 @@ func (p *noder) expr(expr syntax.Expr) *Node {
|
|||||||
l[i] = p.wrapname(expr.ElemList[i], e)
|
l[i] = p.wrapname(expr.ElemList[i], e)
|
||||||
}
|
}
|
||||||
n.List.Set(l)
|
n.List.Set(l)
|
||||||
lineno = src.MakePos(expr.Pos().Base(), expr.EndLine, 0)
|
lineno = MakePos(expr.Pos().Base(), expr.EndLine, 0)
|
||||||
return n
|
return n
|
||||||
case *syntax.KeyValueExpr:
|
case *syntax.KeyValueExpr:
|
||||||
return p.nod(expr, OKEY, p.expr(expr.Key), p.wrapname(expr.Value, p.expr(expr.Value)))
|
return p.nod(expr, OKEY, p.expr(expr.Key), p.wrapname(expr.Value, p.expr(expr.Value)))
|
||||||
case *syntax.FuncLit:
|
case *syntax.FuncLit:
|
||||||
closurehdr(p.typeExpr(expr.Type))
|
closurehdr(p.typeExpr(expr.Type))
|
||||||
body := p.stmts(expr.Body)
|
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))
|
return p.setlineno(expr, closurebody(body))
|
||||||
case *syntax.ParenExpr:
|
case *syntax.ParenExpr:
|
||||||
return p.nod(expr, OPAREN, p.expr(expr.X), nil)
|
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.
|
// TODO(mdempsky): Shouldn't happen. Fix package syntax.
|
||||||
return dst
|
return dst
|
||||||
}
|
}
|
||||||
dst.Pos = pos
|
dst.Pos = Ctxt.PosTable.XPos(pos)
|
||||||
return dst
|
return dst
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1022,12 +1022,12 @@ func (p *noder) lineno(n syntax.Node) {
|
|||||||
// TODO(mdempsky): Shouldn't happen. Fix package syntax.
|
// TODO(mdempsky): Shouldn't happen. Fix package syntax.
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
lineno = pos
|
lineno = Ctxt.PosTable.XPos(pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *noder) error(err error) {
|
func (p *noder) error(err error) {
|
||||||
e := err.(syntax.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 {
|
func (p *noder) pragma(pos src.Pos, text string) syntax.Pragma {
|
||||||
|
@ -511,7 +511,7 @@ func orderstmt(n *Node, order *Order) {
|
|||||||
|
|
||||||
n.Left = orderexpr(n.Left, order, nil)
|
n.Left = orderexpr(n.Left, order, nil)
|
||||||
n.Left = ordersafeexpr(n.Left, order)
|
n.Left = ordersafeexpr(n.Left, order)
|
||||||
tmp1 := treecopy(n.Left, src.NoPos)
|
tmp1 := treecopy(n.Left, src.NoXPos)
|
||||||
if tmp1.Op == OINDEXMAP {
|
if tmp1.Op == OINDEXMAP {
|
||||||
tmp1.Etype = 0 // now an rvalue not an lvalue
|
tmp1.Etype = 0 // now an rvalue not an lvalue
|
||||||
}
|
}
|
||||||
|
@ -312,7 +312,7 @@ func compile(fn *Node) {
|
|||||||
assertI2I2 = Sysfunc("assertI2I2")
|
assertI2I2 = Sysfunc("assertI2I2")
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func(lno src.Pos) {
|
defer func(lno src.XPos) {
|
||||||
lineno = lno
|
lineno = lno
|
||||||
}(setlineno(fn))
|
}(setlineno(fn))
|
||||||
|
|
||||||
|
@ -500,7 +500,7 @@ loop:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// lookupVarOutgoing finds the variable's value at the end of block b.
|
// 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 {
|
for {
|
||||||
if v := s.defvars[b.ID][var_]; v != nil {
|
if v := s.defvars[b.ID][var_]; v != nil {
|
||||||
return v
|
return v
|
||||||
|
@ -496,7 +496,7 @@ func callinstr(np **Node, init *Nodes, wr int, skip int) bool {
|
|||||||
*np = n
|
*np = n
|
||||||
}
|
}
|
||||||
|
|
||||||
n = treecopy(n, src.NoPos)
|
n = treecopy(n, src.NoXPos)
|
||||||
makeaddable(n)
|
makeaddable(n)
|
||||||
var f *Node
|
var f *Node
|
||||||
if flag_msan {
|
if flag_msan {
|
||||||
|
@ -22,14 +22,14 @@ func TestSizeof(t *testing.T) {
|
|||||||
_32bit uintptr // size on 32bit platforms
|
_32bit uintptr // size on 32bit platforms
|
||||||
_64bit uintptr // size on 64bit platforms
|
_64bit uintptr // size on 64bit platforms
|
||||||
}{
|
}{
|
||||||
{Func{}, 100, 184},
|
{Func{}, 100, 168},
|
||||||
{Name{}, 44, 72},
|
{Name{}, 44, 72},
|
||||||
{Param{}, 24, 48},
|
{Param{}, 24, 48},
|
||||||
{Node{}, 96, 160},
|
{Node{}, 96, 152},
|
||||||
{Sym{}, 64, 128},
|
{Sym{}, 64, 120},
|
||||||
{Type{}, 64, 112},
|
{Type{}, 64, 104},
|
||||||
{MapType{}, 20, 40},
|
{MapType{}, 20, 40},
|
||||||
{ForwardType{}, 20, 40},
|
{ForwardType{}, 20, 32},
|
||||||
{FuncType{}, 28, 48},
|
{FuncType{}, 28, 48},
|
||||||
{StructType{}, 12, 24},
|
{StructType{}, 12, 24},
|
||||||
{InterType{}, 4, 8},
|
{InterType{}, 4, 8},
|
||||||
|
@ -229,7 +229,7 @@ type state struct {
|
|||||||
sb *ssa.Value
|
sb *ssa.Value
|
||||||
|
|
||||||
// line number stack. The current line number is top of stack
|
// 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.
|
// list of panic calls by function name and line number.
|
||||||
// Used to deduplicate panic calls.
|
// Used to deduplicate panic calls.
|
||||||
@ -243,12 +243,12 @@ type state struct {
|
|||||||
|
|
||||||
cgoUnsafeArgs bool
|
cgoUnsafeArgs bool
|
||||||
noWB 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 {
|
type funcLine struct {
|
||||||
f *Node
|
f *Node
|
||||||
line src.Pos
|
line src.XPos
|
||||||
}
|
}
|
||||||
|
|
||||||
type ssaLabel struct {
|
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) Logf(msg string, args ...interface{}) { s.config.Logf(msg, args...) }
|
||||||
func (s *state) Log() bool { return s.config.Log() }
|
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) 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...)
|
s.config.Warnl(pos, msg, args...)
|
||||||
}
|
}
|
||||||
func (s *state) Debug_checknil() bool { return s.config.Debug_checknil() }
|
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.
|
// 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() {
|
if !line.IsKnown() {
|
||||||
// the frontend may emit node with line number missing,
|
// the frontend may emit node with line number missing,
|
||||||
// use the parent line number in this case.
|
// 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.
|
// 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]
|
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.
|
// If deref is true, rightIsVolatile reports whether right points to volatile (clobbered by a call) storage.
|
||||||
// Include a write barrier if wb is true.
|
// Include a write barrier if wb is true.
|
||||||
// skip indicates assignments (at the top level) that can be avoided.
|
// 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) {
|
if left.Op == ONAME && isblank(left) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -3260,7 +3260,7 @@ func canSSAType(t *Type) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// exprPtr evaluates n to a pointer and nil-checks it.
|
// 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)
|
p := s.expr(n)
|
||||||
if bounded || n.NonNil {
|
if bounded || n.NonNil {
|
||||||
if s.f.Config.Debug_checknil() && lineno.Line() > 1 {
|
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.
|
// insertWBmove inserts the assignment *left = *right including a write barrier.
|
||||||
// t is the type being assigned.
|
// t is the type being assigned.
|
||||||
// If right == nil, then we're zeroing *left.
|
// 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 {
|
// if writeBarrier.enabled {
|
||||||
// typedmemmove(&t, left, right)
|
// typedmemmove(&t, left, right)
|
||||||
// } else {
|
// } 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.
|
// insertWBstore inserts the assignment *left = right including a write barrier.
|
||||||
// t is the type being assigned.
|
// 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
|
// store scalar fields
|
||||||
// if writeBarrier.enabled {
|
// if writeBarrier.enabled {
|
||||||
// writebarrierptr for pointer fields
|
// writebarrierptr for pointer fields
|
||||||
@ -4381,7 +4381,7 @@ func (s *SSAGenState) Pc() *obj.Prog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SetPos sets the current source position.
|
// SetPos sets the current source position.
|
||||||
func (s *SSAGenState) SetPos(pos src.Pos) {
|
func (s *SSAGenState) SetPos(pos src.XPos) {
|
||||||
lineno = pos
|
lineno = pos
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4961,7 +4961,7 @@ func (e *ssaExport) CanSSA(t ssa.Type) bool {
|
|||||||
return canSSAType(t.(*Type))
|
return canSSAType(t.(*Type))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *ssaExport) Line(pos src.Pos) string {
|
func (e *ssaExport) Line(pos src.XPos) string {
|
||||||
return linestr(pos)
|
return linestr(pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4977,14 +4977,14 @@ func (e *ssaExport) Log() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fatal reports a compiler error and exits.
|
// 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
|
lineno = pos
|
||||||
Fatalf(msg, args...)
|
Fatalf(msg, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Warnl reports a "warning", which is usually flag-triggered
|
// Warnl reports a "warning", which is usually flag-triggered
|
||||||
// logging output for the benefit of tests.
|
// 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...)
|
Warnl(pos, fmt_, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Error struct {
|
type Error struct {
|
||||||
pos src.Pos
|
pos src.XPos
|
||||||
msg string
|
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{
|
errors = append(errors, Error{
|
||||||
pos: pos,
|
pos: pos,
|
||||||
msg: fmt.Sprintf("%v: %s\n", linestr(pos), fmt.Sprintf(format, args...)),
|
msg: fmt.Sprintf("%v: %s\n", linestr(pos), fmt.Sprintf(format, args...)),
|
||||||
@ -86,25 +86,27 @@ func hcrash() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func linestr(pos src.Pos) string {
|
func linestr(pos src.XPos) string {
|
||||||
return pos.String()
|
return Ctxt.PosTable.Pos(pos).String()
|
||||||
}
|
}
|
||||||
|
|
||||||
// lasterror keeps track of the most recently issued error.
|
// lasterror keeps track of the most recently issued error.
|
||||||
// It is used to avoid multiple error messages on the same
|
// It is used to avoid multiple error messages on the same
|
||||||
// line.
|
// line.
|
||||||
var lasterror struct {
|
var lasterror struct {
|
||||||
syntax src.Pos // source position of last syntax error
|
syntax src.XPos // source position of last syntax error
|
||||||
other src.Pos // source position of last non-syntax error
|
other src.XPos // source position of last non-syntax error
|
||||||
msg string // error message 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.
|
// sameline reports whether two positions a, b are on the same line.
|
||||||
func sameline(a, b src.Pos) bool {
|
func sameline(a, b src.XPos) bool {
|
||||||
return a.Filename() == b.Filename() && a.Line() == b.Line()
|
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...)
|
msg := fmt.Sprintf(format, args...)
|
||||||
|
|
||||||
if strings.HasPrefix(msg, "syntax error") {
|
if strings.HasPrefix(msg, "syntax error") {
|
||||||
@ -148,7 +150,7 @@ func Warn(fmt_ string, args ...interface{}) {
|
|||||||
hcrash()
|
hcrash()
|
||||||
}
|
}
|
||||||
|
|
||||||
func Warnl(line src.Pos, fmt_ string, args ...interface{}) {
|
func Warnl(line src.XPos, fmt_ string, args ...interface{}) {
|
||||||
adderr(line, fmt_, args...)
|
adderr(line, fmt_, args...)
|
||||||
if Debug['m'] != 0 {
|
if Debug['m'] != 0 {
|
||||||
flusherrors()
|
flusherrors()
|
||||||
@ -186,7 +188,7 @@ func linehistpragma(file string) {
|
|||||||
Ctxt.AddImport(file)
|
Ctxt.AddImport(file)
|
||||||
}
|
}
|
||||||
|
|
||||||
func setlineno(n *Node) src.Pos {
|
func setlineno(n *Node) src.XPos {
|
||||||
lno := lineno
|
lno := lineno
|
||||||
if n != nil {
|
if n != nil {
|
||||||
switch n.Op {
|
switch n.Op {
|
||||||
@ -461,7 +463,7 @@ func nodbool(b bool) *Node {
|
|||||||
// Copies of iota ONONAME nodes are assigned the current
|
// Copies of iota ONONAME nodes are assigned the current
|
||||||
// value of iota_. If pos.IsKnown(), it sets the source
|
// value of iota_. If pos.IsKnown(), it sets the source
|
||||||
// position of newly allocated nodes to pos.
|
// 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 {
|
if n == nil {
|
||||||
return 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)
|
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
|
dclcontext = PEXTERN
|
||||||
markdcl()
|
markdcl()
|
||||||
@ -1968,7 +1970,7 @@ func Simsimtype(t *Type) EType {
|
|||||||
return et
|
return et
|
||||||
}
|
}
|
||||||
|
|
||||||
func listtreecopy(l []*Node, pos src.Pos) []*Node {
|
func listtreecopy(l []*Node, pos src.XPos) []*Node {
|
||||||
var out []*Node
|
var out []*Node
|
||||||
for _, n := range l {
|
for _, n := range l {
|
||||||
out = append(out, treecopy(n, pos))
|
out = append(out, treecopy(n, pos))
|
||||||
|
@ -44,7 +44,7 @@ type Node struct {
|
|||||||
// Possibly still more uses. If you find any, document them.
|
// Possibly still more uses. If you find any, document them.
|
||||||
Xoffset int64
|
Xoffset int64
|
||||||
|
|
||||||
Pos src.Pos
|
Pos src.XPos
|
||||||
|
|
||||||
Esc uint16 // EscXXX
|
Esc uint16 // EscXXX
|
||||||
|
|
||||||
@ -310,8 +310,8 @@ type Func struct {
|
|||||||
|
|
||||||
Label int32 // largest auto-generated label in this function
|
Label int32 // largest auto-generated label in this function
|
||||||
|
|
||||||
Endlineno src.Pos
|
Endlineno src.XPos
|
||||||
WBPos src.Pos // position of first write barrier
|
WBPos src.XPos // position of first write barrier
|
||||||
|
|
||||||
Pragma Pragma // go:xxx function annotations
|
Pragma Pragma // go:xxx function annotations
|
||||||
Dupok bool // duplicate definitions ok
|
Dupok bool // duplicate definitions ok
|
||||||
|
@ -150,9 +150,9 @@ type Type struct {
|
|||||||
sliceOf *Type
|
sliceOf *Type
|
||||||
ptrTo *Type
|
ptrTo *Type
|
||||||
|
|
||||||
Sym *Sym // symbol containing name, for named types
|
Sym *Sym // symbol containing name, for named types
|
||||||
Vargen int32 // unique name for OTYPE/ONAME
|
Vargen int32 // unique name for OTYPE/ONAME
|
||||||
Pos src.Pos // position at which this type was declared, implicitly or explicitly
|
Pos src.XPos // position at which this type was declared, implicitly or explicitly
|
||||||
|
|
||||||
Etype EType // kind of type
|
Etype EType // kind of type
|
||||||
Noalg bool // suppress hash and eq algorithm generation
|
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.
|
// ForwardType contains Type fields specific to forward types.
|
||||||
type ForwardType struct {
|
type ForwardType struct {
|
||||||
Copyto []*Node // where to copy the eventual value to
|
Copyto []*Node // where to copy the eventual value to
|
||||||
Embedlineno src.Pos // first use of this type as an embedded type
|
Embedlineno src.XPos // first use of this type as an embedded type
|
||||||
}
|
}
|
||||||
|
|
||||||
// ForwardType returns t's extra forward-type-specific fields.
|
// ForwardType returns t's extra forward-type-specific fields.
|
||||||
|
@ -3500,7 +3500,7 @@ func domethod(n *Node) {
|
|||||||
|
|
||||||
type mapqueueval struct {
|
type mapqueueval struct {
|
||||||
n *Node
|
n *Node
|
||||||
lno src.Pos
|
lno src.XPos
|
||||||
}
|
}
|
||||||
|
|
||||||
// tracks the line numbers at which forward types are first used as map keys
|
// tracks the line numbers at which forward types are first used as map keys
|
||||||
|
@ -16,7 +16,7 @@ type Block struct {
|
|||||||
ID ID
|
ID ID
|
||||||
|
|
||||||
// Source position for block's control operation
|
// Source position for block's control operation
|
||||||
Pos src.Pos
|
Pos src.XPos
|
||||||
|
|
||||||
// The kind of block this is.
|
// The kind of block this is.
|
||||||
Kind BlockKind
|
Kind BlockKind
|
||||||
|
@ -129,7 +129,7 @@ func (f *Func) dumpFile(phaseName string) {
|
|||||||
|
|
||||||
fi, err := os.Create(fname)
|
fi, err := os.Create(fname)
|
||||||
if err != nil {
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,10 +89,10 @@ type Logger interface {
|
|||||||
Log() bool
|
Log() bool
|
||||||
|
|
||||||
// Fatal reports a compiler error and exits.
|
// 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 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
|
// Fowards the Debug flags from gc
|
||||||
Debug_checknil() bool
|
Debug_checknil() bool
|
||||||
@ -121,7 +121,7 @@ type Frontend interface {
|
|||||||
SplitInt64(LocalSlot) (LocalSlot, LocalSlot) // returns (hi, lo)
|
SplitInt64(LocalSlot) (LocalSlot, LocalSlot) // returns (hi, lo)
|
||||||
|
|
||||||
// Line returns a string describing the given position.
|
// 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 assigns frame offsets to all live auto variables.
|
||||||
AllocFrame(f *Func)
|
AllocFrame(f *Func)
|
||||||
@ -270,7 +270,7 @@ func NewConfig(arch string, fe Frontend, ctxt *obj.Link, optimize bool) *Config
|
|||||||
c.hasGReg = true
|
c.hasGReg = true
|
||||||
c.noDuffDevice = true
|
c.noDuffDevice = true
|
||||||
default:
|
default:
|
||||||
fe.Fatalf(src.NoPos, "arch %s not implemented", arch)
|
fe.Fatalf(src.NoXPos, "arch %s not implemented", arch)
|
||||||
}
|
}
|
||||||
c.ctxt = ctxt
|
c.ctxt = ctxt
|
||||||
c.optimize = optimize
|
c.optimize = optimize
|
||||||
@ -310,7 +310,7 @@ func NewConfig(arch string, fe Frontend, ctxt *obj.Link, optimize bool) *Config
|
|||||||
if ev != "" {
|
if ev != "" {
|
||||||
v, err := strconv.ParseInt(ev, 10, 64)
|
v, err := strconv.ParseInt(ev, 10, 64)
|
||||||
if err != nil {
|
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
|
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 {
|
func (c *Config) NewFunc() *Func {
|
||||||
// TODO(khr): should this function take name, type, etc. as arguments?
|
// TODO(khr): should this function take name, type, etc. as arguments?
|
||||||
if c.curFunc != nil {
|
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{}}
|
f := &Func{Config: c, NamedValues: map[LocalSlot][]*Value{}}
|
||||||
c.curFunc = f
|
c.curFunc = f
|
||||||
return f
|
return f
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) Logf(msg string, args ...interface{}) { c.fe.Logf(msg, args...) }
|
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) 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) Fatalf(pos src.XPos, 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) 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_checknil() bool { return c.fe.Debug_checknil() }
|
||||||
func (c *Config) Debug_wb() bool { return c.fe.Debug_wb() }
|
func (c *Config) Debug_wb() bool { return c.fe.Debug_wb() }
|
||||||
|
|
||||||
func (c *Config) logDebugHashMatch(evname, name string) {
|
func (c *Config) logDebugHashMatch(evname, name string) {
|
||||||
file := c.logfiles[evname]
|
file := c.logfiles[evname]
|
||||||
@ -355,7 +355,7 @@ func (c *Config) logDebugHashMatch(evname, name string) {
|
|||||||
var ok error
|
var ok error
|
||||||
file, ok = os.Create(tmpfile)
|
file, ok = os.Create(tmpfile)
|
||||||
if ok != nil {
|
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
|
c.logfiles[evname] = file
|
||||||
|
@ -113,7 +113,7 @@ func dse(f *Func) {
|
|||||||
if sz > 0x7fffffff { // work around sparseMap's int32 value type
|
if sz > 0x7fffffff { // work around sparseMap's int32 value type
|
||||||
sz = 0x7fffffff
|
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
|
// walk to previous store
|
||||||
|
@ -63,7 +63,7 @@ func (d DummyFrontend) SplitStruct(s LocalSlot, i int) LocalSlot {
|
|||||||
func (d DummyFrontend) SplitArray(s LocalSlot) LocalSlot {
|
func (d DummyFrontend) SplitArray(s LocalSlot) LocalSlot {
|
||||||
return LocalSlot{s.N, s.Type.ElemType(), s.Off}
|
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"
|
return "unknown.go:0"
|
||||||
}
|
}
|
||||||
func (DummyFrontend) AllocFrame(f *Func) {
|
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) Logf(msg string, args ...interface{}) { d.t.Logf(msg, args...) }
|
||||||
func (d DummyFrontend) Log() bool { return true }
|
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) Fatalf(_ src.XPos, 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) Warnl(_ src.XPos, msg string, args ...interface{}) { d.t.Logf(msg, args...) }
|
||||||
func (d DummyFrontend) Debug_checknil() bool { return false }
|
func (d DummyFrontend) Debug_checknil() bool { return false }
|
||||||
func (d DummyFrontend) Debug_wb() bool { return false }
|
func (d DummyFrontend) Debug_wb() bool { return false }
|
||||||
|
|
||||||
func (d DummyFrontend) TypeBool() Type { return TypeBool }
|
func (d DummyFrontend) TypeBool() Type { return TypeBool }
|
||||||
func (d DummyFrontend) TypeInt8() Type { return TypeInt8 }
|
func (d DummyFrontend) TypeInt8() Type { return TypeInt8 }
|
||||||
|
@ -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.
|
// 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
|
var v *Value
|
||||||
if f.freeValues != nil {
|
if f.freeValues != nil {
|
||||||
v = f.freeValues
|
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.
|
// 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 := b.Func.newValue(op, t, b, pos)
|
||||||
v.AuxInt = 0
|
v.AuxInt = 0
|
||||||
v.Args = v.argstorage[: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.
|
// 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 := b.Func.newValue(op, t, b, pos)
|
||||||
v.AuxInt = auxint
|
v.AuxInt = auxint
|
||||||
v.Args = v.argstorage[:0]
|
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.
|
// 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 {
|
if _, ok := aux.(int64); ok {
|
||||||
// Disallow int64 aux values. They should be in the auxint field instead.
|
// 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
|
// 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.
|
// 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 := b.Func.newValue(op, t, b, pos)
|
||||||
v.AuxInt = auxint
|
v.AuxInt = auxint
|
||||||
v.Aux = aux
|
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.
|
// 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 := b.Func.newValue(op, t, b, pos)
|
||||||
v.AuxInt = 0
|
v.AuxInt = 0
|
||||||
v.Args = v.argstorage[:1]
|
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.
|
// 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 := b.Func.newValue(op, t, b, pos)
|
||||||
v.AuxInt = auxint
|
v.AuxInt = auxint
|
||||||
v.Args = v.argstorage[:1]
|
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.
|
// 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 := b.Func.newValue(op, t, b, pos)
|
||||||
v.AuxInt = 0
|
v.AuxInt = 0
|
||||||
v.Aux = aux
|
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.
|
// 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 := b.Func.newValue(op, t, b, pos)
|
||||||
v.AuxInt = auxint
|
v.AuxInt = auxint
|
||||||
v.Aux = aux
|
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.
|
// 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 := b.Func.newValue(op, t, b, pos)
|
||||||
v.AuxInt = 0
|
v.AuxInt = 0
|
||||||
v.Args = v.argstorage[:2]
|
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.
|
// 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 := b.Func.newValue(op, t, b, pos)
|
||||||
v.AuxInt = auxint
|
v.AuxInt = auxint
|
||||||
v.Args = v.argstorage[:2]
|
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.
|
// 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 := b.Func.newValue(op, t, b, pos)
|
||||||
v.AuxInt = 0
|
v.AuxInt = 0
|
||||||
v.Args = v.argstorage[:3]
|
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.
|
// 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 := b.Func.newValue(op, t, b, pos)
|
||||||
v.AuxInt = auxint
|
v.AuxInt = auxint
|
||||||
v.Args = v.argstorage[:3]
|
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.
|
// 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 := b.Func.newValue(op, t, b, pos)
|
||||||
v.AuxInt = 0
|
v.AuxInt = 0
|
||||||
v.Args = []*Value{arg0, arg1, arg2, arg3}
|
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.
|
// 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 {
|
if f.constants == nil {
|
||||||
f.constants = make(map[int64][]*Value)
|
f.constants = make(map[int64][]*Value)
|
||||||
}
|
}
|
||||||
@ -368,42 +368,42 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// ConstInt returns an int constant representing its argument.
|
// 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)
|
i := int64(0)
|
||||||
if c {
|
if c {
|
||||||
i = 1
|
i = 1
|
||||||
}
|
}
|
||||||
return f.constVal(pos, OpConstBool, t, i, true)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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 := f.constVal(pos, OpConstString, t, constEmptyStringMagic, false)
|
||||||
v.Aux = ""
|
v.Aux = ""
|
||||||
return v
|
return v
|
||||||
|
@ -155,7 +155,7 @@ func Fun(c *Config, entry string, blocs ...bloc) fun {
|
|||||||
blocks[bloc.name] = b
|
blocks[bloc.name] = b
|
||||||
for _, valu := range bloc.valus {
|
for _, valu := range bloc.valus {
|
||||||
// args are filled in the second pass.
|
// 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.
|
// Connect the blocks together and specify control values.
|
||||||
@ -429,12 +429,12 @@ func TestConstCache(t *testing.T) {
|
|||||||
Bloc("entry",
|
Bloc("entry",
|
||||||
Valu("mem", OpInitMem, TypeMem, 0, nil),
|
Valu("mem", OpInitMem, TypeMem, 0, nil),
|
||||||
Exit("mem")))
|
Exit("mem")))
|
||||||
v1 := f.f.ConstBool(src.NoPos, TypeBool, false)
|
v1 := f.f.ConstBool(src.NoXPos, TypeBool, false)
|
||||||
v2 := f.f.ConstBool(src.NoPos, TypeBool, true)
|
v2 := f.f.ConstBool(src.NoXPos, TypeBool, true)
|
||||||
f.f.freeValue(v1)
|
f.f.freeValue(v1)
|
||||||
f.f.freeValue(v2)
|
f.f.freeValue(v2)
|
||||||
v3 := f.f.ConstBool(src.NoPos, TypeBool, false)
|
v3 := f.f.ConstBool(src.NoXPos, TypeBool, false)
|
||||||
v4 := f.f.ConstBool(src.NoPos, TypeBool, true)
|
v4 := f.f.ConstBool(src.NoXPos, TypeBool, true)
|
||||||
if v3.AuxInt != 0 {
|
if v3.AuxInt != 0 {
|
||||||
t.Errorf("expected %s to have auxint of 0\n", v3.LongString())
|
t.Errorf("expected %s to have auxint of 0\n", v3.LongString())
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ type HTMLWriter struct {
|
|||||||
func NewHTMLWriter(path string, logger Logger, funcname string) *HTMLWriter {
|
func NewHTMLWriter(path string, logger Logger, funcname string) *HTMLWriter {
|
||||||
out, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
|
out, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatalf(src.NoPos, "%v", err)
|
logger.Fatalf(src.NoXPos, "%v", err)
|
||||||
}
|
}
|
||||||
html := HTMLWriter{File: out, Logger: logger}
|
html := HTMLWriter{File: out, Logger: logger}
|
||||||
html.start(funcname)
|
html.start(funcname)
|
||||||
@ -329,13 +329,13 @@ func (w *HTMLWriter) WriteColumn(title string, html string) {
|
|||||||
|
|
||||||
func (w *HTMLWriter) Printf(msg string, v ...interface{}) {
|
func (w *HTMLWriter) Printf(msg string, v ...interface{}) {
|
||||||
if _, err := fmt.Fprintf(w.File, msg, v...); err != nil {
|
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) {
|
func (w *HTMLWriter) WriteString(s string) {
|
||||||
if _, err := w.File.WriteString(s); err != nil {
|
if _, err := w.File.WriteString(s); err != nil {
|
||||||
w.Fatalf(src.NoPos, "%v", err)
|
w.Fatalf(src.NoXPos, "%v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,9 +181,9 @@ func pickReg(r regMask) register {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type use struct {
|
type use struct {
|
||||||
dist int32 // distance from start of the block to a use of a value
|
dist int32 // distance from start of the block to a use of a value
|
||||||
pos src.Pos // source position of the use
|
pos src.XPos // source position of the use
|
||||||
next *use // linked list of uses of a value in nondecreasing dist order
|
next *use // linked list of uses of a value in nondecreasing dist order
|
||||||
}
|
}
|
||||||
|
|
||||||
type valState struct {
|
type valState struct {
|
||||||
@ -288,8 +288,8 @@ type endReg struct {
|
|||||||
|
|
||||||
type startReg struct {
|
type startReg struct {
|
||||||
r register
|
r register
|
||||||
vid ID // pre-regalloc value needed in this register
|
vid ID // pre-regalloc value needed in this register
|
||||||
pos src.Pos // source position of use of 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.
|
// 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
|
// allocated register is marked nospill so the assignment cannot be
|
||||||
// undone until the caller allows it by clearing nospill. Returns a
|
// 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.
|
// *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]
|
vi := &s.values[v.ID]
|
||||||
|
|
||||||
// Check if v is already in a requested register.
|
// Check if v is already in a requested register.
|
||||||
@ -555,7 +555,7 @@ func (s *regAllocState) init(f *Func) {
|
|||||||
case "s390x":
|
case "s390x":
|
||||||
// nothing to do, R10 & R11 already reserved
|
// nothing to do, R10 & R11 already reserved
|
||||||
default:
|
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 {
|
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.
|
// Adds a use record for id at distance dist from the start of the block.
|
||||||
// All calls to addUse must happen with nonincreasing dist.
|
// 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
|
r := s.freeUseRecords
|
||||||
if r != nil {
|
if r != nil {
|
||||||
s.freeUseRecords = r.next
|
s.freeUseRecords = r.next
|
||||||
@ -1879,17 +1879,17 @@ type edgeState struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type contentRecord struct {
|
type contentRecord struct {
|
||||||
vid ID // pre-regalloc value
|
vid ID // pre-regalloc value
|
||||||
c *Value // cached value
|
c *Value // cached value
|
||||||
final bool // this is a satisfied destination
|
final bool // this is a satisfied destination
|
||||||
pos src.Pos // source position of use of the value
|
pos src.XPos // source position of use of the value
|
||||||
}
|
}
|
||||||
|
|
||||||
type dstRecord struct {
|
type dstRecord struct {
|
||||||
loc Location // register or stack slot
|
loc Location // register or stack slot
|
||||||
vid ID // pre-regalloc value it should contain
|
vid ID // pre-regalloc value it should contain
|
||||||
splice **Value // place to store reference to the generating instruction
|
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.
|
// 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.
|
// Live registers can be sources.
|
||||||
for _, x := range srcReg {
|
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.
|
// So can all of the spill locations.
|
||||||
for _, spillID := range stacklive {
|
for _, spillID := range stacklive {
|
||||||
v := e.s.orig[spillID]
|
v := e.s.orig[spillID]
|
||||||
spill := e.s.values[v.ID].spill
|
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.
|
// 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
|
// processDest generates code to put value vid into location loc. Returns true
|
||||||
// if progress was made.
|
// 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]
|
occupant := e.contents[loc]
|
||||||
if occupant.vid == vid {
|
if occupant.vid == vid {
|
||||||
// Value is already in the correct place.
|
// 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.
|
// 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.s.f.setHome(c, loc)
|
||||||
e.erase(loc)
|
e.erase(loc)
|
||||||
e.contents[loc] = contentRecord{vid, c, final, pos}
|
e.contents[loc] = contentRecord{vid, c, final, pos}
|
||||||
@ -2291,9 +2291,9 @@ func (v *Value) rematerializeable() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type liveInfo struct {
|
type liveInfo struct {
|
||||||
ID ID // ID of value
|
ID ID // ID of value
|
||||||
dist int32 // # of instructions before next use
|
dist int32 // # of instructions before next use
|
||||||
pos src.Pos // source position of next use
|
pos src.XPos // source position of next use
|
||||||
}
|
}
|
||||||
|
|
||||||
// dblock contains information about desired & avoid registers at the end of a block.
|
// dblock contains information about desired & avoid registers at the end of a block.
|
||||||
|
@ -22,8 +22,8 @@ func TestSizeof(t *testing.T) {
|
|||||||
_32bit uintptr // size on 32bit platforms
|
_32bit uintptr // size on 32bit platforms
|
||||||
_64bit uintptr // size on 64bit platforms
|
_64bit uintptr // size on 64bit platforms
|
||||||
}{
|
}{
|
||||||
{Value{}, 72, 128},
|
{Value{}, 72, 120},
|
||||||
{Block{}, 152, 304},
|
{Block{}, 152, 288},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
@ -12,7 +12,7 @@ import "cmd/internal/src"
|
|||||||
type sparseEntry struct {
|
type sparseEntry struct {
|
||||||
key ID
|
key ID
|
||||||
val int32
|
val int32
|
||||||
aux src.Pos
|
aux src.XPos
|
||||||
}
|
}
|
||||||
|
|
||||||
type sparseMap struct {
|
type sparseMap struct {
|
||||||
@ -45,7 +45,7 @@ func (s *sparseMap) get(k ID) int32 {
|
|||||||
return -1
|
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]
|
i := s.sparse[k]
|
||||||
if i < int32(len(s.dense)) && s.dense[i].key == k {
|
if i < int32(len(s.dense)) && s.dense[i].key == k {
|
||||||
s.dense[i].val = v
|
s.dense[i].val = v
|
||||||
@ -66,7 +66,7 @@ func (s *sparseMap) setBit(k ID, v uint) {
|
|||||||
s.dense[i].val |= 1 << v
|
s.dense[i].val |= 1 << v
|
||||||
return
|
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
|
s.sparse[k] = int32(len(s.dense)) - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ func newStackAllocState(f *Func) *stackAllocState {
|
|||||||
return new(stackAllocState)
|
return new(stackAllocState)
|
||||||
}
|
}
|
||||||
if s.f != nil {
|
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
|
return s
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ type Value struct {
|
|||||||
Block *Block
|
Block *Block
|
||||||
|
|
||||||
// Source position
|
// Source position
|
||||||
Pos src.Pos
|
Pos src.XPos
|
||||||
|
|
||||||
// Use count. Each appearance in Value.Args and Block.Control counts once.
|
// Use count. Each appearance in Value.Args and Block.Control counts once.
|
||||||
Uses int32
|
Uses int32
|
||||||
|
@ -240,7 +240,7 @@ func writebarrier(f *Func) {
|
|||||||
|
|
||||||
// wbcall emits write barrier runtime call in b, returns memory.
|
// wbcall emits write barrier runtime call in b, returns memory.
|
||||||
// if valIsVolatile, it moves val into temp space before making the call.
|
// 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
|
config := b.Func.Config
|
||||||
|
|
||||||
var tmp GCNode
|
var tmp GCNode
|
||||||
|
@ -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.
|
// 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()
|
filename := pos.AbsFilename()
|
||||||
if !pos.IsKnown() || filename == "" {
|
if !pos.IsKnown() || filename == "" {
|
||||||
return Linklookup(ctxt, "??", HistVersion), 0
|
return Linklookup(ctxt, "??", HistVersion), 0
|
||||||
|
@ -30,7 +30,7 @@ func TestLinkgetlineFromPos(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
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)
|
got := fmt.Sprintf("%s:%d", f.Name, l)
|
||||||
if got != test.want {
|
if got != test.want {
|
||||||
t.Errorf("linkgetline(%v) = %q, want %q", test.pos, got, test.want)
|
t.Errorf("linkgetline(%v) = %q, want %q", test.pos, got, test.want)
|
||||||
|
@ -239,7 +239,7 @@ type Prog struct {
|
|||||||
Forwd *Prog // for x86 back end
|
Forwd *Prog // for x86 back end
|
||||||
Rel *Prog // for x86, arm back ends
|
Rel *Prog // for x86, arm back ends
|
||||||
Pc int64 // for back ends or assembler: virtual or actual program counter, depending on phase
|
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)
|
Spadj int32 // effect of instruction on stack pointer (increment or decrement amount)
|
||||||
As As // assembler opcode
|
As As // assembler opcode
|
||||||
Reg int16 // 2nd source operand
|
Reg int16 // 2nd source operand
|
||||||
@ -727,6 +727,7 @@ type Link struct {
|
|||||||
Bso *bufio.Writer
|
Bso *bufio.Writer
|
||||||
Pathname string
|
Pathname string
|
||||||
Hash map[SymVer]*LSym
|
Hash map[SymVer]*LSym
|
||||||
|
PosTable src.PosTable
|
||||||
Imports []string
|
Imports []string
|
||||||
Plists []*Plist
|
Plists []*Plist
|
||||||
Sym_div *LSym
|
Sym_div *LSym
|
||||||
|
@ -24,7 +24,7 @@ func TestSizeof(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{Addr{}, 40, 64},
|
{Addr{}, 40, 64},
|
||||||
{LSym{}, 76, 128},
|
{LSym{}, 76, 128},
|
||||||
{Prog{}, 148, 240},
|
{Prog{}, 148, 232},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
@ -59,7 +59,7 @@ func Getgoextlinkenabled() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *Prog) Line() string {
|
func (p *Prog) Line() string {
|
||||||
return p.Pos.String()
|
return p.Ctxt.PosTable.Pos(p.Pos).String()
|
||||||
}
|
}
|
||||||
|
|
||||||
var armCondCode = []string{
|
var armCondCode = []string{
|
||||||
|
@ -37,6 +37,8 @@ func MakePos(base *PosBase, line, col uint) Pos {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IsKnown reports whether the position p is known.
|
// 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 {
|
func (p Pos) IsKnown() bool {
|
||||||
return p.base != nil || p.Line() != 0
|
return p.base != nil || p.Line() != 0
|
||||||
}
|
}
|
||||||
|
75
src/cmd/internal/src/xpos.go
Normal file
75
src/cmd/internal/src/xpos.go
Normal file
@ -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}
|
||||||
|
}
|
67
src/cmd/internal/src/xpos_test.go
Normal file
67
src/cmd/internal/src/xpos_test.go
Normal file
@ -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))
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user