| // 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 ( | |
| "cmd/compile/internal/base" | |
| "cmd/compile/internal/ir" | |
| "cmd/compile/internal/syntax" | |
| "cmd/compile/internal/typecheck" | |
| "cmd/compile/internal/types" | |
| "cmd/compile/internal/types2" | |
| "cmd/internal/src" | |
| ) | |
| func (g *irgen) def(name *syntax.Name) (*ir.Name, types2.Object) { | |
| obj, ok := g.info.Defs[name] | |
| if !ok { | |
| base.FatalfAt(g.pos(name), "unknown name %v", name) | |
| } | |
| return g.obj(obj), obj | |
| } | |
| // use returns the Name or InstExpr node associated with the use of name, | |
| // possibly instantiated by type arguments. The returned node will have | |
| // the correct type and be marked as typechecked. | |
| func (g *irgen) use(name *syntax.Name) ir.Node { | |
| obj2, ok := g.info.Uses[name] | |
| if !ok { | |
| base.FatalfAt(g.pos(name), "unknown name %v", name) | |
| } | |
| obj := ir.CaptureName(g.pos(name), ir.CurFunc, g.obj(obj2)) | |
| if obj.Defn != nil && obj.Defn.Op() == ir.ONAME { | |
| // If CaptureName created a closure variable, then transfer the | |
| // type of the captured name to the new closure variable. | |
| obj.SetTypecheck(1) | |
| obj.SetType(obj.Defn.Type()) | |
| } | |
| if obj.Class == ir.PFUNC { | |
| if inst, ok := g.info.Instances[name]; ok { | |
| // This is the case where inferring types required the | |
| // types of the function arguments. | |
| targs := make([]ir.Node, inst.TypeArgs.Len()) | |
| for i := range targs { | |
| targs[i] = ir.TypeNode(g.typ(inst.TypeArgs.At(i))) | |
| } | |
| typ := g.substType(obj.Type(), obj.Type().TParams(), targs) | |
| return typed(typ, ir.NewInstExpr(g.pos(name), ir.OFUNCINST, obj, targs)) | |
| } | |
| } | |
| return obj | |
| } | |
| // obj returns the Name that represents the given object. If no such Name exists | |
| // yet, it will be implicitly created. The returned node will have the correct | |
| // type and be marked as typechecked. | |
| // | |
| // For objects declared at function scope, ir.CurFunc must already be | |
| // set to the respective function when the Name is created. | |
| func (g *irgen) obj(obj types2.Object) *ir.Name { | |
| // For imported objects, we use iimport directly instead of mapping | |
| // the types2 representation. | |
| if obj.Pkg() != g.self { | |
| if sig, ok := obj.Type().(*types2.Signature); ok && sig.Recv() != nil { | |
| // We can't import a method by name - must import the type | |
| // and access the method from it. | |
| base.FatalfAt(g.pos(obj), "tried to import a method directly") | |
| } | |
| sym := g.sym(obj) | |
| if sym.Def != nil { | |
| return sym.Def.(*ir.Name) | |
| } | |
| n := typecheck.Resolve(ir.NewIdent(src.NoXPos, sym)) | |
| if n, ok := n.(*ir.Name); ok { | |
| n.SetTypecheck(1) | |
| return n | |
| } | |
| base.FatalfAt(g.pos(obj), "failed to resolve %v", obj) | |
| } | |
| if name, ok := g.objs[obj]; ok { | |
| return name // previously mapped | |
| } | |
| var name *ir.Name | |
| pos := g.pos(obj) | |
| class := typecheck.DeclContext | |
| if obj.Parent() == g.self.Scope() { | |
| class = ir.PEXTERN // forward reference to package-block declaration | |
| } | |
| // "You are in a maze of twisting little passages, all different." | |
| switch obj := obj.(type) { | |
| case *types2.Const: | |
| name = g.objCommon(pos, ir.OLITERAL, g.sym(obj), class, g.typ(obj.Type())) | |
| case *types2.Func: | |
| sig := obj.Type().(*types2.Signature) | |
| var sym *types.Sym | |
| var typ *types.Type | |
| if recv := sig.Recv(); recv == nil { | |
| if obj.Name() == "init" { | |
| sym = renameinit() | |
| } else { | |
| sym = g.sym(obj) | |
| } | |
| typ = g.typ(sig) | |
| } else { | |
| sym = g.selector(obj) | |
| if !sym.IsBlank() { | |
| sym = ir.MethodSym(g.typ(recv.Type()), sym) | |
| } | |
| typ = g.signature(g.param(recv), sig) | |
| } | |
| name = g.objCommon(pos, ir.ONAME, sym, ir.PFUNC, typ) | |
| case *types2.TypeName: | |
| if obj.IsAlias() { | |
| name = g.objCommon(pos, ir.OTYPE, g.sym(obj), class, g.typ(obj.Type())) | |
| name.SetAlias(true) | |
| } else { | |
| name = ir.NewDeclNameAt(pos, ir.OTYPE, g.sym(obj)) | |
| g.objFinish(name, class, types.NewNamed(name)) | |
| } | |
| case *types2.Var: | |
| sym := g.sym(obj) | |
| if class == ir.PPARAMOUT && (sym == nil || sym.IsBlank()) { | |
| // Backend needs names for result parameters, | |
| // even if they're anonymous or blank. | |
| nresults := 0 | |
| for _, n := range ir.CurFunc.Dcl { | |
| if n.Class == ir.PPARAMOUT { | |
| nresults++ | |
| } | |
| } | |
| if sym == nil { | |
| sym = typecheck.LookupNum("~r", nresults) // 'r' for "result" | |
| } else { | |
| sym = typecheck.LookupNum("~b", nresults) // 'b' for "blank" | |
| } | |
| } | |
| name = g.objCommon(pos, ir.ONAME, sym, class, g.typ(obj.Type())) | |
| default: | |
| g.unhandled("object", obj) | |
| } | |
| g.objs[obj] = name | |
| name.SetTypecheck(1) | |
| return name | |
| } | |
| func (g *irgen) objCommon(pos src.XPos, op ir.Op, sym *types.Sym, class ir.Class, typ *types.Type) *ir.Name { | |
| name := ir.NewDeclNameAt(pos, op, sym) | |
| g.objFinish(name, class, typ) | |
| return name | |
| } | |
| func (g *irgen) objFinish(name *ir.Name, class ir.Class, typ *types.Type) { | |
| sym := name.Sym() | |
| name.SetType(typ) | |
| name.Class = class | |
| if name.Class == ir.PFUNC { | |
| sym.SetFunc(true) | |
| } | |
| name.SetTypecheck(1) | |
| if ir.IsBlank(name) { | |
| return | |
| } | |
| switch class { | |
| case ir.PEXTERN: | |
| g.target.Externs = append(g.target.Externs, name) | |
| fallthrough | |
| case ir.PFUNC: | |
| sym.Def = name | |
| if name.Class == ir.PFUNC && name.Type().Recv() != nil { | |
| break // methods are exported with their receiver type | |
| } | |
| if types.IsExported(sym.Name) { | |
| // Generic functions can be marked for export here, even | |
| // though they will not be compiled until instantiated. | |
| typecheck.Export(name) | |
| } | |
| if base.Flag.AsmHdr != "" && !name.Sym().Asm() { | |
| name.Sym().SetAsm(true) | |
| g.target.Asms = append(g.target.Asms, name) | |
| } | |
| default: | |
| // Function-scoped declaration. | |
| name.Curfn = ir.CurFunc | |
| if name.Op() == ir.ONAME { | |
| ir.CurFunc.Dcl = append(ir.CurFunc.Dcl, name) | |
| } | |
| } | |
| } |