// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package gc // evalunsafe evaluates a package unsafe operation and returns the result. func evalunsafe(n *Node) int64 { switch n.Op { case OALIGNOF, OSIZEOF: n.Left = typecheck(n.Left, ctxExpr) n.Left = defaultlit(n.Left, nil) tr := n.Left.Type if tr == nil { return 0 } dowidth(tr) if n.Op == OALIGNOF { return int64(tr.Align) } return tr.Width case OOFFSETOF: // must be a selector. if n.Left.Op != OXDOT { yyerror("invalid expression %v", n) return 0 } // Remember base of selector to find it back after dot insertion. // Since r->left may be mutated by typechecking, check it explicitly // first to track it correctly. n.Left.Left = typecheck(n.Left.Left, ctxExpr) base := n.Left.Left n.Left = typecheck(n.Left, ctxExpr) if n.Left.Type == nil { return 0 } switch n.Left.Op { case ODOT, ODOTPTR: break case OCALLPART: yyerror("invalid expression %v: argument is a method value", n) return 0 default: yyerror("invalid expression %v", n) return 0 } // Sum offsets for dots until we reach base. var v int64 for r := n.Left; r != base; r = r.Left { switch r.Op { case ODOTPTR: // For Offsetof(s.f), s may itself be a pointer, // but accessing f must not otherwise involve // indirection via embedded pointer types. if r.Left != base { yyerror("invalid expression %v: selector implies indirection of embedded %v", n, r.Left) return 0 } fallthrough case ODOT: v += r.Xoffset default: Dump("unsafenmagic", n.Left) Fatalf("impossible %#v node after dot insertion", r.Op) } } return v } Fatalf("unexpected op %v", n.Op) return 0 }