summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cmd/gc/dcl.c51
-rw-r--r--src/cmd/gc/go.h1
-rw-r--r--src/cmd/gc/go.y4
-rw-r--r--src/cmd/gc/unsafe.go2
4 files changed, 57 insertions, 1 deletions
diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c
index 9f7244fc7..d5d3a9bf4 100644
--- a/src/cmd/gc/dcl.c
+++ b/src/cmd/gc/dcl.c
@@ -1483,3 +1483,54 @@ loop:
c = listnext(&citer);
goto loop;
}
+
+/*
+ * look for
+ * unsafe.Sizeof
+ * unsafe.Offsetof
+ * rewrite with a constant
+ */
+Node*
+unsafenmagic(Node *l, Node *r)
+{
+ Node *n;
+ Sym *s;
+ long v;
+ Val val;
+
+ if(l == N || r == N)
+ goto no;
+ if(l->op != ONAME)
+ goto no;
+ s = l->sym;
+ if(s == S)
+ goto no;
+ if(strcmp(s->opackage, "unsafe") != 0)
+ goto no;
+
+ if(strcmp(s->name, "Sizeof") == 0) {
+ walktype(r, Erv);
+ if(r->type == T)
+ goto no;
+ v = r->type->width;
+ goto yes;
+ }
+ if(strcmp(s->name, "Offsetof") == 0) {
+ if(r->op != ODOT && r->op != ODOTPTR)
+ goto no;
+ walktype(r, Erv);
+ v = n->xoffset;
+ goto yes;
+ }
+
+no:
+ return N;
+
+yes:
+ 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;
+ return n;
+}
diff --git a/src/cmd/gc/go.h b/src/cmd/gc/go.h
index 7b861d38c..436ddd9a9 100644
--- a/src/cmd/gc/go.h
+++ b/src/cmd/gc/go.h
@@ -763,6 +763,7 @@ void constiter(Node*, Type*, Node*);
void funclit0(Type*);
Node* funclit1(Type*, Node*);
+Node* unsafenmagic(Node*, Node*);
/*
* export.c
diff --git a/src/cmd/gc/go.y b/src/cmd/gc/go.y
index 5ed7ed09c..29a08912d 100644
--- a/src/cmd/gc/go.y
+++ b/src/cmd/gc/go.y
@@ -804,7 +804,9 @@ pexpr:
}
| pexpr '(' oexpr_list ')'
{
- $$ = nod(OCALL, $1, $3);
+ $$ = unsafenmagic($1, $3);
+ if($$ == N)
+ $$ = nod(OCALL, $1, $3);
}
| LLEN '(' expr ')'
{
diff --git a/src/cmd/gc/unsafe.go b/src/cmd/gc/unsafe.go
index 2b2187b3e..47703f6e0 100644
--- a/src/cmd/gc/unsafe.go
+++ b/src/cmd/gc/unsafe.go
@@ -6,3 +6,5 @@
package PACKAGE
type Pointer *any;
+func Offsetof(any) int;
+func Sizeof(any) int;