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

Go to the documentation of this file.
00001 # define DEBUG
00002 # define OBSOLETE
00003 # undef OBSOLETE
00004 /* Here we assume that reference counts are not being maintained */
00005 
00006 /* 
00007  *   Compile code to fetch the value associated with an identifier.
00008  *  This is nontrivial due to the variety of closure styles,
00009  *  activation record styles, and the possibility of erroneous
00010  *  forward references in declaration blocks.
00011  *
00012  */
00013 # include "parm.h"
00014 # include <stdio.h>
00015 # include "stree/ststructs.mh"
00016 # include "codegen.h"
00017 # include "op_codes.h"
00018 # include "pass4/sigs.h"
00019 # include "pass3/is_local.h"
00020 
00021 FILE * Goutfile;
00022 
00023 extern int yydebug;
00024 extern int yynerrs;
00025 
00026 extern boolean Vflag;  /* Optimization info */
00027 
00028 extern boolean Oflag;  /* Enable optimization */
00029 
00030 extern boolean Fflag;  /* parameters copied on entry */
00031 
00032 extern boolean sl_available;  /* Static link available in      */
00033                               /* current function construction */
00034 
00035 extern int avail_loc;     /* next available location number */
00036 
00037 extern char str_code_buf[];       /* used for strings, "special" fns */
00038                                   /* and by find_inline              */
00039                                   /* and for object file names       */
00040                                   /* and to assemble labels          */
00041 
00042 extern NODE * Gcurrent;      /* Current function construction */
00043 
00044 extern int Glevel;           /* Static nesting level of current function */
00045 
00046 extern boolean copied_globals;
00047 
00048 extern int n_globals;
00049 
00050 extern boolean is_int_const();
00051 
00052 char * Gnewlabel();
00053 
00054 extern FILE * unparse_file;
00055 
00056 /* Return either NIL or an expression q such that p is */
00057 /* equivalent to q. P is different from q only if p is */
00058 /* a (possibly selected) identifier.  The goal is to   */
00059 /* make q as informative as possible.                  */
00060 /* P and q are interchangeable only in that if q is a  */
00061 /* constant, then p is the same constant.  If q is a   */
00062 /* function, then its optimization information (except */
00063 /* for static link availability) also applies to p.    */
00064 /* This can't be done earlier, since we take constant  */
00065 /* parameters into consideration.                      */
00066 
00067 /* q may have type components that have been forgotten */
00068 /* in p.                                               */
00069 NODE * equiv_expr(p)
00070 NODE * p;
00071 {
00072     NODE * d;
00073     NODE * q;
00074     while (p -> kind == LETTERID || p -> kind == OPRID) {
00075       if (p -> sel_type == NIL ) {
00076         d = p -> id_last_definition;
00077         switch(d -> kind) {
00078             case DECLARATION:
00079                 q = d -> decl_denotation;
00080                 break;
00081             case PARAMETER:
00082                 if (is_real_def(d -> par_only_def)) {
00083                     q = d -> par_only_def;
00084                 } else {
00085                     return(p);
00086                 }
00087                 break;
00088             default:
00089                 return(p);
00090         }
00091         if (q -> kind != OPRID && q -> kind != LETTERID
00092             || q -> sel_type != NIL
00093             || q -> id_last_definition -> pre_num < d -> pre_num) {
00094             /* Replacing p by q will not lead to a cycle */
00095             p = q;
00096         } else {
00097             return(q);
00098         }
00099       } else /* p -> sel_type != NIL */ {
00100         NODE * nt = equiv_expr(p -> sel_type);
00101         NODE * new_id;
00102     
00103         if (p -> signature -> kind == FUNCSIGNATURE
00104             && (p -> signature -> fsig_construction != NIL
00105                 || p -> signature -> fsig_inline_code != NIL)) {
00106             /* P already has good information; no reason to continue */
00107             return(p);
00108         }
00109         nt = equiv_expr(p -> sel_type);
00110         if (nt == p -> sel_type) {
00111             return(p);
00112         } else {
00113             if (!is_unique(nt -> signature, p -> id_str_table_index)) {
00114                 /* Too hard to find the correct component   */
00115                 /* since signatures may have changed due to */
00116                 /* substitution.                            */
00117                 return(p);
00118             }
00119             new_id = copynode(p);
00120             new_id -> sel_type = nt;
00121             new_id -> signature = getcomp(nt -> signature, new_id,
00122                                           p -> sel_type, NIL, NIL, NIL, TRUE);
00123             new_id -> sig_done = SIG_DONE;
00124             if (new_id -> signature == NIL) {
00125                 dbgmsg("equiv_expr: getcomp failed\n");
00126                 return(p);
00127             } else {
00128                 new_id -> signature = sig_structure(new_id -> signature);
00129                 return(new_id);
00130             }
00131         }
00132       }
00133     }
00134     return(p);
00135 }
00136 
00137 Gident(p, rloc)
00138 NODE *p;
00139 int rloc;
00140 {
00141     register NODE * v;
00142     int display_reg; /* location used for a.r. pointer */
00143                     
00144     if (Oflag? is_int_const(equiv_expr(p)) : is_int_const(p)) {
00145         extern long int_const_val;
00146 
00147         gen2(LDN, int_const_val, rloc);
00148         return;
00149     }
00150     v = p -> id_last_definition;
00151     if (p -> sel_type == NIL) {
00152         ASSERT2 (v != NIL, "ident: id %s not declared\n", 
00153                  getname(p -> id_str_table_index)
00154         );
00155         ASSERT2 (v -> kind == DECLARATION 
00156                  || v -> kind == PARAMETER
00157                  || v -> kind == MODPRIMARY
00158                     && v -> mp_type_modifier -> kind == WITHLIST,
00159                  "ident: id %x not declaration or parameter\n",v);
00160         ASSERT (v -> kind != DECLARATION
00161                 || !(v -> decl_special & VAR_IN_REG),
00162                 "Taking address of register variable\n");
00163         if (v -> kind == DECLARATION && (v -> decl_special & ID_IN_REG)) {
00164 #           ifdef DEBUG
00165             if(v -> level < Gcurrent -> ar_static_level) {
00166                 dbgmsg("Nonlocal register access\n");
00167                 fprintf(stderr,
00168                         "- to %s declared at level %d from level %d; declaration:\n",
00169                         getname(p -> id_str_table_index), v -> level, Glevel);
00170                 unparse_file = stderr;
00171                 if (v -> kind == DECLARATION) {
00172                     unparse(v -> decl_denotation);
00173                 } else {
00174                     unparse(v);
00175                 }
00176                 fprintf(stderr, "\n");
00177                 errmsg0(p, "Nonlocal access");
00178                 abort(p, v);
00179             }
00180 #           endif
00181             gen2(MOV, v -> displacement, rloc);
00182         } else if (sl_available || v -> level == 0) {
00183           if (!copied_globals || v -> level == 0 || v -> level == Glevel) {
00184             ASSERT2(v -> level == 0 || v -> level >= Gcurrent -> ar_static_level
00185                    || (Gcurrent -> fc_complexity & SL_ACC),
00186                    "Indirecting through nonexistent static link for %s\n",
00187                    getname(p -> id_str_table_index));
00188 #           ifdef DEBUG
00189                 if (v -> level > Glevel) {
00190                     dbgmsg("Accessing identifier %s at nesting level %d from level %d\n",
00191                            getname(p -> id_str_table_index), v -> level, Glevel);
00192                     abort();
00193                 }
00194 #           endif
00195             DISPLAY ( display_reg, v -> level);
00196             if (v -> kind == DECLARATION
00197                 && (v -> decl_special & VAR_ON_STACK)) {
00198                 switch(v -> displacement) {
00199                   case 1:
00200                     gen3(ADP, display_reg, C1, rloc);
00201                     break;
00202                   case 2:
00203                     gen3(ADP, display_reg, C2, rloc);
00204                     break;
00205                   case 3:
00206                     gen3(ADP, display_reg, C3, rloc);
00207                     break;
00208                   default:
00209                     gen2(LDN, v -> displacement, T1);
00210                     gen3(ADP, display_reg, T1, rloc);
00211                     gen1(UDC, T1);
00212                 }
00213             } else {
00214                 gen3 (LDI, display_reg, v->displacement, rloc);
00215             }
00216             UNDISPLAY ( display_reg );
00217           } else /* access to a nonlocal id that has been copied */ {
00218             switch(n_globals) {
00219                 case 0:
00220                     dbgmsg("ident: unexpected non-local: %s\n",
00221                            getname(p -> id_str_table_index));
00222                     fprintf(stderr, "Current function: %s\n",
00223                             Gcurrent -> fc_code_label);
00224                     abort();
00225                 case 1:
00226                     /* Identifier binding is stored in "static link" */
00227                     gen3(LDI, AR, 0, rloc);
00228                     break;
00229                 default:
00230                     /* *AR contains pointer to closure.  Binding */
00231                     /* is stored at offset 2 + index in list     */
00232                     {
00233                         int cl_ptr = avail_loc++;
00234                         int index;   /* Index in list of free ids */
00235 
00236                         index = 1;  /* For first non-local */
00237                         maplist(s, Gcurrent -> fc_free_vars, {
00238                            if (s -> id_last_definition -> pre_num
00239                                == v -> pre_num) {
00240                                 break;
00241                             }
00242                             index ++;
00243                         });
00244 #                       ifdef DEBUG
00245                             if(index > n_globals) {
00246                                 dbgmsg("ident: couldn't find non-local id %s\n",
00247                                        getname(p -> id_str_table_index));
00248                                 printf("Free variables for %s are:\n",
00249                                        Gcurrent -> fc_code_label);
00250                                 maplist(s, Gcurrent -> fc_free_vars, {
00251                                     printf("\t%s\n",
00252                                            getname(s -> id_str_table_index));
00253                                 });
00254                                 abort("couldnt find free var");
00255                             }
00256 #                       endif    
00257                         gen2(DCL, cl_ptr, DCL_ADDR);
00258                         gen3(LDI, AR, 0, cl_ptr);
00259                         gen3(LDI, cl_ptr, 2+index, rloc);
00260                         gen1(UDC, cl_ptr);
00261                     }
00262             }
00263           }
00264         } else /* no static link, no real activation record */ {
00265             extern int first_param_loc;
00266             /* Must be be parameter */
00267 #           ifdef OBSOLETE
00268                 gen3(LDI, FP, v->displacement+1, rloc);
00269 #           else
00270                 if (first_param_loc != 0) {
00271                     /* arguments are actually in temporaries */
00272                     int loc = first_param_loc + v -> displacement - 1;
00273 
00274                     ASSERT(Fflag || Gcurrent -> fc_complexity & DIR_REC,
00275                            "ident: bad first_param_loc\n");
00276                     gen2(MOV, loc, rloc);
00277                 } else {
00278                     gen2(GAR, v -> displacement, rloc);
00279                 }
00280 #           endif
00281         }
00282     } else {
00283         int type_loc = avail_loc++;
00284 
00285         gen2(DCL, type_loc, DCL_ADDR);
00286         Gexpression (p -> sel_type, type_loc, FALSE);
00287         gen3(LDI, type_loc, p -> sel_index, rloc);
00288         gen1(UDC, type_loc);
00289     }
00290     if (p -> id_forward_ref) {
00291       if (p -> signature -> kind == VALSIGNATURE) {
00292         NODE * type_den;
00293         NODE * type_sig;
00294         NODE * new_sig;
00295         extern NODE * id_New;
00296         /* May not be represented as a pointer */
00297         /* May not be possible to check for    */
00298         /* undefined value                     */
00299         /* Try to find out whether it is a ptr: */
00300         type_den = p -> signature -> val_denotation;
00301         tl_findsig(type_den, FALSE);
00302         type_sig = type_den -> signature;
00303         if (type_sig == ERR_SIG) {
00304             exit(1);
00305             /* Nearly impossible */
00306         }
00307         new_sig = getcomp(type_sig, id_New, NIL,
00308                           NIL, NIL, NIL, FALSE);
00309 #       ifdef VERBOSE
00310             unparse_file = stdout;
00311             printf("Trying to find rep of:\n");
00312             unparse(type_den);
00313             printf("\nWith signature:\n");
00314             unparse(type_sig);
00315             printf("\n");
00316             if (new_sig == NIL) {
00317                 printf("No New function\n");
00318             } else {
00319                 printf("Special: %X\n", new_sig -> fsig_special);
00320             }
00321 #       endif
00322         if (new_sig == NIL
00323             || new_sig -> kind != FUNCSIGNATURE
00324             || special_tp(new_sig -> fsig_special) != PTR_NEW) {
00325           errmsg1(p, "Warning: unchecked possible forward reference to %s",
00326                   getname(p -> id_str_table_index));
00327           /* Only a warning */
00328             yynerrs--;
00329         } else {
00330           goto check_undef;
00331         }
00332       } else {
00333         char * tmp_lbl;
00334 check_undef:
00335         /* Check that the value is defined */
00336           tmp_lbl = Gnewlabel("L");
00337           gen2(HINT, OPT, 4);
00338           gen3(EQI, rloc, UN, TL);
00339           genl(BRF, tmp_lbl);
00340           genl(ERR, "_forward_error");
00341           genl(LBL, tmp_lbl);
00342       }
00343     }
00344 }

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