code.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612
  1. /* $Header$ */
  2. /*
  3. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
  4. * See the copyright notice in the ACK home directory, in the file "Copyright".
  5. */
  6. #include "em.h"
  7. #include "expr.h"
  8. #include "symtab.h"
  9. #include "sizes.h"
  10. #include "Lpars.h"
  11. #include "code.h"
  12. extern err;
  13. static void subscript();
  14. enum addr_val { address, value };
  15. void code_val(e) register struct expr *e;
  16. /* Compile e for its value, which is put on the stack. */
  17. {
  18. register struct expr *left, *right;
  19. if (err) return;
  20. switch(e->kind) {
  21. case E_NODE:
  22. left=e->u.node.left;
  23. right=e->u.node.right;
  24. switch (e->u.node.op) {
  25. case '+':
  26. case '-':
  27. case '*':
  28. case '/':
  29. case BS:
  30. code_val(left);
  31. code_val(right);
  32. xxi(e->u.node.op);
  33. break;
  34. case '<':
  35. case '>':
  36. case LE:
  37. case GE:
  38. case NE:
  39. case '=':
  40. code_val(left);
  41. code_val(right);
  42. cmi();
  43. Txx(e->u.node.op);
  44. break;
  45. case AFTER:
  46. code_val(left);
  47. code_val(right);
  48. xxi('-');
  49. cvw();
  50. tst();
  51. Txx('>');
  52. break;
  53. case BA:
  54. code_val(left);
  55. code_val(right);
  56. and();
  57. break;
  58. case BO:
  59. code_val(left);
  60. code_val(right);
  61. ior();
  62. break;
  63. case BX:
  64. code_val(left);
  65. code_val(right);
  66. xor();
  67. break;
  68. case AND:
  69. case OR: {
  70. int T=0, F=0, L=0;
  71. code_bool(e, positive, &T, &F);
  72. Label(T);
  73. Loc(-1L);
  74. branch(&L);
  75. Label(F);
  76. Loc(0L);
  77. Label(L);
  78. }break;
  79. case LS:
  80. code_val(left);
  81. code_val(right);
  82. cvw();
  83. sli();
  84. break;
  85. case RS:
  86. code_val(left);
  87. code_val(right);
  88. cvw();
  89. sri();
  90. break;
  91. case '~':
  92. code_val(left);
  93. ngi();
  94. break;
  95. case NOT:
  96. code_val(left);
  97. com();
  98. break;
  99. case '[':
  100. subscript(e, value);
  101. break;
  102. }
  103. break;
  104. case E_VAR: {
  105. register struct symbol *var=e->u.var;
  106. if (var->type&T_BUILTIN)
  107. Loe(var->info.vc.st.builtin, var->info.vc.offset);
  108. else
  109. if (var->info.vc.st.level==curr_level)
  110. if (var->type&T_PARAM && (var->type&T_TYPE)!=T_VALUE)
  111. Lil(var->info.vc.offset);
  112. else
  113. Lol(var->info.vc.offset);
  114. else {
  115. if (var->info.vc.offset<0)
  116. lxl(curr_level-var->info.vc.st.level);
  117. else
  118. lxa(curr_level-var->info.vc.st.level);
  119. if (var->type&T_PARAM && (var->type&T_TYPE)!=T_VALUE)
  120. Lif(var->info.vc.offset);
  121. else
  122. Lof(var->info.vc.offset);
  123. }
  124. }break;
  125. case E_CONST:
  126. Loc(e->u.const);
  127. break;
  128. case E_NOW:
  129. cal("now");
  130. lfr(vz);
  131. break;
  132. }
  133. }
  134. static void subscript(e, av) register struct expr *e; enum addr_val av;
  135. /* Produce code to compute the address or value of e->left[e->right] or
  136. * the address of e->left[e->right->left FOR e->right->right].
  137. */
  138. {
  139. register char *des;
  140. register struct expr *left;
  141. register struct expr *index;
  142. code_addr(left=e->u.node.left);
  143. if ((index=e->u.node.right)->kind==E_NODE && index->u.node.op==FOR)
  144. index=index->u.node.left;
  145. if (left->arr_siz==0) {
  146. if ((left->type&T_TYPE)==T_CHAN)
  147. des="maxcdes";
  148. else
  149. des= e->type&T_BYTE ? "maxbdes" : "maxwdes";
  150. } else {
  151. register lsiz=left->arr_siz;
  152. if (left->type&T_BYTE && !(e->type&T_BYTE))
  153. lsiz/=vz;
  154. else
  155. if (!(left->type&T_BYTE) && e->type&T_BYTE)
  156. lsiz*=vz;
  157. if (e->type&T_ARR)
  158. lsiz-=(e->arr_siz -1);
  159. if (constant(index)) {
  160. if (index->u.const<0 || index->u.const>=lsiz) {
  161. warning("constant index outside vector");
  162. lin();
  163. loc(0);
  164. trp();
  165. }
  166. } else {
  167. loc(lsiz);
  168. if ((left->type&T_TYPE)==T_CHAN)
  169. des="chandes";
  170. else
  171. des= e->type&T_BYTE ? "bytedes" : "worddes";
  172. ste(des, wz);
  173. }
  174. }
  175. if (constant(index)) {
  176. register offset=index->u.const;
  177. if ((left->type&T_TYPE)==T_CHAN)
  178. offset*=(wz+vz);
  179. else
  180. if ( !(e->type&T_BYTE) )
  181. offset*=vz;
  182. if (av==address)
  183. adp(offset);
  184. else {
  185. if (e->type&T_BYTE) {
  186. adp(offset);
  187. loi(1);
  188. cwv();
  189. } else
  190. Lof(offset);
  191. }
  192. } else {
  193. code_val(index);
  194. cvw();
  195. lin();
  196. lae(des, 0);
  197. if (av==address) {
  198. aar();
  199. } else {
  200. lar();
  201. if (e->type&T_BYTE) cwv();
  202. }
  203. }
  204. }
  205. void code_addr(e) register struct expr *e;
  206. /* The address of e is wat we want. */
  207. {
  208. if (err) return;
  209. switch(e->kind) {
  210. case E_NODE:
  211. subscript(e, address);
  212. break;
  213. case E_VAR: { /* variable or channel */
  214. register struct symbol *var=e->u.var;
  215. if (var->type&T_BUILTIN)
  216. lae(var->info.vc.st.builtin, var->info.vc.offset);
  217. else
  218. if (var->info.vc.st.level==curr_level)
  219. if (var->type&T_PARAM
  220. && (var->type&(T_TYPE|T_ARR))!=T_VALUE)
  221. Lolp(var->info.vc.offset);
  222. else
  223. lal(var->info.vc.offset);
  224. else {
  225. if (var->info.vc.offset<0)
  226. lxl(curr_level-var->info.vc.st.level);
  227. else
  228. lxa(curr_level-var->info.vc.st.level);
  229. if (var->type&T_PARAM
  230. && (var->type&(T_TYPE|T_ARR))!=T_VALUE)
  231. Lofp(var->info.vc.offset);
  232. else
  233. adp(var->info.vc.offset);
  234. }
  235. } break;
  236. case E_TABLE:
  237. case E_BTAB:
  238. laedot(e->u.tab);
  239. break;
  240. }
  241. }
  242. void code_bool(e, pos, T, F)
  243. register struct expr *e;
  244. register pos;
  245. register int *T, *F;
  246. /* if e = pos then
  247. fall through or jump to T;
  248. else
  249. jump to F;
  250. fi
  251. */
  252. {
  253. register Default=0;
  254. if (err) return;
  255. if (e->kind==E_NODE) {
  256. register struct expr *left=e->u.node.left;
  257. register struct expr *right=e->u.node.right;
  258. switch(e->u.node.op) {
  259. case '<':
  260. case '>':
  261. case LE:
  262. case GE:
  263. case NE:
  264. case '=':
  265. case AFTER:
  266. code_val(left);
  267. code_val(right);
  268. bxx(pos, e->u.node.op, new_label(F));
  269. break;
  270. case AND:
  271. case OR:
  272. if ((e->u.node.op==AND && pos)
  273. || (e->u.node.op==OR && !pos)
  274. ) {
  275. int L=0;
  276. code_bool(left, pos, &L, F);
  277. Label(L);
  278. code_bool(right, pos, T, F);
  279. } else {
  280. int L=0;
  281. code_bool(left, !pos, &L, T);
  282. Label(L);
  283. code_bool(right, pos, T, F);
  284. }
  285. break;
  286. case NOT:
  287. code_bool(left, !pos, T, F);
  288. break;
  289. default:
  290. Default=1;
  291. }
  292. } else
  293. Default=1;
  294. if (Default) {
  295. code_val(e);
  296. if (vz>wz) {
  297. ldc0();
  298. cmi();
  299. } else
  300. tst();
  301. if (pos) zeq(new_label(F)); else zne(new_label(F));
  302. }
  303. }
  304. void code_assignment(e) register struct expr *e;
  305. /* e->left := e->right */
  306. {
  307. register struct expr *left=e->u.node.left;
  308. register struct expr *right=e->u.node.right;
  309. if (left->type&T_ARR) {
  310. register siz=left->arr_siz;
  311. code_addr(right);
  312. code_addr(left);
  313. blm(left->type&T_BYTE ? siz : siz*vz);
  314. } else {
  315. code_val(right);
  316. code_addr(left);
  317. sti(left->type&T_BYTE ? 1 : vz);
  318. }
  319. }
  320. void code_input(e) register struct expr *e;
  321. /* Input one v from c ? v0; v1; ... */
  322. {
  323. if (e==nil) {
  324. lae("any", 0);
  325. cal("chan_in");
  326. asp(pz);
  327. } else
  328. if (e->type&T_ARR) {
  329. loc(e->arr_siz);
  330. code_addr(e);
  331. cal(e->type&T_BYTE ? "c_ba_in" : "c_wa_in");
  332. asp(pz+wz);
  333. } else {
  334. code_addr(e);
  335. cal(e->type&T_BYTE ? "cbyte_in" : "chan_in");
  336. asp(pz);
  337. }
  338. }
  339. void code_output(e) register struct expr *e;
  340. /* Output one e from c ? e0; e1; ... */
  341. {
  342. if (e==nil) {
  343. Loc(0L);
  344. cal("chan_out");
  345. asp(vz);
  346. } else
  347. if (e->type&T_ARR) {
  348. loc(e->arr_siz);
  349. code_addr(e);
  350. cal(e->type&T_BYTE ? "c_ba_out" : "c_wa_out");
  351. asp(pz+wz);
  352. } else {
  353. code_val(e);
  354. cal("chan_out");
  355. asp(vz);
  356. }
  357. }
  358. void code_any(e, NO) register struct expr *e; int *NO;
  359. /* Test if the channel (push address on stack) has input. If not so remove the
  360. * channel pointer and jump to NO. Otherwise input values.
  361. */
  362. {
  363. int YES=0;
  364. register struct expr_list *elp;
  365. if (err) return;
  366. code_addr(e->u.io.chan);
  367. cal("chan_any");
  368. lfr(wz);
  369. tst();
  370. zne(new_label(&YES));
  371. asp(pz);
  372. branch(NO);
  373. Label(YES);
  374. elp=e->u.io.args;
  375. while (elp!=nil) {
  376. code_input(elp->arg);
  377. elp=elp->next;
  378. }
  379. asp(pz);
  380. }
  381. void code_void(e) register struct expr *e;
  382. /* Assignment, I/O, or procedure call. */
  383. {
  384. if (err) return;
  385. switch (e->kind) {
  386. case E_NODE: /* Must be assignment */
  387. code_assignment(e);
  388. break;
  389. case E_IO: {
  390. register struct expr_list *elp;
  391. code_addr(e->u.io.chan);
  392. elp=e->u.io.args;
  393. while (elp!=nil) {
  394. if (e->u.io.out)
  395. code_output(elp->arg);
  396. else
  397. code_input(elp->arg);
  398. elp=elp->next;
  399. }
  400. asp(pz);
  401. }
  402. break;
  403. case E_CALL: {
  404. register size=0;
  405. register struct expr_list *elp=e->u.call.args;
  406. register struct symbol *proc=e->u.call.proc->u.var;
  407. register struct par_list *pars=proc->info.proc.pars;
  408. while (elp!=nil) {
  409. if (pars->type==T_VALUE) {
  410. code_val(elp->arg);
  411. size+=vz;
  412. } else {
  413. code_addr(elp->arg);
  414. size+=pz;
  415. }
  416. elp=elp->next;
  417. pars=pars->next;
  418. }
  419. if (proc->type&T_BUILTIN) {
  420. cal(proc->info.proc.st.builtin);
  421. asp(size);
  422. } else {
  423. if (proc->info.proc.st.level>curr_level) {
  424. /* Call down */
  425. lor0();
  426. } else
  427. if (proc->info.proc.st.level==curr_level) {
  428. /* Call at same level */
  429. Lolp(0);
  430. } else {
  431. /* Call up */
  432. lxa(curr_level-proc->info.proc.st.level);
  433. loi(pz);
  434. }
  435. cal(proc_label(proc->info.proc.label, proc->name));
  436. asp(size+pz);
  437. if (proc->info.proc.file!=curr_file) fil();
  438. }
  439. } break;
  440. }
  441. }
  442. void prologue(proc) register struct symbol *proc;
  443. /* Open up the scope for a new proc definition. */
  444. {
  445. static P=0;
  446. if (err) return;
  447. proc->info.proc.st.level= ++curr_level;
  448. proc->info.proc.file= curr_file;
  449. proc->info.proc.label= ++P;
  450. curr_offset=min_offset=0;
  451. pro(proc_label(proc->info.proc.label, proc->name));
  452. if (curr_level==1) fil();
  453. }
  454. void epilogue(proc) register struct symbol *proc;
  455. /* Close the scope of a proc def. */
  456. {
  457. if (err) return;
  458. curr_level--;
  459. ret(0);
  460. _end(-min_offset);
  461. }
  462. void rep_init(v, e1, e2, r_info)
  463. struct symbol *v;
  464. register struct expr *e1, *e2;
  465. register struct replicator *r_info;
  466. /* Compile v=[e1 FOR e2]. Info tells rep_test what decisions rep_init makes. */
  467. {
  468. if (err) return;
  469. r_info->BEGIN=r_info->END=0;
  470. code_val(e1);
  471. Stl(v->info.vc.offset);
  472. if (!constant(e1) || !constant(e2)) {
  473. if (constant(e2) && word_constant(e2->u.const)) {
  474. r_info->counter=memory(wz);
  475. loc((int) e2->u.const);
  476. stl(r_info->counter);
  477. } else {
  478. r_info->counter=memory(vz);
  479. code_val(e2);
  480. Stl(r_info->counter);
  481. }
  482. }
  483. if (!constant(e2) || e2->u.const<=0L)
  484. branch(&r_info->END);
  485. Label(new_label(&r_info->BEGIN));
  486. }
  487. void rep_test(v, e1, e2, r_info)
  488. register struct symbol *v;
  489. register struct expr *e1, *e2;
  490. register struct replicator *r_info;
  491. {
  492. if (err) return;
  493. Inl(v->info.vc.offset);
  494. if (constant(e1) && constant(e2)) {
  495. Lol(v->info.vc.offset);
  496. Loc(e1->u.const+e2->u.const);
  497. if (vz>wz) {
  498. cmi();
  499. zlt(r_info->BEGIN);
  500. } else
  501. blt(r_info->BEGIN);
  502. Label(r_info->END);
  503. } else {
  504. if (constant(e2) && word_constant(e2->u.const)) {
  505. del(r_info->counter);
  506. Label(r_info->END);
  507. lol(r_info->counter);
  508. tst();
  509. } else {
  510. Del(r_info->counter);
  511. Label(r_info->END);
  512. Lol(r_info->counter);
  513. if (vz>wz) {
  514. ldc0();
  515. cmi();
  516. } else
  517. tst();
  518. }
  519. zgt(r_info->BEGIN);
  520. }
  521. }
  522. void chan_init(info, arr_siz) union type_info *info; int arr_siz;
  523. /* Garbage disposal unit for fresh channels. */
  524. {
  525. if (err) return;
  526. loc(arr_siz);
  527. lal(info->vc.offset);
  528. cal("c_init");
  529. asp(wz+pz);
  530. }
  531. void leader()
  532. {
  533. init();
  534. openfile((char *) nil);
  535. magic();
  536. meswp();
  537. maxdes();
  538. }
  539. void header()
  540. {
  541. exp("main");
  542. pro("main");
  543. init_rt();
  544. main_fil();
  545. }
  546. void trailer()
  547. {
  548. if (err)
  549. meserr();
  550. else {
  551. loc(0);
  552. ret(wz);
  553. _end(-min_offset);
  554. }
  555. closefile();
  556. }