C:/Users/Dennis/src/lang/russell.orig/src/pass4/fixhints.c

Go to the documentation of this file.
00001 # define DEBUG
00002 # define TRACE
00003 # undef TRACE
00004 
00005 # ifdef TRACE
00006 #   define IFTRACE(x) x
00007 # else
00008 #   define IFTRACE(x) 
00009 # endif
00010 # include <stdio.h>
00011 # include "parm.h"
00012 
00013 # include "stree/ststructs.mh"
00014 
00015 # include "pass1/stt/sttdefs.h"
00016 
00017 # include "sigs.h"
00018 
00019 # include "../pass3/is_local.h"
00020 
00021 extern unsigned stplinks[];
00022 
00023 extern FILE * unparse_file;
00024 
00025 /*
00026  * fixhints(sig, sig2)
00027  *
00028  *   Returns a structure which is a copy of the first signature except
00029  * that code generation information is adjusted to be consistent with that
00030  * given by the second signature.
00031  *   Code generation info is not meaningful if the two signatures don't match.
00032  *   Inline code is preserved only if it is (pointer-) identical in the
00033  * two signatures.
00034  *   A NIL value for sig2 is treated as an unknown signature.
00035  */
00036 
00037 NODE * fixhints(sig,sig2)
00038 NODE * sig,*sig2;
00039 {
00040     boolean mod_flag = FALSE; /* One of the descendants was modified */
00041     boolean in_line_differs, special_differs, constr_differs;
00042     boolean slink_known_differs;
00043     NODE * tmpcopy[MAXFIELDS];/* temporary version of result         */
00044     NODE ** s;
00045     NODE * p, *r;
00046     NODE * ncopy;             /* copy to be returned                 */
00047     register int i;
00048     register struct cn * c;
00049     int j;
00050 
00051     if (sig == ERR_SIG || sig == NIL || sig2 == ERR_SIG ) {
00052         return(sig);
00053     }
00054 
00055     switch ( sig -> kind ) {
00056         case VALSIGNATURE:
00057         case VARSIGNATURE:
00058             return(sig);
00059 
00060         case TSCOMPONENT:
00061             if (sig2 -> kind != TSCOMPONENT) return(sig);
00062             p = fixhints(sig -> tsc_signature, sig2 -> tsc_signature);
00063             if (p != sig -> tsc_signature) {
00064                 ncopy = copynode(sig);
00065                 chgfld(&(ncopy -> tsc_signature), p);
00066                 return(ncopy);
00067             } else {
00068                 return(sig);
00069             }
00070 
00071         case DEFCHARSIGS:
00072             /* Delete the exception information.  */
00073             /* This so unlikely to arise ...      */
00074             if (sig -> dcs_exceptions != NIL) {
00075                 p = copynode(sig);
00076                 chgfld(&(p -> dcs_exceptions), NIL);
00077             }
00078             return(p);
00079 
00080         case TYPESIGNATURE:
00081 #           ifdef TRACE
00082               printf("fixhints: \n");
00083               unparse_file = stdout;
00084               unparse(sig);
00085               printf("\n");
00086               unparse(sig2);
00087               printf("refcounts: %d, %d\n", sig -> refcount, sig2 -> refcount);
00088 #           endif
00089             if (sig2 == NIL) {
00090                 ncopy = copynode(sig);
00091                                     /* should be locked ... */
00092                 ncopy -> ts_simple_type = FALSE;
00093                 ncopy -> ts_const_code = NIL;
00094                 ncopy -> ts_string_code = NIL;
00095                 ncopy -> ts_element_code = NIL;
00096                 return(ncopy);
00097             }
00098             if (sig2 -> kind != TYPESIGNATURE) return(sig);
00099             p = sig -> ts_clist;
00100             r = sig2 -> ts_clist;
00101             i = 0;
00102             j = length(p);
00103             /* get sufficiently large chunk of memory to temporarily copy */
00104             /* the list, thus minimizing number of allocations.                 */
00105                 if (j <= MAXFIELDS) {
00106                     s = tmpcopy;
00107                 } else {
00108                     s = (NODE **) malloc(j * sizeof(NODE *));
00109                 }
00110             map2lists(q, p, t, r, {
00111                 IFTRACE(
00112                     printf("fixhints: tsc:\n");
00113                     unparse_file = stdout;
00114                     unparse(q);
00115                     printf("\n");
00116                     unparse(t);
00117                     printf("refcounts: %d, %d\n", q -> refcount, t -> refcount);
00118                 )
00119                 s[i] = fixhints(q, t);
00120                 IFTRACE(
00121                     printf("Returned refcount: %d\n", s[i] -> refcount);
00122                 )
00123                         /* should be locked but ... */
00124                 if(s[i] != q) {
00125                     IFTRACE(
00126                         printf("Modified\n");
00127                     )
00128                     mod_flag = TRUE;
00129                 }
00130                 i++;
00131             });
00132             if (mod_flag) {
00133               /* convert the temporary copy in s to a real list structure, */
00134               /* put it into a new type signature node, and return it      */
00135                 NODE * result;
00136                 result = emptylist();
00137                 for (i = 0; i < j; i++) {
00138                     addright(result,s[i]);
00139 #                   ifdef TRACE
00140                         printf("Added %X(%d)\n", s[i], s[i] -> refcount);
00141                         if (s[i] -> kind == TSCOMPONENT) {
00142                             unparse_file = stdout;
00143                             unparse(s[i] -> tsc_id);
00144                             printf(":");
00145                             unparse(s[i] -> tsc_signature);
00146                             printf("\n");
00147                         } else {
00148                             printf("constants");
00149                         }
00150 #                   endif
00151                 }
00152                 if (j > MAXFIELDS) free(s);
00153                 ncopy = copynode(sig);
00154                                  /* again, should be locked ... */
00155                 chgfld(&(ncopy -> ts_clist), result);
00156             } else {
00157                 if (j > MAXFIELDS) free(s);
00158                 if (sig -> ts_simple_type && !(sig2 -> ts_simple_type)
00159                     || sig -> ts_const_code != sig2 -> ts_const_code
00160                     || sig -> ts_string_code != sig2 -> ts_string_code
00161                     || sig -> ts_element_code != sig -> ts_element_code) {
00162                     ncopy = copynode(sig);  /* again .. */
00163                 } else {
00164                     return(sig);
00165                 }
00166             }
00167 #           define make_consistent(field,val) \
00168               if (sig -> field != sig2 -> field) {ncopy -> field = val;}
00169             make_consistent(ts_simple_type, FALSE);
00170             make_consistent(ts_const_code, NIL);
00171             make_consistent(ts_string_code, NIL);
00172             make_consistent(ts_element_code, NIL);
00173             return(ncopy);
00174 
00175         case FUNCSIGNATURE:
00176             if (sig2 == NIL) {
00177                 ncopy = copynode(sig);  /* should be locked ... */
00178                 ncopy -> fsig_inline_code = NIL;
00179                 return(ncopy);
00180             }
00181             if (sig2 -> kind != FUNCSIGNATURE) return(sig);
00182             p = fixhints(sig -> fsig_result_sig, sig2 -> fsig_result_sig);
00183             in_line_differs =
00184                 (sig -> fsig_inline_code != sig2 -> fsig_inline_code);
00185             special_differs =
00186                 (sig -> fsig_special != sig2 -> fsig_special);
00187             constr_differs = 
00188                 (sig -> fsig_construction != sig2 -> fsig_construction);
00189             slink_known_differs =
00190                 (sig -> fsig_slink_known != sig2 -> fsig_slink_known);
00191             if (p != sig -> fsig_result_sig || in_line_differs
00192                 || special_differs || constr_differs || slink_known_differs) {
00193                 ncopy = copynode(sig);
00194             } else {
00195                 ncopy = sig;
00196             }
00197             if (p != sig -> fsig_result_sig) {
00198                 chgfld(&ncopy -> fsig_result_sig, p);
00199             }
00200             if (in_line_differs) {
00201                 ncopy -> fsig_inline_code = NIL;
00202             }
00203             if (special_differs) {
00204                 ncopy -> fsig_special = NOT_SPECIAL;
00205             }
00206             if (constr_differs) {
00207                 ncopy -> fsig_construction = NIL;
00208             }
00209             if (slink_known_differs) {
00210                 ncopy -> fsig_slink_known = FALSE;
00211             }
00212             return(ncopy);
00213 
00214 #       ifdef DEBUG
00215           default:
00216             dbgmsg("fixhints: bad signature");
00217             abort(sig,sig2);
00218 #       endif
00219 
00220     }
00221 }
00222 
00223 /*
00224  * Return the integer constant represented by the expression e,
00225  * if it can be easily determined.  Return UNKNOWN otherwise.
00226  * Should be perhaps be replaced by is_int_const.
00227  */
00228 # define UNKNOWN -1
00229 
00230 long int_value(e)
00231 NODE * e;
00232 {
00233     extern NODE * id_Integer;
00234 
00235     switch (e -> kind) {
00236         case LETTERID:
00237             if (e -> id_def_found && e -> sel_type == NIL &&
00238                 e -> id_last_definition -> kind == DECLARATION &&
00239                 e -> id_last_definition -> post_num < e -> post_num) {
00240                     /* Dont follow recursive declarations ... */
00241                 return(int_value(e -> id_last_definition -> decl_denotation));
00242             } else {
00243                 return(UNKNOWN);
00244             }
00245 
00246         case UQSTR:
00247             {
00248                 NODE * sel_tp = e -> sel_type;
00249             
00250                 if (sel_tp -> kind != LETTERID
00251                     || (!sel_tp -> id_def_found)
00252                     || (!is_declared_by(sel_tp,
00253                                         id_Integer -> id_last_definition))) {
00254                     return(UNKNOWN);
00255                 } else {
00256                     /* Integer constant */
00257                     return(atoi(e -> str_string));
00258                 }
00259             }
00260 
00261         case APPLICATION:
00262             if (e -> ap_operator -> kind != OPRID
00263                 || e -> ap_operator -> sel_type == NIL) {
00264                 return(UNKNOWN);
00265             } else {
00266                 NODE * sel_tp = e -> ap_operator -> sel_type;
00267                 extern long /* sttrelptr */ indx_plus;
00268                 
00269                 if (sel_tp -> kind != LETTERID
00270                     || (!sel_tp -> id_def_found)
00271                     || (!is_declared_by(sel_tp,
00272                                         id_Integer -> id_last_definition))) {
00273                     return(UNKNOWN);
00274                 }
00275                 if (e -> ap_operator -> id_str_table_index == indx_plus) {
00276                     long arg1 = int_value(first(e -> ap_args));
00277                     long arg2 = int_value(last(e -> ap_args));
00278                     if (arg1 != UNKNOWN && arg2 != UNKNOWN) {
00279                         return(arg1 + arg2);
00280                     } else {
00281                         return(UNKNOWN);
00282                     }
00283                 } else {
00284                     /* Should check for other operators here */
00285                     return(UNKNOWN);
00286                 }
00287             }
00288 
00289         default:
00290             return(UNKNOWN);
00291     }
00292 }
00293 
00294 /*
00295  * Set various special fields in the type signature sig to reflect
00296  * the fact that it represents a type returned by the built-in
00297  * Array operation.  The arguments to the Array application are
00298  * size and etype.
00299  * This assumes argument signatures are known.
00300  */
00301 void fix_array_sig(sig, size, etype)
00302 NODE * sig;
00303 NODE * size;
00304 NODE * etype;
00305 {
00306     long size_val = int_value(size);
00307     NODE * e_sig = sig_structure(etype -> signature);
00308     NODE * e_V_sig;
00309     NODE * e_New_sig;
00310     sttrelptr comp_id;
00311     extern sttrelptr indx_subscr;
00312     extern sttrelptr indx_New;
00313     extern sttrelptr indx_ValueOf;
00314     extern sttrelptr indx_size;
00315     boolean std_e_V;        /* Element type has standard V function */
00316     boolean std_e_New;      /* Element type has standard New        */
00317     boolean ptr_e_New;      /* Element type has pointer New         */
00318     extern NODE * id_New;
00319     extern NODE * id_ValueOf;
00320     extern FILE * unparse_file;
00321     int tp;
00322 
00323 #   ifdef VERBOSE
00324         printf("entering fix_array_sig(%X, ...)\nelement sig:\n", sig);
00325         unparse_file = stdout;
00326         unparse(e_sig);
00327         printf("\n");
00328 #   endif
00329     if (sig == ERR_SIG || e_sig == ERR_SIG
00330         || e_sig -> kind != TYPESIGNATURE) return;
00331     if (size_val == UNKNOWN || size_val > MAX_SP_VAL) {
00332         size_val = 0;
00333     }
00334     e_V_sig = getcomp(e_sig, id_ValueOf, NIL,
00335                       NIL, NIL, NIL, FALSE);
00336     if (e_V_sig == ERR_SIG) return;
00337     e_New_sig = getcomp(e_sig, id_New, NIL,
00338                         NIL, NIL, NIL, FALSE);
00339     if (e_New_sig == ERR_SIG) return;
00340     if (e_V_sig == NIL || e_New_sig == NIL) {
00341         return;
00342         /* Error may not yet have been caught, but it will be */
00343     }
00344     std_e_V = (special_tp(e_V_sig -> fsig_special) == STD_VALUEOF
00345                && special_val(e_V_sig -> fsig_special) == 1);
00346     tp = special_tp(e_New_sig -> fsig_special);
00347     std_e_New = (tp == STD_NEW
00348                  && special_val(e_New_sig -> fsig_special) == 1);
00349     ptr_e_New = (tp == UNION_NEW || tp == PROD_NEW ||
00350                  (tp == PTR_NEW
00351                   && special_val(e_New_sig -> fsig_special) == 1));
00352 #   ifdef VERBOSE
00353         printf("V special = 0x%X, New special = 0x%X\n",
00354                e_V_sig -> fsig_special, e_New_sig -> fsig_special);
00355         printf("std_e_V = %d, std_e_New = %d, ptr_e_New = %d\n",
00356                 std_e_V, std_e_New, ptr_e_New);
00357 #   endif
00358     maplist(s, sig -> ts_clist, {
00359         if (s -> kind == TSCOMPONENT) {
00360             comp_id = s -> tsc_id -> id_str_table_index;
00361             if (comp_id == indx_New) {
00362                 if (std_e_New) {
00363                     s -> tsc_signature -> fsig_special =
00364                         special(ARRAY_STD_NEW, size_val);
00365                 } else if (ptr_e_New) {
00366                     s -> tsc_signature -> fsig_special =
00367                         special(ARRAY_PTR_NEW, size_val);
00368                 }
00369             } else if (comp_id == indx_ValueOf) {
00370                 if (std_e_V) {
00371                     s -> tsc_signature -> fsig_special =
00372                         special(ARRAY_VALUEOF, size_val);
00373                 }
00374             } else if (comp_id == indx_size) {
00375                 s -> tsc_signature -> fsig_special =
00376                     special(ARRAY_SIZE, size_val); 
00377             } else if (comp_id == indx_subscr) {
00378                 if (s -> tsc_signature -> fsig_result_sig -> kind
00379                     == VARSIGNATURE) {
00380                     s -> tsc_signature -> fsig_special =
00381                         special(ARRAY_VAR_SUB, size_val);
00382                 } else {
00383                     s -> tsc_signature -> fsig_special =
00384                         special(ARRAY_VAL_SUB, size_val);
00385                 }
00386             }
00387         }
00388     });
00389 }
00390 
00391 /* Clear all slink_known fields in the function signature or */
00392 /* recursively in the components of the type signature.      */
00393 void clear_slink_known(sig)
00394 NODE * sig;
00395 {
00396     NODE * p;
00397     NODE * q;
00398 
00399     if (sig == ERR_SIG || sig == NIL) {
00400         return;
00401     }
00402 
00403     switch ( sig -> kind ) {
00404         case LETTERID:
00405         case OPRID:
00406             if (p -> id_last_definition == NIL) {
00407                 dbgmsg("clear_slink_known: unresolved id reference\n");
00408             }
00409             /* We claim that signatures bound to identifiers cant contain  */
00410             /* any interesting optimization info.  Thus there's none to be */
00411             /* cleared.                                                    */
00412             break;
00413 
00414         case VARSIGNATURE:
00415         case VALSIGNATURE:
00416         case SIGNATURESIG:
00417             break;
00418 
00419         case TYPESIGNATURE:
00420             p = sig -> ts_clist;
00421             maplist(q, p, {
00422                 if (q -> kind == TSCOMPONENT) {
00423                     clear_slink_known(q -> tsc_signature);
00424                 }
00425             });
00426             break;
00427 
00428         case FUNCSIGNATURE:
00429             sig -> fsig_slink_known = FALSE;
00430             break;
00431 
00432 #       ifdef DEBUG
00433           default:
00434             dbgmsg("clear_slink_known: bad signature");
00435             abort(sig);
00436 #       endif
00437 
00438     }
00439 }
00440 
00441 /* Return a copy of sig with all fsig_construction fields in the  */
00442 /* signature cleared.                                             */
00443 NODE * clear_construction(sig)
00444 NODE * sig;
00445 {
00446     NODE * p;
00447     NODE * q;
00448 
00449     if (sig == ERR_SIG || sig == NIL) {
00450         return(sig);
00451     }
00452 
00453     switch ( sig -> kind ) {
00454         case LETTERID:
00455         case OPRID:
00456 #           ifdef DEBUG
00457               if (p -> id_last_definition == NIL) {
00458                   dbgmsg("clear_construction: unresolved id reference\n");
00459               }
00460 #           endif
00461             /* We claim that signatures bound to identifiers cant contain  */
00462             /* any interesting optimization info.  Thus there's none to be */
00463             /* cleared.                                                    */
00464             return(sig);
00465 
00466         case VARSIGNATURE:
00467         case VALSIGNATURE:
00468         case SIGNATURESIG:
00469             return(sig);
00470 
00471         case TYPESIGNATURE:
00472             {
00473               boolean modified = FALSE;
00474               NODE * new_comp_list = emptylist();
00475               NODE * new_comp;
00476 
00477               maplist(s, sig -> ts_clist, {
00478                 if (s -> kind == TSCOMPONENT) {
00479                     p = clear_construction(s -> tsc_signature);
00480                     if (p != s -> tsc_signature) {
00481                         modified = TRUE;
00482                         new_comp = copynode(s);
00483                         chgfld(&(new_comp -> tsc_signature), p);
00484                         addright(new_comp_list, new_comp);
00485                     } else {
00486                         addright(new_comp_list, s);
00487                     }
00488                 } else if (s -> kind == DEFCHARSIGS) {
00489                     if (s -> dcs_exceptions != NIL) {
00490                         /* We punt */
00491                         modified = TRUE;
00492                         new_comp = copynode(s);
00493                         chgfld(&(new_comp -> dcs_exceptions), NIL);
00494                         addright(new_comp_list, new_comp);
00495                     } else {
00496                         addright(new_comp_list, s);
00497                     }
00498                 } else {
00499                     dbgmsg("clear_construction: bad typesignature\n");
00500                 }
00501               });
00502               if (modified) {
00503                 p = copynode(sig);
00504                 chgfld(&(p -> ts_clist), new_comp_list);
00505                 return(p);
00506               } else {
00507                 vfree(new_comp_list);
00508                 return(sig);
00509               }
00510             }
00511 
00512         case FUNCSIGNATURE:
00513             p = clear_construction(sig -> fsig_result_sig);
00514             if (p != sig -> fsig_result_sig
00515                 || sig -> fsig_construction != NIL) {
00516                 q = copynode(sig);
00517                 chgfld (&(q -> fsig_result_sig),p);
00518                 q -> fsig_construction = NIL;
00519                 return(q);
00520             } else {
00521                 return(sig);
00522             }
00523 
00524 #       ifdef DEBUG
00525           default:
00526             dbgmsg("clear_construction: bad signature");
00527             abort(sig);
00528 #       endif
00529 
00530     }
00531 }
00532 

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