stubs.c 14 KB

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