w.string(s.Name)
}
+func (w *exportWriter) typ(t *types.Type) {
+ w.data.uint64(w.p.typOff(t))
+}
+
+// The "exotic" functions in this section encode a wider range of
+// items than the standard encoding functions above. These include
+// types that do not appear in declarations, only in code, such as
+// method types. These methods need to be separate from the standard
+// encoding functions because we don't want to modify the encoding
+// generated by the standard functions (because that exported
+// information is read by tools besides the compiler).
+
+// exoticType exports a type to the writer.
+func (w *exportWriter) exoticType(t *types.Type) {
+ switch {
+ case t == nil:
+ // Calls-as-statements have no type.
+ w.data.uint64(exoticTypeNil)
+ case t.IsStruct() && t.StructType().Funarg != types.FunargNone:
+ // These are weird structs for representing tuples of types returned
+ // by multi-return functions.
+ // They don't fit the standard struct type mold. For instance,
+ // they don't have any package info.
+ w.data.uint64(exoticTypeTuple)
+ w.uint64(uint64(t.StructType().Funarg))
+ w.uint64(uint64(t.NumFields()))
+ for _, f := range t.FieldSlice() {
+ w.pos(f.Pos)
+ s := f.Sym
+ if s == nil {
+ w.uint64(0)
+ } else if s.Pkg == nil {
+ w.uint64(exoticTypeSymNoPkg)
+ w.string(s.Name)
+ } else {
+ w.uint64(exoticTypeSymWithPkg)
+ w.pkg(s.Pkg)
+ w.string(s.Name)
+ }
+ w.typ(f.Type)
+ if f.Embedded != 0 || f.Note != "" {
+ panic("extra info in funarg struct field")
+ }
+ }
+ case t.Kind() == types.TFUNC && t.Recv() != nil:
+ w.data.uint64(exoticTypeRecv)
+ // interface method types have a fake receiver type.
+ isFakeRecv := t.Recv().Type == types.FakeRecvType()
+ w.bool(isFakeRecv)
+ if !isFakeRecv {
+ w.exoticParam(t.Recv())
+ }
+ w.exoticSignature(t)
+
+ default:
+ // A regular type.
+ w.data.uint64(exoticTypeRegular)
+ w.typ(t)
+ }
+}
+
+const (
+ exoticTypeNil = iota
+ exoticTypeTuple
+ exoticTypeRecv
+ exoticTypeRegular
+)
+const (
+ exoticTypeSymNil = iota
+ exoticTypeSymNoPkg
+ exoticTypeSymWithPkg
+)
+
// Export a selector, but one whose package may not match
// the package being compiled. This is a separate function
// because the standard selector() serialization format is fixed
}
}
-func (w *exportWriter) typ(t *types.Type) {
- w.data.uint64(w.p.typOff(t))
+func (w *exportWriter) exoticSignature(t *types.Type) {
+ hasPkg := t.Pkg() != nil
+ w.bool(hasPkg)
+ if hasPkg {
+ w.pkg(t.Pkg())
+ }
+ w.exoticParamList(t.Params().FieldSlice())
+ w.exoticParamList(t.Results().FieldSlice())
+}
+
+func (w *exportWriter) exoticParamList(fs []*types.Field) {
+ w.uint64(uint64(len(fs)))
+ for _, f := range fs {
+ w.exoticParam(f)
+ }
+
+}
+func (w *exportWriter) exoticParam(f *types.Field) {
+ w.pos(f.Pos)
+ w.exoticSym(f.Sym)
+ w.uint64(uint64(f.Offset))
+ w.exoticType(f.Type)
+ w.bool(f.IsDDD())
+}
+func (w *exportWriter) exoticSym(s *types.Sym) {
+ if s == nil {
+ w.string("")
+ return
+ }
+ if s.Name == "" {
+ base.Fatalf("empty symbol name")
+ }
+ w.string(s.Name)
+ if !types.IsExported(s.Name) {
+ w.pkg(s.Pkg)
+ }
}
func (p *iexporter) newWriter() *exportWriter {
}
func (w *exportWriter) funcBody(fn *ir.Func) {
+ //fmt.Printf("Exporting %s\n", fn.Nname.Sym().Name)
w.writeNames(fn.Inl.Dcl)
w.stmtList(fn.Inl.Body)
case ir.OAS2, ir.OAS2DOTTYPE, ir.OAS2FUNC, ir.OAS2MAPR, ir.OAS2RECV:
n := n.(*ir.AssignListStmt)
- w.op(ir.OAS2)
+ if go117ExportTypes {
+ w.op(n.Op())
+ } else {
+ w.op(ir.OAS2)
+ }
w.pos(n.Pos())
w.exprList(n.Lhs)
w.exprList(n.Rhs)
w.exprList(n.Results)
// case ORETJMP:
- // unreachable - generated by compiler for trampolin routines
+ // unreachable - generated by compiler for trampoline routines
case ir.OGO, ir.ODEFER:
n := n.(*ir.GoDeferStmt)
if (n.Class == ir.PEXTERN || n.Class == ir.PFUNC) && !ir.IsBlank(n) {
w.op(ir.ONONAME)
w.qualifiedIdent(n)
+ if go117ExportTypes {
+ w.typ(n.Type())
+ }
break
}
// Function scope name.
+ // We don't need a type here, as the type will be provided at the
+ // declaration of n.
w.op(ir.ONAME)
w.localName(n)
case ir.OPTRLIT:
n := n.(*ir.AddrExpr)
- w.op(ir.OADDR)
+ if go117ExportTypes {
+ w.op(ir.OPTRLIT)
+ } else {
+ w.op(ir.OADDR)
+ }
w.pos(n.Pos())
w.expr(n.X)
+ if go117ExportTypes {
+ w.typ(n.Type())
+ }
case ir.OSTRUCTLIT:
n := n.(*ir.CompLitExpr)
case ir.OARRAYLIT, ir.OSLICELIT, ir.OMAPLIT:
n := n.(*ir.CompLitExpr)
- w.op(ir.OCOMPLIT)
+ if go117ExportTypes {
+ w.op(n.Op())
+ } else {
+ w.op(ir.OCOMPLIT)
+ }
w.pos(n.Pos())
w.typ(n.Type())
w.exprList(n.List)
-
+ if go117ExportTypes && n.Op() == ir.OSLICELIT {
+ w.uint64(uint64(n.Len))
+ }
case ir.OKEY:
n := n.(*ir.KeyExpr)
w.op(ir.OKEY)
case ir.OXDOT, ir.ODOT, ir.ODOTPTR, ir.ODOTINTER, ir.ODOTMETH, ir.OCALLPART, ir.OMETHEXPR:
n := n.(*ir.SelectorExpr)
- w.op(ir.OXDOT)
+ if go117ExportTypes {
+ if n.Op() == ir.OXDOT {
+ base.Fatalf("shouldn't encounter XDOT in new exporter")
+ }
+ w.op(n.Op())
+ } else {
+ w.op(ir.OXDOT)
+ }
w.pos(n.Pos())
w.expr(n.X)
w.exoticSelector(n.Sel)
+ if go117ExportTypes {
+ w.exoticType(n.Type())
+ if n.Op() == ir.ODOT || n.Op() == ir.ODOTPTR || n.Op() == ir.ODOTINTER || n.Op() == ir.OMETHEXPR {
+ w.exoticParam(n.Selection)
+ if n.Op() == ir.OMETHEXPR {
+ name := ir.MethodExprName(n)
+ w.bool(name != nil)
+ if name != nil {
+ w.exoticType(name.Type())
+ }
+ }
+ }
+ // n.Selection is not required for ODOTMETH and OCALLPART. It will
+ // be reconstructed during import.
+ }
case ir.ODOTTYPE, ir.ODOTTYPE2:
n := n.(*ir.TypeAssertExpr)
- w.op(ir.ODOTTYPE)
+ if go117ExportTypes {
+ w.op(n.Op())
+ } else {
+ w.op(ir.ODOTTYPE)
+ }
w.pos(n.Pos())
w.expr(n.X)
w.typ(n.Type())
case ir.OINDEX, ir.OINDEXMAP:
n := n.(*ir.IndexExpr)
- w.op(ir.OINDEX)
+ if go117ExportTypes {
+ w.op(n.Op())
+ } else {
+ w.op(ir.OINDEX)
+ }
w.pos(n.Pos())
w.expr(n.X)
w.expr(n.Index)
+ if go117ExportTypes {
+ w.typ(n.Type())
+ if n.Op() == ir.OINDEXMAP {
+ w.bool(n.Assigned)
+ }
+ }
case ir.OSLICE, ir.OSLICESTR, ir.OSLICEARR:
n := n.(*ir.SliceExpr)
- w.op(ir.OSLICE)
+ if go117ExportTypes {
+ w.op(n.Op())
+ } else {
+ w.op(ir.OSLICE)
+ }
w.pos(n.Pos())
w.expr(n.X)
w.exprsOrNil(n.Low, n.High)
+ if go117ExportTypes {
+ w.typ(n.Type())
+ }
case ir.OSLICE3, ir.OSLICE3ARR:
n := n.(*ir.SliceExpr)
- w.op(ir.OSLICE3)
+ if go117ExportTypes {
+ w.op(n.Op())
+ } else {
+ w.op(ir.OSLICE3)
+ }
w.pos(n.Pos())
w.expr(n.X)
w.exprsOrNil(n.Low, n.High)
w.expr(n.Max)
+ if go117ExportTypes {
+ w.typ(n.Type())
+ }
case ir.OCOPY, ir.OCOMPLEX:
// treated like other builtin calls (see e.g., OREAL)
w.pos(n.Pos())
w.expr(n.X)
w.expr(n.Y)
- w.op(ir.OEND)
+ if go117ExportTypes {
+ w.typ(n.Type())
+ } else {
+ w.op(ir.OEND)
+ }
case ir.OCONV, ir.OCONVIFACE, ir.OCONVNOP, ir.OBYTES2STR, ir.ORUNES2STR, ir.OSTR2BYTES, ir.OSTR2RUNES, ir.ORUNESTR:
n := n.(*ir.ConvExpr)
- w.op(ir.OCONV)
+ if go117ExportTypes {
+ w.op(n.Op())
+ } else {
+ w.op(ir.OCONV)
+ }
w.pos(n.Pos())
w.typ(n.Type())
w.expr(n.X)
w.op(n.Op())
w.pos(n.Pos())
w.expr(n.X)
- w.op(ir.OEND)
+ if go117ExportTypes {
+ if n.Op() != ir.OPANIC {
+ w.typ(n.Type())
+ }
+ } else {
+ w.op(ir.OEND)
+ }
case ir.OAPPEND, ir.ODELETE, ir.ORECOVER, ir.OPRINT, ir.OPRINTN:
n := n.(*ir.CallExpr)
} else if n.IsDDD {
base.Fatalf("exporter: unexpected '...' with %v call", n.Op())
}
+ if go117ExportTypes {
+ if n.Op() != ir.ODELETE && n.Op() != ir.OPRINT && n.Op() != ir.OPRINTN {
+ w.typ(n.Type())
+ }
+ }
case ir.OCALL, ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER, ir.OGETG:
n := n.(*ir.CallExpr)
- w.op(ir.OCALL)
+ if go117ExportTypes {
+ w.op(n.Op())
+ } else {
+ w.op(ir.OCALL)
+ }
w.pos(n.Pos())
w.stmtList(n.Init())
w.expr(n.X)
w.exprList(n.Args)
w.bool(n.IsDDD)
+ if go117ExportTypes {
+ w.exoticType(n.Type())
+ w.uint64(uint64(n.Use))
+ }
case ir.OMAKEMAP, ir.OMAKECHAN, ir.OMAKESLICE:
n := n.(*ir.MakeExpr)
w.expr(n.Cap)
w.op(ir.OEND)
case n.Len != nil && (n.Op() == ir.OMAKESLICE || !n.Len.Type().IsUntyped()):
+ // Note: the extra conditional exists because make(T) for
+ // T a map or chan type, gets an untyped zero added as
+ // an argument. Don't serialize that argument here.
+ w.expr(n.Len)
+ w.op(ir.OEND)
+ case n.Len != nil && go117ExportTypes:
w.expr(n.Len)
w.op(ir.OEND)
}
w.op(n.Op())
w.pos(n.Pos())
w.expr(n.X)
+ if go117ExportTypes {
+ w.typ(n.Type())
+ }
case ir.OADDR:
n := n.(*ir.AddrExpr)
w.op(n.Op())
w.pos(n.Pos())
w.expr(n.X)
+ if go117ExportTypes {
+ w.typ(n.Type())
+ }
case ir.ODEREF:
n := n.(*ir.StarExpr)
w.op(n.Op())
w.pos(n.Pos())
w.expr(n.X)
+ if go117ExportTypes {
+ w.typ(n.Type())
+ }
case ir.OSEND:
n := n.(*ir.SendStmt)
w.pos(n.Pos())
w.expr(n.X)
w.expr(n.Y)
+ if go117ExportTypes {
+ w.typ(n.Type())
+ }
case ir.OANDAND, ir.OOROR:
n := n.(*ir.LogicalExpr)
w.pos(n.Pos())
w.expr(n.X)
w.expr(n.Y)
+ if go117ExportTypes {
+ w.typ(n.Type())
+ }
case ir.OADDSTR:
n := n.(*ir.AddStringExpr)
w.op(ir.OADDSTR)
w.pos(n.Pos())
w.exprList(n.List)
+ if go117ExportTypes {
+ w.typ(n.Type())
+ }
case ir.ODCLCONST:
// if exporting, DCLCONST should just be removed as its usage
w.pos(n.Pos())
w.selector(n.Field)
w.expr(n.Value)
+ if go117ExportTypes {
+ w.uint64(uint64(n.Offset))
+ }
}
}
n := binary.PutUvarint(buf[:], x)
w.Write(buf[:n])
}
+
+// If go117ExportTypes is true, then we write type information when
+// exporting function bodies, so those function bodies don't need to
+// be re-typechecked on import.
+// This flag adds some other info to the serialized stream as well
+// which was previously recomputed during typechecking, like
+// specializing opcodes (e.g. OXDOT to ODOTPTR) and ancillary
+// information (e.g. length field for OSLICELIT).
+const go117ExportTypes = true
+const Go117ExportTypes = go117ExportTypes
func (r *importReader) localIdent() *types.Sym { return r.ident(false) }
func (r *importReader) selector() *types.Sym { return r.ident(true) }
-func (r *importReader) exoticSelector() *types.Sym {
- name := r.string()
- if name == "" {
- return nil
- }
- pkg := r.currPkg
- if types.IsExported(name) {
- pkg = types.LocalPkg
- }
- if r.uint64() != 0 {
- pkg = r.pkg()
- }
- return pkg.Lookup(name)
-}
-
func (r *importReader) qualifiedIdent() *ir.Ident {
name := r.string()
pkg := r.pkg()
return r.p.typAt(r.uint64())
}
+func (r *importReader) exoticType() *types.Type {
+ switch r.uint64() {
+ case exoticTypeNil:
+ return nil
+ case exoticTypeTuple:
+ funarg := types.Funarg(r.uint64())
+ n := r.uint64()
+ fs := make([]*types.Field, n)
+ for i := range fs {
+ pos := r.pos()
+ var sym *types.Sym
+ switch r.uint64() {
+ case exoticTypeSymNil:
+ sym = nil
+ case exoticTypeSymNoPkg:
+ sym = types.NoPkg.Lookup(r.string())
+ case exoticTypeSymWithPkg:
+ pkg := r.pkg()
+ sym = pkg.Lookup(r.string())
+ default:
+ base.Fatalf("unknown symbol kind")
+ }
+ typ := r.typ()
+ f := types.NewField(pos, sym, typ)
+ fs[i] = f
+ }
+ t := types.NewStruct(types.NoPkg, fs)
+ t.StructType().Funarg = funarg
+ return t
+ case exoticTypeRecv:
+ var rcvr *types.Field
+ if r.bool() { // isFakeRecv
+ rcvr = fakeRecvField()
+ } else {
+ rcvr = r.exoticParam()
+ }
+ return r.exoticSignature(rcvr)
+ case exoticTypeRegular:
+ return r.typ()
+ default:
+ base.Fatalf("bad kind of call type")
+ return nil
+ }
+}
+
+func (r *importReader) exoticSelector() *types.Sym {
+ name := r.string()
+ if name == "" {
+ return nil
+ }
+ pkg := r.currPkg
+ if types.IsExported(name) {
+ pkg = types.LocalPkg
+ }
+ if r.uint64() != 0 {
+ pkg = r.pkg()
+ }
+ return pkg.Lookup(name)
+}
+
+func (r *importReader) exoticSignature(recv *types.Field) *types.Type {
+ var pkg *types.Pkg
+ if r.bool() { // hasPkg
+ pkg = r.pkg()
+ }
+ params := r.exoticParamList()
+ results := r.exoticParamList()
+ return types.NewSignature(pkg, recv, nil, params, results)
+}
+
+func (r *importReader) exoticParamList() []*types.Field {
+ n := r.uint64()
+ fs := make([]*types.Field, n)
+ for i := range fs {
+ fs[i] = r.exoticParam()
+ }
+ return fs
+}
+
+func (r *importReader) exoticParam() *types.Field {
+ pos := r.pos()
+ sym := r.exoticSym()
+ off := r.uint64()
+ typ := r.exoticType()
+ ddd := r.bool()
+ f := types.NewField(pos, sym, typ)
+ f.Offset = int64(off)
+ if sym != nil {
+ f.Nname = ir.NewNameAt(pos, sym)
+ }
+ f.SetIsDDD(ddd)
+ return f
+}
+
+func (r *importReader) exoticSym() *types.Sym {
+ name := r.string()
+ if name == "" {
+ return nil
+ }
+ var pkg *types.Pkg
+ if types.IsExported(name) {
+ pkg = types.LocalPkg
+ } else {
+ pkg = r.pkg()
+ }
+ return pkg.Lookup(name)
+}
+
func (p *iimporter) typAt(off uint64) *types.Type {
t, ok := p.typCache[off]
if !ok {
// functions).
body = []ir.Node{}
}
+ if go117ExportTypes {
+ ir.VisitList(body, func(n ir.Node) {
+ n.SetTypecheck(1)
+ })
+ }
fn.Inl.Body = body
r.curfn = outerfn
// TODO(gri) split into expr and stmt
func (r *importReader) node() ir.Node {
- switch op := r.op(); op {
+ op := r.op()
+ switch op {
// expressions
// case OPAREN:
// unreachable - unpacked by exporter
return n
case ir.ONONAME:
- return r.qualifiedIdent()
+ n := r.qualifiedIdent()
+ if go117ExportTypes {
+ n2 := Resolve(n)
+ typ := r.typ()
+ if n2.Type() == nil {
+ n2.SetType(typ)
+ }
+ return n2
+ }
+ return n
case ir.ONAME:
return r.localName()
return clo
- // case OPTRLIT:
- // unreachable - mapped to case OADDR below by exporter
-
case ir.OSTRUCTLIT:
+ if go117ExportTypes {
+ pos := r.pos()
+ typ := r.typ()
+ list := r.fieldList()
+ n := ir.NewCompLitExpr(pos, ir.OSTRUCTLIT, nil, list)
+ n.SetType(typ)
+ return n
+ }
return ir.NewCompLitExpr(r.pos(), ir.OCOMPLIT, ir.TypeNode(r.typ()), r.fieldList())
- // case OARRAYLIT, OSLICELIT, OMAPLIT:
- // unreachable - mapped to case OCOMPLIT below by exporter
-
case ir.OCOMPLIT:
return ir.NewCompLitExpr(r.pos(), ir.OCOMPLIT, ir.TypeNode(r.typ()), r.exprList())
+ case ir.OARRAYLIT, ir.OSLICELIT, ir.OMAPLIT:
+ if !go117ExportTypes {
+ // unreachable - mapped to OCOMPLIT by exporter
+ goto error
+ }
+ pos := r.pos()
+ typ := r.typ()
+ list := r.exprList()
+ n := ir.NewCompLitExpr(pos, op, ir.TypeNode(typ), list)
+ n.SetType(typ)
+ if op == ir.OSLICELIT {
+ n.Len = int64(r.uint64())
+ }
+ return n
+
case ir.OKEY:
return ir.NewKeyExpr(r.pos(), r.expr(), r.expr())
// case OSTRUCTKEY:
// unreachable - handled in case OSTRUCTLIT by elemList
- // case OCALLPART:
- // unreachable - mapped to case OXDOT below by exporter
-
- // case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH:
- // unreachable - mapped to case OXDOT below by exporter
-
case ir.OXDOT:
// see parser.new_dotname
+ if go117ExportTypes {
+ base.Fatalf("shouldn't encounter XDOT in new importer")
+ }
return ir.NewSelectorExpr(r.pos(), ir.OXDOT, r.expr(), r.exoticSelector())
- // case ODOTTYPE, ODOTTYPE2:
- // unreachable - mapped to case ODOTTYPE below by exporter
+ case ir.ODOT, ir.ODOTPTR, ir.ODOTINTER, ir.ODOTMETH, ir.OCALLPART, ir.OMETHEXPR:
+ if !go117ExportTypes {
+ // unreachable - mapped to case OXDOT by exporter
+ goto error
+ }
+ pos := r.pos()
+ expr := r.expr()
+ sel := r.exoticSelector()
+ n := ir.NewSelectorExpr(pos, ir.OXDOT, expr, sel)
+ n.SetOp(op)
+ n.SetType(r.exoticType())
+ switch op {
+ case ir.ODOT, ir.ODOTPTR, ir.ODOTINTER, ir.OMETHEXPR:
+ n.Selection = r.exoticParam()
+ if op == ir.OMETHEXPR {
+ if r.bool() { // has name
+ ir.MethodExprName(n).SetType(r.exoticType())
+ }
+ }
+ case ir.ODOTMETH, ir.OCALLPART:
+ // These require a Lookup to link to the correct declaration.
+ rcvrType := expr.Type()
+ typ := n.Type()
+ n.Selection = Lookdot(n, rcvrType, 1)
+ if op == ir.OCALLPART {
+ // Lookdot clobbers the opcode and type, undo that.
+ n.SetOp(op)
+ n.SetType(typ)
+ }
+ }
+ return n
- case ir.ODOTTYPE:
+ case ir.ODOTTYPE, ir.ODOTTYPE2:
n := ir.NewTypeAssertExpr(r.pos(), r.expr(), nil)
n.SetType(r.typ())
+ if go117ExportTypes {
+ n.SetOp(op)
+ }
return n
- // case OINDEX, OINDEXMAP, OSLICE, OSLICESTR, OSLICEARR, OSLICE3, OSLICE3ARR:
- // unreachable - mapped to cases below by exporter
-
- case ir.OINDEX:
- return ir.NewIndexExpr(r.pos(), r.expr(), r.expr())
+ case ir.OINDEX, ir.OINDEXMAP:
+ n := ir.NewIndexExpr(r.pos(), r.expr(), r.expr())
+ if go117ExportTypes {
+ n.SetOp(op)
+ n.SetType(r.typ())
+ if op == ir.OINDEXMAP {
+ n.Assigned = r.bool()
+ }
+ }
+ return n
- case ir.OSLICE, ir.OSLICE3:
+ case ir.OSLICE, ir.OSLICESTR, ir.OSLICEARR, ir.OSLICE3, ir.OSLICE3ARR:
pos, x := r.pos(), r.expr()
low, high := r.exprsOrNil()
var max ir.Node
if op.IsSlice3() {
max = r.expr()
}
- return ir.NewSliceExpr(pos, op, x, low, high, max)
-
- // case OCONV, OCONVIFACE, OCONVNOP, OBYTES2STR, ORUNES2STR, OSTR2BYTES, OSTR2RUNES, ORUNESTR:
- // unreachable - mapped to OCONV case below by exporter
+ n := ir.NewSliceExpr(pos, op, x, low, high, max)
+ if go117ExportTypes {
+ n.SetType(r.typ())
+ }
+ return n
- case ir.OCONV:
- return ir.NewConvExpr(r.pos(), ir.OCONV, r.typ(), r.expr())
+ case ir.OCONV, ir.OCONVIFACE, ir.OCONVNOP, ir.OBYTES2STR, ir.ORUNES2STR, ir.OSTR2BYTES, ir.OSTR2RUNES, ir.ORUNESTR:
+ if !go117ExportTypes && op != ir.OCONV {
+ // unreachable - mapped to OCONV case by exporter
+ goto error
+ }
+ return ir.NewConvExpr(r.pos(), op, r.typ(), r.expr())
case ir.OCOPY, ir.OCOMPLEX, ir.OREAL, ir.OIMAG, ir.OAPPEND, ir.OCAP, ir.OCLOSE, ir.ODELETE, ir.OLEN, ir.OMAKE, ir.ONEW, ir.OPANIC, ir.ORECOVER, ir.OPRINT, ir.OPRINTN:
+ if go117ExportTypes {
+ switch op {
+ case ir.OCOPY, ir.OCOMPLEX:
+ n := ir.NewBinaryExpr(r.pos(), op, r.expr(), r.expr())
+ n.SetType(r.typ())
+ return n
+ case ir.OREAL, ir.OIMAG, ir.OCAP, ir.OCLOSE, ir.OLEN, ir.ONEW, ir.OPANIC:
+ n := ir.NewUnaryExpr(r.pos(), op, r.expr())
+ if op != ir.OPANIC {
+ n.SetType(r.typ())
+ }
+ return n
+ case ir.OAPPEND, ir.ODELETE, ir.ORECOVER, ir.OPRINT, ir.OPRINTN:
+ n := ir.NewCallExpr(r.pos(), op, nil, r.exprList())
+ if op == ir.OAPPEND {
+ n.IsDDD = r.bool()
+ }
+ if op == ir.OAPPEND || op == ir.ORECOVER {
+ n.SetType(r.typ())
+ }
+ return n
+ }
+ // ir.OMAKE
+ goto error
+ }
n := builtinCall(r.pos(), op)
n.Args = r.exprList()
if op == ir.OAPPEND {
}
return n
- // case OCALLFUNC, OCALLMETH, OCALLINTER, OGETG:
- // unreachable - mapped to OCALL case below by exporter
-
- case ir.OCALL:
+ case ir.OCALL, ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER, ir.OGETG:
pos := r.pos()
init := r.stmtList()
n := ir.NewCallExpr(pos, ir.OCALL, r.expr(), r.exprList())
+ if go117ExportTypes {
+ n.SetOp(op)
+ }
*n.PtrInit() = init
n.IsDDD = r.bool()
+ if go117ExportTypes {
+ n.SetType(r.exoticType())
+ n.Use = ir.CallUse(r.uint64())
+ }
return n
case ir.OMAKEMAP, ir.OMAKECHAN, ir.OMAKESLICE:
+ if go117ExportTypes {
+ pos := r.pos()
+ typ := r.typ()
+ list := r.exprList()
+ var len_, cap_ ir.Node
+ if len(list) > 0 {
+ len_ = list[0]
+ }
+ if len(list) > 1 {
+ cap_ = list[1]
+ }
+ n := ir.NewMakeExpr(pos, op, len_, cap_)
+ n.SetType(typ)
+ return n
+ }
n := builtinCall(r.pos(), ir.OMAKE)
n.Args.Append(ir.TypeNode(r.typ()))
n.Args.Append(r.exprList()...)
// unary expressions
case ir.OPLUS, ir.ONEG, ir.OBITNOT, ir.ONOT, ir.ORECV:
- return ir.NewUnaryExpr(r.pos(), op, r.expr())
+ n := ir.NewUnaryExpr(r.pos(), op, r.expr())
+ if go117ExportTypes {
+ n.SetType(r.typ())
+ }
+ return n
- case ir.OADDR:
- return NodAddrAt(r.pos(), r.expr())
+ case ir.OADDR, ir.OPTRLIT:
+ n := NodAddrAt(r.pos(), r.expr())
+ if go117ExportTypes {
+ n.SetOp(op)
+ n.SetType(r.typ())
+ }
+ return n
case ir.ODEREF:
- return ir.NewStarExpr(r.pos(), r.expr())
+ n := ir.NewStarExpr(r.pos(), r.expr())
+ if go117ExportTypes {
+ n.SetType(r.typ())
+ }
+ return n
// binary expressions
case ir.OADD, ir.OAND, ir.OANDNOT, ir.ODIV, ir.OEQ, ir.OGE, ir.OGT, ir.OLE, ir.OLT,
ir.OLSH, ir.OMOD, ir.OMUL, ir.ONE, ir.OOR, ir.ORSH, ir.OSUB, ir.OXOR:
- return ir.NewBinaryExpr(r.pos(), op, r.expr(), r.expr())
+ n := ir.NewBinaryExpr(r.pos(), op, r.expr(), r.expr())
+ if go117ExportTypes {
+ n.SetType(r.typ())
+ }
+ return n
case ir.OANDAND, ir.OOROR:
- return ir.NewLogicalExpr(r.pos(), op, r.expr(), r.expr())
+ n := ir.NewLogicalExpr(r.pos(), op, r.expr(), r.expr())
+ if go117ExportTypes {
+ n.SetType(r.typ())
+ }
+ return n
case ir.OSEND:
return ir.NewSendStmt(r.pos(), r.expr(), r.expr())
case ir.OADDSTR:
pos := r.pos()
list := r.exprList()
+ if go117ExportTypes {
+ n := ir.NewAddStringExpr(pos, list)
+ n.SetType(r.typ())
+ return n
+ }
x := list[0]
for _, y := range list[1:] {
x = ir.NewBinaryExpr(pos, ir.OADD, x, y)
stmts.Append(ir.NewAssignStmt(n.Pos(), n, nil))
return ir.NewBlockStmt(n.Pos(), stmts)
- // case OAS, OASWB:
- // unreachable - mapped to OAS case below by exporter
+ // case OASWB:
+ // unreachable - never exported
case ir.OAS:
return ir.NewAssignStmt(r.pos(), r.expr(), r.expr())
}
return n
- // case OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV:
- // unreachable - mapped to OAS2 case below by exporter
-
- case ir.OAS2:
- return ir.NewAssignListStmt(r.pos(), ir.OAS2, r.exprList(), r.exprList())
+ case ir.OAS2, ir.OAS2DOTTYPE, ir.OAS2FUNC, ir.OAS2MAPR, ir.OAS2RECV:
+ if !go117ExportTypes && op != ir.OAS2 {
+ // unreachable - mapped to case OAS2 by exporter
+ goto error
+ }
+ return ir.NewAssignListStmt(r.pos(), op, r.exprList(), r.exprList())
case ir.ORETURN:
return ir.NewReturnStmt(r.pos(), r.exprList())
"\t==> please file an issue and assign to gri@", op, int(op))
panic("unreachable") // satisfy compiler
}
+error:
+ base.Fatalf("cannot import %v (%d) node\n"+
+ "\t==> please file an issue and assign to khr@", op, int(op))
+ panic("unreachable") // satisfy compiler
}
func (r *importReader) op() ir.Op {
func (r *importReader) fieldList() []ir.Node {
list := make([]ir.Node, r.uint64())
for i := range list {
- list[i] = ir.NewStructKeyExpr(r.pos(), r.selector(), r.expr())
+ x := ir.NewStructKeyExpr(r.pos(), r.selector(), r.expr())
+ if go117ExportTypes {
+ x.Offset = int64(r.uint64())
+ }
+ list[i] = x
}
return list
}
}
func builtinCall(pos src.XPos, op ir.Op) *ir.CallExpr {
+ if go117ExportTypes {
+ // These should all be encoded as direct ops, not OCALL.
+ base.Fatalf("builtinCall should not be invoked when types are included in inport/export")
+ }
return ir.NewCallExpr(pos, ir.OCALL, ir.NewIdent(base.Pos, types.BuiltinPkg.Lookup(ir.OpNames[op])), nil)
}
y := func(x int) int { // ERROR "can inline main.func11" "func literal does not escape"
return x + 2
}
- y, sink = func() (func(int) int, int) { // ERROR "can inline main.func12"
- return func(x int) int { // ERROR "can inline main.func12"
+ y, sink = func() (func(int) int, int) { // ERROR "func literal does not escape"
+ return func(x int) int { // ERROR "can inline main.func12" "func literal escapes"
return x + 1
}, 42
- }() // ERROR "func literal does not escape" "inlining call to main.func12"
+ }()
if y(40) != 41 {
ppanic("y(40) != 41")
}
{
func() { // ERROR "func literal does not escape"
- y := func(x int) int { // ERROR "func literal does not escape" "can inline main.func13.1"
+ y := func(x int) int { // ERROR "can inline main.func13.1" "func literal does not escape"
return x + 2
}
- y, sink = func() (func(int) int, int) { // ERROR "can inline main.func13.2"
- return func(x int) int { // ERROR "can inline main.func13.2"
+ y, sink = func() (func(int) int, int) { // ERROR "func literal does not escape"
+ return func(x int) int { // ERROR "can inline main.func13.2" "func literal escapes"
return x + 1
}, 42
- }() // ERROR "inlining call to main.func13.2" "func literal does not escape"
+ }()
if y(40) != 41 {
ppanic("y(40) != 41")
}
{
x := 42
- if z := func(y int) int { // ERROR "can inline main.func22"
- return func() int { // ERROR "can inline main.func22.1" "can inline main.func30"
+ if z := func(y int) int { // ERROR "func literal does not escape"
+ return func() int { // ERROR "can inline main.func22.1"
return x + y
}() // ERROR "inlining call to main.func22.1"
- }(1); z != 43 { // ERROR "inlining call to main.func22" "inlining call to main.func30"
+ }(1); z != 43 {
ppanic("z != 43")
}
- if z := func(y int) int { // ERROR "func literal does not escape" "can inline main.func23"
- return func() int { // ERROR "can inline main.func23.1" "can inline main.func31"
+ if z := func(y int) int { // ERROR "func literal does not escape"
+ return func() int { // ERROR "can inline main.func23.1"
return x + y
}() // ERROR "inlining call to main.func23.1"
- }; z(1) != 43 { // ERROR "inlining call to main.func23" "inlining call to main.func31"
+ }; z(1) != 43 {
ppanic("z(1) != 43")
}
}
{
a := 1
- func() { // ERROR "can inline main.func24"
- func() { // ERROR "can inline main.func24" "can inline main.func32"
+ func() { // ERROR "func literal does not escape"
+ func() { // ERROR "can inline main.func24"
a = 2
}() // ERROR "inlining call to main.func24"
- }() // ERROR "inlining call to main.func24" "inlining call to main.func32"
+ }()
if a != 2 {
ppanic("a != 2")
}
a := 2
if r := func(x int) int { // ERROR "func literal does not escape"
b := 3
- return func(y int) int { // ERROR "can inline main.func27.1"
+ return func(y int) int { // ERROR "func literal does not escape"
c := 5
- return func(z int) int { // ERROR "can inline main.func27.1.1" "can inline main.func27.2"
+ return func(z int) int { // ERROR "can inline main.func27.1.1"
return a*x + b*y + c*z
}(10) // ERROR "inlining call to main.func27.1.1"
- }(100) // ERROR "inlining call to main.func27.1" "inlining call to main.func27.2"
+ }(100)
}(1000); r != 2350 {
ppanic("r != 2350")
}
a := 2
if r := func(x int) int { // ERROR "func literal does not escape"
b := 3
- return func(y int) int { // ERROR "can inline main.func28.1"
+ return func(y int) int { // ERROR "func literal does not escape"
c := 5
- func(z int) { // ERROR "can inline main.func28.1.1" "can inline main.func28.2"
+ func(z int) { // ERROR "can inline main.func28.1.1"
a = a * x
b = b * y
c = c * z
}(10) // ERROR "inlining call to main.func28.1.1"
return a + c
- }(100) + b // ERROR "inlining call to main.func28.1" "inlining call to main.func28.2"
+ }(100) + b
}(1000); r != 2350 {
ppanic("r != 2350")
}