github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/compile/internal/gc/dcl.go (about)

     1  // Copyright 2009 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 gc
     6  
     7  import (
     8  	"bytes"
     9  	"github.com/gagliardetto/golang-go/cmd/compile/internal/types"
    10  	"github.com/gagliardetto/golang-go/cmd/internal/obj"
    11  	"github.com/gagliardetto/golang-go/cmd/internal/src"
    12  	"fmt"
    13  	"strings"
    14  )
    15  
    16  // Declaration stack & operations
    17  
    18  var externdcl []*Node
    19  
    20  func testdclstack() {
    21  	if !types.IsDclstackValid() {
    22  		if nerrors != 0 {
    23  			errorexit()
    24  		}
    25  		Fatalf("mark left on the dclstack")
    26  	}
    27  }
    28  
    29  // redeclare emits a diagnostic about symbol s being redeclared at pos.
    30  func redeclare(pos src.XPos, s *types.Sym, where string) {
    31  	if !s.Lastlineno.IsKnown() {
    32  		pkg := s.Origpkg
    33  		if pkg == nil {
    34  			pkg = s.Pkg
    35  		}
    36  		yyerrorl(pos, "%v redeclared %s\n"+
    37  			"\tprevious declaration during import %q", s, where, pkg.Path)
    38  	} else {
    39  		prevPos := s.Lastlineno
    40  
    41  		// When an import and a declaration collide in separate files,
    42  		// present the import as the "redeclared", because the declaration
    43  		// is visible where the import is, but not vice versa.
    44  		// See issue 4510.
    45  		if s.Def == nil {
    46  			pos, prevPos = prevPos, pos
    47  		}
    48  
    49  		yyerrorl(pos, "%v redeclared %s\n"+
    50  			"\tprevious declaration at %v", s, where, linestr(prevPos))
    51  	}
    52  }
    53  
    54  var vargen int
    55  
    56  // declare individual names - var, typ, const
    57  
    58  var declare_typegen int
    59  
    60  // declare records that Node n declares symbol n.Sym in the specified
    61  // declaration context.
    62  func declare(n *Node, ctxt Class) {
    63  	if n.isBlank() {
    64  		return
    65  	}
    66  
    67  	if n.Name == nil {
    68  		// named OLITERAL needs Name; most OLITERALs don't.
    69  		n.Name = new(Name)
    70  	}
    71  
    72  	s := n.Sym
    73  
    74  	// kludgy: typecheckok means we're past parsing. Eg genwrapper may declare out of package names later.
    75  	if !inimport && !typecheckok && s.Pkg != localpkg {
    76  		yyerrorl(n.Pos, "cannot declare name %v", s)
    77  	}
    78  
    79  	gen := 0
    80  	if ctxt == PEXTERN {
    81  		if s.Name == "init" {
    82  			yyerrorl(n.Pos, "cannot declare init - must be func")
    83  		}
    84  		if s.Name == "main" && s.Pkg.Name == "main" {
    85  			yyerrorl(n.Pos, "cannot declare main - must be func")
    86  		}
    87  		externdcl = append(externdcl, n)
    88  	} else {
    89  		if Curfn == nil && ctxt == PAUTO {
    90  			lineno = n.Pos
    91  			Fatalf("automatic outside function")
    92  		}
    93  		if Curfn != nil {
    94  			Curfn.Func.Dcl = append(Curfn.Func.Dcl, n)
    95  		}
    96  		if n.Op == OTYPE {
    97  			declare_typegen++
    98  			gen = declare_typegen
    99  		} else if n.Op == ONAME && ctxt == PAUTO && !strings.Contains(s.Name, "·") {
   100  			vargen++
   101  			gen = vargen
   102  		}
   103  		types.Pushdcl(s)
   104  		n.Name.Curfn = Curfn
   105  	}
   106  
   107  	if ctxt == PAUTO {
   108  		n.Xoffset = 0
   109  	}
   110  
   111  	if s.Block == types.Block {
   112  		// functype will print errors about duplicate function arguments.
   113  		// Don't repeat the error here.
   114  		if ctxt != PPARAM && ctxt != PPARAMOUT {
   115  			redeclare(n.Pos, s, "in this block")
   116  		}
   117  	}
   118  
   119  	s.Block = types.Block
   120  	s.Lastlineno = lineno
   121  	s.Def = asTypesNode(n)
   122  	n.Name.Vargen = int32(gen)
   123  	n.SetClass(ctxt)
   124  	if ctxt == PFUNC {
   125  		n.Sym.SetFunc(true)
   126  	}
   127  
   128  	autoexport(n, ctxt)
   129  }
   130  
   131  func addvar(n *Node, t *types.Type, ctxt Class) {
   132  	if n == nil || n.Sym == nil || (n.Op != ONAME && n.Op != ONONAME) || t == nil {
   133  		Fatalf("addvar: n=%v t=%v nil", n, t)
   134  	}
   135  
   136  	n.Op = ONAME
   137  	declare(n, ctxt)
   138  	n.Type = t
   139  }
   140  
   141  // declare variables from grammar
   142  // new_name_list (type | [type] = expr_list)
   143  func variter(vl []*Node, t *Node, el []*Node) []*Node {
   144  	var init []*Node
   145  	doexpr := len(el) > 0
   146  
   147  	if len(el) == 1 && len(vl) > 1 {
   148  		e := el[0]
   149  		as2 := nod(OAS2, nil, nil)
   150  		as2.List.Set(vl)
   151  		as2.Rlist.Set1(e)
   152  		for _, v := range vl {
   153  			v.Op = ONAME
   154  			declare(v, dclcontext)
   155  			v.Name.Param.Ntype = t
   156  			v.Name.Defn = as2
   157  			if Curfn != nil {
   158  				init = append(init, nod(ODCL, v, nil))
   159  			}
   160  		}
   161  
   162  		return append(init, as2)
   163  	}
   164  
   165  	nel := len(el)
   166  	for _, v := range vl {
   167  		var e *Node
   168  		if doexpr {
   169  			if len(el) == 0 {
   170  				yyerror("assignment mismatch: %d variables but %d values", len(vl), nel)
   171  				break
   172  			}
   173  			e = el[0]
   174  			el = el[1:]
   175  		}
   176  
   177  		v.Op = ONAME
   178  		declare(v, dclcontext)
   179  		v.Name.Param.Ntype = t
   180  
   181  		if e != nil || Curfn != nil || v.isBlank() {
   182  			if Curfn != nil {
   183  				init = append(init, nod(ODCL, v, nil))
   184  			}
   185  			e = nod(OAS, v, e)
   186  			init = append(init, e)
   187  			if e.Right != nil {
   188  				v.Name.Defn = e
   189  			}
   190  		}
   191  	}
   192  
   193  	if len(el) != 0 {
   194  		yyerror("assignment mismatch: %d variables but %d values", len(vl), nel)
   195  	}
   196  	return init
   197  }
   198  
   199  // newnoname returns a new ONONAME Node associated with symbol s.
   200  func newnoname(s *types.Sym) *Node {
   201  	if s == nil {
   202  		Fatalf("newnoname nil")
   203  	}
   204  	n := nod(ONONAME, nil, nil)
   205  	n.Sym = s
   206  	n.Xoffset = 0
   207  	return n
   208  }
   209  
   210  // newfuncnamel generates a new name node for a function or method.
   211  // TODO(rsc): Use an ODCLFUNC node instead. See comment in CL 7360.
   212  func newfuncnamel(pos src.XPos, s *types.Sym) *Node {
   213  	n := newnamel(pos, s)
   214  	n.Func = new(Func)
   215  	n.Func.SetIsHiddenClosure(Curfn != nil)
   216  	return n
   217  }
   218  
   219  // this generates a new name node for a name
   220  // being declared.
   221  func dclname(s *types.Sym) *Node {
   222  	n := newname(s)
   223  	n.Op = ONONAME // caller will correct it
   224  	return n
   225  }
   226  
   227  func typenod(t *types.Type) *Node {
   228  	return typenodl(src.NoXPos, t)
   229  }
   230  
   231  func typenodl(pos src.XPos, t *types.Type) *Node {
   232  	// if we copied another type with *t = *u
   233  	// then t->nod might be out of date, so
   234  	// check t->nod->type too
   235  	if asNode(t.Nod) == nil || asNode(t.Nod).Type != t {
   236  		t.Nod = asTypesNode(nodl(pos, OTYPE, nil, nil))
   237  		asNode(t.Nod).Type = t
   238  		asNode(t.Nod).Sym = t.Sym
   239  	}
   240  
   241  	return asNode(t.Nod)
   242  }
   243  
   244  func anonfield(typ *types.Type) *Node {
   245  	return symfield(nil, typ)
   246  }
   247  
   248  func namedfield(s string, typ *types.Type) *Node {
   249  	return symfield(lookup(s), typ)
   250  }
   251  
   252  func symfield(s *types.Sym, typ *types.Type) *Node {
   253  	n := nodSym(ODCLFIELD, nil, s)
   254  	n.Type = typ
   255  	return n
   256  }
   257  
   258  // oldname returns the Node that declares symbol s in the current scope.
   259  // If no such Node currently exists, an ONONAME Node is returned instead.
   260  func oldname(s *types.Sym) *Node {
   261  	n := asNode(s.Def)
   262  	if n == nil {
   263  		// Maybe a top-level declaration will come along later to
   264  		// define s. resolve will check s.Def again once all input
   265  		// source has been processed.
   266  		return newnoname(s)
   267  	}
   268  
   269  	if Curfn != nil && n.Op == ONAME && n.Name.Curfn != nil && n.Name.Curfn != Curfn {
   270  		// Inner func is referring to var in outer func.
   271  		//
   272  		// TODO(rsc): If there is an outer variable x and we
   273  		// are parsing x := 5 inside the closure, until we get to
   274  		// the := it looks like a reference to the outer x so we'll
   275  		// make x a closure variable unnecessarily.
   276  		c := n.Name.Param.Innermost
   277  		if c == nil || c.Name.Curfn != Curfn {
   278  			// Do not have a closure var for the active closure yet; make one.
   279  			c = newname(s)
   280  			c.SetClass(PAUTOHEAP)
   281  			c.Name.SetIsClosureVar(true)
   282  			c.SetIsDDD(n.IsDDD())
   283  			c.Name.Defn = n
   284  
   285  			// Link into list of active closure variables.
   286  			// Popped from list in func closurebody.
   287  			c.Name.Param.Outer = n.Name.Param.Innermost
   288  			n.Name.Param.Innermost = c
   289  
   290  			Curfn.Func.Cvars.Append(c)
   291  		}
   292  
   293  		// return ref to closure var, not original
   294  		return c
   295  	}
   296  
   297  	return n
   298  }
   299  
   300  // := declarations
   301  func colasname(n *Node) bool {
   302  	switch n.Op {
   303  	case ONAME,
   304  		ONONAME,
   305  		OPACK,
   306  		OTYPE,
   307  		OLITERAL:
   308  		return n.Sym != nil
   309  	}
   310  
   311  	return false
   312  }
   313  
   314  func colasdefn(left []*Node, defn *Node) {
   315  	for _, n := range left {
   316  		if n.Sym != nil {
   317  			n.Sym.SetUniq(true)
   318  		}
   319  	}
   320  
   321  	var nnew, nerr int
   322  	for i, n := range left {
   323  		if n.isBlank() {
   324  			continue
   325  		}
   326  		if !colasname(n) {
   327  			yyerrorl(defn.Pos, "non-name %v on left side of :=", n)
   328  			nerr++
   329  			continue
   330  		}
   331  
   332  		if !n.Sym.Uniq() {
   333  			yyerrorl(defn.Pos, "%v repeated on left side of :=", n.Sym)
   334  			n.SetDiag(true)
   335  			nerr++
   336  			continue
   337  		}
   338  
   339  		n.Sym.SetUniq(false)
   340  		if n.Sym.Block == types.Block {
   341  			continue
   342  		}
   343  
   344  		nnew++
   345  		n = newname(n.Sym)
   346  		declare(n, dclcontext)
   347  		n.Name.Defn = defn
   348  		defn.Ninit.Append(nod(ODCL, n, nil))
   349  		left[i] = n
   350  	}
   351  
   352  	if nnew == 0 && nerr == 0 {
   353  		yyerrorl(defn.Pos, "no new variables on left side of :=")
   354  	}
   355  }
   356  
   357  // declare the arguments in an
   358  // interface field declaration.
   359  func ifacedcl(n *Node) {
   360  	if n.Op != ODCLFIELD || n.Left == nil {
   361  		Fatalf("ifacedcl")
   362  	}
   363  
   364  	if n.Sym.IsBlank() {
   365  		yyerror("methods must have a unique non-blank name")
   366  	}
   367  }
   368  
   369  // declare the function proper
   370  // and declare the arguments.
   371  // called in extern-declaration context
   372  // returns in auto-declaration context.
   373  func funchdr(n *Node) {
   374  	// change the declaration context from extern to auto
   375  	if Curfn == nil && dclcontext != PEXTERN {
   376  		Fatalf("funchdr: dclcontext = %d", dclcontext)
   377  	}
   378  
   379  	dclcontext = PAUTO
   380  	types.Markdcl()
   381  	funcstack = append(funcstack, Curfn)
   382  	Curfn = n
   383  
   384  	if n.Func.Nname != nil {
   385  		funcargs(n.Func.Nname.Name.Param.Ntype)
   386  	} else if n.Func.Ntype != nil {
   387  		funcargs(n.Func.Ntype)
   388  	} else {
   389  		funcargs2(n.Type)
   390  	}
   391  }
   392  
   393  func funcargs(nt *Node) {
   394  	if nt.Op != OTFUNC {
   395  		Fatalf("funcargs %v", nt.Op)
   396  	}
   397  
   398  	// re-start the variable generation number
   399  	// we want to use small numbers for the return variables,
   400  	// so let them have the chunk starting at 1.
   401  	//
   402  	// TODO(mdempsky): This is ugly, and only necessary because
   403  	// esc.go uses Vargen to figure out result parameters' index
   404  	// within the result tuple.
   405  	vargen = nt.Rlist.Len()
   406  
   407  	// declare the receiver and in arguments.
   408  	if nt.Left != nil {
   409  		funcarg(nt.Left, PPARAM)
   410  	}
   411  	for _, n := range nt.List.Slice() {
   412  		funcarg(n, PPARAM)
   413  	}
   414  
   415  	oldvargen := vargen
   416  	vargen = 0
   417  
   418  	// declare the out arguments.
   419  	gen := nt.List.Len()
   420  	for _, n := range nt.Rlist.Slice() {
   421  		if n.Sym == nil {
   422  			// Name so that escape analysis can track it. ~r stands for 'result'.
   423  			n.Sym = lookupN("~r", gen)
   424  			gen++
   425  		}
   426  		if n.Sym.IsBlank() {
   427  			// Give it a name so we can assign to it during return. ~b stands for 'blank'.
   428  			// The name must be different from ~r above because if you have
   429  			//	func f() (_ int)
   430  			//	func g() int
   431  			// f is allowed to use a plain 'return' with no arguments, while g is not.
   432  			// So the two cases must be distinguished.
   433  			n.Sym = lookupN("~b", gen)
   434  			gen++
   435  		}
   436  
   437  		funcarg(n, PPARAMOUT)
   438  	}
   439  
   440  	vargen = oldvargen
   441  }
   442  
   443  func funcarg(n *Node, ctxt Class) {
   444  	if n.Op != ODCLFIELD {
   445  		Fatalf("funcarg %v", n.Op)
   446  	}
   447  	if n.Sym == nil {
   448  		return
   449  	}
   450  
   451  	n.Right = newnamel(n.Pos, n.Sym)
   452  	n.Right.Name.Param.Ntype = n.Left
   453  	n.Right.SetIsDDD(n.IsDDD())
   454  	declare(n.Right, ctxt)
   455  
   456  	vargen++
   457  	n.Right.Name.Vargen = int32(vargen)
   458  }
   459  
   460  // Same as funcargs, except run over an already constructed TFUNC.
   461  // This happens during import, where the hidden_fndcl rule has
   462  // used functype directly to parse the function's type.
   463  func funcargs2(t *types.Type) {
   464  	if t.Etype != TFUNC {
   465  		Fatalf("funcargs2 %v", t)
   466  	}
   467  
   468  	for _, f := range t.Recvs().Fields().Slice() {
   469  		funcarg2(f, PPARAM)
   470  	}
   471  	for _, f := range t.Params().Fields().Slice() {
   472  		funcarg2(f, PPARAM)
   473  	}
   474  	for _, f := range t.Results().Fields().Slice() {
   475  		funcarg2(f, PPARAMOUT)
   476  	}
   477  }
   478  
   479  func funcarg2(f *types.Field, ctxt Class) {
   480  	if f.Sym == nil {
   481  		return
   482  	}
   483  	n := newnamel(f.Pos, f.Sym)
   484  	f.Nname = asTypesNode(n)
   485  	n.Type = f.Type
   486  	n.SetIsDDD(f.IsDDD())
   487  	declare(n, ctxt)
   488  }
   489  
   490  var funcstack []*Node // stack of previous values of Curfn
   491  
   492  // finish the body.
   493  // called in auto-declaration context.
   494  // returns in extern-declaration context.
   495  func funcbody() {
   496  	// change the declaration context from auto to extern
   497  	if dclcontext != PAUTO {
   498  		Fatalf("funcbody: unexpected dclcontext %d", dclcontext)
   499  	}
   500  	types.Popdcl()
   501  	funcstack, Curfn = funcstack[:len(funcstack)-1], funcstack[len(funcstack)-1]
   502  	if Curfn == nil {
   503  		dclcontext = PEXTERN
   504  	}
   505  }
   506  
   507  // structs, functions, and methods.
   508  // they don't belong here, but where do they belong?
   509  func checkembeddedtype(t *types.Type) {
   510  	if t == nil {
   511  		return
   512  	}
   513  
   514  	if t.Sym == nil && t.IsPtr() {
   515  		t = t.Elem()
   516  		if t.IsInterface() {
   517  			yyerror("embedded type cannot be a pointer to interface")
   518  		}
   519  	}
   520  
   521  	if t.IsPtr() || t.IsUnsafePtr() {
   522  		yyerror("embedded type cannot be a pointer")
   523  	} else if t.Etype == TFORW && !t.ForwardType().Embedlineno.IsKnown() {
   524  		t.ForwardType().Embedlineno = lineno
   525  	}
   526  }
   527  
   528  func structfield(n *Node) *types.Field {
   529  	lno := lineno
   530  	lineno = n.Pos
   531  
   532  	if n.Op != ODCLFIELD {
   533  		Fatalf("structfield: oops %v\n", n)
   534  	}
   535  
   536  	f := types.NewField()
   537  	f.Pos = n.Pos
   538  	f.Sym = n.Sym
   539  
   540  	if n.Left != nil {
   541  		n.Left = typecheck(n.Left, ctxType)
   542  		n.Type = n.Left.Type
   543  		n.Left = nil
   544  	}
   545  
   546  	f.Type = n.Type
   547  	if f.Type == nil {
   548  		f.SetBroke(true)
   549  	}
   550  
   551  	if n.Embedded() {
   552  		checkembeddedtype(n.Type)
   553  		f.Embedded = 1
   554  	} else {
   555  		f.Embedded = 0
   556  	}
   557  
   558  	switch u := n.Val().U.(type) {
   559  	case string:
   560  		f.Note = u
   561  	default:
   562  		yyerror("field tag must be a string")
   563  	case nil:
   564  		// no-op
   565  	}
   566  
   567  	lineno = lno
   568  	return f
   569  }
   570  
   571  // checkdupfields emits errors for duplicately named fields or methods in
   572  // a list of struct or interface types.
   573  func checkdupfields(what string, fss ...[]*types.Field) {
   574  	seen := make(map[*types.Sym]bool)
   575  	for _, fs := range fss {
   576  		for _, f := range fs {
   577  			if f.Sym == nil || f.Sym.IsBlank() {
   578  				continue
   579  			}
   580  			if seen[f.Sym] {
   581  				yyerrorl(f.Pos, "duplicate %s %s", what, f.Sym.Name)
   582  				continue
   583  			}
   584  			seen[f.Sym] = true
   585  		}
   586  	}
   587  }
   588  
   589  // convert a parsed id/type list into
   590  // a type for struct/interface/arglist
   591  func tostruct(l []*Node) *types.Type {
   592  	t := types.New(TSTRUCT)
   593  	tostruct0(t, l)
   594  	return t
   595  }
   596  
   597  func tostruct0(t *types.Type, l []*Node) {
   598  	if t == nil || !t.IsStruct() {
   599  		Fatalf("struct expected")
   600  	}
   601  
   602  	fields := make([]*types.Field, len(l))
   603  	for i, n := range l {
   604  		f := structfield(n)
   605  		if f.Broke() {
   606  			t.SetBroke(true)
   607  		}
   608  		fields[i] = f
   609  	}
   610  	t.SetFields(fields)
   611  
   612  	checkdupfields("field", t.FieldSlice())
   613  
   614  	if !t.Broke() {
   615  		checkwidth(t)
   616  	}
   617  }
   618  
   619  func tofunargs(l []*Node, funarg types.Funarg) *types.Type {
   620  	t := types.New(TSTRUCT)
   621  	t.StructType().Funarg = funarg
   622  
   623  	fields := make([]*types.Field, len(l))
   624  	for i, n := range l {
   625  		f := structfield(n)
   626  		f.SetIsDDD(n.IsDDD())
   627  		if n.Right != nil {
   628  			n.Right.Type = f.Type
   629  			f.Nname = asTypesNode(n.Right)
   630  		}
   631  		if f.Broke() {
   632  			t.SetBroke(true)
   633  		}
   634  		fields[i] = f
   635  	}
   636  	t.SetFields(fields)
   637  	return t
   638  }
   639  
   640  func tofunargsfield(fields []*types.Field, funarg types.Funarg) *types.Type {
   641  	t := types.New(TSTRUCT)
   642  	t.StructType().Funarg = funarg
   643  	t.SetFields(fields)
   644  	return t
   645  }
   646  
   647  func interfacefield(n *Node) *types.Field {
   648  	lno := lineno
   649  	lineno = n.Pos
   650  
   651  	if n.Op != ODCLFIELD {
   652  		Fatalf("interfacefield: oops %v\n", n)
   653  	}
   654  
   655  	if n.Val().Ctype() != CTxxx {
   656  		yyerror("interface method cannot have annotation")
   657  	}
   658  
   659  	// MethodSpec = MethodName Signature | InterfaceTypeName .
   660  	//
   661  	// If Sym != nil, then Sym is MethodName and Left is Signature.
   662  	// Otherwise, Left is InterfaceTypeName.
   663  
   664  	if n.Left != nil {
   665  		n.Left = typecheck(n.Left, ctxType)
   666  		n.Type = n.Left.Type
   667  		n.Left = nil
   668  	}
   669  
   670  	f := types.NewField()
   671  	f.Pos = n.Pos
   672  	f.Sym = n.Sym
   673  	f.Type = n.Type
   674  	if f.Type == nil {
   675  		f.SetBroke(true)
   676  	}
   677  
   678  	lineno = lno
   679  	return f
   680  }
   681  
   682  func tointerface(l []*Node) *types.Type {
   683  	if len(l) == 0 {
   684  		return types.Types[TINTER]
   685  	}
   686  	t := types.New(TINTER)
   687  	tointerface0(t, l)
   688  	return t
   689  }
   690  
   691  func tointerface0(t *types.Type, l []*Node) {
   692  	if t == nil || !t.IsInterface() {
   693  		Fatalf("interface expected")
   694  	}
   695  
   696  	var fields []*types.Field
   697  	for _, n := range l {
   698  		f := interfacefield(n)
   699  		if f.Broke() {
   700  			t.SetBroke(true)
   701  		}
   702  		fields = append(fields, f)
   703  	}
   704  	t.SetInterface(fields)
   705  }
   706  
   707  func fakeRecv() *Node {
   708  	return anonfield(types.FakeRecvType())
   709  }
   710  
   711  func fakeRecvField() *types.Field {
   712  	f := types.NewField()
   713  	f.Type = types.FakeRecvType()
   714  	return f
   715  }
   716  
   717  // isifacemethod reports whether (field) m is
   718  // an interface method. Such methods have the
   719  // special receiver type types.FakeRecvType().
   720  func isifacemethod(f *types.Type) bool {
   721  	return f.Recv().Type == types.FakeRecvType()
   722  }
   723  
   724  // turn a parsed function declaration into a type
   725  func functype(this *Node, in, out []*Node) *types.Type {
   726  	t := types.New(TFUNC)
   727  	functype0(t, this, in, out)
   728  	return t
   729  }
   730  
   731  func functype0(t *types.Type, this *Node, in, out []*Node) {
   732  	if t == nil || t.Etype != TFUNC {
   733  		Fatalf("function type expected")
   734  	}
   735  
   736  	var rcvr []*Node
   737  	if this != nil {
   738  		rcvr = []*Node{this}
   739  	}
   740  	t.FuncType().Receiver = tofunargs(rcvr, types.FunargRcvr)
   741  	t.FuncType().Params = tofunargs(in, types.FunargParams)
   742  	t.FuncType().Results = tofunargs(out, types.FunargResults)
   743  
   744  	checkdupfields("argument", t.Recvs().FieldSlice(), t.Params().FieldSlice(), t.Results().FieldSlice())
   745  
   746  	if t.Recvs().Broke() || t.Results().Broke() || t.Params().Broke() {
   747  		t.SetBroke(true)
   748  	}
   749  
   750  	t.FuncType().Outnamed = t.NumResults() > 0 && origSym(t.Results().Field(0).Sym) != nil
   751  }
   752  
   753  func functypefield(this *types.Field, in, out []*types.Field) *types.Type {
   754  	t := types.New(TFUNC)
   755  	functypefield0(t, this, in, out)
   756  	return t
   757  }
   758  
   759  func functypefield0(t *types.Type, this *types.Field, in, out []*types.Field) {
   760  	var rcvr []*types.Field
   761  	if this != nil {
   762  		rcvr = []*types.Field{this}
   763  	}
   764  	t.FuncType().Receiver = tofunargsfield(rcvr, types.FunargRcvr)
   765  	t.FuncType().Params = tofunargsfield(in, types.FunargParams)
   766  	t.FuncType().Results = tofunargsfield(out, types.FunargResults)
   767  
   768  	t.FuncType().Outnamed = t.NumResults() > 0 && origSym(t.Results().Field(0).Sym) != nil
   769  }
   770  
   771  // origSym returns the original symbol written by the user.
   772  func origSym(s *types.Sym) *types.Sym {
   773  	if s == nil {
   774  		return nil
   775  	}
   776  
   777  	if len(s.Name) > 1 && s.Name[0] == '~' {
   778  		switch s.Name[1] {
   779  		case 'r': // originally an unnamed result
   780  			return nil
   781  		case 'b': // originally the blank identifier _
   782  			// TODO(mdempsky): Does s.Pkg matter here?
   783  			return nblank.Sym
   784  		}
   785  		return s
   786  	}
   787  
   788  	if strings.HasPrefix(s.Name, ".anon") {
   789  		// originally an unnamed or _ name (see subr.go: structargs)
   790  		return nil
   791  	}
   792  
   793  	return s
   794  }
   795  
   796  // methodSym returns the method symbol representing a method name
   797  // associated with a specific receiver type.
   798  //
   799  // Method symbols can be used to distinguish the same method appearing
   800  // in different method sets. For example, T.M and (*T).M have distinct
   801  // method symbols.
   802  //
   803  // The returned symbol will be marked as a function.
   804  func methodSym(recv *types.Type, msym *types.Sym) *types.Sym {
   805  	sym := methodSymSuffix(recv, msym, "")
   806  	sym.SetFunc(true)
   807  	return sym
   808  }
   809  
   810  // methodSymSuffix is like methodsym, but allows attaching a
   811  // distinguisher suffix. To avoid collisions, the suffix must not
   812  // start with a letter, number, or period.
   813  func methodSymSuffix(recv *types.Type, msym *types.Sym, suffix string) *types.Sym {
   814  	if msym.IsBlank() {
   815  		Fatalf("blank method name")
   816  	}
   817  
   818  	rsym := recv.Sym
   819  	if recv.IsPtr() {
   820  		if rsym != nil {
   821  			Fatalf("declared pointer receiver type: %v", recv)
   822  		}
   823  		rsym = recv.Elem().Sym
   824  	}
   825  
   826  	// Find the package the receiver type appeared in. For
   827  	// anonymous receiver types (i.e., anonymous structs with
   828  	// embedded fields), use the "go" pseudo-package instead.
   829  	rpkg := gopkg
   830  	if rsym != nil {
   831  		rpkg = rsym.Pkg
   832  	}
   833  
   834  	var b bytes.Buffer
   835  	if recv.IsPtr() {
   836  		// The parentheses aren't really necessary, but
   837  		// they're pretty traditional at this point.
   838  		fmt.Fprintf(&b, "(%-S)", recv)
   839  	} else {
   840  		fmt.Fprintf(&b, "%-S", recv)
   841  	}
   842  
   843  	// A particular receiver type may have multiple non-exported
   844  	// methods with the same name. To disambiguate them, include a
   845  	// package qualifier for names that came from a different
   846  	// package than the receiver type.
   847  	if !types.IsExported(msym.Name) && msym.Pkg != rpkg {
   848  		b.WriteString(".")
   849  		b.WriteString(msym.Pkg.Prefix)
   850  	}
   851  
   852  	b.WriteString(".")
   853  	b.WriteString(msym.Name)
   854  	b.WriteString(suffix)
   855  
   856  	return rpkg.LookupBytes(b.Bytes())
   857  }
   858  
   859  // Add a method, declared as a function.
   860  // - msym is the method symbol
   861  // - t is function type (with receiver)
   862  // Returns a pointer to the existing or added Field; or nil if there's an error.
   863  func addmethod(msym *types.Sym, t *types.Type, local, nointerface bool) *types.Field {
   864  	if msym == nil {
   865  		Fatalf("no method symbol")
   866  	}
   867  
   868  	// get parent type sym
   869  	rf := t.Recv() // ptr to this structure
   870  	if rf == nil {
   871  		yyerror("missing receiver")
   872  		return nil
   873  	}
   874  
   875  	mt := methtype(rf.Type)
   876  	if mt == nil || mt.Sym == nil {
   877  		pa := rf.Type
   878  		t := pa
   879  		if t != nil && t.IsPtr() {
   880  			if t.Sym != nil {
   881  				yyerror("invalid receiver type %v (%v is a pointer type)", pa, t)
   882  				return nil
   883  			}
   884  			t = t.Elem()
   885  		}
   886  
   887  		switch {
   888  		case t == nil || t.Broke():
   889  			// rely on typecheck having complained before
   890  		case t.Sym == nil:
   891  			yyerror("invalid receiver type %v (%v is not a defined type)", pa, t)
   892  		case t.IsPtr():
   893  			yyerror("invalid receiver type %v (%v is a pointer type)", pa, t)
   894  		case t.IsInterface():
   895  			yyerror("invalid receiver type %v (%v is an interface type)", pa, t)
   896  		default:
   897  			// Should have picked off all the reasons above,
   898  			// but just in case, fall back to generic error.
   899  			yyerror("invalid receiver type %v (%L / %L)", pa, pa, t)
   900  		}
   901  		return nil
   902  	}
   903  
   904  	if local && mt.Sym.Pkg != localpkg {
   905  		yyerror("cannot define new methods on non-local type %v", mt)
   906  		return nil
   907  	}
   908  
   909  	if msym.IsBlank() {
   910  		return nil
   911  	}
   912  
   913  	if mt.IsStruct() {
   914  		for _, f := range mt.Fields().Slice() {
   915  			if f.Sym == msym {
   916  				yyerror("type %v has both field and method named %v", mt, msym)
   917  				f.SetBroke(true)
   918  				return nil
   919  			}
   920  		}
   921  	}
   922  
   923  	for _, f := range mt.Methods().Slice() {
   924  		if msym.Name != f.Sym.Name {
   925  			continue
   926  		}
   927  		// types.Identical only checks that incoming and result parameters match,
   928  		// so explicitly check that the receiver parameters match too.
   929  		if !types.Identical(t, f.Type) || !types.Identical(t.Recv().Type, f.Type.Recv().Type) {
   930  			yyerror("method redeclared: %v.%v\n\t%v\n\t%v", mt, msym, f.Type, t)
   931  		}
   932  		return f
   933  	}
   934  
   935  	f := types.NewField()
   936  	f.Pos = lineno
   937  	f.Sym = msym
   938  	f.Type = t
   939  	f.SetNointerface(nointerface)
   940  
   941  	mt.Methods().Append(f)
   942  	return f
   943  }
   944  
   945  func funcsymname(s *types.Sym) string {
   946  	return s.Name + "·f"
   947  }
   948  
   949  // funcsym returns s·f.
   950  func funcsym(s *types.Sym) *types.Sym {
   951  	// funcsymsmu here serves to protect not just mutations of funcsyms (below),
   952  	// but also the package lookup of the func sym name,
   953  	// since this function gets called concurrently from the backend.
   954  	// There are no other concurrent package lookups in the backend,
   955  	// except for the types package, which is protected separately.
   956  	// Reusing funcsymsmu to also cover this package lookup
   957  	// avoids a general, broader, expensive package lookup mutex.
   958  	// Note makefuncsym also does package look-up of func sym names,
   959  	// but that it is only called serially, from the front end.
   960  	funcsymsmu.Lock()
   961  	sf, existed := s.Pkg.LookupOK(funcsymname(s))
   962  	// Don't export s·f when compiling for dynamic linking.
   963  	// When dynamically linking, the necessary function
   964  	// symbols will be created explicitly with makefuncsym.
   965  	// See the makefuncsym comment for details.
   966  	if !Ctxt.Flag_dynlink && !existed {
   967  		funcsyms = append(funcsyms, s)
   968  	}
   969  	funcsymsmu.Unlock()
   970  	return sf
   971  }
   972  
   973  // makefuncsym ensures that s·f is exported.
   974  // It is only used with -dynlink.
   975  // When not compiling for dynamic linking,
   976  // the funcsyms are created as needed by
   977  // the packages that use them.
   978  // Normally we emit the s·f stubs as DUPOK syms,
   979  // but DUPOK doesn't work across shared library boundaries.
   980  // So instead, when dynamic linking, we only create
   981  // the s·f stubs in s's package.
   982  func makefuncsym(s *types.Sym) {
   983  	if !Ctxt.Flag_dynlink {
   984  		Fatalf("makefuncsym dynlink")
   985  	}
   986  	if s.IsBlank() {
   987  		return
   988  	}
   989  	if compiling_runtime && (s.Name == "getg" || s.Name == "getclosureptr" || s.Name == "getcallerpc" || s.Name == "getcallersp") {
   990  		// runtime.getg(), getclosureptr(), getcallerpc(), and
   991  		// getcallersp() are not real functions and so do not
   992  		// get funcsyms.
   993  		return
   994  	}
   995  	if _, existed := s.Pkg.LookupOK(funcsymname(s)); !existed {
   996  		funcsyms = append(funcsyms, s)
   997  	}
   998  }
   999  
  1000  // disableExport prevents sym from being included in package export
  1001  // data. To be effectual, it must be called before declare.
  1002  func disableExport(sym *types.Sym) {
  1003  	sym.SetOnExportList(true)
  1004  }
  1005  
  1006  func dclfunc(sym *types.Sym, tfn *Node) *Node {
  1007  	if tfn.Op != OTFUNC {
  1008  		Fatalf("expected OTFUNC node, got %v", tfn)
  1009  	}
  1010  
  1011  	fn := nod(ODCLFUNC, nil, nil)
  1012  	fn.Func.Nname = newfuncnamel(lineno, sym)
  1013  	fn.Func.Nname.Name.Defn = fn
  1014  	fn.Func.Nname.Name.Param.Ntype = tfn
  1015  	declare(fn.Func.Nname, PFUNC)
  1016  	funchdr(fn)
  1017  	fn.Func.Nname.Name.Param.Ntype = typecheck(fn.Func.Nname.Name.Param.Ntype, ctxType)
  1018  	return fn
  1019  }
  1020  
  1021  type nowritebarrierrecChecker struct {
  1022  	// extraCalls contains extra function calls that may not be
  1023  	// visible during later analysis. It maps from the ODCLFUNC of
  1024  	// the caller to a list of callees.
  1025  	extraCalls map[*Node][]nowritebarrierrecCall
  1026  
  1027  	// curfn is the current function during AST walks.
  1028  	curfn *Node
  1029  }
  1030  
  1031  type nowritebarrierrecCall struct {
  1032  	target *Node    // ODCLFUNC of caller or callee
  1033  	lineno src.XPos // line of call
  1034  }
  1035  
  1036  type nowritebarrierrecCallSym struct {
  1037  	target *obj.LSym // LSym of callee
  1038  	lineno src.XPos  // line of call
  1039  }
  1040  
  1041  // newNowritebarrierrecChecker creates a nowritebarrierrecChecker. It
  1042  // must be called before transformclosure and walk.
  1043  func newNowritebarrierrecChecker() *nowritebarrierrecChecker {
  1044  	c := &nowritebarrierrecChecker{
  1045  		extraCalls: make(map[*Node][]nowritebarrierrecCall),
  1046  	}
  1047  
  1048  	// Find all systemstack calls and record their targets. In
  1049  	// general, flow analysis can't see into systemstack, but it's
  1050  	// important to handle it for this check, so we model it
  1051  	// directly. This has to happen before transformclosure since
  1052  	// it's a lot harder to work out the argument after.
  1053  	for _, n := range xtop {
  1054  		if n.Op != ODCLFUNC {
  1055  			continue
  1056  		}
  1057  		c.curfn = n
  1058  		inspect(n, c.findExtraCalls)
  1059  	}
  1060  	c.curfn = nil
  1061  	return c
  1062  }
  1063  
  1064  func (c *nowritebarrierrecChecker) findExtraCalls(n *Node) bool {
  1065  	if n.Op != OCALLFUNC {
  1066  		return true
  1067  	}
  1068  	fn := n.Left
  1069  	if fn == nil || fn.Op != ONAME || fn.Class() != PFUNC || fn.Name.Defn == nil {
  1070  		return true
  1071  	}
  1072  	if !isRuntimePkg(fn.Sym.Pkg) || fn.Sym.Name != "systemstack" {
  1073  		return true
  1074  	}
  1075  
  1076  	var callee *Node
  1077  	arg := n.List.First()
  1078  	switch arg.Op {
  1079  	case ONAME:
  1080  		callee = arg.Name.Defn
  1081  	case OCLOSURE:
  1082  		callee = arg.Func.Closure
  1083  	default:
  1084  		Fatalf("expected ONAME or OCLOSURE node, got %+v", arg)
  1085  	}
  1086  	if callee.Op != ODCLFUNC {
  1087  		Fatalf("expected ODCLFUNC node, got %+v", callee)
  1088  	}
  1089  	c.extraCalls[c.curfn] = append(c.extraCalls[c.curfn], nowritebarrierrecCall{callee, n.Pos})
  1090  	return true
  1091  }
  1092  
  1093  // recordCall records a call from ODCLFUNC node "from", to function
  1094  // symbol "to" at position pos.
  1095  //
  1096  // This should be done as late as possible during compilation to
  1097  // capture precise call graphs. The target of the call is an LSym
  1098  // because that's all we know after we start SSA.
  1099  //
  1100  // This can be called concurrently for different from Nodes.
  1101  func (c *nowritebarrierrecChecker) recordCall(from *Node, to *obj.LSym, pos src.XPos) {
  1102  	if from.Op != ODCLFUNC {
  1103  		Fatalf("expected ODCLFUNC, got %v", from)
  1104  	}
  1105  	// We record this information on the *Func so this is
  1106  	// concurrent-safe.
  1107  	fn := from.Func
  1108  	if fn.nwbrCalls == nil {
  1109  		fn.nwbrCalls = new([]nowritebarrierrecCallSym)
  1110  	}
  1111  	*fn.nwbrCalls = append(*fn.nwbrCalls, nowritebarrierrecCallSym{to, pos})
  1112  }
  1113  
  1114  func (c *nowritebarrierrecChecker) check() {
  1115  	// We walk the call graph as late as possible so we can
  1116  	// capture all calls created by lowering, but this means we
  1117  	// only get to see the obj.LSyms of calls. symToFunc lets us
  1118  	// get back to the ODCLFUNCs.
  1119  	symToFunc := make(map[*obj.LSym]*Node)
  1120  	// funcs records the back-edges of the BFS call graph walk. It
  1121  	// maps from the ODCLFUNC of each function that must not have
  1122  	// write barriers to the call that inhibits them. Functions
  1123  	// that are directly marked go:nowritebarrierrec are in this
  1124  	// map with a zero-valued nowritebarrierrecCall. This also
  1125  	// acts as the set of marks for the BFS of the call graph.
  1126  	funcs := make(map[*Node]nowritebarrierrecCall)
  1127  	// q is the queue of ODCLFUNC Nodes to visit in BFS order.
  1128  	var q nodeQueue
  1129  
  1130  	for _, n := range xtop {
  1131  		if n.Op != ODCLFUNC {
  1132  			continue
  1133  		}
  1134  
  1135  		symToFunc[n.Func.lsym] = n
  1136  
  1137  		// Make nowritebarrierrec functions BFS roots.
  1138  		if n.Func.Pragma&Nowritebarrierrec != 0 {
  1139  			funcs[n] = nowritebarrierrecCall{}
  1140  			q.pushRight(n)
  1141  		}
  1142  		// Check go:nowritebarrier functions.
  1143  		if n.Func.Pragma&Nowritebarrier != 0 && n.Func.WBPos.IsKnown() {
  1144  			yyerrorl(n.Func.WBPos, "write barrier prohibited")
  1145  		}
  1146  	}
  1147  
  1148  	// Perform a BFS of the call graph from all
  1149  	// go:nowritebarrierrec functions.
  1150  	enqueue := func(src, target *Node, pos src.XPos) {
  1151  		if target.Func.Pragma&Yeswritebarrierrec != 0 {
  1152  			// Don't flow into this function.
  1153  			return
  1154  		}
  1155  		if _, ok := funcs[target]; ok {
  1156  			// Already found a path to target.
  1157  			return
  1158  		}
  1159  
  1160  		// Record the path.
  1161  		funcs[target] = nowritebarrierrecCall{target: src, lineno: pos}
  1162  		q.pushRight(target)
  1163  	}
  1164  	for !q.empty() {
  1165  		fn := q.popLeft()
  1166  
  1167  		// Check fn.
  1168  		if fn.Func.WBPos.IsKnown() {
  1169  			var err bytes.Buffer
  1170  			call := funcs[fn]
  1171  			for call.target != nil {
  1172  				fmt.Fprintf(&err, "\n\t%v: called by %v", linestr(call.lineno), call.target.Func.Nname)
  1173  				call = funcs[call.target]
  1174  			}
  1175  			yyerrorl(fn.Func.WBPos, "write barrier prohibited by caller; %v%s", fn.Func.Nname, err.String())
  1176  			continue
  1177  		}
  1178  
  1179  		// Enqueue fn's calls.
  1180  		for _, callee := range c.extraCalls[fn] {
  1181  			enqueue(fn, callee.target, callee.lineno)
  1182  		}
  1183  		if fn.Func.nwbrCalls == nil {
  1184  			continue
  1185  		}
  1186  		for _, callee := range *fn.Func.nwbrCalls {
  1187  			target := symToFunc[callee.target]
  1188  			if target != nil {
  1189  				enqueue(fn, target, callee.lineno)
  1190  			}
  1191  		}
  1192  	}
  1193  }