aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/noder/decoder.go
diff options
context:
space:
mode:
authorMatthew Dempsky <mdempsky@google.com>2022-02-14 09:41:19 -0800
committerMatthew Dempsky <mdempsky@google.com>2022-03-01 07:36:05 +0000
commit7c151f328056c354d3db13c17b3d96bec316cff6 (patch)
tree01327d059a54a85d4cfe4f83bdcefeb2626d6c9f /src/cmd/compile/internal/noder/decoder.go
parent6d881da9c894dfcd8c3dda0057a7c63a3ab59ea2 (diff)
downloadgo-7c151f328056c354d3db13c17b3d96bec316cff6.tar.xz
internal/pkgbits: extract unified IR coding-level logic
This logic is needed for the go/types unified IR importer, so extract it into a separate internal package so we can reuse a single copy. Change-Id: I5f734b76e580fdb69ee39e45ac553c22d01c5909 Reviewed-on: https://go-review.googlesource.com/c/go/+/386000 Run-TryBot: Matthew Dempsky <mdempsky@google.com> Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com> TryBot-Result: Gopher Robot <gobot@golang.org> Trust: Matthew Dempsky <mdempsky@google.com>
Diffstat (limited to 'src/cmd/compile/internal/noder/decoder.go')
-rw-r--r--src/cmd/compile/internal/noder/decoder.go302
1 files changed, 0 insertions, 302 deletions
diff --git a/src/cmd/compile/internal/noder/decoder.go b/src/cmd/compile/internal/noder/decoder.go
deleted file mode 100644
index 2c18727420..0000000000
--- a/src/cmd/compile/internal/noder/decoder.go
+++ /dev/null
@@ -1,302 +0,0 @@
-// UNREVIEWED
-
-// Copyright 2021 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 noder
-
-import (
- "encoding/binary"
- "fmt"
- "go/constant"
- "go/token"
- "math/big"
- "os"
- "runtime"
- "strings"
-
- "cmd/compile/internal/base"
-)
-
-type pkgDecoder struct {
- pkgPath string
-
- elemEndsEnds [numRelocs]uint32
- elemEnds []uint32
- elemData string
-}
-
-func newPkgDecoder(pkgPath, input string) pkgDecoder {
- pr := pkgDecoder{
- pkgPath: pkgPath,
- }
-
- // TODO(mdempsky): Implement direct indexing of input string to
- // avoid copying the position information.
-
- r := strings.NewReader(input)
-
- assert(binary.Read(r, binary.LittleEndian, pr.elemEndsEnds[:]) == nil)
-
- pr.elemEnds = make([]uint32, pr.elemEndsEnds[len(pr.elemEndsEnds)-1])
- assert(binary.Read(r, binary.LittleEndian, pr.elemEnds[:]) == nil)
-
- pos, err := r.Seek(0, os.SEEK_CUR)
- assert(err == nil)
-
- pr.elemData = input[pos:]
- assert(len(pr.elemData) == int(pr.elemEnds[len(pr.elemEnds)-1]))
-
- return pr
-}
-
-func (pr *pkgDecoder) numElems(k reloc) int {
- count := int(pr.elemEndsEnds[k])
- if k > 0 {
- count -= int(pr.elemEndsEnds[k-1])
- }
- return count
-}
-
-func (pr *pkgDecoder) totalElems() int {
- return len(pr.elemEnds)
-}
-
-func (pr *pkgDecoder) absIdx(k reloc, idx int) int {
- absIdx := idx
- if k > 0 {
- absIdx += int(pr.elemEndsEnds[k-1])
- }
- if absIdx >= int(pr.elemEndsEnds[k]) {
- base.Fatalf("%v:%v is out of bounds; %v", k, idx, pr.elemEndsEnds)
- }
- return absIdx
-}
-
-func (pr *pkgDecoder) dataIdx(k reloc, idx int) string {
- absIdx := pr.absIdx(k, idx)
-
- var start uint32
- if absIdx > 0 {
- start = pr.elemEnds[absIdx-1]
- }
- end := pr.elemEnds[absIdx]
-
- return pr.elemData[start:end]
-}
-
-func (pr *pkgDecoder) stringIdx(idx int) string {
- return pr.dataIdx(relocString, idx)
-}
-
-func (pr *pkgDecoder) newDecoder(k reloc, idx int, marker syncMarker) decoder {
- r := pr.newDecoderRaw(k, idx)
- r.sync(marker)
- return r
-}
-
-func (pr *pkgDecoder) newDecoderRaw(k reloc, idx int) decoder {
- r := decoder{
- common: pr,
- k: k,
- idx: idx,
- }
-
- // TODO(mdempsky) r.data.Reset(...) after #44505 is resolved.
- r.data = *strings.NewReader(pr.dataIdx(k, idx))
-
- r.sync(syncRelocs)
- r.relocs = make([]relocEnt, r.len())
- for i := range r.relocs {
- r.sync(syncReloc)
- r.relocs[i] = relocEnt{reloc(r.len()), r.len()}
- }
-
- return r
-}
-
-type decoder struct {
- common *pkgDecoder
-
- relocs []relocEnt
- data strings.Reader
-
- k reloc
- idx int
-}
-
-func (r *decoder) checkErr(err error) {
- if err != nil {
- base.Fatalf("unexpected error: %v", err)
- }
-}
-
-func (r *decoder) rawUvarint() uint64 {
- x, err := binary.ReadUvarint(&r.data)
- r.checkErr(err)
- return x
-}
-
-func (r *decoder) rawVarint() int64 {
- ux := r.rawUvarint()
-
- // Zig-zag decode.
- x := int64(ux >> 1)
- if ux&1 != 0 {
- x = ^x
- }
- return x
-}
-
-func (r *decoder) rawReloc(k reloc, idx int) int {
- e := r.relocs[idx]
- assert(e.kind == k)
- return e.idx
-}
-
-func (r *decoder) sync(mWant syncMarker) {
- if !enableSync {
- return
- }
-
- pos, _ := r.data.Seek(0, os.SEEK_CUR) // TODO(mdempsky): io.SeekCurrent after #44505 is resolved
- mHave := syncMarker(r.rawUvarint())
- writerPCs := make([]int, r.rawUvarint())
- for i := range writerPCs {
- writerPCs[i] = int(r.rawUvarint())
- }
-
- if mHave == mWant {
- return
- }
-
- // There's some tension here between printing:
- //
- // (1) full file paths that tools can recognize (e.g., so emacs
- // hyperlinks the "file:line" text for easy navigation), or
- //
- // (2) short file paths that are easier for humans to read (e.g., by
- // omitting redundant or irrelevant details, so it's easier to
- // focus on the useful bits that remain).
- //
- // The current formatting favors the former, as it seems more
- // helpful in practice. But perhaps the formatting could be improved
- // to better address both concerns. For example, use relative file
- // paths if they would be shorter, or rewrite file paths to contain
- // "$GOROOT" (like objabi.AbsFile does) if tools can be taught how
- // to reliably expand that again.
-
- fmt.Printf("export data desync: package %q, section %v, index %v, offset %v\n", r.common.pkgPath, r.k, r.idx, pos)
-
- fmt.Printf("\nfound %v, written at:\n", mHave)
- if len(writerPCs) == 0 {
- fmt.Printf("\t[stack trace unavailable; recompile package %q with -d=syncframes]\n", r.common.pkgPath)
- }
- for _, pc := range writerPCs {
- fmt.Printf("\t%s\n", r.common.stringIdx(r.rawReloc(relocString, pc)))
- }
-
- fmt.Printf("\nexpected %v, reading at:\n", mWant)
- var readerPCs [32]uintptr // TODO(mdempsky): Dynamically size?
- n := runtime.Callers(2, readerPCs[:])
- for _, pc := range fmtFrames(readerPCs[:n]...) {
- fmt.Printf("\t%s\n", pc)
- }
-
- // We already printed a stack trace for the reader, so now we can
- // simply exit. Printing a second one with panic or base.Fatalf
- // would just be noise.
- os.Exit(1)
-}
-
-func (r *decoder) bool() bool {
- r.sync(syncBool)
- x, err := r.data.ReadByte()
- r.checkErr(err)
- assert(x < 2)
- return x != 0
-}
-
-func (r *decoder) int64() int64 {
- r.sync(syncInt64)
- return r.rawVarint()
-}
-
-func (r *decoder) uint64() uint64 {
- r.sync(syncUint64)
- return r.rawUvarint()
-}
-
-func (r *decoder) len() int { x := r.uint64(); v := int(x); assert(uint64(v) == x); return v }
-func (r *decoder) int() int { x := r.int64(); v := int(x); assert(int64(v) == x); return v }
-func (r *decoder) uint() uint { x := r.uint64(); v := uint(x); assert(uint64(v) == x); return v }
-
-func (r *decoder) code(mark syncMarker) int {
- r.sync(mark)
- return r.len()
-}
-
-func (r *decoder) reloc(k reloc) int {
- r.sync(syncUseReloc)
- return r.rawReloc(k, r.len())
-}
-
-func (r *decoder) string() string {
- r.sync(syncString)
- return r.common.stringIdx(r.reloc(relocString))
-}
-
-func (r *decoder) strings() []string {
- res := make([]string, r.len())
- for i := range res {
- res[i] = r.string()
- }
- return res
-}
-
-func (r *decoder) value() constant.Value {
- r.sync(syncValue)
- isComplex := r.bool()
- val := r.scalar()
- if isComplex {
- val = constant.BinaryOp(val, token.ADD, constant.MakeImag(r.scalar()))
- }
- return val
-}
-
-func (r *decoder) scalar() constant.Value {
- switch tag := codeVal(r.code(syncVal)); tag {
- default:
- panic(fmt.Sprintf("unexpected scalar tag: %v", tag))
-
- case valBool:
- return constant.MakeBool(r.bool())
- case valString:
- return constant.MakeString(r.string())
- case valInt64:
- return constant.MakeInt64(r.int64())
- case valBigInt:
- return constant.Make(r.bigInt())
- case valBigRat:
- num := r.bigInt()
- denom := r.bigInt()
- return constant.Make(new(big.Rat).SetFrac(num, denom))
- case valBigFloat:
- return constant.Make(r.bigFloat())
- }
-}
-
-func (r *decoder) bigInt() *big.Int {
- v := new(big.Int).SetBytes([]byte(r.string()))
- if r.bool() {
- v.Neg(v)
- }
- return v
-}
-
-func (r *decoder) bigFloat() *big.Float {
- v := new(big.Float).SetPrec(512)
- assert(v.UnmarshalText([]byte(r.string())) == nil)
- return v
-}