pgen.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  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. hasdoubled = 0;
  11. /*
  12. * isolate name
  13. */
  14. for(n1 = nn;; n1 = n1->left) {
  15. if(n1 == Z) {
  16. diag(nn, "cant find function name");
  17. return;
  18. }
  19. if(n1->op == ONAME)
  20. break;
  21. }
  22. nearln = nn->lineno;
  23. gpseudo(ATEXT, n1->sym, nodconst(stkoff));
  24. sp = p;
  25. if(typecmplx[thisfn->link->etype]) {
  26. if(nodret == nil) {
  27. nodret = new(ONAME, Z, Z);
  28. nodret->sym = slookup(".ret");
  29. nodret->class = CPARAM;
  30. nodret->type = types[TIND];
  31. nodret->etype = TIND;
  32. nodret = new(OIND, nodret, Z);
  33. }
  34. n1 = nodret->left;
  35. if(n1->type == T || n1->type->link != thisfn->link) {
  36. n1->type = typ(TIND, thisfn->link);
  37. n1->etype = n1->type->etype;
  38. nodret = new(OIND, n1, Z);
  39. complex(nodret);
  40. }
  41. }
  42. /*
  43. * isolate first argument
  44. */
  45. if(REGARG >= 0) {
  46. if(typecmplx[thisfn->link->etype]) {
  47. nod1 = *nodret->left;
  48. nodreg(&nod, &nod1, REGARG);
  49. gmove(&nod, &nod1);
  50. } else
  51. if(firstarg && typeword[firstargtype->etype]) {
  52. nod1 = znode;
  53. nod1.op = ONAME;
  54. nod1.sym = firstarg;
  55. nod1.type = firstargtype;
  56. nod1.class = CPARAM;
  57. nod1.xoffset = align(0, firstargtype, Aarg1);
  58. nod1.etype = firstargtype->etype;
  59. xcom(&nod1);
  60. nodreg(&nod, &nod1, REGARG);
  61. gmove(&nod, &nod1);
  62. }
  63. }
  64. canreach = 1;
  65. warnreach = 1;
  66. gen(n);
  67. if(canreach && thisfn->link->etype != TVOID){
  68. if(debug['B'])
  69. warn(Z, "no return at end of function: %s", n1->sym->name);
  70. else
  71. diag(Z, "no return at end of function: %s", n1->sym->name);
  72. }
  73. noretval(3);
  74. gbranch(ORETURN);
  75. if(!debug['N'] || debug['R'] || debug['P'])
  76. regopt(sp);
  77. if(thechar=='6' || thechar=='7' || thechar=='9' || hasdoubled) /* [sic] */
  78. maxargsafe = round(maxargsafe, 8);
  79. sp->to.offset += maxargsafe;
  80. }
  81. void
  82. supgen(Node *n)
  83. {
  84. int owarn;
  85. long spc;
  86. Prog *sp;
  87. if(n == Z)
  88. return;
  89. suppress++;
  90. owarn = warnreach;
  91. warnreach = 0;
  92. spc = pc;
  93. sp = lastp;
  94. gen(n);
  95. lastp = sp;
  96. pc = spc;
  97. sp->link = nil;
  98. suppress--;
  99. warnreach = owarn;
  100. }
  101. Node*
  102. uncomma(Node *n)
  103. {
  104. while(n != Z && n->op == OCOMMA) {
  105. cgen(n->left, Z);
  106. n = n->right;
  107. }
  108. return n;
  109. }
  110. void
  111. gen(Node *n)
  112. {
  113. Node *l, nod, rn;
  114. Prog *sp, *spc, *spb;
  115. Case *cn;
  116. long sbc, scc;
  117. int snbreak, sncontin;
  118. int f, o, oldreach;
  119. loop:
  120. if(n == Z)
  121. return;
  122. nearln = n->lineno;
  123. o = n->op;
  124. if(debug['G'])
  125. if(o != OLIST)
  126. print("%L %O\n", nearln, o);
  127. if(!canreach) {
  128. switch(o) {
  129. case OLABEL:
  130. case OCASE:
  131. case OLIST:
  132. case OCOMMA:
  133. case OBREAK:
  134. case OFOR:
  135. case OWHILE:
  136. case ODWHILE:
  137. /* all handled specially - see switch body below */
  138. break;
  139. default:
  140. if(warnreach) {
  141. warn(n, "unreachable code %O", o);
  142. warnreach = 0;
  143. }
  144. }
  145. }
  146. switch(o) {
  147. default:
  148. complex(n);
  149. cgen(n, Z);
  150. break;
  151. case OLIST:
  152. case OCOMMA:
  153. gen(n->left);
  154. rloop:
  155. n = n->right;
  156. goto loop;
  157. case ORETURN:
  158. canreach = 0;
  159. warnreach = !suppress;
  160. complex(n);
  161. if(n->type == T)
  162. break;
  163. l = uncomma(n->left);
  164. if(l == Z) {
  165. noretval(3);
  166. gbranch(ORETURN);
  167. break;
  168. }
  169. if(typecmplx[n->type->etype]) {
  170. nod = znode;
  171. nod.op = OAS;
  172. nod.left = nodret;
  173. nod.right = l;
  174. nod.type = n->type;
  175. nod.complex = l->complex;
  176. cgen(&nod, Z);
  177. noretval(3);
  178. gbranch(ORETURN);
  179. break;
  180. }
  181. if(newvlongcode && !typefd[n->type->etype]){
  182. regret(&rn, n);
  183. regfree(&rn);
  184. nod = znode;
  185. nod.op = OAS;
  186. nod.left = &rn;
  187. nod.right = l;
  188. nod.type = n->type;
  189. nod.complex = l->complex;
  190. cgen(&nod, Z);
  191. noretval(2);
  192. gbranch(ORETURN);
  193. break;
  194. }
  195. regret(&nod, n);
  196. cgen(l, &nod);
  197. regfree(&nod);
  198. if(typefd[n->type->etype])
  199. noretval(1);
  200. else
  201. noretval(2);
  202. gbranch(ORETURN);
  203. break;
  204. case OLABEL:
  205. canreach = 1;
  206. l = n->left;
  207. if(l) {
  208. l->pc = pc;
  209. if(l->label)
  210. patch(l->label, pc);
  211. }
  212. gbranch(OGOTO); /* prevent self reference in reg */
  213. patch(p, pc);
  214. goto rloop;
  215. case OGOTO:
  216. canreach = 0;
  217. warnreach = !suppress;
  218. n = n->left;
  219. if(n == Z)
  220. return;
  221. if(n->complex == 0) {
  222. diag(Z, "label undefined: %s", n->sym->name);
  223. return;
  224. }
  225. if(suppress)
  226. return;
  227. gbranch(OGOTO);
  228. if(n->pc) {
  229. patch(p, n->pc);
  230. return;
  231. }
  232. if(n->label)
  233. patch(n->label, pc-1);
  234. n->label = p;
  235. return;
  236. case OCASE:
  237. canreach = 1;
  238. l = n->left;
  239. if(cases == C)
  240. diag(n, "case/default outside a switch");
  241. if(l == Z) {
  242. casf();
  243. cases->val = 0;
  244. cases->def = 1;
  245. cases->label = pc;
  246. cases->isv = 0;
  247. goto rloop;
  248. }
  249. complex(l);
  250. if(l->type == T)
  251. goto rloop;
  252. if(l->op != OCONST || !typeswitch[l->type->etype]) {
  253. diag(n, "case expression must be integer constant");
  254. goto rloop;
  255. }
  256. casf();
  257. cases->val = l->vconst;
  258. cases->def = 0;
  259. cases->label = pc;
  260. cases->isv = typev[l->type->etype];
  261. goto rloop;
  262. case OSWITCH:
  263. l = n->left;
  264. complex(l);
  265. if(l->type == T)
  266. break;
  267. if(!typeswitch[l->type->etype]) {
  268. diag(n, "switch expression must be integer");
  269. break;
  270. }
  271. gbranch(OGOTO); /* entry */
  272. sp = p;
  273. cn = cases;
  274. cases = C;
  275. casf();
  276. sbc = breakpc;
  277. breakpc = pc;
  278. snbreak = nbreak;
  279. nbreak = 0;
  280. gbranch(OGOTO);
  281. spb = p;
  282. gen(n->right); /* body */
  283. if(canreach){
  284. gbranch(OGOTO);
  285. patch(p, breakpc);
  286. nbreak++;
  287. }
  288. patch(sp, pc);
  289. regalloc(&nod, l, Z);
  290. /* always signed */
  291. if(typev[l->type->etype])
  292. nod.type = types[TVLONG];
  293. else
  294. nod.type = types[TLONG];
  295. cgen(l, &nod);
  296. doswit(&nod);
  297. regfree(&nod);
  298. patch(spb, pc);
  299. cases = cn;
  300. breakpc = sbc;
  301. canreach = nbreak!=0;
  302. if(canreach == 0)
  303. warnreach = !suppress;
  304. nbreak = snbreak;
  305. break;
  306. case OWHILE:
  307. case ODWHILE:
  308. l = n->left;
  309. gbranch(OGOTO); /* entry */
  310. sp = p;
  311. scc = continpc;
  312. continpc = pc;
  313. gbranch(OGOTO);
  314. spc = p;
  315. sbc = breakpc;
  316. breakpc = pc;
  317. snbreak = nbreak;
  318. nbreak = 0;
  319. gbranch(OGOTO);
  320. spb = p;
  321. patch(spc, pc);
  322. if(n->op == OWHILE)
  323. patch(sp, pc);
  324. bcomplex(l, Z); /* test */
  325. patch(p, breakpc);
  326. if(l->op != OCONST || vconst(l) == 0)
  327. nbreak++;
  328. if(n->op == ODWHILE)
  329. patch(sp, pc);
  330. gen(n->right); /* body */
  331. gbranch(OGOTO);
  332. patch(p, continpc);
  333. patch(spb, pc);
  334. continpc = scc;
  335. breakpc = sbc;
  336. canreach = nbreak!=0;
  337. if(canreach == 0)
  338. warnreach = !suppress;
  339. nbreak = snbreak;
  340. break;
  341. case OFOR:
  342. l = n->left;
  343. if(!canreach && l->right->left && warnreach) {
  344. warn(n, "unreachable code FOR");
  345. warnreach = 0;
  346. }
  347. gen(l->right->left); /* init */
  348. gbranch(OGOTO); /* entry */
  349. sp = p;
  350. /*
  351. * if there are no incoming labels in the
  352. * body and the top's not reachable, warn
  353. */
  354. if(!canreach && warnreach && deadheads(n)) {
  355. warn(n, "unreachable code %O", o);
  356. warnreach = 0;
  357. }
  358. scc = continpc;
  359. continpc = pc;
  360. gbranch(OGOTO);
  361. spc = p;
  362. sbc = breakpc;
  363. breakpc = pc;
  364. snbreak = nbreak;
  365. nbreak = 0;
  366. sncontin = ncontin;
  367. ncontin = 0;
  368. gbranch(OGOTO);
  369. spb = p;
  370. patch(spc, pc);
  371. gen(l->right->right); /* inc */
  372. patch(sp, pc);
  373. if(l->left != Z) { /* test */
  374. bcomplex(l->left, Z);
  375. patch(p, breakpc);
  376. if(l->left->op != OCONST || vconst(l->left) == 0)
  377. nbreak++;
  378. }
  379. canreach = 1;
  380. gen(n->right); /* body */
  381. if(canreach){
  382. gbranch(OGOTO);
  383. patch(p, continpc);
  384. ncontin++;
  385. }
  386. if(!ncontin && l->right->right && warnreach) {
  387. warn(l->right->right, "unreachable FOR inc");
  388. warnreach = 0;
  389. }
  390. patch(spb, pc);
  391. continpc = scc;
  392. breakpc = sbc;
  393. canreach = nbreak!=0;
  394. if(canreach == 0)
  395. warnreach = !suppress;
  396. nbreak = snbreak;
  397. ncontin = sncontin;
  398. break;
  399. case OCONTINUE:
  400. if(continpc < 0) {
  401. diag(n, "continue not in a loop");
  402. break;
  403. }
  404. gbranch(OGOTO);
  405. patch(p, continpc);
  406. ncontin++;
  407. canreach = 0;
  408. warnreach = !suppress;
  409. break;
  410. case OBREAK:
  411. if(breakpc < 0) {
  412. diag(n, "break not in a loop");
  413. break;
  414. }
  415. /*
  416. * Don't complain about unreachable break statements.
  417. * There are breaks hidden in yacc's output and some people
  418. * write return; break; in their switch statements out of habit.
  419. * However, don't confuse the analysis by inserting an
  420. * unreachable reference to breakpc either.
  421. */
  422. if(!canreach)
  423. break;
  424. gbranch(OGOTO);
  425. patch(p, breakpc);
  426. nbreak++;
  427. canreach = 0;
  428. warnreach = !suppress;
  429. break;
  430. case OIF:
  431. l = n->left;
  432. if(bcomplex(l, n->right)) {
  433. if(typefd[l->type->etype])
  434. f = !l->fconst;
  435. else
  436. f = !l->vconst;
  437. if(debug['c'])
  438. print("%L const if %s\n", nearln, f ? "false" : "true");
  439. if(f) {
  440. canreach = 1;
  441. supgen(n->right->left);
  442. oldreach = canreach;
  443. canreach = 1;
  444. gen(n->right->right);
  445. /*
  446. * treat constant ifs as regular ifs for
  447. * reachability warnings.
  448. */
  449. if(!canreach && oldreach && debug['w'] < 2)
  450. warnreach = 0;
  451. }
  452. else {
  453. canreach = 1;
  454. gen(n->right->left);
  455. oldreach = canreach;
  456. canreach = 1;
  457. supgen(n->right->right);
  458. /*
  459. * treat constant ifs as regular ifs for
  460. * reachability warnings.
  461. */
  462. if(!oldreach && canreach && debug['w'] < 2)
  463. warnreach = 0;
  464. canreach = oldreach;
  465. }
  466. }
  467. else {
  468. sp = p;
  469. canreach = 1;
  470. if(n->right->left != Z)
  471. gen(n->right->left);
  472. oldreach = canreach;
  473. canreach = 1;
  474. if(n->right->right != Z) {
  475. gbranch(OGOTO);
  476. patch(sp, pc);
  477. sp = p;
  478. gen(n->right->right);
  479. }
  480. patch(sp, pc);
  481. canreach = canreach || oldreach;
  482. if(canreach == 0)
  483. warnreach = !suppress;
  484. }
  485. break;
  486. case OSET:
  487. case OUSED:
  488. usedset(n->left, o);
  489. break;
  490. }
  491. }
  492. void
  493. usedset(Node *n, int o)
  494. {
  495. if(n->op == OLIST) {
  496. usedset(n->left, o);
  497. usedset(n->right, o);
  498. return;
  499. }
  500. complex(n);
  501. switch(n->op) {
  502. case OADDR: /* volatile */
  503. gins(ANOP, n, Z);
  504. break;
  505. case ONAME:
  506. if(o == OSET)
  507. gins(ANOP, Z, n);
  508. else
  509. gins(ANOP, n, Z);
  510. break;
  511. }
  512. }
  513. int
  514. bcomplex(Node *n, Node *c)
  515. {
  516. Node *b, nod;
  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. gbranch(OGOTO);
  523. return 0;
  524. }
  525. if(c != Z && n->op == OCONST && deadheads(c))
  526. return 1;
  527. if(newvlongcode && typev[n->type->etype] && machcap(Z)) {
  528. nod = znode;
  529. b = &nod;
  530. b->op = ONE;
  531. b->left = n;
  532. b->right = new(0, Z, Z);
  533. *b->right = *nodconst(0);
  534. b->right->type = n->type;
  535. b->type = types[TLONG];
  536. xcom(b);
  537. boolgen(b, 1, Z);
  538. return 0;
  539. }
  540. bool64(n);
  541. boolgen(n, 1, Z);
  542. return 0;
  543. }