1
0
mirror of https://github.com/golang/go synced 2024-11-20 06:54:42 -07:00

gc: introduce rune

R=ken, r
CC=golang-dev
https://golang.org/cl/5293046
This commit is contained in:
Russ Cox 2011-10-25 22:19:39 -07:00
parent f4568882eb
commit 6ed3fa6553
15 changed files with 186 additions and 35 deletions

View File

@ -44,6 +44,8 @@ OFILES=\
walk.$O\ walk.$O\
y1.tab.$O\ y1.tab.$O\
HOST_CFLAGS+=-DGOEXPERIMENT='"$(GOEXPERIMENT)"'
NOINSTALL=1 NOINSTALL=1
include ../../Make.clib include ../../Make.clib

View File

@ -31,11 +31,11 @@ char *runtimeimport =
"func @\"\".slicestring1 (? string, ? int) string\n" "func @\"\".slicestring1 (? string, ? int) string\n"
"func @\"\".intstring (? int64) string\n" "func @\"\".intstring (? int64) string\n"
"func @\"\".slicebytetostring (? []byte) string\n" "func @\"\".slicebytetostring (? []byte) string\n"
"func @\"\".sliceinttostring (? []int) string\n" "func @\"\".slicerunetostring (? []rune) string\n"
"func @\"\".stringtoslicebyte (? string) []byte\n" "func @\"\".stringtoslicebyte (? string) []byte\n"
"func @\"\".stringtosliceint (? string) []int\n" "func @\"\".stringtoslicerune (? string) []rune\n"
"func @\"\".stringiter (? string, ? int) int\n" "func @\"\".stringiter (? string, ? int) int\n"
"func @\"\".stringiter2 (? string, ? int) (retk int, retv int)\n" "func @\"\".stringiter2 (? string, ? int) (retk int, retv rune)\n"
"func @\"\".slicecopy (to any, fr any, wid uint32) int\n" "func @\"\".slicecopy (to any, fr any, wid uint32) int\n"
"func @\"\".slicestringcopy (to any, fr any) int\n" "func @\"\".slicestringcopy (to any, fr any) int\n"
"func @\"\".convI2E (elem any) any\n" "func @\"\".convI2E (elem any) any\n"

View File

@ -94,7 +94,7 @@ dumpprereq(Type *t)
if(t == T) if(t == T)
return; return;
if(t->printed || t == types[t->etype] || t == bytetype) if(t->printed || t == types[t->etype] || t == bytetype || t == runetype)
return; return;
t->printed = 1; t->printed = 1;

View File

@ -785,6 +785,7 @@ EXTERN Type* types[NTYPE];
EXTERN Type* idealstring; EXTERN Type* idealstring;
EXTERN Type* idealbool; EXTERN Type* idealbool;
EXTERN Type* bytetype; EXTERN Type* bytetype;
EXTERN Type* runetype;
EXTERN uchar simtype[NTYPE]; EXTERN uchar simtype[NTYPE];
EXTERN uchar isptr[NTYPE]; EXTERN uchar isptr[NTYPE];
EXTERN uchar isforw[NTYPE]; EXTERN uchar isforw[NTYPE];
@ -840,6 +841,7 @@ EXTERN Node* nblank;
extern int thechar; extern int thechar;
extern char* thestring; extern char* thestring;
EXTERN char* hunk; EXTERN char* hunk;
EXTERN int32 nhunk; EXTERN int32 nhunk;
EXTERN int32 thunk; EXTERN int32 thunk;
@ -854,6 +856,8 @@ EXTERN int packagequotes;
EXTERN int longsymnames; EXTERN int longsymnames;
EXTERN int compiling_runtime; EXTERN int compiling_runtime;
EXTERN int rune32;
/* /*
* y.tab.c * y.tab.c
*/ */
@ -1009,6 +1013,7 @@ Node* renameinit(Node *n);
void cannedimports(char *file, char *cp); void cannedimports(char *file, char *cp);
void importfile(Val *f, int line); void importfile(Val *f, int line);
char* lexname(int lex); char* lexname(int lex);
char* expstring(void);
void mkpackage(char* pkgname); void mkpackage(char* pkgname);
void unimportfile(void); void unimportfile(void);
int32 yylex(void); int32 yylex(void);

