put.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. /* $Id$ */
  2. /*
  3. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
  4. * See the copyright notice in the ACK home directory, in the file "Copyright".
  5. */
  6. /* P U T . C */
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <em_pseu.h>
  10. #include <em_spec.h>
  11. #include "types.h"
  12. #include "global.h"
  13. #include "debug.h"
  14. #include "def.h"
  15. #include "map.h"
  16. #include "lset.h"
  17. #include "alloc.h"
  18. #include "put.h"
  19. #include "cset.h"
  20. FILE *curoutp;
  21. /* The output can be either 'typed' or 'untyped'. Typed data
  22. * consists of a value preceded by a byte specifying what kind
  23. * of value it is (e.g. 2 bytes constant, 4 bytes constant,
  24. * proc-id, lab-id, string etc.). Untyped data consists
  25. * of the value only. We use typed data for the EM text and
  26. * untyped data for all other files.
  27. */
  28. /* putlines */
  29. static void putstr(argb_p abp);
  30. static void outlab(lab_id lid);
  31. static void outobject(obj_p obj);
  32. static void putstr(argb_p abp);
  33. static void putstr(argb_p abp);
  34. static void putargs(arg_p ap)
  35. {
  36. while (ap != (arg_p) 0) {
  37. outbyte((byte) ap->a_type & BMASK);
  38. switch(ap->a_type) {
  39. case ARGOFF:
  40. outoff(ap->a_a.a_offset);
  41. break;
  42. case ARGINSTRLAB:
  43. outlab(ap->a_a.a_instrlab);
  44. break;
  45. case ARGOBJECT:
  46. outobject(ap->a_a.a_obj);
  47. break;
  48. case ARGPROC:
  49. outproc(ap->a_a.a_proc);
  50. break;
  51. case ARGSTRING:
  52. putstr(&ap->a_a.a_string);
  53. break;
  54. case ARGICN:
  55. case ARGUCN:
  56. case ARGFCN:
  57. outshort(ap->a_a.a_con.ac_length);
  58. putstr(&ap->a_a.a_con.ac_con);
  59. break;
  60. }
  61. ap = ap->a_next;
  62. }
  63. outbyte((byte) ARGCEND);
  64. }
  65. static void putstr(argb_p abp)
  66. {
  67. argb_p tbp;
  68. int length;
  69. length = 0;
  70. tbp = abp;
  71. while (tbp!= (argb_p) 0) {
  72. length += tbp->ab_index;
  73. tbp = tbp->ab_next;
  74. }
  75. outshort(length);
  76. while (abp != (argb_p) 0) {
  77. for (length=0;length<abp->ab_index;length++)
  78. outbyte( (byte) abp->ab_contents[length] );
  79. abp = abp->ab_next;
  80. }
  81. }
  82. void outoff(offset off)
  83. {
  84. outshort( (short) (off&0177777L) );
  85. outshort( (short) (off>>16) );
  86. }
  87. void outshort(short i)
  88. {
  89. outbyte( (byte) (i&BMASK) );
  90. outbyte( (byte) (i>>8) );
  91. }
  92. static void outint(int i)
  93. {
  94. /* Write an integer to the output file. This routine is
  95. * only used when outputting a bitvector-set. We expect an
  96. * integer to be either a short or a long.
  97. */
  98. if (sizeof(int) == sizeof(short)) {
  99. outshort(i);
  100. } else {
  101. assert (sizeof(int) == sizeof(offset));
  102. outoff((offset) i);
  103. }
  104. }
  105. static void outlab(lab_id lid)
  106. {
  107. outshort((short) lid);
  108. }
  109. static void outobject(obj_p obj)
  110. {
  111. outshort((short) obj->o_id);
  112. }
  113. void outproc(proc_p p)
  114. {
  115. outshort((short) p->p_id);
  116. }
  117. short putlines(line_p l, FILE *lf)
  118. {
  119. /* Output the list of em instructions headed by l.
  120. * Return the number of instruction written.
  121. */
  122. line_p lnp;
  123. line_p next;
  124. short instr;
  125. short count= 0;
  126. curoutp = lf; /* Set f to the EM-text output file */
  127. for (lnp = l; lnp != (line_p) 0; lnp = next) {
  128. VL(lnp);
  129. count++;
  130. next = lnp->l_next;
  131. instr = INSTR(lnp);
  132. outbyte((byte) instr);
  133. outbyte((byte) TYPE(lnp));
  134. switch(TYPE(lnp)) {
  135. case OPSHORT:
  136. outshort(SHORT(lnp));
  137. break;
  138. case OPOFFSET:
  139. outoff(OFFSET(lnp));
  140. break;
  141. case OPINSTRLAB:
  142. outlab(INSTRLAB(lnp));
  143. break;
  144. case OPOBJECT:
  145. outobject(OBJ(lnp));
  146. break;
  147. case OPPROC:
  148. outproc(PROC(lnp));
  149. break;
  150. case OPLIST:
  151. putargs(ARG(lnp));
  152. break;
  153. }
  154. oldline(lnp);
  155. }
  156. return count;
  157. }
  158. /* putdtable */
  159. #define outmark(m) outbyte((byte) m)
  160. static void putobjects(obj_p obj)
  161. {
  162. while (obj != (obj_p) 0) {
  163. outmark(MARK_OBJ);
  164. outshort(obj->o_id);
  165. outoff(obj->o_size);
  166. outoff(obj->o_off);
  167. obj = obj->o_next;
  168. }
  169. }
  170. static void putvalues(arg_p arg)
  171. {
  172. while (arg != (arg_p) 0) {
  173. assert(arg->a_type == ARGOFF);
  174. outmark(MARK_ARG);
  175. outoff(arg->a_a.a_offset);
  176. arg = arg->a_next;
  177. }
  178. }
  179. void putdtable(dblock_p head, FILE *df)
  180. {
  181. /* Write the datablock table to the data block file df. */
  182. dblock_p dbl;
  183. obj_p obj;
  184. dblock_p next;
  185. short n = 0;
  186. curoutp = df; /* set f to the data block output file */
  187. /* Count the number of objects */
  188. for (dbl = head; dbl != (dblock_p) 0; dbl = dbl->d_next) {
  189. for (obj = dbl->d_objlist; obj != (obj_p) 0;
  190. obj = obj->o_next) {
  191. n++;
  192. }
  193. }
  194. outshort(n); /* The table is preceded by #objects . */
  195. for (dbl = head; dbl != (dblock_p) 0; dbl = next) {
  196. next = dbl->d_next;
  197. outmark(MARK_DBLOCK);
  198. outshort(dbl->d_id);
  199. outbyte(dbl->d_pseudo);
  200. outoff(dbl->d_size);
  201. outshort(dbl->d_fragmnr);
  202. outbyte(dbl->d_flags1);
  203. putobjects(dbl->d_objlist);
  204. putvalues(dbl->d_values);
  205. olddblock(dbl);
  206. }
  207. fclose(curoutp);
  208. if (omap != (obj_p *) 0) {
  209. oldmap((short **) omap,olength); /* release memory for omap */
  210. }
  211. }
  212. /* putptable */
  213. static void outcset(cset s)
  214. {
  215. /* A 'compact' set is represented externally as a row of words
  216. * (its bitvector) preceded by its length.
  217. */
  218. short i;
  219. outshort(s->v_size);
  220. for (i = 0; i <= DIVWL(s->v_size - 1); i++) {
  221. outint(s->v_bits[i]);
  222. }
  223. }
  224. void putptable(proc_p head, FILE *pf, bool all)
  225. {
  226. proc_p p;
  227. proc_p next;
  228. short n = 0;
  229. /* Write the proc table */
  230. curoutp = pf;
  231. /* Determine the number of procs */
  232. for (p = head; p != (proc_p) 0; p = p->p_next) {
  233. n++;
  234. }
  235. outshort(n); /* The table is preceded by its length. */
  236. outshort ((all?1:0)); /* if all=false, only some of the attributes
  237. are written. */
  238. for (p = head; p != (proc_p) 0; p = next) {
  239. next = p->p_next;
  240. outshort(p->p_id);
  241. outbyte(p->p_flags1);
  242. if (p->p_flags1 & PF_BODYSEEN) {
  243. /* If we have no access to the EM text of the
  244. * body of a procedure, we have no information
  245. * about it whatsoever, so there is nothing
  246. * to output in that case.
  247. */
  248. outshort(p->p_nrlabels);
  249. outoff(p->p_localbytes);
  250. outoff(p->p_nrformals);
  251. if (all) {
  252. outcset(p->p_change->c_ext);
  253. outshort(p->p_change->c_flags);
  254. outshort(p->p_use->u_flags);
  255. outcset(p->p_calling);
  256. Cdeleteset(p->p_change->c_ext);
  257. oldchange(p->p_change);
  258. olduse(p->p_use);
  259. Cdeleteset(p->p_calling);
  260. }
  261. }
  262. oldproc(p);
  263. }
  264. fclose(curoutp);
  265. if (pmap != (proc_p *) 0) {
  266. oldmap((short **) pmap,plength); /* release memory for pmap */
  267. }
  268. }
  269. /* putunit */
  270. static void outloop(Lelem_t param)
  271. {
  272. loop_p l = (loop_p)param;
  273. outshort((short) l->lp_id);
  274. }
  275. static void outblock(Lelem_t param)
  276. {
  277. bblock_p b = (bblock_p)param;
  278. if (b == (bblock_p) 0) {
  279. outshort((short) 0);
  280. } else {
  281. outshort((short) b->b_id);
  282. }
  283. }
  284. static void outid(Lelem_t e, void (*p)(Lelem_t))
  285. {
  286. /* Auxiliary routine used by outlset. */
  287. /* NOSTRICT */
  288. (*p) (e);
  289. }
  290. static void outlset(lset s, void (*p)(Lelem_t))
  291. {
  292. /* A 'long' set is represented externally as a
  293. * a sequence of elements terminated by a 0 word.
  294. * The procedural parameter p is a routine that
  295. * prints an id (proc_id, obj_id etc.).
  296. */
  297. Lindex i;
  298. for (i = Lfirst(s); i != (Lindex) 0; i = Lnext(i,s)) {
  299. outid(Lelem(i),p);
  300. }
  301. outshort((short) 0);
  302. }
  303. void putunit(short kind, proc_p p, line_p l, FILE *gf, FILE *lf)
  304. {
  305. bblock_p b;
  306. short n = 0;
  307. Lindex pi;
  308. loop_p lp;
  309. curoutp = gf;
  310. if (kind == LDATA) {
  311. outshort(0); /* No basic blocks */
  312. n = putlines(l,lf);
  313. curoutp = gf;
  314. outshort(n);
  315. return;
  316. }
  317. /* Determine the number of basic blocks */
  318. for (b = p->p_start; b != (bblock_p) 0; b = b->b_next) {
  319. n++;
  320. }
  321. outshort(n); /* # basic blocks */
  322. outshort(Lnrelems(p->p_loops)); /* # loops */
  323. for (b = p->p_start; b != (bblock_p) 0; b = b->b_next) {
  324. n = putlines(b->b_start,lf);
  325. curoutp = gf;
  326. outblock(b); /* put its block_id */
  327. outshort(n); /* #instructions of the block */
  328. outlset(b->b_succ, outblock); /* put succ set */
  329. outlset(b->b_pred, outblock); /* put pred set */
  330. outblock(b->b_idom); /* put id of immediate dominator */
  331. outlset(b->b_loops, outloop); /* put loop set */
  332. outshort(b->b_flags);
  333. }
  334. /* The Control Flow Graph of every procedure is followed
  335. * by a description of the loops of the procedure.
  336. * Every loop contains an id, an entry block and a level.
  337. */
  338. for (pi = Lfirst(p->p_loops); pi != (Lindex) 0;
  339. pi = Lnext(pi,p->p_loops)) {
  340. lp = (loop_p) Lelem(pi);
  341. outloop(lp); /* id */
  342. outshort(lp->lp_level); /* nesting level */
  343. outblock(lp->lp_entry); /* loop entry block */
  344. outblock(lp->lp_end);
  345. oldloop(lp);
  346. }
  347. Ldeleteset(p->p_loops);
  348. /* We will now release the memory of the basic blocks.
  349. * Note that it would be incorrect to release a basic block
  350. * after it has been written, because there may be references
  351. * to it from other (later) blocks.
  352. */
  353. for (b = p->p_start; b != (bblock_p) 0; b = b->b_next) {
  354. Ldeleteset(b->b_loops);
  355. Ldeleteset(b->b_succ);
  356. Ldeleteset(b->b_pred);
  357. oldbblock(b);
  358. }
  359. /* Release the memory for the lmap, lbmap, bmap, lpmap tables */
  360. if (lmap != (line_p *) 0) oldmap((short **) lmap,llength);
  361. if (lbmap != (bblock_p *) 0) oldmap((short **) lbmap,llength);
  362. if (bmap != (bblock_p *) 0) oldmap((short **) bmap,blength);
  363. if (lpmap != (loop_p *) 0) oldmap((short **) lpmap,lplength);
  364. curoutp = lf;
  365. }