cgen.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395
  1. #include "gc.h"
  2. void
  3. cgen(Node *n, int result, Node *nn)
  4. {
  5. Node *l, *r, nod;
  6. int lg, rg, xg, yg, g, o;
  7. long v;
  8. Prog *p1;
  9. if(n == Z || n->type == T)
  10. return;
  11. if(typesuv[n->type->etype]) {
  12. sugen(n, result, nn, n->type->width);
  13. return;
  14. }
  15. if(debug['g']) {
  16. if(result == D_TREE)
  17. prtree(nn, "result");
  18. else
  19. print("result = %R\n", result);
  20. prtree(n, "cgen");
  21. }
  22. l = n->left;
  23. r = n->right;
  24. o = n->op;
  25. if(n->addable >= INDEXED) {
  26. if(result == D_NONE) {
  27. switch(o) {
  28. default:
  29. nullwarn(Z, Z);
  30. break;
  31. case OINDEX:
  32. nullwarn(l, r);
  33. break;
  34. }
  35. return;
  36. }
  37. gmove(n->type, nn->type, D_TREE, n, result, nn);
  38. return;
  39. }
  40. v = 0; /* set */
  41. switch(o) {
  42. default:
  43. diag(n, "unknown op in cgen: %O", o);
  44. break;
  45. case OAS:
  46. if(l->op == OBIT)
  47. goto bitas;
  48. /*
  49. * recursive use of result
  50. */
  51. if(result == D_NONE)
  52. if(l->addable > INDEXED)
  53. if(l->complex < FNX) {
  54. cgen(r, D_TREE, l);
  55. break;
  56. }
  57. /*
  58. * function calls on both sides
  59. */
  60. if(l->complex >= FNX && r->complex >= FNX) {
  61. cgen(r, D_TOS, r);
  62. v = argoff;
  63. lg = regaddr(result);
  64. lcgen(l, lg, Z);
  65. lg |= I_INDIR;
  66. adjsp(v - argoff);
  67. gmove(r->type, l->type, D_TOS, r, lg, l);
  68. if(result != D_NONE)
  69. gmove(l->type, nn->type, lg, l, result, nn);
  70. regfree(lg);
  71. break;
  72. }
  73. rg = D_TREE;
  74. lg = D_TREE;
  75. if(r->complex >= l->complex) {
  76. /*
  77. * right side before left
  78. */
  79. if(result != D_NONE) {
  80. rg = regalloc(n->type, result);
  81. cgen(r, rg, n);
  82. } else
  83. if(r->complex >= FNX || r->addable < INDEXED) {
  84. rg = regalloc(r->type, result);
  85. cgen(r, rg, r);
  86. }
  87. if(l->addable < INDEXED) {
  88. lg = regaddr(lg);
  89. lcgen(l, lg, Z);
  90. lg |= I_INDIR;
  91. }
  92. } else {
  93. /*
  94. * left before right
  95. */
  96. if(l->complex >= FNX || l->addable < INDEXED) {
  97. lg = regaddr(lg);
  98. lcgen(l, lg, Z);
  99. lg |= I_INDIR;
  100. }
  101. if(result != D_NONE) {
  102. rg = regalloc(n->type, result);
  103. cgen(r, rg, n);
  104. } else
  105. if(r->addable < INDEXED) {
  106. rg = regalloc(r->type, result);
  107. cgen(r, rg, r);
  108. }
  109. }
  110. if(result != D_NONE) {
  111. gmove(n->type, l->type, rg, r, lg, l);
  112. gmove(n->type, nn->type, rg, r, result, nn);
  113. } else
  114. gmove(r->type, l->type, rg, r, lg, l);
  115. regfree(lg);
  116. regfree(rg);
  117. break;
  118. bitas:
  119. n = l->left;
  120. rg = regalloc(tfield, result);
  121. if(l->complex >= r->complex) {
  122. lg = regaddr(D_NONE);
  123. lcgen(n, lg, Z);
  124. lg |= I_INDIR;
  125. cgen(r, rg, r);
  126. } else {
  127. cgen(r, rg, r);
  128. lg = regaddr(D_NONE);
  129. lcgen(n, lg, Z);
  130. lg |= I_INDIR;
  131. }
  132. g = regalloc(n->type, D_NONE);
  133. gmove(l->type, l->type, lg, l, g, l);
  134. bitstore(l, rg, lg, g, result, nn);
  135. break;
  136. case OBIT:
  137. if(result == D_NONE) {
  138. nullwarn(l, Z);
  139. break;
  140. }
  141. g = bitload(n, D_NONE, D_NONE, result, nn);
  142. gopcode(OAS, nn->type, g, n, result, nn);
  143. regfree(g);
  144. break;
  145. case ODOT:
  146. sugen(l, D_TREE, nodrat, l->type->width);
  147. if(result != D_NONE) {
  148. warn(n, "non-interruptable temporary");
  149. nod = *nodrat;
  150. if(!r || r->op != OCONST) {
  151. diag(n, "DOT and no offset");
  152. break;
  153. }
  154. nod.xoffset += r->vconst;
  155. nod.type = n->type;
  156. cgen(&nod, result, nn);
  157. }
  158. break;
  159. case OASLDIV:
  160. case OASLMOD:
  161. case OASDIV:
  162. case OASMOD:
  163. if(l->op == OBIT)
  164. goto asbitop;
  165. if(typefd[n->type->etype])
  166. goto asbinop;
  167. rg = D_TREE;
  168. if(l->complex >= FNX || r->complex >= FNX) {
  169. rg = D_TOS;
  170. cgen(r, rg, r);
  171. v = argoff;
  172. } else
  173. if(r->addable < INDEXED) {
  174. rg = regalloc(n->type, D_NONE);
  175. cgen(r, rg, r);
  176. }
  177. lg = D_TREE;
  178. if(!simplv(l)) {
  179. lg = regaddr(D_NONE);
  180. lcgen(l, lg, Z); /* destroys register optimization */
  181. lg |= I_INDIR;
  182. }
  183. g = regpair(result);
  184. gmove(l->type, n->type, lg, l, g, n);
  185. if(rg == D_TOS)
  186. adjsp(v - argoff);
  187. gopcode(o, n->type, rg, r, g, n);
  188. if(o == OASLMOD || o == OASMOD)
  189. gmove(n->type, l->type, g+1, n, lg, l);
  190. else
  191. gmove(n->type, l->type, g, n, lg, l);
  192. if(result != D_NONE)
  193. if(o == OASLMOD || o == OASMOD)
  194. gmove(n->type, nn->type, g+1, n, result, nn);
  195. else
  196. gmove(n->type, nn->type, g, n, result, nn);
  197. regfree(g);
  198. regfree(g+1);
  199. regfree(lg);
  200. regfree(rg);
  201. break;
  202. case OASXOR:
  203. case OASAND:
  204. case OASOR:
  205. if(l->op == OBIT)
  206. goto asbitop;
  207. if(l->complex >= FNX ||
  208. l->addable < INDEXED ||
  209. result != D_NONE ||
  210. typefd[n->type->etype])
  211. goto asbinop;
  212. rg = D_TREE;
  213. if(r->op != OCONST) {
  214. rg = regalloc(n->type, D_NONE);
  215. cgen(r, rg, r);
  216. }
  217. gopcode(o, l->type, rg, r, D_TREE, l);
  218. regfree(rg);
  219. break;
  220. case OASADD:
  221. case OASSUB:
  222. if(l->op == OBIT ||
  223. l->complex >= FNX ||
  224. l->addable < INDEXED ||
  225. result != D_NONE ||
  226. typefd[n->type->etype])
  227. goto asbinop;
  228. v = vconst(r);
  229. if(v > 0 && v <= 8) {
  230. gopcode(o, n->type, D_TREE, r, D_TREE, l);
  231. break;
  232. }
  233. rg = regalloc(n->type, D_NONE);
  234. cgen(r, rg, r);
  235. gopcode(o, n->type, rg, r, D_TREE, l);
  236. regfree(rg);
  237. break;
  238. case OASLSHR:
  239. case OASASHR:
  240. case OASASHL:
  241. if(l->op == OBIT ||
  242. l->complex >= FNX ||
  243. l->addable < INDEXED ||
  244. result != D_NONE ||
  245. typefd[n->type->etype])
  246. goto asbinop;
  247. rg = D_TREE;
  248. v = vconst(r);
  249. if(v <= 0 || v > 8) {
  250. rg = regalloc(n->type, D_NONE);
  251. cgen(r, rg, r);
  252. }
  253. lg = regalloc(n->type, D_NONE);
  254. cgen(l, lg, l);
  255. gopcode(o, n->type, rg, r, lg, l);
  256. gmove(n->type, n->type, lg, l, D_TREE, l);
  257. regfree(lg);
  258. regfree(rg);
  259. break;
  260. case OASLMUL:
  261. case OASMUL:
  262. asbinop:
  263. if(l->op == OBIT)
  264. goto asbitop;
  265. rg = D_TREE;
  266. if(l->complex >= FNX || r->complex >= FNX) {
  267. rg = D_TOS;
  268. cgen(r, rg, r);
  269. v = argoff;
  270. } else
  271. if(r->addable < INDEXED) {
  272. rg = regalloc(n->type, D_NONE);
  273. cgen(r, rg, r);
  274. } else {
  275. if(o == OASLSHR || o == OASASHR || o == OASASHL) {
  276. v = vconst(r);
  277. if(v <= 0 || v > 8) {
  278. rg = regalloc(n->type, D_NONE);
  279. cgen(r, rg, r);
  280. }
  281. }
  282. }
  283. lg = D_TREE;
  284. if(!simplv(l)) {
  285. lg = regaddr(D_NONE);
  286. lcgen(l, lg, Z); /* destroys register optimization */
  287. lg |= I_INDIR;
  288. }
  289. g = regalloc(n->type, result);
  290. gmove(l->type, n->type, lg, l, g, n);
  291. if(rg == D_TOS)
  292. adjsp(v - argoff);
  293. if(o == OASXOR)
  294. if(rg == D_TREE) {
  295. rg = regalloc(n->type, D_NONE);
  296. cgen(r, rg, r);
  297. }
  298. if(o == OASXOR || o == OASLSHR || o == OASASHR || o == OASASHL)
  299. if(rg == D_TOS) {
  300. rg = regalloc(n->type, D_NONE);
  301. gmove(n->type, n->type, D_TOS, n, rg, n);
  302. }
  303. gopcode(o, n->type, rg, r, g, n);
  304. gmove(n->type, l->type, g, n, lg, l);
  305. if(result != D_NONE)
  306. gmove(n->type, nn->type, g, n, result, nn);
  307. regfree(g);
  308. regfree(lg);
  309. regfree(rg);
  310. break;
  311. asbitop:
  312. rg = regaddr(D_NONE);
  313. lg = regalloc(tfield, D_NONE);
  314. if(l->complex >= r->complex) {
  315. g = bitload(l, lg, rg, result, nn);
  316. xg = regalloc(r->type, D_NONE);
  317. cgen(r, xg, nn);
  318. } else {
  319. xg = regalloc(r->type, D_NONE);
  320. cgen(r, xg, nn);
  321. g = bitload(l, lg, rg, result, nn);
  322. }
  323. if(!typefd[n->type->etype]) {
  324. if(o == OASLDIV || o == OASDIV) {
  325. yg = regpair(result);
  326. gmove(tfield, n->type, g, l, yg, n);
  327. gopcode(o, n->type, xg, r, yg, n);
  328. gmove(n->type, tfield, yg, n, g, l);
  329. regfree(yg);
  330. regfree(yg+1);
  331. regfree(xg);
  332. bitstore(l, g, rg, lg, D_NONE, nn);
  333. break;
  334. }
  335. if(o == OASLMOD || o == OASMOD) {
  336. yg = regpair(result);
  337. gmove(tfield, n->type, g, l, yg, n);
  338. gopcode(o, n->type, xg, r, yg, n);
  339. gmove(n->type, tfield, yg+1, n, g, l);
  340. regfree(yg);
  341. regfree(yg+1);
  342. regfree(xg);
  343. bitstore(l, g, rg, lg, D_NONE, nn);
  344. break;
  345. }
  346. }
  347. yg = regalloc(n->type, result);
  348. gmove(tfield, n->type, g, l, yg, n);
  349. gopcode(o, n->type, xg, r, yg, n);
  350. gmove(n->type, tfield, yg, n, g, l);
  351. regfree(yg);
  352. regfree(xg);
  353. bitstore(l, g, rg, lg, D_NONE, nn);
  354. break;
  355. case OCAST:
  356. if(result == D_NONE) {
  357. nullwarn(l, Z);
  358. break;
  359. }
  360. lg = result;
  361. if(l->complex >= FNX)
  362. lg = regret(l->type);
  363. lg = eval(l, lg);
  364. if(nocast(l->type, n->type)) {
  365. gmove(n->type, nn->type, lg, l, result, nn);
  366. regfree(lg);
  367. break;
  368. }
  369. if(nocast(n->type, nn->type)) {
  370. gmove(l->type, n->type, lg, l, result, nn);
  371. regfree(lg);
  372. break;
  373. }
  374. rg = regalloc(n->type, result);
  375. gmove(l->type, n->type, lg, l, rg, n);
  376. gmove(n->type, nn->type, rg, n, result, nn);
  377. regfree(rg);
  378. regfree(lg);
  379. break;
  380. case OCOND:
  381. doinc(l, PRE);
  382. boolgen(l, 1, D_NONE, Z, l);
  383. p1 = p;
  384. inargs++;
  385. doinc(r->left, PRE);
  386. cgen(r->left, result, nn);
  387. doinc(r->left, POST);
  388. gbranch(OGOTO);
  389. patch(p1, pc);
  390. p1 = p;
  391. doinc(r->right, PRE);
  392. cgen(r->right, result, nn);
  393. doinc(r->right, POST);
  394. patch(p1, pc);
  395. inargs--;
  396. break;
  397. case OIND:
  398. if(result == D_NONE) {
  399. nullwarn(l, Z);
  400. break;
  401. }
  402. lg = nodalloc(types[TIND], result, &nod);
  403. nod.lineno = n->lineno;
  404. if(l->op == OADD) {
  405. if(l->left->op == OCONST) {
  406. nod.xoffset += l->left->vconst;
  407. l = l->right;
  408. } else
  409. if(l->right->op == OCONST) {
  410. nod.xoffset += l->right->vconst;
  411. l = l->left;
  412. }
  413. }
  414. cgen(l, lg, l);
  415. gmove(n->type, nn->type, D_TREE, &nod, result, nn);
  416. regfree(lg);
  417. break;
  418. case OFUNC:
  419. v = argoff;
  420. inargs++;
  421. gargs(r);
  422. lg = D_TREE;
  423. if(l->addable < INDEXED) {
  424. lg = regaddr(result);
  425. lcgen(l, lg, Z);
  426. lg |= I_INDIR;
  427. }
  428. inargs--;
  429. doinc(r, POST);
  430. doinc(l, POST);
  431. gopcode(OFUNC, types[TCHAR], D_NONE, Z, lg, l);
  432. regfree(lg);
  433. if(inargs)
  434. adjsp(v - argoff);
  435. if(result != D_NONE) {
  436. lg = regret(n->type);
  437. gmove(n->type, nn->type, lg, n, result, nn);
  438. }
  439. break;
  440. case OLDIV:
  441. case OLMOD:
  442. case ODIV:
  443. case OMOD:
  444. if(result == D_NONE) {
  445. nullwarn(l, r);
  446. break;
  447. }
  448. if(typefd[n->type->etype])
  449. goto binop;
  450. if(r->addable >= INDEXED && r->complex < FNX) {
  451. lg = regpair(result);
  452. cgen(l, lg, l);
  453. rg = D_TREE;
  454. } else {
  455. cgen(r, D_TOS, r);
  456. v = argoff;
  457. lg = regpair(result);
  458. cgen(l, lg, l);
  459. adjsp(v - argoff);
  460. rg = D_TOS;
  461. }
  462. gopcode(o, n->type, rg, r, lg, l);
  463. if(o == OMOD || o == OLMOD)
  464. gmove(l->type, nn->type, lg+1, l, result, nn);
  465. else
  466. gmove(l->type, nn->type, lg, l, result, nn);
  467. regfree(lg);
  468. regfree(lg+1);
  469. break;
  470. case OMUL:
  471. case OLMUL:
  472. if(l->op == OCONST)
  473. if(mulcon(r, l, result, nn))
  474. break;
  475. if(r->op == OCONST)
  476. if(mulcon(l, r, result, nn))
  477. break;
  478. if(debug['M'])
  479. print("%L multiply\n", n->lineno);
  480. goto binop;
  481. case OAND:
  482. if(r->op == OCONST)
  483. if(typeil[n->type->etype])
  484. if(l->op == OCAST) {
  485. if(typec[l->left->type->etype])
  486. if(!(r->vconst & ~0xff)) {
  487. l = l->left;
  488. goto binop;
  489. }
  490. if(typeh[l->left->type->etype])
  491. if(!(r->vconst & ~0xffff)) {
  492. l = l->left;
  493. goto binop;
  494. }
  495. }
  496. goto binop;
  497. case OADD:
  498. if(result == D_TOS)
  499. if(r->addable >= INDEXED)
  500. if(l->op == OCONST)
  501. if(typeil[l->type->etype]) {
  502. v = l->vconst;
  503. if(v > -32768 && v < 32768) {
  504. rg = regaddr(D_NONE);
  505. gmove(r->type, r->type, D_TREE, r, rg, r);
  506. gopcode(OADDR, types[TSHORT], D_NONE, Z, rg, r);
  507. p->to.offset = v;
  508. p->to.type |= I_INDIR;
  509. regfree(rg);
  510. break;
  511. }
  512. }
  513. case OSUB:
  514. if(result == D_TOS)
  515. if(l->addable >= INDEXED)
  516. if(r->op == OCONST)
  517. if(typeil[r->type->etype]) {
  518. v = r->vconst;
  519. if(v > -32768 && v < 32768) {
  520. if(n->op == OSUB)
  521. v = -v;
  522. lg = regaddr(D_NONE);
  523. gmove(l->type, l->type, D_TREE, l, lg, l);
  524. gopcode(OADDR, types[TSHORT], D_NONE, Z, lg, l);
  525. p->to.offset = v;
  526. p->to.type |= I_INDIR;
  527. regfree(lg);
  528. break;
  529. }
  530. }
  531. goto binop;
  532. case OOR:
  533. case OXOR:
  534. binop:
  535. if(result == D_NONE) {
  536. nullwarn(l, r);
  537. break;
  538. }
  539. if(l->complex >= FNX && r->complex >= FNX) {
  540. cgen(r, D_TOS, r);
  541. v = argoff;
  542. lg = regalloc(l->type, result);
  543. cgen(l, lg, l);
  544. adjsp(v - argoff);
  545. if(o == OXOR) {
  546. rg = regalloc(r->type, D_NONE);
  547. gmove(r->type, r->type, D_TOS, r, rg, r);
  548. gopcode(o, n->type, rg, r, lg, l);
  549. regfree(rg);
  550. } else
  551. gopcode(o, n->type, D_TOS, r, lg, l);
  552. gmove(n->type, nn->type, lg, l, result, nn);
  553. regfree(lg);
  554. break;
  555. }
  556. if(l->complex >= r->complex) {
  557. if(l->op == OADDR && (o == OADD || o == OSUB))
  558. lg = regaddr(result);
  559. else
  560. lg = regalloc(l->type, result);
  561. cgen(l, lg, l);
  562. rg = eval(r, D_NONE);
  563. } else {
  564. rg = regalloc(r->type, D_NONE);
  565. cgen(r, rg, r);
  566. lg = regalloc(l->type, result);
  567. cgen(l, lg, l);
  568. }
  569. if(o == OXOR) {
  570. if(rg == D_TREE) {
  571. rg = regalloc(r->type, D_NONE);
  572. cgen(r, rg, r);
  573. }
  574. if(rg == D_TOS) {
  575. rg = regalloc(r->type, D_NONE);
  576. gmove(r->type, r->type, D_TOS, r, rg, r);
  577. }
  578. }
  579. gopcode(o, n->type, rg, r, lg, l);
  580. gmove(n->type, nn->type, lg, l, result, nn);
  581. regfree(lg);
  582. regfree(rg);
  583. break;
  584. case OASHL:
  585. if(r->op == OCONST)
  586. if(shlcon(l, r, result, nn))
  587. break;
  588. case OLSHR:
  589. case OASHR:
  590. if(result == D_NONE) {
  591. nullwarn(l, r);
  592. break;
  593. }
  594. if(l->complex >= FNX && r->complex >= FNX) {
  595. cgen(r, D_TOS, r);
  596. v = argoff;
  597. lg = regalloc(l->type, result);
  598. cgen(l, lg, l);
  599. adjsp(v - argoff);
  600. rg = regalloc(r->type, D_NONE);
  601. gopcode(OAS, r->type, D_TOS, r, rg, r);
  602. gopcode(n->op, n->type, rg, r, lg, l);
  603. gmove(n->type, nn->type, lg, l, result, nn);
  604. regfree(lg);
  605. regfree(rg);
  606. break;
  607. }
  608. if(l->complex >= r->complex) {
  609. lg = regalloc(l->type, result);
  610. cgen(l, lg, l);
  611. v = vconst(r);
  612. if(v <= 0 || v > 8) {
  613. rg = regalloc(r->type, D_NONE);
  614. cgen(r, rg, r);
  615. } else
  616. rg = eval(r, D_NONE);
  617. } else {
  618. rg = regalloc(r->type, D_NONE);
  619. cgen(r, rg, r);
  620. lg = regalloc(l->type, result);
  621. cgen(l, lg, l);
  622. }
  623. gopcode(o, n->type, rg, r, lg, l);
  624. gmove(n->type, nn->type, lg, l, result, nn);
  625. regfree(lg);
  626. regfree(rg);
  627. break;
  628. case ONEG:
  629. case OCOM:
  630. if(result == D_NONE) {
  631. nullwarn(l, Z);
  632. break;
  633. }
  634. lg = regalloc(l->type, result);
  635. cgen(l, lg, l);
  636. gopcode(o, l->type, D_NONE, Z, lg, l);
  637. gmove(n->type, nn->type, lg, l, result, nn);
  638. regfree(lg);
  639. break;
  640. case OADDR:
  641. if(result == D_NONE) {
  642. nullwarn(l, Z);
  643. break;
  644. }
  645. lcgen(l, result, nn);
  646. break;
  647. case OEQ:
  648. case ONE:
  649. case OLE:
  650. case OLT:
  651. case OGE:
  652. case OGT:
  653. case OLO:
  654. case OLS:
  655. case OHI:
  656. case OHS:
  657. if(result == D_NONE) {
  658. nullwarn(l, r);
  659. break;
  660. }
  661. boolgen(n, 1, result, nn, Z);
  662. break;
  663. case OANDAND:
  664. case OOROR:
  665. boolgen(n, 1, result, nn, Z);
  666. if(result == D_NONE)
  667. patch(p, pc);
  668. break;
  669. case OCOMMA:
  670. cgen(l, D_NONE, l);
  671. doinc(l, POST);
  672. doinc(r, PRE);
  673. cgen(r, result, nn);
  674. break;
  675. case ONOT:
  676. if(result == D_NONE) {
  677. nullwarn(l, Z);
  678. break;
  679. }
  680. boolgen(n, 1, result, nn, Z);
  681. break;
  682. case OPOSTINC:
  683. case OPOSTDEC:
  684. v = 1;
  685. if(l->type->etype == TIND)
  686. v = l->type->link->width;
  687. if(o == OPOSTDEC)
  688. v = -v;
  689. if(l->op == OBIT)
  690. goto bitinc;
  691. if(nn == Z)
  692. goto pre;
  693. lg = D_TREE;
  694. if(l->addable < INDEXED) {
  695. lg = regaddr(D_NONE);
  696. lcgen(l, lg, Z);
  697. lg |= I_INDIR;
  698. }
  699. if(result != D_NONE)
  700. gmove(l->type, nn->type, lg, l, result, nn);
  701. if(typefd[n->type->etype]) {
  702. rg = regalloc(n->type, D_NONE);
  703. gmove(l->type, l->type, lg, l, rg, l);
  704. gopcode(o, n->type, D_CONST, nodconst(1), rg, l);
  705. gmove(l->type, l->type, rg, l, lg, l);
  706. regfree(rg);
  707. } else {
  708. if(v < 0)
  709. gopcode(o, n->type, D_CONST, nodconst(-v), lg, l);
  710. else
  711. gopcode(o, n->type, D_CONST, nodconst(v), lg, l);
  712. }
  713. regfree(lg);
  714. break;
  715. case OPREINC:
  716. case OPREDEC:
  717. v = 1;
  718. if(l->type->etype == TIND)
  719. v = l->type->link->width;
  720. if(o == OPREDEC)
  721. v = -v;
  722. if(l->op == OBIT)
  723. goto bitinc;
  724. pre:
  725. lg = D_TREE;
  726. if(l->addable < INDEXED) {
  727. lg = regaddr(D_NONE);
  728. lcgen(l, lg, Z);
  729. lg |= I_INDIR;
  730. }
  731. if(typefd[n->type->etype]) {
  732. rg = regalloc(n->type, D_NONE);
  733. gmove(l->type, l->type, lg, l, rg, l);
  734. gopcode(o, n->type, D_CONST, nodconst(1), rg, l);
  735. gmove(l->type, l->type, rg, l, lg, l);
  736. regfree(rg);
  737. } else {
  738. if(v < 0)
  739. gopcode(o, n->type, D_CONST, nodconst(-v), lg, l);
  740. else
  741. gopcode(o, n->type, D_CONST, nodconst(v), lg, l);
  742. }
  743. if(result != D_NONE)
  744. gmove(l->type, nn->type, lg, l, result, nn);
  745. regfree(lg);
  746. break;
  747. bitinc:
  748. rg = regaddr(D_NONE);
  749. lg = regalloc(tfield, D_NONE);
  750. if(result != D_NONE && (o == OPOSTINC || o == OPOSTDEC)) {
  751. g = bitload(l, lg, rg, D_NONE, nn);
  752. if(nn != Z)
  753. gmove(l->type, nn->type, g, l, result, nn);
  754. if(v < 0)
  755. gopcode(o, n->type, D_CONST, nodconst(-v), g, n);
  756. else
  757. gopcode(o, n->type, D_CONST, nodconst(v), g, n);
  758. bitstore(l, g, rg, lg, D_NONE, nn);
  759. break;
  760. }
  761. g = bitload(l, lg, rg, result, nn);
  762. if(v < 0)
  763. gopcode(o, n->type, D_CONST, nodconst(-v), g, n);
  764. else
  765. gopcode(o, n->type, D_CONST, nodconst(v), g, n);
  766. if(result != D_NONE)
  767. gmove(l->type, nn->type, g, l, result, nn);
  768. bitstore(l, g, rg, lg, D_NONE, nn);
  769. break;
  770. }
  771. }
  772. void
  773. lcgen(Node *n, int result, Node *nn)
  774. {
  775. Node rn;
  776. Prog *p1;
  777. int lg;
  778. if(n == Z || n->type == T)
  779. return;
  780. if(debug['g']) {
  781. if(result == D_TREE)
  782. prtree(nn, "result");
  783. else
  784. print("result = %R\n", result);
  785. prtree(n, "lcgen");
  786. }
  787. if(nn == Z) {
  788. nn = &rn;
  789. nn->type = types[TIND];
  790. }
  791. switch(n->op) {
  792. case OCOMMA:
  793. cgen(n->left, D_NONE, n->left);
  794. doinc(n->left, POST);
  795. doinc(n->right, PRE);
  796. lcgen(n->right, result, nn);
  797. break;
  798. case OCOND:
  799. doinc(n->left, PRE);
  800. boolgen(n->left, 1, D_NONE, Z, n->left);
  801. p1 = p;
  802. inargs++;
  803. doinc(n->right->left, PRE);
  804. lcgen(n->right->left, result, nn);
  805. doinc(n->right->left, POST);
  806. gbranch(OGOTO);
  807. patch(p1, pc);
  808. p1 = p;
  809. doinc(n->right->right, PRE);
  810. lcgen(n->right->right, result, nn);
  811. doinc(n->right->right, POST);
  812. patch(p1, pc);
  813. inargs--;
  814. break;
  815. case OIND:
  816. if(n->addable >= INDEXED) {
  817. if(result >= D_A0 && result < D_A0+NREG) {
  818. gopcode(OADDR, types[TLONG], D_TREE, n, result, nn);
  819. break;
  820. }
  821. if(result == D_TOS) {
  822. gopcode(OADDR, types[TSHORT], D_NONE, nn, D_TREE, n);
  823. break;
  824. }
  825. }
  826. cgen(n->left, result, nn);
  827. break;
  828. default:
  829. if(n->addable < INDEXED) {
  830. diag(n, "unknown op in lcgen: %O", n->op);
  831. break;
  832. }
  833. if(result >= D_A0 && result < D_A0+NREG) {
  834. gopcode(OADDR, types[TLONG], D_TREE, n, result, nn);
  835. break;
  836. }
  837. if(result == D_TOS) {
  838. gopcode(OADDR, types[TSHORT], D_NONE, nn, D_TREE, n);
  839. break;
  840. }
  841. lg = regaddr(result);
  842. gopcode(OADDR, types[TLONG], D_TREE, n, lg, nn);
  843. gopcode(OAS, nn->type, lg, nn, result, nn);
  844. regfree(lg);
  845. break;
  846. }
  847. }
  848. void
  849. bcgen(Node *n, int true)
  850. {
  851. boolgen(n, true, D_NONE, Z, Z);
  852. }
  853. void
  854. boolgen(Node *n, int true, int result, Node *nn, Node *post)
  855. {
  856. Prog *p1, *p2;
  857. Node *l, *r;
  858. int lg, rg, fp, o;
  859. long v;
  860. if(debug['g']) {
  861. if(result == D_TREE)
  862. prtree(nn, "result");
  863. else
  864. print("result = %R\n", result);
  865. prtree(n, "boolgen");
  866. }
  867. l = n->left;
  868. r = n->right;
  869. switch(n->op) {
  870. default:
  871. lg = eval(n, result);
  872. if(lg >= D_A0 && lg < D_A0+NREG) {
  873. rg = regalloc(types[TLONG], D_NONE);
  874. gopcode(OAS, types[TLONG], lg, n, rg, Z);
  875. regfree(rg);
  876. } else
  877. gopcode(OTST, n->type, D_NONE, Z, lg, n);
  878. regfree(lg);
  879. o = ONE;
  880. fp = typefd[n->type->etype];
  881. goto genbool;
  882. case OCONST:
  883. fp = vconst(n);
  884. if(!true)
  885. fp = !fp;
  886. gbranch(OGOTO);
  887. if(fp) {
  888. p1 = p;
  889. gbranch(OGOTO);
  890. patch(p1, pc);
  891. }
  892. goto com;
  893. case ONOT:
  894. boolgen(l, !true, result, nn, post);
  895. break;
  896. case OCOND:
  897. doinc(l, PRE);
  898. boolgen(l, 1, D_NONE, Z, l);
  899. p1 = p;
  900. inargs++;
  901. doinc(r->left, PRE);
  902. boolgen(r->left, true, result, nn, r->left);
  903. if(result != D_NONE) {
  904. doinc(r->left, POST);
  905. gbranch(OGOTO);
  906. patch(p1, pc);
  907. p1 = p;
  908. doinc(r->right, PRE);
  909. boolgen(r->right, !true, result, nn, r->right);
  910. doinc(r->right, POST);
  911. patch(p1, pc);
  912. inargs--;
  913. break;
  914. }
  915. p2 = p;
  916. gbranch(OGOTO);
  917. patch(p1, pc);
  918. p1 = p;
  919. doinc(r->right, PRE);
  920. boolgen(r->right, !true, result, nn, r->right);
  921. patch(p2, pc);
  922. p2 = p;
  923. if(doinc(post, POST|TEST)) {
  924. lg = regalloc(types[TSHORT], D_NONE);
  925. gopcode(OAS, types[TSHORT], D_CCR, Z, lg, Z);
  926. doinc(post, POST);
  927. gopcode(OAS, types[TSHORT], lg, Z, D_CCR, Z);
  928. regfree(lg);
  929. }
  930. gbranch(OGOTO);
  931. patch(p1, pc);
  932. patch(p2, pc);
  933. inargs--;
  934. goto com;
  935. case OANDAND:
  936. if(!true)
  937. goto caseor;
  938. caseand:
  939. doinc(l, PRE);
  940. boolgen(l, true, D_NONE, Z, l);
  941. p1 = p;
  942. inargs++;
  943. doinc(r, PRE);
  944. boolgen(r, !true, D_NONE, Z, r);
  945. p2 = p;
  946. patch(p1, pc);
  947. gbranch(OGOTO);
  948. patch(p2, pc);
  949. inargs--;
  950. goto com;
  951. case OOROR:
  952. if(!true)
  953. goto caseand;
  954. caseor:
  955. doinc(l, PRE);
  956. boolgen(l, !true, D_NONE, Z, l);
  957. p1 = p;
  958. inargs++;
  959. doinc(r, PRE);
  960. boolgen(r, !true, D_NONE, Z, r);
  961. p2 = p;
  962. gbranch(OGOTO);
  963. patch(p1, pc);
  964. patch(p2, pc);
  965. inargs--;
  966. goto com;
  967. case OEQ:
  968. case ONE:
  969. if(vconst(l) == 0) {
  970. if(n->op == ONE) {
  971. boolgen(r, true, result, nn, post);
  972. break;
  973. }
  974. boolgen(r, !true, result, nn, post);
  975. break;
  976. }
  977. case OLE:
  978. case OLT:
  979. case OGE:
  980. case OGT:
  981. case OHI:
  982. case OHS:
  983. case OLO:
  984. case OLS:
  985. fp = typefd[r->type->etype];
  986. if(l->op == OCONST) {
  987. v = vconst(l);
  988. if(v == 0) { /* tst instruction */
  989. o = invrel[relindex(n->op)];
  990. rg = eval(r, result);
  991. gopcode(OTST, r->type, D_NONE, Z, rg, r);
  992. regfree(rg);
  993. goto genbool;
  994. }
  995. if(!fp) { /* cmpi and movq, saves about .5% both time and space */
  996. if(v < 128 && v >= -128 &&
  997. ewidth[r->type->etype] == SZ_LONG) {
  998. rg = eval(r, result);
  999. lg = regalloc(l->type, D_NONE);
  1000. cgen(l, lg, l);
  1001. o = n->op;
  1002. gopcode(o, l->type, lg, l, rg, r);
  1003. regfree(lg);
  1004. regfree(rg);
  1005. goto genbool;
  1006. }
  1007. o = invrel[relindex(n->op)];
  1008. rg = eval(r, result);
  1009. gopcode(o, r->type, rg, r, D_TREE, l);
  1010. regfree(rg);
  1011. goto genbool;
  1012. }
  1013. }
  1014. lg = D_TOS;
  1015. if(r->complex < FNX)
  1016. lg = regalloc(l->type, lg);
  1017. cgen(l, lg, l);
  1018. v = argoff;
  1019. rg = eval(r, result);
  1020. if(lg == D_TOS) {
  1021. adjsp(v - argoff);
  1022. lg = regalloc(l->type, lg);
  1023. gopcode(OAS, l->type, D_TOS, l, lg, l);
  1024. }
  1025. o = n->op;
  1026. gopcode(o, l->type, lg, l, rg, r);
  1027. regfree(lg);
  1028. regfree(rg);
  1029. genbool:
  1030. if(true)
  1031. o = comrel[relindex(o)];
  1032. if(doinc(post, POST|TEST)) {
  1033. lg = regalloc(types[TSHORT], D_NONE);
  1034. gopcode(OAS, types[TSHORT], D_CCR, Z, lg, Z);
  1035. doinc(post, POST);
  1036. gopcode(OAS, types[TSHORT], lg, Z, D_CCR, Z);
  1037. regfree(lg);
  1038. }
  1039. gbranch(o);
  1040. if(fp)
  1041. fpbranch();
  1042. com:
  1043. if(result == D_NONE)
  1044. break;
  1045. p1 = p;
  1046. gopcode(OAS, nn->type, D_CONST, nodconst(1), result, nn);
  1047. gbranch(OGOTO);
  1048. p2 = p;
  1049. patch(p1, pc);
  1050. gopcode(OAS, nn->type, D_CONST, nodconst(0), result, nn);
  1051. patch(p2, pc);
  1052. break;
  1053. }
  1054. }
  1055. void
  1056. sugen(Node *n, int result, Node *nn, long w)
  1057. {
  1058. long s, v, o;
  1059. int lg, rg, ng;
  1060. Prog *p1;
  1061. Node *l, *r, nod;
  1062. Type *t;
  1063. if(n == Z || n->type == T)
  1064. return;
  1065. if(debug['g']) {
  1066. if(result == D_TREE)
  1067. prtree(nn, "result");
  1068. else
  1069. print("result = %R width = %ld\n", result, w);
  1070. prtree(n, "sugen");
  1071. }
  1072. s = argoff;
  1073. if(result == D_TREE) {
  1074. if(nn == nodrat)
  1075. if(w > nrathole)
  1076. nrathole = w;
  1077. }
  1078. if(n->addable >= INDEXED && n->op != OCONST)
  1079. goto copy;
  1080. switch(n->op) {
  1081. default:
  1082. diag(n, "unknown op in sugen: %O", n->op);
  1083. break;
  1084. case OCONST:
  1085. if(n->type && typev[n->type->etype]) {
  1086. if(result == D_NONE) {
  1087. nullwarn(n->left, Z);
  1088. break;
  1089. }
  1090. lg = regaddr(D_NONE);
  1091. if(result == D_TOS) {
  1092. adjsp(s - argoff + w);
  1093. gopcode(OADDR, types[TIND], result, nn, lg, n);
  1094. } else
  1095. if(result == D_TREE) {
  1096. lcgen(nn, lg, Z);
  1097. } else
  1098. diag(n, "unknown su result: %R", result);
  1099. gopcode(OAS, types[TLONG], D_CONST, nodconst((long)(n->vconst>>32)),
  1100. lg|I_INDINC, n);
  1101. gopcode(OAS, types[TLONG], D_CONST, nodconst((long)(n->vconst)),
  1102. lg|I_INDINC, n);
  1103. regfree(lg);
  1104. break;
  1105. }
  1106. goto copy;
  1107. case ODOT:
  1108. l = n->left;
  1109. sugen(l, D_TREE, nodrat, l->type->width);
  1110. if(result != D_NONE) {
  1111. warn(n, "non-interruptable temporary");
  1112. nod = *nodrat;
  1113. r = n->right;
  1114. if(!r || r->op != OCONST) {
  1115. diag(n, "DOT and no offset");
  1116. break;
  1117. }
  1118. nod.xoffset += r->vconst;
  1119. nod.type = n->type;
  1120. sugen(&nod, result, nn, w);
  1121. }
  1122. break;
  1123. case OIND:
  1124. if(result == D_NONE) {
  1125. nullwarn(n->left, Z);
  1126. break;
  1127. }
  1128. goto copy;
  1129. case OSTRUCT:
  1130. lg = nodalloc(types[TIND], result, &nod);
  1131. nod.lineno = n->lineno;
  1132. if(result == D_TREE)
  1133. lcgen(nn, lg, Z);
  1134. else
  1135. if(result == D_TOS) {
  1136. adjsp(s - argoff + w);
  1137. gopcode(OADDR, types[TIND], result, nn, lg, n);
  1138. } else
  1139. diag(n, "unknown su result: %R", result);
  1140. o = 0;
  1141. r = n->left;
  1142. for(t = n->type->link; t != T; t = t->down) {
  1143. l = r;
  1144. if(r->op == OLIST) {
  1145. l = r->left;
  1146. r = r->right;
  1147. }
  1148. nod.type = t;
  1149. if(l->complex < FNX) {
  1150. nod.xoffset = 0;
  1151. if(o != t->offset) {
  1152. gopcode(OADD, types[TIND], D_CONST,
  1153. nodconst(t->offset-o), lg, Z);
  1154. o = t->offset;
  1155. }
  1156. cgen(l, D_TREE, &nod);
  1157. continue;
  1158. }
  1159. nod.xoffset = t->offset - o;
  1160. gopcode(OAS, types[TIND], lg, Z, D_TOS, Z);
  1161. s = argoff;
  1162. if(typesuv[t->etype]) {
  1163. sugen(l, D_TREE, nodrat, t->width);
  1164. adjsp(s - argoff);
  1165. gopcode(OAS, types[TIND], D_TOS, Z, lg, Z);
  1166. warn(n, "non-interruptable temporary");
  1167. sugen(nodrat, D_TREE, &nod, t->width);
  1168. continue;
  1169. }
  1170. rg = regalloc(t, D_NONE);
  1171. cgen(l, rg, l);
  1172. adjsp(s - argoff);
  1173. gopcode(OAS, types[TIND], D_TOS, Z, lg, Z);
  1174. gopcode(OAS, t, rg, Z, D_TREE, &nod);
  1175. regfree(rg);
  1176. }
  1177. regfree(lg);
  1178. break;
  1179. case OAS:
  1180. if(result == D_NONE) {
  1181. sugen(n->right, D_TREE, n->left, w);
  1182. break;
  1183. }
  1184. sugen(n->right, D_TREE, nodrat, w); /* could do better */
  1185. warn(n, "non-interruptable temporary");
  1186. sugen(nodrat, D_TREE, n->left, w);
  1187. sugen(nodrat, result, nn, w);
  1188. break;
  1189. case OFUNC:
  1190. if(result == D_NONE) {
  1191. sugen(n, D_TREE, nodrat, w);
  1192. break;
  1193. }
  1194. inargs++;
  1195. /* prepare zero-th arg: address of result */
  1196. if(result == D_TOS) {
  1197. adjsp(s - argoff + w);
  1198. v = argoff;
  1199. gargs(n->right);
  1200. gopcode(OADDR, types[TSHORT], D_NONE, nn, result, nn);
  1201. p->to.type = D_STACK;
  1202. p->to.offset = argoff - v;
  1203. } else
  1204. if(result == D_TREE) {
  1205. v = argoff;
  1206. gargs(n->right);
  1207. if(nn->complex >= FNX) {
  1208. rg = regalloc(types[TIND], regret(types[TIND]));
  1209. lcgen(nn, rg, Z);
  1210. gopcode(OAS, types[TIND], rg, Z, D_TOS, Z);
  1211. regfree(rg);
  1212. } else
  1213. lcgen(nn, D_TOS, Z);
  1214. } else {
  1215. diag(n, "unknown result in FUNC sugen");
  1216. break;
  1217. }
  1218. argoff += types[TIND]->width;
  1219. l = n->left;
  1220. lg = D_TREE;
  1221. if(l->addable < INDEXED) {
  1222. lg = regaddr(result);
  1223. lcgen(l, lg, Z);
  1224. lg |= I_INDIR;
  1225. }
  1226. inargs--;
  1227. doinc(n->right, POST);
  1228. doinc(n->left, POST);
  1229. gopcode(OFUNC, types[TCHAR], D_NONE, Z, lg, l);
  1230. regfree(lg);
  1231. if(inargs)
  1232. adjsp(v - argoff);
  1233. break;
  1234. case OCOND:
  1235. doinc(n->left, PRE);
  1236. boolgen(n->left, 1, D_NONE, Z, n->left);
  1237. p1 = p;
  1238. inargs++;
  1239. doinc(n->right->left, PRE);
  1240. sugen(n->right->left, result, nn, w);
  1241. doinc(n->right->left, POST);
  1242. gbranch(OGOTO);
  1243. patch(p1, pc);
  1244. p1 = p;
  1245. doinc(n->right->right, PRE);
  1246. sugen(n->right->right, result, nn, w);
  1247. doinc(n->right->right, POST);
  1248. patch(p1, pc);
  1249. inargs--;
  1250. break;
  1251. case OCOMMA:
  1252. cgen(n->left, D_NONE, n->left);
  1253. doinc(n->left, POST);
  1254. doinc(n->right, PRE);
  1255. sugen(n->right, result, nn, w);
  1256. break;
  1257. }
  1258. return;
  1259. copy:
  1260. if(result == D_NONE)
  1261. return;
  1262. rg = regaddr(D_NONE);
  1263. lcgen(n, rg, Z);
  1264. lg = regaddr(D_NONE);
  1265. if(result == D_TOS) {
  1266. adjsp(s - argoff + w);
  1267. gopcode(OADDR, types[TIND], result, nn, lg, n);
  1268. } else
  1269. if(result == D_TREE) {
  1270. if(nn->complex >= FNX) {
  1271. gopcode(OAS, types[TIND], rg, n, D_TOS, n);
  1272. s = argoff;
  1273. lcgen(nn, lg, Z);
  1274. adjsp(s - argoff);
  1275. gopcode(OAS, types[TIND], D_TOS, n, rg, n);
  1276. } else
  1277. lcgen(nn, lg, Z);
  1278. } else
  1279. diag(n, "unknown su result: %R", result);
  1280. if(w % SZ_LONG)
  1281. diag(Z, "sucopy width not 0%%%d", SZ_LONG);
  1282. v = w / SZ_LONG;
  1283. if(v & 1) {
  1284. gopcode(OAS, types[TLONG], rg|I_INDINC, n, lg|I_INDINC, n);
  1285. v--;
  1286. }
  1287. if(v > 6) {
  1288. ng = regalloc(types[TLONG], D_NONE);
  1289. gopcode(OAS, types[TLONG], D_CONST, nodconst(v/2-1), ng, n);
  1290. v = pc;
  1291. gopcode(OAS, types[TLONG], rg|I_INDINC, n, lg|I_INDINC, n);
  1292. gopcode(OAS, types[TLONG], rg|I_INDINC, n, lg|I_INDINC, n);
  1293. gbranch(OGT);
  1294. patch(p, v);
  1295. p->from.type = ng;
  1296. p->as = ADBF;
  1297. regfree(ng);
  1298. } else
  1299. while(v > 0) {
  1300. gopcode(OAS, types[TLONG], rg|I_INDINC, n, lg|I_INDINC, n);
  1301. v--;
  1302. }
  1303. regfree(lg);
  1304. regfree(rg);
  1305. }