1 #include "limbo.h"
2
3 static long stubalign(long offset, int a, char** b, char *e);
4 static void pickadtstub(Type *t);
5
6 void
emit(Decl * globals)7 emit(Decl *globals)
8 {
9 Decl *m, *d, *id;
10
11 for(m = globals; m != nil; m = m->next){
12 if(m->store != Dtype || m->ty->kind != Tmodule)
13 continue;
14 m->ty = usetype(m->ty);
15 for(d = m->ty->ids; d != nil; d = d->next){
16 d->ty = usetype(d->ty);
17 if(d->store == Dglobal || d->store == Dfn)
18 modrefable(d->ty);
19 if(d->store == Dtype && d->ty->kind == Tadt){
20 for(id = d->ty->ids; id != nil; id = id->next){
21 id->ty = usetype(id->ty);
22 modrefable(d->ty);
23 }
24 }
25 }
26 }
27 if(emitstub){
28 adtstub(globals);
29 modstub(globals);
30 }
31 if(emittab != nil)
32 modtab(globals);
33 if(emitcode)
34 modcode(globals);
35 }
36
37 static char*
lowercase(char * f)38 lowercase(char *f)
39 {
40 char *s = f;
41
42 for( ; *s != 0; s++)
43 if(*s >= 'A' && *s <= 'Z')
44 *s += 'a' - 'A';
45 return f;
46 }
47
48 void
modcode(Decl * globals)49 modcode(Decl *globals)
50 {
51 Decl *d, *id;
52 char buf[32];
53
54 if(emitdyn){
55 strcpy(buf, emitcode);
56 lowercase(buf);
57 print("#include \"%s.h\"\n", buf);
58 }
59 else{
60 print("#include <lib9.h>\n");
61 print("#include <isa.h>\n");
62 print("#include <interp.h>\n");
63 print("#include \"%smod.h\"\n", emitcode);
64 }
65 print("\n");
66
67 for(d = globals; d != nil; d = d->next)
68 if(d->store == Dtype && d->ty->kind == Tmodule && strcmp(d->sym->name, emitcode) == 0)
69 break;
70
71 if(d == nil)
72 return;
73
74 /*
75 * stub types
76 */
77 for(id = d->ty->ids; id != nil; id = id->next){
78 if(id->store == Dtype && id->ty->kind == Tadt){
79 id->ty = usetype(id->ty);
80 print("Type*\tT_%s;\n", id->sym->name);
81 }
82 }
83
84 /*
85 * type maps
86 */
87 if(emitdyn){
88 for(id = d->ty->ids; id != nil; id = id->next)
89 if(id->store == Dtype && id->ty->kind == Tadt)
90 print("uchar %s_map[] = %s_%s_map;\n",
91 id->sym->name, emitcode, id->sym->name);
92 }
93
94 /*
95 * heap allocation and garbage collection for a type
96 */
97 if(emitdyn){
98 for(id = d->ty->ids; id != nil; id = id->next)
99 if(id->store == Dtype && id->ty->kind == Tadt){
100 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);
101 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);
102 }
103 }
104
105 /*
106 * initialization function
107 */
108 if(emitdyn)
109 print("\nvoid\n%sinit(void)\n{\n", emitcode);
110 else{
111 print("\nvoid\n%smodinit(void)\n{\n", emitcode);
112 print("\tbuiltinmod(\"$%s\", %smodtab, %smodlen);\n", emitcode, emitcode, emitcode);
113 }
114 for(id = d->ty->ids; id != nil; id = id->next){
115 if(id->store == Dtype && id->ty->kind == Tadt){
116 if(emitdyn)
117 print("\tT_%s = dtype(%sfree%s, %s_%s_size, %s_map, sizeof(%s_map));\n",
118 id->sym->name, emitcode, id->sym->name, emitcode, id->sym->name, id->sym->name, id->sym->name);
119 else
120 print("\tT_%s = dtype(freeheap, sizeof(%s), %smap, sizeof(%smap));\n",
121 id->sym->name, id->sym->name, id->sym->name, id->sym->name);
122 }
123 }
124 print("}\n");
125
126 /*
127 * end function
128 */
129 if(emitdyn){
130 print("\nvoid\n%send(void)\n{\n", emitcode);
131 for(id = d->ty->ids; id != nil; id = id->next)
132 if(id->store == Dtype && id->ty->kind == Tadt)
133 print("\tfreetype(T_%s);\n", id->sym->name);
134 print("}\n");
135 }
136
137 /*
138 * stub functions
139 */
140 for(id = d->ty->tof->ids; id != nil; id = id->next){
141 print("\nvoid\n%s_%s(void *fp)\n{\n\tF_%s_%s *f = fp;\n",
142 id->dot->sym->name, id->sym->name,
143 id->dot->sym->name, id->sym->name);
144 if(id->ty->tof != tnone && tattr[id->ty->tof->kind].isptr){
145 print("\tvoid *r;\n");
146 print("\n\tr = *f->ret;\n\t*f->ret = H;\n\tdestroy(r);\n");
147 }
148 print("}\n");
149 }
150
151 if(emitdyn)
152 print("\n#include \"%smod.h\"\n", buf);
153 }
154
155 void
modtab(Decl * globals)156 modtab(Decl *globals)
157 {
158 int n;
159 Desc *md;
160 Decl *d, *id;
161
162 print("typedef struct{char *name; long sig; void (*fn)(void*); int size; int np; uchar map[16];} Runtab;\n");
163 for(d = globals; d != nil; d = d->next){
164 if(d->store == Dtype && d->ty->kind == Tmodule && strcmp(d->sym->name, emittab) == 0){
165 n = 0;
166 print("Runtab %smodtab[]={\n", d->sym->name);
167 for(id = d->ty->tof->ids; id != nil; id = id->next){
168 n++;
169 print("\t\"");
170 if(id->dot != d)
171 print("%s.", id->dot->sym->name);
172 print("%s\",0x%lux,%s_%s,", id->sym->name, sign(id),
173 id->dot->sym->name, id->sym->name);
174 if(id->ty->varargs)
175 print("0,0,{0},");
176 else{
177 md = mkdesc(idoffsets(id->ty->ids, MaxTemp, MaxAlign), id->ty->ids);
178 print("%ld,%ld,%M,", md->size, md->nmap, md);
179 }
180 print("\n");
181 }
182 print("\t0\n};\n");
183 print("#define %smodlen %d\n", d->sym->name, n);
184 }
185 }
186 }
187
188 /*
189 * produce activation records for all the functions in modules
190 */
191 void
modstub(Decl * globals)192 modstub(Decl *globals)
193 {
194 Type *t;
195 Decl *d, *id, *m;
196 char buf[StrSize*2], *p;
197 long offset;
198 int arg;
199
200 for(d = globals; d != nil; d = d->next){
201 if(d->store != Dtype || d->ty->kind != Tmodule)
202 continue;
203 arg = 0;
204 for(id = d->ty->tof->ids; id != nil; id = id->next){
205 if(emitdyn && id->dot->dot != nil)
206 seprint(buf, buf+sizeof(buf), "%s_%s_%s", id->dot->dot->sym->name, id->dot->sym->name, id->sym->name);
207 else
208 seprint(buf, buf+sizeof(buf), "%s_%s", id->dot->sym->name, id->sym->name);
209 print("void %s(void*);\ntypedef struct F_%s F_%s;\nstruct F_%s\n{\n",
210 buf, buf, buf, buf);
211 print(" WORD regs[NREG-1];\n");
212 if(id->ty->tof != tnone)
213 print(" %R* ret;\n", id->ty->tof);
214 else
215 print(" WORD noret;\n");
216 print(" uchar temps[%d];\n", MaxTemp-NREG*IBY2WD);
217 offset = MaxTemp;
218 for(m = id->ty->ids; m != nil; m = m->next){
219 if(m->sym != nil)
220 p = m->sym->name;
221 else{
222 seprint(buf, buf+sizeof(buf), "arg%d", arg);
223 p = buf;
224 }
225
226 /*
227 * explicit pads for structure alignment
228 */
229 t = m->ty;
230 offset = stubalign(offset, t->align, nil, nil);
231 if(offset != m->offset)
232 yyerror("module stub must not contain data objects");
233 // fatal("modstub bad offset");
234 print(" %R %s;\n", t, p);
235 arg++;
236 offset += t->size;
237 }
238 if(id->ty->varargs)
239 print(" WORD vargs;\n");
240 print("};\n");
241 }
242 for(id = d->ty->ids; id != nil; id = id->next)
243 if(id->store == Dconst)
244 constub(id);
245 }
246 }
247
248 static void
chanstub(char * in,Decl * id)249 chanstub(char *in, Decl *id)
250 {
251 Desc *desc;
252
253 print("typedef %R %s_%s;\n", id->ty->tof, in, id->sym->name);
254 desc = mktdesc(id->ty->tof);
255 print("#define %s_%s_size %ld\n", in, id->sym->name, desc->size);
256 print("#define %s_%s_map %M\n", in, id->sym->name, desc);
257 }
258
259 /*
260 * produce c structs for all adts
261 */
262 void
adtstub(Decl * globals)263 adtstub(Decl *globals)
264 {
265 Type *t, *tt;
266 Desc *desc;
267 Decl *m, *d, *id;
268 char buf[2*StrSize];
269 long offset;
270
271 for(m = globals; m != nil; m = m->next){
272 if(m->store != Dtype || m->ty->kind != Tmodule)
273 continue;
274 for(d = m->ty->ids; d != nil; d = d->next){
275 if(d->store != Dtype)
276 continue;
277 t = usetype(d->ty);
278 d->ty = t;
279 dotprint(buf, buf+sizeof(buf), d->ty->decl, '_');
280 switch(d->ty->kind){
281 case Tadt:
282 print("typedef struct %s %s;\n", buf, buf);
283 break;
284 case Tint:
285 case Tbyte:
286 case Treal:
287 case Tbig:
288 case Tfix:
289 print("typedef %T %s;\n", t, buf);
290 break;
291 }
292 }
293 }
294 for(m = globals; m != nil; m = m->next){
295 if(m->store != Dtype || m->ty->kind != Tmodule)
296 continue;
297 for(d = m->ty->ids; d != nil; d = d->next){
298 if(d->store != Dtype)
299 continue;
300 t = d->ty;
301 if(t->kind == Tadt || t->kind == Ttuple && t->decl->sym != anontupsym){
302 if(t->tags != nil){
303 pickadtstub(t);
304 continue;
305 }
306 dotprint(buf, buf+sizeof(buf), t->decl, '_');
307 print("struct %s\n{\n", buf);
308 offset = 0;
309 for(id = t->ids; id != nil; id = id->next){
310 if(id->store == Dfield){
311 tt = id->ty;
312 offset = stubalign(offset, tt->align, nil, nil);
313 if(offset != id->offset)
314 fatal("adtstub bad offset");
315 print(" %R %s;\n", tt, id->sym->name);
316 offset += tt->size;
317 }
318 }
319 if(t->ids == nil){
320 print(" char dummy[1];\n");
321 offset = 1;
322 }
323 offset = stubalign(offset, t->align, nil ,nil);
324 offset = stubalign(offset, IBY2WD, nil , nil);
325 if(offset != t->size && t->ids != nil)
326 fatal("adtstub: bad size");
327 print("};\n");
328
329 for(id = t->ids; id != nil; id = id->next)
330 if(id->store == Dconst)
331 constub(id);
332
333 for(id = t->ids; id != nil; id = id->next)
334 if(id->ty->kind == Tchan)
335 chanstub(buf, id);
336
337 desc = mktdesc(t);
338 if(offset != desc->size && t->ids != nil)
339 fatal("adtstub: bad desc size");
340 print("#define %s_size %ld\n", buf, offset);
341 print("#define %s_map %M\n", buf, desc);
342 if(0)
343 print("struct %s_check {int s[2*(sizeof(%s)==%s_size)-1];};\n", buf, buf, buf);
344 }else if(t->kind == Tchan)
345 chanstub(m->sym->name, d);
346 }
347 }
348 }
349
350 /*
351 * emit an expicit pad field for aligning emitted c structs
352 * according to limbo's definition
353 */
354 static long
stubalign(long offset,int a,char ** buf,char * end)355 stubalign(long offset, int a, char **buf, char *end)
356 {
357 long x;
358
359 x = offset & (a-1);
360 if(x == 0)
361 return offset;
362 x = a - x;
363 if(buf == nil)
364 print("\tuchar\t_pad%ld[%ld];\n", offset, x);
365 else
366 *buf = seprint(*buf, end, "uchar\t_pad%ld[%ld]; ", offset, x);
367 offset += x;
368 if((offset & (a-1)) || x >= a)
369 fatal("compiler stub misalign");
370 return offset;
371 }
372
373 void
constub(Decl * id)374 constub(Decl *id)
375 {
376 char buf[StrSize*2];
377
378 seprint(buf, buf+sizeof(buf), "%s_%s", id->dot->sym->name, id->sym->name);
379 switch(id->ty->kind){
380 case Tbyte:
381 print("#define %s %d\n", buf, (int)id->init->val & 0xff);
382 break;
383 case Tint:
384 case Tfix:
385 print("#define %s %ld\n", buf, (long)id->init->val);
386 break;
387 case Tbig:
388 print("#define %s %ld\n", buf, (long)id->init->val);
389 break;
390 case Treal:
391 print("#define %s %g\n", buf, id->init->rval);
392 break;
393 case Tstring:
394 print("#define %s \"%s\"\n", buf, id->init->decl->sym->name);
395 break;
396 }
397 }
398
399 int
mapconv(Fmt * f)400 mapconv(Fmt *f)
401 {
402 Desc *d;
403 char *s, *e, buf[1024];
404 int i;
405
406 d = va_arg(f->args, Desc*);
407 e = buf+sizeof(buf);
408 s = buf;
409 s = secpy(s, e, "{");
410 for(i = 0; i < d->nmap; i++)
411 s = seprint(s, e, "0x%x,", d->map[i]);
412 if(i == 0)
413 s = seprint(s, e, "0");
414 seprint(s, e, "}");
415 return fmtstrcpy(f, buf);
416 }
417
418 char*
dotprint(char * buf,char * end,Decl * d,int dot)419 dotprint(char *buf, char *end, Decl *d, int dot)
420 {
421 if(d->dot != nil){
422 buf = dotprint(buf, end, d->dot, dot);
423 if(buf < end)
424 *buf++ = dot;
425 }
426 if(d->sym == nil)
427 return buf;
428 return seprint(buf, end, "%s", d->sym->name);
429 }
430
431 char *ckindname[Tend] =
432 {
433 /* Tnone */ "void",
434 /* Tadt */ "struct",
435 /* Tadtpick */ "?adtpick?",
436 /* Tarray */ "Array*",
437 /* Tbig */ "LONG",
438 /* Tbyte */ "BYTE",
439 /* Tchan */ "Channel*",
440 /* Treal */ "REAL",
441 /* Tfn */ "?fn?",
442 /* Tint */ "WORD",
443 /* Tlist */ "List*",
444 /* Tmodule */ "Modlink*",
445 /* Tref */ "?ref?",
446 /* Tstring */ "String*",
447 /* Ttuple */ "?tuple?",
448 /* Texception */ "?exception",
449 /* Tfix */ "WORD",
450 /* Tpoly */ "void*",
451
452 /* Tainit */ "?ainit?",
453 /* Talt */ "?alt?",
454 /* Tany */ "void*",
455 /* Tarrow */ "?arrow?",
456 /* Tcase */ "?case?",
457 /* Tcasel */ "?casel",
458 /* Tcasec */ "?casec?",
459 /* Tdot */ "?dot?",
460 /* Terror */ "?error?",
461 /* Tgoto */ "?goto?",
462 /* Tid */ "?id?",
463 /* Tiface */ "?iface?",
464 /* Texcept */ "?except?",
465 /* Tinst */ "?inst?",
466 };
467
468 char*
ctprint(char * buf,char * end,Type * t)469 ctprint(char *buf, char *end, Type *t)
470 {
471 Decl *id;
472 Type *tt;
473 long offset;
474
475 if(t == nil)
476 return secpy(buf, end, "void");
477 switch(t->kind){
478 case Tref:
479 return seprint(buf, end, "%R*", t->tof);
480 case Tarray:
481 case Tlist:
482 case Tint:
483 case Tbig:
484 case Tstring:
485 case Treal:
486 case Tbyte:
487 case Tnone:
488 case Tany:
489 case Tchan:
490 case Tmodule:
491 case Tfix:
492 case Tpoly:
493 return seprint(buf, end, "%s", ckindname[t->kind]);
494 case Tadtpick:
495 return ctprint(buf, end, t->decl->dot->ty);
496 case Tadt:
497 case Ttuple:
498 if(t->decl->sym != anontupsym)
499 return dotprint(buf, end, t->decl, '_');
500 offset = 0;
501 buf = secpy(buf, end, "struct{ ");
502 for(id = t->ids; id != nil; id = id->next){
503 tt = id->ty;
504 offset = stubalign(offset, tt->align, &buf, end);
505 if(offset != id->offset)
506 fatal("ctypeconv tuple bad offset");
507 buf = seprint(buf, end, "%R %s; ", tt, id->sym->name);
508 offset += tt->size;
509 }
510 offset = stubalign(offset, t->align, &buf, end);
511 if(offset != t->size)
512 fatal("ctypeconv tuple bad t=%T size=%ld offset=%ld", t, t->size, offset);
513 return secpy(buf, end, "}");
514 default:
515 if(t->kind >= Tend)
516 yyerror("no C equivalent for type %d", t->kind);
517 else
518 yyerror("no C equivalent for type %s", kindname[t->kind]);
519 break;
520 }
521 return buf;
522 }
523
524 static void
pickadtstub(Type * t)525 pickadtstub(Type *t)
526 {
527 Type *tt;
528 Desc *desc;
529 Decl *id, *tg;
530 char buf[2*StrSize];
531 int ok;
532 long offset, tgoffset;
533
534 dotprint(buf, buf+sizeof(buf), t->decl, '_');
535 offset = 0;
536 for(tg = t->tags; tg != nil; tg = tg->next)
537 print("#define %s_%s %ld\n", buf, tg->sym->name, offset++);
538 print("struct %s\n{\n", buf);
539 print(" int pick;\n");
540 offset = IBY2WD;
541 for(id = t->ids; id != nil; id = id->next){
542 if(id->store == Dfield){
543 tt = id->ty;
544 offset = stubalign(offset, tt->align, nil, nil);
545 if(offset != id->offset)
546 fatal("pickadtstub bad offset");
547 print(" %R %s;\n", tt, id->sym->name);
548 offset += tt->size;
549 }
550 }
551 print(" union{\n");
552 for(tg = t->tags; tg != nil; tg = tg->next){
553 tgoffset = offset;
554 print(" struct{\n");
555 for(id = tg->ty->ids; id != nil; id = id->next){
556 if(id->store == Dfield){
557 tt = id->ty;
558 tgoffset = stubalign(tgoffset, tt->align, nil, nil);
559 if(tgoffset != id->offset)
560 fatal("pickadtstub bad offset");
561 print(" %R %s;\n", tt, id->sym->name);
562 tgoffset += tt->size;
563 }
564 }
565 if(tg->ty->ids == nil)
566 print(" char dummy[1];\n");
567 print(" } %s;\n", tg->sym->name);
568 }
569 print(" } u;\n");
570 print("};\n");
571
572 for(id = t->ids; id != nil; id = id->next)
573 if(id->store == Dconst)
574 constub(id);
575
576 for(id = t->ids; id != nil; id = id->next)
577 if(id->ty->kind == Tchan)
578 chanstub(buf, id);
579
580 for(tg = t->tags; tg != nil; tg = tg->next){
581 ok = tg->ty->tof->ok;
582 tg->ty->tof->ok = OKverify;
583 sizetype(tg->ty->tof);
584 tg->ty->tof->ok = OKmask;
585 desc = mktdesc(tg->ty->tof);
586 tg->ty->tof->ok = ok;
587 print("#define %s_%s_size %ld\n", buf, tg->sym->name, tg->ty->size);
588 print("#define %s_%s_map %M\n", buf, tg->sym->name, desc);
589 }
590 }
591