aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Dempsky <mdempsky@google.com>2022-07-31 18:48:16 -0700
committerGopher Robot <gobot@golang.org>2022-08-03 19:20:41 +0000
commitc9f2150cfb3c1db87f6434f727c25403d985a6e4 (patch)
tree8341f6a10d7a5aa209510ee79006e0bac3bc65be
parent994ff78ba01b921870866f9ce9db7563bd89494f (diff)
downloadgo-c9f2150cfb3c1db87f6434f727c25403d985a6e4.tar.gz
go-c9f2150cfb3c1db87f6434f727c25403d985a6e4.zip
[dev.unified] cmd/compile: start using runtime dictionaries
This CL switches unified IR to start using runtime dictionaries, rather than pure stenciling. In particular, for each instantiated function `F[T]`, it now: 1. Generates a global variable `F[T]-dict` of type `[N]uintptr`, with all of the `*runtime._type` values needed by `F[T]`. 2. Generates a function `F[T]-shaped`, with an extra `.dict *[N]uintptr` parameter and indexing into that parameter for derived types. (N.B., this function is not yet actually using shape types.) 3. Changes `F[T]` to instead be a wrapper function that calls `F[T]-shaped` passing `&F[T]-dict` as the `.dict` parameter. This is done in one pass to make sure the overall wiring is all working (especially, function literals and inlining). Subsequent CLs will write more information into `F[T]-dict` and update `F[T]-shaped` to use it instead of relying on `T`-derived information itself. Once that's done, `F[T]-shaped` can be changed to `F[shapify(T)]` (e.g., `F[go.shape.int]`) and deduplicated. Change-Id: I0e802a4d9934794e01a6bfc367820af893335155 Reviewed-on: https://go-review.googlesource.com/c/go/+/420416 Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Auto-Submit: Matthew Dempsky <mdempsky@google.com> Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com> Reviewed-by: Keith Randall <khr@google.com> Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: David Chase <drchase@google.com>
-rw-r--r--src/cmd/compile/internal/noder/reader.go318
-rw-r--r--src/cmd/compile/internal/noder/unified.go4
-rw-r--r--src/cmd/compile/internal/noder/writer.go22
-rw-r--r--src/cmd/compile/internal/ssa/debug_lines_test.go4
-rw-r--r--src/internal/pkgbits/encoder.go1
5 files changed, 308 insertions, 41 deletions
diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go
index 9458332fc8..d02d05bc5d 100644
--- a/src/cmd/compile/internal/noder/reader.go
+++ b/src/cmd/compile/internal/noder/reader.go
@@ -17,6 +17,7 @@ import (
"cmd/compile/internal/dwarfgen"
"cmd/compile/internal/inline"
"cmd/compile/internal/ir"
+ "cmd/compile/internal/objw"
"cmd/compile/internal/reflectdata"
"cmd/compile/internal/typecheck"
"cmd/compile/internal/types"
@@ -61,14 +62,16 @@ func newPkgReader(pr pkgbits.PkgDecoder) *pkgReader {
// A pkgReaderIndex compactly identifies an index (and its
// corresponding dictionary) within a package's export data.
type pkgReaderIndex struct {
- pr *pkgReader
- idx pkgbits.Index
- dict *readerDict
+ pr *pkgReader
+ idx pkgbits.Index
+ dict *readerDict
+ shapedFn *ir.Func
}
func (pri pkgReaderIndex) asReader(k pkgbits.RelocKind, marker pkgbits.SyncMarker) *reader {
r := pri.pr.newReader(k, pri.idx, marker)
r.dict = pri.dict
+ r.shapedFn = pri.shapedFn
return r
}
@@ -98,6 +101,12 @@ type reader struct {
funarghack bool
+ // shapedFn is the shape-typed version of curfn, if any.
+ shapedFn *ir.Func
+
+ // dictParam is the .dict param, if any.
+ dictParam *ir.Name
+
// scopeVars is a stack tracking the number of variables declared in
// the current function at the moment each open scope was opened.
scopeVars []int
@@ -119,7 +128,13 @@ type reader struct {
// Label to return to.
retlabel *types.Sym
- inlvars, retvars ir.Nodes
+ // inlvars is the list of variables that the inlinee's arguments are
+ // assigned to, one for each receiver and normal parameter, in order.
+ inlvars ir.Nodes
+
+ // retvars is the list of variables that the inlinee's results are
+ // assigned to, one for each result parameter, in order.
+ retvars ir.Nodes
}
type readerDict struct {
@@ -737,12 +752,7 @@ func (pr *pkgReader) objDictIdx(sym *types.Sym, idx pkgbits.Index, implicits, ex
// For stenciling, we can just skip over the type parameters.
for range dict.targs[dict.implicits:] {
// Skip past bounds without actually evaluating them.
- r.Sync(pkgbits.SyncType)
- if r.Bool() {
- r.Len()
- } else {
- r.Reloc(pkgbits.RelocType)
- }
+ r.typInfo()
}
dict.derived = make([]derivedInfo, r.Len())
@@ -806,9 +816,7 @@ func (r *reader) method(rext *reader) *types.Field {
_, recv := r.param()
typ := r.signature(pkg, recv)
- fnsym := sym
- fnsym = ir.MethodSym(recv.Type, fnsym)
- name := ir.NewNameAt(pos, fnsym)
+ name := ir.NewNameAt(pos, ir.MethodSym(recv.Type, sym))
setType(name, typ)
name.Func = ir.NewFunc(r.pos())
@@ -981,7 +989,7 @@ var importBodyReader = map[*types.Sym]pkgReaderIndex{}
func bodyReaderFor(fn *ir.Func) (pri pkgReaderIndex, ok bool) {
if fn.Nname.Defn != nil {
pri, ok = bodyReader[fn]
- assert(ok) // must always be available
+ base.AssertfAt(ok, base.Pos, "must have bodyReader for %v", fn) // must always be available
} else {
pri, ok = importBodyReader[fn.Sym()]
}
@@ -999,7 +1007,38 @@ func (r *reader) addBody(fn *ir.Func) {
// generic functions; see comment in funcExt.
assert(fn.Nname.Defn != nil)
- pri := pkgReaderIndex{r.p, r.Reloc(pkgbits.RelocBody), r.dict}
+ idx := r.Reloc(pkgbits.RelocBody)
+
+ var shapedFn *ir.Func
+ if r.hasTypeParams() && fn.OClosure == nil {
+ name := fn.Nname
+ sym := name.Sym()
+
+ shapedSym := sym.Pkg.Lookup(sym.Name + "-shaped")
+
+ // TODO(mdempsky): Once we actually start shaping functions, we'll
+ // need to deduplicate them.
+ shaped := ir.NewDeclNameAt(name.Pos(), ir.ONAME, shapedSym)
+ setType(shaped, shapeSig(fn, r.dict)) // TODO(mdempsky): Use shape types.
+
+ shapedFn = ir.NewFunc(fn.Pos())
+ shaped.Func = shapedFn
+ shapedFn.Nname = shaped
+ shapedFn.SetDupok(true)
+
+ shaped.Class = 0 // so MarkFunc doesn't complain
+ ir.MarkFunc(shaped)
+
+ shaped.Defn = shapedFn
+
+ shapedFn.Pragma = fn.Pragma // TODO(mdempsky): How does stencil.go handle pragmas?
+ typecheck.Func(shapedFn)
+
+ bodyReader[shapedFn] = pkgReaderIndex{r.p, idx, r.dict, nil}
+ todoBodies = append(todoBodies, shapedFn)
+ }
+
+ pri := pkgReaderIndex{r.p, idx, r.dict, shapedFn}
bodyReader[fn] = pri
if r.curfn == nil {
@@ -1020,6 +1059,9 @@ func (pri pkgReaderIndex) funcBody(fn *ir.Func) {
func (r *reader) funcBody(fn *ir.Func) {
r.curfn = fn
r.closureVars = fn.ClosureVars
+ if len(r.closureVars) != 0 && r.hasTypeParams() {
+ r.dictParam = r.closureVars[len(r.closureVars)-1] // dictParam is last; see reader.funcLit
+ }
ir.WithFunc(fn, func() {
r.funcargs(fn)
@@ -1028,6 +1070,11 @@ func (r *reader) funcBody(fn *ir.Func) {
return
}
+ if r.shapedFn != nil {
+ r.callShaped(fn.Pos())
+ return
+ }
+
body := r.stmts()
if body == nil {
body = []ir.Node{typecheck.Stmt(ir.NewBlockStmt(src.NoXPos, nil))}
@@ -1039,6 +1086,139 @@ func (r *reader) funcBody(fn *ir.Func) {
r.marker.WriteTo(fn)
}
+// callShaped emits a tail call to r.shapedFn, passing along the
+// arguments to the current function.
+func (r *reader) callShaped(pos src.XPos) {
+ sig := r.curfn.Nname.Type()
+
+ var args ir.Nodes
+
+ // First argument is a pointer to the -dict global variable.
+ args.Append(r.dictPtr())
+
+ // Collect the arguments to the current function, so we can pass
+ // them along to the shaped function. (This is unfortunately quite
+ // hairy.)
+ for _, params := range &types.RecvsParams {
+ for _, param := range params(sig).FieldSlice() {
+ var arg ir.Node
+ if param.Nname != nil {
+ name := param.Nname.(*ir.Name)
+ if !ir.IsBlank(name) {
+ if r.inlCall != nil {
+ // During inlining, we want the respective inlvar where we
+ // assigned the callee's arguments.
+ arg = r.inlvars[len(args)-1]
+ } else {
+ // Otherwise, we can use the parameter itself directly.
+ base.AssertfAt(name.Curfn == r.curfn, name.Pos(), "%v has curfn %v, but want %v", name, name.Curfn, r.curfn)
+ arg = name
+ }
+ }
+ }
+
+ // For anonymous and blank parameters, we don't have an *ir.Name
+ // to use as the argument. However, since we know the shaped
+ // function won't use the value either, we can just pass the
+ // zero value. (Also unfortunately, we don't have an easy
+ // zero-value IR node; so we use a default-initialized temporary
+ // variable.)
+ if arg == nil {
+ tmp := typecheck.TempAt(pos, r.curfn, param.Type)
+ r.curfn.Body.Append(
+ typecheck.Stmt(ir.NewDecl(pos, ir.ODCL, tmp)),
+ typecheck.Stmt(ir.NewAssignStmt(pos, tmp, nil)),
+ )
+ arg = tmp
+ }
+
+ args.Append(arg)
+ }
+ }
+
+ // Mark the function as a wrapper so it doesn't show up in stack
+ // traces.
+ r.curfn.SetWrapper(true)
+
+ call := typecheck.Call(pos, r.shapedFn.Nname, args, sig.IsVariadic()).(*ir.CallExpr)
+
+ var stmt ir.Node
+ if sig.NumResults() != 0 {
+ stmt = typecheck.Stmt(ir.NewReturnStmt(pos, []ir.Node{call}))
+ } else {
+ stmt = call
+ }
+ r.curfn.Body.Append(stmt)
+}
+
+// dictPtr returns a pointer to the runtime dictionary variable needed
+// for the current function to call its shaped variant.
+func (r *reader) dictPtr() ir.Node {
+ var fn *ir.Func
+ if r.inlCall != nil {
+ // During inlining, r.curfn is named after the caller (not the
+ // callee), because it's relevant to closure naming, sigh.
+ fn = r.inlFunc
+ } else {
+ fn = r.curfn
+ }
+
+ var baseSym *types.Sym
+ if recv := fn.Nname.Type().Recv(); recv != nil {
+ // All methods of a given instantiated receiver type share the
+ // same dictionary.
+ baseSym = deref(recv.Type).Sym()
+ } else {
+ baseSym = fn.Nname.Sym()
+ }
+
+ sym := baseSym.Pkg.Lookup(baseSym.Name + "-dict")
+
+ if sym.Def == nil {
+ dict := ir.NewNameAt(r.curfn.Pos(), sym)
+ dict.Class = ir.PEXTERN
+
+ lsym := dict.Linksym()
+ ot := 0
+
+ for idx, info := range r.dict.derived {
+ if info.needed {
+ typ := r.p.typIdx(typeInfo{idx: pkgbits.Index(idx), derived: true}, r.dict, false)
+ rtype := reflectdata.TypeLinksym(typ)
+ ot = objw.SymPtr(lsym, ot, rtype, 0)
+ } else {
+ // TODO(mdempsky): Compact unused runtime dictionary space.
+ ot = objw.Uintptr(lsym, ot, 0)
+ }
+ }
+
+ // TODO(mdempsky): Write out more dictionary information.
+
+ objw.Global(lsym, int32(ot), obj.DUPOK|obj.RODATA)
+
+ dict.SetType(r.dict.varType())
+ dict.SetTypecheck(1)
+
+ sym.Def = dict
+ }
+
+ return typecheck.Expr(ir.NewAddrExpr(r.curfn.Pos(), sym.Def.(*ir.Name)))
+}
+
+// numWords returns the number of words that dict's runtime dictionary
+// variable requires.
+func (dict *readerDict) numWords() int64 {
+ var num int
+ num += len(dict.derivedTypes)
+ // TODO(mdempsky): Add space for more dictionary information.
+ return int64(num)
+}
+
+// varType returns the type of dict's runtime dictionary variable.
+func (dict *readerDict) varType() *types.Type {
+ return types.NewArray(types.Types[types.TUINTPTR], dict.numWords())
+}
+
func (r *reader) funcargs(fn *ir.Func) {
sig := fn.Nname.Type()
@@ -1096,16 +1276,20 @@ func (r *reader) funcarg(param *types.Field, sym *types.Sym, ctxt ir.Class) {
func (r *reader) addLocal(name *ir.Name, ctxt ir.Class) {
assert(ctxt == ir.PAUTO || ctxt == ir.PPARAM || ctxt == ir.PPARAMOUT)
- r.Sync(pkgbits.SyncAddLocal)
- if r.p.SyncMarkers() {
- want := r.Int()
- if have := len(r.locals); have != want {
- base.FatalfAt(name.Pos(), "locals table has desynced")
+ if name.Sym().Name == dictParamName {
+ r.dictParam = name
+ } else {
+ r.Sync(pkgbits.SyncAddLocal)
+ if r.p.SyncMarkers() {
+ want := r.Int()
+ if have := len(r.locals); have != want {
+ base.FatalfAt(name.Pos(), "locals table has desynced")
+ }
}
+ r.locals = append(r.locals, name)
}
name.SetUsed(true)
- r.locals = append(r.locals, name)
// TODO(mdempsky): Move earlier.
if ir.IsBlank(name) {
@@ -2000,6 +2184,11 @@ func (r *reader) funcLit() ir.Node {
for len(fn.ClosureVars) < cap(fn.ClosureVars) {
ir.NewClosureVar(r.pos(), fn, r.useLocal())
}
+ if param := r.dictParam; param != nil {
+ // If we have a dictionary parameter, capture it too. For
+ // simplicity, we capture it last and unconditionally.
+ ir.NewClosureVar(param.Pos(), fn, param)
+ }
r.addBody(fn)
@@ -2024,39 +2213,60 @@ func (r *reader) exprs() []ir.Node {
return nodes
}
-// rtype returns an expression of type *runtime._type.
+// dictWord returns an expression to return the specified
+// uintptr-typed word from the dictionary parameter.
+func (r *reader) dictWord(pos src.XPos, idx int64) ir.Node {
+ base.AssertfAt(r.dictParam != nil, pos, "expected dictParam in %v", r.curfn)
+ return typecheck.Expr(ir.NewIndexExpr(pos, r.dictParam, ir.NewBasicLit(pos, constant.MakeInt64(idx))))
+}
+
+// rtype reads a type reference from the element bitstream, and
+// returns an expression of type *runtime._type representing that
+// type.
func (r *reader) rtype(pos src.XPos) ir.Node {
r.Sync(pkgbits.SyncRType)
- // TODO(mdempsky): For derived types, use dictionary instead.
- return reflectdata.TypePtrAt(pos, r.typ())
+ return r.rtypeInfo(pos, r.typInfo())
+}
+
+// rtypeInfo returns an expression of type *runtime._type representing
+// the given decoded type reference.
+func (r *reader) rtypeInfo(pos src.XPos, info typeInfo) ir.Node {
+ if !info.derived {
+ typ := r.p.typIdx(info, r.dict, true)
+ return reflectdata.TypePtrAt(pos, typ)
+ }
+ return typecheck.Expr(ir.NewConvExpr(pos, ir.OCONVNOP, types.NewPtr(types.Types[types.TUINT8]), r.dictWord(pos, int64(info.idx))))
}
// convRTTI returns expressions appropriate for populating an
// ir.ConvExpr's TypeWord and SrcRType fields, respectively.
func (r *reader) convRTTI(pos src.XPos) (typeWord, srcRType ir.Node) {
r.Sync(pkgbits.SyncConvRTTI)
- src := r.typ()
- dst := r.typ()
+ srcInfo := r.typInfo()
+ dstInfo := r.typInfo()
+ dst := r.p.typIdx(dstInfo, r.dict, true)
if !dst.IsInterface() {
return
}
+ src := r.p.typIdx(srcInfo, r.dict, true)
+
// See reflectdata.ConvIfaceTypeWord.
switch {
case dst.IsEmptyInterface():
if !src.IsInterface() {
- typeWord = reflectdata.TypePtrAt(pos, src) // direct eface construction
+ typeWord = r.rtypeInfo(pos, srcInfo) // direct eface construction
}
case !src.IsInterface():
typeWord = reflectdata.ITabAddrAt(pos, src, dst) // direct iface construction
default:
- typeWord = reflectdata.TypePtrAt(pos, dst) // convI2I
+ typeWord = r.rtypeInfo(pos, dstInfo) // convI2I
}
// See reflectdata.ConvIfaceSrcRType.
if !src.IsInterface() {
- srcRType = reflectdata.TypePtrAt(pos, src)
+ srcRType = r.rtypeInfo(pos, srcInfo)
}
return
@@ -2096,7 +2306,7 @@ func (r *reader) exprType() ir.Node {
return n
}
- rtype = lsymPtr(reflectdata.TypeLinksym(typ))
+ rtype = r.rtypeInfo(pos, info)
}
dt := ir.NewDynamicType(pos, rtype)
@@ -2275,6 +2485,9 @@ func InlineCall(call *ir.CallExpr, fn *ir.Func, inlIndex int) *ir.InlinedCallExp
for i, cv := range r.inlFunc.ClosureVars {
r.closureVars[i] = cv.Outer
}
+ if len(r.closureVars) != 0 && r.hasTypeParams() {
+ r.dictParam = r.closureVars[len(r.closureVars)-1] // dictParam is last; see reader.funcLit
+ }
r.funcargs(fn)
@@ -2337,8 +2550,12 @@ func InlineCall(call *ir.CallExpr, fn *ir.Func, inlIndex int) *ir.InlinedCallExp
nparams := len(r.curfn.Dcl)
ir.WithFunc(r.curfn, func() {
- r.curfn.Body = r.stmts()
- r.curfn.Endlineno = r.pos()
+ if r.shapedFn != nil {
+ r.callShaped(call.Pos())
+ } else {
+ r.curfn.Body = r.stmts()
+ r.curfn.Endlineno = r.pos()
+ }
// TODO(mdempsky): This shouldn't be necessary. Inlining might
// read in new function/method declarations, which could
@@ -2800,3 +3017,40 @@ func setBasePos(pos src.XPos) {
// Set the position for any error messages we might print (e.g. too large types).
base.Pos = pos
}
+
+// dictParamName is the name of the synthetic dictionary parameter
+// added to shaped functions.
+const dictParamName = ".dict"
+
+// shapeSig returns a copy of fn's signature, except adding a
+// dictionary parameter and promoting the receiver parameter (if any)
+// to a normal parameter.
+//
+// The parameter types.Fields are all copied too, so their Nname
+// fields can be initialized for use by the shape function.
+func shapeSig(fn *ir.Func, dict *readerDict) *types.Type {
+ sig := fn.Nname.Type()
+ recv := sig.Recv()
+ nrecvs := 0
+ if recv != nil {
+ nrecvs++
+ }
+
+ params := make([]*types.Field, 1+nrecvs+sig.Params().Fields().Len())
+ params[0] = types.NewField(fn.Pos(), fn.Sym().Pkg.Lookup(dictParamName), types.NewPtr(dict.varType()))
+ if recv != nil {
+ params[1] = types.NewField(recv.Pos, recv.Sym, recv.Type)
+ }
+ for i, param := range sig.Params().Fields().Slice() {
+ d := types.NewField(param.Pos, param.Sym, param.Type)
+ d.SetIsDDD(param.IsDDD())
+ params[1+nrecvs+i] = d
+ }
+
+ results := make([]*types.Field, sig.Results().Fields().Len())
+ for i, result := range sig.Results().Fields().Slice() {
+ results[i] = types.NewField(result.Pos, result.Sym, result.Type)
+ }
+
+ return types.NewSignature(types.LocalPkg, nil, nil, params, results)
+}
diff --git a/src/cmd/compile/internal/noder/unified.go b/src/cmd/compile/internal/noder/unified.go
index eebbb03742..1ded367383 100644
--- a/src/cmd/compile/internal/noder/unified.go
+++ b/src/cmd/compile/internal/noder/unified.go
@@ -247,7 +247,7 @@ func readPackage(pr *pkgReader, importpkg *types.Pkg, localStub bool) {
path, name, code := r.p.PeekObj(idx)
if code != pkgbits.ObjStub {
- objReader[types.NewPkg(path, "").Lookup(name)] = pkgReaderIndex{pr, idx, nil}
+ objReader[types.NewPkg(path, "").Lookup(name)] = pkgReaderIndex{pr, idx, nil, nil}
}
}
@@ -271,7 +271,7 @@ func readPackage(pr *pkgReader, importpkg *types.Pkg, localStub bool) {
sym := types.NewPkg(path, "").Lookup(name)
if _, ok := importBodyReader[sym]; !ok {
- importBodyReader[sym] = pkgReaderIndex{pr, idx, nil}
+ importBodyReader[sym] = pkgReaderIndex{pr, idx, nil, nil}
}
}
diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go
index 0005c2e7fa..5f8767bf83 100644
--- a/src/cmd/compile/internal/noder/writer.go
+++ b/src/cmd/compile/internal/noder/writer.go
@@ -190,7 +190,7 @@ type writerDict struct {
// A derivedInfo represents a reference to an encoded generic Go type.
type derivedInfo struct {
idx pkgbits.Index
- needed bool // TODO(mdempsky): Remove; will break x/tools importer
+ needed bool
}
// A typeInfo represents a reference to an encoded Go type.
@@ -1952,15 +1952,26 @@ func (w *writer) exprs(exprs []syntax.Expr) {
// expression of type *runtime._type representing typ.
func (w *writer) rtype(typ types2.Type) {
w.Sync(pkgbits.SyncRType)
- w.typ(typ)
+ w.typNeeded(typ)
+}
+
+// typNeeded writes a reference to typ, and records that its
+// *runtime._type is needed.
+func (w *writer) typNeeded(typ types2.Type) {
+ info := w.p.typIdx(typ, w.dict)
+ w.typInfo(info)
+
+ if info.derived {
+ w.dict.derived[info.idx].needed = true
+ }
}
// convRTTI writes information so that the reader can construct
// expressions for converting from src to dst.
func (w *writer) convRTTI(src, dst types2.Type) {
w.Sync(pkgbits.SyncConvRTTI)
- w.typ(src)
- w.typ(dst)
+ w.typNeeded(src)
+ w.typNeeded(dst)
}
func (w *writer) exprType(iface types2.Type, typ syntax.Expr) {
@@ -1992,6 +2003,9 @@ func (w *writer) exprType(iface types2.Type, typ syntax.Expr) {
}
w.typInfo(info)
+ if info.derived {
+ w.dict.derived[info.idx].needed = true
+ }
}
func (dict *writerDict) methodExprIdx(recvInfo typeInfo, methodInfo selectorInfo) int {
diff --git a/src/cmd/compile/internal/ssa/debug_lines_test.go b/src/cmd/compile/internal/ssa/debug_lines_test.go
index a76358967d..1b564055d3 100644
--- a/src/cmd/compile/internal/ssa/debug_lines_test.go
+++ b/src/cmd/compile/internal/ssa/debug_lines_test.go
@@ -76,7 +76,7 @@ func TestDebugLinesPushback(t *testing.T) {
fn := "(*List[go.shape.int_0]).PushBack"
if buildcfg.Experiment.Unified {
// Unified mangles differently
- fn = "(*List[int]).PushBack"
+ fn = "(*List[int]).PushBack-shaped"
}
testDebugLines(t, "-N -l", "pushback.go", fn, []int{17, 18, 19, 20, 21, 22, 24}, true)
}
@@ -95,7 +95,7 @@ func TestDebugLinesConvert(t *testing.T) {
fn := "G[go.shape.int_0]"
if buildcfg.Experiment.Unified {
// Unified mangles differently
- fn = "G[int]"
+ fn = "G[int]-shaped"
}
testDebugLines(t, "-N -l", "convertline.go", fn, []int{9, 10, 11}, true)
}
diff --git a/src/internal/pkgbits/encoder.go b/src/internal/pkgbits/encoder.go
index f1bc8367ef..ec47e352cb 100644
--- a/src/internal/pkgbits/encoder.go
+++ b/src/internal/pkgbits/encoder.go
@@ -21,7 +21,6 @@ import (
// - v1: adds the flags uint32 word
//
// TODO(mdempsky): For the next version bump:
-// - remove the unused dict.derived.needed bool
// - remove the legacy "has init" bool from the public root
const currentVersion uint32 = 1