View File

@ -30,6 +30,60 @@ static void addidir(char*);
static int getlinepragma(void); static int getlinepragma(void);
static char *goos, *goarch, *goroot; static char *goos, *goarch, *goroot;
// Compiler experiments.
// These are controlled by the GCEXPERIMENT environment
// variable recorded when the compiler is built.
static struct {
char *name;
int *val;
} exper[] = {
{"rune32", &rune32},
};
static void
addexp(char *s)
{
int i;
for(i=0; i<nelem(exper); i++) {
if(strcmp(exper[i].name, s) == 0) {
*exper[i].val = 1;
return;
}
}
print("unknown experiment %s\n", s);
exits("unknown experiment");
}
static void
setexp(void)
{
char *f[20];
int i, nf;
// The makefile #defines GOEXPERIMENT for us.
nf = getfields(GOEXPERIMENT, f, nelem(f), 1, ",");
for(i=0; i<nf; i++)
addexp(f[i]);
}
char*
expstring(void)
{
int i;
static char buf[512];
strcpy(buf, "X");
for(i=0; i<nelem(exper); i++)
if(*exper[i].val)
seprint(buf+strlen(buf), buf+sizeof buf, ",%s", exper[i].name);
if(strlen(buf) == 1)
strcpy(buf, "X,none");
buf[1] = ':';
return buf;
}
// Our own isdigit, isspace, isalpha, isalnum that take care // Our own isdigit, isspace, isalpha, isalnum that take care
// of EOF and other out of range arguments. // of EOF and other out of range arguments.
static int static int
@ -94,7 +148,7 @@ usage(void)
print(" -u disable package unsafe\n"); print(" -u disable package unsafe\n");
print(" -w print the parse tree after typing\n"); print(" -w print the parse tree after typing\n");
print(" -x print lex tokens\n"); print(" -x print lex tokens\n");
exits(0); exits("usage");
} }
void void
@ -144,6 +198,8 @@ main(int argc, char *argv[])
goroot = getgoroot(); goroot = getgoroot();
goos = getgoos(); goos = getgoos();
goarch = thestring; goarch = thestring;
setexp();
outfile = nil; outfile = nil;
ARGBEGIN { ARGBEGIN {
@ -170,7 +226,10 @@ main(int argc, char *argv[])
break; break;
case 'V': case 'V':
print("%cg version %s\n", thechar, getgoversion()); p = expstring();
if(strcmp(p, "X:none") == 0)
p = "";
print("%cg version %s%s%s%s\n", thechar, getgoversion(), *p ? " " : "", p);
exits(0); exits(0);
} ARGEND } ARGEND
@ -540,7 +599,7 @@ importfile(Val *f, int line)
yyerror("import %s: not a go object file", file); yyerror("import %s: not a go object file", file);
errorexit(); errorexit();
} }
q = smprint("%s %s %s", getgoos(), thestring, getgoversion()); q = smprint("%s %s %s %s", getgoos(), thestring, getgoversion(), expstring());
if(strcmp(p+10, q) != 0) { if(strcmp(p+10, q) != 0) {
yyerror("import %s: object is [%s] expected [%s]", file, p+10, q); yyerror("import %s: object is [%s] expected [%s]", file, p+10, q);
errorexit(); errorexit();
@ -1720,6 +1779,18 @@ lexinit1(void)
s1 = pkglookup("byte", builtinpkg); s1 = pkglookup("byte", builtinpkg);
s1->lexical = LNAME; s1->lexical = LNAME;
s1->def = typenod(bytetype); s1->def = typenod(bytetype);
// rune alias
s = lookup("rune");
s->lexical = LNAME;
if(rune32)
runetype = typ(TINT32);
else
runetype = typ(TINT);
runetype->sym = s;
s1 = pkglookup("rune", builtinpkg);
s1->lexical = LNAME;
s1->def = typenod(runetype);
} }
static void static void
@ -1761,6 +1832,10 @@ lexfini(void)
if(s->def == N) if(s->def == N)
s->def = typenod(bytetype); s->def = typenod(bytetype);
s = lookup("rune");
if(s->def == N)
s->def = typenod(runetype);
types[TNIL] = typ(TNIL); types[TNIL] = typ(TNIL);
s = lookup("nil"); s = lookup("nil");
if(s->def == N) { if(s->def == N) {

View File

@ -23,7 +23,7 @@ dumpobj(void)
errorexit(); errorexit();
} }
Bprint(bout, "go object %s %s %s\n", getgoos(), thestring, getgoversion()); Bprint(bout, "go object %s %s %s %s\n", getgoos(), thestring, getgoversion(), expstring());
Bprint(bout, " exports automatically generated from\n"); Bprint(bout, " exports automatically generated from\n");
Bprint(bout, " %s in package \"%s\"\n", curio.infile, localpkg->name); Bprint(bout, " %s in package \"%s\"\n", curio.infile, localpkg->name);
dumpexport(); dumpexport();

