Add vendor to improve building speed.
This also adds ability to be built in network-constrained environment.
This commit is contained in:
470
vendor/github.com/twitchyliquid64/golang-asm/src/pos.go
generated
vendored
Normal file
470
vendor/github.com/twitchyliquid64/golang-asm/src/pos.go
generated
vendored
Normal file
@@ -0,0 +1,470 @@
|
||||
// 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 encoding of source positions.
|
||||
|
||||
package src
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
// A Pos encodes a source position consisting of a (line, column) number pair
|
||||
// and a position base. A zero Pos is a ready to use "unknown" position (nil
|
||||
// position base and zero line number).
|
||||
//
|
||||
// The (line, column) values refer to a position in a file independent of any
|
||||
// position base ("absolute" file position).
|
||||
//
|
||||
// The position base is used to determine the "relative" position, that is the
|
||||
// filename and line number relative to the position base. If the base refers
|
||||
// to the current file, there is no difference between absolute and relative
|
||||
// positions. If it refers to a //line directive, a relative position is relative
|
||||
// to that directive. A position base in turn contains the position at which it
|
||||
// was introduced in the current file.
|
||||
type Pos struct {
|
||||
base *PosBase
|
||||
lico
|
||||
}
|
||||
|
||||
// NoPos is a valid unknown position.
|
||||
var NoPos Pos
|
||||
|
||||
// MakePos creates a new Pos value with the given base, and (file-absolute)
|
||||
// line and column.
|
||||
func MakePos(base *PosBase, line, col uint) Pos {
|
||||
return Pos{base, makeLico(line, col)}
|
||||
}
|
||||
|
||||
// IsKnown reports whether the position p is known.
|
||||
// A position is known if it either has a non-nil
|
||||
// position base, or a non-zero line number.
|
||||
func (p Pos) IsKnown() bool {
|
||||
return p.base != nil || p.Line() != 0
|
||||
}
|
||||
|
||||
// Before reports whether the position p comes before q in the source.
|
||||
// For positions in different files, ordering is by filename.
|
||||
func (p Pos) Before(q Pos) bool {
|
||||
n, m := p.Filename(), q.Filename()
|
||||
return n < m || n == m && p.lico < q.lico
|
||||
}
|
||||
|
||||
// After reports whether the position p comes after q in the source.
|
||||
// For positions in different files, ordering is by filename.
|
||||
func (p Pos) After(q Pos) bool {
|
||||
n, m := p.Filename(), q.Filename()
|
||||
return n > m || n == m && p.lico > q.lico
|
||||
}
|
||||
|
||||
func (p Pos) LineNumber() string {
|
||||
if !p.IsKnown() {
|
||||
return "?"
|
||||
}
|
||||
return p.lico.lineNumber()
|
||||
}
|
||||
|
||||
func (p Pos) LineNumberHTML() string {
|
||||
if !p.IsKnown() {
|
||||
return "?"
|
||||
}
|
||||
return p.lico.lineNumberHTML()
|
||||
}
|
||||
|
||||
// Filename returns the name of the actual file containing this position.
|
||||
func (p Pos) Filename() string { return p.base.Pos().RelFilename() }
|
||||
|
||||
// Base returns the position base.
|
||||
func (p Pos) Base() *PosBase { return p.base }
|
||||
|
||||
// SetBase sets the position base.
|
||||
func (p *Pos) SetBase(base *PosBase) { p.base = base }
|
||||
|
||||
// RelFilename returns the filename recorded with the position's base.
|
||||
func (p Pos) RelFilename() string { return p.base.Filename() }
|
||||
|
||||
// RelLine returns the line number relative to the position's base.
|
||||
func (p Pos) RelLine() uint {
|
||||
b := p.base
|
||||
if b.Line() == 0 {
|
||||
// base line is unknown => relative line is unknown
|
||||
return 0
|
||||
}
|
||||
return b.Line() + (p.Line() - b.Pos().Line())
|
||||
}
|
||||
|
||||
// RelCol returns the column number relative to the position's base.
|
||||
func (p Pos) RelCol() uint {
|
||||
b := p.base
|
||||
if b.Col() == 0 {
|
||||
// base column is unknown => relative column is unknown
|
||||
// (the current specification for line directives requires
|
||||
// this to apply until the next PosBase/line directive,
|
||||
// not just until the new newline)
|
||||
return 0
|
||||
}
|
||||
if p.Line() == b.Pos().Line() {
|
||||
// p on same line as p's base => column is relative to p's base
|
||||
return b.Col() + (p.Col() - b.Pos().Col())
|
||||
}
|
||||
return p.Col()
|
||||
}
|
||||
|
||||
// AbsFilename() returns the absolute filename recorded with the position's base.
|
||||
func (p Pos) AbsFilename() string { return p.base.AbsFilename() }
|
||||
|
||||
// SymFilename() returns the absolute filename recorded with the position's base,
|
||||
// prefixed by FileSymPrefix to make it appropriate for use as a linker symbol.
|
||||
func (p Pos) SymFilename() string { return p.base.SymFilename() }
|
||||
|
||||
func (p Pos) String() string {
|
||||
return p.Format(true, true)
|
||||
}
|
||||
|
||||
// Format formats a position as "filename:line" or "filename:line:column",
|
||||
// controlled by the showCol flag and if the column is known (!= 0).
|
||||
// For positions relative to line directives, the original position is
|
||||
// shown as well, as in "filename:line[origfile:origline:origcolumn] if
|
||||
// showOrig is set.
|
||||
func (p Pos) Format(showCol, showOrig bool) string {
|
||||
buf := new(bytes.Buffer)
|
||||
p.WriteTo(buf, showCol, showOrig)
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// WriteTo a position to w, formatted as Format does.
|
||||
func (p Pos) WriteTo(w io.Writer, showCol, showOrig bool) {
|
||||
if !p.IsKnown() {
|
||||
io.WriteString(w, "<unknown line number>")
|
||||
return
|
||||
}
|
||||
|
||||
if b := p.base; b == b.Pos().base {
|
||||
// base is file base (incl. nil)
|
||||
format(w, p.Filename(), p.Line(), p.Col(), showCol)
|
||||
return
|
||||
}
|
||||
|
||||
// base is relative
|
||||
// Print the column only for the original position since the
|
||||
// relative position's column information may be bogus (it's
|
||||
// typically generated code and we can't say much about the
|
||||
// original source at that point but for the file:line info
|
||||
// that's provided via a line directive).
|
||||
// TODO(gri) This may not be true if we have an inlining base.
|
||||
// We may want to differentiate at some point.
|
||||
format(w, p.RelFilename(), p.RelLine(), p.RelCol(), showCol)
|
||||
if showOrig {
|
||||
io.WriteString(w, "[")
|
||||
format(w, p.Filename(), p.Line(), p.Col(), showCol)
|
||||
io.WriteString(w, "]")
|
||||
}
|
||||
}
|
||||
|
||||
// format formats a (filename, line, col) tuple as "filename:line" (showCol
|
||||
// is false or col == 0) or "filename:line:column" (showCol is true and col != 0).
|
||||
func format(w io.Writer, filename string, line, col uint, showCol bool) {
|
||||
io.WriteString(w, filename)
|
||||
io.WriteString(w, ":")
|
||||
fmt.Fprint(w, line)
|
||||
// col == 0 and col == colMax are interpreted as unknown column values
|
||||
if showCol && 0 < col && col < colMax {
|
||||
io.WriteString(w, ":")
|
||||
fmt.Fprint(w, col)
|
||||
}
|
||||
}
|
||||
|
||||
// formatstr wraps format to return a string.
|
||||
func formatstr(filename string, line, col uint, showCol bool) string {
|
||||
buf := new(bytes.Buffer)
|
||||
format(buf, filename, line, col, showCol)
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// PosBase
|
||||
|
||||
// A PosBase encodes a filename and base position.
|
||||
// Typically, each file and line directive introduce a PosBase.
|
||||
type PosBase struct {
|
||||
pos Pos // position at which the relative position is (line, col)
|
||||
filename string // file name used to open source file, for error messages
|
||||
absFilename string // absolute file name, for PC-Line tables
|
||||
symFilename string // cached symbol file name, to avoid repeated string concatenation
|
||||
line, col uint // relative line, column number at pos
|
||||
inl int // inlining index (see cmd/internal/obj/inl.go)
|
||||
}
|
||||
|
||||
// NewFileBase returns a new *PosBase for a file with the given (relative and
|
||||
// absolute) filenames.
|
||||
func NewFileBase(filename, absFilename string) *PosBase {
|
||||
base := &PosBase{
|
||||
filename: filename,
|
||||
absFilename: absFilename,
|
||||
symFilename: FileSymPrefix + absFilename,
|
||||
line: 1,
|
||||
col: 1,
|
||||
inl: -1,
|
||||
}
|
||||
base.pos = MakePos(base, 1, 1)
|
||||
return base
|
||||
}
|
||||
|
||||
// NewLinePragmaBase returns a new *PosBase for a line directive of the form
|
||||
// //line filename:line:col
|
||||
// /*line filename:line:col*/
|
||||
// at position pos.
|
||||
func NewLinePragmaBase(pos Pos, filename, absFilename string, line, col uint) *PosBase {
|
||||
return &PosBase{pos, filename, absFilename, FileSymPrefix + absFilename, line, col, -1}
|
||||
}
|
||||
|
||||
// NewInliningBase returns a copy of the old PosBase with the given inlining
|
||||
// index. If old == nil, the resulting PosBase has no filename.
|
||||
func NewInliningBase(old *PosBase, inlTreeIndex int) *PosBase {
|
||||
if old == nil {
|
||||
base := &PosBase{line: 1, col: 1, inl: inlTreeIndex}
|
||||
base.pos = MakePos(base, 1, 1)
|
||||
return base
|
||||
}
|
||||
copy := *old
|
||||
base := ©
|
||||
base.inl = inlTreeIndex
|
||||
if old == old.pos.base {
|
||||
base.pos.base = base
|
||||
}
|
||||
return base
|
||||
}
|
||||
|
||||
var noPos Pos
|
||||
|
||||
// Pos returns the position at which base is located.
|
||||
// If b == nil, the result is the zero position.
|
||||
func (b *PosBase) Pos() *Pos {
|
||||
if b != nil {
|
||||
return &b.pos
|
||||
}
|
||||
return &noPos
|
||||
}
|
||||
|
||||
// Filename returns the filename recorded with the base.
|
||||
// If b == nil, the result is the empty string.
|
||||
func (b *PosBase) Filename() string {
|
||||
if b != nil {
|
||||
return b.filename
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// AbsFilename returns the absolute filename recorded with the base.
|
||||
// If b == nil, the result is the empty string.
|
||||
func (b *PosBase) AbsFilename() string {
|
||||
if b != nil {
|
||||
return b.absFilename
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
const FileSymPrefix = "gofile.."
|
||||
|
||||
// SymFilename returns the absolute filename recorded with the base,
|
||||
// prefixed by FileSymPrefix to make it appropriate for use as a linker symbol.
|
||||
// If b is nil, SymFilename returns FileSymPrefix + "??".
|
||||
func (b *PosBase) SymFilename() string {
|
||||
if b != nil {
|
||||
return b.symFilename
|
||||
}
|
||||
return FileSymPrefix + "??"
|
||||
}
|
||||
|
||||
// Line returns the line number recorded with the base.
|
||||
// If b == nil, the result is 0.
|
||||
func (b *PosBase) Line() uint {
|
||||
if b != nil {
|
||||
return b.line
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Col returns the column number recorded with the base.
|
||||
// If b == nil, the result is 0.
|
||||
func (b *PosBase) Col() uint {
|
||||
if b != nil {
|
||||
return b.col
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// InliningIndex returns the index into the global inlining
|
||||
// tree recorded with the base. If b == nil or the base has
|
||||
// not been inlined, the result is < 0.
|
||||
func (b *PosBase) InliningIndex() int {
|
||||
if b != nil {
|
||||
return b.inl
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// lico
|
||||
|
||||
// A lico is a compact encoding of a LIne and COlumn number.
|
||||
type lico uint32
|
||||
|
||||
// Layout constants: 20 bits for line, 8 bits for column, 2 for isStmt, 2 for pro/epilogue
|
||||
// (If this is too tight, we can either make lico 64b wide,
|
||||
// or we can introduce a tiered encoding where we remove column
|
||||
// information as line numbers grow bigger; similar to what gcc
|
||||
// does.)
|
||||
// The bitfield order is chosen to make IsStmt be the least significant
|
||||
// part of a position; its use is to communicate statement edges through
|
||||
// instruction scrambling in code generation, not to impose an order.
|
||||
// TODO: Prologue and epilogue are perhaps better handled as pseudo-ops for the assembler,
|
||||
// because they have almost no interaction with other uses of the position.
|
||||
const (
|
||||
lineBits, lineMax = 20, 1<<lineBits - 2
|
||||
bogusLine = 1 // Used to disrupt infinite loops to prevent debugger looping
|
||||
isStmtBits, isStmtMax = 2, 1<<isStmtBits - 1
|
||||
xlogueBits, xlogueMax = 2, 1<<xlogueBits - 1
|
||||
colBits, colMax = 32 - lineBits - xlogueBits - isStmtBits, 1<<colBits - 1
|
||||
|
||||
isStmtShift = 0
|
||||
isStmtMask = isStmtMax << isStmtShift
|
||||
xlogueShift = isStmtBits + isStmtShift
|
||||
xlogueMask = xlogueMax << xlogueShift
|
||||
colShift = xlogueBits + xlogueShift
|
||||
lineShift = colBits + colShift
|
||||
)
|
||||
const (
|
||||
// It is expected that the front end or a phase in SSA will usually generate positions tagged with
|
||||
// PosDefaultStmt, but note statement boundaries with PosIsStmt. Simple statements will have a single
|
||||
// boundary; for loops with initialization may have one for their entry and one for their back edge
|
||||
// (this depends on exactly how the loop is compiled; the intent is to provide a good experience to a
|
||||
// user debugging a program; the goal is that a breakpoint set on the loop line fires both on entry
|
||||
// and on iteration). Proper treatment of non-gofmt input with multiple simple statements on a single
|
||||
// line is TBD.
|
||||
//
|
||||
// Optimizing compilation will move instructions around, and some of these will become known-bad as
|
||||
// step targets for debugging purposes (examples: register spills and reloads; code generated into
|
||||
// the entry block; invariant code hoisted out of loops) but those instructions will still have interesting
|
||||
// positions for profiling purposes. To reflect this these positions will be changed to PosNotStmt.
|
||||
//
|
||||
// When the optimizer removes an instruction marked PosIsStmt; it should attempt to find a nearby
|
||||
// instruction with the same line marked PosDefaultStmt to be the new statement boundary. I.e., the
|
||||
// optimizer should make a best-effort to conserve statement boundary positions, and might be enhanced
|
||||
// to note when a statement boundary is not conserved.
|
||||
//
|
||||
// Code cloning, e.g. loop unrolling or loop unswitching, is an exception to the conservation rule
|
||||
// because a user running a debugger would expect to see breakpoints active in the copies of the code.
|
||||
//
|
||||
// In non-optimizing compilation there is still a role for PosNotStmt because of code generation
|
||||
// into the entry block. PosIsStmt statement positions should be conserved.
|
||||
//
|
||||
// When code generation occurs any remaining default-marked positions are replaced with not-statement
|
||||
// positions.
|
||||
//
|
||||
PosDefaultStmt uint = iota // Default; position is not a statement boundary, but might be if optimization removes the designated statement boundary
|
||||
PosIsStmt // Position is a statement boundary; if optimization removes the corresponding instruction, it should attempt to find a new instruction to be the boundary.
|
||||
PosNotStmt // Position should not be a statement boundary, but line should be preserved for profiling and low-level debugging purposes.
|
||||
)
|
||||
|
||||
type PosXlogue uint
|
||||
|
||||
const (
|
||||
PosDefaultLogue PosXlogue = iota
|
||||
PosPrologueEnd
|
||||
PosEpilogueBegin
|
||||
)
|
||||
|
||||
func makeLicoRaw(line, col uint) lico {
|
||||
return lico(line<<lineShift | col<<colShift)
|
||||
}
|
||||
|
||||
// This is a not-position that will not be elided.
|
||||
// Depending on the debugger (gdb or delve) it may or may not be displayed.
|
||||
func makeBogusLico() lico {
|
||||
return makeLicoRaw(bogusLine, 0).withIsStmt()
|
||||
}
|
||||
|
||||
func makeLico(line, col uint) lico {
|
||||
if line > lineMax {
|
||||
// cannot represent line, use max. line so we have some information
|
||||
line = lineMax
|
||||
}
|
||||
if col > colMax {
|
||||
// cannot represent column, use max. column so we have some information
|
||||
col = colMax
|
||||
}
|
||||
// default is not-sure-if-statement
|
||||
return makeLicoRaw(line, col)
|
||||
}
|
||||
|
||||
func (x lico) Line() uint { return uint(x) >> lineShift }
|
||||
func (x lico) SameLine(y lico) bool { return 0 == (x^y)&^lico(1<<lineShift-1) }
|
||||
func (x lico) Col() uint { return uint(x) >> colShift & colMax }
|
||||
func (x lico) IsStmt() uint {
|
||||
if x == 0 {
|
||||
return PosNotStmt
|
||||
}
|
||||
return uint(x) >> isStmtShift & isStmtMax
|
||||
}
|
||||
func (x lico) Xlogue() PosXlogue {
|
||||
return PosXlogue(uint(x) >> xlogueShift & xlogueMax)
|
||||
}
|
||||
|
||||
// withNotStmt returns a lico for the same location, but not a statement
|
||||
func (x lico) withNotStmt() lico {
|
||||
return x.withStmt(PosNotStmt)
|
||||
}
|
||||
|
||||
// withDefaultStmt returns a lico for the same location, with default isStmt
|
||||
func (x lico) withDefaultStmt() lico {
|
||||
return x.withStmt(PosDefaultStmt)
|
||||
}
|
||||
|
||||
// withIsStmt returns a lico for the same location, tagged as definitely a statement
|
||||
func (x lico) withIsStmt() lico {
|
||||
return x.withStmt(PosIsStmt)
|
||||
}
|
||||
|
||||
// withLogue attaches a prologue/epilogue attribute to a lico
|
||||
func (x lico) withXlogue(xlogue PosXlogue) lico {
|
||||
if x == 0 {
|
||||
if xlogue == 0 {
|
||||
return x
|
||||
}
|
||||
// Normalize 0 to "not a statement"
|
||||
x = lico(PosNotStmt << isStmtShift)
|
||||
}
|
||||
return lico(uint(x) & ^uint(xlogueMax<<xlogueShift) | (uint(xlogue) << xlogueShift))
|
||||
}
|
||||
|
||||
// withStmt returns a lico for the same location with specified is_stmt attribute
|
||||
func (x lico) withStmt(stmt uint) lico {
|
||||
if x == 0 {
|
||||
return lico(0)
|
||||
}
|
||||
return lico(uint(x) & ^uint(isStmtMax<<isStmtShift) | (stmt << isStmtShift))
|
||||
}
|
||||
|
||||
func (x lico) lineNumber() string {
|
||||
return fmt.Sprintf("%d", x.Line())
|
||||
}
|
||||
|
||||
func (x lico) lineNumberHTML() string {
|
||||
if x.IsStmt() == PosDefaultStmt {
|
||||
return fmt.Sprintf("%d", x.Line())
|
||||
}
|
||||
style, pfx := "b", "+"
|
||||
if x.IsStmt() == PosNotStmt {
|
||||
style = "s" // /strike not supported in HTML5
|
||||
pfx = ""
|
||||
}
|
||||
return fmt.Sprintf("<%s>%s%d</%s>", style, pfx, x.Line(), style)
|
||||
}
|
||||
|
||||
func (x lico) atColumn1() lico {
|
||||
return makeLico(x.Line(), 1).withIsStmt()
|
||||
}
|
176
vendor/github.com/twitchyliquid64/golang-asm/src/xpos.go
generated
vendored
Normal file
176
vendor/github.com/twitchyliquid64/golang-asm/src/xpos.go
generated
vendored
Normal file
@@ -0,0 +1,176 @@
|
||||
// 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
|
||||
}
|
||||
|
||||
// SameFile reports whether p and q are positions in the same file.
|
||||
func (p XPos) SameFile(q XPos) bool {
|
||||
return p.index == q.index
|
||||
}
|
||||
|
||||
// SameFileAndLine reports whether p and q are positions on the same line in the same file.
|
||||
func (p XPos) SameFileAndLine(q XPos) bool {
|
||||
return p.index == q.index && p.lico.SameLine(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
|
||||
}
|
||||
|
||||
// WithNotStmt returns the same location to be marked with DWARF is_stmt=0
|
||||
func (p XPos) WithNotStmt() XPos {
|
||||
p.lico = p.lico.withNotStmt()
|
||||
return p
|
||||
}
|
||||
|
||||
// WithDefaultStmt returns the same location with undetermined is_stmt
|
||||
func (p XPos) WithDefaultStmt() XPos {
|
||||
p.lico = p.lico.withDefaultStmt()
|
||||
return p
|
||||
}
|
||||
|
||||
// WithIsStmt returns the same location to be marked with DWARF is_stmt=1
|
||||
func (p XPos) WithIsStmt() XPos {
|
||||
p.lico = p.lico.withIsStmt()
|
||||
return p
|
||||
}
|
||||
|
||||
// WithBogusLine returns a bogus line that won't match any recorded for the source code.
|
||||
// Its use is to disrupt the statements within an infinite loop so that the debugger
|
||||
// will not itself loop infinitely waiting for the line number to change.
|
||||
// gdb chooses not to display the bogus line; delve shows it with a complaint, but the
|
||||
// alternative behavior is to hang.
|
||||
func (p XPos) WithBogusLine() XPos {
|
||||
if p.index == 0 {
|
||||
// See #35652
|
||||
panic("Assigning a bogus line to XPos with no file will cause mysterious downstream failures.")
|
||||
}
|
||||
p.lico = makeBogusLico()
|
||||
return p
|
||||
}
|
||||
|
||||
// WithXlogue returns the same location but marked with DWARF function prologue/epilogue
|
||||
func (p XPos) WithXlogue(x PosXlogue) XPos {
|
||||
p.lico = p.lico.withXlogue(x)
|
||||
return p
|
||||
}
|
||||
|
||||
// LineNumber returns a string for the line number, "?" if it is not known.
|
||||
func (p XPos) LineNumber() string {
|
||||
if !p.IsKnown() {
|
||||
return "?"
|
||||
}
|
||||
return p.lico.lineNumber()
|
||||
}
|
||||
|
||||
// FileIndex returns a smallish non-negative integer corresponding to the
|
||||
// file for this source position. Smallish is relative; it can be thousands
|
||||
// large, but not millions.
|
||||
func (p XPos) FileIndex() int32 {
|
||||
return p.index
|
||||
}
|
||||
|
||||
func (p XPos) LineNumberHTML() string {
|
||||
if !p.IsKnown() {
|
||||
return "?"
|
||||
}
|
||||
return p.lico.lineNumberHTML()
|
||||
}
|
||||
|
||||
// AtColumn1 returns the same location but shifted to column 1.
|
||||
func (p XPos) AtColumn1() XPos {
|
||||
p.lico = p.lico.atColumn1()
|
||||
return p
|
||||
}
|
||||
|
||||
// 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
|
||||
nameMap map[string]int // Maps file symbol name to index for debug information.
|
||||
}
|
||||
|
||||
// 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
|
||||
t.nameMap = make(map[string]int)
|
||||
}
|
||||
i, ok := m[pos.base]
|
||||
if !ok {
|
||||
i = len(t.baseList)
|
||||
t.baseList = append(t.baseList, pos.base)
|
||||
t.indexMap[pos.base] = i
|
||||
if _, ok := t.nameMap[pos.base.symFilename]; !ok {
|
||||
t.nameMap[pos.base.symFilename] = len(t.nameMap)
|
||||
}
|
||||
}
|
||||
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}
|
||||
}
|
||||
|
||||
// FileIndex returns the index of the given filename(symbol) in the PosTable, or -1 if not found.
|
||||
func (t *PosTable) FileIndex(filename string) int {
|
||||
if v, ok := t.nameMap[filename]; ok {
|
||||
return v
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// FileTable returns a slice of all files used to build this package.
|
||||
func (t *PosTable) FileTable() []string {
|
||||
// Create a LUT of the global package level file indices. This table is what
|
||||
// is written in the debug_lines header, the file[N] will be referenced as
|
||||
// N+1 in the debug_lines table.
|
||||
fileLUT := make([]string, len(t.nameMap))
|
||||
for str, i := range t.nameMap {
|
||||
fileLUT[i] = str
|
||||
}
|
||||
return fileLUT
|
||||
}
|
Reference in New Issue
Block a user