Pristine Ack-5.5
[Ack-5.5.git] / util / ego / il / il3_subst.c
1 /* $Id: il3_subst.c,v 1.6 1994/06/24 10:26:01 ceriel Exp $ */
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 /*  I N L I N E   S U B S T I T U T I O N
7  *
8  *  I L 3 _ S U B S T . C
9  */
10
11 #include <stdio.h>
12 #include <em_mnem.h>
13 #include "../share/types.h"
14 #include "il.h"
15 #include "../share/debug.h"
16 #include "../share/alloc.h"
17 #include "../share/global.h"
18 #include "../share/lset.h"
19 #include "../share/get.h"
20 #include "il_aux.h"
21 #include "il3_aux.h"
22 #include "il3_change.h"
23 #include "il3_subst.h"
24
25 STATIC line_p fetch_text(lf,c)
26         FILE *lf;
27         call_p c;
28 {
29         /* Read the EM text of the called procedure.
30          * We use random access I/O here.
31          */
32
33         line_p l;
34         proc_p p;
35         lset   savmes;
36
37         savmes = mesregs;
38         mesregs = Lempty_set();
39         fseek(lf,c->cl_proc->P_LADDR,0);
40         l = get_text(lf,&p);
41         assert (p == c->cl_proc);
42         Ldeleteset(mesregs);
43         mesregs = savmes;
44         return l;
45 }
46
47
48
49
50 line_p scan_to_cal(lines,n)
51         line_p lines;
52         short  n;
53 {
54         /* Find the n-th CAL instruction */
55
56         register line_p l;
57
58         for (l = lines; l != (line_p) 0; l = l->l_next) {
59                 if (INSTR(l) == op_cal) {
60                         if (--n == 0) return l;
61                 }
62         }
63         return (line_p) 0; /* CAL not found */
64 }
65
66
67
68 substitute(lf,c,cal,firstline)
69         FILE *lf;
70         call_p c;
71         line_p cal,firstline;
72 {
73         /* Perform in line substitution of the call described
74          * by c. The EM text of the called routine is fetched
75          * and modified, the calling sequence is changed,
76          * the modified routine is put at the place of the call
77          * and all global information (proctable etc.) is kept
78          * up to date.
79          */
80
81         line_p l, text, lab;
82         offset ab_off, lb_off;
83         line_p startscan, ncal;
84         short lastcid;
85         call_p nc;
86
87         Ssubst++;
88         ab_off = - curproc->p_localbytes;
89         /* offset of temporaries for parameters
90          * that are not expanded in line.
91          */
92         chg_callseq(c,cal,&l);
93         /* Change the calling sequence; l points to the place
94          * where the expanded text must be put
95          */
96         text = fetch_text(lf,c);        /* fetch EM text of called routine */
97         lb_off = - curproc->p_localbytes;
98         /* offset of temps. for locals of called proc. */
99         curproc->p_localbytes += c->cl_proc->P_ORGLOCALS;
100         /* locals of called routine are put in stack frame of caller */
101         if (!FALLTHROUGH(c->cl_proc)) {
102                 /* The called proc contains one or more RETurns
103                  * somewhere in the middle of its text; these
104                  * should be changed into a jump to the end
105                  * of the text. We create a label for this
106                  * purpose (if there was no one already).
107                  */
108                 lab = make_label(l,curproc);
109         }
110         modify(text,c,lab,ab_off,lb_off,curproc->p_nrlabels);
111         curproc->p_nrlabels += c->cl_proc->P_ORGLABELS;
112         insert(text,l,firstline);
113         /* insert text; instructions are put after l, pseudos
114          * are put at beginning of caller.
115          */
116         /* Now take care of the nested calls */
117         startscan = l->l_next;
118         lastcid = 0;
119         for (nc = c->cl_car; nc != (call_p) 0; nc = nc->cl_cdr) {
120                 mod_actuals(nc,c,lab,ab_off,lb_off,curproc->p_nrlabels);
121                 ncal = scan_to_cal(startscan,nc->cl_id - lastcid);
122                 assert(ncal != (line_p) 0);
123                 startscan = scan_to_cal(ncal->l_next,1);
124                 lastcid = nc->cl_id;
125                 substitute(lf,nc,ncal,firstline);
126         }
127 }