cgen.c 17 KB

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