pgen.c 10 KB

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