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