github.com/tidwall/go@v0.0.0-20170415222209-6694a6888b7d/src/cmd/compile/internal/gc/unsafe.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  // evalunsafe evaluates a package unsafe operation and returns the result.
     8  func evalunsafe(n *Node) int64 {
     9  	switch n.Op {
    10  	case OALIGNOF, OSIZEOF:
    11  		n.Left = typecheck(n.Left, Erv)
    12  		n.Left = defaultlit(n.Left, nil)
    13  		tr := n.Left.Type
    14  		if tr == nil {
    15  			yyerror("invalid expression %v", n)
    16  			return 0
    17  		}
    18  		dowidth(tr)
    19  		if n.Op == OALIGNOF {
    20  			return int64(tr.Align)
    21  		}
    22  		return tr.Width
    23  
    24  	case OOFFSETOF:
    25  		// must be a selector.
    26  		if n.Left.Op != OXDOT {
    27  			yyerror("invalid expression %v", n)
    28  			return 0
    29  		}
    30  
    31  		// Remember base of selector to find it back after dot insertion.
    32  		// Since r->left may be mutated by typechecking, check it explicitly
    33  		// first to track it correctly.
    34  		n.Left.Left = typecheck(n.Left.Left, Erv)
    35  		base := n.Left.Left
    36  
    37  		n.Left = typecheck(n.Left, Erv)
    38  		switch n.Left.Op {
    39  		case ODOT, ODOTPTR:
    40  			break
    41  		case OCALLPART:
    42  			yyerror("invalid expression %v: argument is a method value", n)
    43  			return 0
    44  		default:
    45  			yyerror("invalid expression %v", n)
    46  			return 0
    47  		}
    48  
    49  		// Sum offsets for dots until we reach base.
    50  		var v int64
    51  		for r := n.Left; r != base; r = r.Left {
    52  			switch r.Op {
    53  			case ODOTPTR:
    54  				// For Offsetof(s.f), s may itself be a pointer,
    55  				// but accessing f must not otherwise involve
    56  				// indirection via embedded pointer types.
    57  				if r.Left != base {
    58  					yyerror("invalid expression %v: selector implies indirection of embedded %v", n, r.Left)
    59  					return 0
    60  				}
    61  				fallthrough
    62  			case ODOT:
    63  				v += r.Xoffset
    64  			default:
    65  				Dump("unsafenmagic", n.Left)
    66  				Fatalf("impossible %#v node after dot insertion", r.Op)
    67  			}
    68  		}
    69  		return v
    70  	}
    71  
    72  	Fatalf("unexpected op %v", n.Op)
    73  	return 0
    74  }