github.com/q45/go@v0.0.0-20151101211701-a4fb8c13db3f/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 import "cmd/internal/obj" 8 9 // look for 10 // unsafe.Sizeof 11 // unsafe.Offsetof 12 // unsafe.Alignof 13 // rewrite with a constant 14 func unsafenmagic(nn *Node) *Node { 15 fn := nn.Left 16 args := nn.List 17 18 if safemode != 0 || fn == nil || fn.Op != ONAME { 19 return nil 20 } 21 s := fn.Sym 22 if s == nil { 23 return nil 24 } 25 if s.Pkg != unsafepkg { 26 return nil 27 } 28 29 if args == nil { 30 Yyerror("missing argument for %v", s) 31 return nil 32 } 33 34 r := args.N 35 36 var v int64 37 if s.Name == "Sizeof" { 38 typecheck(&r, Erv) 39 defaultlit(&r, nil) 40 tr := r.Type 41 if tr == nil { 42 goto bad 43 } 44 dowidth(tr) 45 v = tr.Width 46 goto yes 47 } 48 49 if s.Name == "Offsetof" { 50 // must be a selector. 51 if r.Op != OXDOT { 52 goto bad 53 } 54 55 // Remember base of selector to find it back after dot insertion. 56 // Since r->left may be mutated by typechecking, check it explicitly 57 // first to track it correctly. 58 typecheck(&r.Left, Erv) 59 60 base := r.Left 61 typecheck(&r, Erv) 62 switch r.Op { 63 case ODOT, ODOTPTR: 64 break 65 66 case OCALLPART: 67 Yyerror("invalid expression %v: argument is a method value", nn) 68 v = 0 69 goto ret 70 71 default: 72 goto bad 73 } 74 75 v = 0 76 77 // add offsets for inserted dots. 78 var r1 *Node 79 for r1 = r; r1.Left != base; r1 = r1.Left { 80 switch r1.Op { 81 case ODOT: 82 v += r1.Xoffset 83 84 case ODOTPTR: 85 Yyerror("invalid expression %v: selector implies indirection of embedded %v", nn, r1.Left) 86 goto ret 87 88 default: 89 Dump("unsafenmagic", r) 90 Fatalf("impossible %v node after dot insertion", Oconv(int(r1.Op), obj.FmtSharp)) 91 goto bad 92 } 93 } 94 95 v += r1.Xoffset 96 goto yes 97 } 98 99 if s.Name == "Alignof" { 100 typecheck(&r, Erv) 101 defaultlit(&r, nil) 102 tr := r.Type 103 if tr == nil { 104 goto bad 105 } 106 107 // make struct { byte; T; } 108 t := typ(TSTRUCT) 109 110 t.Type = typ(TFIELD) 111 t.Type.Type = Types[TUINT8] 112 t.Type.Down = typ(TFIELD) 113 t.Type.Down.Type = tr 114 115 // compute struct widths 116 dowidth(t) 117 118 // the offset of T is its required alignment 119 v = t.Type.Down.Width 120 121 goto yes 122 } 123 124 return nil 125 126 bad: 127 Yyerror("invalid expression %v", nn) 128 v = 0 129 goto ret 130 131 yes: 132 if args.Next != nil { 133 Yyerror("extra arguments for %v", s) 134 } 135 136 // any side effects disappear; ignore init 137 ret: 138 var val Val 139 val.U = new(Mpint) 140 Mpmovecfix(val.U.(*Mpint), v) 141 n := Nod(OLITERAL, nil, nil) 142 n.Orig = nn 143 n.SetVal(val) 144 n.Type = Types[TUINTPTR] 145 nn.Type = Types[TUINTPTR] 146 return n 147 } 148 149 func isunsafebuiltin(n *Node) bool { 150 if n == nil || n.Op != ONAME || n.Sym == nil || n.Sym.Pkg != unsafepkg { 151 return false 152 } 153 if n.Sym.Name == "Sizeof" { 154 return true 155 } 156 if n.Sym.Name == "Offsetof" { 157 return true 158 } 159 if n.Sym.Name == "Alignof" { 160 return true 161 } 162 return false 163 }