// obj reads an instantiated object reference from the bitstream.
func (r *reader) obj() ir.Node {
r.Sync(pkgbits.SyncObject)
-
- if r.Bool() {
- idx := r.Len()
- obj := r.dict.funcsObj[idx]
- if obj == nil {
- fn := r.dict.funcs[idx]
- targs := make([]*types.Type, len(fn.explicits))
- for i, targ := range fn.explicits {
- targs[i] = r.p.typIdx(targ, r.dict, true)
- }
-
- obj = r.p.objIdx(fn.idx, nil, targs)
- assert(r.dict.funcsObj[idx] == nil)
- r.dict.funcsObj[idx] = obj
- }
- return obj
- }
-
+ assert(!r.Bool()) // TODO(mdempsky): Remove; was derived func inst.
idx := r.Reloc(pkgbits.RelocObj)
explicits := make([]*types.Type, r.Len())
// TODO(mdempsky): Handle builtins directly in exprCall, like method calls?
return typecheck.Callee(r.obj())
+ case exprFuncInst:
+ if r.Bool() {
+ idx := r.Len()
+ obj := r.dict.funcsObj[idx]
+ if obj == nil {
+ fn := r.dict.funcs[idx]
+ targs := make([]*types.Type, len(fn.explicits))
+ for i, targ := range fn.explicits {
+ targs[i] = r.p.typIdx(targ, r.dict, true)
+ }
+
+ obj = r.p.objIdx(fn.idx, nil, targs)
+ assert(r.dict.funcsObj[idx] == nil)
+ r.dict.funcsObj[idx] = obj
+ }
+ return obj
+ }
+ return r.obj()
+
case exprConst:
pos := r.pos()
typ := r.typ()
// arguments used to instantiate it (i.e., used to substitute the
// object's own declared type parameters).
func (w *writer) obj(obj types2.Object, explicits *types2.TypeList) {
- explicitInfos := make([]typeInfo, explicits.Len())
- for i := range explicitInfos {
- explicitInfos[i] = w.p.typIdx(explicits.At(i), w.dict)
- }
- info := objInfo{idx: w.p.objIdx(obj), explicits: explicitInfos}
-
- if _, ok := obj.(*types2.Func); ok && info.anyDerived() {
- idx := -1
- for i, prev := range w.dict.funcs {
- if prev.equals(info) {
- idx = i
- }
- }
- if idx < 0 {
- idx = len(w.dict.funcs)
- w.dict.funcs = append(w.dict.funcs, info)
- }
-
- // TODO(mdempsky): Push up into expr; this shouldn't appear
- // outside of expression context.
- w.Sync(pkgbits.SyncObject)
- w.Bool(true)
- w.Len(idx)
- return
- }
+ w.objInfo(w.p.objInstIdx(obj, explicits, w.dict))
+}
+// objInfo writes a use of the given encoded object into the
+// bitstream.
+func (w *writer) objInfo(info objInfo) {
w.Sync(pkgbits.SyncObject)
- w.Bool(false)
+ w.Bool(false) // TODO(mdempsky): Remove; was derived func inst.
w.Reloc(pkgbits.RelocObj, info.idx)
w.Len(len(info.explicits))
}
}
+// objInstIdx returns the indices for an object and a corresponding
+// list of type arguments used to instantiate it, adding them to the
+// export data as needed.
+func (pw *pkgWriter) objInstIdx(obj types2.Object, explicits *types2.TypeList, dict *writerDict) objInfo {
+ explicitInfos := make([]typeInfo, explicits.Len())
+ for i := range explicitInfos {
+ explicitInfos[i] = pw.typIdx(explicits.At(i), dict)
+ }
+ return objInfo{idx: pw.objIdx(obj), explicits: explicitInfos}
+}
+
// objIdx returns the index for the given Object, adding it to the
// export data as needed.
func (pw *pkgWriter) objIdx(obj types2.Object) pkgbits.Index {
}
if obj != nil {
+ if targs.Len() != 0 {
+ obj := obj.(*types2.Func)
+ info := w.p.objInstIdx(obj, targs, w.dict)
+
+ w.Code(exprFuncInst)
+ if w.Bool(info.anyDerived()) {
+ w.Len(w.dict.funcIdx(info))
+ return
+ }
+ w.objInfo(info)
+ return
+ }
+
if isGlobal(obj) {
w.Code(exprGlobal)
- w.obj(obj, targs)
+ w.obj(obj, nil)
return
}
obj := obj.(*types2.Var)
assert(!obj.IsField())
- assert(targs.Len() == 0)
w.Code(exprLocal)
w.useLocal(expr.Pos(), obj)
return types2.CoreType(typ).(*types2.Slice).Elem()
}
+// funcIdx returns the index of a given encoded function instantiation
+// within the dictionary, adding it if not already present.
+func (dict *writerDict) funcIdx(newInfo objInfo) int {
+ for idx, oldInfo := range dict.funcs {
+ if oldInfo.equals(newInfo) {
+ return idx
+ }
+ }
+
+ idx := len(dict.funcs)
+ dict.funcs = append(dict.funcs, newInfo)
+ return idx
+}
+
func (w *writer) optExpr(expr syntax.Expr) {
if w.Bool(expr != nil) {
w.expr(expr)