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

Go to the documentation of this file.
00001 # define DEBUG
00002 
00003 /* 
00004  *  This is an attempt at a portable Russell code generator.
00005  *  It is based on the VAX specific version (pass5c).
00006  *
00007  *      Hans Boehm (started 2 July 1985)
00008  *
00009  */
00010 # include "parm.h"
00011 # include <stdio.h>
00012 # include "stree/ststructs.mh"
00013 # include "codegen.h"
00014 # include "op_codes.h"
00015 # include "pass4/sigs.h"
00016 # include "pass3/is_local.h"
00017 
00018 extern int yydebug;
00019 extern int yynerrs;
00020 
00021 extern boolean Pflag;  /* Generate profiling code */
00022 extern boolean Tflag;  /* Generate trace code */
00023 extern boolean Vflag;  /* Optimization info */
00024 extern boolean Oflag;  /* Optimize for execution speed */
00025 extern boolean Xflag;  /* Generate externally callable code */
00026 extern boolean xflag;  /* Generate code for Xerox Portable Common Runtime */
00027 extern boolean Fflag;  /* Load arguments into temporaries */
00028 
00029 extern char * entry_name; /* "" for main compilation */
00030 
00031 boolean sl_available = TRUE;  /* Static link available in      */
00032                               /* current function construction */
00033 
00034 boolean compile_fcs = TRUE;   /* Also compile nested function constructions */
00035                               /* as they are encountered.                   */
00036 
00037 boolean copied_globals;     /* Current function uses closure with copied */
00038                             /* non-local identifier bindings             */
00039 
00040 int n_globals;              /* Number of non-local identifiers referenced */
00041                             /* in current function.  Valid only if        */
00042                             /* copied_globals applies.                    */
00043 
00044 int avail_loc = FIRST_AVAIL_LOC;     /* next available location number */
00045 
00046 int first_param_loc;        /* First parameter location for current fn.  */
00047                             /* Applies only if parameters were copied.   */
00048                             /* This is done only if the DIR_REC bit is   */
00049                             /* set for the current function construction */
00050                             /* Otherwise first_param_loc is 0.           */
00051 
00052 void type_expr();  /* generate code for type in record element */
00053 
00054 boolean Gpush_size();  /* Push the size of an array onto the stack */
00055 
00056 char str_code_buf[MAXSTRCODELEN]; /* used for strings, "special" fns */
00057                                   /* and by find_inline              */
00058                                   /* and for object file names       */
00059                                   /* and to assemble labels          */
00060 char str_code_buf2[MAXSTRCODELEN]; /* used for strings */
00061 
00062 extern FILE * objfilelist;  /* List of object files which must be loaded */
00063 
00064 extern FILE * unparse_file;
00065 
00066 #ifdef UNDEFINED
00067 void add_objfile(fn)
00068 char * fn;
00069 {
00070     char *s;
00071 
00072     if (objfilelist == NULL) {
00073         objfilelist = fopen(OBJFILELIST, "w");
00074         if (objfilelist == NULL) {
00075             fprintf(stderr, "Can't open %s\n", OBJFILELIST);
00076             exit(1);
00077         }
00078     }
00079     for (s = fn; *s != '\0'; s++) {
00080         putc(*s, objfilelist);
00081     }
00082     putc('\n', objfilelist);
00083 }
00084 #endif
00085 
00086 /* Definitions for list of function constructions for whose body
00087  * we still need to generate code
00088  */
00089 
00090 typedef struct Fc_Entry {
00091         NODE * fc_pointer;
00092         int fc_level;
00093         int fc_fast_only;  /* Only simplified version needed */
00094                            /* Not really needed anymore ...  */
00095         struct Fc_Entry * fc_next;
00096 } fc_entry;
00097 
00098 fc_entry * Gfc_list = NIL;
00099 
00100 /* Add an entry to the front of Gfc_list, provided compile_fcs is TRUE */
00101 void Gfc_add(ptr,lvl,fast_only)
00102 NODE * ptr;    /* pointer to function construction */
00103 int lvl;       /* level of function construction   */
00104 int fast_only; /* generate only BSF version        */
00105 {
00106     fc_entry * p;
00107 
00108     if (!compile_fcs) { return; }
00109     p = (fc_entry *)malloc(sizeof (fc_entry));
00110     p -> fc_pointer = ptr;
00111     p -> fc_level = lvl;
00112     p -> fc_fast_only = fast_only;
00113     p -> fc_next = Gfc_list;
00114     Gfc_list = p;
00115 }
00116 
00117 /* remove an entry from the head of Gfc_list */
00118 void Gfc_delete()
00119 {
00120     fc_entry * p = Gfc_list;
00121 
00122     Gfc_list = Gfc_list -> fc_next;
00123     free(p);
00124 }
00125 
00126 int Glevel = -1;   /* current static nesting level */
00127 
00128 NODE * Gcurrent;
00129 FILE * Goutfile;
00130 
00131 boolean finished_accessible = FALSE;    /* Finished BOTH accessibility    */
00132                                         /* check and static link analysis */
00133 
00134 /* Compile all function constructions on Gfc_list */
00135 void Gcompile_funcs()
00136 {
00137     NODE * fc_ptr;
00138     int fc_lvl;
00139     int fc_fast_only;
00140     int first_avail_loc;
00141 
00142     first_avail_loc = avail_loc;
00143     while (Gfc_list != NIL) {
00144         fc_ptr = Gfc_list -> fc_pointer;
00145         fc_lvl = Gfc_list -> fc_level;
00146         fc_fast_only = Gfc_list -> fc_fast_only;
00147         Gfc_delete();
00148         if(!fc_fast_only) {
00149             /* Reset location counter so numbers don't grow too */
00150             /* rapidly.                                         */
00151               avail_loc = first_avail_loc;
00152             Gfunc_body(fc_ptr, fc_lvl);
00153         }
00154         if((fc_ptr -> fc_complexity & NO_SL) && fc_lvl != 0) {
00155             boolean old_sl_avail = sl_available;
00156 
00157             sl_available = FALSE;
00158             if (!fc_fast_only) { compile_fcs = FALSE; }
00159             avail_loc = first_avail_loc;
00160             Gfunc_body(fc_ptr,fc_lvl);
00161             sl_available = old_sl_avail;
00162             compile_fcs = TRUE;
00163         }
00164     }
00165 }
00166 
00167 
00168 /* generate code for syntax tree p into file f */
00169 Ggeneratecode ( f , p )
00170 NODE * p;
00171 FILE * f;
00172 {
00173     Goutfile = f;
00174     p -> fc_code_label = "_russell_top_level";
00175     analyze(p);     /* Compute fc_complexity fields */
00176     accessible(p);  /* find accessible code                 */
00177     bld_analyze(&p);  /* Find blocks requiring activation records */
00178     Gallocate (p,TRUE);   /* allocate space in activation records */
00179     sl_analyze(p);  /* Decide which functions reference free ids  */
00180     finished_accessible = TRUE;
00181     if (Oflag) {
00182         /* Redo fc_complexity analysis to take advantage of new info */
00183         if (Vflag) {
00184             printf("Repeating basic analysis:\n");
00185         }
00186         analyze(p);
00187     }
00188     cl_analyze(p, TRUE);  /* Decide on closure rep.               */
00189     if (yydebug) prtree(p);
00190     Gfc_add(p,0,FALSE); /* add main function to list of functions that need */
00191                         /* compiling.                                       */
00192     Gcompile_funcs();
00193 }
00194 
00195 /* generate code for syntax tree p embedded in syntax tree q into file f */
00196 /* invoked with -c compiler flag                                         */
00197 Ggeneratepcode ( f, q, p )
00198 NODE * p;
00199 NODE * q;
00200 FILE * f;
00201 {
00202     extern char * ofname;  /* Name of assembly language file */
00203 
00204     Goutfile = f;
00205     q -> fc_code_label = "_russell_top_level";
00206     if (p -> kind != FUNCCONSTR) {
00207         errmsg0(p, "Outermost expression must be function construction");
00208         return;
00209     }
00210     analyze(q);     /* Compute fc_complexity fields */
00211     accessible(q);  /* find accessible code                 */
00212     bld_analyze(&q);  /* Find blocks requiring activation records */
00213     Gallocate (q,FALSE);  /* allocate space in activation records */
00214     sl_analyze(p);  /* Decide which functions reference free ids  */
00215     finished_accessible = TRUE;
00216     if (Oflag) {
00217         /* Redo fc_complexity analysis to take advantage of new info */
00218         if (Vflag) {
00219             printf("Repeating basic analysis:\n");
00220         }
00221         analyze(q);
00222     }
00223     cl_analyze(p, TRUE);  /* Decide on closure rep.               */
00224 #   ifdef DEBUG
00225         if (yydebug) prtree(p);
00226 #   endif
00227     if (p -> ar_static_level != 1) {
00228         dbgmsg("user program must be at level 1");
00229     }
00230     /* Compile main function */
00231       sprintf(str_code_buf, "m_%s", entry_name);
00232       genl(EXT,str_code_buf);
00233       genl(BFN,str_code_buf);
00234       Glevel = 0;
00235       Gfuncconstructor(p, RL);
00236       gen0(RTN);
00237 
00238     Gcompile_funcs();
00239 }
00240 
00241 /* Generate code for syntax tree p embedded in syntax tree q into file f */
00242 /* The expression p should have type signature.  Generate an externally  */
00243 /* callable interface for p.                                             */
00244 /* Invoked with -X compiler flag                                         */
00245 GgenerateXcode ( f, q, p )
00246 NODE * p;
00247 NODE * q;
00248 FILE * f;
00249 {
00250     NODE * sig = sig_structure(p -> signature);
00251     char name_buf[120];
00252     char ar_name_buf[120];
00253 
00254     if (strlen(entry_name) > 100) {
00255         errmsg0(p, "file name too long");
00256         return;
00257     }
00258     Goutfile = f;
00259     q -> fc_code_label = "_russell_top_level";
00260     if (sig -> kind != TYPESIGNATURE) {
00261         errmsg0(p, "-X requires expression with type signature");
00262         return;
00263     }
00264     analyze(q);     /* Compute fc_complexity fields */
00265     accessible(q);  /* find accessible code                 */
00266     bld_analyze(&q);  /* Find blocks requiring activation records */
00267     Gallocate (q,FALSE);  /* allocate space in activation records */
00268     sl_analyze(q);  /* Decide which functions reference free ids  */
00269     finished_accessible = TRUE;
00270     if (Oflag) {
00271         /* Redo fc_complexity analysis to take advantage of new info */
00272         if (Vflag) {
00273             printf("Repeating basic analysis:\n");
00274         }
00275         analyze(q);
00276     }
00277     cl_analyze(q, TRUE);  /* Decide on closure rep.               */
00278 #   ifdef DEBUG
00279         if (yydebug) prtree(p);
00280 #   endif
00281     /* Compile the type expression in the context of a C callable function */
00282         Gcurrent = q;
00283         Glevel = 0;
00284         copied_globals = FALSE;
00285         sl_available = TRUE;
00286 
00287         /* Generate prolog */
00288           if (xflag) { 
00289             sprintf(name_buf, "_XR_run");
00290           } else {
00291             sprintf(name_buf, "_%s_", entry_name);
00292           }
00293           genl(EXT, name_buf);
00294           genl(BSF, name_buf);
00295 
00296         /* Generate a call to russell_set_up to set up main act. record */
00297           gen2(LDN, q -> ar_size, T1);     /* activation record size */
00298           if (xflag) {
00299               gen2(ARG, 1, T1);
00300           } else {
00301               gen2(ARG, 3, T1);
00302               gen2(GAR, 2, T1);     /* argv */
00303               gen2(ARG, 2, T1);
00304               gen2(GAR, 1, T1);     /* argc */
00305               gen2(ARG, 1, T1);
00306           }
00307           genl(EXT, "_russell_set_up");
00308           genl(LBA, "_russell_set_up");
00309           if (xflag) {
00310               gen1(CLC, 1);
00311           } else {
00312               gen1(CLC, 3);
00313           }
00314           gen1(HINT, GFU);
00315           gen2(MOV, RL, GF);
00316           gen2(MOV, GF, AR);
00317 
00318         /* Save the result in a named global location */
00319           sprintf(ar_name_buf, "_%s_ar_save_loc", entry_name);
00320           genl(LBA, ar_name_buf);
00321           gen1(IDT, 0);
00322           gen2(DCL, T2, DCL_ADDR);
00323           genl(LBA, ar_name_buf);
00324           gen1(LDL, T2);
00325           gen3(STI, T2, 0, GF);
00326           gen1(UDC, T2);
00327 
00328         /* Also save the result in global_ar, so that the various */
00329         /* call_russell routines will work correctly.             */
00330         /* For C code generation, this is needed by every routine */
00331         /* in a nested file that references GF.                   */
00332           gen2(HINT, ET, DCL_INT);
00333           genl(EXT, "_global_ar");
00334 #         ifdef GEN_C
00335             /* The C code has to declare global_ar in each file anyway. */
00336             /* Furthermore, there is an initialized declaration in      */
00337             /* startup.c.  Skip it here.                                */
00338 #         else
00339             genl(LBA, "_global_ar");
00340             gen1(IDT, 0);
00341 #         endif
00342           if (xflag) {
00343             /* Global_ar is set up by the startup code.  Furthermore, it */
00344             /* shouldn't matter which global_ar I get, since nobody      */
00345             /* relies on anything in the global frame except initenv.    */
00346             /* Separately compiled functions don't see anything else,    */
00347             /* and functions in this file will lokk in the right place.  */
00348             /* If I load things separately, pcr should actually          */
00349             /* guarantee that each Russell program sees the right one,   */
00350             /* but we don't rely on that.                                */
00351           } else {
00352             gen2(DCL, T2, DCL_ADDR);
00353             genl(LBA, "_global_ar");
00354             gen1(LDL, T2);
00355             gen3(STI, T2, 0, GF);
00356             gen1(UDC, T2);
00357           }
00358 
00359         Gexpression( p, T1, FALSE );
00360 
00361         /* Generate an epilog that stores the type value */
00362           sprintf(name_buf, "_%s_save_loc", entry_name);
00363           genl(LBA, name_buf);
00364           gen1(IDT, 0);
00365           gen2(DCL, T2, DCL_ADDR);
00366           genl(LBA, name_buf);
00367           gen1(LDL, T2);
00368           gen3(STI, T2, 0, T1);
00369           gen1(UDC, T2);
00370           gen0(RTN);
00371 
00372     /* Generate the necessary C callable procedure stubs  */
00373     /* These access both the stored type value and stored */
00374     /* global activation record.                          */
00375         compile_stubs(sig, name_buf, ar_name_buf);
00376 
00377     Gcompile_funcs();
00378 }
00379 
00380 
00381 /* generate code for function constructor p.  Return location holding object */
00382 Gfuncconstructor(p, rloc)
00383 NODE * p;
00384 int rloc;
00385 
00386 /*
00387  * Generate code to put the function object for the function construction
00388  * p into rloc.  Queue the function body for later code generation.
00389  */
00390 {
00391     int n_args;
00392     boolean contains_globals;  /* Closure contains non-local bindings */
00393     int cl_size;
00394     int fv_len;         /* number of non-locals */
00395     int tloc = avail_loc++;
00396 
00397     gen2(DCL, tloc, DCL_INT);
00398     if (p -> fc_body -> kind == EXTERNDEF) {
00399       int n_args = length(p -> signature -> fsig_param_list);
00400 
00401       /* allocate function object */
00402         ALLOC_FO(rloc);
00403 #     ifdef UNDEFINED
00404         /* Generate new name for function stub */
00405           p -> fc_code_label = new_global_label("fstub");
00406 #     endif
00407       /* Fill in ip */
00408         genl(EXT, p -> fc_code_label);
00409         genl(LBA, p -> fc_code_label);
00410         gen1(LDL, tloc);
00411         gen3(STI, rloc, FO_IP, tloc);
00412       /* fill in arg count + 1 as size */
00413         gen2(LDN, n_args + 1, tloc);
00414         gen3(STI, rloc, FO_SIZE, tloc);
00415       /* use arg count as ep */
00416         gen2(LDN, n_args, tloc);
00417         gen3(STI, rloc, FO_EP, tloc);
00418     } else {
00419         /* Compute size of closure */
00420           contains_globals = ((p -> fc_complexity & CP_GLOBALS) != 0);
00421           if (contains_globals) {
00422             fv_len = length(p -> fc_free_vars);
00423             if (fv_len <= 1) {
00424               cl_size = 3;
00425             } else {
00426               cl_size = 3 + fv_len;
00427             }
00428           } else {
00429             cl_size = 3;
00430           }
00431       /* Allocate function object */
00432         gen2(LDN, cl_size, tloc);
00433         gen2(ALH, tloc, rloc);
00434 
00435       /* Fill in ip */
00436         genl(EXT, p -> fc_code_label);
00437         genl(LBA, p -> fc_code_label);
00438         gen1(LDL, tloc);
00439         gen3(STI, rloc, FO_IP, tloc);
00440       /* fill in size */
00441         if (p -> fc_complexity & NO_AR_REFS) {
00442           /* store positive size, indicating stack a.r. is OK */
00443             gen2(LDN, p -> ar_size, tloc);
00444         } else {
00445             gen2(LDN, -(p -> ar_size), tloc);
00446         }
00447         gen3(STI, rloc, FO_SIZE, tloc);
00448       /* Fill in a suitable value as environment pointer */
00449         if (contains_globals) {
00450 
00451           if (fv_len == 1) {
00452             /* tloc := binding of non-local id */
00453                 Gident(first(p -> fc_free_vars), tloc);
00454             /* ep := tloc */
00455                 gen3(STI, rloc, FO_EP, tloc);
00456           } else if (fv_len > 1) {
00457             int cp;  /* Next position in closure to be filled in */
00458 
00459             /* ep := closure itself */
00460                 gen3(STI, rloc, FO_EP, rloc);
00461             /* copy non-locals */
00462                 cp = 3;
00463                 maplist(s, p -> fc_free_vars, {
00464                     Gident(s, tloc);
00465                     gen3(STI, rloc, cp, tloc);
00466                     cp++;
00467                 });
00468           }
00469         } else {
00470           /* Fill in current AR as ep */
00471             gen3(STI, rloc, FO_EP, AR);
00472         }
00473     }
00474     gen1(UDC, tloc);
00475     /* Add the function body to the queue */
00476         Gfc_add(p, Glevel + 1, FALSE);
00477 }
00478 
00479 
00480 /*
00481  * Generate code for the body of the function construction p at level l.
00482  * The actual function value is computed by Gfuncconstructor above.
00483  */
00484 Gfunc_body(p, l)
00485 NODE * p;
00486 int l;
00487 {
00488     boolean is_extern = (p -> fc_body -> kind == EXTERNDEF);
00489 /* 
00490  *      Enter scope of new function construction
00491  */
00492         Gcurrent = p;
00493         Glevel = l;
00494         copied_globals = ((Gcurrent -> fc_complexity & CP_GLOBALS) != 0);
00495         if (copied_globals) {
00496             n_globals = length(Gcurrent -> fc_free_vars);
00497         }
00498 
00499         if (sl_available) {
00500             genl(EXT, p -> fc_code_label);
00501             genl(BFN, p -> fc_code_label);
00502         } else {
00503           /* This is "fast" version of routine */
00504             sprintf(str_code_buf, "F%s", p -> fc_code_label);
00505             genl(EXT, str_code_buf);
00506             genl(BSF, str_code_buf);
00507         }
00508 
00509         if (Glevel == 0) {
00510           /* save global frame pointer */
00511             gen1(HINT, GFU);
00512             gen2(MOV,AR,GF);
00513         }
00514 
00515         if (Pflag) {
00516           /* generate profiling code */
00517             genl(PRO, (is_extern? p -> fc_body -> ext_name
00518                                 : p -> fc_code_label));
00519         }
00520 
00521         if (Tflag) {
00522           /* generate calls to stack trace routines */
00523             Gentry_trace((is_extern? p -> fc_body -> ext_name
00524                                    : p -> fc_code_label),
00525                            p -> signature -> fsig_param_list, FALSE);
00526         }
00527 
00528         if ((Fflag || (p -> fc_complexity & DIR_REC)) && !sl_available) {
00529             int i, n_args;
00530 
00531             /* Copy arguments into temporaries */
00532               first_param_loc = avail_loc;
00533               n_args = p -> ar_size - 1;  /* ar_size = # args + 1 */
00534               avail_loc += n_args;
00535               for (i = 0; i < n_args; i++) {
00536                 gen2(DCL, first_param_loc + i, DCL_INT);
00537                 gen2(GAR, i+1, first_param_loc + i);
00538               }
00539         } else {
00540             first_param_loc = 0;
00541         }
00542         if (p -> fc_complexity & DIR_REC) {
00543             if (sl_available) {
00544               sprintf(str_code_buf, "R%s", p -> fc_code_label);
00545             } else {
00546               sprintf(str_code_buf, "RF%s", p -> fc_code_label);
00547             }
00548             genl(LBL, str_code_buf);
00549         }
00550 
00551     if (is_extern) {
00552       /* Generate stub */
00553         NODE * params = p -> signature -> fsig_param_list;
00554         int n_args = length(params) - n_vacuous_params(params);
00555         int i;
00556 
00557       ASSERT(sl_available, "Can't compile stub without activation record\n");
00558       /* Push arguments */
00559         {
00560             int j = avail_loc++;
00561 
00562             gen2(DCL, j, DCL_INT);
00563             for (i = n_args; i >= 1; i--) {
00564                 gen3(LDI, AR, i, j);
00565                 gen2(ARG, i, j);
00566             }
00567             gen1(UDC, j);
00568         }
00569       /* Call procedure */
00570         genl(EXT, p -> fc_body -> ext_name);
00571         genl(LBA, p -> fc_body -> ext_name);
00572         gen1(CLC, n_args);
00573       
00574     } else {
00575       /* recursively descend */
00576         Gexpression( p -> fc_body, RL, TRUE );
00577     }
00578 
00579     if ((Fflag || (p -> fc_complexity & DIR_REC)) && !sl_available) {
00580         int i, n_args;
00581 
00582         /* Undeclare argument temporaries */
00583           n_args = p -> ar_size - 1;  /* ar_size = # args + 1 */
00584           for (i = 0; i < n_args; i++) {
00585                gen1(UDC, first_param_loc + i);
00586           }
00587     }
00588 
00589     /* Generate the epilog */
00590         if (Tflag) {
00591           /* generate call to stack trace routine */
00592             Gexit_trace(is_extern? p -> fc_body -> ext_name
00593                                  : p -> fc_code_label);
00594         }
00595         gen0(RTN);
00596 
00597     if (Glevel == 0) {
00598         gen2(HINT, ET, DCL_INT);
00599         genl(EXT, "_entry_ar_sz");
00600         genl(LBA, "_entry_ar_sz");
00601         gen1(IDT, p -> ar_size);
00602     }
00603 }
00604 
00605 /*
00606  * Generate code for the expression tree headed by p.  The value of the
00607  * expression is left in the location passed as a parameter.
00608  * The location rloc is presumed to have been declared.
00609  * Last_expr is TRUE only if it is known that this is the last subexpression
00610  * to be executed as a part of the current function body.  (This
00611  * is used to improve handling of tail recursion.)
00612  */
00613 Gexpression (p, rloc, last_expr)
00614 register NODE * p;
00615 int rloc;
00616 boolean last_expr;
00617 {
00618     int i;
00619     
00620     ASSERT( !last_expr || rloc == RL, "Gexpression: bad last_expr value\n");
00621 
00622     if (p -> signature -> kind == SIGNATURESIG) {
00623         /* signatures don't evaluate to anything interesting. */
00624         gen2(MOV, UN, rloc);
00625         return;
00626     }
00627 
00628     switch ( p -> kind ) {
00629 
00630         case OPRID :
00631         case LETTERID :
00632                 Gident(p, rloc);
00633                 break;
00634 
00635         case QSTR:
00636         case UQSTR:
00637                 {
00638                     NODE * sig = p -> sel_type -> signature;
00639                     char * code;  /* Actually list of RIC instrs */
00640                     int maxlen;  /* Maximum length for validity of */
00641                                  /* ts_string_code                 */
00642                     boolean know_inline;
00643 
00644                     ASSERT(sig -> kind == TYPESIGNATURE,
00645                            "codegen: bad string type\n");
00646                     if (sig -> ts_string_max == -1) {
00647                         maxlen = MAXSTRLEN;
00648                     } else {
00649                         maxlen = sig -> ts_string_max;
00650                     }
00651                     know_inline = (sig -> ts_string_code != NIL 
00652                                    && sig -> ts_element_code != NIL
00653                                    && strlen(p -> str_string) <= maxlen);
00654                     if (know_inline
00655                         && ! calls_put(p -> sel_type)) {
00656                         /* build body of in-line expansion */
00657                           char *r = p -> str_string;
00658                           char *q = str_code_buf;
00659 
00660                           *q = '\0';
00661                           while (*r != '\0') {
00662                             sprintf(q, sig -> ts_element_code, *r);
00663                             /* position q at trailing 0 */
00664                               q += strlen(q);
00665                             r++;
00666                           }
00667                         sprintf(str_code_buf2, sig -> ts_string_code,
00668                                 str_code_buf);
00669                         code = (char *)Ginline_cnvt(str_code_buf2);
00670                         write_RIC_seq(Goutfile, code, 0, rloc);
00671                         free_RIC(code);
00672                     } else {
00673                         if (Vflag) {
00674                             printf("Compiling expansion of %s\n",
00675                                    p -> str_string);
00676                         }
00677                         /* Should consider ts_meta_concat here */
00678                         Gexpression(p -> str_expansion, rloc, last_expr);
00679                     }
00680                 }
00681                 break;
00682 
00683         case APPLICATION :
00684                 Gappl(p, rloc, last_expr);
00685                 break;
00686 
00687         case BLOCKDENOTATION :
00688                 {
00689                     if ( p -> bld_flags & REQUIRES_AR ) {
00690                       /* Allocate activation record on heap.  Stack */
00691                       /* allocation doesn't make any sense, since   */
00692                       /* we only allocate a separate a.r. if refs   */
00693                       /* to the environment can escape.             */
00694                         int sz_loc = avail_loc++;
00695                         int ar_loc = avail_loc++;
00696 
00697                         ASSERT(sl_available, "Block a.r. inside simple fn");
00698                         Glevel++;
00699                         gen2(DCL, sz_loc, DCL_INT);
00700                         gen2(DCL, ar_loc, DCL_ADDR);
00701                         gen2(LDN, p -> ar_size, sz_loc);
00702                         gen2(ALH, sz_loc, ar_loc);
00703                         gen3(STI, ar_loc, 0, AR);
00704                         gen2(MOV, ar_loc, AR);
00705                         gen1(UDC, sz_loc);
00706                         gen1(UDC, ar_loc);
00707                     }
00708                     /* fill in undefined values so that forward refs */
00709                     /* can be checked.                               */
00710                     /* Declare virtual registers used for bindings.  */
00711                       maplist (v, p -> bld_declaration_list, {
00712                         ASSERT (v->kind == DECLARATION,
00713                                 "codegen.c: decl expected");
00714                         if (v -> decl_needed &&
00715                             (v -> decl_special & (ID_IN_REG | VAR_IN_REG))) {
00716                             genl(LBR, getname(v -> decl_id
00717                                                 -> id_str_table_index));
00718                             if (v -> decl_special & PTR_VAR_IN_REG) {
00719                                 gen2(DCL, v -> displacement, DCL_ADDR);
00720                             } else {
00721                                 gen2(DCL, v -> displacement, DCL_INT);
00722                             }
00723                         }
00724                         if (v -> decl_needed &&
00725                             v -> decl_can_be_refd <= v -> pre_num) {
00726                           /* possible forward reference to this decl */
00727                             gen2(HINT, OPT, 1);
00728                             if (v -> decl_special & (ID_IN_REG | VAR_IN_REG)) {
00729                                 gen2(MOV, UN, v -> displacement);
00730                             } else {
00731                                 gen3(STI, AR, v -> displacement, UN);
00732                             }
00733                         }
00734                       });
00735                     maplist (v, p -> bld_declaration_list, {
00736                       extern compile_decl();
00737 
00738                       compile_decl(v);
00739                     });
00740                     maplist (v,p->bld_den_seq, {
00741                         if (v != last(p -> bld_den_seq)) {
00742                             Gexpression(v, SK, FALSE);
00743                         } else {
00744                             Gexpression(v, rloc, last_expr);
00745                         }
00746                     });
00747                     /* Undeclare locations holding id bindings */
00748                       maplist (v, p -> bld_declaration_list, {
00749                         if (v -> decl_needed &&
00750                             (v -> decl_special & (ID_IN_REG | VAR_IN_REG))) {
00751                             if (v -> decl_special & ARRAY_CONTIG) {
00752                                 /* References to the interior of the array */
00753                                 /* can be live up to this point.  Thus     */
00754                                 /* the pointer to the beggining of the     */
00755                                 /* array should be kept around.            */
00756                                 gen2(HINT, LIVE, v -> displacement);
00757                             }
00758                             gen1(UDC, v -> displacement);
00759                         }
00760                       });
00761                     if ( p -> bld_flags & REQUIRES_AR ) {
00762                         Glevel--;
00763                         gen3(LDI, AR, 0, AR);
00764                     }
00765                     break;
00766                 }
00767                 
00768         case LOOPDENOTATION :
00769                 if (length(p -> gl_list) == 1) {
00770                     compile_while_loop(first(p -> gl_list), rloc);
00771                     break;
00772                 } /* else continue as with GUARDEDLIST: */
00773 
00774         case GUARDEDLIST :
00775                 {
00776                     char * L0;
00777                     register NODE * v;
00778                     boolean saw_else = FALSE;
00779 
00780                     if (p->kind == LOOPDENOTATION) {
00781                         L0=Gnewlabel("loop");
00782                         genl(LBL, L0);
00783                     } 
00784                     else {
00785                         L0=Gnewlabel("guard_exit");
00786                     }
00787                     maplist (v,p->gl_list, {
00788                         char * L1;
00789                         
00790                         ASSERT (v->kind == GUARDEDELEMENT,
00791                                         "codegen.c: bad guard list");
00792                         if (v -> ge_guard -> kind == WORDELSE)  {
00793                             saw_else = TRUE;
00794                         } else {
00795                             L1 = Gnewlabel ("guard");
00796                             if (Oflag && LAST_ITER
00797                                 && p -> kind == GUARDEDLIST) {
00798                                 /* No reason to perform the test, since */
00799                                 /* it better be true.                   */
00800                                 /* Evaluate guard for effect:           */
00801                                 Gexpression(v -> ge_guard, SK, FALSE);
00802                             } else {
00803                                 Gexpression(v->ge_guard, TL, FALSE);
00804                                 genl(BRF, L1);
00805                             }
00806                         }
00807                         if (p -> kind == LOOPDENOTATION) {
00808                             Gexpression(v -> ge_element, SK, FALSE);
00809                             genl(BR, L0);
00810                         } else {
00811                             Gexpression(v -> ge_element, rloc, last_expr);
00812                             if (saw_else) {
00813                                 /* Just fall off the end, dropping */
00814                                 /* any other else clauses          */
00815                                     break;
00816                             } else {
00817                                 /* Skip over the rest */
00818                                     genl(BR, L0);
00819                             }
00820                         }
00821                         genl(LBL, L1);
00822                     });
00823                     if (p -> kind == LOOPDENOTATION) {
00824                       /* return Void value "Null" */
00825                         gen2(MOV, UN, rloc);
00826                     } else {
00827                       if (!saw_else) {
00828                         /* Fell through the end of else-less "if" */
00829                             gen2(HINT, OPT, 1);
00830                             genl(ERR, "_cond_error");
00831                       }
00832                       /* Exit label for "if" */
00833                         genl(LBL, L0);
00834                     }
00835                     break;
00836                 }
00837 
00838         case WORDELSE :
00839                 {
00840                     /* Use true value */
00841                       gen1(TRU, rloc);
00842                     break;
00843                 }
00844                 
00845 
00846         case FUNCCONSTR :
00847                 {
00848                     Gfuncconstructor (p, rloc);
00849                     break;
00850                 }
00851 
00852         case REXTERNDEF :
00853                 {
00854                     int name_length = strlen(p -> r_ext_name);
00855                     char * q;
00856 
00857                     if (name_length + 3 > MAXSTRCODELEN) {
00858                         errmsg0(p, "File name too long");
00859                     }
00860                     if (Vflag) {
00861                         printf("%s forces evaluation of externally defined object %s\n",
00862                                Gcurrent -> fc_code_label,
00863                                p -> r_ext_name);
00864                     }
00865                     strcpy(str_code_buf, p -> r_ext_name);
00866                     str_code_buf[name_length] = '.';
00867                     str_code_buf[name_length+1] = 'o';
00868                     str_code_buf[name_length+2] = 0;
00869                     add_objfile(str_code_buf);
00870 
00871                     strcpy(str_code_buf, "m_");
00872                     strcat(str_code_buf, p -> r_ext_name);
00873                     /* Replace slashes with periods */
00874                         for (q = str_code_buf; *q != '\0'; q++) {
00875                             if (*q == '/') {
00876                                 *q = '.';
00877                             }
00878                         }
00879                     gen2(ARG, 1, GF);
00880                     genl(CLL, str_code_buf);
00881                     gen2(MOV, RL, rloc);
00882                     break;
00883                 }
00884 
00885         case USELIST :
00886                 {
00887                     maplist (v,p->usl_den_seq, {
00888                         if (v != last(p -> usl_den_seq)) {
00889                           Gexpression(v, SK, FALSE);
00890                         } else {
00891                           Gexpression(v, rloc, last_expr);
00892                         }
00893                     });
00894                     break;
00895                 }
00896 
00897 
00898         case MODPRIMARY :
00899                 {
00900                     NODE * tm = p -> mp_type_modifier;
00901                     unsigned * delv = (unsigned *)(p -> mp_delete_v);
00902                     int orig = p -> mp_orig_length;
00903                     int final = 0;  /* size of modified type */
00904                     int i,j;
00905                     int res_pos;    /* current position in result    */
00906                                     /* type                          */
00907                     DECLARE_ITER;   /* used for unusual traversal of */
00908                     NODE *s;        /* with list.  Note that with    */
00909                                     /* list is initially ordered by  */
00910                                     /* final component positions.    */
00911                     int *q;
00912                     boolean is_wl = (tm == NIL? FALSE
00913                                               : (tm -> kind == WITHLIST));
00914                     int wl_length;
00915 
00916                     if (is_wl) {
00917                         wl_length = length(tm -> wl_component_list);
00918                     } else {
00919                         wl_length = 0;
00920                     }
00921                     /* calculate size of new type */
00922                       if (orig > 0) {
00923                         q = (int *)delv; i = 0; j = *q;
00924                         while (i < orig) {
00925                           if (j >= 0) /* not deleted */ final++;
00926                           i++; j <<= 1;
00927                           if (i % WORDLENGTH == 0) /* go on to next word */ {
00928                             j = *(++q);
00929                           }
00930                         }
00931                       }
00932                       final += wl_length;
00933                     if (final == 0) {
00934                         gen2(LDN, 0, rloc);
00935                     } else {
00936                         int sz_loc = avail_loc++;
00937                                      /* size of new type              */
00938                                      /* also used as temp for copying */
00939                                      /* and wl components             */
00940                         int primary_loc = avail_loc++; /* pointer to orig tp */
00941                         int result_loc = avail_loc++;
00942 
00943                         /* Set up result_loc, in case rloc is SK */
00944                             if (rloc == SK || rloc == RL){
00945                                 /* RL might interfere with subsidiary */
00946                                 /* code generation for WITH list      */
00947                                 gen2(DCL, result_loc, DCL_ADDR);
00948                             } else {
00949                                 result_loc = rloc;
00950                             }
00951                         /* Evaluate original type */
00952                             if (orig > 0) {
00953                               gen2(DCL, primary_loc, DCL_ADDR);
00954                               Gexpression(p -> mp_primary, primary_loc, FALSE);
00955                             }
00956 
00957                         /* allocate type object, put ptr to it into tp_loc */
00958                         /* and rloc                                        */
00959                             gen2(DCL, sz_loc, DCL_INT);
00960                             gen2(LDN, final, sz_loc);
00961                             gen2(ALH, sz_loc, result_loc);
00962                             gen1(UDC, sz_loc);
00963 
00964                         /* save new type in space reserved for local name */
00965                           if (is_wl) {
00966                             int display_entry;
00967 
00968                             DISPLAY (display_entry, p -> level);
00969                             gen3(STI, display_entry, p -> displacement,
00970                                       result_loc);
00971                             UNDISPLAY(display_entry);
00972                           }
00973 
00974                         /* pointer to new object is in tp_loc      */
00975                         /* copy selected fields, reserve new ones  */
00976                           
00977                           /* s := first element of with list, NIL if there */
00978                           /* are none.                                     */
00979                             if (is_wl && !is_empty(tm->wl_component_list)) {
00980                               INIT_ITER(s, tm -> wl_component_list);
00981                             } else {
00982                               s = NIL;
00983                             }
00984                           q = (int *)delv; i = res_pos = 0;
00985                           j = (orig > 0? *q : 0);
00986                           while (s != NIL || i < orig) {
00987                             /* i = position in original type             */
00988                             /* sign bit of j = corr. deletion vector bit */
00989                             /* s = next unprocessed entry in with list   */
00990                             ASSERT(res_pos < 5000 && i < 5000,
00991                                    "Gexpression: bad type modification\n");
00992                             if (s != NIL && s -> decl_sel_index == res_pos) {
00993                                 res_pos++;
00994                                 NEXT_ITER(s);
00995                                 continue;
00996                             } else if (j >= 0) /* not deleted */ {
00997                                 /* Copy this element and increment pointers */
00998                                   gen3(LDI, primary_loc, i, T1);
00999                                   gen3(STI, result_loc, res_pos, T1);
01000                                 res_pos++;
01001                                 i++; j <<= 1;
01002                             } else /* deleted */ {
01003                                 i++; j <<= 1;
01004                             }
01005                             if (i % WORDLENGTH == 0) /*go on to next word*/ {
01006                                 j = *(++q);
01007                             }
01008                           }
01009                         /* new type, with with-list components missing, */
01010                         /* is in result_loc.                            */
01011                         if (orig > 0) {
01012                             gen1(UDC, primary_loc);
01013                         }
01014                         if (is_wl) {
01015                           NODE * decl_l = (NODE *)
01016                                              decl_sort(p -> mp_type_modifier
01017                                                        -> wl_component_list);
01018                                               /* declaration list in original*/
01019                                               /* order, with forward refs    */
01020                                               /* marked.                     */
01021                           int comp_loc = avail_loc++;
01022 
01023                           /* fill in undefined values so that forward refs */
01024                           /* can be checked.                               */
01025                             maplist (v, decl_l, {
01026                               ASSERT (v -> kind == DECLARATION,
01027                                       "codegen.c: decl expected");
01028                               if (v -> decl_can_be_refd <= v -> pre_num) {
01029                                 /* possible forward reference to this decl */
01030                                   gen3(STI, result_loc, v -> decl_sel_index, UN);
01031                               }
01032                             });
01033                           /* Fill in with list components */
01034                             gen2(DCL, comp_loc, DCL_ADDR);
01035                             maplist(s, decl_l, {
01036                               Gexpression(s -> decl_denotation, comp_loc, FALSE);
01037                               gen3(STI, result_loc,
01038                                    s -> decl_sel_index, comp_loc);
01039                             });
01040                             gen1(UDC, comp_loc);
01041                         }
01042                         /* result is in result_loc */
01043                         if (rloc == SK) {
01044                             gen1(UDC, result_loc);
01045                         } else if (rloc == RL) {
01046                             gen2(MOV, result_loc, rloc);
01047                             gen1(UDC, result_loc);
01048                         }  
01049                     }
01050                     break;
01051                 }
01052 
01053         case RECORDCONSTRUCTION:
01054         case PRODCONSTRUCTION :
01055         case UNIONCONSTRUCTION :
01056         case ENUMERATION:
01057         case EXTENSION :
01058                 type_constr(p, rloc);
01059                 break;
01060 
01061 
01062         default :
01063             findvl( p -> vlineno );
01064 
01065             dbgmsg( "Gexpression: Unimplemented construct (kind = %s) in file %s at line %d\n",
01066                     kindname(p->kind), getname(getfn()), getrl() );
01067             dbgmsg( "Gexpression:  p is 0x%x\n",p);
01068             fprintf( Goutfile, "?" );
01069             fflush (Goutfile);
01070             abort();
01071     }
01072 }
01073 
01074 /* Compile a loop consisting of a single guarded command efficiently */
01075 /* Could probably be generalized ...                                 */
01076 compile_while_loop(p, rloc)
01077 NODE *p;
01078 int rloc;
01079 {
01080     extern boolean OOOflag;     /* Unroll once */
01081     char * cond_label = Gnewlabel("guard");
01082     char * start_label = Gnewlabel("loop");
01083     char * end_label;
01084     boolean Ocompile_fcs = compile_fcs;
01085 
01086     if (OOOflag) {
01087       /* Compile unrolled loop body */
01088         compile_fcs = FALSE;  /* ignore nested functions; we'll get them */
01089                               /* later.                                  */
01090         end_label = Gnewlabel("loop_end");
01091         Gexpression(p -> ge_guard, TL, FALSE);
01092         genl(BRF, end_label);
01093         Gexpression(p -> ge_element, SK, FALSE);
01094         compile_fcs = Ocompile_fcs;
01095     }
01096     genl(BR, cond_label);
01097     genl(LBL, start_label);
01098     Gexpression(p -> ge_element, SK, FALSE);
01099     genl(LBL, cond_label);
01100     Gexpression(p -> ge_guard, TL, FALSE);
01101     genl(BRT, start_label);
01102     if (OOOflag) {
01103         genl(LBL, end_label);
01104     }
01105     /* Expression value is Null */
01106         gen2(MOV, UN, rloc);
01107 }

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