mirror of https://github.com/golang/go.git
206 lines
5.6 KiB
Go
206 lines
5.6 KiB
Go
// 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)
|
|
}
|
|
}
|
|
}
|