1
0
mirror of https://github.com/golang/go synced 2024-09-25 11:30:13 -06:00

6l: generate gotypesigs on demand.

add sys.unreflect, which uses gotypesigs.

R=r
DELTA=170  (152 added, 12 deleted, 6 changed)
OCL=18396
CL=18404
This commit is contained in:
Russ Cox 2008-11-03 16:03:12 -08:00
parent bcd6403cc9
commit 47caf6424c
7 changed files with 158 additions and 18 deletions

View File

@ -7,6 +7,7 @@
// accumulate all type information from .6 files.
// check for inconsistencies.
// define gotypestrings variable if needed.
// define gotypesigs variable if needed.
// TODO:
// include type info for non-exported types.
@ -301,6 +302,16 @@ importcmp(const void *va, const void *vb)
return strcmp(a->name, b->name);
}
static int
symcmp(const void *va, const void *vb)
{
Sym *a, *b;
a = *(Sym**)va;
b = *(Sym**)vb;
return strcmp(a->name, b->name);
}
// if there is an undefined reference to gotypestrings,
// create it. c declaration is
// extern char gotypestrings[];
@ -309,7 +320,7 @@ importcmp(const void *va, const void *vb)
void
definetypestrings(void)
{
int i, j, len, n;
int i, j, len, n, w;
char *p;
Import **all, *x;
Fmt f;
@ -376,27 +387,79 @@ definetypestrings(void)
// (had to add D_SBIG even to do that; the compiler
// would have generated 8-byte chunks.)
for(i=0; i<n; i+=100) {
prog = mal(sizeof *prog);
prog->as = ADATA;
prog->width = 100;
if(prog->width > n - i)
prog->width = n - i;
prog->from.scale = prog->width;
prog->from.type = D_EXTERN;
prog->from.sym = s;
prog->from.offset = i;
w = 100;
if(w > n - i)
w = n - i;
prog = newdata(s, i, w, D_EXTERN);
prog->to.type = D_SBIG;
prog->to.sbig = p + i;
if(edatap == P)
datap = prog;
else
edatap->link = prog;
edatap = prog;
prog->link = P;
}
if(debug['v'])
Bprint(&bso, "%5.2f typestrings %d\n", cputime(), n);
}
// if there is an undefined reference to gotypesigs, create it.
// c declaration is
// extern Sigt *gotypesigs[];
// extern int ngotypesigs;
// used by sys.unreflect runtime.
void
definetypesigs(void)
{
int i, j, n;
Sym **all, *s, *x;
Prog *prog;
if(debug['g'])
return;
if(debug['v'])
Bprint(&bso, "%5.2f definetypesigs\n", cputime());
s = lookup("gotypesigs", 0);
if(s->type == 0)
return;
if(s->type != SXREF) {
diag("gotypesigs already defined");
return;
}
s->type = SDATA;
// make a list of all the sigt symbols.
n = 0;
for(i=0; i<NHASH; i++)
for(x = hash[i]; x; x=x->link)
if(memcmp(x->name, "sigt·", 6) == 0)
n++;
all = mal(n*sizeof all[0]);
j = 0;
for(i=0; i<NHASH; i++)
for(x = hash[i]; x; x=x->link)
if(memcmp(x->name, "sigt·", 6) == 0)
all[j++] = x;
// sort them by name
qsort(all, n, sizeof all[0], symcmp);
// emit array as sequence of references.
enum { PtrSize = 8 };
for(i=0; i<n; i++) {
prog = newdata(s, PtrSize*i, PtrSize, D_EXTERN);
prog->to.type = D_ADDR;
prog->to.index = D_EXTERN;
prog->to.sym = all[i];
}
s->value = PtrSize*n;
// emit count
s = lookup("ngotypesigs", 0);
s->type = SDATA;
s->value = sizeof(int32);
prog = newdata(s, 0, sizeof(int32), D_EXTERN);
prog->to.offset = n;
if(debug['v'])
Bprint(&bso, "%5.2f typestrings %d\n", cputime(), n);
}

