cgen.c 17 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060
  1. #include "gc.h"
  2. void
  3. cgen(Node *n, Node *nn)
  4. {
  5. Node *l, *r;
  6. Prog *p1;
  7. Node nod, nod1, nod2, nod3, nod4;
  8. int o;
  9. long v, curs;
  10. if(debug['g']) {
  11. prtree(nn, "cgen lhs");
  12. prtree(n, "cgen");
  13. }
  14. if(n == Z || n->type == T)
  15. return;
  16. if(typesu[n->type->etype]) {
  17. sugen(n, nn, n->type->width);
  18. return;
  19. }
  20. l = n->left;
  21. r = n->right;
  22. o = n->op;
  23. if(n->addable >= INDEXED) {
  24. if(nn == Z) {
  25. switch(o) {
  26. default:
  27. nullwarn(Z, Z);
  28. break;
  29. case OINDEX:
  30. nullwarn(l, r);
  31. break;
  32. }
  33. return;
  34. }
  35. gmove(n, nn);
  36. return;
  37. }
  38. curs = cursafe;
  39. if(n->complex >= FNX)
  40. if(l->complex >= FNX)
  41. if(r != Z && r->complex >= FNX)
  42. switch(o) {
  43. default:
  44. regret(&nod, r);
  45. cgen(r, &nod);
  46. regsalloc(&nod1, r);
  47. gopcode(OAS, &nod, Z, &nod1);
  48. regfree(&nod);
  49. nod = *n;
  50. nod.right = &nod1;
  51. cgen(&nod, nn);
  52. return;
  53. case OFUNC:
  54. case OCOMMA:
  55. case OANDAND:
  56. case OOROR:
  57. case OCOND:
  58. case ODOT:
  59. break;
  60. }
  61. switch(o) {
  62. default:
  63. diag(n, "unknown op in cgen: %O", o);
  64. break;
  65. case OAS:
  66. if(l->op == OBIT)
  67. goto bitas;
  68. if(l->addable >= INDEXED && l->complex < FNX) {
  69. if(nn != Z || r->addable < INDEXED) {
  70. regalloc(&nod, r, nn);
  71. cgen(r, &nod);
  72. gmove(&nod, l);
  73. regfree(&nod);
  74. } else
  75. gmove(r, l);
  76. break;
  77. }
  78. if(l->complex >= r->complex) {
  79. reglcgen(&nod1, l, Z);
  80. if(r->addable >= INDEXED) {
  81. gmove(r, &nod1);
  82. if(nn != Z)
  83. gmove(r, nn);
  84. regfree(&nod1);
  85. break;
  86. }
  87. regalloc(&nod, r, nn);
  88. cgen(r, &nod);
  89. } else {
  90. regalloc(&nod, r, nn);
  91. cgen(r, &nod);
  92. reglcgen(&nod1, l, Z);
  93. }
  94. gmove(&nod, &nod1);
  95. regfree(&nod);
  96. regfree(&nod1);
  97. break;
  98. bitas:
  99. n = l->left;
  100. regalloc(&nod, r, nn);
  101. if(l->complex >= r->complex) {
  102. reglcgen(&nod1, n, Z);
  103. cgen(r, &nod);
  104. } else {
  105. cgen(r, &nod);
  106. reglcgen(&nod1, n, Z);
  107. }
  108. regalloc(&nod2, n, Z);
  109. gopcode(OAS, &nod1, Z, &nod2);
  110. bitstore(l, &nod, &nod1, &nod2, nn);
  111. break;
  112. case OBIT:
  113. if(nn == Z) {
  114. nullwarn(l, Z);
  115. break;
  116. }
  117. bitload(n, &nod, Z, Z, nn);
  118. gopcode(OAS, &nod, Z, nn);
  119. regfree(&nod);
  120. break;
  121. case OADD:
  122. case OSUB:
  123. case OAND:
  124. case OOR:
  125. case OXOR:
  126. case OLSHR:
  127. case OASHL:
  128. case OASHR:
  129. case OLDIV:
  130. case OLMOD:
  131. case ODIV:
  132. case OMOD:
  133. case OMUL:
  134. case OLMUL:
  135. /*
  136. * immediate operands
  137. */
  138. if(nn != Z)
  139. if(r->op == OCONST)
  140. if(!typefd[n->type->etype]) {
  141. cgen(l, nn);
  142. if(r->vconst == 0)
  143. if(o != OAND)
  144. break;
  145. if(nn != Z)
  146. gopcode(o, r, Z, nn);
  147. break;
  148. }
  149. if(nn == Z) {
  150. nullwarn(l, r);
  151. break;
  152. }
  153. /* if(o == OMUL || o == OLMUL) {
  154. if(mulcon(n, nn))
  155. break;
  156. } */
  157. if(l->complex >= r->complex) {
  158. regalloc(&nod, l, nn);
  159. cgen(l, &nod);
  160. regalloc(&nod1, l, Z); /* note: l used for type, so shifts work! */
  161. cgen(r, &nod1);
  162. gopcode(o, &nod1, Z, &nod);
  163. } else {
  164. regalloc(&nod, l, nn); /* note: l used for type, so shifts work! */
  165. cgen(r, &nod);
  166. regalloc(&nod1, l, Z);
  167. cgen(l, &nod1);
  168. gopcode(o, &nod, &nod1, &nod);
  169. }
  170. gopcode(OAS, &nod, Z, nn);
  171. regfree(&nod);
  172. regfree(&nod1);
  173. break;
  174. case OASLSHR:
  175. case OASASHL:
  176. case OASASHR:
  177. case OASAND:
  178. case OASADD:
  179. case OASSUB:
  180. case OASXOR:
  181. case OASOR:
  182. case OASLDIV:
  183. case OASLMOD:
  184. case OASDIV:
  185. case OASMOD:
  186. case OASLMUL:
  187. case OASMUL:
  188. if(l->op == OBIT)
  189. goto asbitop;
  190. if(r->op == OCONST)
  191. if(!typefd[n->type->etype]) {
  192. if(l->addable < INDEXED)
  193. reglcgen(&nod2, l, Z);
  194. else
  195. nod2 = *l;
  196. regalloc(&nod, l, nn); /* note: l used for type, so shifts work! */
  197. gopcode(OAS, &nod2, Z, &nod);
  198. gopcode(o, r, Z, &nod);
  199. gopcode(OAS, &nod, Z, &nod2);
  200. regfree(&nod);
  201. if(l->addable < INDEXED)
  202. regfree(&nod2);
  203. break;
  204. }
  205. if(l->op == OBIT)
  206. goto asbitop;
  207. if(l->complex >= r->complex) {
  208. if(l->addable < INDEXED)
  209. reglcgen(&nod2, l, Z);
  210. else
  211. nod2 = *l;
  212. regalloc(&nod1, l, Z); /* l used for type so shifts work */
  213. cgen(r, &nod1);
  214. } else {
  215. regalloc(&nod1, l, Z); /* l used for type so shifts work */
  216. cgen(r, &nod1);
  217. if(l->addable < INDEXED)
  218. reglcgen(&nod2, l, Z);
  219. else
  220. nod2 = *l;
  221. }
  222. regalloc(&nod, n, nn);
  223. gmove(&nod2, &nod);
  224. gopcode(o, &nod1, Z, &nod);
  225. gmove(&nod, &nod2);
  226. if(nn != Z)
  227. gopcode(OAS, &nod, Z, nn);
  228. regfree(&nod);
  229. regfree(&nod1);
  230. if(l->addable < INDEXED)
  231. regfree(&nod2);
  232. break;
  233. asbitop:
  234. regalloc(&nod4, n, nn);
  235. if(l->complex >= r->complex) {
  236. bitload(l, &nod, &nod1, &nod2, &nod4);
  237. regalloc(&nod3, r, Z);
  238. cgen(r, &nod3);
  239. } else {
  240. regalloc(&nod3, r, Z);
  241. cgen(r, &nod3);
  242. bitload(l, &nod, &nod1, &nod2, &nod4);
  243. }
  244. gmove(&nod, &nod4);
  245. gopcode(o, &nod3, Z, &nod4);
  246. regfree(&nod3);
  247. gmove(&nod4, &nod);
  248. regfree(&nod4);
  249. bitstore(l, &nod, &nod1, &nod2, nn);
  250. break;
  251. case OADDR:
  252. if(nn == Z) {
  253. nullwarn(l, Z);
  254. break;
  255. }
  256. lcgen(l, nn);
  257. break;
  258. case OFUNC:
  259. if(l->complex >= FNX) {
  260. if(l->op != OIND)
  261. diag(n, "bad function call");
  262. regret(&nod, l->left);
  263. cgen(l->left, &nod);
  264. regsalloc(&nod1, l->left);
  265. gopcode(OAS, &nod, Z, &nod1);
  266. regfree(&nod);
  267. nod = *n;
  268. nod.left = &nod2;
  269. nod2 = *l;
  270. nod2.left = &nod1;
  271. nod2.complex = 1;
  272. cgen(&nod, nn);
  273. return;
  274. }
  275. if(REGARG != NREG)
  276. o = reg[REGARG];
  277. gargs(r, &nod, &nod1);
  278. if(l->addable < INDEXED) {
  279. reglcgen(&nod, l, Z);
  280. gopcode(OFUNC, Z, Z, &nod);
  281. regfree(&nod);
  282. } else
  283. gopcode(OFUNC, Z, Z, l);
  284. if(REGARG != NREG)
  285. if(o != reg[REGARG])
  286. reg[REGARG]--;
  287. if(nn != Z) {
  288. regret(&nod, n);
  289. gopcode(OAS, &nod, Z, nn);
  290. regfree(&nod);
  291. }
  292. break;
  293. case OIND:
  294. if(nn == Z) {
  295. nullwarn(l, Z);
  296. break;
  297. }
  298. regialloc(&nod, n, nn);
  299. r = l;
  300. while(r->op == OADD)
  301. r = r->right;
  302. if(sconst(r)) {
  303. v = r->vconst;
  304. r->vconst = 0;
  305. cgen(l, &nod);
  306. nod.xoffset += v;
  307. r->vconst = v;
  308. } else
  309. cgen(l, &nod);
  310. regind(&nod, n);
  311. gopcode(OAS, &nod, Z, nn);
  312. regfree(&nod);
  313. break;
  314. case OEQ:
  315. case ONE:
  316. case OLE:
  317. case OLT:
  318. case OGE:
  319. case OGT:
  320. case OLO:
  321. case OLS:
  322. case OHI:
  323. case OHS:
  324. if(nn == Z) {
  325. nullwarn(l, r);
  326. break;
  327. }
  328. boolgen(n, 1, nn);
  329. break;
  330. case OANDAND:
  331. case OOROR:
  332. boolgen(n, 1, nn);
  333. if(nn == Z)
  334. patch(p, pc);
  335. break;
  336. case ONOT:
  337. if(nn == Z) {
  338. nullwarn(l, Z);
  339. break;
  340. }
  341. boolgen(n, 1, nn);
  342. break;
  343. case OCOMMA:
  344. cgen(l, Z);
  345. cgen(r, nn);
  346. break;
  347. case OCAST:
  348. if(nn == Z) {
  349. nullwarn(l, Z);
  350. break;
  351. }
  352. /*
  353. * convert from types l->n->nn
  354. */
  355. if(nocast(l->type, n->type)) {
  356. if(nocast(n->type, nn->type)) {
  357. cgen(l, nn);
  358. break;
  359. }
  360. }
  361. regalloc(&nod, l, nn);
  362. cgen(l, &nod);
  363. regalloc(&nod1, n, &nod);
  364. gopcode(OAS, &nod, Z, &nod1);
  365. gopcode(OAS, &nod1, Z, nn);
  366. regfree(&nod1);
  367. regfree(&nod);
  368. break;
  369. case ODOT:
  370. sugen(l, nodrat, l->type->width);
  371. if(nn != Z) {
  372. warn(n, "non-interruptable temporary");
  373. nod = *nodrat;
  374. if(!r || r->op != OCONST) {
  375. diag(n, "DOT and no offset");
  376. break;
  377. }
  378. nod.xoffset += (long)r->vconst;
  379. nod.type = n->type;
  380. cgen(&nod, nn);
  381. }
  382. break;
  383. case OCOND:
  384. bcgen(l, 1);
  385. p1 = p;
  386. cgen(r->left, nn);
  387. gbranch(OGOTO);
  388. patch(p1, pc);
  389. p1 = p;
  390. cgen(r->right, nn);
  391. patch(p1, pc);
  392. break;
  393. case OPOSTINC:
  394. case OPOSTDEC:
  395. v = 1;
  396. if(l->type->etype == TIND)
  397. v = l->type->link->width;
  398. if(o == OPOSTDEC)
  399. v = -v;
  400. if(l->op == OBIT)
  401. goto bitinc;
  402. if(nn == Z)
  403. goto pre;
  404. if(l->addable < INDEXED)
  405. reglcgen(&nod2, l, Z);
  406. else
  407. nod2 = *l;
  408. regalloc(&nod, l, nn);
  409. gopcode(OAS, &nod2, Z, &nod);
  410. regalloc(&nod1, l, Z);
  411. if(typefd[l->type->etype]) {
  412. regalloc(&nod3, l, Z);
  413. if(v < 0) {
  414. gopcode(OAS, nodfconst(-v), Z, &nod3);
  415. gopcode(OSUB, &nod3, &nod, &nod1);
  416. } else {
  417. gopcode(OAS, nodfconst(v), Z, &nod3);
  418. gopcode(OADD, &nod3, &nod, &nod1);
  419. }
  420. regfree(&nod3);
  421. } else
  422. gopcode(OADD, nodconst(v), &nod, &nod1);
  423. gopcode(OAS, &nod1, Z, &nod2);
  424. regfree(&nod);
  425. regfree(&nod1);
  426. if(l->addable < INDEXED)
  427. regfree(&nod2);
  428. break;
  429. case OPREINC:
  430. case OPREDEC:
  431. v = 1;
  432. if(l->type->etype == TIND)
  433. v = l->type->link->width;
  434. if(o == OPREDEC)
  435. v = -v;
  436. if(l->op == OBIT)
  437. goto bitinc;
  438. pre:
  439. if(l->addable < INDEXED)
  440. reglcgen(&nod2, l, Z);
  441. else
  442. nod2 = *l;
  443. regalloc(&nod, l, nn);
  444. gopcode(OAS, &nod2, Z, &nod);
  445. if(typefd[l->type->etype]) {
  446. regalloc(&nod3, l, Z);
  447. if(v < 0) {
  448. gopcode(OAS, nodfconst(-v), Z, &nod3);
  449. gopcode(OSUB, &nod3, Z, &nod);
  450. } else {
  451. gopcode(OAS, nodfconst(v), Z, &nod3);
  452. gopcode(OADD, &nod3, Z, &nod);
  453. }
  454. regfree(&nod3);
  455. } else
  456. gopcode(OADD, nodconst(v), Z, &nod);
  457. gopcode(OAS, &nod, Z, &nod2);
  458. regfree(&nod);
  459. if(l->addable < INDEXED)
  460. regfree(&nod2);
  461. break;
  462. bitinc:
  463. if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
  464. bitload(l, &nod, &nod1, &nod2, Z);
  465. gopcode(OAS, &nod, Z, nn);
  466. gopcode(OADD, nodconst(v), Z, &nod);
  467. bitstore(l, &nod, &nod1, &nod2, Z);
  468. break;
  469. }
  470. bitload(l, &nod, &nod1, &nod2, nn);
  471. gopcode(OADD, nodconst(v), Z, &nod);
  472. bitstore(l, &nod, &nod1, &nod2, nn);
  473. break;
  474. }
  475. cursafe = curs;
  476. return;
  477. }
  478. void
  479. reglcgen(Node *t, Node *n, Node *nn)
  480. {
  481. Node *r;
  482. long v;
  483. regialloc(t, n, nn);
  484. if(n->op == OIND) {
  485. r = n->left;
  486. while(r->op == OADD)
  487. r = r->right;
  488. if(sconst(r)) {
  489. v = r->vconst;
  490. r->vconst = 0;
  491. lcgen(n, t);
  492. t->xoffset += v;
  493. r->vconst = v;
  494. regind(t, n);
  495. return;
  496. }
  497. }
  498. lcgen(n, t);
  499. regind(t, n);
  500. }
  501. void
  502. lcgen(Node *n, Node *nn)
  503. {
  504. Prog *p1;
  505. Node nod;
  506. if(debug['g']) {
  507. prtree(nn, "lcgen lhs");
  508. prtree(n, "lcgen");
  509. }
  510. if(n == Z || n->type == T)
  511. return;
  512. if(nn == Z) {
  513. nn = &nod;
  514. regalloc(&nod, n, Z);
  515. }
  516. switch(n->op) {
  517. default:
  518. if(n->addable < INDEXED) {
  519. diag(n, "unknown op in lcgen: %O", n->op);
  520. break;
  521. }
  522. nod = *n;
  523. nod.op = OADDR;
  524. nod.left = n;
  525. nod.right = Z;
  526. nod.type = types[TIND];
  527. gopcode(OAS, &nod, Z, nn);
  528. break;
  529. case OCOMMA:
  530. cgen(n->left, n->left);
  531. lcgen(n->right, nn);
  532. break;
  533. case OIND:
  534. cgen(n->left, nn);
  535. break;
  536. case OCOND:
  537. bcgen(n->left, 1);
  538. p1 = p;
  539. lcgen(n->right->left, nn);
  540. gbranch(OGOTO);
  541. patch(p1, pc);
  542. p1 = p;
  543. lcgen(n->right->right, nn);
  544. patch(p1, pc);
  545. break;
  546. }
  547. }
  548. void
  549. bcgen(Node *n, int true)
  550. {
  551. if(n->type == T)
  552. gbranch(OGOTO);
  553. else
  554. boolgen(n, true, Z);
  555. }
  556. void
  557. boolgen(Node *n, int true, Node *nn)
  558. {
  559. int o;
  560. Prog *p1, *p2;
  561. Node *l, *r, nod, nod1;
  562. long curs;
  563. if(debug['g']) {
  564. prtree(nn, "boolgen lhs");
  565. prtree(n, "boolgen");
  566. }
  567. curs = cursafe;
  568. l = n->left;
  569. r = n->right;
  570. switch(n->op) {
  571. default:
  572. regalloc(&nod, n, nn);
  573. cgen(n, &nod);
  574. o = ONE;
  575. if(true)
  576. o = comrel[relindex(o)];
  577. if(typefd[n->type->etype]) {
  578. nodreg(&nod1, n, NREG+FREGZERO);
  579. gopcode(o, &nod, Z, &nod1);
  580. } else
  581. gopcode(o, &nod, Z, nodconst(0));
  582. regfree(&nod);
  583. goto com;
  584. case OCONST:
  585. o = vconst(n);
  586. if(!true)
  587. o = !o;
  588. gbranch(OGOTO);
  589. if(o) {
  590. p1 = p;
  591. gbranch(OGOTO);
  592. patch(p1, pc);
  593. }
  594. goto com;
  595. case OCOMMA:
  596. cgen(l, Z);
  597. boolgen(r, true, nn);
  598. break;
  599. case ONOT:
  600. boolgen(l, !true, nn);
  601. break;
  602. case OCOND:
  603. bcgen(l, 1);
  604. p1 = p;
  605. bcgen(r->left, true);
  606. p2 = p;
  607. gbranch(OGOTO);
  608. patch(p1, pc);
  609. p1 = p;
  610. bcgen(r->right, !true);
  611. patch(p2, pc);
  612. p2 = p;
  613. gbranch(OGOTO);
  614. patch(p1, pc);
  615. patch(p2, pc);
  616. goto com;
  617. case OANDAND:
  618. if(!true)
  619. goto caseor;
  620. caseand:
  621. bcgen(l, true);
  622. p1 = p;
  623. bcgen(r, !true);
  624. p2 = p;
  625. patch(p1, pc);
  626. gbranch(OGOTO);
  627. patch(p2, pc);
  628. goto com;
  629. case OOROR:
  630. if(!true)
  631. goto caseand;
  632. caseor:
  633. bcgen(l, !true);
  634. p1 = p;
  635. bcgen(r, !true);
  636. p2 = p;
  637. gbranch(OGOTO);
  638. patch(p1, pc);
  639. patch(p2, pc);
  640. goto com;
  641. case OEQ:
  642. case ONE:
  643. case OLE:
  644. case OLT:
  645. case OGE:
  646. case OGT:
  647. case OHI:
  648. case OHS:
  649. case OLO:
  650. case OLS:
  651. o = n->op;
  652. if(true)
  653. o = comrel[relindex(o)];
  654. if(l->complex >= FNX && r->complex >= FNX) {
  655. regret(&nod, r);
  656. cgen(r, &nod);
  657. regsalloc(&nod1, r);
  658. gopcode(OAS, &nod, Z, &nod1);
  659. regfree(&nod);
  660. nod = *n;
  661. nod.right = &nod1;
  662. boolgen(&nod, true, nn);
  663. break;
  664. }
  665. if(bconst(r)) {
  666. regalloc(&nod, l, nn);
  667. cgen(l, &nod);
  668. gopcode(o, &nod, Z, r);
  669. regfree(&nod);
  670. goto com;
  671. }
  672. if(l->complex >= r->complex) {
  673. regalloc(&nod1, l, nn);
  674. cgen(l, &nod1);
  675. regalloc(&nod, r, Z);
  676. cgen(r, &nod);
  677. } else {
  678. regalloc(&nod, r, nn);
  679. cgen(r, &nod);
  680. regalloc(&nod1, l, Z);
  681. cgen(l, &nod1);
  682. }
  683. gopcode(o, &nod1, Z, &nod);
  684. regfree(&nod);
  685. regfree(&nod1);
  686. com:
  687. if(nn != Z) {
  688. p1 = p;
  689. gopcode(OAS, nodconst(1), Z, nn);
  690. gbranch(OGOTO);
  691. p2 = p;
  692. patch(p1, pc);
  693. gopcode(OAS, nodconst(0), Z, nn);
  694. patch(p2, pc);
  695. }
  696. break;
  697. }
  698. cursafe = curs;
  699. }
  700. void
  701. sugen(Node *n, Node *nn, long w)
  702. {
  703. Prog *p1;
  704. Node nod0, nod1, nod2, nod3, nod4, *l, *r;
  705. Type *t;
  706. long pc1;
  707. int i, m, c;
  708. if(n == Z || n->type == T)
  709. return;
  710. if(debug['g']) {
  711. prtree(nn, "sugen lhs");
  712. prtree(n, "sugen");
  713. }
  714. if(nn == nodrat)
  715. if(w > nrathole)
  716. nrathole = w;
  717. switch(n->op) {
  718. case OIND:
  719. if(nn == Z) {
  720. nullwarn(n->left, Z);
  721. break;
  722. }
  723. default:
  724. goto copy;
  725. case ODOT:
  726. l = n->left;
  727. sugen(l, nodrat, l->type->width);
  728. if(nn != Z) {
  729. warn(n, "non-interruptable temporary");
  730. nod1 = *nodrat;
  731. r = n->right;
  732. if(!r || r->op != OCONST) {
  733. diag(n, "DOT and no offset");
  734. break;
  735. }
  736. nod1.xoffset += (long)r->vconst;
  737. nod1.type = n->type;
  738. sugen(&nod1, nn, w);
  739. }
  740. break;
  741. case OSTRUCT:
  742. /*
  743. * rewrite so lhs has no fn call
  744. */
  745. if(nn != Z && nn->complex >= FNX) {
  746. nod1 = *n;
  747. nod1.type = typ(TIND, n->type);
  748. regret(&nod2, &nod1);
  749. lcgen(nn, &nod2);
  750. regsalloc(&nod0, &nod1);
  751. gopcode(OAS, &nod2, Z, &nod0);
  752. regfree(&nod2);
  753. nod1 = *n;
  754. nod1.op = OIND;
  755. nod1.left = &nod0;
  756. nod1.right = Z;
  757. nod1.complex = 1;
  758. sugen(n, &nod1, w);
  759. return;
  760. }
  761. r = n->left;
  762. for(t = n->type->link; t != T; t = t->down) {
  763. l = r;
  764. if(r->op == OLIST) {
  765. l = r->left;
  766. r = r->right;
  767. }
  768. if(nn == Z) {
  769. cgen(l, nn);
  770. continue;
  771. }
  772. /*
  773. * hand craft *(&nn + o) = l
  774. */
  775. nod0 = znode;
  776. nod0.op = OAS;
  777. nod0.type = t;
  778. nod0.left = &nod1;
  779. nod0.right = l;
  780. nod1 = znode;
  781. nod1.op = OIND;
  782. nod1.type = t;
  783. nod1.left = &nod2;
  784. nod2 = znode;
  785. nod2.op = OADD;
  786. nod2.type = typ(TIND, t);
  787. nod2.left = &nod3;
  788. nod2.right = &nod4;
  789. nod3 = znode;
  790. nod3.op = OADDR;
  791. nod3.type = nod2.type;
  792. nod3.left = nn;
  793. nod4 = znode;
  794. nod4.op = OCONST;
  795. nod4.type = nod2.type;
  796. nod4.vconst = t->offset;
  797. ccom(&nod0);
  798. acom(&nod0);
  799. xcom(&nod0);
  800. nod0.addable = 0;
  801. /* prtree(&nod0, "hand craft"); /* */
  802. cgen(&nod0, Z);
  803. }
  804. break;
  805. case OAS:
  806. if(nn == Z) {
  807. if(n->addable < INDEXED)
  808. sugen(n->right, n->left, w);
  809. break;
  810. }
  811. sugen(n->right, nodrat, w);
  812. warn(n, "non-interruptable temporary");
  813. sugen(nodrat, n->left, w);
  814. sugen(nodrat, nn, w);
  815. break;
  816. case OFUNC:
  817. if(nn == Z) {
  818. sugen(n, nodrat, w);
  819. break;
  820. }
  821. if(nn->op != OIND) {
  822. nn = new1(OADDR, nn, Z);
  823. nn->type = types[TIND];
  824. nn->addable = 0;
  825. } else
  826. nn = nn->left;
  827. n = new(OFUNC, n->left, new(OLIST, nn, n->right));
  828. n->type = types[TVOID];
  829. n->left->type = types[TVOID];
  830. cgen(n, Z);
  831. break;
  832. case OCOND:
  833. bcgen(n->left, 1);
  834. p1 = p;
  835. sugen(n->right->left, nn, w);
  836. gbranch(OGOTO);
  837. patch(p1, pc);
  838. p1 = p;
  839. sugen(n->right->right, nn, w);
  840. patch(p1, pc);
  841. break;
  842. case OCOMMA:
  843. cgen(n->left, Z);
  844. sugen(n->right, nn, w);
  845. break;
  846. }
  847. return;
  848. copy:
  849. if(nn == Z)
  850. return;
  851. if(n->complex >= FNX && nn->complex >= FNX) {
  852. t = nn->type;
  853. nn->type = types[TLONG];
  854. regialloc(&nod1, nn, Z);
  855. lcgen(nn, &nod1);
  856. regsalloc(&nod2, nn);
  857. nn->type = t;
  858. gopcode(OAS, &nod1, Z, &nod2);
  859. regfree(&nod1);
  860. nod2.type = typ(TIND, t);
  861. nod1 = nod2;
  862. nod1.op = OIND;
  863. nod1.left = &nod2;
  864. nod1.right = Z;
  865. nod1.complex = 1;
  866. nod1.type = t;
  867. sugen(n, &nod1, w);
  868. return;
  869. }
  870. if(n->complex > nn->complex) {
  871. t = n->type;
  872. n->type = types[TLONG];
  873. reglcgen(&nod1, n, Z);
  874. n->type = t;
  875. t = nn->type;
  876. nn->type = types[TLONG];
  877. reglcgen(&nod2, nn, Z);
  878. nn->type = t;
  879. } else {
  880. t = nn->type;
  881. nn->type = types[TLONG];
  882. reglcgen(&nod2, nn, Z);
  883. nn->type = t;
  884. t = n->type;
  885. n->type = types[TLONG];
  886. reglcgen(&nod1, n, Z);
  887. n->type = t;
  888. }
  889. w /= SZ_LONG;
  890. if(w <= 5) {
  891. layout(&nod1, &nod2, w, 0, Z);
  892. goto out;
  893. }
  894. /*
  895. * minimize space for unrolling loop
  896. * 3,4,5 times. (6 or more is never minimum)
  897. * if small structure, try 2 also.
  898. */
  899. c = 0; /* set */
  900. m = 100;
  901. i = 3;
  902. if(w <= 15)
  903. i = 2;
  904. for(; i<=5; i++)
  905. if(i + w%i <= m) {
  906. c = i;
  907. m = c + w%c;
  908. }
  909. regalloc(&nod3, &regnode, Z);
  910. layout(&nod1, &nod2, w%c, w/c, &nod3);
  911. pc1 = pc;
  912. layout(&nod1, &nod2, c, 0, Z);
  913. gopcode(OSUB, nodconst(1), Z, &nod3);
  914. nod1.op = OREGISTER;
  915. gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod1);
  916. nod2.op = OREGISTER;
  917. gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod2);
  918. gopcode(OGT, &nod3, Z, nodconst(0));
  919. patch(p, pc1);
  920. regfree(&nod3);
  921. out:
  922. regfree(&nod1);
  923. regfree(&nod2);
  924. }
  925. void
  926. layout(Node *f, Node *t, int c, int cv, Node *cn)
  927. {
  928. Node t1, t2;
  929. while(c > 3) {
  930. layout(f, t, 2, 0, Z);
  931. c -= 2;
  932. }
  933. regalloc(&t1, &regnode, Z);
  934. regalloc(&t2, &regnode, Z);
  935. if(c > 0) {
  936. gopcode(OAS, f, Z, &t1);
  937. f->xoffset += SZ_LONG;
  938. }
  939. if(cn != Z)
  940. gopcode(OAS, nodconst(cv), Z, cn);
  941. if(c > 1) {
  942. gopcode(OAS, f, Z, &t2);
  943. f->xoffset += SZ_LONG;
  944. }
  945. if(c > 0) {
  946. gopcode(OAS, &t1, Z, t);
  947. t->xoffset += SZ_LONG;
  948. }
  949. if(c > 2) {
  950. gopcode(OAS, f, Z, &t1);
  951. f->xoffset += SZ_LONG;
  952. }
  953. if(c > 1) {
  954. gopcode(OAS, &t2, Z, t);
  955. t->xoffset += SZ_LONG;
  956. }
  957. if(c > 2) {
  958. gopcode(OAS, &t1, Z, t);
  959. t->xoffset += SZ_LONG;
  960. }
  961. regfree(&t1);
  962. regfree(&t2);
  963. }