View File

@ -54,7 +54,7 @@ typecheckrange(Node *n)
case TSTRING: case TSTRING:
t1 = types[TINT]; t1 = types[TINT];
t2 = types[TINT]; t2 = runetype;
break; break;
} }
@ -216,7 +216,7 @@ walkrange(Node *n)
if(v2 == N) if(v2 == N)
a = nod(OAS, hv1, mkcall("stringiter", types[TINT], nil, ha, hv1)); a = nod(OAS, hv1, mkcall("stringiter", types[TINT], nil, ha, hv1));
else { else {
hv2 = temp(types[TINT]); hv2 = temp(runetype);
a = nod(OAS2, N, N); a = nod(OAS2, N, N);
a->list = list(list1(hv1), hv2); a->list = list(list1(hv1), hv2);
fn = syslook("stringiter2", 0); fn = syslook("stringiter2", 0);

View File

@ -692,7 +692,7 @@ dtypesym(Type *t)
tbase = t->type; tbase = t->type;
dupok = tbase->sym == S; dupok = tbase->sym == S;
if(compiling_runtime && (tbase == types[tbase->etype] || tbase == bytetype)) // int, float, etc if(compiling_runtime && (tbase == types[tbase->etype] || tbase == bytetype || tbase == runetype)) // int, float, etc
goto ok; goto ok;
// named types from other files are defined only by those files // named types from other files are defined only by those files

View File

@ -47,11 +47,11 @@ func slicestring(string, int, int) string
func slicestring1(string, int) string func slicestring1(string, int) string
func intstring(int64) string func intstring(int64) string
func slicebytetostring([]byte) string func slicebytetostring([]byte) string
func sliceinttostring([]int) string func slicerunetostring([]rune) string
func stringtoslicebyte(string) []byte func stringtoslicebyte(string) []byte
func stringtosliceint(string) []int func stringtoslicerune(string) []rune
func stringiter(string, int) int func stringiter(string, int) int
func stringiter2(string, int) (retk int, retv int) func stringiter2(string, int) (retk int, retv rune)
func slicecopy(to any, fr any, wid uint32) int func slicecopy(to any, fr any, wid uint32) int
func slicestringcopy(to any, fr any) int func slicestringcopy(to any, fr any) int

View File

@ -1285,13 +1285,15 @@ Tpretty(Fmt *fp, Type *t)
// called from typesym // called from typesym
if(t == bytetype) if(t == bytetype)
t = types[bytetype->etype]; t = types[bytetype->etype];
if(t == runetype)
t = types[runetype->etype];
} }
if(t->etype != TFIELD if(t->etype != TFIELD
&& t->sym != S && t->sym != S
&& !(fp->flags&FmtLong)) { && !(fp->flags&FmtLong)) {
s = t->sym; s = t->sym;
if((t == types[t->etype] && t->etype != TUNSAFEPTR) || t == bytetype) if((t == types[t->etype] && t->etype != TUNSAFEPTR) || t == bytetype || t == runetype)
return fmtprint(fp, "%s", s->name); return fmtprint(fp, "%s", s->name);
if(exporting) { if(exporting) {
if(fp->flags & FmtShort) if(fp->flags & FmtShort)
@ -1875,6 +1877,11 @@ eqtype(Type *t1, Type *t2)
if((t1 == types[TUINT8] || t1 == bytetype) && (t2 == types[TUINT8] || t2 == bytetype)) if((t1 == types[TUINT8] || t1 == bytetype) && (t2 == types[TUINT8] || t2 == bytetype))
return 1; return 1;
break; break;
case TINT:
case TINT32:
if((t1 == types[runetype->etype] || t1 == runetype) && (t2 == types[runetype->etype] || t2 == runetype))
return 1;
break;
} }
return 0; return 0;
} }
@ -2100,7 +2107,7 @@ convertop(Type *src, Type *dst, char **why)
return OCONV; return OCONV;
} }
// 6. src is an integer or has type []byte or []int // 6. src is an integer or has type []byte or []rune
// and dst is a string type. // and dst is a string type.
if(isint[src->etype] && dst->etype == TSTRING) if(isint[src->etype] && dst->etype == TSTRING)
return ORUNESTR; return ORUNESTR;
@ -2108,16 +2115,16 @@ convertop(Type *src, Type *dst, char **why)
if(isslice(src) && src->sym == nil && dst->etype == TSTRING) { if(isslice(src) && src->sym == nil && dst->etype == TSTRING) {
if(eqtype(src->type, bytetype)) if(eqtype(src->type, bytetype))
return OARRAYBYTESTR; return OARRAYBYTESTR;
if(eqtype(src->type, types[TINT])) if(eqtype(src->type, runetype))
return OARRAYRUNESTR; return OARRAYRUNESTR;
} }
// 7. src is a string and dst is []byte or []int. // 7. src is a string and dst is []byte or []rune.
// String to slice. // String to slice.
if(src->etype == TSTRING && isslice(dst) && dst->sym == nil) { if(src->etype == TSTRING && isslice(dst) && dst->sym == nil) {
if(eqtype(dst->type, bytetype)) if(eqtype(dst->type, bytetype))
return OSTRARRAYBYTE; return OSTRARRAYBYTE;
if(eqtype(dst->type, types[TINT])) if(eqtype(dst->type, runetype))
return OSTRARRAYRUNE; return OSTRARRAYRUNE;
} }

