put.c 8.8 KB

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