Commit 5c2666c1 authored by Russ Cox's avatar Russ Cox

gc: unsafe.Pointer is not a pointer

Change unsafe.Pointer to be its own kind of
type, instead of making it equivalent to *any.
The change complicates import and export
but avoids the need to find all the places that
operate on pointers but should not operate on
unsafe.Pointer.

Fixes #1566. (a different way)
Fixes #1582.

R=ken2
CC=golang-dev
https://golang.org/cl/4264050
parent 22c45c55
...@@ -172,6 +172,9 @@ dowidth(Type *t) ...@@ -172,6 +172,9 @@ dowidth(Type *t)
w = 8; w = 8;
checkwidth(t->type); checkwidth(t->type);
break; break;
case TUNSAFEPTR:
w = widthptr;
break;
case TINTER: // implemented as 2 pointers case TINTER: // implemented as 2 pointers
w = 2*widthptr; w = 2*widthptr;
t->align = widthptr; t->align = widthptr;
...@@ -400,6 +403,13 @@ typeinit(void) ...@@ -400,6 +403,13 @@ typeinit(void)
types[TPTR64] = typ(TPTR64); types[TPTR64] = typ(TPTR64);
dowidth(types[TPTR64]); dowidth(types[TPTR64]);
t = typ(TUNSAFEPTR);
types[TUNSAFEPTR] = t;
t->sym = pkglookup("Pointer", unsafepkg);
t->sym->def = typenod(t);
dowidth(types[TUNSAFEPTR]);
tptr = TPTR32; tptr = TPTR32;
if(widthptr == 8) if(widthptr == 8)
...@@ -481,6 +491,7 @@ typeinit(void) ...@@ -481,6 +491,7 @@ typeinit(void)
okforeq[TPTR32] = 1; okforeq[TPTR32] = 1;
okforeq[TPTR64] = 1; okforeq[TPTR64] = 1;
okforeq[TUNSAFEPTR] = 1;
okforeq[TINTER] = 1; okforeq[TINTER] = 1;
okforeq[TMAP] = 1; okforeq[TMAP] = 1;
okforeq[TCHAN] = 1; okforeq[TCHAN] = 1;
...@@ -570,6 +581,7 @@ typeinit(void) ...@@ -570,6 +581,7 @@ typeinit(void)
simtype[TMAP] = tptr; simtype[TMAP] = tptr;
simtype[TCHAN] = tptr; simtype[TCHAN] = tptr;
simtype[TFUNC] = tptr; simtype[TFUNC] = tptr;
simtype[TUNSAFEPTR] = tptr;
/* pick up the backend typedefs */ /* pick up the backend typedefs */
for(i=0; typedefs[i].name; i++) { for(i=0; typedefs[i].name; i++) {
......
...@@ -96,7 +96,7 @@ char *runtimeimport = ...@@ -96,7 +96,7 @@ char *runtimeimport =
"$$\n"; "$$\n";
char *unsafeimport = char *unsafeimport =
"package unsafe\n" "package unsafe\n"
"type \"\".Pointer *any\n" "type \"\".Pointer uintptr\n"
"func \"\".Offsetof (? any) int\n" "func \"\".Offsetof (? any) int\n"
"func \"\".Sizeof (? any) int\n" "func \"\".Sizeof (? any) int\n"
"func \"\".Alignof (? any) int\n" "func \"\".Alignof (? any) int\n"
......
...@@ -155,6 +155,7 @@ convlit1(Node **np, Type *t, int explicit) ...@@ -155,6 +155,7 @@ convlit1(Node **np, Type *t, int explicit)
case TMAP: case TMAP:
case TCHAN: case TCHAN:
case TFUNC: case TFUNC:
case TUNSAFEPTR:
break; break;
} }
break; break;
......
...@@ -656,10 +656,19 @@ typedcl2(Type *pt, Type *t) ...@@ -656,10 +656,19 @@ typedcl2(Type *pt, Type *t)
{ {
Node *n; Node *n;
// override declaration in unsafe.go for Pointer.
// there is no way in Go code to define unsafe.Pointer
// so we have to supply it.
if(incannedimport &&
strcmp(importpkg->name, "unsafe") == 0 &&
strcmp(pt->nod->sym->name, "Pointer") == 0) {
t = types[TUNSAFEPTR];
}
if(pt->etype == TFORW) if(pt->etype == TFORW)
goto ok; goto ok;
if(!eqtype(pt->orig, t)) if(!eqtype(pt->orig, t))
yyerror("inconsistent definition for type %S during import\n\t%lT\n\t%lT", pt->sym, pt, t); yyerror("inconsistent definition for type %S during import\n\t%lT\n\t%lT", pt->sym, pt->orig, t);
return; return;
ok: ok:
......
...@@ -459,9 +459,10 @@ enum ...@@ -459,9 +459,10 @@ enum
TFIELD, TFIELD,
TANY, TANY,
TSTRING, TSTRING,
TUNSAFEPTR,
// pseudo-types for literals // pseudo-types for literals
TIDEAL, // 32 TIDEAL, // 33
TNIL, TNIL,
TBLANK, TBLANK,
......
...@@ -466,6 +466,7 @@ kinds[] = ...@@ -466,6 +466,7 @@ kinds[] =
[TFUNC] = KindFunc, [TFUNC] = KindFunc,
[TCOMPLEX64] = KindComplex64, [TCOMPLEX64] = KindComplex64,
[TCOMPLEX128] = KindComplex128, [TCOMPLEX128] = KindComplex128,
[TUNSAFEPTR] = KindUnsafePointer,
}; };
static char* static char*
...@@ -488,6 +489,7 @@ structnames[] = ...@@ -488,6 +489,7 @@ structnames[] =
[TFLOAT64] = "*runtime.FloatType", [TFLOAT64] = "*runtime.FloatType",
[TBOOL] = "*runtime.BoolType", [TBOOL] = "*runtime.BoolType",
[TSTRING] = "*runtime.StringType", [TSTRING] = "*runtime.StringType",
[TUNSAFEPTR] = "*runtime.UnsafePointerType",
[TPTR32] = "*runtime.PtrType", [TPTR32] = "*runtime.PtrType",
[TPTR64] = "*runtime.PtrType", [TPTR64] = "*runtime.PtrType",
...@@ -514,9 +516,6 @@ typestruct(Type *t) ...@@ -514,9 +516,6 @@ typestruct(Type *t)
if(isslice(t)) if(isslice(t))
name = "*runtime.SliceType"; name = "*runtime.SliceType";
if(isptr[et] && t->type->etype == TANY)
name = "*runtime.UnsafePointerType";
return pkglookup(name, typepkg); return pkglookup(name, typepkg);
} }
...@@ -553,6 +552,7 @@ haspointers(Type *t) ...@@ -553,6 +552,7 @@ haspointers(Type *t)
case TSTRING: case TSTRING:
case TPTR32: case TPTR32:
case TPTR64: case TPTR64:
case TUNSAFEPTR:
case TINTER: case TINTER:
case TCHAN: case TCHAN:
case TMAP: case TMAP:
...@@ -612,8 +612,6 @@ dcommontype(Sym *s, int ot, Type *t) ...@@ -612,8 +612,6 @@ dcommontype(Sym *s, int ot, Type *t)
i = kinds[t->etype]; i = kinds[t->etype];
if(t->etype == TARRAY && t->bound < 0) if(t->etype == TARRAY && t->bound < 0)
i = KindSlice; i = KindSlice;
if(isptr[t->etype] && t->type->etype == TANY)
i = KindUnsafePointer;
if(!haspointers(t)) if(!haspointers(t))
i |= KindNoPointers; i |= KindNoPointers;
ot = duint8(s, ot, i); // kind ot = duint8(s, ot, i); // kind
...@@ -714,12 +712,8 @@ dtypesym(Type *t) ...@@ -714,12 +712,8 @@ dtypesym(Type *t)
tbase = t->type; tbase = t->type;
dupok = tbase->sym == S; dupok = tbase->sym == S;
if(compiling_runtime) { if(compiling_runtime && tbase == types[tbase->etype]) // int, float, etc
if(tbase == types[tbase->etype]) // int, float, etc goto ok;
goto ok;
if(tbase->etype == tptr && tbase->type->etype == TANY) // unsafe.Pointer
goto ok;
}
// named types from other files are defined only by those files // named types from other files are defined only by those files
if(tbase->sym && !tbase->local) if(tbase->sym && !tbase->local)
...@@ -908,7 +902,7 @@ dumptypestructs(void) ...@@ -908,7 +902,7 @@ dumptypestructs(void)
for(i=1; i<=TBOOL; i++) for(i=1; i<=TBOOL; i++)
dtypesym(ptrto(types[i])); dtypesym(ptrto(types[i]));
dtypesym(ptrto(types[TSTRING])); dtypesym(ptrto(types[TSTRING]));
dtypesym(ptrto(pkglookup("Pointer", unsafepkg)->def->type)); dtypesym(ptrto(types[TUNSAFEPTR]));
// add paths for runtime and main, which 6l imports implicitly. // add paths for runtime and main, which 6l imports implicitly.
dimportpath(runtimepkg); dimportpath(runtimepkg);
......
...@@ -1144,7 +1144,7 @@ Tpretty(Fmt *fp, Type *t) ...@@ -1144,7 +1144,7 @@ Tpretty(Fmt *fp, Type *t)
&& t->sym != S && t->sym != S
&& !(fp->flags&FmtLong)) { && !(fp->flags&FmtLong)) {
s = t->sym; s = t->sym;
if(t == types[t->etype]) if(t == types[t->etype] && t->etype != TUNSAFEPTR)
return fmtprint(fp, "%s", s->name); return fmtprint(fp, "%s", s->name);
if(exporting) { if(exporting) {
if(fp->flags & FmtShort) if(fp->flags & FmtShort)
...@@ -1304,6 +1304,11 @@ Tpretty(Fmt *fp, Type *t) ...@@ -1304,6 +1304,11 @@ Tpretty(Fmt *fp, Type *t)
if(t->sym) if(t->sym)
return fmtprint(fp, "undefined %S", t->sym); return fmtprint(fp, "undefined %S", t->sym);
return fmtprint(fp, "undefined"); return fmtprint(fp, "undefined");
case TUNSAFEPTR:
if(exporting)
return fmtprint(fp, "\"unsafe\".Pointer");
return fmtprint(fp, "unsafe.Pointer");
} }
// Don't know how to handle - fall back to detailed prints. // Don't know how to handle - fall back to detailed prints.
...@@ -1346,6 +1351,9 @@ Tconv(Fmt *fp) ...@@ -1346,6 +1351,9 @@ Tconv(Fmt *fp)
} }
} }
if(sharp || exporting)
fatal("missing %E case during export", t->etype);
et = t->etype; et = t->etype;
fmtprint(fp, "%E ", et); fmtprint(fp, "%E ", et);
if(t->sym != S) if(t->sym != S)
...@@ -1864,7 +1872,7 @@ assignop(Type *src, Type *dst, char **why) ...@@ -1864,7 +1872,7 @@ assignop(Type *src, Type *dst, char **why)
if(why != nil) if(why != nil)
*why = ""; *why = "";
if(safemode && (isptrto(src, TANY) || isptrto(dst, TANY))) { if(safemode && src != T && src->etype == TUNSAFEPTR) {
yyerror("cannot use unsafe.Pointer"); yyerror("cannot use unsafe.Pointer");
errorexit(); errorexit();
} }
...@@ -2028,11 +2036,11 @@ convertop(Type *src, Type *dst, char **why) ...@@ -2028,11 +2036,11 @@ convertop(Type *src, Type *dst, char **why)
} }
// 8. src is a pointer or uintptr and dst is unsafe.Pointer. // 8. src is a pointer or uintptr and dst is unsafe.Pointer.
if((isptr[src->etype] || src->etype == TUINTPTR) && isptrto(dst, TANY)) if((isptr[src->etype] || src->etype == TUINTPTR) && dst->etype == TUNSAFEPTR)
return OCONVNOP; return OCONVNOP;
// 9. src is unsafe.Pointer and dst is a pointer or uintptr. // 9. src is unsafe.Pointer and dst is a pointer or uintptr.
if(isptrto(src, TANY) && (isptr[dst->etype] || dst->etype == TUINTPTR)) if(src->etype == TUNSAFEPTR && (isptr[dst->etype] || dst->etype == TUINTPTR))
return OCONVNOP; return OCONVNOP;
return 0; return 0;
......
...@@ -318,7 +318,7 @@ reswitch: ...@@ -318,7 +318,7 @@ reswitch:
n->left = N; n->left = N;
goto ret; goto ret;
} }
if(!isptr[t->etype] || (t->type != T && t->type->etype == TANY) /* unsafe.Pointer */) { if(!isptr[t->etype]) {
yyerror("invalid indirect of %+N", n->left); yyerror("invalid indirect of %+N", n->left);
goto error; goto error;
} }
...@@ -1316,7 +1316,7 @@ ret: ...@@ -1316,7 +1316,7 @@ ret:
// TODO(rsc): should not need to check importpkg, // TODO(rsc): should not need to check importpkg,
// but reflect mentions unsafe.Pointer. // but reflect mentions unsafe.Pointer.
if(safemode && !incannedimport && !importpkg && isptrto(t, TANY)) if(safemode && !incannedimport && !importpkg && t->etype == TUNSAFEPTR)
yyerror("cannot use unsafe.Pointer"); yyerror("cannot use unsafe.Pointer");
evconst(n); evconst(n);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
package PACKAGE package PACKAGE
type Pointer *any type Pointer uintptr // not really; filled in by compiler
func Offsetof(any) int func Offsetof(any) int
func Sizeof(any) int func Sizeof(any) int
......
...@@ -11,4 +11,5 @@ import "unsafe" ...@@ -11,4 +11,5 @@ import "unsafe"
func main() { func main() {
var x unsafe.Pointer var x unsafe.Pointer
println(*x) // ERROR "invalid indirect.*unsafe.Pointer" println(*x) // ERROR "invalid indirect.*unsafe.Pointer"
var _ = (unsafe.Pointer)(nil).foo // ERROR "no field or method foo"
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment