00001 #define DEBUG
00002
00003 #define TRACE
00004 #undef TRACE
00005
00006
00007
00008
00009
00010 # include "parm.h"
00011 # include <stdio.h>
00012 # include "stree/ststructs.mh"
00013 # include "pass3/is_local.h"
00014 # include "codegen.h"
00015
00016 extern FILE * unparse_file;
00017
00018 extern boolean Vflag;
00019
00020 static int nestlevel;
00021
00022 static NODE * current_blk;
00023
00024
00025
00026 static NODE * current_fc;
00027
00028
00029
00030
00031
00032
00033 struct constr_list {
00034 NODE * cl_constr;
00035 struct constr_list * cl_next;
00036 };
00037 # define cl_nil ((struct constr_list *)0)
00038
00039
00040 struct adj_list {
00041 NODE * adj_source;
00042 struct constr_list * adj_dests;
00043 struct adj_list * adj_next;
00044
00045 };
00046 # define adj_nil ((struct adj_list *)0)
00047
00048
00049 # define HSIZE 317
00050 # define hash(p) (((int)p) % HSIZE)
00051
00052 struct adj_list * sl_deps[HSIZE];
00053
00054
00055 void adj_free(p)
00056 struct adj_list * p;
00057 {
00058 struct constr_list * q, *nq;
00059
00060 for (q = p -> adj_dests; q != cl_nil; q = nq) {
00061 nq = q -> cl_next;
00062 free(q);
00063 }
00064 free(p);
00065 }
00066
00067
00068 struct adj_list * find_adj(i)
00069 NODE * i;
00070 {
00071 int h = hash(i);
00072 struct adj_list *p;
00073
00074 for (p = sl_deps[h]; p != adj_nil && p -> adj_source != i;
00075 p = p -> adj_next);
00076 if (p == adj_nil) {
00077 p = (struct adj_list *)malloc(sizeof (struct adj_list));
00078 p -> adj_source = i;
00079 p -> adj_next = sl_deps[h];
00080 p -> adj_dests = cl_nil;
00081 sl_deps[h] = p;
00082 }
00083 return(p);
00084 }
00085
00086
00087 void sl_dep_add(i, j)
00088 NODE *i, *j;
00089 {
00090 struct adj_list *p = find_adj(i);
00091 struct constr_list * q = (struct constr_list *)
00092 malloc(sizeof (struct constr_list));
00093 q -> cl_next = p -> adj_dests;
00094 q -> cl_constr = j;
00095 p -> adj_dests = q;
00096 }
00097
00098
00099 sl_mark_reachable(i)
00100 NODE * i;
00101 {
00102 struct adj_list * p;
00103 struct constr_list * q;
00104 NODE * cfc;
00105
00106 p = find_adj(i);
00107 for (q = p -> adj_dests; q != cl_nil; q = q -> cl_next) {
00108 cfc = q -> cl_constr;
00109 # ifdef DEBUG
00110 if (cfc -> kind != FUNCCONSTR) {
00111 dbgmsg("Sl_mark_reachable: bad construction\n");
00112 abort(p,q,cfc);
00113 }
00114 # endif
00115 if (!(cfc -> fc_complexity & SL_ACC)) {
00116 # ifdef TRACE
00117 printf("Sl_mark_reachable: setting SL_ACC for %s\n",
00118 cfc -> fc_code_label);
00119 printf("\tpropagated from %s\n",
00120 i -> fc_code_label);
00121 # endif
00122 cfc -> fc_complexity |= SL_ACC;
00123 sl_mark_reachable(cfc);
00124 }
00125 }
00126 }
00127
00128
00129
00130
00131 void sl_solve()
00132 {
00133 int i;
00134 struct adj_list * p, *np;
00135 struct constr_list * q;
00136
00137 for (i = 0; i < HSIZE; i++) {
00138 for (p = sl_deps[i]; p != adj_nil; p = p -> adj_next) {
00139 if (p -> adj_source -> fc_complexity & SL_ACC) {
00140 # ifdef TRACE
00141 printf("Sl_solve: propagating SL_ACC from %s\n",
00142 p -> adj_source -> fc_code_label);
00143 # endif
00144 sl_mark_reachable(p -> adj_source);
00145 }
00146 }
00147 }
00148
00149 for (i = 0; i < HSIZE; i++) {
00150 for (p = sl_deps[i]; p != adj_nil; p = np) {
00151 np = p -> adj_next;
00152 adj_free(p);
00153 }
00154 }
00155 }
00156
00157
00158
00159 void process_global(i)
00160 int i;
00161 {
00162 int j;
00163 NODE * blk = current_blk;
00164
00165 for (j = nestlevel; j > i; j--) {
00166 if (blk -> kind == BLOCKDENOTATION) {
00167 # ifdef DEBUG
00168 if (!(blk -> bld_flags & REQUIRES_AR)) {
00169 dbgmsg("process_global: bad block\n");
00170 }
00171 # endif
00172 # ifdef TRACE
00173 printf("Skipping level %d block, decl lvl = %d\n", j, i);
00174 # endif
00175 } else {
00176 # ifdef TRACE
00177 printf("Setting SL_ACC for %s (levels:%d,%d)\n",
00178 blk -> fc_code_label, i,j);
00179 # endif
00180 blk -> fc_complexity |= SL_ACC;
00181 }
00182 blk = blk -> ar_static_link;
00183 }
00184 }
00185
00186
00187
00188 void cond_process_global(i, fc)
00189 int i;
00190 NODE * fc;
00191 {
00192 int j;
00193 NODE * blk = current_blk;
00194
00195 if (current_fc -> fc_complexity & SL_ACC) {
00196 process_global(i);
00197 return;
00198 }
00199 for (j = nestlevel; j > i; j--) {
00200 if (blk -> kind != BLOCKDENOTATION) {
00201 # ifdef TRACE
00202 printf("Entering dependency for %s on %s (levels:%d,%d)\n",
00203 blk -> fc_code_label, fc -> fc_code_label, i,j);
00204 # endif
00205 sl_dep_add(fc, blk);
00206 }
00207 blk = blk -> ar_static_link;
00208 }
00209 }
00210
00211
00212
00213
00214 sl_analyze(p)
00215 NODE * p;
00216 {
00217 sl_analyze1(p);
00218 sl_solve();
00219 }
00220
00221
00222
00223 cond_sl_analyze1(p, needed)
00224 NODE * p;
00225 boolean needed;
00226 {
00227 extern boolean is_id();
00228
00229 if (needed || !is_id(p)) {
00230 sl_analyze1(p);
00231 }
00232 }
00233
00234 sl_analyze1(p)
00235 register NODE * p;
00236 {
00237 NODE * v;
00238 int i;
00239
00240 if (p == NIL) return;
00241
00242 if (p -> signature -> kind == SIGNATURESIG) {
00243
00244 return;
00245 }
00246
00247 switch ( p -> kind ) {
00248 case LETTERID:
00249 case OPRID:
00250 if (p -> sel_type != NIL) {
00251 sl_analyze1(p -> sel_type);
00252 } else {
00253 int id_lev = p -> id_last_definition -> level;
00254
00255 if (id_lev != 0 && id_lev != nestlevel) {
00256 if(p -> id_last_definition -> kind == DECLARATION
00257 && !(p -> id_last_definition
00258 -> decl_special & ID_IMPORTED)) {
00259
00260
00261 # ifdef TRACE
00262 printf("Discarding bogus global reference: ");
00263 unparse_file = stdout;
00264 unparse(p);
00265 printf("\n");
00266 # endif
00267 } else {
00268 # ifdef TRACE
00269 printf("Processing identifier: ");
00270 unparse_file = stdout;
00271 unparse(p);
00272 printf("\n");
00273 # endif
00274 process_global(id_lev);
00275 }
00276 }
00277 }
00278 break;
00279
00280 case BLOCKDENOTATION :
00281 {
00282 NODE * old_blk = current_blk;
00283
00284 if (p -> bld_flags & REQUIRES_AR) {
00285 nestlevel++;
00286 current_blk = p;
00287 }
00288 maplist (v, p->bld_declaration_list, {
00289 ASSERT (v->kind == DECLARATION,
00290 "sl_analyze1: decl expected");
00291 sl_analyze1(v-> decl_denotation);
00292 });
00293 maplist (v,p->bld_den_seq, {
00294 sl_analyze1(v);
00295 });
00296 if (p -> bld_flags & REQUIRES_AR) {
00297 nestlevel--;
00298 current_blk = old_blk;
00299 }
00300 break;
00301 }
00302
00303 case USELIST:
00304 maplist(s, p -> usl_den_seq, {
00305 sl_analyze1(s);
00306 });
00307 break;
00308
00309 case APPLICATION:
00310 {
00311 NODE * op_sig = p -> ap_operator -> signature;
00312 NODE * constr = op_sig -> fsig_construction;
00313
00314
00315
00316 {
00317 extern boolean is_id();
00318 boolean is_ident = is_id(p -> ap_operator);
00319 boolean no_op_val =
00320 is_ident
00321 && (op_sig -> fsig_inline_code != NIL
00322 || (constr != NIL &&
00323 (constr -> ar_static_level == 1
00324 || constr -> fc_complexity & NO_SL)));
00325 if (!no_op_val) {
00326 # ifdef TRACE
00327 printf("Examining op: ");
00328 unparse_file = stdout;
00329 unparse(p -> ap_operator);
00330 printf("\n");
00331 # endif
00332 if (is_ident
00333 && constr != NIL && op_sig -> fsig_slink_known) {
00334
00335 cond_process_global(constr -> ar_static_level - 1,
00336 constr);
00337 } else {
00338 sl_analyze1(p -> ap_operator);
00339 }
00340 }
00341 # ifdef TRACE
00342 if (no_op_val) {
00343 printf("Op value not needed (level %d): ",
00344 constr == NIL? -1 : constr -> ar_static_level);
00345 unparse_file = stdout;
00346 unparse(p -> ap_operator);
00347 printf("\n");
00348 }
00349 # endif
00350 }
00351 }
00352 maprlist_non_vacuous(p -> ap_args, cond_sl_analyze1);
00353 break;
00354
00355 case LOOPDENOTATION:
00356 case GUARDEDLIST:
00357 maplist(v,p->gl_list, {
00358 sl_analyze1(v);
00359 });
00360 break;
00361
00362 case GUARDEDELEMENT:
00363 sl_analyze1(p -> ge_guard);
00364 sl_analyze1(p -> ge_element);
00365 break;
00366
00367 case FUNCCONSTR:
00368 {
00369 NODE * old_fc = current_fc;
00370 NODE * old_blk = current_blk;
00371
00372 current_fc = p;
00373 current_blk = p;
00374 # ifdef DEBUG
00375 if (old_blk != NIL
00376 && nestlevel != old_blk -> ar_static_level) {
00377 dbgmsg("sl_analyze: nesting level confusion\n");
00378 }
00379 # endif
00380 nestlevel = current_fc -> ar_static_level;
00381 sl_analyze1(p -> fc_body);
00382
00383 current_fc = old_fc;
00384 current_blk = old_blk;
00385 if (current_fc != NIL) {
00386 nestlevel = current_blk -> ar_static_level;
00387 }
00388 }
00389 break;
00390
00391 case MODPRIMARY:
00392 sl_analyze1(p -> mp_primary);
00393 if (p -> mp_type_modifier != NIL
00394 && p -> mp_type_modifier -> kind == WITHLIST) {
00395 maplist (q, p -> mp_type_modifier -> wl_component_list, {
00396 sl_analyze1(q -> decl_denotation);
00397 });
00398 }
00399 break;
00400
00401 case ENUMERATION:
00402 case PRODCONSTRUCTION:
00403 case UNIONCONSTRUCTION:
00404
00405 break;
00406
00407 case QSTR:
00408 case UQSTR:
00409 {
00410 NODE * tsig = p -> sel_type -> signature;
00411
00412 ASSERT(tsig -> kind == TYPESIGNATURE,
00413 "sl_analyze1: bad string type");
00414 if (tsig -> ts_string_code != NIL
00415 && tsig -> ts_element_code != NIL
00416 && strlen(p -> str_string) <= MAXSTRLEN) {
00417 break;
00418
00419 } else {
00420 sl_analyze1(p -> str_expansion);
00421 }
00422 break;
00423 }
00424
00425 case WORDELSE:
00426 break;
00427
00428 case EXTERNDEF:
00429 break;
00430
00431 case REXTERNDEF:
00432 break;
00433
00434 case RECORDCONSTRUCTION:
00435 maplist(s, p -> rec_component_list, {
00436 sl_analyze1(s -> re_denotation);
00437 });
00438 break;
00439
00440 case EXTENSION:
00441 sl_analyze1(p -> ext_denotation);
00442 break;
00443
00444 case RECORDELEMENT:
00445 case DECLARATION:
00446 case PARAMETER:
00447 case FUNCSIGNATURE:
00448 case LISTHEADER:
00449 case VARSIGNATURE:
00450 case VALSIGNATURE:
00451 case TYPESIGNATURE:
00452 case TSCOMPONENT:
00453 case DEFCHARSIGS:
00454 case WITHLIST:
00455 case EXPORTLIST:
00456 case EXPORTELEMENT:
00457 case ALLCONSTANTS:
00458 case HIDELIST:
00459 case WORDCAND:
00460 case WORDCOR:
00461 default:
00462 dbgmsg("sl_analyze1: bad kind, kind = %d\n", p -> kind);
00463 abort();
00464 };
00465 return;
00466 }