Home | History | Annotate | Download | only in gc
      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 }
     75