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 }