Source file src/cmd/compile/internal/typecheck/dcl.go

     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 typecheck
     6  
     7  import (
     8  	"fmt"
     9  	"sync"
    10  
    11  	"cmd/compile/internal/base"
    12  	"cmd/compile/internal/ir"
    13  	"cmd/compile/internal/types"
    14  	"cmd/internal/src"
    15  )
    16  
    17  var funcStack []*ir.Func // stack of previous values of ir.CurFunc
    18  
    19  // DeclFunc declares the parameters for fn and adds it to
    20  // Target.Funcs.
    21  //
    22  // Before returning, it sets CurFunc to fn. When the caller is done
    23  // constructing fn, it must call FinishFuncBody to restore CurFunc.
    24  func DeclFunc(fn *ir.Func) {
    25  	fn.DeclareParams(true)
    26  	fn.Nname.Defn = fn
    27  	Target.Funcs = append(Target.Funcs, fn)
    28  
    29  	funcStack = append(funcStack, ir.CurFunc)
    30  	ir.CurFunc = fn
    31  }
    32  
    33  // FinishFuncBody restores ir.CurFunc to its state before the last
    34  // call to DeclFunc.
    35  func FinishFuncBody() {
    36  	funcStack, ir.CurFunc = funcStack[:len(funcStack)-1], funcStack[len(funcStack)-1]
    37  }
    38  
    39  func CheckFuncStack() {
    40  	if len(funcStack) != 0 {
    41  		base.Fatalf("funcStack is non-empty: %v", len(funcStack))
    42  	}
    43  }
    44  
    45  // make a new Node off the books.
    46  func TempAt(pos src.XPos, curfn *ir.Func, typ *types.Type) *ir.Name {
    47  	if curfn == nil {
    48  		base.FatalfAt(pos, "no curfn for TempAt")
    49  	}
    50  	if typ == nil {
    51  		base.FatalfAt(pos, "TempAt called with nil type")
    52  	}
    53  	if typ.Kind() == types.TFUNC && typ.Recv() != nil {
    54  		base.FatalfAt(pos, "misuse of method type: %v", typ)
    55  	}
    56  	types.CalcSize(typ)
    57  
    58  	sym := &types.Sym{
    59  		Name: autotmpname(len(curfn.Dcl)),
    60  		Pkg:  types.LocalPkg,
    61  	}
    62  	name := curfn.NewLocal(pos, sym, typ)
    63  	name.SetEsc(ir.EscNever)
    64  	name.SetUsed(true)
    65  	name.SetAutoTemp(true)
    66  
    67  	return name
    68  }
    69  
    70  var (
    71  	autotmpnamesmu sync.Mutex
    72  	autotmpnames   []string
    73  )
    74  
    75  // autotmpname returns the name for an autotmp variable numbered n.
    76  func autotmpname(n int) string {
    77  	autotmpnamesmu.Lock()
    78  	defer autotmpnamesmu.Unlock()
    79  
    80  	// Grow autotmpnames, if needed.
    81  	if n >= len(autotmpnames) {
    82  		autotmpnames = append(autotmpnames, make([]string, n+1-len(autotmpnames))...)
    83  		autotmpnames = autotmpnames[:cap(autotmpnames)]
    84  	}
    85  
    86  	s := autotmpnames[n]
    87  	if s == "" {
    88  		// Give each tmp a different name so that they can be registerized.
    89  		// Add a preceding . to avoid clashing with legal names.
    90  		prefix := ".autotmp_%d"
    91  
    92  		s = fmt.Sprintf(prefix, n)
    93  		autotmpnames[n] = s
    94  	}
    95  	return s
    96  }
    97  
    98  // f is method type, with receiver.
    99  // return function type, receiver as first argument (or not).
   100  func NewMethodType(sig *types.Type, recv *types.Type) *types.Type {
   101  	nrecvs := 0
   102  	if recv != nil {
   103  		nrecvs++
   104  	}
   105  
   106  	// TODO(mdempsky): Move this function to types.
   107  	// TODO(mdempsky): Preserve positions, names, and package from sig+recv.
   108  
   109  	params := make([]*types.Field, nrecvs+sig.NumParams())
   110  	if recv != nil {
   111  		params[0] = types.NewField(base.Pos, nil, recv)
   112  	}
   113  	for i, param := range sig.Params() {
   114  		d := types.NewField(base.Pos, nil, param.Type)
   115  		d.SetIsDDD(param.IsDDD())
   116  		params[nrecvs+i] = d
   117  	}
   118  
   119  	results := make([]*types.Field, sig.NumResults())
   120  	for i, t := range sig.Results() {
   121  		results[i] = types.NewField(base.Pos, nil, t.Type)
   122  	}
   123  
   124  	return types.NewSignature(nil, params, results)
   125  }
   126  

View as plain text