View File

@ -2469,7 +2469,7 @@ stringtoarraylit(Node **np)
while(p < ep) while(p < ep)
l = list(l, nod(OKEY, nodintconst(i++), nodintconst((uchar)*p++))); l = list(l, nod(OKEY, nodintconst(i++), nodintconst((uchar)*p++)));
} else { } else {
// utf-8 []int // utf-8 []rune
while(p < ep) { while(p < ep) {
p += chartorune(&r, p); p += chartorune(&r, p);
l = list(l, nod(OKEY, nodintconst(i++), nodintconst(r))); l = list(l, nod(OKEY, nodintconst(i++), nodintconst(r)));

View File

@ -1151,8 +1151,8 @@ walkexpr(Node **np, NodeList **init)
goto ret; goto ret;
case OARRAYRUNESTR: case OARRAYRUNESTR:
// sliceinttostring([]int) string; // slicerunetostring([]rune) string;
n = mkcall("sliceinttostring", n->type, init, n->left); n = mkcall("slicerunetostring", n->type, init, n->left);
goto ret; goto ret;
case OSTRARRAYBYTE: case OSTRARRAYBYTE:
@ -1161,8 +1161,8 @@ walkexpr(Node **np, NodeList **init)
goto ret; goto ret;
case OSTRARRAYRUNE: case OSTRARRAYRUNE:
// stringtosliceint(string) []int // stringtoslicerune(string) []rune
n = mkcall("stringtosliceint", n->type, init, n->left); n = mkcall("stringtoslicerune", n->type, init, n->left);
goto ret; goto ret;
case OCMPIFACE: case OCMPIFACE:

View File

@ -611,6 +611,43 @@ qcmd(char *arname, int count, char **files)
close(fd); close(fd);
} }
/*
* does the object header line p match the last one we saw?
* update *lastp if it gets more specific.
*/
int
matchhdr(char *p, char **lastp)
{
int n;
char *last;
// no information?
last = *lastp;
if(last == nil) {
*lastp = strdup(p);
return 1;
}
// identical match?
if(strcmp(last, p) == 0)
return 1;
// last has extra fields
n = strlen(p);
if(n < strlen(last) && last[n] == ' ')
return 1;
// p has extra fields - save in last
n = strlen(last);
if(n < strlen(p) && p[n] == ' ') {
free(last);
*lastp = strdup(p);
return 1;
}
return 0;
}
/* /*
* extract the symbol references from an object file * extract the symbol references from an object file
*/ */
@ -670,18 +707,23 @@ scanobj(Biobuf *b, Arfile *ap, long size)
return; return;
} }
if ((lastobj >= 0 && obj != lastobj) || (objhdr != nil && strcmp(p, objhdr) != 0)) { if (!matchhdr(p, &objhdr)) {
fprint(2, "gopack: inconsistent object file %s\n", file); fprint(2, "gopack: inconsistent object file %s: [%s] vs [%s]\n", file, p, objhdr);
errors++; errors++;
allobj = 0; allobj = 0;
free(p); free(p);
return; return;
} }
free(p);
// Old check. Should be impossible since objhdrs match, but keep the check anyway.
if (lastobj >= 0 && obj != lastobj) {
fprint(2, "gopack: inconsistent object file %s\n", file);
errors++;
allobj = 0;
return;
}
lastobj = obj; lastobj = obj;
if(objhdr == nil)
objhdr = p;
else
free(p);
if (!readar(b, obj, offset+size, 0)) { if (!readar(b, obj, offset+size, 0)) {
fprint(2, "gopack: invalid symbol reference in file %s\n", file); fprint(2, "gopack: invalid symbol reference in file %s\n", file);

View File

@ -46,6 +46,7 @@ static int cout = -1;
char* goroot; char* goroot;
char* goarch; char* goarch;
char* goos; char* goos;
char* theline;
void void
Lflag(char *arg) Lflag(char *arg)
@ -478,12 +479,31 @@ ldobj(Biobuf *f, char *pkg, int64 len, char *pn, int whence)
diag("%s: not an object file", pn); diag("%s: not an object file", pn);
return; return;
} }
t = smprint("%s %s %s", getgoos(), thestring, getgoversion());
if(strcmp(line+10, t) != 0 && !debug['f']) { // First, check that the basic goos, string, and version match.
t = smprint("%s %s %s ", getgoos(), thestring, getgoversion());
line[n] = ' ';
if(strncmp(line+10, t, strlen(t)) != 0 && !debug['f']) {
line[n] = '\0';
diag("%s: object is [%s] expected [%s]", pn, line+10, t); diag("%s: object is [%s] expected [%s]", pn, line+10, t);
free(t); free(t);
return; return;
} }
// Second, check that longer lines match each other exactly,
// so that the Go compiler and write additional information
// that must be the same from run to run.
line[n] = '\0';
if(n-10 > strlen(t)) {
if(theline == nil)
theline = strdup(line+10);
else if(strcmp(theline, line+10) != 0) {
line[n] = '\0';
diag("%s: object is [%s] expected [%s]", pn, line+10, theline);
free(t);
return;
}
}
free(t); free(t);
line[n] = '\n'; line[n] = '\n';

View File

@ -278,7 +278,7 @@ func stringtoslicebyte(s String) (b Slice) {
runtime·memmove(b.array, s.str, s.len); runtime·memmove(b.array, s.str, s.len);
} }
func sliceinttostring(b Slice) (s String) { func slicerunetostring(b Slice) (s String) {
int32 siz1, siz2, i; int32 siz1, siz2, i;
int32 *a; int32 *a;
byte dum[8]; byte dum[8];
@ -301,13 +301,13 @@ func sliceinttostring(b Slice) (s String) {
s.str[s.len] = 0; s.str[s.len] = 0;
} }
func stringtosliceint(s String) (b Slice) { func stringtoslicerune(s String) (b Slice) {
int32 n; int32 n;
int32 dum, *r; int32 dum, *r;
uint8 *p, *ep; uint8 *p, *ep;
// two passes. // two passes.
// unlike sliceinttostring, no race because strings are immutable. // unlike slicerunetostring, no race because strings are immutable.
p = s.str; p = s.str;
ep = s.str+s.len; ep = s.str+s.len;
n = 0; n = 0;