|
|
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.