github.com/zach-klippenstein/go@v0.0.0-20150108044943-fcfbeb3adf58/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  }