|
|
1.1 root 1: /*
2: * Sydney C Compiler.
3: *
4: * Copyright 1984, Bruce Ellis.
5: *
6: * Unauthorised possesion, sale or use prohibited.
7: */
8:
9: #include "defs.h"
10: #include "cnodes.h"
11: #include "flow.h"
12:
13: /*
14: * Lifetime determination.
15: *
16: * Method (per pure ident):
17: *
18: * Initially the ords are set to L_NONE and the flags contain
19: * possibly the five flow set flags. The outer loop attempts to
20: * fill in the graph's ords. Each fill is cut by C_CUT_ID nodes
21: * and dead ends. A fill is further processed twice. The fill's
22: * ords are set to L_ACTIVE in the outer loop. The first scan
23: * breaks the fill up into id equivalent classes and detects which
24: * of these classes are active. Equivalence classes start at
25: * L_EQUIV and go up. The equivalence class values are stored in a
26: * vector. The second pass marks the nodes in inactive classes as
27: * dead and assigns a new ordinal, unique to this fill, to the
28: * active node. These start at L_HEAD, which signifies that this
29: * fill started at the function entry point, and go down.
30: *
31: * Four types of diagnostics can be gained from this analysis. The
32: * error [variable used where it cannot have a meaningful value],
33: * the weaker warning [variable may be used before set], and the
34: * warnings [value assigned to variable not used] and [initial
35: * value of argument not used].
36: *
37: * Suspensions.
38: * ------------
39: * An equiv class that is under consideration goes into E_SUSP
40: * mode. His knowledge starts off suspended. E_SUSP is the
41: * identity element under (|), equiv combination. Since we have no
42: * unreachable code each fill must be resolved by a write or the
43: * top of the code. Thus we can change all current suspensions to
44: * the return value at the base level.
45: */
46:
47: /*
48: * Initialise equivalence data.
49: */
50: void
51: equiv_init()
52: {
53: register int i;
54:
55: eord = L_EQUIV;
56:
57: for (i = 0; i < equiv_max; i++)
58: equiv_value[i] = 0;
59: }
60:
61: /*
62: * Store equivalence value.
63: */
64: void
65: equiv_store(i, v)
66: register int i;
67: int v;
68: {
69: if (i >= equiv_max)
70: {
71: equiv_max = E_ROUND(i);
72: equiv_value = vector(equiv_value, equiv_max, char);
73: }
74:
75: equiv_value[i] = v;
76: }
77:
78: /*
79: * Trace an equivalence class of an instance of an identifier.
80: */
81: int
82: trace_equiv(start)
83: cnode *start;
84: {
85: typedef enum
86: {
87: eq_combine,
88: eq_return,
89: eq_scan,
90: }
91: eq_states;
92:
93: register cnode *c;
94: register int ret;
95: register int ord;
96: register int combine;
97: register eq_states state;
98: register int cmod;
99:
100: static int equiv_combine[4][4] =
101: {
102: /* E_NONE, E_SOME, E_ALL, E_SUSP */
103: E_NONE, E_SOME, E_SOME, E_NONE, /* E_NONE */
104: E_SOME, E_SOME, E_SOME, E_SOME, /* E_SOME */
105: E_SOME, E_SOME, E_ALL, E_ALL, /* E_ALL */
106: E_NONE, E_SOME, E_ALL, E_SUSP, /* E_SUSP */
107: };
108:
109: combine = E_NONE;
110: c = start;
111: ord = eord++;
112: equiv_store(ord, E_SUSP);
113: ret = E_SUSP;
114: cmod = 0;
115: state = eq_scan;
116:
117: loop
118: {
119: switch (state)
120: {
121: case eq_combine:
122: ret = equiv_combine[ret][combine];
123: state = eq_scan;
124: break;
125:
126: case eq_return:
127: if (ret == E_NONE && cmod)
128: ret = E_SOME;
129:
130: return equiv_value[ord] = equiv_combine[ret][combine];
131:
132: case eq_scan:
133: if (c == NULL)
134: {
135: if (trace_argument)
136: combine = E_ALL;
137: else
138: combine = E_NONE;
139:
140: state = eq_return;
141: continue;
142: }
143:
144:
145: if (in(mip_dead_ends, c->c_what) && c != start)
146: {
147: combine = E_SUSP;
148: state = eq_return;
149: continue;
150: }
151:
152: if (c->c_ord == ord)
153: internal("trace_equiv", "circular last trail");
154:
155: if ((c->c_flags & C_X_MOD) != 0 && c != start)
156: {
157: combine = E_ALL;
158: state = eq_return;
159: continue;
160: }
161:
162: if ((c->c_flags & C_X_CMOD) != 0 && c != start)
163: cmod = 1;
164:
165: if (c->c_ord != L_ACTIVE)
166: {
167: if (c->c_ord < L_NONE)
168: internal("trace_equiv", "ran into trouble");
169: else if (c->c_ord == L_NONE)
170: internal("trace_equiv", "ran off fill");
171:
172: combine = equiv_value[c->c_ord];
173: state = eq_return;
174: continue;
175: }
176:
177: if (c->c_what == ct_label)
178: {
179: register cnode *d;
180:
181: for (d = c->c_value.c; d != NULL; d = d->c_link)
182: {
183: if ((d->c_flags & C_SWITCH) != 0)
184: {
185: register cnode *s;
186:
187: s = d->c_switch;
188:
189: if (s->c_ord != ord && s->c_ord != L_NONE)
190: {
191: if ((s->c_flags & C_X_CUT) != 0)
192: combine = E_ALL;
193: else if (s->c_ord == L_ACTIVE)
194: {
195: s->c_ord = ord;
196: combine = trace_equiv(s->c_last);
197: }
198: else
199: {
200: if (s->c_ord < L_NONE)
201: internal("trace_equiv", "ran into switch trouble");
202: combine = equiv_value[s->c_ord];
203: }
204: }
205: }
206: else
207: combine = trace_equiv(d);
208:
209: ret = equiv_combine[ret][combine];
210: }
211: }
212:
213: break;
214:
215: default:
216: internal("trace_equiv", "bad state");
217: }
218:
219:
220: c->c_ord = ord;
221: c = c->c_last;
222: }
223: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.