if buildcfg.Experiment.Unified {
Debug.Unified = 1
}
+ Debug.SyncFrames = -1 // disable sync markers by default
Debug.Checkptr = -1 // so we can tell whether it is set explicitly
assert(ctxt == ir.PAUTO || ctxt == ir.PPARAM || ctxt == ir.PPARAMOUT)
r.Sync(pkgbits.SyncAddLocal)
- if pkgbits.EnableSync {
+ if r.p.SyncMarkers() {
want := r.Int()
if have := len(r.locals); have != want {
base.FatalfAt(name.Pos(), "locals table has desynced")
func (w *writer) addLocal(obj *types2.Var) {
w.Sync(pkgbits.SyncAddLocal)
idx := len(w.localsIdx)
- if pkgbits.EnableSync {
+ if w.p.SyncMarkers() {
w.Int(idx)
}
if w.localsIdx == nil {
// A PkgDecoder provides methods for decoding a package's Unified IR
// export data.
type PkgDecoder struct {
+ // version is the file format version.
+ version uint32
+
+ // sync indicates whether the file uses sync markers.
+ sync bool
+
// pkgPath is the package path for the package to be decoded.
//
// TODO(mdempsky): Remove; unneeded since CL 391014.
// TODO(mdempsky): Remove; unneeded since CL 391014.
func (pr *PkgDecoder) PkgPath() string { return pr.pkgPath }
+// SyncMarkers reports whether pr uses sync markers.
+func (pr *PkgDecoder) SyncMarkers() bool { return pr.sync }
+
// NewPkgDecoder returns a PkgDecoder initialized to read the Unified
// IR export data from input. pkgPath is the package path for the
// compilation unit that produced the export data.
r := strings.NewReader(input)
- var version uint32
- assert(binary.Read(r, binary.LittleEndian, &version) == nil)
- assert(version == 0)
+ assert(binary.Read(r, binary.LittleEndian, &pr.version) == nil)
+
+ switch pr.version {
+ default:
+ panic(fmt.Errorf("unsupported version: %v", pr.version))
+ case 0:
+ // no flags
+ case 1:
+ var flags uint32
+ assert(binary.Read(r, binary.LittleEndian, &flags) == nil)
+ pr.sync = flags&flagSyncMarkers != 0
+ }
assert(binary.Read(r, binary.LittleEndian, pr.elemEndsEnds[:]) == nil)
//
// If EnableSync is false, then Sync is a no-op.
func (r *Decoder) Sync(mWant SyncMarker) {
- if !EnableSync {
+ if !r.common.sync {
return
}
"runtime"
)
+// currentVersion is the current version number.
+//
+// - v0: initial prototype
+//
+// - v1: adds the flags uint32 word
+const currentVersion uint32 = 1
+
// A PkgEncoder provides methods for encoding a package's Unified IR
// export data.
type PkgEncoder struct {
// elems[RelocString][stringsIdx[s]] == s (if present).
stringsIdx map[string]Index
+ // syncFrames is the number of frames to write at each sync
+ // marker. A negative value means sync markers are omitted.
syncFrames int
}
+// SyncMarkers reports whether pw uses sync markers.
+func (pw *PkgEncoder) SyncMarkers() bool { return pw.syncFrames >= 0 }
+
// NewPkgEncoder returns an initialized PkgEncoder.
//
// syncFrames is the number of caller frames that should be serialized
// at Sync points. Serializing additional frames results in larger
// export data files, but can help diagnosing desync errors in
-// higher-level Unified IR reader/writer code.
+// higher-level Unified IR reader/writer code. If syncFrames is
+// negative, then sync markers are omitted entirely.
func NewPkgEncoder(syncFrames int) PkgEncoder {
return PkgEncoder{
stringsIdx: make(map[string]Index),
assert(binary.Write(out, binary.LittleEndian, x) == nil)
}
- writeUint32(0) // version
+ writeUint32(currentVersion)
+
+ var flags uint32
+ if pw.SyncMarkers() {
+ flags |= flagSyncMarkers
+ }
+ writeUint32(flags)
// Write elemEndsEnds.
var sum uint32
}
func (w *Encoder) Sync(m SyncMarker) {
- if !EnableSync {
+ if !w.p.SyncMarkers() {
return
}
--- /dev/null
+// Copyright 2022 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 pkgbits
+
+const (
+ flagSyncMarkers = 1 << iota // file format contains sync markers
+)
"strings"
)
-// EnableSync controls whether sync markers are written into unified
-// IR's export data format and also whether they're expected when
-// reading them back in. They're inessential to the correct
-// functioning of unified IR, but are helpful during development to
-// detect mistakes.
-//
-// When sync is enabled, writer stack frames will also be included in
-// the export data. Currently, a fixed number of frames are included,
-// controlled by -d=syncframes (default 0).
-const EnableSync = true
-
// fmtFrames formats a backtrace for reporting reader/writer desyncs.
func fmtFrames(pcs ...uintptr) []string {
res := make([]string, 0, len(pcs))