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