diff options
| author | Matthew Dempsky <mdempsky@google.com> | 2022-02-14 09:41:19 -0800 |
|---|---|---|
| committer | Matthew Dempsky <mdempsky@google.com> | 2022-03-01 07:36:05 +0000 |
| commit | 7c151f328056c354d3db13c17b3d96bec316cff6 (patch) | |
| tree | 01327d059a54a85d4cfe4f83bdcefeb2626d6c9f /src/cmd/compile/internal/noder/encoder.go | |
| parent | 6d881da9c894dfcd8c3dda0057a7c63a3ab59ea2 (diff) | |
| download | go-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/encoder.go')
| -rw-r--r-- | src/cmd/compile/internal/noder/encoder.go | 285 |
1 files changed, 0 insertions, 285 deletions
diff --git a/src/cmd/compile/internal/noder/encoder.go b/src/cmd/compile/internal/noder/encoder.go deleted file mode 100644 index b07b3a4a48..0000000000 --- a/src/cmd/compile/internal/noder/encoder.go +++ /dev/null @@ -1,285 +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 ( - "bytes" - "encoding/binary" - "fmt" - "go/constant" - "io" - "math/big" - "runtime" - - "cmd/compile/internal/base" -) - -type pkgEncoder struct { - elems [numRelocs][]string - - stringsIdx map[string]int -} - -func newPkgEncoder() pkgEncoder { - return pkgEncoder{ - stringsIdx: make(map[string]int), - } -} - -func (pw *pkgEncoder) dump(out io.Writer) { - writeUint32 := func(x uint32) { - assert(binary.Write(out, binary.LittleEndian, x) == nil) - } - - var sum uint32 - for _, elems := range &pw.elems { - sum += uint32(len(elems)) - writeUint32(sum) - } - - sum = 0 - for _, elems := range &pw.elems { - for _, elem := range elems { - sum += uint32(len(elem)) - writeUint32(sum) - } - } - - for _, elems := range &pw.elems { - for _, elem := range elems { - _, err := io.WriteString(out, elem) - assert(err == nil) - } - } -} - -func (pw *pkgEncoder) stringIdx(s string) int { - if idx, ok := pw.stringsIdx[s]; ok { - assert(pw.elems[relocString][idx] == s) - return idx - } - - idx := len(pw.elems[relocString]) - pw.elems[relocString] = append(pw.elems[relocString], s) - pw.stringsIdx[s] = idx - return idx -} - -func (pw *pkgEncoder) newEncoder(k reloc, marker syncMarker) encoder { - e := pw.newEncoderRaw(k) - e.sync(marker) - return e -} - -func (pw *pkgEncoder) newEncoderRaw(k reloc) encoder { - idx := len(pw.elems[k]) - pw.elems[k] = append(pw.elems[k], "") // placeholder - - return encoder{ - p: pw, - k: k, - idx: idx, - } -} - -// Encoders - -type encoder struct { - p *pkgEncoder - - relocs []relocEnt - data bytes.Buffer - - encodingRelocHeader bool - - k reloc - idx int -} - -func (w *encoder) flush() int { - var sb bytes.Buffer // TODO(mdempsky): strings.Builder after #44505 is resolved - - // Backup the data so we write the relocations at the front. - var tmp bytes.Buffer - io.Copy(&tmp, &w.data) - - // TODO(mdempsky): Consider writing these out separately so they're - // easier to strip, along with function bodies, so that we can prune - // down to just the data that's relevant to go/types. - if w.encodingRelocHeader { - base.Fatalf("encodingRelocHeader already true; recursive flush?") - } - w.encodingRelocHeader = true - w.sync(syncRelocs) - w.len(len(w.relocs)) - for _, rent := range w.relocs { - w.sync(syncReloc) - w.len(int(rent.kind)) - w.len(rent.idx) - } - - io.Copy(&sb, &w.data) - io.Copy(&sb, &tmp) - w.p.elems[w.k][w.idx] = sb.String() - - return w.idx -} - -func (w *encoder) checkErr(err error) { - if err != nil { - base.Fatalf("unexpected error: %v", err) - } -} - -func (w *encoder) rawUvarint(x uint64) { - var buf [binary.MaxVarintLen64]byte - n := binary.PutUvarint(buf[:], x) - _, err := w.data.Write(buf[:n]) - w.checkErr(err) -} - -func (w *encoder) rawVarint(x int64) { - // Zig-zag encode. - ux := uint64(x) << 1 - if x < 0 { - ux = ^ux - } - - w.rawUvarint(ux) -} - -func (w *encoder) rawReloc(r reloc, idx int) int { - // TODO(mdempsky): Use map for lookup. - for i, rent := range w.relocs { - if rent.kind == r && rent.idx == idx { - return i - } - } - - i := len(w.relocs) - w.relocs = append(w.relocs, relocEnt{r, idx}) - return i -} - -func (w *encoder) sync(m syncMarker) { - if !enableSync { - return - } - - // Writing out stack frame string references requires working - // relocations, but writing out the relocations themselves involves - // sync markers. To prevent infinite recursion, we simply trim the - // stack frame for sync markers within the relocation header. - var frames []string - if !w.encodingRelocHeader && base.Debug.SyncFrames > 0 { - pcs := make([]uintptr, base.Debug.SyncFrames) - n := runtime.Callers(2, pcs) - frames = fmtFrames(pcs[:n]...) - } - - // TODO(mdempsky): Save space by writing out stack frames as a - // linked list so we can share common stack frames. - w.rawUvarint(uint64(m)) - w.rawUvarint(uint64(len(frames))) - for _, frame := range frames { - w.rawUvarint(uint64(w.rawReloc(relocString, w.p.stringIdx(frame)))) - } -} - -func (w *encoder) bool(b bool) bool { - w.sync(syncBool) - var x byte - if b { - x = 1 - } - err := w.data.WriteByte(x) - w.checkErr(err) - return b -} - -func (w *encoder) int64(x int64) { - w.sync(syncInt64) - w.rawVarint(x) -} - -func (w *encoder) uint64(x uint64) { - w.sync(syncUint64) - w.rawUvarint(x) -} - -func (w *encoder) len(x int) { assert(x >= 0); w.uint64(uint64(x)) } -func (w *encoder) int(x int) { w.int64(int64(x)) } -func (w *encoder) uint(x uint) { w.uint64(uint64(x)) } - -func (w *encoder) reloc(r reloc, idx int) { - w.sync(syncUseReloc) - w.len(w.rawReloc(r, idx)) -} - -func (w *encoder) code(c code) { - w.sync(c.marker()) - w.len(c.value()) -} - -func (w *encoder) string(s string) { - w.sync(syncString) - w.reloc(relocString, w.p.stringIdx(s)) -} - -func (w *encoder) strings(ss []string) { - w.len(len(ss)) - for _, s := range ss { - w.string(s) - } -} - -func (w *encoder) value(val constant.Value) { - w.sync(syncValue) - if w.bool(val.Kind() == constant.Complex) { - w.scalar(constant.Real(val)) - w.scalar(constant.Imag(val)) - } else { - w.scalar(val) - } -} - -func (w *encoder) scalar(val constant.Value) { - switch v := constant.Val(val).(type) { - default: - panic(fmt.Sprintf("unhandled %v (%v)", val, val.Kind())) - case bool: - w.code(valBool) - w.bool(v) - case string: - w.code(valString) - w.string(v) - case int64: - w.code(valInt64) - w.int64(v) - case *big.Int: - w.code(valBigInt) - w.bigInt(v) - case *big.Rat: - w.code(valBigRat) - w.bigInt(v.Num()) - w.bigInt(v.Denom()) - case *big.Float: - w.code(valBigFloat) - w.bigFloat(v) - } -} - -func (w *encoder) bigInt(v *big.Int) { - b := v.Bytes() - w.string(string(b)) // TODO: More efficient encoding. - w.bool(v.Sign() < 0) -} - -func (w *encoder) bigFloat(v *big.Float) { - b := v.Append(nil, 'p', -1) - w.string(string(b)) // TODO: More efficient encoding. -} |
