// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. #include "go.h" /* * look for * unsafe.Sizeof * unsafe.Offsetof * rewrite with a constant */ Node* unsafenmagic(Node *fn, NodeList *args) { Node *r, *n; Sym *s; Type *t, *tr; long v; Val val; if(fn == N || fn->op != ONAME || (s = fn->sym) == S) goto no; if(strcmp(s->package, "unsafe") != 0) goto no; if(args == nil) { yyerror("missing argument for %S", s); goto no; } r = args->n; n = nod(OLITERAL, N, N); if(strcmp(s->name, "Sizeof") == 0) { typecheck(&r, Erv); tr = r->type; if(r->op == OLITERAL && r->val.ctype == CTSTR) tr = types[TSTRING]; if(tr == T) goto no; v = tr->width; goto yes; } if(strcmp(s->name, "Offsetof") == 0) { if(r->op != ODOT && r->op != ODOTPTR) goto no; typecheck(&r, Erv); v = r->xoffset; goto yes; } if(strcmp(s->name, "Alignof") == 0) { typecheck(&r, Erv); tr = r->type; if(r->op == OLITERAL && r->val.ctype == CTSTR) tr = types[TSTRING]; if(tr == T) goto no; // make struct { byte; T; } t = typ(TSTRUCT); t->type = typ(TFIELD); t->type->type = types[TUINT8]; t->type->down = typ(TFIELD); t->type->down->type = tr; // compute struct widths dowidth(t); // the offset of T is its required alignment v = t->type->down->width; goto yes; } no: return N; yes: if(args->next != nil) yyerror("extra arguments for %S", s); // any side effects disappear; ignore init val.ctype = CTINT; val.u.xval = mal(sizeof(*n->val.u.xval)); mpmovecfix(val.u.xval, v); n = nod(OLITERAL, N, N); n->val = val; n->type = types[TINT]; return n; }