View File

@ -380,6 +380,7 @@ Prog* copyp(Prog*);
double cputime(void);
void datblk(int32, int32);
void definetypestrings(void);
void definetypesigs(void);
void diag(char*, ...);
void dodata(void);
void doinit(void);
@ -409,6 +410,7 @@ void lputl(int32);
void main(int, char*[]);
void mkfwd(void);
void* mysbrk(uint32);
Prog* newdata(Sym*, int, int, int);
void nuxiinit(void);
void objfile(char*);
int opsize(Prog*);

View File

@ -369,6 +369,7 @@ main(int argc, char *argv[])
objfile(a);
}
definetypestrings();
definetypesigs();
firstp = firstp->link;
if(firstp == P)

View File

@ -926,7 +926,7 @@ ckoff(Sym *s, int32 v)
diag("relocation offset %ld for %s out of range", v, s->name);
}
static Prog*
Prog*
newdata(Sym *s, int o, int w, int t)
{
Prog *p;

View File

@ -33,6 +33,7 @@ export func ifaceI2T(sigt *byte, iface any) (ret any);
export func ifaceI2I(sigi *byte, iface any) (ret any);
export func ifaceeq(i1 any, i2 any) (ret bool);
export func reflect(i interface { }) (uint64, string);
export func unreflect(uint64, string) (ret interface { });
export func argc() int;
export func envc() int;

View File

@ -25,6 +25,7 @@ char *sysimport =
"export func sys.ifaceI2I (sigi *uint8, iface any) (ret any)\n"
"export func sys.ifaceeq (i1 any, i2 any) (ret bool)\n"
"export func sys.reflect (i interface { }) (? uint64, ? string)\n"
"export func sys.unreflect (? uint64, ? string) (ret interface { })\n"
"export func sys.argc () (? int)\n"
"export func sys.envc () (? int)\n"
"export func sys.argv (? int) (? string)\n"

View File

@ -378,3 +378,75 @@ sys·reflect(Map *im, void *it, uint64 retit, string rettype)
FLUSH(&retit);
FLUSH(&rettype);
}
extern Sigt *gotypesigs[];
extern int32 ngotypesigs;
static Sigt*
fakesigt(string type)
{
// TODO(rsc): Cache these by type string.
Sigt *sigt;
// Must be pointer in order for alg, width to be right.
if(type == nil || type->len == 0 || type->str[0] != '*') {
// TODO(rsc): What to do here?
prints("bad unreflect type: ");
sys·printstring(type);
prints("\n");
throw("unreflect");
}
sigt = mal(2*sizeof sigt[0]);
sigt[0].name = mal(type->len + 1);
mcpy(sigt[0].name, type->str, type->len);
sigt[0].hash = ASIMP; // alg
sigt[0].offset = sizeof(void*); // width
return sigt;
}
static int32
cmpstringchars(string a, uint8 *b)
{
int32 i;
for(i=0;; i++) {
if(i == a->len) {
if(b[i] == 0)
return 0;
return -1;
}
if(b[i] == 0)
return 1;
if(a->str[i] != b[i]) {
if((uint8)a->str[i] < (uint8)b[i])
return -1;
return 1;
}
}
}
static Sigt*
findtype(string type)
{
int32 i;
for(i=0; i<ngotypesigs; i++)
if(cmpstringchars(type, gotypesigs[i]->name) == 0)
return gotypesigs[i];
return fakesigt(type);
}
void
sys·unreflect(uint64 it, string type, Map *retim, void *retit)
{
if(cmpstring(type, emptystring) == 0) {
retim = 0;
retit = 0;
} else {
retim = hashmap(sigi·inter, findtype(type), 0);
retit = (void*)it;
}
FLUSH(&retim);
FLUSH(&retit);
}