C:/Users/Dennis/src/lang/russell.orig/src/pass5d/sl_analyze.c

Go to the documentation of this file.
00001 #define DEBUG
00002 
00003 #define TRACE
00004 #undef TRACE
00005 /*
00006  *  Set the SL_ACC bits in FUNCCONSTR nodes.  (See stree/streedefs.h
00007  * for definition.)
00008  *  This affects cl_analyze1, and is thus done first.
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;     /* Current nesting level */
00021 
00022 static NODE * current_blk; /* Innermost construction or block           */
00023                            /* currently being analyzed.                 */
00024                            /* blocks count only if they require an      */
00025                            /* activation record.                        */
00026 static NODE * current_fc;  /* Innermost function.  Blocks don't count.  */
00027 
00028 /* Data structure declarations for hash table representing sl access  */
00029 /* dependency graph.  An edge i -> j is in the graph if it is known   */
00030 /* that a static link access by i forces a static link access by j    */
00031 
00032 /* List of function constructions.  Used in adjacency lists. */
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 /* Adjacency list for a single source vertex: */
00040 struct adj_list {
00041     NODE * adj_source;
00042     struct constr_list * adj_dests;
00043     struct adj_list * adj_next;     /* Next adjacency list in hash table */
00044                                     /* chain.                            */
00045 };
00046 # define adj_nil ((struct adj_list *)0)
00047 
00048 /* Hash table of adjacency lists */
00049 # define HSIZE 317
00050 # define hash(p) (((int)p) % HSIZE)
00051 
00052 struct adj_list * sl_deps[HSIZE];
00053 
00054 /* Deallocate all memory associated with the adjacency list p */
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 /* Find i's adjacency list.  Create one if it's not there. */
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 /* Add an edge i -> j to the graph */
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 /* Set SL_ACC bits for all nodes reachable from i */
00099 sl_mark_reachable(i)
00100 NODE * i;
00101 {
00102     struct adj_list * p;
00103     struct constr_list * q;
00104     NODE * cfc;             /* current function construction */
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 /* Set SL_ACC bits for all constructions in the graph that are */
00129 /* reachable from a construction with the SL_ACC bit set.      */
00130 /* Subsequently delete the graph.                              */
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     /* Now deallocate the whole thing */
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 /* Set SL_ACC bits in accordance with the fact that we have just seen */
00158 /* a level i identifier.                                              */
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 /* Analogous to process_global, but SL_ACC bit should be set only if */
00187 /* the SL_ACC bit in fc either is set, or eventually gets set.       */
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  *  Set fields in the tree headed by p.
00213  */
00214 sl_analyze(p)
00215 NODE * p;
00216 {
00217     sl_analyze1(p);
00218     sl_solve();
00219 }
00220  
00221 /* Call sl_analyze1 on p if non_vac is true or p is not an identifier */
00222 /* Used in conjunction with maprlist_non_vacuous.                     */
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         /* signature evaluation doesn't reference anything. */
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                            /* The accessibility check decided that this access was impossible; */
00260                            /* We'll believe it.                                                */
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                   /* Check if this call could require operator value */
00315                   /* sl_analyze1 the operator if necessary.           */
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                               /* May need to be able to get to its env */
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                 /* Subexpressions are not evaluated */
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                             /* May be dubious on VAX ? */
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: /* should never get here */
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 }

Generated on Fri Jan 25 10:39:47 2008 for russell by  doxygen 1.5.4