Source file src/cmd/compile/internal/noder/object.go

     1  // Copyright 2021 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package noder
     6  
     7  import (
     8  	"cmd/compile/internal/base"
     9  	"cmd/compile/internal/ir"
    10  	"cmd/compile/internal/syntax"
    11  	"cmd/compile/internal/typecheck"
    12  	"cmd/compile/internal/types"
    13  	"cmd/compile/internal/types2"
    14  	"cmd/internal/src"
    15  )
    16  
    17  func (g *irgen) def(name *syntax.Name) (*ir.Name, types2.Object) {
    18  	obj, ok := g.info.Defs[name]
    19  	if !ok {
    20  		base.FatalfAt(g.pos(name), "unknown name %v", name)
    21  	}
    22  	return g.obj(obj), obj
    23  }
    24  
    25  // use returns the Name or InstExpr node associated with the use of name,
    26  // possibly instantiated by type arguments. The returned node will have
    27  // the correct type and be marked as typechecked.
    28  func (g *irgen) use(name *syntax.Name) ir.Node {
    29  	obj2, ok := g.info.Uses[name]
    30  	if !ok {
    31  		base.FatalfAt(g.pos(name), "unknown name %v", name)
    32  	}
    33  	obj := ir.CaptureName(g.pos(name), ir.CurFunc, g.obj(obj2))
    34  	if obj.Defn != nil && obj.Defn.Op() == ir.ONAME {
    35  		// If CaptureName created a closure variable, then transfer the
    36  		// type of the captured name to the new closure variable.
    37  		obj.SetTypecheck(1)
    38  		obj.SetType(obj.Defn.Type())
    39  	}
    40  
    41  	if obj.Class == ir.PFUNC {
    42  		if inst, ok := g.info.Instances[name]; ok {
    43  			// This is the case where inferring types required the
    44  			// types of the function arguments.
    45  			targs := make([]ir.Node, inst.TypeArgs.Len())
    46  			for i := range targs {
    47  				targs[i] = ir.TypeNode(g.typ(inst.TypeArgs.At(i)))
    48  			}
    49  			typ := g.substType(obj.Type(), obj.Type().TParams(), targs)
    50  			return typed(typ, ir.NewInstExpr(g.pos(name), ir.OFUNCINST, obj, targs))
    51  		}
    52  	}
    53  
    54  	return obj
    55  }
    56  
    57  // obj returns the Name that represents the given object. If no such Name exists
    58  // yet, it will be implicitly created. The returned node will have the correct
    59  // type and be marked as typechecked.
    60  //
    61  // For objects declared at function scope, ir.CurFunc must already be
    62  // set to the respective function when the Name is created.
    63  func (g *irgen) obj(obj types2.Object) *ir.Name {
    64  	// For imported objects, we use iimport directly instead of mapping
    65  	// the types2 representation.
    66  	if obj.Pkg() != g.self {
    67  		if sig, ok := obj.Type().(*types2.Signature); ok && sig.Recv() != nil {
    68  			// We can't import a method by name - must import the type
    69  			// and access the method from it.
    70  			base.FatalfAt(g.pos(obj), "tried to import a method directly")
    71  		}
    72  		sym := g.sym(obj)
    73  		if sym.Def != nil {
    74  			return sym.Def.(*ir.Name)
    75  		}
    76  		n := typecheck.Resolve(ir.NewIdent(src.NoXPos, sym))
    77  		if n, ok := n.(*ir.Name); ok {
    78  			n.SetTypecheck(1)
    79  			return n
    80  		}
    81  		base.FatalfAt(g.pos(obj), "failed to resolve %v", obj)
    82  	}
    83  
    84  	if name, ok := g.objs[obj]; ok {
    85  		return name // previously mapped
    86  	}
    87  
    88  	var name *ir.Name
    89  	pos := g.pos(obj)
    90  
    91  	class := typecheck.DeclContext
    92  	if obj.Parent() == g.self.Scope() {
    93  		class = ir.PEXTERN // forward reference to package-block declaration
    94  	}
    95  
    96  	// "You are in a maze of twisting little passages, all different."
    97  	switch obj := obj.(type) {
    98  	case *types2.Const:
    99  		name = g.objCommon(pos, ir.OLITERAL, g.sym(obj), class, g.typ(obj.Type()))
   100  
   101  	case *types2.Func:
   102  		sig := obj.Type().(*types2.Signature)
   103  		var sym *types.Sym
   104  		var typ *types.Type
   105  		if recv := sig.Recv(); recv == nil {
   106  			if obj.Name() == "init" {
   107  				sym = renameinit()
   108  			} else {
   109  				sym = g.sym(obj)
   110  			}
   111  			typ = g.typ(sig)
   112  		} else {
   113  			sym = g.selector(obj)
   114  			if !sym.IsBlank() {
   115  				sym = ir.MethodSym(g.typ(recv.Type()), sym)
   116  			}
   117  			typ = g.signature(g.param(recv), sig)
   118  		}
   119  		name = g.objCommon(pos, ir.ONAME, sym, ir.PFUNC, typ)
   120  
   121  	case *types2.TypeName:
   122  		if obj.IsAlias() {
   123  			name = g.objCommon(pos, ir.OTYPE, g.sym(obj), class, g.typ(obj.Type()))
   124  			name.SetAlias(true)
   125  		} else {
   126  			name = ir.NewDeclNameAt(pos, ir.OTYPE, g.sym(obj))
   127  			g.objFinish(name, class, types.NewNamed(name))
   128  		}
   129  
   130  	case *types2.Var:
   131  		sym := g.sym(obj)
   132  		if class == ir.PPARAMOUT && (sym == nil || sym.IsBlank()) {
   133  			// Backend needs names for result parameters,
   134  			// even if they're anonymous or blank.
   135  			nresults := 0
   136  			for _, n := range ir.CurFunc.Dcl {
   137  				if n.Class == ir.PPARAMOUT {
   138  					nresults++
   139  				}
   140  			}
   141  			if sym == nil {
   142  				sym = typecheck.LookupNum("~r", nresults) // 'r' for "result"
   143  			} else {
   144  				sym = typecheck.LookupNum("~b", nresults) // 'b' for "blank"
   145  			}
   146  		}
   147  		name = g.objCommon(pos, ir.ONAME, sym, class, g.typ(obj.Type()))
   148  
   149  	default:
   150  		g.unhandled("object", obj)
   151  	}
   152  
   153  	g.objs[obj] = name
   154  	name.SetTypecheck(1)
   155  	return name
   156  }
   157  
   158  func (g *irgen) objCommon(pos src.XPos, op ir.Op, sym *types.Sym, class ir.Class, typ *types.Type) *ir.Name {
   159  	name := ir.NewDeclNameAt(pos, op, sym)
   160  	g.objFinish(name, class, typ)
   161  	return name
   162  }
   163  
   164  func (g *irgen) objFinish(name *ir.Name, class ir.Class, typ *types.Type) {
   165  	sym := name.Sym()
   166  
   167  	name.SetType(typ)
   168  	name.Class = class
   169  	if name.Class == ir.PFUNC {
   170  		sym.SetFunc(true)
   171  	}
   172  
   173  	name.SetTypecheck(1)
   174  	name.SetWalkdef(1)
   175  
   176  	if ir.IsBlank(name) {
   177  		return
   178  	}
   179  
   180  	switch class {
   181  	case ir.PEXTERN:
   182  		g.target.Externs = append(g.target.Externs, name)
   183  		fallthrough
   184  	case ir.PFUNC:
   185  		sym.Def = name
   186  		if name.Class == ir.PFUNC && name.Type().Recv() != nil {
   187  			break // methods are exported with their receiver type
   188  		}
   189  		if types.IsExported(sym.Name) {
   190  			// Generic functions can be marked for export here, even
   191  			// though they will not be compiled until instantiated.
   192  			typecheck.Export(name)
   193  		}
   194  		if base.Flag.AsmHdr != "" && !name.Sym().Asm() {
   195  			name.Sym().SetAsm(true)
   196  			g.target.Asms = append(g.target.Asms, name)
   197  		}
   198  
   199  	default:
   200  		// Function-scoped declaration.
   201  		name.Curfn = ir.CurFunc
   202  		if name.Op() == ir.ONAME {
   203  			ir.CurFunc.Dcl = append(ir.CurFunc.Dcl, name)
   204  		}
   205  	}
   206  }
   207  

View as plain text