summaryrefslogtreecommitdiff
path: root/src/cmd/gc/unsafe.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/gc/unsafe.c')
-rw-r--r--src/cmd/gc/unsafe.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/src/cmd/gc/unsafe.c b/src/cmd/gc/unsafe.c
new file mode 100644
index 000000000..9c1f9519a
--- /dev/null
+++ b/src/cmd/gc/unsafe.c
@@ -0,0 +1,87 @@
+// 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;
+}