cgen.c 16 KB

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