summaryrefslogtreecommitdiff
path: root/vendor/github.com/twitchyliquid64/golang-asm/src
diff options
context:
space:
mode:
authorLibravatar Daenney <daenney@users.noreply.github.com>2023-02-25 13:12:40 +0100
committerLibravatar GitHub <noreply@github.com>2023-02-25 12:12:40 +0000
commitecdc8379fa8f9d88faca626e7de748c2afbe4910 (patch)
tree8c20a5826db2136fc89bee45e15355c5899fa65b /vendor/github.com/twitchyliquid64/golang-asm/src
parent[bugfix] Fix deleted status causing issues when getting bookmark (#1551) (diff)
downloadgotosocial-ecdc8379fa8f9d88faca626e7de748c2afbe4910.tar.xz
[chore] Update gin to v1.9.0 (#1553)
Diffstat (limited to 'vendor/github.com/twitchyliquid64/golang-asm/src')
-rw-r--r--vendor/github.com/twitchyliquid64/golang-asm/src/pos.go470
-rw-r--r--vendor/github.com/twitchyliquid64/golang-asm/src/xpos.go176
2 files changed, 646 insertions, 0 deletions
diff --git a/vendor/github.com/twitchyliquid64/golang-asm/src/pos.go b/vendor/github.com/twitchyliquid64/golang-asm/src/pos.go
new file mode 100644
index 000000000..b6816a56e
--- /dev/null
+++ b/vendor/github.com/twitchyliquid64/golang-asm/src/pos.go
@@ -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 := &copy
+ 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()
+}
diff --git a/vendor/github.com/twitchyliquid64/golang-asm/src/xpos.go b/vendor/github.com/twitchyliquid64/golang-asm/src/xpos.go
new file mode 100644
index 000000000..867d0ab06
--- /dev/null
+++ b/vendor/github.com/twitchyliquid64/golang-asm/src/xpos.go
@@ -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
+}