123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590 |
- #include "limbo.h"
- static long stubalign(long offset, int a, char** b, char *e);
- static void pickadtstub(Type *t);
- void
- emit(Decl *globals)
- {
- Decl *m, *d, *id;
- for(m = globals; m != nil; m = m->next){
- if(m->store != Dtype || m->ty->kind != Tmodule)
- continue;
- m->ty = usetype(m->ty);
- for(d = m->ty->ids; d != nil; d = d->next){
- d->ty = usetype(d->ty);
- if(d->store == Dglobal || d->store == Dfn)
- modrefable(d->ty);
- if(d->store == Dtype && d->ty->kind == Tadt){
- for(id = d->ty->ids; id != nil; id = id->next){
- id->ty = usetype(id->ty);
- modrefable(d->ty);
- }
- }
- }
- }
- if(emitstub){
- adtstub(globals);
- modstub(globals);
- }
- if(emittab != nil)
- modtab(globals);
- if(emitcode)
- modcode(globals);
- }
- static char*
- lowercase(char *f)
- {
- char *s = f;
- for( ; *s != 0; s++)
- if(*s >= 'A' && *s <= 'Z')
- *s += 'a' - 'A';
- return f;
- }
- void
- modcode(Decl *globals)
- {
- Decl *d, *id;
- char buf[32];
- if(emitdyn){
- strcpy(buf, emitcode);
- lowercase(buf);
- print("#include \"%s.h\"\n", buf);
- }
- else{
- print("#include <lib9.h>\n");
- print("#include <isa.h>\n");
- print("#include <interp.h>\n");
- print("#include \"%smod.h\"\n", emitcode);
- }
- print("\n");
- for(d = globals; d != nil; d = d->next)
- if(d->store == Dtype && d->ty->kind == Tmodule && strcmp(d->sym->name, emitcode) == 0)
- break;
- if(d == nil)
- return;
-
- /*
- * stub types
- */
- for(id = d->ty->ids; id != nil; id = id->next){
- if(id->store == Dtype && id->ty->kind == Tadt){
- id->ty = usetype(id->ty);
- print("Type*\tT_%s;\n", id->sym->name);
- }
- }
- /*
- * type maps
- */
- if(emitdyn){
- for(id = d->ty->ids; id != nil; id = id->next)
- if(id->store == Dtype && id->ty->kind == Tadt)
- print("uchar %s_map[] = %s_%s_map;\n",
- id->sym->name, emitcode, id->sym->name);
- }
-
- /*
- * heap allocation and garbage collection for a type
- */
- if(emitdyn){
- for(id = d->ty->ids; id != nil; id = id->next)
- if(id->store == Dtype && id->ty->kind == Tadt){
- print("\n%s_%s*\n%salloc%s(void)\n{\n\tHeap *h;\n\n\th = heap(T_%s);\n\treturn H2D(%s_%s*, h);\n}\n", emitcode, id->sym->name, emitcode, id->sym->name, id->sym->name, emitcode, id->sym->name);
- print("\nvoid\n%sfree%s(Heap *h, int swept)\n{\n\t%s_%s *d;\n\n\td = H2D(%s_%s*, h);\n\tfreeheap(h, swept);\n}\n", emitcode, id->sym->name, emitcode, id->sym->name, emitcode, id->sym->name);
- }
- }
- /*
- * initialization function
- */
- if(emitdyn)
- print("\nvoid\n%sinit(void)\n{\n", emitcode);
- else{
- print("\nvoid\n%smodinit(void)\n{\n", emitcode);
- print("\tbuiltinmod(\"$%s\", %smodtab, %smodlen);\n", emitcode, emitcode, emitcode);
- }
- for(id = d->ty->ids; id != nil; id = id->next){
- if(id->store == Dtype && id->ty->kind == Tadt){
- if(emitdyn)
- print("\tT_%s = dtype(%sfree%s, %s_%s_size, %s_map, sizeof(%s_map));\n",
- id->sym->name, emitcode, id->sym->name, emitcode, id->sym->name, id->sym->name, id->sym->name);
- else
- print("\tT_%s = dtype(freeheap, sizeof(%s), %smap, sizeof(%smap));\n",
- id->sym->name, id->sym->name, id->sym->name, id->sym->name);
- }
- }
- print("}\n");
- /*
- * end function
- */
- if(emitdyn){
- print("\nvoid\n%send(void)\n{\n", emitcode);
- for(id = d->ty->ids; id != nil; id = id->next)
- if(id->store == Dtype && id->ty->kind == Tadt)
- print("\tfreetype(T_%s);\n", id->sym->name);
- print("}\n");
- }
- /*
- * stub functions
- */
- for(id = d->ty->tof->ids; id != nil; id = id->next){
- print("\nvoid\n%s_%s(void *fp)\n{\n\tF_%s_%s *f = fp;\n",
- id->dot->sym->name, id->sym->name,
- id->dot->sym->name, id->sym->name);
- if(id->ty->tof != tnone && tattr[id->ty->tof->kind].isptr){
- print("\tvoid *r;\n");
- print("\n\tr = *f->ret;\n\t*f->ret = H;\n\tdestroy(r);\n");
- }
- print("}\n");
- }
- if(emitdyn)
- print("\n#include \"%smod.h\"\n", buf);
- }
- void
- modtab(Decl *globals)
- {
- int n;
- Desc *md;
- Decl *d, *id;
- print("typedef struct{char *name; long sig; void (*fn)(void*); int size; int np; uchar map[16];} Runtab;\n");
- for(d = globals; d != nil; d = d->next){
- if(d->store == Dtype && d->ty->kind == Tmodule && strcmp(d->sym->name, emittab) == 0){
- n = 0;
- print("Runtab %smodtab[]={\n", d->sym->name);
- for(id = d->ty->tof->ids; id != nil; id = id->next){
- n++;
- print("\t\"");
- if(id->dot != d)
- print("%s.", id->dot->sym->name);
- print("%s\",0x%lux,%s_%s,", id->sym->name, sign(id),
- id->dot->sym->name, id->sym->name);
- if(id->ty->varargs)
- print("0,0,{0},");
- else{
- md = mkdesc(idoffsets(id->ty->ids, MaxTemp, MaxAlign), id->ty->ids);
- print("%ld,%ld,%M,", md->size, md->nmap, md);
- }
- print("\n");
- }
- print("\t0\n};\n");
- print("#define %smodlen %d\n", d->sym->name, n);
- }
- }
- }
- /*
- * produce activation records for all the functions in modules
- */
- void
- modstub(Decl *globals)
- {
- Type *t;
- Decl *d, *id, *m;
- char buf[StrSize*2], *p;
- long offset;
- int arg;
- for(d = globals; d != nil; d = d->next){
- if(d->store != Dtype || d->ty->kind != Tmodule)
- continue;
- arg = 0;
- for(id = d->ty->tof->ids; id != nil; id = id->next){
- if(emitdyn && id->dot->dot != nil)
- seprint(buf, buf+sizeof(buf), "%s_%s_%s", id->dot->dot->sym->name, id->dot->sym->name, id->sym->name);
- else
- seprint(buf, buf+sizeof(buf), "%s_%s", id->dot->sym->name, id->sym->name);
- print("void %s(void*);\ntypedef struct F_%s F_%s;\nstruct F_%s\n{\n",
- buf, buf, buf, buf);
- print(" WORD regs[NREG-1];\n");
- if(id->ty->tof != tnone)
- print(" %R* ret;\n", id->ty->tof);
- else
- print(" WORD noret;\n");
- print(" uchar temps[%d];\n", MaxTemp-NREG*IBY2WD);
- offset = MaxTemp;
- for(m = id->ty->ids; m != nil; m = m->next){
- if(m->sym != nil)
- p = m->sym->name;
- else{
- seprint(buf, buf+sizeof(buf), "arg%d", arg);
- p = buf;
- }
- /*
- * explicit pads for structure alignment
- */
- t = m->ty;
- offset = stubalign(offset, t->align, nil, nil);
- if(offset != m->offset)
- yyerror("module stub must not contain data objects");
- // fatal("modstub bad offset");
- print(" %R %s;\n", t, p);
- arg++;
- offset += t->size;
- }
- if(id->ty->varargs)
- print(" WORD vargs;\n");
- print("};\n");
- }
- for(id = d->ty->ids; id != nil; id = id->next)
- if(id->store == Dconst)
- constub(id);
- }
- }
- static void
- chanstub(char *in, Decl *id)
- {
- Desc *desc;
- print("typedef %R %s_%s;\n", id->ty->tof, in, id->sym->name);
- desc = mktdesc(id->ty->tof);
- print("#define %s_%s_size %ld\n", in, id->sym->name, desc->size);
- print("#define %s_%s_map %M\n", in, id->sym->name, desc);
- }
- /*
- * produce c structs for all adts
- */
- void
- adtstub(Decl *globals)
- {
- Type *t, *tt;
- Desc *desc;
- Decl *m, *d, *id;
- char buf[2*StrSize];
- long offset;
- for(m = globals; m != nil; m = m->next){
- if(m->store != Dtype || m->ty->kind != Tmodule)
- continue;
- for(d = m->ty->ids; d != nil; d = d->next){
- if(d->store != Dtype)
- continue;
- t = usetype(d->ty);
- d->ty = t;
- dotprint(buf, buf+sizeof(buf), d->ty->decl, '_');
- switch(d->ty->kind){
- case Tadt:
- print("typedef struct %s %s;\n", buf, buf);
- break;
- case Tint:
- case Tbyte:
- case Treal:
- case Tbig:
- case Tfix:
- print("typedef %T %s;\n", t, buf);
- break;
- }
- }
- }
- for(m = globals; m != nil; m = m->next){
- if(m->store != Dtype || m->ty->kind != Tmodule)
- continue;
- for(d = m->ty->ids; d != nil; d = d->next){
- if(d->store != Dtype)
- continue;
- t = d->ty;
- if(t->kind == Tadt || t->kind == Ttuple && t->decl->sym != anontupsym){
- if(t->tags != nil){
- pickadtstub(t);
- continue;
- }
- dotprint(buf, buf+sizeof(buf), t->decl, '_');
- print("struct %s\n{\n", buf);
- offset = 0;
- for(id = t->ids; id != nil; id = id->next){
- if(id->store == Dfield){
- tt = id->ty;
- offset = stubalign(offset, tt->align, nil, nil);
- if(offset != id->offset)
- fatal("adtstub bad offset");
- print(" %R %s;\n", tt, id->sym->name);
- offset += tt->size;
- }
- }
- if(t->ids == nil){
- print(" char dummy[1];\n");
- offset = 1;
- }
- offset = stubalign(offset, t->align, nil ,nil);
- offset = stubalign(offset, IBY2WD, nil , nil);
- if(offset != t->size && t->ids != nil)
- fatal("adtstub: bad size");
- print("};\n");
- for(id = t->ids; id != nil; id = id->next)
- if(id->store == Dconst)
- constub(id);
- for(id = t->ids; id != nil; id = id->next)
- if(id->ty->kind == Tchan)
- chanstub(buf, id);
- desc = mktdesc(t);
- if(offset != desc->size && t->ids != nil)
- fatal("adtstub: bad desc size");
- print("#define %s_size %ld\n", buf, offset);
- print("#define %s_map %M\n", buf, desc);
- if(0)
- print("struct %s_check {int s[2*(sizeof(%s)==%s_size)-1];};\n", buf, buf, buf);
- }else if(t->kind == Tchan)
- chanstub(m->sym->name, d);
- }
- }
- }
- /*
- * emit an expicit pad field for aligning emitted c structs
- * according to limbo's definition
- */
- static long
- stubalign(long offset, int a, char **buf, char *end)
- {
- long x;
- x = offset & (a-1);
- if(x == 0)
- return offset;
- x = a - x;
- if(buf == nil)
- print("\tuchar\t_pad%ld[%ld];\n", offset, x);
- else
- *buf = seprint(*buf, end, "uchar\t_pad%ld[%ld]; ", offset, x);
- offset += x;
- if((offset & (a-1)) || x >= a)
- fatal("compiler stub misalign");
- return offset;
- }
- void
- constub(Decl *id)
- {
- char buf[StrSize*2];
- seprint(buf, buf+sizeof(buf), "%s_%s", id->dot->sym->name, id->sym->name);
- switch(id->ty->kind){
- case Tbyte:
- print("#define %s %d\n", buf, (int)id->init->val & 0xff);
- break;
- case Tint:
- case Tfix:
- print("#define %s %ld\n", buf, (long)id->init->val);
- break;
- case Tbig:
- print("#define %s %ld\n", buf, (long)id->init->val);
- break;
- case Treal:
- print("#define %s %g\n", buf, id->init->rval);
- break;
- case Tstring:
- print("#define %s \"%s\"\n", buf, id->init->decl->sym->name);
- break;
- }
- }
- int
- mapconv(Fmt *f)
- {
- Desc *d;
- char *s, *e, buf[1024];
- int i;
- d = va_arg(f->args, Desc*);
- e = buf+sizeof(buf);
- s = buf;
- s = secpy(s, e, "{");
- for(i = 0; i < d->nmap; i++)
- s = seprint(s, e, "0x%x,", d->map[i]);
- if(i == 0)
- s = seprint(s, e, "0");
- seprint(s, e, "}");
- return fmtstrcpy(f, buf);
- }
- char*
- dotprint(char *buf, char *end, Decl *d, int dot)
- {
- if(d->dot != nil){
- buf = dotprint(buf, end, d->dot, dot);
- if(buf < end)
- *buf++ = dot;
- }
- if(d->sym == nil)
- return buf;
- return seprint(buf, end, "%s", d->sym->name);
- }
- char *ckindname[Tend] =
- {
- /* Tnone */ "void",
- /* Tadt */ "struct",
- /* Tadtpick */ "?adtpick?",
- /* Tarray */ "Array*",
- /* Tbig */ "LONG",
- /* Tbyte */ "BYTE",
- /* Tchan */ "Channel*",
- /* Treal */ "REAL",
- /* Tfn */ "?fn?",
- /* Tint */ "WORD",
- /* Tlist */ "List*",
- /* Tmodule */ "Modlink*",
- /* Tref */ "?ref?",
- /* Tstring */ "String*",
- /* Ttuple */ "?tuple?",
- /* Texception */ "?exception",
- /* Tfix */ "WORD",
- /* Tpoly */ "void*",
- /* Tainit */ "?ainit?",
- /* Talt */ "?alt?",
- /* Tany */ "void*",
- /* Tarrow */ "?arrow?",
- /* Tcase */ "?case?",
- /* Tcasel */ "?casel",
- /* Tcasec */ "?casec?",
- /* Tdot */ "?dot?",
- /* Terror */ "?error?",
- /* Tgoto */ "?goto?",
- /* Tid */ "?id?",
- /* Tiface */ "?iface?",
- /* Texcept */ "?except?",
- /* Tinst */ "?inst?",
- };
- char*
- ctprint(char *buf, char *end, Type *t)
- {
- Decl *id;
- Type *tt;
- long offset;
- if(t == nil)
- return secpy(buf, end, "void");
- switch(t->kind){
- case Tref:
- return seprint(buf, end, "%R*", t->tof);
- case Tarray:
- case Tlist:
- case Tint:
- case Tbig:
- case Tstring:
- case Treal:
- case Tbyte:
- case Tnone:
- case Tany:
- case Tchan:
- case Tmodule:
- case Tfix:
- case Tpoly:
- return seprint(buf, end, "%s", ckindname[t->kind]);
- case Tadtpick:
- return ctprint(buf, end, t->decl->dot->ty);
- case Tadt:
- case Ttuple:
- if(t->decl->sym != anontupsym)
- return dotprint(buf, end, t->decl, '_');
- offset = 0;
- buf = secpy(buf, end, "struct{ ");
- for(id = t->ids; id != nil; id = id->next){
- tt = id->ty;
- offset = stubalign(offset, tt->align, &buf, end);
- if(offset != id->offset)
- fatal("ctypeconv tuple bad offset");
- buf = seprint(buf, end, "%R %s; ", tt, id->sym->name);
- offset += tt->size;
- }
- offset = stubalign(offset, t->align, &buf, end);
- if(offset != t->size)
- fatal("ctypeconv tuple bad t=%T size=%ld offset=%ld", t, t->size, offset);
- return secpy(buf, end, "}");
- default:
- if(t->kind >= Tend)
- yyerror("no C equivalent for type %d", t->kind);
- else
- yyerror("no C equivalent for type %s", kindname[t->kind]);
- break;
- }
- return buf;
- }
- static void
- pickadtstub(Type *t)
- {
- Type *tt;
- Desc *desc;
- Decl *id, *tg;
- char buf[2*StrSize];
- int ok;
- long offset, tgoffset;
- dotprint(buf, buf+sizeof(buf), t->decl, '_');
- offset = 0;
- for(tg = t->tags; tg != nil; tg = tg->next)
- print("#define %s_%s %ld\n", buf, tg->sym->name, offset++);
- print("struct %s\n{\n", buf);
- print(" int pick;\n");
- offset = IBY2WD;
- for(id = t->ids; id != nil; id = id->next){
- if(id->store == Dfield){
- tt = id->ty;
- offset = stubalign(offset, tt->align, nil, nil);
- if(offset != id->offset)
- fatal("pickadtstub bad offset");
- print(" %R %s;\n", tt, id->sym->name);
- offset += tt->size;
- }
- }
- print(" union{\n");
- for(tg = t->tags; tg != nil; tg = tg->next){
- tgoffset = offset;
- print(" struct{\n");
- for(id = tg->ty->ids; id != nil; id = id->next){
- if(id->store == Dfield){
- tt = id->ty;
- tgoffset = stubalign(tgoffset, tt->align, nil, nil);
- if(tgoffset != id->offset)
- fatal("pickadtstub bad offset");
- print(" %R %s;\n", tt, id->sym->name);
- tgoffset += tt->size;
- }
- }
- if(tg->ty->ids == nil)
- print(" char dummy[1];\n");
- print(" } %s;\n", tg->sym->name);
- }
- print(" } u;\n");
- print("};\n");
- for(id = t->ids; id != nil; id = id->next)
- if(id->store == Dconst)
- constub(id);
- for(id = t->ids; id != nil; id = id->next)
- if(id->ty->kind == Tchan)
- chanstub(buf, id);
- for(tg = t->tags; tg != nil; tg = tg->next){
- ok = tg->ty->tof->ok;
- tg->ty->tof->ok = OKverify;
- sizetype(tg->ty->tof);
- tg->ty->tof->ok = OKmask;
- desc = mktdesc(tg->ty->tof);
- tg->ty->tof->ok = ok;
- print("#define %s_%s_size %ld\n", buf, tg->sym->name, tg->ty->size);
- print("#define %s_%s_map %M\n", buf, tg->sym->name, desc);
- }
- }
|