diff --git a/src/cmd/gc/dcl.c b/src/cmd/gc/dcl.c index 9f7244fc7ca..d5d3a9bf4df 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 7b861d38c26..436ddd9a9b9 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 5ed7ed09c9f..29a08912d4a 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 2b2187b3e3b..47703f6e0ff 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;