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  // TempAt makes a new Node off the books.
    46  //
    47  // N.B., the new Node is a function-local variable defaulting to function scope.
    48  // It helps in some cases if an ODCL is also created and placed in a narrower scope,
    49  // such as if the variable can be used in a loop body and potentially escape.
    50  // TODO: Consider some mechanism to more conveniently create a block scoped temporary.
    51  func TempAt(pos src.XPos, curfn *ir.Func, typ *types.Type) *ir.Name {
    52  	if curfn == nil {
    53  		base.FatalfAt(pos, "no curfn for TempAt")
    54  	}
    55  	if typ == nil {
    56  		base.FatalfAt(pos, "TempAt called with nil type")
    57  	}
    58  	if typ.Kind() == types.TFUNC && typ.Recv() != nil {
    59  		base.FatalfAt(pos, "misuse of method type: %v", typ)
    60  	}
    61  	types.CalcSize(typ)
    62  
    63  	sym := &types.Sym{
    64  		Name: autotmpname(len(curfn.Dcl)),
    65  		Pkg:  types.LocalPkg,
    66  	}
    67  	name := curfn.NewLocal(pos, sym, typ)
    68  	name.SetEsc(ir.EscNever)
    69  	name.SetUsed(true)
    70  	name.SetAutoTemp(true)
    71  
    72  	return name
    73  }
    74  
    75  var (
    76  	autotmpnamesmu sync.Mutex
    77  	autotmpnames   []string
    78  )
    79  
    80  // autotmpname returns the name for an autotmp variable numbered n.
    81  func autotmpname(n int) string {
    82  	autotmpnamesmu.Lock()
    83  	defer autotmpnamesmu.Unlock()
    84  
    85  	// Grow autotmpnames, if needed.
    86  	if n >= len(autotmpnames) {
    87  		autotmpnames = append(autotmpnames, make([]string, n+1-len(autotmpnames))...)
    88  		autotmpnames = autotmpnames[:cap(autotmpnames)]
    89  	}
    90  
    91  	s := autotmpnames[n]
    92  	if s == "" {
    93  		// Give each tmp a different name so that they can be registerized.
    94  		// Add a preceding . to avoid clashing with legal names.
    95  		prefix := ".autotmp_%d"
    96  
    97  		s = fmt.Sprintf(prefix, n)
    98  		autotmpnames[n] = s
    99  	}
   100  	return s
   101  }
   102  
   103  // f is method type, with receiver.
   104  // return function type, receiver as first argument (or not).
   105  func NewMethodType(sig *types.Type, recv *types.Type) *types.Type {
   106  	nrecvs := 0
   107  	if recv != nil {
   108  		nrecvs++
   109  	}
   110  
   111  	// TODO(mdempsky): Move this function to types.
   112  	// TODO(mdempsky): Preserve positions, names, and package from sig+recv.
   113  
   114  	params := make([]*types.Field, nrecvs+sig.NumParams())
   115  	if recv != nil {
   116  		params[0] = types.NewField(base.Pos, nil, recv)
   117  	}
   118  	for i, param := range sig.Params() {
   119  		d := types.NewField(base.Pos, nil, param.Type)
   120  		d.SetIsDDD(param.IsDDD())
   121  		params[nrecvs+i] = d
   122  	}
   123  
   124  	results := make([]*types.Field, sig.NumResults())
   125  	for i, t := range sig.Results() {
   126  		results[i] = types.NewField(base.Pos, nil, t.Type)
   127  	}
   128  
   129  	return types.NewSignature(nil, params, results)
   130  }
   131  

View as plain text