Black Lives Matter. Support the Equal Justice Initiative.

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

Documentation: cmd/compile/internal/noder

     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 node associated with the use of name. The returned node
    26  // will have the correct type and be marked as typechecked.
    27  func (g *irgen) use(name *syntax.Name) *ir.Name {
    28  	obj2, ok := g.info.Uses[name]
    29  	if !ok {
    30  		base.FatalfAt(g.pos(name), "unknown name %v", name)
    31  	}
    32  	obj := ir.CaptureName(g.pos(obj2), ir.CurFunc, g.obj(obj2))
    33  	if obj.Defn != nil && obj.Defn.Op() == ir.ONAME {
    34  		// If CaptureName created a closure variable, then transfer the
    35  		// type of the captured name to the new closure variable.
    36  		obj.SetTypecheck(1)
    37  		obj.SetType(obj.Defn.Type())
    38  	}
    39  	return obj
    40  }
    41  
    42  // obj returns the Name that represents the given object. If no such Name exists
    43  // yet, it will be implicitly created. The returned node will have the correct
    44  // type and be marked as typechecked.
    45  //
    46  // For objects declared at function scope, ir.CurFunc must already be
    47  // set to the respective function when the Name is created.
    48  func (g *irgen) obj(obj types2.Object) *ir.Name {
    49  	// For imported objects, we use iimport directly instead of mapping
    50  	// the types2 representation.
    51  	if obj.Pkg() != g.self {
    52  		sym := g.sym(obj)
    53  		if sym.Def != nil {
    54  			return sym.Def.(*ir.Name)
    55  		}
    56  		n := typecheck.Resolve(ir.NewIdent(src.NoXPos, sym))
    57  		if n, ok := n.(*ir.Name); ok {
    58  			n.SetTypecheck(1)
    59  			return n
    60  		}
    61  		base.FatalfAt(g.pos(obj), "failed to resolve %v", obj)
    62  	}
    63  
    64  	if name, ok := g.objs[obj]; ok {
    65  		return name // previously mapped
    66  	}
    67  
    68  	var name *ir.Name
    69  	pos := g.pos(obj)
    70  
    71  	class := typecheck.DeclContext
    72  	if obj.Parent() == g.self.Scope() {
    73  		class = ir.PEXTERN // forward reference to package-block declaration
    74  	}
    75  
    76  	// "You are in a maze of twisting little passages, all different."
    77  	switch obj := obj.(type) {
    78  	case *types2.Const:
    79  		name = g.objCommon(pos, ir.OLITERAL, g.sym(obj), class, g.typ(obj.Type()))
    80  
    81  	case *types2.Func:
    82  		sig := obj.Type().(*types2.Signature)
    83  		var sym *types.Sym
    84  		var typ *types.Type
    85  		if recv := sig.Recv(); recv == nil {
    86  			if obj.Name() == "init" {
    87  				sym = renameinit()
    88  			} else {
    89  				sym = g.sym(obj)
    90  			}
    91  			typ = g.typ(sig)
    92  		} else {
    93  			sym = g.selector(obj)
    94  			if !sym.IsBlank() {
    95  				sym = ir.MethodSym(g.typ(recv.Type()), sym)
    96  			}
    97  			typ = g.signature(g.param(recv), sig)
    98  		}
    99  		name = g.objCommon(pos, ir.ONAME, sym, ir.PFUNC, typ)
   100  
   101  	case *types2.TypeName:
   102  		if obj.IsAlias() {
   103  			name = g.objCommon(pos, ir.OTYPE, g.sym(obj), class, g.typ(obj.Type()))
   104  		} else {
   105  			name = ir.NewDeclNameAt(pos, ir.OTYPE, g.sym(obj))
   106  			g.objFinish(name, class, types.NewNamed(name))
   107  		}
   108  
   109  	case *types2.Var:
   110  		var sym *types.Sym
   111  		if class == ir.PPARAMOUT {
   112  			// Backend needs names for result parameters,
   113  			// even if they're anonymous or blank.
   114  			switch obj.Name() {
   115  			case "":
   116  				sym = typecheck.LookupNum("~r", len(ir.CurFunc.Dcl)) // 'r' for "result"
   117  			case "_":
   118  				sym = typecheck.LookupNum("~b", len(ir.CurFunc.Dcl)) // 'b' for "blank"
   119  			}
   120  		}
   121  		if sym == nil {
   122  			sym = g.sym(obj)
   123  		}
   124  		name = g.objCommon(pos, ir.ONAME, sym, class, g.typ(obj.Type()))
   125  
   126  	default:
   127  		g.unhandled("object", obj)
   128  	}
   129  
   130  	g.objs[obj] = name
   131  	name.SetTypecheck(1)
   132  	return name
   133  }
   134  
   135  func (g *irgen) objCommon(pos src.XPos, op ir.Op, sym *types.Sym, class ir.Class, typ *types.Type) *ir.Name {
   136  	name := ir.NewDeclNameAt(pos, op, sym)
   137  	g.objFinish(name, class, typ)
   138  	return name
   139  }
   140  
   141  func (g *irgen) objFinish(name *ir.Name, class ir.Class, typ *types.Type) {
   142  	sym := name.Sym()
   143  
   144  	name.SetType(typ)
   145  	name.Class = class
   146  	if name.Class == ir.PFUNC {
   147  		sym.SetFunc(true)
   148  	}
   149  
   150  	name.SetTypecheck(1)
   151  	name.SetWalkdef(1)
   152  
   153  	if ir.IsBlank(name) {
   154  		return
   155  	}
   156  
   157  	switch class {
   158  	case ir.PEXTERN:
   159  		g.target.Externs = append(g.target.Externs, name)
   160  		fallthrough
   161  	case ir.PFUNC:
   162  		sym.Def = name
   163  		if name.Class == ir.PFUNC && name.Type().Recv() != nil {
   164  			break // methods are exported with their receiver type
   165  		}
   166  		if types.IsExported(sym.Name) {
   167  			if name.Class == ir.PFUNC && name.Type().NumTParams() > 0 {
   168  				base.FatalfAt(name.Pos(), "Cannot export a generic function (yet): %v", name)
   169  			}
   170  			typecheck.Export(name)
   171  		}
   172  		if base.Flag.AsmHdr != "" && !name.Sym().Asm() {
   173  			name.Sym().SetAsm(true)
   174  			g.target.Asms = append(g.target.Asms, name)
   175  		}
   176  
   177  	default:
   178  		// Function-scoped declaration.
   179  		name.Curfn = ir.CurFunc
   180  		if name.Op() == ir.ONAME {
   181  			ir.CurFunc.Dcl = append(ir.CurFunc.Dcl, name)
   182  		}
   183  	}
   184  }
   185  

View as plain text