cgen.c 17 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067
  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. if(nn && l->op == ONAME) /* in x=++i, emit USED(i) */
  464. gins(ANOP, l, Z);
  465. regfree(&nod);
  466. if(l->addable < INDEXED)
  467. regfree(&nod2);
  468. break;
  469. bitinc:
  470. if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
  471. bitload(l, &nod, &nod1, &nod2, Z);
  472. gopcode(OAS, &nod, Z, nn);
  473. gopcode(OADD, nodconst(v), Z, &nod);
  474. bitstore(l, &nod, &nod1, &nod2, Z);
  475. break;
  476. }
  477. bitload(l, &nod, &nod1, &nod2, nn);
  478. gopcode(OADD, nodconst(v), Z, &nod);
  479. bitstore(l, &nod, &nod1, &nod2, nn);
  480. break;
  481. }
  482. cursafe = curs;
  483. return;
  484. }
  485. void
  486. reglcgen(Node *t, Node *n, Node *nn)
  487. {
  488. Node *r;
  489. long v;
  490. regialloc(t, n, nn);
  491. if(n->op == OIND) {
  492. r = n->left;
  493. while(r->op == OADD)
  494. r = r->right;
  495. if(sconst(r)) {
  496. v = r->vconst;
  497. r->vconst = 0;
  498. lcgen(n, t);
  499. t->xoffset += v;
  500. r->vconst = v;
  501. regind(t, n);
  502. return;
  503. }
  504. }
  505. lcgen(n, t);
  506. regind(t, n);
  507. }
  508. void
  509. lcgen(Node *n, Node *nn)
  510. {
  511. Prog *p1;
  512. Node nod;
  513. if(debug['g']) {
  514. prtree(nn, "lcgen lhs");
  515. prtree(n, "lcgen");
  516. }
  517. if(n == Z || n->type == T)
  518. return;
  519. if(nn == Z) {
  520. nn = &nod;
  521. regalloc(&nod, n, Z);
  522. }
  523. switch(n->op) {
  524. default:
  525. if(n->addable < INDEXED) {
  526. diag(n, "unknown op in lcgen: %O", n->op);
  527. break;
  528. }
  529. nod = *n;
  530. nod.op = OADDR;
  531. nod.left = n;
  532. nod.right = Z;
  533. nod.type = types[TIND];
  534. gopcode(OAS, &nod, Z, nn);
  535. break;
  536. case OCOMMA:
  537. cgen(n->left, n->left);
  538. lcgen(n->right, nn);
  539. break;
  540. case OIND:
  541. cgen(n->left, nn);
  542. break;
  543. case OCOND:
  544. bcgen(n->left, 1);
  545. p1 = p;
  546. lcgen(n->right->left, nn);
  547. gbranch(OGOTO);
  548. patch(p1, pc);
  549. p1 = p;
  550. lcgen(n->right->right, nn);
  551. patch(p1, pc);
  552. break;
  553. }
  554. }
  555. void
  556. bcgen(Node *n, int true)
  557. {
  558. if(n->type == T)
  559. gbranch(OGOTO);
  560. else
  561. boolgen(n, true, Z);
  562. }
  563. void
  564. boolgen(Node *n, int true, Node *nn)
  565. {
  566. int o;
  567. Prog *p1, *p2;
  568. Node *l, *r, nod, nod1;
  569. long curs;
  570. if(debug['g']) {
  571. prtree(nn, "boolgen lhs");
  572. prtree(n, "boolgen");
  573. }
  574. curs = cursafe;
  575. l = n->left;
  576. r = n->right;
  577. switch(n->op) {
  578. default:
  579. regalloc(&nod, n, nn);
  580. cgen(n, &nod);
  581. o = ONE;
  582. if(true)
  583. o = comrel[relindex(o)];
  584. if(typefd[n->type->etype]) {
  585. nodreg(&nod1, n, NREG+FREGZERO);
  586. gopcode(o, &nod, Z, &nod1);
  587. } else
  588. gopcode(o, &nod, Z, nodconst(0));
  589. regfree(&nod);
  590. goto com;
  591. case OCONST:
  592. o = vconst(n);
  593. if(!true)
  594. o = !o;
  595. gbranch(OGOTO);
  596. if(o) {
  597. p1 = p;
  598. gbranch(OGOTO);
  599. patch(p1, pc);
  600. }
  601. goto com;
  602. case OCOMMA:
  603. cgen(l, Z);
  604. boolgen(r, true, nn);
  605. break;
  606. case ONOT:
  607. boolgen(l, !true, nn);
  608. break;
  609. case OCOND:
  610. bcgen(l, 1);
  611. p1 = p;
  612. bcgen(r->left, true);
  613. p2 = p;
  614. gbranch(OGOTO);
  615. patch(p1, pc);
  616. p1 = p;
  617. bcgen(r->right, !true);
  618. patch(p2, pc);
  619. p2 = p;
  620. gbranch(OGOTO);
  621. patch(p1, pc);
  622. patch(p2, pc);
  623. goto com;
  624. case OANDAND:
  625. if(!true)
  626. goto caseor;
  627. caseand:
  628. bcgen(l, true);
  629. p1 = p;
  630. bcgen(r, !true);
  631. p2 = p;
  632. patch(p1, pc);
  633. gbranch(OGOTO);
  634. patch(p2, pc);
  635. goto com;
  636. case OOROR:
  637. if(!true)
  638. goto caseand;
  639. caseor:
  640. bcgen(l, !true);
  641. p1 = p;
  642. bcgen(r, !true);
  643. p2 = p;
  644. gbranch(OGOTO);
  645. patch(p1, pc);
  646. patch(p2, pc);
  647. goto com;
  648. case OEQ:
  649. case ONE:
  650. case OLE:
  651. case OLT:
  652. case OGE:
  653. case OGT:
  654. case OHI:
  655. case OHS:
  656. case OLO:
  657. case OLS:
  658. o = n->op;
  659. if(true)
  660. o = comrel[relindex(o)];
  661. if(l->complex >= FNX && r->complex >= FNX) {
  662. regret(&nod, r);
  663. cgen(r, &nod);
  664. regsalloc(&nod1, r);
  665. gopcode(OAS, &nod, Z, &nod1);
  666. regfree(&nod);
  667. nod = *n;
  668. nod.right = &nod1;
  669. boolgen(&nod, true, nn);
  670. break;
  671. }
  672. if(bconst(r)) {
  673. regalloc(&nod, l, nn);
  674. cgen(l, &nod);
  675. gopcode(o, &nod, Z, r);
  676. regfree(&nod);
  677. goto com;
  678. }
  679. if(l->complex >= r->complex) {
  680. regalloc(&nod1, l, nn);
  681. cgen(l, &nod1);
  682. regalloc(&nod, r, Z);
  683. cgen(r, &nod);
  684. } else {
  685. regalloc(&nod, r, nn);
  686. cgen(r, &nod);
  687. regalloc(&nod1, l, Z);
  688. cgen(l, &nod1);
  689. }
  690. gopcode(o, &nod1, Z, &nod);
  691. regfree(&nod);
  692. regfree(&nod1);
  693. com:
  694. if(nn != Z) {
  695. p1 = p;
  696. gopcode(OAS, nodconst(1), Z, nn);
  697. gbranch(OGOTO);
  698. p2 = p;
  699. patch(p1, pc);
  700. gopcode(OAS, nodconst(0), Z, nn);
  701. patch(p2, pc);
  702. }
  703. break;
  704. }
  705. cursafe = curs;
  706. }
  707. void
  708. sugen(Node *n, Node *nn, long w)
  709. {
  710. Prog *p1;
  711. Node nod0, nod1, nod2, nod3, nod4, *l, *r;
  712. Type *t;
  713. long pc1;
  714. int i, m, c;
  715. if(n == Z || n->type == T)
  716. return;
  717. if(debug['g']) {
  718. prtree(nn, "sugen lhs");
  719. prtree(n, "sugen");
  720. }
  721. if(nn == nodrat)
  722. if(w > nrathole)
  723. nrathole = w;
  724. switch(n->op) {
  725. case OIND:
  726. if(nn == Z) {
  727. nullwarn(n->left, Z);
  728. break;
  729. }
  730. default:
  731. goto copy;
  732. case ODOT:
  733. l = n->left;
  734. sugen(l, nodrat, l->type->width);
  735. if(nn != Z) {
  736. warn(n, "non-interruptable temporary");
  737. nod1 = *nodrat;
  738. r = n->right;
  739. if(!r || r->op != OCONST) {
  740. diag(n, "DOT and no offset");
  741. break;
  742. }
  743. nod1.xoffset += (long)r->vconst;
  744. nod1.type = n->type;
  745. sugen(&nod1, nn, w);
  746. }
  747. break;
  748. case OSTRUCT:
  749. /*
  750. * rewrite so lhs has no fn call
  751. */
  752. if(nn != Z && nn->complex >= FNX) {
  753. nod1 = *n;
  754. nod1.type = typ(TIND, n->type);
  755. regret(&nod2, &nod1);
  756. lcgen(nn, &nod2);
  757. regsalloc(&nod0, &nod1);
  758. gopcode(OAS, &nod2, Z, &nod0);
  759. regfree(&nod2);
  760. nod1 = *n;
  761. nod1.op = OIND;
  762. nod1.left = &nod0;
  763. nod1.right = Z;
  764. nod1.complex = 1;
  765. sugen(n, &nod1, w);
  766. return;
  767. }
  768. r = n->left;
  769. for(t = n->type->link; t != T; t = t->down) {
  770. l = r;
  771. if(r->op == OLIST) {
  772. l = r->left;
  773. r = r->right;
  774. }
  775. if(nn == Z) {
  776. cgen(l, nn);
  777. continue;
  778. }
  779. /*
  780. * hand craft *(&nn + o) = l
  781. */
  782. nod0 = znode;
  783. nod0.op = OAS;
  784. nod0.type = t;
  785. nod0.left = &nod1;
  786. nod0.right = l;
  787. nod1 = znode;
  788. nod1.op = OIND;
  789. nod1.type = t;
  790. nod1.left = &nod2;
  791. nod2 = znode;
  792. nod2.op = OADD;
  793. nod2.type = typ(TIND, t);
  794. nod2.left = &nod3;
  795. nod2.right = &nod4;
  796. nod3 = znode;
  797. nod3.op = OADDR;
  798. nod3.type = nod2.type;
  799. nod3.left = nn;
  800. nod4 = znode;
  801. nod4.op = OCONST;
  802. nod4.type = nod2.type;
  803. nod4.vconst = t->offset;
  804. ccom(&nod0);
  805. acom(&nod0);
  806. xcom(&nod0);
  807. nod0.addable = 0;
  808. /* prtree(&nod0, "hand craft"); /* */
  809. cgen(&nod0, Z);
  810. }
  811. break;
  812. case OAS:
  813. if(nn == Z) {
  814. if(n->addable < INDEXED)
  815. sugen(n->right, n->left, w);
  816. break;
  817. }
  818. sugen(n->right, nodrat, w);
  819. warn(n, "non-interruptable temporary");
  820. sugen(nodrat, n->left, w);
  821. sugen(nodrat, nn, w);
  822. break;
  823. case OFUNC:
  824. if(nn == Z) {
  825. sugen(n, nodrat, w);
  826. break;
  827. }
  828. if(nn->op != OIND) {
  829. nn = new1(OADDR, nn, Z);
  830. nn->type = types[TIND];
  831. nn->addable = 0;
  832. } else
  833. nn = nn->left;
  834. n = new(OFUNC, n->left, new(OLIST, nn, n->right));
  835. n->type = types[TVOID];
  836. n->left->type = types[TVOID];
  837. cgen(n, Z);
  838. break;
  839. case OCOND:
  840. bcgen(n->left, 1);
  841. p1 = p;
  842. sugen(n->right->left, nn, w);
  843. gbranch(OGOTO);
  844. patch(p1, pc);
  845. p1 = p;
  846. sugen(n->right->right, nn, w);
  847. patch(p1, pc);
  848. break;
  849. case OCOMMA:
  850. cgen(n->left, Z);
  851. sugen(n->right, nn, w);
  852. break;
  853. }
  854. return;
  855. copy:
  856. if(nn == Z)
  857. return;
  858. if(n->complex >= FNX && nn->complex >= FNX) {
  859. t = nn->type;
  860. nn->type = types[TLONG];
  861. regialloc(&nod1, nn, Z);
  862. lcgen(nn, &nod1);
  863. regsalloc(&nod2, nn);
  864. nn->type = t;
  865. gopcode(OAS, &nod1, Z, &nod2);
  866. regfree(&nod1);
  867. nod2.type = typ(TIND, t);
  868. nod1 = nod2;
  869. nod1.op = OIND;
  870. nod1.left = &nod2;
  871. nod1.right = Z;
  872. nod1.complex = 1;
  873. nod1.type = t;
  874. sugen(n, &nod1, w);
  875. return;
  876. }
  877. if(n->complex > nn->complex) {
  878. t = n->type;
  879. n->type = types[TLONG];
  880. reglcgen(&nod1, n, Z);
  881. n->type = t;
  882. t = nn->type;
  883. nn->type = types[TLONG];
  884. reglcgen(&nod2, nn, Z);
  885. nn->type = t;
  886. } else {
  887. t = nn->type;
  888. nn->type = types[TLONG];
  889. reglcgen(&nod2, nn, Z);
  890. nn->type = t;
  891. t = n->type;
  892. n->type = types[TLONG];
  893. reglcgen(&nod1, n, Z);
  894. n->type = t;
  895. }
  896. w /= SZ_LONG;
  897. if(w <= 5) {
  898. layout(&nod1, &nod2, w, 0, Z);
  899. goto out;
  900. }
  901. /*
  902. * minimize space for unrolling loop
  903. * 3,4,5 times. (6 or more is never minimum)
  904. * if small structure, try 2 also.
  905. */
  906. c = 0; /* set */
  907. m = 100;
  908. i = 3;
  909. if(w <= 15)
  910. i = 2;
  911. for(; i<=5; i++)
  912. if(i + w%i <= m) {
  913. c = i;
  914. m = c + w%c;
  915. }
  916. regalloc(&nod3, &regnode, Z);
  917. layout(&nod1, &nod2, w%c, w/c, &nod3);
  918. pc1 = pc;
  919. layout(&nod1, &nod2, c, 0, Z);
  920. gopcode(OSUB, nodconst(1), Z, &nod3);
  921. nod1.op = OREGISTER;
  922. gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod1);
  923. nod2.op = OREGISTER;
  924. gopcode(OADD, nodconst(c*SZ_LONG), Z, &nod2);
  925. gopcode(OGT, &nod3, Z, nodconst(0));
  926. patch(p, pc1);
  927. regfree(&nod3);
  928. out:
  929. regfree(&nod1);
  930. regfree(&nod2);
  931. }
  932. void
  933. layout(Node *f, Node *t, int c, int cv, Node *cn)
  934. {
  935. Node t1, t2;
  936. while(c > 3) {
  937. layout(f, t, 2, 0, Z);
  938. c -= 2;
  939. }
  940. regalloc(&t1, &regnode, Z);
  941. regalloc(&t2, &regnode, Z);
  942. if(c > 0) {
  943. gopcode(OAS, f, Z, &t1);
  944. f->xoffset += SZ_LONG;
  945. }
  946. if(cn != Z)
  947. gopcode(OAS, nodconst(cv), Z, cn);
  948. if(c > 1) {
  949. gopcode(OAS, f, Z, &t2);
  950. f->xoffset += SZ_LONG;
  951. }
  952. if(c > 0) {
  953. gopcode(OAS, &t1, Z, t);
  954. t->xoffset += SZ_LONG;
  955. }
  956. if(c > 2) {
  957. gopcode(OAS, f, Z, &t1);
  958. f->xoffset += SZ_LONG;
  959. }
  960. if(c > 1) {
  961. gopcode(OAS, &t2, Z, t);
  962. t->xoffset += SZ_LONG;
  963. }
  964. if(c > 2) {
  965. gopcode(OAS, &t1, Z, t);
  966. t->xoffset += SZ_LONG;
  967. }
  968. regfree(&t1);
  969. regfree(&t2);
  970. }