sgen.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588
  1. #include "gc.h"
  2. void
  3. codgen(Node *n, Node *nn)
  4. {
  5. Prog *sp;
  6. Node *n1, nod, nod1;
  7. cursafe = 0;
  8. curarg = 0;
  9. maxargsafe = 0;
  10. /*
  11. * isolate name
  12. */
  13. for(n1 = nn;; n1 = n1->left) {
  14. if(n1 == Z) {
  15. diag(nn, "cant find function name");
  16. return;
  17. }
  18. if(n1->op == ONAME)
  19. break;
  20. }
  21. nearln = nn->lineno;
  22. gpseudo(ATEXT, n1->sym, nodconst(stkoff));
  23. sp = p;
  24. /*
  25. * isolate first argument
  26. */
  27. if(REGARG != NREG) {
  28. if(typesu[thisfn->link->etype]) {
  29. nod1 = *nodret->left;
  30. nodreg(&nod, &nod1, REGARG);
  31. gopcode(OAS, &nod, Z, &nod1);
  32. } else
  33. if(firstarg && (typechlp[firstargtype->etype]||typev[firstargtype->etype])) {
  34. nod1 = *nodret->left;
  35. nod1.sym = firstarg;
  36. nod1.type = firstargtype;
  37. nod1.xoffset = align(0, firstargtype, Aarg1);
  38. nod1.etype = firstargtype->etype;
  39. nodreg(&nod, &nod1, REGARG);
  40. gopcode(OAS, &nod, Z, &nod1);
  41. }
  42. }
  43. retok = 0;
  44. gen(n);
  45. if(!retok)
  46. if(thisfn->link->etype != TVOID)
  47. warn(Z, "no return at end of function: %s", n1->sym->name);
  48. noretval(3);
  49. gbranch(ORETURN);
  50. if(!debug['N'] || debug['R'] || debug['P'])
  51. regopt(sp);
  52. maxargsafe = round(maxargsafe, 8); // probably a noop
  53. sp->to.offset += maxargsafe;
  54. }
  55. void
  56. gen(Node *n)
  57. {
  58. Node *l, nod;
  59. Prog *sp, *spc, *spb;
  60. Case *cn;
  61. long sbc, scc;
  62. int o;
  63. loop:
  64. if(n == Z)
  65. return;
  66. nearln = n->lineno;
  67. o = n->op;
  68. if(debug['G'])
  69. if(o != OLIST)
  70. print("%L %O\n", nearln, o);
  71. retok = 0;
  72. switch(o) {
  73. default:
  74. complex(n);
  75. cgen(n, Z);
  76. break;
  77. case OLIST:
  78. gen(n->left);
  79. rloop:
  80. n = n->right;
  81. goto loop;
  82. case ORETURN:
  83. retok = 1;
  84. complex(n);
  85. if(n->type == T)
  86. break;
  87. l = n->left;
  88. if(l == Z) {
  89. noretval(3);
  90. gbranch(ORETURN);
  91. break;
  92. }
  93. if(typesu[n->type->etype]) {
  94. sugen(l, nodret, n->type->width);
  95. noretval(3);
  96. gbranch(ORETURN);
  97. break;
  98. }
  99. regret(&nod, n);
  100. cgen(l, &nod);
  101. regfree(&nod);
  102. if(typefd[n->type->etype])
  103. noretval(1);
  104. else
  105. noretval(2);
  106. gbranch(ORETURN);
  107. break;
  108. case OLABEL:
  109. l = n->left;
  110. if(l) {
  111. l->pc = pc;
  112. if(l->label)
  113. patch(l->label, pc);
  114. }
  115. gbranch(OGOTO); /* prevent self reference in reg */
  116. patch(p, pc);
  117. goto rloop;
  118. case OGOTO:
  119. retok = 1;
  120. n = n->left;
  121. if(n == Z)
  122. return;
  123. if(n->complex == 0) {
  124. diag(Z, "label undefined: %s", n->sym->name);
  125. return;
  126. }
  127. gbranch(OGOTO);
  128. if(n->pc) {
  129. patch(p, n->pc);
  130. return;
  131. }
  132. if(n->label)
  133. patch(n->label, pc-1);
  134. n->label = p;
  135. return;
  136. case OCASE:
  137. l = n->left;
  138. if(cases == C)
  139. diag(n, "case/default outside a switch");
  140. if(l == Z) {
  141. cas();
  142. cases->val = 0;
  143. cases->def = 1;
  144. cases->label = pc;
  145. goto rloop;
  146. }
  147. complex(l);
  148. if(l->type == T)
  149. goto rloop;
  150. if(l->op == OCONST)
  151. if(typechl[l->type->etype]) {
  152. cas();
  153. cases->val = l->vconst;
  154. cases->def = 0;
  155. cases->label = pc;
  156. goto rloop;
  157. }
  158. diag(n, "case expression must be integer constant");
  159. goto rloop;
  160. case OSWITCH:
  161. l = n->left;
  162. complex(l);
  163. if(l->type == T)
  164. break;
  165. if(!typechl[l->type->etype]) {
  166. diag(n, "switch expression must be integer");
  167. break;
  168. }
  169. gbranch(OGOTO); /* entry */
  170. sp = p;
  171. cn = cases;
  172. cases = C;
  173. cas();
  174. sbc = breakpc;
  175. breakpc = pc;
  176. gbranch(OGOTO);
  177. spb = p;
  178. gen(n->right);
  179. gbranch(OGOTO);
  180. patch(p, breakpc);
  181. patch(sp, pc);
  182. regalloc(&nod, l, Z);
  183. nod.type = types[TLONG];
  184. cgen(l, &nod);
  185. doswit(&nod);
  186. regfree(&nod);
  187. patch(spb, pc);
  188. cases = cn;
  189. breakpc = sbc;
  190. break;
  191. case OWHILE:
  192. case ODWHILE:
  193. l = n->left;
  194. gbranch(OGOTO); /* entry */
  195. sp = p;
  196. scc = continpc;
  197. continpc = pc;
  198. gbranch(OGOTO);
  199. spc = p;
  200. sbc = breakpc;
  201. breakpc = pc;
  202. gbranch(OGOTO);
  203. spb = p;
  204. patch(spc, pc);
  205. if(n->op == OWHILE)
  206. patch(sp, pc);
  207. bcomplex(l); /* test */
  208. patch(p, breakpc);
  209. if(n->op == ODWHILE)
  210. patch(sp, pc);
  211. gen(n->right); /* body */
  212. gbranch(OGOTO);
  213. patch(p, continpc);
  214. patch(spb, pc);
  215. continpc = scc;
  216. breakpc = sbc;
  217. break;
  218. case OFOR:
  219. l = n->left;
  220. gen(l->right->left); /* init */
  221. gbranch(OGOTO); /* entry */
  222. sp = p;
  223. scc = continpc;
  224. continpc = pc;
  225. gbranch(OGOTO);
  226. spc = p;
  227. sbc = breakpc;
  228. breakpc = pc;
  229. gbranch(OGOTO);
  230. spb = p;
  231. patch(spc, pc);
  232. gen(l->right->right); /* inc */
  233. patch(sp, pc);
  234. if(l->left != Z) { /* test */
  235. bcomplex(l->left);
  236. patch(p, breakpc);
  237. }
  238. gen(n->right); /* body */
  239. gbranch(OGOTO);
  240. patch(p, continpc);
  241. patch(spb, pc);
  242. continpc = scc;
  243. breakpc = sbc;
  244. break;
  245. case OCONTINUE:
  246. if(continpc < 0) {
  247. diag(n, "continue not in a loop");
  248. break;
  249. }
  250. gbranch(OGOTO);
  251. patch(p, continpc);
  252. break;
  253. case OBREAK:
  254. if(breakpc < 0) {
  255. diag(n, "break not in a loop");
  256. break;
  257. }
  258. gbranch(OGOTO);
  259. patch(p, breakpc);
  260. break;
  261. case OIF:
  262. l = n->left;
  263. bcomplex(l);
  264. sp = p;
  265. if(n->right->left != Z)
  266. gen(n->right->left);
  267. if(n->right->right != Z) {
  268. gbranch(OGOTO);
  269. patch(sp, pc);
  270. sp = p;
  271. gen(n->right->right);
  272. }
  273. patch(sp, pc);
  274. break;
  275. case OSET:
  276. case OUSED:
  277. usedset(n->left, o);
  278. break;
  279. }
  280. }
  281. void
  282. usedset(Node *n, int o)
  283. {
  284. if(n->op == OLIST) {
  285. usedset(n->left, o);
  286. usedset(n->right, o);
  287. return;
  288. }
  289. complex(n);
  290. switch(n->op) {
  291. case OADDR: /* volatile */
  292. gins(ANOP, n, Z);
  293. break;
  294. case ONAME:
  295. if(o == OSET)
  296. gins(ANOP, Z, n);
  297. else
  298. gins(ANOP, n, Z);
  299. break;
  300. }
  301. }
  302. void
  303. noretval(int n)
  304. {
  305. if(n & 1) {
  306. gins(ANOP, Z, Z);
  307. p->to.type = D_REG;
  308. p->to.reg = REGRET;
  309. }
  310. if(n & 2) {
  311. gins(ANOP, Z, Z);
  312. p->to.type = D_FREG;
  313. p->to.reg = FREGRET;
  314. }
  315. }
  316. /*
  317. * calculate addressability as follows
  318. * CONST ==> 20 $value
  319. * NAME ==> 10 name
  320. * REGISTER ==> 11 register
  321. * INDREG ==> 12 *[(reg)+offset]
  322. * &10 ==> 2 $name
  323. * ADD(2, 20) ==> 2 $name+offset
  324. * ADD(3, 20) ==> 3 $(reg)+offset
  325. * &12 ==> 3 $(reg)+offset
  326. * *11 ==> 11 ??
  327. * *2 ==> 10 name
  328. * *3 ==> 12 *(reg)+offset
  329. * calculate complexity (number of registers)
  330. */
  331. void
  332. xcom(Node *n)
  333. {
  334. Node *l, *r;
  335. int t;
  336. if(n == Z)
  337. return;
  338. l = n->left;
  339. r = n->right;
  340. n->addable = 0;
  341. n->complex = 0;
  342. switch(n->op) {
  343. case OCONST:
  344. n->addable = 20;
  345. return;
  346. case OREGISTER:
  347. n->addable = 11;
  348. return;
  349. case OINDREG:
  350. n->addable = 12;
  351. return;
  352. case ONAME:
  353. n->addable = 10;
  354. return;
  355. case OADDR:
  356. xcom(l);
  357. if(l->addable == 10)
  358. n->addable = 2;
  359. if(l->addable == 12)
  360. n->addable = 3;
  361. break;
  362. case OIND:
  363. xcom(l);
  364. if(l->addable == 11)
  365. n->addable = 12;
  366. if(l->addable == 3)
  367. n->addable = 12;
  368. if(l->addable == 2)
  369. n->addable = 10;
  370. break;
  371. case OADD:
  372. xcom(l);
  373. xcom(r);
  374. if(l->addable == 20) {
  375. if(r->addable == 2)
  376. n->addable = 2;
  377. if(r->addable == 3)
  378. n->addable = 3;
  379. }
  380. if(r->addable == 20) {
  381. if(l->addable == 2)
  382. n->addable = 2;
  383. if(l->addable == 3)
  384. n->addable = 3;
  385. }
  386. break;
  387. case OASLMUL:
  388. case OASMUL:
  389. xcom(l);
  390. xcom(r);
  391. t = vlog(r);
  392. if(t >= 0) {
  393. n->op = OASASHL;
  394. r->vconst = t;
  395. r->type = types[TINT];
  396. }
  397. break;
  398. case OMUL:
  399. case OLMUL:
  400. xcom(l);
  401. xcom(r);
  402. t = vlog(r);
  403. if(t >= 0) {
  404. n->op = OASHL;
  405. r->vconst = t;
  406. r->type = types[TINT];
  407. }
  408. t = vlog(l);
  409. if(t >= 0) {
  410. n->op = OASHL;
  411. n->left = r;
  412. n->right = l;
  413. r = l;
  414. l = n->left;
  415. r->vconst = t;
  416. r->type = types[TINT];
  417. }
  418. break;
  419. case OASLDIV:
  420. xcom(l);
  421. xcom(r);
  422. t = vlog(r);
  423. if(t >= 0) {
  424. n->op = OASLSHR;
  425. r->vconst = t;
  426. r->type = types[TINT];
  427. }
  428. break;
  429. case OLDIV:
  430. xcom(l);
  431. xcom(r);
  432. t = vlog(r);
  433. if(t >= 0) {
  434. n->op = OLSHR;
  435. r->vconst = t;
  436. r->type = types[TINT];
  437. }
  438. break;
  439. case OASLMOD:
  440. xcom(l);
  441. xcom(r);
  442. t = vlog(r);
  443. if(t >= 0) {
  444. n->op = OASAND;
  445. r->vconst--;
  446. }
  447. break;
  448. case OLMOD:
  449. xcom(l);
  450. xcom(r);
  451. t = vlog(r);
  452. if(t >= 0) {
  453. n->op = OAND;
  454. r->vconst--;
  455. }
  456. break;
  457. default:
  458. if(l != Z)
  459. xcom(l);
  460. if(r != Z)
  461. xcom(r);
  462. break;
  463. }
  464. if(n->addable >= 10)
  465. return;
  466. if(l != Z)
  467. n->complex = l->complex;
  468. if(r != Z) {
  469. if(r->complex == n->complex)
  470. n->complex = r->complex+1;
  471. else
  472. if(r->complex > n->complex)
  473. n->complex = r->complex;
  474. }
  475. if(n->complex == 0)
  476. n->complex++;
  477. switch(n->op) {
  478. case OFUNC:
  479. n->complex = FNX;
  480. break;
  481. case OEQ:
  482. case ONE:
  483. case OLE:
  484. case OLT:
  485. case OGE:
  486. case OGT:
  487. case OHI:
  488. case OHS:
  489. case OLO:
  490. case OLS:
  491. /*
  492. * immediate operators, make const on right
  493. */
  494. if(l->op == OCONST) {
  495. n->left = r;
  496. n->right = l;
  497. n->op = invrel[relindex(n->op)];
  498. }
  499. break;
  500. case OADD:
  501. case OXOR:
  502. case OAND:
  503. case OOR:
  504. /*
  505. * immediate operators, make const on right
  506. */
  507. if(l->op == OCONST) {
  508. n->left = r;
  509. n->right = l;
  510. }
  511. break;
  512. }
  513. }
  514. void
  515. bcomplex(Node *n)
  516. {
  517. complex(n);
  518. if(n->type != T)
  519. if(tcompat(n, T, n->type, tnot))
  520. n->type = T;
  521. if(n->type != T) {
  522. boolgen(n, 1, Z);
  523. } else
  524. gbranch(OGOTO);
  525. }