C:/Users/Dennis/src/lang/russell.orig/src/pass5c/accessible.c

Go to the documentation of this file.
00001 #define DEBUG
00002 
00003 #define VERBOSE
00004 #undef VERBOSE
00005 
00006 /*
00007  *  Sets the decl_needed, mp_needed, and fc_body_needed fields 
00008  * in subtrees of p which might be executed if control reaches p.
00009  * Adds object files to link list if nested entry points are
00010  * directly referenced.
00011  *  Set the ID_IMPORTED and VAR_NONTR_REF of decl_special fields.
00012  *  Set id_forward_ref and decl_can_be_refd fields.
00013  *  Requires that level fields for DECLARATION and MODPRIMARY nodes,
00014  * as well as ar_static_level fields for function constructions be set
00015  * correctly.
00016  */
00017 
00018 # include "parm.h"
00019 # include <stdio.h>
00020 # include "stree/ststructs.mh"
00021 # include "codeutil.h"
00022 # include "../runtime/runtime.h"
00023 # include "pass3/is_local.h"
00024 # include "pass4/sigs.h"
00025 
00026 # ifdef VERBOSE
00027 #   define IFVERBOSE(x) x
00028 # else
00029 #   define IFVERBOSE(x) 
00030 # endif
00031 
00032 extern FILE * Voutfile;
00033 
00034 extern FILE * unparse_file;
00035 
00036 extern NODE * insrtptr;     /* Pointer to user program */
00037 
00038 extern boolean has_externs;  /* Program contains REXTERN nodes */
00039 
00040 extern boolean Tflag; /* generate trace code */
00041 
00042 extern boolean Gflag; /* generate intermediate code */
00043 
00044 extern boolean Vflag; /* verbose */
00045 
00046 extern boolean Oflag; /* optimize */
00047 
00048 extern unsigned indx_put; /* should be sttrelptr ... */
00049 
00050 static int Clevel = -1;      /* Current nesting level */
00051 
00052 extern void add_objfile();
00053 
00054 extern boolean is_int_const();
00055 
00056 extern char * rindex();
00057 
00058 /* Determine whether the rhs of a declaration needs to be evaluated */
00059 /* due to potential side effects, or due to possible reference      */
00060 /* by a separately compiled program.                                */
00061 boolean eval_decl(p)
00062 NODE *p;
00063 {
00064     int decl_den_kind, decl_sig_kind;
00065     NODE * decl_sig;
00066     extern NODE * declerr;
00067     extern NODE * declsig();
00068 
00069     if (has_externs && !is_descendant(p, insrtptr)) {
00070         /* Outside user program.  May be referenced by -c compilations. */
00071         return(TRUE);
00072     }
00073     decl_sig = p -> decl_signature;
00074     if (decl_sig == NIL) {
00075         decl_sig = declsig(p);
00076         if (declerr != SUCCESS) return(TRUE);
00077     } else if (decl_sig == ERR_SIG) {
00078         return(TRUE);
00079     }
00080     decl_sig_kind = decl_sig -> kind;
00081     decl_den_kind = p -> decl_denotation -> kind;
00082     if (decl_sig_kind == VARSIGNATURE
00083         || decl_sig_kind == VALSIGNATURE
00084         || decl_sig_kind == FUNCSIGNATURE
00085            && decl_den_kind != FUNCCONSTR
00086            && (impure(p -> decl_signature)
00087                || calls_put(p -> decl_denotation))
00088         || decl_sig_kind == TYPESIGNATURE
00089            && calls_put(p -> decl_denotation)) {
00090             return(TRUE);
00091     } else {
00092             return(FALSE);
00093     }
00094 }
00095 
00096 /* Add the object file containing the named entry point */
00097 void add_extracted_objfile(entry_name)
00098 char * entry_name;
00099 {
00100     char * filename = (char *) malloc(strlen(entry_name));
00101     char * p, *q;
00102 
00103     /* Copy starting after first underscore char */
00104         for(p = entry_name; *p != '_'; p++);
00105         p++;
00106         q = filename;
00107         while(*q++ = *p++);
00108     /* Replace tail with ".o" */
00109         p = rindex(filename, '.');
00110         /* Replace embedded periods by slashes */
00111             for (q = filename; q < p; q++) {
00112                 if (*q == '.') {
00113                     *q = '/';
00114                 }
00115             }
00116         *(p+1) = 'o';
00117         *(p+2) = '\0';
00118 
00119     if (filename[0] != '\0') {
00120         add_objfile(filename);
00121     }
00122     free(filename);
00123 }
00124 
00125 /* Mark the body of the function construction p as evaluable at run-time */
00126 body_accessible(p)
00127 register NODE * p;
00128 {
00129     int Olevel = Clevel;
00130 
00131     if (p -> fc_body_needed) return;
00132     Clevel = p -> ar_static_level;
00133     p -> fc_body_needed = TRUE;
00134     accessible(p -> fc_body);
00135     Clevel = Olevel;
00136 }
00137 
00138 /* Mark an identifier and its declaration as accessible.  Set ID_IMPORTED */
00139 /* if appropriate.  VAR_NONTR_REF is not affected.                        */
00140 id_accessible(p)
00141 NODE *p;
00142 {
00143     if (!is_int_const(p)) {
00144         if (p -> sel_type != NIL) {
00145             accessible(p->sel_type);
00146         } else {
00147 #           ifdef DEBUG
00148                 int Olevel = Clevel;
00149 #           endif
00150             NODE * def = p -> id_last_definition;
00151 
00152             /* Clevel will be reset from level fields in DECLARATION */
00153             /* and MODPRIMARY.                                       */
00154             accessible(def);
00155 #           ifdef DEBUG
00156                 if (Clevel != Olevel) {
00157                     dbgmsg("id_accessible: Clevel clobbered\n");
00158                     abort(Clevel,Olevel);
00159                 }
00160 #           endif
00161             if (def -> kind == DECLARATION && def -> level != Clevel) {
00162 #               ifdef VERBOSE
00163                     unparse_file = stdout;
00164                     printf("Non-local reference from level %d to ", Clevel);
00165                     unparse(p);
00166                     printf("\n");
00167 #               endif
00168                 def -> decl_special |= ID_IMPORTED;
00169             }
00170         }
00171     }
00172 }
00173 
00174 /* Mark the expression p as needed at run-time */
00175 accessible(p)
00176 register NODE * p;
00177 {
00178 register NODE * v;
00179 
00180     if (p == NIL) return;
00181     if (p -> kind == PARAMETER) return;
00182     if (p -> kind != DECLARATION
00183         && p -> signature -> kind == SIGNATURESIG) {
00184         /* Evaluation of signatures is trivial.  */
00185         return;
00186     }
00187 
00188     switch ( p -> kind ) {
00189 
00190         case DECLARATION:
00191                 if (p -> decl_needed) break;
00192                 {
00193                     int Olevel = Clevel;
00194                     p -> decl_needed = TRUE;
00195                     Clevel = p -> level;
00196                     accessible(p -> decl_denotation);
00197                     Clevel = Olevel;
00198                 }
00199                 break;
00200 
00201         case BLOCKDENOTATION:
00202                 /* mark forward declarations etc. */
00203                     label_decls(p -> bld_declaration_list);
00204                 maplist(v,p->bld_den_seq,accessible(v));
00205                 /* declarations are likely to not be accessible due */
00206                 /* to inline expansion.                             */
00207                 maplist (v, p -> bld_declaration_list, {
00208                     NODE * sig;
00209 
00210                     if (v -> decl_needed) {
00211                         continue; /* already taken care of */
00212                     }
00213                     sig = v -> decl_denotation -> signature;
00214                     if ((eval_decl(v) && !is_int_const(v -> decl_denotation))
00215                         || Tflag
00216                            && sig -> kind == TYPESIGNATURE
00217                            && hascomp(sig, indx_put)) {
00218                            /* Either side effects are possible, or */
00219                            /* we need put function for tracing.    */
00220                            accessible(v);
00221                     }
00222                 });
00223                 break;
00224 
00225         case APPLICATION:
00226                 v = p -> ap_operator -> signature;
00227                 /* Try to fill in in-line code if not already there */
00228                     if (v -> fsig_inline_code == NIL
00229                         && v -> fsig_construction != NIL) {
00230                         v -> fsig_inline_code = v -> fsig_construction
00231                                                   -> signature
00232                                                   -> fsig_inline_code;
00233                     }
00234                 if (impure(v)
00235                     && !is_id(p -> ap_operator)
00236                     || calls_put(p -> ap_operator)) {
00237 #                   ifdef VERBOSE
00238                         unparse_file = stdout;
00239                         printf("Accessible operator (impure or put): ");
00240                         unparse(p -> ap_operator);
00241                         printf("\n");
00242 #                   endif
00243                     accessible(p -> ap_operator);
00244                 } else if (v -> fsig_inline_code == NIL) {
00245                     if (Oflag && v -> fsig_construction != NIL) {
00246                         map2lists(a, p -> ap_args,
00247                                   f, v -> fsig_construction -> signature -> fsig_param_list, {
00248                             if (f -> par_only_def == NIL
00249                                 || is_real_def(f -> par_only_def)
00250                                    && comp_st(a, f -> par_only_def,
00251                                               NIL, NIL) == 0) {
00252                                 f -> par_only_def = a;
00253                             } else {
00254                                 f -> par_only_def = MULTIPLE_DEFS;
00255                                 /* Could possibly be MULTIPLE_TP_DEFS */
00256                             }
00257                         });
00258                     }
00259                     if (v -> fsig_construction != NIL &&
00260                         (v -> fsig_slink_known ||
00261                          (v -> fsig_construction -> fc_complexity & NO_SL))) {
00262                         if (v -> fsig_construction -> fc_body -> kind
00263                             == EXTERNDEF
00264                             && v -> fsig_construction -> fc_body -> ext_name
00265                                == NIL) {
00266                             /* Dummy for separately compiled function */
00267                             add_extracted_objfile(v -> fsig_construction
00268                                                     -> fc_code_label);
00269                         } else {
00270 #                           ifdef VERBOSE
00271                                 printf("Accessible construction: %s,",
00272                                        v -> fsig_construction
00273                                          -> fc_code_label);
00274                                 if (v -> fsig_slink_known) {
00275                                     printf("Static link known\n");
00276                                 } else {
00277                                     printf("Simple construction\n");
00278                                 }
00279 #                           endif
00280                             /* Construction is in this compilation unit */
00281                             v -> fsig_construction -> fc_complexity
00282                                                    |= DIR_CALL;
00283                                 /* Don't perform "optimizations" that   */
00284                                 /* would make the operator accessible.  */
00285                             body_accessible(v -> fsig_construction);
00286                         }
00287                     } else {
00288 #                       ifdef VERBOSE
00289                             unparse_file = stdout;
00290                             if (v -> fsig_construction == NIL) {
00291                               printf("Accessible operator (unknown constr): ");
00292                             } else {
00293                               printf("Accessible operator (unknown sl): ");
00294                             }
00295                             unparse(p -> ap_operator);
00296                             printf("\n");
00297 #                       endif
00298                         if (v -> fsig_construction != NIL
00299                             && v -> fsig_construction -> fc_body -> kind
00300                                == EXTERNDEF
00301                             && v -> fsig_construction -> fc_body -> ext_name
00302                                == NIL) {
00303                             /* Dummy for separately compiled function     */
00304                             /* Make sure it gets linked, even if we later */
00305                             /* decide not to compile operator.            */
00306                             add_extracted_objfile(v -> fsig_construction
00307                                                     -> fc_code_label);
00308                         }
00309                         accessible(p -> ap_operator);
00310                     }
00311                 }
00312                 /* Arguments are accessible, but V and := and similar */
00313                 /* operations have to be treated specially.           */
00314                 {
00315                     int s = special_tp(v -> fsig_special);
00316 
00317                     switch(s) {
00318                         case RECORD_VALUEOF:
00319                         case PROD_VALUEOF:
00320                         case ENUM_VALUEOF:
00321                             s = STD_VALUEOF;
00322                             break;
00323                         case RECORD_ASSIGN:
00324                         case PROD_ASSIGN:
00325                         case ENUM_ASSIGN:
00326                         case STD_PASSIGN:
00327                         case STD_MASSIGN:
00328                         case STD_TASSIGN:
00329                             s = STD_ASSIGN;
00330                             break;
00331                     }
00332                     if (s == STD_VALUEOF || s == STD_ASSIGN) {
00333                         /* Deal with first argument specially */
00334                         NODE * arg1 = first(p -> ap_args);
00335 
00336                         if (arg1 -> kind == LETTERID
00337                             || arg1 -> kind == OPRID) {
00338                             id_accessible(arg1);
00339                         } else {
00340                             accessible(arg1);
00341                         }
00342                         if (s == STD_ASSIGN) {
00343                             accessible(second(p -> ap_args));
00344                         }
00345                     } else if (Oflag && Gflag
00346                                && v -> fsig_inline_code != NIL) {
00347                         /* Use in-line code to determine whether we */
00348                         /* need addresses correponding to variable  */
00349                         /* arguments.                               */
00350                         int argcount = 1;
00351 
00352                         maplist(s, p -> ap_args, {
00353                             if ((s -> kind == LETTERID
00354                                 || s -> kind == OPRID)
00355                                 && s -> sel_type == NIL
00356                                 && s -> id_last_definition -> kind
00357                                    == DECLARATION) {
00358                                 NODE * sig = sig_structure(s -> signature);
00359 
00360                               if (sig -> kind == VARSIGNATURE
00361                                   && !(s -> id_last_definition -> decl_special
00362                                        & VAR_NONTR_REF)) {
00363                                 if (only_indirect_ref(v -> fsig_inline_code,
00364                                                       argcount)) {
00365                                     id_accessible(s);
00366                                 } else {
00367                                     accessible(s);
00368                                 }
00369                               } else {
00370                                 accessible(s);
00371                               }
00372                             } else {
00373                                 accessible(s);
00374                             } 
00375                             argcount++;
00376                         });
00377                     } else {
00378                         maplist(s,p->ap_args,accessible(s));
00379                     }
00380                 }
00381                 break;
00382 
00383         case LOOPDENOTATION:
00384         case GUARDEDLIST:
00385                 maplist(v,p->gl_list,accessible(v));
00386                 break;
00387 
00388         case GUARDEDELEMENT:
00389                 accessible(p->ge_guard);
00390                 accessible(p->ge_element);
00391                 break;
00392 
00393         case OPRID:
00394         case LETTERID:
00395                 if (p -> signature -> kind == VARSIGNATURE
00396                     /* Can't be selection */
00397                     && p -> id_last_definition -> kind == DECLARATION) {
00398                     /* Got here without going through V or := */
00399                     if (Vflag) {
00400                         printf("Direct reference to variable cell ");
00401                         unparse_file = stdout;
00402                         unparse(p);
00403                         findvl(p -> vlineno);
00404                         printf(" from line %d\n", getrl());
00405                     }
00406                     p -> id_last_definition -> decl_special |= VAR_NONTR_REF;
00407                 }
00408                 id_accessible(p);
00409                 break;
00410 
00411         case FUNCCONSTR:
00412                 (p -> fc_complexity) |= NEED_CL;
00413                 /* Need function value.  Thus we don't know the */
00414                 /* identity of parameters.                      */
00415                   maplist(q, p -> signature -> fsig_param_list, {
00416                     q -> par_only_def = MULTIPLE_DEFS;
00417                   });
00418                 if (p -> fc_body_needed) break;
00419                 p -> fc_body_needed = TRUE;
00420                 Clevel++;
00421                 accessible(p -> fc_body);
00422                 Clevel--;
00423                 break;
00424 
00425         case USELIST:
00426                 maplist(q, p -> usl_den_seq, accessible(q));
00427                 break;
00428 
00429         case MODPRIMARY:
00430                 {
00431                   int Olevel = Clevel;
00432 #                 ifdef VERBOSE
00433                     printf("Accessible type modification:\n");
00434                     unparse_file = stdout;
00435                     unparse(p);
00436                     printf("\n");
00437 #                 endif
00438                   if (p -> mp_needed) break;
00439                   p -> mp_needed = TRUE;
00440                   Clevel = p -> level;
00441                   accessible(p -> mp_primary);
00442                   if (p -> mp_type_modifier != NIL
00443                     && p -> mp_type_modifier -> kind == WITHLIST) {
00444                     /* Mark forward references */
00445                         (void) label_wl(p);
00446                     maplist (q, p -> mp_type_modifier -> wl_component_list, {
00447                         IFVERBOSE(
00448                           printf("Accessible wlc:\n");
00449                           unparse_file = stdout;
00450                           unparse(q -> decl_id);
00451                           printf("\n");
00452                         )
00453                         accessible(q -> decl_denotation);
00454                     });
00455                   }
00456                   Clevel = Olevel;
00457                 }
00458                 break;
00459 
00460         case QSTR:
00461         case UQSTR:
00462                 {
00463                     NODE * sig = p -> sel_type -> signature;
00464                     int maxlen;
00465 
00466                     ASSERT(sig -> kind == TYPESIGNATURE,
00467                            "accessible: bad string type\n");
00468                     if (sig -> ts_string_max == -1) {
00469                         maxlen = MAXSTRLEN;
00470                     } else {
00471                         maxlen = sig -> ts_string_max;
00472                     }
00473                     if (sig -> ts_string_code != NIL 
00474                         && sig -> ts_element_code != NIL
00475                         && strlen(p -> str_string) <= maxlen
00476                         && ! calls_put(p -> sel_type)) {
00477                         /* Nothing else needed */
00478                     } else {
00479                         accessible(p -> str_expansion);
00480                     }
00481                 }
00482                 break;
00483 
00484         case ENUMERATION:
00485         case PRODCONSTRUCTION:
00486         case UNIONCONSTRUCTION:
00487                 /* Subexpressions are not evaluated */
00488                 break;
00489 
00490         case WORDELSE:
00491         case EXTERNDEF:
00492         case REXTERNDEF:
00493                 break;
00494 
00495         case RECORDCONSTRUCTION:
00496                 maplist(s, p -> rec_component_list, {
00497                   accessible(s -> re_denotation);
00498                 });
00499                 break;
00500 
00501         case EXTENSION:
00502                 accessible(p -> ext_denotation);
00503                 break;
00504 
00505         case PARAMETER:
00506         case RECORDELEMENT:
00507         case FUNCSIGNATURE:
00508         case LISTHEADER: /* should never get here */
00509         case VARSIGNATURE:
00510         case VALSIGNATURE:
00511         case TYPESIGNATURE:
00512         case TSCOMPONENT:
00513         case DEFCHARSIGS:
00514         case WITHLIST:
00515         case EXPORTLIST:
00516         case EXPORTELEMENT:
00517         case ALLCONSTANTS:
00518         case HIDELIST:
00519         case WORDCAND:
00520         case WORDCOR:
00521         default:
00522                 dbgmsg("accessible: bad kind, kind = %d\n", p -> kind);
00523                 abort();
00524 
00525     };
00526     return;
00527 }
00528 
00529 extern void Vexpression();
00530 extern void fc_add();
00531 extern int Vlevel;  /* Current nesting level */
00532 
00533 /*
00534  *  Traverse the subtree headed by p and generate code for subexpressions
00535  * which might need to be evaluated.
00536  */
00537 Vtraverse(p)
00538 register NODE * p;
00539 {
00540 register NODE * v;
00541 
00542     if (p == NIL) return;
00543 
00544     switch ( p -> kind ) {
00545 
00546         case BLOCKDENOTATION :
00547                 {
00548                     if ( p -> bld_flags & REQUIRES_AR ) {
00549                         Vlevel++;
00550                     }
00551                     maplist (v, (LIST)decl_sort(p->bld_declaration_list), {
00552                         ASSERT (v->kind == DECLARATION,
00553                                 "Vtraverse: decl expected");
00554                         if (v -> decl_needed) {
00555                             Vexpression (v-> decl_denotation);
00556                             POP_DISP ("ap",v->displacement,
00557                                       "# store declared value");
00558                         } else {
00559                           /* Generate code for nested function       */
00560                           /* constructions or modified primary nodes */
00561                           /* that may be evaluated.                  */
00562                             Vtraverse (v -> decl_denotation);
00563                         }
00564                     }
00565                     );
00566                     maplist (v,p->bld_den_seq, {
00567                         Vtraverse(v);
00568                     });
00569                     if ( p -> bld_flags & REQUIRES_AR ) {
00570                         Vlevel--;
00571                     }
00572                     break;
00573                 }
00574                 
00575         case APPLICATION:
00576                 Vtraverse(p -> ap_operator);
00577                 maplist(v,p->ap_args,Vtraverse(v));
00578                 break;
00579 
00580         case LOOPDENOTATION:
00581         case GUARDEDLIST:
00582                 maplist(v,p->gl_list,Vtraverse(v));
00583                 break;
00584 
00585         case GUARDEDELEMENT:
00586                 Vtraverse(p->ge_guard);
00587                 Vtraverse(p->ge_element);
00588                 break;
00589 
00590         case OPRID:
00591         case LETTERID:
00592                 if (p -> sel_type != NIL) {
00593                     Vtraverse(p->sel_type);
00594                 }
00595                 break;
00596 
00597         case FUNCCONSTR:
00598                 if (p -> fc_body_needed) {
00599                   if (p -> fc_complexity & NO_SL) {
00600                     fc_add(p, Vlevel+1, TRUE /* only fast version */);
00601                   } else {
00602                     fc_add(p, Vlevel+1, FALSE);
00603                   }
00604                 } else {
00605                   Vlevel++;  /* presumably not necessary, but ... */
00606                   Vtraverse(p -> fc_body);
00607                   Vlevel--;
00608                 }
00609                 break;
00610 
00611         case USELIST:
00612                 maplist(q, p -> usl_den_seq, Vtraverse(q));
00613                 break;
00614 
00615         case MODPRIMARY:
00616                 if (p -> mp_needed) {
00617                     Vexpression(p);
00618                     POP("r0", "# type modification value not used");
00619                 } else {
00620                     Vtraverse(p -> mp_primary);
00621                     if (p -> mp_type_modifier != NIL
00622                         && p -> mp_type_modifier -> kind == WITHLIST) {
00623                       maplist (q, p -> mp_type_modifier -> wl_component_list, {
00624                         Vtraverse(q -> decl_denotation);
00625                       });
00626                     }
00627                 }
00628                 break;
00629 
00630         case ENUMERATION:
00631         case PRODCONSTRUCTION:
00632         case UNIONCONSTRUCTION:
00633                 /* Subexpressions are not evaluated */
00634                 break;
00635 
00636         case QSTR:
00637         case UQSTR:
00638                 Vtraverse(p -> sel_type);
00639                 /* There can't be anything of interest in the expansion */
00640                 break;
00641 
00642         case WORDELSE:
00643         case EXTERNDEF:
00644         case REXTERNDEF:
00645                 break;
00646 
00647         case RECORDCONSTRUCTION:
00648                 maplist(s, p -> rec_component_list, {
00649                   Vtraverse(s -> re_denotation);
00650                 });
00651                 break;
00652 
00653         case EXTENSION:
00654                 Vtraverse(p -> ext_denotation);
00655                 break;
00656 
00657         case VALSIGNATURE:
00658         case VARSIGNATURE:
00659         case FUNCSIGNATURE:
00660         case TYPESIGNATURE:
00661         case SIGNATURESIG:
00662                 break;
00663 
00664         case RECORDELEMENT:
00665         case DECLARATION:
00666         case PARAMETER:
00667         case LISTHEADER: /* should never get here */
00668         case TSCOMPONENT:
00669         case DEFCHARSIGS:
00670         case WITHLIST:
00671         case EXPORTLIST:
00672         case EXPORTELEMENT:
00673         case ALLCONSTANTS:
00674         case HIDELIST:
00675         case WORDCAND:
00676         case WORDCOR:
00677         default:
00678                 dbgmsg("Vtraverse: bad kind, kind = %d\n", p -> kind);
00679                 abort();
00680 
00681     };
00682     return;
00683 }

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