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