github.com/bir3/gocompiler@v0.3.205/src/cmd/compile/internal/escape/stmt.go (about)

     1  // Copyright 2018 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 escape
     6  
     7  import (
     8  	"github.com/bir3/gocompiler/src/cmd/compile/internal/base"
     9  	"github.com/bir3/gocompiler/src/cmd/compile/internal/ir"
    10  	"fmt"
    11  )
    12  
    13  // stmt evaluates a single Go statement.
    14  func (e *escape) stmt(n ir.Node) {
    15  	if n == nil {
    16  		return
    17  	}
    18  
    19  	lno := ir.SetPos(n)
    20  	defer func() {
    21  		base.Pos = lno
    22  	}()
    23  
    24  	if base.Flag.LowerM > 2 {
    25  		fmt.Printf("%v:[%d] %v stmt: %v\n", base.FmtPos(base.Pos), e.loopDepth, e.curfn, n)
    26  	}
    27  
    28  	e.stmts(n.Init())
    29  
    30  	switch n.Op() {
    31  	default:
    32  		base.Fatalf("unexpected stmt: %v", n)
    33  
    34  	case ir.ODCLCONST, ir.ODCLTYPE, ir.OFALL, ir.OINLMARK:
    35  		// nop
    36  
    37  	case ir.OBREAK, ir.OCONTINUE, ir.OGOTO:
    38  		// TODO(mdempsky): Handle dead code?
    39  
    40  	case ir.OBLOCK:
    41  		n := n.(*ir.BlockStmt)
    42  		e.stmts(n.List)
    43  
    44  	case ir.ODCL:
    45  		// Record loop depth at declaration.
    46  		n := n.(*ir.Decl)
    47  		if !ir.IsBlank(n.X) {
    48  			e.dcl(n.X)
    49  		}
    50  
    51  	case ir.OLABEL:
    52  		n := n.(*ir.LabelStmt)
    53  		if n.Label.IsBlank() {
    54  			break
    55  		}
    56  		switch e.labels[n.Label] {
    57  		case nonlooping:
    58  			if base.Flag.LowerM > 2 {
    59  				fmt.Printf("%v:%v non-looping label\n", base.FmtPos(base.Pos), n)
    60  			}
    61  		case looping:
    62  			if base.Flag.LowerM > 2 {
    63  				fmt.Printf("%v: %v looping label\n", base.FmtPos(base.Pos), n)
    64  			}
    65  			e.loopDepth++
    66  		default:
    67  			base.Fatalf("label missing tag")
    68  		}
    69  		delete(e.labels, n.Label)
    70  
    71  	case ir.OIF:
    72  		n := n.(*ir.IfStmt)
    73  		e.discard(n.Cond)
    74  		e.block(n.Body)
    75  		e.block(n.Else)
    76  
    77  	case ir.OCHECKNIL:
    78  		n := n.(*ir.UnaryExpr)
    79  		e.discard(n.X)
    80  
    81  	case ir.OFOR:
    82  		n := n.(*ir.ForStmt)
    83  		e.loopDepth++
    84  		e.discard(n.Cond)
    85  		e.stmt(n.Post)
    86  		e.block(n.Body)
    87  		e.loopDepth--
    88  
    89  	case ir.ORANGE:
    90  		// for Key, Value = range X { Body }
    91  		n := n.(*ir.RangeStmt)
    92  
    93  		// X is evaluated outside the loop.
    94  		tmp := e.newLoc(nil, false)
    95  		e.expr(tmp.asHole(), n.X)
    96  
    97  		e.loopDepth++
    98  		ks := e.addrs([]ir.Node{n.Key, n.Value})
    99  		if n.X.Type().IsArray() {
   100  			e.flow(ks[1].note(n, "range"), tmp)
   101  		} else {
   102  			e.flow(ks[1].deref(n, "range-deref"), tmp)
   103  		}
   104  		e.reassigned(ks, n)
   105  
   106  		e.block(n.Body)
   107  		e.loopDepth--
   108  
   109  	case ir.OSWITCH:
   110  		n := n.(*ir.SwitchStmt)
   111  
   112  		if guard, ok := n.Tag.(*ir.TypeSwitchGuard); ok {
   113  			var ks []hole
   114  			if guard.Tag != nil {
   115  				for _, cas := range n.Cases {
   116  					cv := cas.Var
   117  					k := e.dcl(cv) // type switch variables have no ODCL.
   118  					if cv.Type().HasPointers() {
   119  						ks = append(ks, k.dotType(cv.Type(), cas, "switch case"))
   120  					}
   121  				}
   122  			}
   123  			e.expr(e.teeHole(ks...), n.Tag.(*ir.TypeSwitchGuard).X)
   124  		} else {
   125  			e.discard(n.Tag)
   126  		}
   127  
   128  		for _, cas := range n.Cases {
   129  			e.discards(cas.List)
   130  			e.block(cas.Body)
   131  		}
   132  
   133  	case ir.OSELECT:
   134  		n := n.(*ir.SelectStmt)
   135  		for _, cas := range n.Cases {
   136  			e.stmt(cas.Comm)
   137  			e.block(cas.Body)
   138  		}
   139  	case ir.ORECV:
   140  		// TODO(mdempsky): Consider e.discard(n.Left).
   141  		n := n.(*ir.UnaryExpr)
   142  		e.exprSkipInit(e.discardHole(), n) // already visited n.Ninit
   143  	case ir.OSEND:
   144  		n := n.(*ir.SendStmt)
   145  		e.discard(n.Chan)
   146  		e.assignHeap(n.Value, "send", n)
   147  
   148  	case ir.OAS:
   149  		n := n.(*ir.AssignStmt)
   150  		e.assignList([]ir.Node{n.X}, []ir.Node{n.Y}, "assign", n)
   151  	case ir.OASOP:
   152  		n := n.(*ir.AssignOpStmt)
   153  		// TODO(mdempsky): Worry about OLSH/ORSH?
   154  		e.assignList([]ir.Node{n.X}, []ir.Node{n.Y}, "assign", n)
   155  	case ir.OAS2:
   156  		n := n.(*ir.AssignListStmt)
   157  		e.assignList(n.Lhs, n.Rhs, "assign-pair", n)
   158  
   159  	case ir.OAS2DOTTYPE: // v, ok = x.(type)
   160  		n := n.(*ir.AssignListStmt)
   161  		e.assignList(n.Lhs, n.Rhs, "assign-pair-dot-type", n)
   162  	case ir.OAS2MAPR: // v, ok = m[k]
   163  		n := n.(*ir.AssignListStmt)
   164  		e.assignList(n.Lhs, n.Rhs, "assign-pair-mapr", n)
   165  	case ir.OAS2RECV, ir.OSELRECV2: // v, ok = <-ch
   166  		n := n.(*ir.AssignListStmt)
   167  		e.assignList(n.Lhs, n.Rhs, "assign-pair-receive", n)
   168  
   169  	case ir.OAS2FUNC:
   170  		n := n.(*ir.AssignListStmt)
   171  		e.stmts(n.Rhs[0].Init())
   172  		ks := e.addrs(n.Lhs)
   173  		e.call(ks, n.Rhs[0])
   174  		e.reassigned(ks, n)
   175  	case ir.ORETURN:
   176  		n := n.(*ir.ReturnStmt)
   177  		results := e.curfn.Type().Results().FieldSlice()
   178  		dsts := make([]ir.Node, len(results))
   179  		for i, res := range results {
   180  			dsts[i] = res.Nname.(*ir.Name)
   181  		}
   182  		e.assignList(dsts, n.Results, "return", n)
   183  	case ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER, ir.OINLCALL, ir.OCLOSE, ir.OCOPY, ir.ODELETE, ir.OPANIC, ir.OPRINT, ir.OPRINTN, ir.ORECOVER:
   184  		e.call(nil, n)
   185  	case ir.OGO, ir.ODEFER:
   186  		n := n.(*ir.GoDeferStmt)
   187  		e.goDeferStmt(n)
   188  
   189  	case ir.OTAILCALL:
   190  		n := n.(*ir.TailCallStmt)
   191  		e.call(nil, n.Call)
   192  	}
   193  }
   194  
   195  func (e *escape) stmts(l ir.Nodes) {
   196  	for _, n := range l {
   197  		e.stmt(n)
   198  	}
   199  }
   200  
   201  // block is like stmts, but preserves loopDepth.
   202  func (e *escape) block(l ir.Nodes) {
   203  	old := e.loopDepth
   204  	e.stmts(l)
   205  	e.loopDepth = old
   206  }
   207  
   208  func (e *escape) dcl(n *ir.Name) hole {
   209  	if n.Curfn != e.curfn || n.IsClosureVar() {
   210  		base.Fatalf("bad declaration of %v", n)
   211  	}
   212  	loc := e.oldLoc(n)
   213  	loc.loopDepth = e.loopDepth
   214  	return loc.asHole()
   215  }