github.com/mh-cbon/go@v0.0.0-20160603070303-9e112a3fe4c0/src/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 // unsafenmagic rewrites calls to package unsafe's functions into constants. 8 func unsafenmagic(nn *Node) *Node { 9 fn := nn.Left 10 args := nn.List 11 12 if safemode || fn == nil || fn.Op != ONAME { 13 return nil 14 } 15 s := fn.Sym 16 if s == nil { 17 return nil 18 } 19 if s.Pkg != unsafepkg { 20 return nil 21 } 22 23 if args.Len() == 0 { 24 Yyerror("missing argument for %v", s) 25 return nil 26 } 27 28 r := args.First() 29 30 var v int64 31 switch s.Name { 32 case "Alignof", "Sizeof": 33 r = typecheck(r, Erv) 34 r = defaultlit(r, nil) 35 tr := r.Type 36 if tr == nil { 37 goto bad 38 } 39 dowidth(tr) 40 if s.Name == "Alignof" { 41 v = int64(tr.Align) 42 } else { 43 v = tr.Width 44 } 45 46 case "Offsetof": 47 // must be a selector. 48 if r.Op != OXDOT { 49 goto bad 50 } 51 52 // Remember base of selector to find it back after dot insertion. 53 // Since r->left may be mutated by typechecking, check it explicitly 54 // first to track it correctly. 55 r.Left = typecheck(r.Left, Erv) 56 base := r.Left 57 58 r = typecheck(r, Erv) 59 switch r.Op { 60 case ODOT, ODOTPTR: 61 break 62 case OCALLPART: 63 Yyerror("invalid expression %v: argument is a method value", nn) 64 goto ret 65 default: 66 goto bad 67 } 68 69 // Sum offsets for dots until we reach base. 70 for r1 := r; r1 != base; r1 = r1.Left { 71 switch r1.Op { 72 case ODOTPTR: 73 // For Offsetof(s.f), s may itself be a pointer, 74 // but accessing f must not otherwise involve 75 // indirection via embedded pointer types. 76 if r1.Left != base { 77 Yyerror("invalid expression %v: selector implies indirection of embedded %v", nn, r1.Left) 78 goto ret 79 } 80 fallthrough 81 case ODOT: 82 v += r1.Xoffset 83 default: 84 Dump("unsafenmagic", r) 85 Fatalf("impossible %#v node after dot insertion", r1.Op) 86 goto bad 87 } 88 } 89 90 default: 91 return nil 92 } 93 94 if args.Len() > 1 { 95 Yyerror("extra arguments for %v", s) 96 } 97 goto ret 98 99 bad: 100 Yyerror("invalid expression %v", nn) 101 102 ret: 103 // any side effects disappear; ignore init 104 var val Val 105 val.U = new(Mpint) 106 val.U.(*Mpint).SetInt64(v) 107 n := Nod(OLITERAL, nil, nil) 108 n.Orig = nn 109 n.SetVal(val) 110 n.Type = Types[TUINTPTR] 111 nn.Type = Types[TUINTPTR] 112 return n 113 } 114 115 func isunsafebuiltin(n *Node) bool { 116 if n == nil || n.Op != ONAME || n.Sym == nil || n.Sym.Pkg != unsafepkg { 117 return false 118 } 119 if n.Sym.Name == "Sizeof" { 120 return true 121 } 122 if n.Sym.Name == "Offsetof" { 123 return true 124 } 125 if n.Sym.Name == "Alignof" { 126 return true 127 } 128 return false 129 }