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

Go to the documentation of this file.
00001 /* 
00002  *  This is the zeroth approximation to the Russell code generator.
00003  *  I have started with printastx.c from pass5a and have begun to hack.
00004  *      Jim Hook  27 March 1982 
00005  *  Trying to revive this code.  Switched from display to static chain.
00006  *  Adding stack based calls, in-line calls, and type modification.
00007  *      Hans Boehm 7 Feb 1984
00008  *  Adding type constructions, etc.
00009  *      Hans Boehm 15 June 1984
00010  *  Added jsb calls, etc.
00011  *      Hans Boehm 6 Oct 1984
00012  *  Adding stack based variable allocation.
00013  *      Hans Boehm 4 June 1986 
00014  */
00015 # include "parm.h"
00016 # include <stdio.h>
00017 # include "stree/ststructs.mh"
00018 # include "codeutil.h"
00019 # include "pass4/sigs.h"
00020 # include "pass3/is_local.h"
00021 
00022 # ifdef DEBUG
00023 #   define IFDEBUG(x) x
00024 # else
00025 #   define IFDEBUG(x)
00026 # endif
00027 
00028 # define UNDEF (0x87654321)  /* runtime rep of undefined value */
00029 # define MAXOBJSZ 512   /* Must agree with the (obsolete) VAX runtime */
00030 
00031 extern int yydebug;
00032 extern int yynerrs;
00033 
00034 extern boolean Pflag;  /* Generate profiling code */
00035 extern boolean Tflag;  /* Generate trace code */
00036 
00037 extern char * entry_name; /* "" for main compilation */
00038 
00039 boolean mentions_r11();
00040 
00041 void type_expr();  /* generate code for type in record element */
00042 
00043 extern boolean is_int_const();
00044 
00045 char str_code_buf[MAXSTRCODELEN]; /* used for strings, "special" fns */
00046                                   /* and by find_inline              */
00047                                   /* and for object file names       */
00048 
00049 FILE * objfilelist = NULL;  /* List of object files which must be loaded */
00050 
00051 /* Add an object file to the list of files needed for linking */
00052 void add_objfile(fn)
00053 char * fn;
00054 {
00055     char *s;
00056 
00057     if (objfilelist == NULL) {
00058         objfilelist = fopen(OBJFILELIST, "w");
00059         if (objfilelist == NULL) {
00060             fprintf(stderr, "Can't open %s\n", OBJFILELIST);
00061             exit(1);
00062         }
00063     }
00064     for (s = fn; *s != '\0'; s++) {
00065         putc(*s, objfilelist);
00066     }
00067     putc('\n', objfilelist);
00068 }
00069 
00070 /* Definitions for list of function constructions for whose body
00071  * we still need to generate code
00072  */
00073 
00074 typedef struct Fc_Entry {
00075         NODE * fc_pointer;
00076         int fc_level;
00077         int fc_fast_only;  /* Only jsb version needed */
00078         struct Fc_Entry * fc_next;
00079 } fc_entry;
00080 
00081 fc_entry * fc_list = NIL;
00082 
00083 /* Add an entry to the front of fc_list */
00084 void fc_add(ptr,lvl,fast_only)
00085 NODE * ptr;    /* pointer to function construction */
00086 int lvl;       /* level of function construction   */
00087 int fast_only; /* generate only jsb version        */
00088 {
00089     fc_entry * p = (fc_entry *)malloc(sizeof (fc_entry));
00090 
00091     p -> fc_pointer = ptr;
00092     p -> fc_level = lvl;
00093     p -> fc_fast_only = fast_only;
00094     p -> fc_next = fc_list;
00095     fc_list = p;
00096 }
00097 
00098 /* remove an entry from the head of fc_list */
00099 void fc_delete()
00100 {
00101     fc_entry * p = fc_list;
00102 
00103     fc_list = fc_list -> fc_next;
00104     free(p);
00105 }
00106 
00107 int Ventry_mask,Vgc_mask;
00108 int Vlevel = -1;   /* current static nesting level */
00109 
00110 NODE * Vcurrent;   /* Function currently being compiled */
00111 FILE * Voutfile;
00112 
00113 
00114 /* generate code for syntax tree p into file f */
00115 Vgeneratecode ( f , p )
00116 NODE * p;
00117 FILE * f;
00118 {
00119     NODE * fc_ptr;
00120     int fc_lvl;
00121     int fc_fast_only;
00122 
00123     Voutfile = f;
00124     p -> fc_code_label = "russell_top_level";
00125     analyze(p);     /* Set up fc_complexity fields, etc. */
00126     accessible(p);  /* find accessible code                 */
00127     bld_analyze(&p);  /* Find blocks requiring activation records */
00128     Vallocate (p, TRUE);  /* allocate space in activation records */
00129     if (yydebug) prtree(p);
00130     ASM_HEADER;
00131     fc_add(p,0,FALSE);  /* add main function to list of functions that need */
00132                         /* compiling.                                       */
00133     while (fc_list != NIL) {
00134         fc_ptr = fc_list -> fc_pointer;
00135         fc_lvl = fc_list -> fc_level;
00136         fc_fast_only = fc_list -> fc_fast_only;
00137         fc_delete();
00138         if(!fc_fast_only) Vfuncbody(fc_ptr, fc_lvl);
00139         if((fc_ptr -> fc_complexity & NO_SL) && fc_lvl != 0) {
00140             Ffuncbody(fc_ptr);
00141             /* These have no nested function constructions */
00142         }
00143     }
00144 }
00145 
00146 /* generate code for syntax tree p embedded in syntax tree q into file f */
00147 /* invoked with -c compiler flag                                         */
00148 Vgeneratepcode ( f, q, p )
00149 NODE * q;
00150 NODE * p;
00151 FILE * f;
00152 {
00153     NODE * fc_ptr;
00154     int fc_lvl;
00155     int fc_fast_only;
00156     extern char * ofname;  /* Name of assembly language file */
00157 
00158     Voutfile = f;
00159     q -> fc_code_label = "russell_top_level";
00160     if (p -> kind != FUNCCONSTR) {
00161         errmsg0(p, "Outermost expression must be function construction");
00162         return;
00163     }
00164     analyze(q);     /* Set up fc_complexity fields */
00165     accessible(q);  /* find accessible code                 */
00166     bld_analyze(&q);  /* Find blocks requiring activation records */
00167     Vallocate (q, TRUE);  /* allocate space in activation records */
00168     if (yydebug) prtree(p);
00169     if (p -> ar_static_level != 1) {
00170         dbgmsg("user program must be at level 1");
00171     }
00172     /* Compile main function */
00173       fprintf(Voutfile, "\t.globl\tm_%s\n", entry_name);
00174       fprintf(Voutfile, "m_%s:\n", entry_name);
00175       Vlevel = 0;
00176       Vfuncconstructor(p);
00177       fprintf(Voutfile, "\tmovl\t(sp)+,r0\n");
00178       fprintf(Voutfile, "\trsb\n");
00179 
00180     while (fc_list != NIL) {
00181         fc_ptr = fc_list -> fc_pointer;
00182         fc_lvl = fc_list -> fc_level;
00183         fc_fast_only = fc_list -> fc_fast_only;
00184         fc_delete();
00185         if(!fc_fast_only) Vfuncbody(fc_ptr, fc_lvl);
00186         if((fc_ptr -> fc_complexity & NO_SL) && fc_lvl != 0) {
00187             Ffuncbody(fc_ptr);
00188             /* These have no nested function constructions */
00189         }
00190     }
00191 }
00192 
00193 
00194 /* generate code for function constructor p */
00195 Vfuncconstructor(p)
00196 NODE * p;
00197 
00198 /*
00199  * Generate code to push the function object for the function construction
00200  * p onto the stack.  Queue the function body for later code generation.
00201  */
00202 {
00203         if (p -> fc_body -> kind == EXTERNDEF) {
00204           int n_args = length(p -> signature -> fsig_param_list);
00205           /* compute the function "value" */
00206             putcomment ("# request new function object");
00207             FXD_NEWOBJ(FO_OBJ_SIZE);
00208             fprintf(Voutfile,"\tmovl\t$%d,%d(r0)", n_args, FO_EP);
00209             putcomment("# environment pointer");
00210             fprintf(Voutfile,"\t.globl\t%s\n",p -> fc_code_label);
00211             fprintf(Voutfile,"\tmovab\t%s,%d(r0)",p -> fc_code_label, FO_IP);
00212             putcomment("# instruction pointer");
00213             fprintf(Voutfile,"\tmovl\t$%d,%d(r0)", n_args+1 ,FO_SIZE);
00214             putcomment("# size of activation record");
00215             PUSH ("r0","# push function value");
00216             return;
00217         }
00218 
00219       /* compute the function "value" for non-external */
00220         putcomment ("# request new function object");
00221         FXD_NEWOBJ(FO_OBJ_SIZE);
00222         fprintf(Voutfile,"\tmovl\tap,%d(r0)",FO_EP);
00223         putcomment("# environment pointer");
00224         fprintf(Voutfile,"\tmovab\t%s,%d(r0)",p -> fc_code_label, FO_IP);
00225         putcomment("# instruction pointer");
00226 
00227                 /* Note that there is an implicit assumption that
00228                         small integers will be sufficient for stack
00229                         frame size.  */
00230         fprintf(Voutfile,"\tmovzwl\t$%d,%d(r0)",p -> ar_size,FO_SIZE);
00231         putcomment("# size of activation record");
00232         PUSH ("r0","# push function value");
00233 
00234     /* Add the function body to the queue */
00235         fc_add(p, Vlevel + 1, FALSE);
00236 }
00237 
00238 
00239 /*
00240  * Generate code for the body of the function construction p at level l.
00241  * The actual function value is computed by Vfuncconstructor above.
00242  */
00243 Vfuncbody(p, l)
00244 NODE * p;
00245 int l;
00246 {
00247         char * M1;
00248         
00249 /* 
00250  *      Enter scope of new function construction
00251  */
00252         Vcurrent = p;
00253         Ventry_mask = 0;
00254         Vgc_mask = 0;
00255         Vlevel = l;
00256 
00257         fprintf(Voutfile,"\t.globl\t%s\n",p -> fc_code_label);
00258         M1 = Vnewlabel ("mask");
00259         CODE ("\t.align  1");
00260         fprintf(Voutfile,"%s:\t.word\t%s",p -> fc_code_label,M1);
00261         putcomment("# code body");
00262 
00263         if (Vlevel == 0) {
00264           /* save global frame pointer */
00265             fprintf(Voutfile,"\tmovl\tap,%s\n", L0fp);
00266             Ventry_mask |= L0FP;
00267         }
00268 
00269         if (Pflag) {
00270           /* generate profiling code */
00271             Vcall_mcount();
00272         }
00273 
00274         if (Tflag) {
00275           /* generate calls to stack trace routines */
00276             Ventry_trace(p -> fc_code_label,
00277                          p -> signature -> fsig_param_list, FALSE);
00278         }
00279 
00280     /* recursively descend */
00281         Vexpression( p -> fc_body );
00282 
00283     /* Generate the epilog:  r0 <- top of stack */
00284         if (Tflag) {
00285           /* generate call to stack trace routine */
00286             Vexit_trace();
00287         }
00288         POP ("r0","# function value to r0");
00289         fprintf(Voutfile,"\tret\n");
00290         fprintf(Voutfile,"\t.set\t%s,0x%x\n",M1,Ventry_mask);
00291 
00292     if (Vlevel == 0) {
00293         CODE("\t.data");
00294         fprintf(Voutfile,"_entry_ar_sz:\t.long\t%d\n",p -> ar_size);
00295         CODE("\t.text");
00296     }
00297 }
00298 
00299 /*
00300  * Generate code for the expression tree headed by p.
00301  */
00302 Vexpression (p)
00303 register NODE * p;
00304 {
00305     int i;
00306 
00307     if (p -> signature -> kind == SIGNATURESIG) {
00308         /* signatures don't evaluate to anything interesting. */
00309         fprintf(Voutfile, "\tpushl\t$0\n");
00310         return;
00311     }
00312 
00313     switch ( p -> kind ) {
00314 
00315         case OPRID :
00316         case LETTERID :
00317                 {
00318                     register NODE * v;
00319                     char * display_reg; /* name of reg used for a.r. pointer */
00320                     char * r10 = "r10";
00321 
00322                     if (is_int_const(p)) {
00323                         extern long int_const_val;
00324 
00325                         fprintf(Voutfile, "\tpushl\t$%d\n", int_const_val);
00326                         return;
00327                     }
00328 
00329                     v = p -> id_last_definition;
00330                     if (p -> sel_type == NIL) {
00331                         ASSERT2 (v != NIL, "Vexpression: id %s not declared\n", 
00332                                  getname(p -> id_str_table_index)
00333                         );
00334                         ASSERT2 (v -> kind == DECLARATION 
00335                              || v -> kind == PARAMETER
00336                              || v -> kind == MODPRIMARY
00337                                 && v -> mp_type_modifier -> kind == WITHLIST,
00338                               "Vexpression: id %x not declaration or parameter\n",v
00339                         );
00340                         putcomment1("\t\t\t# Identifier %s",
00341                                      getname(p -> id_str_table_index));
00342                         DISPLAY ( display_reg, v -> level, r10,
00343                                 "# display entry in place");
00344                         if (display_reg == r10) Ventry_mask |= R10;
00345                         if (v -> kind == DECLARATION
00346                             && (v -> decl_special & VAR_ON_STACK)) {
00347                           fprintf(Voutfile, "\tmoval\t%d(%s),-(sp)\n",
00348                                   4 * v->displacement, display_reg);
00349                         } else {
00350                           PUSH_DISP (display_reg, v->displacement,
00351                                                   "# referenced object");
00352                         }
00353                     }
00354                     else {
00355                         putcomment1("\t\t\t# Selection of %s",
00356                                      getname(p->id_str_table_index));
00357                         Vexpression (p -> sel_type);
00358                         POP ("r0","# type value to r0");
00359                         PUSH_DISP ("r0",p -> sel_index,
00360                                 "# push selected function value");
00361                     }
00362                     if (p -> id_forward_ref) {
00363                       /* Check that the value is defined */
00364                         fprintf(Voutfile, "\tcmpl\t(sp),$0x%X\t #---\n",
00365                                 UNDEF);
00366                         fprintf(Voutfile, "\tbneq\t1f\t #---\n");
00367                         fprintf(Voutfile,
00368                                 "\tcalls\t$0,_forward_error\t #---\n");
00369                         fprintf(Voutfile, "1:\n");
00370                     }
00371                     break;
00372                 }
00373 
00374         case QSTR:
00375         case UQSTR:
00376                 {
00377                     NODE * sig = p -> sel_type -> signature;
00378                     int maxlen;  /* Maximum length for validity of */
00379                                  /* ts_string_code                 */
00380                     boolean know_inline;
00381 
00382 
00383                     ASSERT(sig -> kind == TYPESIGNATURE,
00384                            "codegen: bad string type\n");
00385                     if (sig -> ts_string_max == -1) {
00386                         maxlen = MAXSTRLEN;
00387                     } else {
00388                         maxlen = sig -> ts_string_max;
00389                     }
00390                     know_inline = (sig -> ts_string_code != NIL 
00391                                    && sig -> ts_element_code != NIL
00392                                    && strlen(p -> str_string) <= maxlen);
00393                     if (know_inline
00394                         && ! calls_put(p -> sel_type)) {
00395                         /* build body of in-line expansion */
00396                           char *r = p -> str_string;
00397                           char *q = str_code_buf;
00398 
00399                           *q = '\0';
00400                           while (*r != '\0') {
00401                             sprintf(q, sig -> ts_element_code, *r);
00402                             /* position q at trailing 0 */
00403                               q += strlen(q);
00404                             r++;
00405                           }
00406                         fprintf(Voutfile, sig -> ts_string_code, str_code_buf);
00407                         fprintf(Voutfile, "\n");
00408                     } else {
00409                         /* Should consider ts_meta_concat here */
00410                         Vexpression(p -> str_expansion);
00411                     }
00412                 }
00413                 break;
00414                 
00415         case APPLICATION :
00416                 Vappl(p);
00417                 break;
00418 
00419         case BLOCKDENOTATION :
00420                 {
00421                     if ( p -> bld_flags & REQUIRES_AR ) {
00422                       /* Allocate activation record on heap.  Stack */
00423                       /* allocation doesn't make any sense, since   */
00424                       /* we only allocate a separate a.r. if refs   */
00425                       /* to the environment can escape.             */ 
00426                         Vlevel++;
00427                         FXD_NEWOBJ(p -> ar_size);
00428                         CODE("\tmovl\tap,(r0)");
00429                         CODE("\tmovl\tr0,ap");
00430                     }
00431                     /* fill in undefined values so that forward refs */
00432                     /* can be checked.                               */
00433                       maplist (v, p -> bld_declaration_list, {
00434                         ASSERT (v->kind == DECLARATION,
00435                                 "codegen.c: decl expected");
00436                         if (v -> decl_needed &&
00437                             v -> decl_can_be_refd <= v -> pre_num) {
00438                           /* possible forward reference to this decl */
00439                             fprintf(Voutfile,"\tmovl\t$0x%X,%d(ap)\t #---\n",
00440                                     UNDEF, ObjSize * (v -> displacement));
00441                             putcomment("# store undefined value");
00442                         }
00443                       });
00444                     maplist (v, p -> bld_declaration_list, {
00445                       if (!v -> decl_needed) {
00446                           /* Generate code for nested function       */
00447                           /* constructions or modified primary nodes */
00448                           /* that may be evaluated.                  */
00449                             Vtraverse (v -> decl_denotation);
00450                       } else {
00451                         if (!(v -> decl_special & VAR_ON_STACK)) {
00452                             Vexpression (v-> decl_denotation);
00453                             POP_DISP ("ap",v->displacement,
00454                                       "# store declared value");
00455                         } else {
00456                           /* Initialize location */
00457                             if (v -> decl_special & SIMPLE_VAR_ON_STACK) {
00458                                 fprintf(Voutfile,"\tmovl\t$0,%d(ap)\n",
00459                                         4 * v->displacement);
00460                             } else if (v -> decl_special & PTR_VAR_ON_STACK) {
00461                                 fprintf(Voutfile,"\tmovl\t$%d,%d(ap)\n",
00462                                         UNDEF, 4 * v->displacement);
00463                             } else /* explicitly initialized */ {
00464                                 NODE * appl = v -> decl_denotation;
00465                                 NODE * arg = first(appl -> ap_args);
00466 
00467                                 ASSERT(appl -> kind == APPLICATION,
00468                                        "codegen.c: bad New application");
00469                                 Vexpression (arg);
00470                                 POP_DISP ("ap",v->displacement,
00471                                           "# store initial value");
00472                             }
00473                         }
00474                       }
00475                     });
00476                     maplist (v,p->bld_den_seq, {
00477                         Vexpression(v);
00478                         if (v != last(p -> bld_den_seq)) {
00479                             POP ("r0","# trash value");
00480                         }
00481                     });
00482                     if ( p -> bld_flags & REQUIRES_AR ) {
00483                         Vlevel--;                                      
00484                         CODE("\tmovl\t(ap),ap");                          
00485                     }
00486                     break;
00487                 }
00488                 
00489         case GUARDEDLIST :
00490         case LOOPDENOTATION :
00491                 {
00492                     char * L0;
00493                     register NODE * v;
00494 
00495                     if (p->kind == LOOPDENOTATION) {
00496                         L0=Vnewlabel("loop");
00497                         fprintf(Voutfile,"%s:\n",L0);
00498                     } 
00499                     else {
00500                         L0=Vnewlabel("guard_exit");
00501                     }
00502                     maplist (v,p->gl_list, {
00503                         char * L1;
00504                         
00505                         ASSERT (v->kind == GUARDEDELEMENT,
00506                                         "codegen.c: bad guard list");
00507                         Vexpression(v->ge_guard);
00508                         L1 = Vnewlabel ("guard");
00509                         POP ("r0","# value of guard");
00510                         fprintf(Voutfile,"\tjeql\t%s", L1);
00511                         putcomment ("# branch on false");
00512                         Vexpression(v->ge_element);
00513                         if (p -> kind == LOOPDENOTATION) {
00514                             POP("r0","# trash element value");
00515                         } else {
00516                             /* only one element execd */
00517                         }
00518                         fprintf(Voutfile,"\tjbr\t%s",L0);
00519                         putcomment ("# leave guarded list");
00520                         fprintf(Voutfile,"%s:",L1);
00521                         putcomment ("# next case");
00522                     });
00523                     if (p -> kind == LOOPDENOTATION) {
00524                       PUSH ("$0","# Value of loop or default of else is void");
00525                     } else {
00526                       fprintf(Voutfile,"\tcalls\t$0,_cond_error\n");
00527                     }
00528                     if (p->kind == GUARDEDLIST) {
00529                         fprintf (Voutfile,"%s:\n",L0);
00530                     }
00531                     break;
00532                 }
00533         case WORDELSE :
00534                 {
00535                     PUSH ("$1","# Else = constant 1");
00536                     break;
00537                 }
00538                 
00539 
00540         case FUNCCONSTR :
00541                 {
00542                     Vfuncconstructor (p);
00543                     break;
00544                 }
00545 
00546         case REXTERNDEF :
00547                 {
00548                     int name_length = strlen(p -> r_ext_name);
00549                     char *q;
00550 
00551                     if (name_length + 3 > MAXSTRCODELEN) {
00552                         errmsg0(p, "File name too long");
00553                     }
00554                     strcpy(str_code_buf, p -> r_ext_name);
00555                     str_code_buf[name_length] = '.';
00556                     str_code_buf[name_length+1] = 'o';
00557                     str_code_buf[name_length+2] = 0;
00558                     add_objfile(str_code_buf);
00559 
00560                     strcpy(str_code_buf, p -> r_ext_name);
00561                     /* Replace slashes with periods */
00562                         for (q = str_code_buf; *q != '\0'; q++) {
00563                             if (*q == '/') {
00564                                 *q = '.';
00565                             }                
00566                         }
00567                     fprintf(Voutfile, "\t.globl\tm_%s\n", str_code_buf);
00568                     fprintf(Voutfile, "\tjsb\tm_%s\n", str_code_buf);
00569                     fprintf(Voutfile, "\tpushl\tr0\n");
00570                     break;
00571                 }
00572 
00573         case USELIST :
00574                 {
00575                     maplist (v,p->usl_den_seq, {
00576                         Vexpression(v);
00577                         if (v != last(p -> usl_den_seq)) {
00578                           POP ("r0","# trash value");
00579                         }
00580                     });
00581                     break;
00582                 }
00583 
00584 
00585         case MODPRIMARY :
00586                 {
00587                     NODE * tm = p -> mp_type_modifier;
00588                     unsigned * delv = (unsigned *)p -> mp_delete_v;
00589                     int orig = p -> mp_orig_length;
00590                     int final = 0;  /* size of modified type */
00591                     int i,j;
00592                     int res_pos;    /* current position in result    */
00593                                     /* type                          */
00594                     DECLARE_ITER;   /* used for unusual traversal of */
00595                     NODE *s;        /* with list.  Note that with    */
00596                                     /* list is initially ordered by  */
00597                                     /* final component positions.    */
00598                     int *q;
00599                     int skipcnt;
00600                     int copycnt;
00601                     boolean is_wl = (tm == NIL? FALSE
00602                                               : (tm -> kind == WITHLIST));
00603                     int wl_length;
00604 
00605                     if (is_wl) {
00606                         wl_length = length(tm -> wl_component_list);
00607                     } else {
00608                         wl_length = 0;
00609                     }
00610                     /* calculate size of new type */
00611                       if (orig > 0) {
00612                         q = (int *)delv; i = 0; j = *q;
00613                         while (i < orig) {
00614                           if (j >= 0) /* not deleted */ final++;
00615                           i++; j <<= 1;
00616                           if (i % WORDLENGTH == 0) /* go on to next word */ {
00617                             j = *(++q);
00618                           }
00619                         }
00620                       }
00621                       final += wl_length;
00622                     if (final == 0) {
00623                         CODE("\tclrl\t-(sp)");
00624                     } else {
00625                         Vexpression(p -> mp_primary);
00626                         putcomment("# Get type object");
00627                         FXD_NEWOBJ(final);
00628                         CODE("\tclrl\t(r0)");
00629 
00630                         /* pointer to new object is in r0          */
00631                         /* copy selected fields, reserve new ones  */
00632                           
00633                           Ventry_mask |= R10;
00634                           POP("r10", "# original type");
00635                           PUSH("r0", "# new type");
00636                           /* s := first element of with list, NIL if there */
00637                           /* are none.                                     */
00638                             if (is_wl && !is_empty(tm->wl_component_list)) {
00639                               INIT_ITER(s, tm -> wl_component_list);
00640                             } else {
00641                               s = NIL;
00642                             }
00643                           q = (int *)delv; i = res_pos = 0;
00644                           j = (orig > 0? *q : 0);
00645                           skipcnt = 0; copycnt = 0;
00646                           while (s != NIL || i < orig) {
00647                             /* i = position in original type             */
00648                             /* sign bit of j = corr. deletion vector bit */
00649                             /* s = next unprocessed entry in with list   */
00650                             /* skipcnt = number of fields to be skipped  */
00651                             /* before next field is copied               */
00652                             /* copycnt = number of fields still to be    */
00653                             /* copied.                                   */
00654                             if (s != NIL && s -> decl_sel_index == res_pos) {
00655                                 /* first take care of postponed copies */
00656                                   copy_r10_to_r0(copycnt);
00657                                   copycnt = 0;
00658                                 fprintf(Voutfile,"\tclrl\t(r0)+");
00659                                 putcomment("# space for with list component");
00660                                 res_pos++;
00661                                 NEXT_ITER(s);
00662                                 continue;
00663                             } else if (j >= 0) /* not deleted */ {
00664                                 /* skip indicated number of slots */
00665                                   if (skipcnt != 0) {
00666                                       fprintf(Voutfile,"\taddl2\t$%d,r10",
00667                                                        4*skipcnt);
00668                                       putcomment("# skip slots");
00669                                       skipcnt = 0;
00670                                   }
00671                                 copycnt++;
00672                                 res_pos++;
00673                                 i++; j <<= 1;
00674                             } else /* deleted */ {
00675                                 /* copy indicated number of slots */
00676                                   copy_r10_to_r0(copycnt);
00677                                   copycnt = 0;
00678                                 skipcnt++;
00679                                 i++; j <<= 1;
00680                             }
00681                             if (i % WORDLENGTH == 0) /*go on to next word*/ {
00682                                 j = *(++q);
00683                             }
00684                           }
00685                           /* take care of any remaining copies */
00686                             copy_r10_to_r0(copycnt);
00687                             copycnt = 0;
00688                         /* new type, with with-list components missing, */
00689                         /* is on top of the stack                       */
00690                         if (is_wl) {
00691                           char * display_reg; /* name of reg used for a.r. */
00692                                               /* pointer                   */
00693                           char * r10 = "r10";
00694                           NODE * decl_l = (LIST)
00695                                             decl_sort(p -> mp_type_modifier
00696                                                         -> wl_component_list);
00697                                               /* declaration list in original*/
00698                                               /* order, with forward refs    */
00699                                               /* marked.                     */
00700                           char * nt_tmp;  /* temporary for new type object  */
00701                           boolean in_memory;
00702                                             
00703                           /* allocate temporary for new type and save it    */
00704                           /* there.                                         */
00705                             nt_tmp = Vnewreg();
00706                             in_memory = (Vreg_bit == 0);
00707                             fprintf(Voutfile, "\tmovl\t(sp),%s", nt_tmp);
00708                             putcomment("# new type to temporary");
00709                           /* save new type in space reserved for local name */
00710                             DISPLAY (display_reg, p -> level, r10,
00711                                      "# display entry for wlc");
00712                             if (display_reg == r10) Ventry_mask |= R10;
00713                             fprintf(Voutfile, "\tmovl\t%s,%d(%s)",
00714                                               nt_tmp,
00715                                               4 * (p -> displacement),
00716                                               display_reg);
00717                             putcomment("# save for local id references");
00718 
00719                           /* fill in undefined values so that forward refs */
00720                           /* can be checked.                               */
00721                             maplist (v, decl_l, {
00722                               ASSERT (v -> kind == DECLARATION,
00723                                       "codegen.c: decl expected");
00724                               if (v -> decl_can_be_refd <= v -> pre_num) {
00725                                 /* possible forward reference to this decl */
00726                                   if (in_memory) {
00727                                     fprintf(Voutfile,
00728                                             "\tmovl\t%s,r0\t #---\n", nt_tmp);
00729                                   }
00730                                   fprintf(Voutfile,
00731                                           "\tmovl\t$0x%X,%d(%s)\t #---",
00732                                           UNDEF,
00733                                           ObjSize * (v -> decl_sel_index),
00734                                           in_memory? "r0" : nt_tmp);
00735                                   putcomment("# store undefined value");
00736                               }
00737                             });
00738                           /* Fill in with list components */
00739                             maplist(s, decl_l, {
00740                               Vexpression(s -> decl_denotation);
00741                               if (in_memory) {
00742                                 fprintf(Voutfile, "\tmovl\t%s,r0\n", nt_tmp);
00743                                 POP_DISP("r0", s -> decl_sel_index,
00744                                          "# store with list component");
00745                               } else {
00746                                 POP_DISP(nt_tmp, s -> decl_sel_index,
00747                                          "# store with list component");
00748                               }
00749                             });
00750                           Vretreg(nt_tmp);
00751                         }
00752                         /* result is on top of the stack */
00753                     }
00754                     break;
00755                 }
00756 
00757         case RECORDCONSTRUCTION:
00758                 {
00759                     int n_components = length(p -> rec_component_list);
00760                     int i;
00761 
00762                     /* Allocate "environment" object for New, := and V */
00763                     /* This is a vector of these 3 functions for each  */
00764                     /* component.                                      */
00765                       if (3 * n_components > MAXOBJSZ) {
00766                           errmsg0(p, "Record too big\n");
00767                       }
00768                       putcomment ("# request pseudo-environment object");
00769                       FXD_NEWOBJ(3 * n_components);
00770                       CODE("\tclrl\t(r0)");
00771                     /* pointer to new type object is in r0   */
00772                     /* push it onto the stack                */
00773                       CODE("\tpushl\tr0");
00774                     /* evaluate type expressions in reverse order */
00775                       maprlist(p -> rec_component_list, type_expr);
00776                     /* Fill in fields in "environment"       */
00777                       i = 0;  /* position in "environment" */
00778                       maplist(s, p -> rec_component_list, {
00779                         fprintf(Voutfile, "\tmovl\t(sp)+,r1");
00780                         putcomment("# get component type");
00781                         fprintf(Voutfile, "\tmovl\t%d(r1),(r0)+",
00782                                 4 * (s -> re_assign_index));
00783                         putcomment("# component := operator");
00784                         fprintf(Voutfile, "\tmovl\t%d(r1),(r0)+",
00785                                 4 * (s -> re_New_index));
00786                         putcomment("# component New operator");
00787                         fprintf(Voutfile, "\tmovl\t%d(r1),(r0)+",
00788                                 4 * (s -> re_ValueOf_index));
00789                         putcomment("# component ValueOf operator");
00790                       });
00791                     /* Only a pointer to the pseudo-env object is  */
00792                     /* on the stack.  Proceed as with other constr */
00793                 }
00794 
00795         case PRODCONSTRUCTION :
00796         case UNIONCONSTRUCTION :
00797         case ENUMERATION:
00798                 {
00799                     NODE * clist = p -> signature -> ts_clist;
00800                     int len = tsig_length(p -> signature);
00801 
00802                     if (len > MAXOBJSZ) {
00803                         errmsg0(p, "Constructed type too big");
00804                     }
00805                     /* allocate an object of the right size */
00806                       putcomment ("# request new type object");
00807                       FXD_NEWOBJ(len);
00808                     /* pointer to new type object is in r0   */
00809                     /* Push it onto the stack and copy to r2 */
00810                       CODE("\tpushl\tr0");
00811                       CODE("\tmovl\tr0,r2");
00812                       Ventry_mask |= R2;
00813                     /* Fill in individual fields. r2 points to */
00814                     /* next field to be filled in.             */
00815                       /* First take care of 1 character constants in enumerations */
00816                         {                              
00817                           NODE * dcs = first(clist); 
00818                                            
00819                           ASSERT(dcs -> kind == DEFCHARSIGS,
00820                                  "codegen: type constr: bad DCS node\n");
00821                           if (dcs -> dcs_exceptions != NIL) {
00822                             maplist(s, dcs -> dcs_exceptions, {
00823                               gen_special(s -> dcse_special);
00824                               CODE("\tmovl\tr0,(r2)+");
00825                             });
00826                           }
00827                         }
00828 
00829                       maplist(s, clist, {
00830                         switch(s -> kind) {
00831                             case TSCOMPONENT:
00832                               gen_special(s -> tsc_signature -> fsig_special);
00833                               CODE("\tmovl\tr0,(r2)+");
00834                               break;
00835                           IFDEBUG(
00836                             case DEFCHARSIGS:
00837                               /* no constants */
00838                               break;
00839                             default:
00840                               dbgmsg("codegen: bad type constr. sig\n");
00841                           )
00842                         }
00843                       });
00844                     if (p -> kind == RECORDCONSTRUCTION) {
00845                       /* pop pseudo-environment from under type */
00846                         fprintf(Voutfile,"\tmovl\t(sp)+,(sp)");
00847                         putcomment(" # remove pseudo-environment");
00848                     }
00849                     break;
00850                 }
00851 
00852         case EXTENSION :
00853                 {
00854                     int len = tsig_length(p -> signature);
00855 
00856                     if (len > MAXOBJSZ) {
00857                         errmsg0(p, "Constructed type too big");
00858                     }
00859                     /* allocate an object of the right size */
00860                       putcomment ("# request new extension type object");
00861                       FXD_NEWOBJ(len);
00862                       CODE("\tclrl\t(r0)");
00863                     /* pointer to new type object is in r0   */
00864                     /* Push it.                              */
00865                       CODE("\tpushl\tr0");
00866                     /* put "argument" value into r3 */
00867                       Vexpression(p -> ext_denotation);
00868                       fprintf(Voutfile, "\tmovl\t(sp)+,r3");
00869                       putcomment("# Extension argument");
00870                       Ventry_mask |= R3;
00871                       Vgc_mask |= R3;
00872                     /* Copy new type object form top of stack into r2 */
00873                       CODE("\tmovl\t(sp),r2");
00874                       Ventry_mask |= R2;
00875                     /* put identity function value in r0       */
00876                       gen_special(special(IDENTITY, 0));
00877                     /* Fill in individual fields. r2 points to */
00878                     /* next field to be filled in.             */
00879                     /* r3 points to next unused field in arg   */
00880                       Vgc_mask &= ~R3; /* no allocation before its discarded */
00881                       ASSERT(p -> In_index < p -> Out_index,
00882                              "Vexpression: bad In, Out indicees\n");
00883                       copy_r3_to_r2(p -> In_index);
00884                       fprintf(Voutfile, "\tmovl\tr0,(r2)+");
00885                       putcomment("# In function");
00886                       copy_r3_to_r2(p->Out_index - p->In_index - 1);
00887                       fprintf(Voutfile, "\tmovl\tr0,(r2)+");
00888                       putcomment("# Out function");
00889                       copy_r3_to_r2(len - p->Out_index - 1);
00890                     /* new function value is left on the stack */
00891                     break;
00892                 }
00893 
00894 
00895         default :
00896             findvl( p -> vlineno );
00897 
00898             dbgmsg( "Vexpression: Unimplemented construct (kind = %s) in file %s at line %d\n",
00899                     kindname(p->kind), getname(getfn()), getrl() );
00900             dbgmsg( "Vexpression:  p is 0x%x\n",p);
00901             fprintf( Voutfile, "?" );
00902             fflush (Voutfile);
00903             abort();
00904     }
00905 }
00906 
00907 
00908 /* Compute the function value associated with the given special value */
00909 /* Leave the result in r0.  Also affects r1 and r10.                  */
00910 /* If a nontrivial pseudo-environment is needed, it is presumed to be */
00911 /* immediately below the top of the stack.                            */
00912 gen_special(spcl)
00913 unsigned spcl;
00914 {
00915     char * routine_name;  /* name of routine for each operation */
00916     int n_args;           /* number of arguments to routine     */
00917     boolean ep_on_stack = FALSE;  /* pseudo-env to be obtained from stack */
00918 
00919     /* Find routine name and n_args */
00920         switch(special_tp(spcl)) {
00921             case PROD_PROJ:
00922             case RECORD_VAL_FIELD:
00923             case RECORD_VAR_FIELD:
00924                 routine_name = "_P_R_ith";
00925                 n_args = 1;
00926                 break;
00927 
00928             case RECORD_MK:
00929             case PROD_MK:
00930                 routine_name = "_P_R_Make";
00931                 n_args = special_val(spcl);
00932                 break;
00933 
00934             case PROD_NEW:
00935             case UNION_NEW:
00936                 routine_name = "_P_U_New";
00937                 n_args = 0;
00938                 break;
00939 
00940             case RECORD_NEW:
00941                 routine_name = "_Record_New";
00942                 n_args = 0;
00943                 ep_on_stack = TRUE;
00944                 break;
00945 
00946             case ENUM_NEW:
00947                 routine_name = "_E_New";
00948                 n_args = 0;
00949                 break;
00950 
00951             case PROD_ASSIGN:
00952             case UNION_ASSIGN:
00953             case ENUM_ASSIGN:
00954                 routine_name = "_P_U_E_Assign";
00955                 n_args = 2;
00956                 break;
00957 
00958             case RECORD_ASSIGN:
00959                 routine_name = "_Record_Assign";
00960                 n_args = 2;
00961                 ep_on_stack = TRUE;
00962                 break;
00963     
00964             case PROD_VALUEOF:
00965             case UNION_VALUEOF:
00966             case ENUM_VALUEOF:
00967                 routine_name = "_P_U_E_ValueOf";
00968                 n_args = 1;
00969                 break;
00970                       
00971             case RECORD_VALUEOF:
00972                 routine_name = "_Record_ValueOf";
00973                 n_args = 1;
00974                 ep_on_stack = TRUE;
00975                 break;
00976 
00977             case UNION_PROJ:
00978                 routine_name = "_Union_Proj";
00979                 n_args = 1;
00980                 break;
00981     
00982             case UNION_INJ:
00983                 routine_name = "_Union_Inj";
00984                 n_args = 1;
00985                 break;
00986 
00987             case UNION_INQ:
00988                 routine_name = "_Union_Inq";
00989                 n_args = 1;
00990                 break;
00991 
00992             case ENUM_EQ:
00993                 routine_name = "_Enum_eq";
00994                 n_args = 2;
00995                 break;
00996 
00997             case ENUM_NE:
00998                 routine_name = "_Enum_ne";
00999                 n_args = 2;
01000                 break;
01001 
01002             case ENUM_ELEMENT:
01003                 routine_name = "_Enum_Element";
01004                 n_args = 0;
01005                 break;
01006 
01007             case ENUM_CARD:
01008                 routine_name = "_Enum_Card";
01009                 n_args = 0;
01010                 break;
01011 
01012             case ENUM_PRED:
01013                 routine_name = "_Enum_Pred";
01014                 n_args = 1;
01015                 break;
01016 
01017             case ENUM_SUCC:
01018                 routine_name = "_Enum_Succ";
01019                 n_args = 1;
01020                 break;
01021 
01022             case IDENTITY:
01023                 routine_name = "_Identity";
01024                 n_args = 1;
01025                 break;
01026 
01027 #         ifdef DEBUG
01028             default:
01029                 dbgmsg("gen_special: Unknown special function\n");
01030 #         endif
01031         }
01032     /* allocate new function object */
01033         putcomment ("# request new function object");
01034         FXD_NEWOBJ(FO_OBJ_SIZE);
01035         if (!ep_on_stack) {
01036           /* Use special value as ep */
01037             fprintf(Voutfile,"\tmovl\t$%d,%d(r0)",special_val(spcl), FO_EP);
01038         } else {
01039             fprintf(Voutfile,"\tmovl\t4(sp),%d(r0)", FO_EP);
01040         }
01041         putcomment("# dummy environment pointer");
01042     /* Set up ip */
01043         fprintf(Voutfile,"\t.globl\t%s\n", routine_name);
01044         fprintf(Voutfile,"\tmovab\t%s,%d(r0)",routine_name, FO_IP);
01045         putcomment("# instruction pointer");
01046     /* set activation record size to number of arguments plus 1 */
01047         fprintf(Voutfile,"\tmovzwl\t$%d,%d(r0)", n_args + 1, FO_SIZE);
01048         putcomment("# size of activation record");
01049 }
01050 
01051 
01052 /* Copy copycnt longwords from the source pointed to by r0 to the    */
01053 /* destination pointed to by r10.  r0 and r10 point to the addresses */
01054 /* past the last word moved after the operation is finished.         */
01055 copy_r10_to_r0(copycnt)
01056 int copycnt;
01057 {
01058 # ifdef EXTENDED_RANGE
01059     while (copycnt >= 4) {
01060         CODE("\tmovo\t(r10)+,(r0)+");
01061         copycnt -= 4;
01062     }
01063 # endif
01064     while (copycnt >= 2) {
01065         CODE("\tmovq\t(r10)+,(r0)+");
01066         copycnt -= 2;
01067     }
01068     while (copycnt >= 1) {
01069         CODE("\tmovl\t(r10)+,(r0)+");
01070         copycnt -= 1;
01071     }
01072 }
01073 
01074 /* Same as above, but r3 to r2 */
01075 copy_r3_to_r2(copycnt)
01076 int copycnt;
01077 {
01078 # ifdef EXTENDED_RANGE
01079     while (copycnt >= 4) {
01080         CODE("\tmovo\t(r3)+,(r2)+");
01081         copycnt -= 4;
01082     }
01083 # endif
01084     while (copycnt >= 2) {
01085         CODE("\tmovq\t(r3)+,(r2)+");
01086         copycnt -= 2;
01087     }
01088     while (copycnt >= 1) {
01089         CODE("\tmovl\t(r3)+,(r2)+");
01090         copycnt -= 1;
01091     }
01092 }
01093 
01094 /* Convert the special function descriptor from function signature to */
01095 /* inline code.                                                       */
01096 /* Clobbers str_code_buf                                              */
01097 char * Vspcl_to_inline(spcl)
01098 unsigned spcl;
01099 {
01100 #   define MAX_PROD_EXP_LEN 5
01101     int tp = special_tp(spcl);
01102     int val = special_val(spcl);
01103     int i;
01104     char * result;
01105 
01106     switch(tp) {
01107         case PROD_NEW:
01108         case UNION_NEW:
01109             sprintf(str_code_buf, "\tmovl\t_objfreelist+4,r0\n\tjneq\t1f\n\tmovl\t$0x%%X,r11\n\tpushl\t$1\n\tcalls\t$1,_allocobj\n1:\tmovl\t(r0),_objfreelist+4\n\tmovl\t$0x%X,(r0)\n\tpushl\tr0", UNDEF);
01110             break;
01111         case ENUM_NEW:
01112             sprintf(str_code_buf, "\tmovl\t_objfreelist+4,r0\n\tjneq\t1f\n\tmovl\t$0x%%X,r11\n\tpushl\t$1\n\tcalls\t$1,_allocobj\n1:\tmovl\t(r0),_objfreelist+4\n\tmovl\t$0,(r0)\n\tpushl\tr0", 0);
01113             break;
01114         case PROD_ASSIGN:
01115         case UNION_ASSIGN:
01116         case ENUM_ASSIGN:
01117             return("\tmovl\t4(sp),*(sp)+");
01118         case PROD_VALUEOF:
01119         case UNION_VALUEOF:
01120         case ENUM_VALUEOF:
01121             return("\tmovl\t*(sp),(sp)");
01122         case PROD_MK:
01123             if (val > MAX_PROD_EXP_LEN) return(NIL);
01124             sprintf(str_code_buf, "\tmovl\t_objfreelist+%d,r0\n\tjneq\t1f\n\tpushl\t$%d\n\tmovl\t$0x%%X,r11\n\tcalls\t$1,_allocobj\n1:\tmovl\t(r0),_objfreelist+%d\n\tmovl\tr0,r1", 4*val, val, 4*val);
01125             for(i = 0; i < val; i++) {
01126                 strcat(str_code_buf, "\n\tmovl\t(sp)+,(r1)+");
01127             }
01128             strcat(str_code_buf, "\n\tpushl\tr0");
01129             break;
01130         case PROD_PROJ:
01131         case RECORD_VAL_FIELD:
01132         case RECORD_VAR_FIELD:
01133             if (val == 0) {
01134                 return("\tmovl\t*(sp),(sp)");
01135             } else {
01136                 sprintf(str_code_buf, "\tmovl\t(sp),r0\n\tmovl\t%d(r0),(sp)",
01137                                       4*val);
01138             }
01139             break;
01140         case UNION_INJ:
01141             sprintf(str_code_buf, "\tmovl\t_objfreelist+8,r0\n\tjneq\t1f\n\tpushl\t$2\n\tmovl\t$0x%%X,r11\n\tcalls\t$1,_allocobj\n1:\tmovl\t(r0),_objfreelist+8\n\tmovl\t$%d,4(r0)\n\tmovl\t(sp),(r0)\n\tmovl\tr0,(sp)", val);
01142             break;
01143         case UNION_INQ:
01144             sprintf(str_code_buf, "\tmovl\t(sp)+,r0;\tcmpl\t4(r0),$%d #COMP jneq 4\n\tmovpsl\tr0\n\trotl\t$-2,r0,r0\n\tbicl3\t$0xfffffffe,r0,-(sp)", val);
01145             break;
01146         case UNION_PROJ:
01147             sprintf(str_code_buf, "\tmovl\t(sp),r0 #---\n\tcmpl\t$%d,4(r0) #---\n\tbeql\t1f #---\n\t.globl\t_union_err #---\n\tcalls\t$0,_union_err #---\n1:\tmovl\t*(sp),(sp)",val);
01148             break;
01149         case ENUM_EQ:
01150             sprintf(str_code_buf, "\tcmpl\t(sp)+,(sp)+ #COMP jneq 4\n\tmovpsl\tr0\n\trotl\t$-2,r0,r0\n\tbicl3\t$0xfffffffe,r0,-(sp)", val);
01151             break;
01152         case ENUM_NE:
01153             sprintf(str_code_buf, "\tcmpl\t(sp)+,(sp)+ #COMP jeql 4\n\tmovpsl\tr0\n\trotl\t$-2,r0,r0\n\tbicl3\tr0,$0x1,-(sp)", val);
01154             break;
01155         case ENUM_CARD:
01156         case ENUM_ELEMENT:
01157             sprintf(str_code_buf, "\tpushl\t$%d", val);
01158             break;
01159         case IDENTITY:
01160             return("# application of In, Out, Ord or OrdInv");
01161         case ENUM_PRED:
01162             return("\tdecl\t(sp)\n\tbgeq\t1f #---\n\t.globl\t_pred_error #---\n\tcalls\t$0,_pred_error #---\n1:\t\t #---");
01163         case ENUM_SUCC:
01164             sprintf(str_code_buf, "\tincl\t(sp)\n\tcmpl\t(sp),$%d #---\n\tbleq\t1f #---\n\t.globl\t_succ_error #---\n\tcalls\t$0,_succ_error #---\n1:\t\t #---",val);
01165             break;
01166         default:
01167             return(NIL);
01168     }
01169     /* code is in str_code_buf */
01170     result = (char *) malloc(strlen(str_code_buf) + 1);
01171     strcpy(result, str_code_buf);
01172     return(result);
01173 }
01174 
01175 /* Return TRUE iff the argument has "r11" as a substring */
01176 boolean mentions_r11(string)
01177 char *string;
01178 {
01179     register char * s;
01180 
01181     s = string;
01182     while (*s != '\0') {
01183         if (*s++ == 'r') {
01184             if (*s == '1') {
01185                 s++;
01186                 if (*s == '1') {
01187                     return(TRUE);
01188                 }
01189             }
01190         }
01191     }
01192     return(FALSE);
01193 }
01194 
01195 /* generate code to push the value of the type expression in a record */
01196 /* component.                                                         */
01197 void type_expr(re)
01198 NODE * re;
01199 {
01200   Vexpression(re -> re_denotation);
01201 }

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