github.com/razvanm/vanadium-go-1.3@v0.0.0-20160721203343-4a65068e5915/src/cmd/gc/unsafe.c (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 #include <u.h> 6 #include <libc.h> 7 #include "go.h" 8 9 /* 10 * look for 11 * unsafe.Sizeof 12 * unsafe.Offsetof 13 * unsafe.Alignof 14 * rewrite with a constant 15 */ 16 Node* 17 unsafenmagic(Node *nn) 18 { 19 Node *r, *n, *base, *r1; 20 Sym *s; 21 Type *t, *tr; 22 vlong v; 23 Val val; 24 Node *fn; 25 NodeList *args; 26 27 fn = nn->left; 28 args = nn->list; 29 30 if(safemode || fn == N || fn->op != ONAME || (s = fn->sym) == S) 31 goto no; 32 if(s->pkg != unsafepkg) 33 goto no; 34 35 if(args == nil) { 36 yyerror("missing argument for %S", s); 37 goto no; 38 } 39 r = args->n; 40 41 if(strcmp(s->name, "Sizeof") == 0) { 42 typecheck(&r, Erv); 43 defaultlit(&r, T); 44 tr = r->type; 45 if(tr == T) 46 goto bad; 47 dowidth(tr); 48 v = tr->width; 49 goto yes; 50 } 51 if(strcmp(s->name, "Offsetof") == 0) { 52 // must be a selector. 53 if(r->op != OXDOT) 54 goto bad; 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 base = r->left; 60 typecheck(&r, Erv); 61 switch(r->op) { 62 case ODOT: 63 case ODOTPTR: 64 break; 65 case OCALLPART: 66 yyerror("invalid expression %N: argument is a method value", nn); 67 v = 0; 68 goto ret; 69 default: 70 goto bad; 71 } 72 v = 0; 73 // add offsets for inserted dots. 74 for(r1=r; r1->left!=base; r1=r1->left) { 75 switch(r1->op) { 76 case ODOT: 77 v += r1->xoffset; 78 break; 79 case ODOTPTR: 80 yyerror("invalid expression %N: selector implies indirection of embedded %N", nn, r1->left); 81 goto ret; 82 default: 83 dump("unsafenmagic", r); 84 fatal("impossible %#O node after dot insertion", r1->op); 85 goto bad; 86 } 87 } 88 v += r1->xoffset; 89 goto yes; 90 } 91 if(strcmp(s->name, "Alignof") == 0) { 92 typecheck(&r, Erv); 93 defaultlit(&r, T); 94 tr = r->type; 95 if(tr == T) 96 goto bad; 97 98 // make struct { byte; T; } 99 t = typ(TSTRUCT); 100 t->type = typ(TFIELD); 101 t->type->type = types[TUINT8]; 102 t->type->down = typ(TFIELD); 103 t->type->down->type = tr; 104 // compute struct widths 105 dowidth(t); 106 107 // the offset of T is its required alignment 108 v = t->type->down->width; 109 goto yes; 110 } 111 112 no: 113 return N; 114 115 bad: 116 yyerror("invalid expression %N", nn); 117 v = 0; 118 goto ret; 119 120 yes: 121 if(args->next != nil) 122 yyerror("extra arguments for %S", s); 123 ret: 124 // any side effects disappear; ignore init 125 val.ctype = CTINT; 126 val.u.xval = mal(sizeof(*n->val.u.xval)); 127 mpmovecfix(val.u.xval, v); 128 n = nod(OLITERAL, N, N); 129 n->orig = nn; 130 n->val = val; 131 n->type = types[TUINTPTR]; 132 nn->type = types[TUINTPTR]; 133 return n; 134 } 135 136 int 137 isunsafebuiltin(Node *n) 138 { 139 if(n == N || n->op != ONAME || n->sym == S || n->sym->pkg != unsafepkg) 140 return 0; 141 if(strcmp(n->sym->name, "Sizeof") == 0) 142 return 1; 143 if(strcmp(n->sym->name, "Offsetof") == 0) 144 return 1; 145 if(strcmp(n->sym->name, "Alignof") == 0) 146 return 1; 147 return 0; 148 }