desig.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705
  1. /*
  2. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
  3. * See the copyright notice in the ACK home directory, in the file "Copyright".
  4. *
  5. * Author: Ceriel J.H. Jacobs
  6. */
  7. /* D E S I G N A T O R E V A L U A T I O N */
  8. /* $Id$ */
  9. /* Code generation for designators.
  10. This file contains some routines that generate code common to address
  11. as well as value computations, and leave a description in a "desig"
  12. structure. It also contains routines to load an address, load a value
  13. or perform a store.
  14. */
  15. #include "debug.h"
  16. #include <em_arith.h>
  17. #include <em_label.h>
  18. #include <em_code.h>
  19. #include <assert.h>
  20. #include <alloc.h>
  21. #include "type.h"
  22. #include "LLlex.h"
  23. #include "def.h"
  24. #include "scope.h"
  25. #include "desig.h"
  26. #include "node.h"
  27. #include "warning.h"
  28. #include "walk.h"
  29. #include "squeeze.h"
  30. extern int proclevel;
  31. extern arith NewPtr();
  32. extern char options[];
  33. int
  34. WordOrDouble(ds, size)
  35. t_desig *ds;
  36. arith size;
  37. {
  38. /* Check if designator is suitable for word or double-word
  39. operation
  40. */
  41. if ((int) (ds->dsg_offset) % word_align == 0) {
  42. if (size == word_size) return 1;
  43. if (size == dword_size) return 2;
  44. }
  45. return 0;
  46. }
  47. LOL(offset, size)
  48. arith offset, size;
  49. {
  50. if (size == word_size) {
  51. C_lol(offset);
  52. }
  53. else if (size == dword_size) {
  54. C_ldl(offset);
  55. }
  56. else {
  57. C_lal(offset);
  58. C_loi(size);
  59. }
  60. }
  61. STL(offset, size)
  62. arith offset, size;
  63. {
  64. if (size == word_size) {
  65. C_stl(offset);
  66. }
  67. else if (size == dword_size) {
  68. C_sdl(offset);
  69. }
  70. else {
  71. C_lal(offset);
  72. C_sti(size);
  73. }
  74. }
  75. int
  76. DoLoad(ds, size)
  77. register t_desig *ds;
  78. arith size;
  79. {
  80. /* Try to load designator with word or double-word operation.
  81. Return 0 if not done
  82. */
  83. switch (WordOrDouble(ds, size)) {
  84. default:
  85. return 0;
  86. case 1:
  87. if (ds->dsg_name) {
  88. C_loe_dnam(ds->dsg_name, ds->dsg_offset);
  89. }
  90. else C_lol(ds->dsg_offset);
  91. break;
  92. case 2:
  93. if (ds->dsg_name) {
  94. C_lde_dnam(ds->dsg_name, ds->dsg_offset);
  95. }
  96. else C_ldl(ds->dsg_offset);
  97. break;
  98. }
  99. return 1;
  100. }
  101. int
  102. DoStore(ds, size)
  103. register t_desig *ds;
  104. arith size;
  105. {
  106. /* Try to store designator with word or double-word operation.
  107. Return 0 if not done
  108. */
  109. switch (WordOrDouble(ds, size)) {
  110. default:
  111. return 0;
  112. case 1:
  113. if (ds->dsg_name) {
  114. C_ste_dnam(ds->dsg_name, ds->dsg_offset);
  115. }
  116. else C_stl(ds->dsg_offset);
  117. break;
  118. case 2:
  119. if (ds->dsg_name) {
  120. C_sde_dnam(ds->dsg_name, ds->dsg_offset);
  121. }
  122. else C_sdl(ds->dsg_offset);
  123. break;
  124. }
  125. return 1;
  126. }
  127. /* Return 1 if the type indicated by tp has a size that is a
  128. multiple of the word_size and is also word_aligned
  129. */
  130. #define word_multiple(tp) \
  131. ( (int)(tp->tp_size) % (int)word_size == 0 && \
  132. tp->tp_align >= word_align)
  133. /* Return 1 if the type indicated by tp has a size that is a proper
  134. dividor of the word_size, and has alignment >= size or
  135. alignment >= word_align
  136. */
  137. #define word_dividor(tp) \
  138. ( tp->tp_size < word_size && \
  139. (int)word_size % (int)(tp->tp_size) == 0 && \
  140. (tp->tp_align >= word_align || \
  141. tp->tp_align >= (int)(tp->tp_size)))
  142. #define USE_LOI_STI 0
  143. #define USE_LOS_STS 1
  144. #define USE_LOAD_STORE 2
  145. #define USE_BLM 3 /* like USE_LOI_STI, but more restricted:
  146. multiple of word_size only
  147. */
  148. STATIC int
  149. suitable_move(tp)
  150. register t_type *tp;
  151. {
  152. /* Find out how to load or store the value indicated by "ds".
  153. There are four ways:
  154. - suitable for BLM/LOI/STI
  155. - suitable for LOI/STI
  156. - suitable for LOS/STS/BLS
  157. - suitable for calls to load/store/blockmove
  158. */
  159. if (! word_multiple(tp)) {
  160. if (word_dividor(tp)) return USE_LOI_STI;
  161. return USE_LOAD_STORE;
  162. }
  163. if (! fit(tp->tp_size, (int) word_size)) return USE_LOS_STS;
  164. return USE_BLM;
  165. }
  166. CodeValue(ds, tp)
  167. register t_desig *ds;
  168. register t_type *tp;
  169. {
  170. /* Generate code to load the value of the designator described
  171. in "ds".
  172. */
  173. arith sz;
  174. switch(ds->dsg_kind) {
  175. case DSG_LOADED:
  176. break;
  177. case DSG_FIXED:
  178. if (DoLoad(ds, tp->tp_size)) break;
  179. /* Fall through */
  180. case DSG_PLOADED:
  181. case DSG_PFIXED:
  182. switch (suitable_move(tp)) {
  183. case USE_BLM:
  184. case USE_LOI_STI:
  185. #ifndef SQUEEZE
  186. CodeAddress(ds);
  187. C_loi(tp->tp_size);
  188. break;
  189. #endif
  190. case USE_LOS_STS:
  191. CodeAddress(ds);
  192. CodeConst(tp->tp_size, (int)pointer_size);
  193. C_los(pointer_size);
  194. break;
  195. case USE_LOAD_STORE:
  196. sz = WA(tp->tp_size);
  197. if (ds->dsg_kind != DSG_PFIXED) {
  198. arith tmp = NewPtr();
  199. CodeAddress(ds);
  200. STL(tmp, pointer_size);
  201. CodeConst(-sz, (int) pointer_size);
  202. C_ass(pointer_size);
  203. LOL(tmp, pointer_size);
  204. FreePtr(tmp);
  205. }
  206. else {
  207. CodeConst(-sz, (int) pointer_size);
  208. C_ass(pointer_size);
  209. CodeAddress(ds);
  210. }
  211. CodeConst(tp->tp_size, (int) pointer_size);
  212. CAL("load", (int)pointer_size + (int)pointer_size);
  213. break;
  214. }
  215. break;
  216. case DSG_INDEXED:
  217. C_lar(word_size);
  218. break;
  219. default:
  220. crash("(CodeValue)");
  221. }
  222. ds->dsg_kind = DSG_LOADED;
  223. }
  224. ChkForFOR(nd)
  225. register t_node *nd;
  226. {
  227. /* Check for an assignment to a FOR-loop control variable
  228. */
  229. if (nd->nd_class == Def) {
  230. register t_def *df = nd->nd_def;
  231. if (df->df_flags & D_FORLOOP) {
  232. node_warning(nd,
  233. W_ORDINARY,
  234. "assignment to FOR-loop control variable");
  235. df->df_flags &= ~D_FORLOOP;
  236. /* only procude warning once */
  237. }
  238. }
  239. }
  240. CodeStore(ds, tp)
  241. register t_desig *ds;
  242. register t_type *tp;
  243. {
  244. /* Generate code to store the value on the stack in the designator
  245. described in "ds"
  246. */
  247. switch(ds->dsg_kind) {
  248. case DSG_FIXED:
  249. if (DoStore(ds, tp->tp_size)) break;
  250. /* Fall through */
  251. case DSG_PLOADED:
  252. case DSG_PFIXED:
  253. CodeAddress(ds);
  254. switch (suitable_move(tp)) {
  255. case USE_BLM:
  256. case USE_LOI_STI:
  257. #ifndef SQUEEZE
  258. C_sti(tp->tp_size);
  259. break;
  260. #endif
  261. case USE_LOS_STS:
  262. CodeConst(tp->tp_size, (int) pointer_size);
  263. C_sts(pointer_size);
  264. break;
  265. case USE_LOAD_STORE:
  266. CodeConst(tp->tp_size, (int) pointer_size);
  267. C_cal("store");
  268. CodeConst(pointer_size + pointer_size + WA(tp->tp_size),
  269. (int) pointer_size);
  270. C_ass(pointer_size);
  271. break;
  272. }
  273. break;
  274. case DSG_INDEXED:
  275. C_sar(word_size);
  276. break;
  277. default:
  278. crash("(CodeStore)");
  279. }
  280. ds->dsg_kind = DSG_INIT;
  281. }
  282. CodeCopy(lhs, rhs, sz, psize)
  283. register t_desig *lhs, *rhs;
  284. arith sz, *psize;
  285. {
  286. /* Do part of a copy, which is assumed to be "reasonable",
  287. so that it can be done with LOI/STI or BLM.
  288. */
  289. t_desig l, r;
  290. l = *lhs; r = *rhs;
  291. *psize -= sz;
  292. lhs->dsg_offset += sz;
  293. rhs->dsg_offset += sz;
  294. CodeAddress(&r);
  295. if (sz <= dword_size) {
  296. C_loi(sz);
  297. CodeAddress(&l);
  298. C_sti(sz);
  299. }
  300. else {
  301. CodeAddress(&l);
  302. C_blm(sz);
  303. }
  304. }
  305. t_desig null_desig;
  306. CodeMove(rhs, left, rtp)
  307. register t_desig *rhs;
  308. register t_node *left;
  309. t_type *rtp;
  310. {
  311. /* Generate code for an assignment. Testing of type
  312. compatibility and the like is already done.
  313. Go through some (considerable) trouble to see if a BLM can be
  314. generated.
  315. */
  316. t_desig lhs;
  317. register t_type *tp = left->nd_type;
  318. int loadedflag = 0;
  319. lhs = null_desig;
  320. ChkForFOR(left);
  321. switch(rhs->dsg_kind) {
  322. case DSG_LOADED:
  323. CodeDesig(left, &lhs);
  324. if (rtp->tp_fund == T_STRING) {
  325. /* size of a string literal fits in an
  326. int of size word_size
  327. */
  328. CodeAddress(&lhs);
  329. C_loc(rtp->tp_size);
  330. C_loc(tp->tp_size);
  331. CAL("StringAssign", (int)pointer_size + (int)pointer_size + (int)dword_size);
  332. break;
  333. }
  334. CodeStore(&lhs, tp);
  335. break;
  336. case DSG_FIXED:
  337. CodeDesig(left, &lhs);
  338. if (lhs.dsg_kind == DSG_FIXED &&
  339. fit(tp->tp_size, (int) word_size) &&
  340. (int) (lhs.dsg_offset) % word_align ==
  341. (int) (rhs->dsg_offset) % word_align) {
  342. register int sz = 1;
  343. arith size = tp->tp_size;
  344. while (size && sz < word_align) {
  345. /* First copy up to word-aligned
  346. boundaries
  347. */
  348. if (!((int)(lhs.dsg_offset)%(sz+sz))) {
  349. sz += sz;
  350. }
  351. else CodeCopy(&lhs, rhs, (arith) sz, &size);
  352. }
  353. /* Now copy the bulk
  354. */
  355. sz = (int) size % (int) word_size;
  356. size -= sz;
  357. CodeCopy(&lhs, rhs, size, &size);
  358. size = sz;
  359. sz = word_size;
  360. while (size) {
  361. /* And then copy remaining parts
  362. */
  363. sz >>= 1;
  364. if (size >= sz) {
  365. CodeCopy(&lhs, rhs, (arith) sz, &size);
  366. }
  367. }
  368. break;
  369. }
  370. CodeAddress(&lhs);
  371. loadedflag = 1;
  372. /* Fall through */
  373. case DSG_PLOADED:
  374. case DSG_PFIXED:
  375. assert(! loadedflag || rhs->dsg_kind == DSG_FIXED);
  376. CodeAddress(rhs);
  377. if (loadedflag) {
  378. C_exg(pointer_size);
  379. }
  380. else {
  381. CodeDesig(left, &lhs);
  382. CodeAddress(&lhs);
  383. }
  384. switch (suitable_move(tp)) {
  385. case USE_BLM:
  386. #ifndef SQUEEZE
  387. C_blm(tp->tp_size);
  388. break;
  389. #endif
  390. case USE_LOS_STS:
  391. CodeConst(tp->tp_size, (int) pointer_size);
  392. C_bls(pointer_size);
  393. break;
  394. case USE_LOAD_STORE:
  395. case USE_LOI_STI:
  396. CodeConst(tp->tp_size, (int) pointer_size);
  397. CAL("blockmove", 3 * (int)pointer_size);
  398. break;
  399. }
  400. break;
  401. default:
  402. crash("CodeMove");
  403. }
  404. }
  405. CodeAddress(ds)
  406. register t_desig *ds;
  407. {
  408. /* Generate code to load the address of the designator described
  409. in "ds"
  410. */
  411. switch(ds->dsg_kind) {
  412. case DSG_PLOADED:
  413. if (ds->dsg_offset) {
  414. C_adp(ds->dsg_offset);
  415. }
  416. break;
  417. case DSG_FIXED:
  418. if (ds->dsg_name) {
  419. C_lae_dnam(ds->dsg_name, ds->dsg_offset);
  420. break;
  421. }
  422. C_lal(ds->dsg_offset);
  423. if (ds->dsg_def) ds->dsg_def->df_flags |= D_NOREG;
  424. break;
  425. case DSG_PFIXED:
  426. if (! DoLoad(ds, pointer_size)) {
  427. assert(0);
  428. }
  429. break;
  430. case DSG_INDEXED:
  431. C_aar(word_size);
  432. break;
  433. default:
  434. crash("(CodeAddress)");
  435. }
  436. ds->dsg_offset = 0;
  437. ds->dsg_kind = DSG_PLOADED;
  438. }
  439. CodeFieldDesig(df, ds)
  440. register t_def *df;
  441. register t_desig *ds;
  442. {
  443. /* Generate code for a field designator. Only the code common for
  444. address as well as value computation is generated, and the
  445. resulting information on where to find the designator is placed
  446. in "ds". "df" indicates the definition of the field.
  447. */
  448. if (ds->dsg_kind == DSG_INIT) {
  449. /* In a WITH statement. We must find the designator in the
  450. WITH statement, and act as if the field is a selection
  451. of this designator.
  452. So, first find the right WITH statement, which is the
  453. first one of the proper record type, which is
  454. recognized by its scope indication.
  455. */
  456. register struct withdesig *wds = WithDesigs;
  457. assert(wds != 0);
  458. while (wds->w_scope != df->df_scope) {
  459. wds = wds->w_next;
  460. assert(wds != 0);
  461. }
  462. /* Found it. Now, act like it was a selection.
  463. */
  464. *ds = wds->w_desig;
  465. wds->w_flags |= df->df_flags;
  466. assert(ds->dsg_kind == DSG_PFIXED);
  467. }
  468. switch(ds->dsg_kind) {
  469. case DSG_PLOADED:
  470. case DSG_FIXED:
  471. ds->dsg_offset += df->fld_off;
  472. break;
  473. case DSG_PFIXED:
  474. case DSG_INDEXED:
  475. CodeAddress(ds);
  476. ds->dsg_kind = DSG_PLOADED;
  477. ds->dsg_offset = df->fld_off;
  478. break;
  479. default:
  480. crash("(CodeFieldDesig)");
  481. }
  482. }
  483. CodeVarDesig(df, ds)
  484. register t_def *df;
  485. register t_desig *ds;
  486. {
  487. /* Generate code for a variable represented by a "def" structure.
  488. Of course, there are numerous cases: the variable is local,
  489. it is a value parameter, it is a var parameter, it is one of
  490. those of an enclosing procedure, or it is global.
  491. */
  492. register t_scope *sc = df->df_scope;
  493. int difflevel;
  494. /* Selections from a module are handled earlier, when identifying
  495. the variable, so ...
  496. */
  497. assert(ds->dsg_kind == DSG_INIT);
  498. if (df->df_flags & D_ADDRGIVEN) {
  499. /* the programmer specified an address in the declaration of
  500. the variable. Generate code to push the address.
  501. */
  502. CodeConst(df->var_off, (int) pointer_size);
  503. ds->dsg_kind = DSG_PLOADED;
  504. ds->dsg_offset = 0;
  505. return;
  506. }
  507. if (df->var_name) {
  508. /* this variable has been given a name, so it is global.
  509. It is directly accessible.
  510. */
  511. ds->dsg_name = df->var_name;
  512. ds->dsg_offset = 0;
  513. ds->dsg_kind = DSG_FIXED;
  514. return;
  515. }
  516. if ((difflevel = proclevel - sc->sc_level) != 0) {
  517. /* the variable is local to a statically enclosing procedure.
  518. */
  519. assert(difflevel > 0);
  520. df->df_flags |= D_NOREG;
  521. if (df->df_flags & (D_VARPAR|D_VALPAR)) {
  522. /* value or var parameter
  523. */
  524. C_lxa((arith) difflevel);
  525. if ((df->df_flags & D_VARPAR) ||
  526. IsConformantArray(df->df_type)) {
  527. /* var parameter or conformant array.
  528. The address is passed.
  529. */
  530. C_adp(df->var_off);
  531. C_loi(pointer_size);
  532. ds->dsg_offset = 0;
  533. ds->dsg_kind = DSG_PLOADED;
  534. return;
  535. }
  536. }
  537. else C_lxl((arith) difflevel);
  538. ds->dsg_kind = DSG_PLOADED;
  539. ds->dsg_offset = df->var_off;
  540. return;
  541. }
  542. /* Now, finally, we have a local variable or a local parameter
  543. */
  544. if ((df->df_flags & D_VARPAR) ||
  545. IsConformantArray(df->df_type)) {
  546. /* a var parameter; address directly accessible.
  547. */
  548. ds->dsg_kind = DSG_PFIXED;
  549. }
  550. else ds->dsg_kind = DSG_FIXED;
  551. ds->dsg_offset = df->var_off;
  552. ds->dsg_def = df;
  553. }
  554. CodeDesig(nd, ds)
  555. register t_node *nd;
  556. register t_desig *ds;
  557. {
  558. /* Generate code for a designator. Use divide and conquer
  559. principle
  560. */
  561. register t_def *df;
  562. switch(nd->nd_class) { /* Divide */
  563. case Def:
  564. df = nd->nd_def;
  565. if (nd->nd_NEXT) CodeDesig(nd->nd_NEXT, ds);
  566. switch(df->df_kind) {
  567. case D_FIELD:
  568. CodeFieldDesig(df, ds);
  569. break;
  570. case D_VARIABLE:
  571. CodeVarDesig(df, ds);
  572. break;
  573. default:
  574. crash("(CodeDesig) Def");
  575. }
  576. break;
  577. case Arrsel:
  578. assert(nd->nd_symb == '[' || nd->nd_symb == ',');
  579. CodeDesig(nd->nd_LEFT, ds);
  580. CodeAddress(ds);
  581. CodePExpr(nd->nd_RIGHT);
  582. nd = nd->nd_LEFT;
  583. /* Now load address of descriptor
  584. */
  585. if (IsConformantArray(nd->nd_type)) {
  586. arith off;
  587. assert(nd->nd_class == Def);
  588. df = nd->nd_def;
  589. off = df->var_off + pointer_size;
  590. if (proclevel > df->df_scope->sc_level) {
  591. C_lxa((arith) (proclevel - df->df_scope->sc_level));
  592. C_adp(off);
  593. }
  594. else C_lal(off);
  595. }
  596. else {
  597. C_loc(nd->nd_type->arr_low);
  598. C_sbu(int_size);
  599. c_lae_dlb(nd->nd_type->arr_descr);
  600. }
  601. if (options['A']) {
  602. C_cal("rcka");
  603. }
  604. ds->dsg_kind = DSG_INDEXED;
  605. break;
  606. case Arrow:
  607. assert(nd->nd_symb == '^');
  608. nd = nd->nd_RIGHT;
  609. CodeDesig(nd, ds);
  610. switch(ds->dsg_kind) {
  611. case DSG_LOADED:
  612. ds->dsg_kind = DSG_PLOADED;
  613. break;
  614. case DSG_INDEXED:
  615. case DSG_PLOADED:
  616. case DSG_PFIXED:
  617. CodeValue(ds, nd->nd_type);
  618. ds->dsg_kind = DSG_PLOADED;
  619. ds->dsg_offset = 0;
  620. break;
  621. case DSG_FIXED:
  622. ds->dsg_kind = DSG_PFIXED;
  623. break;
  624. default:
  625. crash("(CodeDesig) Uoper");
  626. }
  627. break;
  628. default:
  629. crash("(CodeDesig) class");
  630. }
  631. }