Pristine Ack-5.5
[Ack-5.5.git] / util / ego / il / il1_anal.c
1 /* $Id: il1_anal.c,v 1.8 1994/06/24 10:25:18 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 1 _ A N A L . C
9  */
10
11 #include <stdio.h>
12 #include <em_mnem.h>
13 #include <em_pseu.h>
14 #include "../share/types.h"
15 #include "il.h"
16 #include "../share/debug.h"
17 #include "../share/alloc.h"
18 #include "../share/global.h"
19 #include "../share/lset.h"
20 #include "../share/aux.h"
21 #include "il1_aux.h"
22 #include "il1_formal.h"
23 #include "il1_cal.h"
24 #include "il1_anal.h"
25 #include "il_aux.h"
26 #include "../share/put.h"
27
28 #define ENVIRON(p)              (p->p_flags1 & (byte) PF_ENVIRON)
29 #define RETURN_BLOCK(b)         (Lnrelems(b->b_succ) == 0)
30 #define LAST_BLOCK(b)           (b->b_next == (bblock_p) 0)
31
32 /* Daisy chain recursion not yet accounted for: */
33 #define RECURSIVE(p)            (Cis_elem(p->p_id,p->p_calling))
34 /*
35 #define CALLS_UNKNOWN(p)        (p->p_flags1 & (byte) PF_CALUNKNOWN)
36 */
37 #define CALLS_UNKNOWN(p)        (FALSE)
38
39
40
41 apriori(proctab)
42         proc_p proctab;
43 {
44         /* For every procedure, see if we can determine
45          * from the information provided by the previous
46          * phases of the optimizer that it cannot or should not
47          * be expanded in line. This will reduce the length
48          * of the call list.
49          */
50
51         register proc_p p;
52
53         for (p = proctab; p != (proc_p) 0; p = p->p_next) {
54                 if (!BODY_KNOWN(p)  ||
55                      ENVIRON(p) || RECURSIVE(p) ||
56                      PARAMS_UNKNOWN(p) || MANY_LOCALS(p) ||
57                      IS_ENTERED_WITH_GTO(p)) {
58                          UNSUITABLE(p);
59 #ifdef VERBOSE
60                         if (BODY_KNOWN(p)) {
61                                 if (ENVIRON(p)) Senv++;
62                                 if (RECURSIVE(p)) Srecursive++;
63                                 if (MANY_LOCALS(p)) Slocals++;
64                         }
65 #endif
66                 }
67         }
68 }
69
70
71 STATIC check_labels(p,arglist)
72         proc_p p;
73         arg_p arglist;
74 {
75         /* Check if any of the arguments contains an instruction
76          * label; if so, make p unsuitable.
77          */
78
79         arg_p arg;
80
81         for (arg = arglist; arg != (arg_p) 0; arg = arg->a_next) {
82                 if (arg->a_type == ARGINSTRLAB) {
83                         UNSUITABLE(p);
84 #ifdef VERBOSE
85                         Sinstrlab++;
86 #endif
87                         break;
88                 }
89         }
90 }
91
92
93
94 STATIC anal_instr(p,b,cf)
95         proc_p   p;
96         bblock_p b;
97         FILE     *cf;
98 {
99         /* Analyze the instructions of block b
100          * within procedure p.
101          * See which parameters are used, changed
102          * or have their address taken. Recognize
103          * the actual parameter expressions of
104          * the CAL instructions.
105          */
106
107         register line_p l;
108
109         for (l = b->b_start; l != (line_p) 0; l = l->l_next) {
110            switch(INSTR(l)) {
111                 case op_cal:
112                         anal_cal(p,l,b,cf);
113                         break;
114                 case op_stl:
115                 case op_inl:
116                 case op_del:
117                 case op_zrl:
118                         formal(p,b,off_set(l),SINGLE,CHANGE);
119                         /* see if the local is a parameter.
120                          * If so, it is a one-word parameter
121                          * that is stored into.
122                          */
123                         break;
124                 case op_sdl:
125                         formal(p,b,off_set(l),DOUBLE,CHANGE);
126                         break;
127                 case op_lol:
128                         formal(p,b,off_set(l),SINGLE,USE);
129                         break;
130                 case op_ldl:
131                         formal(p,b,off_set(l),DOUBLE,USE);
132                         break;
133                 case op_sil:
134                 case op_lil:
135                         formal(p,b,off_set(l),POINTER,USE);
136                         break;
137                 case op_lal:
138                         formal(p,b,off_set(l),UNKNOWN,ADDRESS);
139                         break;
140                 case ps_rom:
141                 case ps_con:
142                 case ps_bss:
143                 case ps_hol:
144                         check_labels(p,ARG(l));
145                         break;
146                 case op_nop:    /* volatile */
147                         UNSUITABLE(p);
148                         break;
149            }
150         }
151 }
152
153
154
155 anal_proc(p,cf,ccf)
156         proc_p p;
157         FILE   *cf,*ccf;
158 {
159         /* Analyze a procedure; use information
160          * stored in its basic blocks or in
161          * its instructions.
162          */
163
164         register bblock_p b;
165         bool     fallthrough = TRUE;
166
167         cchead = (calcnt_p) 0;
168         for (b = p->p_start; b != (bblock_p) 0; b = b->b_next) {
169                 if (RETURN_BLOCK(b) && !LAST_BLOCK(b)) {
170                         fallthrough = FALSE;
171                         /* p contains a RET instruction somewhere
172                          * in the middle of its code.
173                          */
174                 }
175                 anal_instr(p,b,cf); /* analyze instructions */
176         }
177         if (fallthrough) {
178                 p->p_flags2 |= PF_FALLTHROUGH;
179         }
180         rem_indir_acc(p);
181         /* don't expand formal that may be accessed indirectly */
182         p->P_CCADDR = putcc(cchead,ccf);
183         /* write calcnt info and remember disk address */
184         remcc(cchead);
185 }