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

Go to the documentation of this file.
00001 # define DEBUG DEBUG
00002 #include <stdio.h>
00003 #include <ctype.h>
00004 #include "../parm.h"
00005 #include "op_codes.h"
00006 #include "codegen.h"
00007 
00008 #define OCLENGTH 9  /* maximum length of mnemonics */
00009 
00010 #define MAXLOC 100000  /* Largest plausible location number */
00011 
00012 /* Miscellaneous routines for conversion between representations */
00013 /* of Russell Intermediate Code                                  */
00014 
00015 /* hash table structure for op codes and special locations */
00016 typedef struct hrecord {
00017     char hr_name[OCLENGTH+1];
00018     int hr_val;
00019     struct hrecord * hr_next;
00020 } hrecord;
00021 
00022 # define NIL 0
00023 
00024 # define TABSIZE 50
00025 # define hash(s) ((((s)[0]<<2) + (((s)[1]) == '\0'? 0 : (s)[1] + (s)[2]))%TABSIZE)
00026 
00027 static hrecord * htable[TABSIZE];
00028 
00029 /* Add entry with name nm and value vl to the hash table.  No check is made */
00030 /* to see whether it is already there.                                      */
00031 void add_RIC_table(nm, val)
00032 char * nm;
00033 int val;
00034 {
00035     register int index = hash(nm);
00036     register hrecord *  nhr = (hrecord *)gc_malloc(sizeof (hrecord));
00037 
00038     nhr -> hr_next = htable[index];
00039     strcpy(nhr -> hr_name,nm);
00040     nhr -> hr_val = val;
00041     htable[index] = nhr;
00042 }
00043 
00044 extern char * op_code_table[];
00045 #define NONE ((char *)0)
00046 
00047 /* Initialize htable to contain opcodes and predefined location names */
00048 void init_RIC_table()
00049 {
00050     int i;
00051     /* Op codes */
00052       for ( i = 0; i < N_OP_CODES; i++ ) {
00053           if (op_code_table[i] != NONE) {
00054               add_RIC_table(op_code_table[i], i);
00055           }
00056       }
00057     /* Special locations */
00058       add_RIC_table("RS", RS);
00059       add_RIC_table("AR", AR);    /* activation record pointer */
00060       add_RIC_table("SP", SP);    /* stack pointer             */
00061       add_RIC_table("GF", GF);    /* global frame pointer      */
00062       add_RIC_table("UN", UN);    /* undefined value constant  */
00063       add_RIC_table("SK", SK);    /* value sink                */
00064       add_RIC_table("RL", RL);    /* function result location  */
00065       add_RIC_table("TL", TL);    /* test result location      */
00066       add_RIC_table("C0", C0);    /* constant 0                */
00067       add_RIC_table("C1", C1);    /* constant 1                */
00068       add_RIC_table("C2", C2);    /* constant 2                */
00069       add_RIC_table("C3", C3);    /* constant 3                */
00070       add_RIC_table("C4", C4);    /* constant 4                */
00071       add_RIC_table("T1", T1);    /* temporary 1               */
00072       add_RIC_table("T2", T2);    /* temporary 2               */
00073     /* Types for DCL instruction */
00074       add_RIC_table("ADDR", DCL_ADDR);
00075       add_RIC_table("INT", DCL_INT);
00076       add_RIC_table("FLOAT", DCL_FLOAT);
00077       add_RIC_table("DBL_FLOAT", DCL_DBL_FLOAT);
00078     /* Kinds for HINT instruction */
00079       add_RIC_table("OPT", OPT);
00080       add_RIC_table("NP", NP);
00081       add_RIC_table("PT", PT);
00082       add_RIC_table("AL", AL);
00083       add_RIC_table("DEA", DEA);
00084       add_RIC_table("NSC", NSC);
00085       add_RIC_table("STSZ", STSZ);
00086       add_RIC_table("DEAD", DEAD);
00087       add_RIC_table("GFU",GFU);
00088       add_RIC_table("LIVE",LIVE);
00089       add_RIC_table("ET", ET);
00090       add_RIC_table("ONS", ONS);
00091 }
00092 
00093 /* Look up the indicated name in the hash table. Return the associated */
00094 /* value.   Returns MISSING if entry is not found                      */
00095 int find_RIC_table(name)
00096 char * name;
00097 {
00098     register hrecord * ce = htable[hash(name)];
00099     
00100     while (ce != NIL) {
00101         if (strcmp(ce -> hr_name, name) == 0) {
00102             return (ce -> hr_val);
00103         }
00104         ce = ce -> hr_next;
00105     }
00106 
00107     return(MISSING);
00108 }
00109 
00110 /* Copy the string pointed to by p to field_buf.  Stop after OCLENGTH */
00111 /* characters, or after a \0, \b, \t, \n.                             */
00112 /* Return a pointer to the field separator.                           */
00113 static char field_buf[OCLENGTH+1];
00114 
00115 static char * extract_field(p)
00116 char * p;
00117 {
00118     register int i;
00119     register char c;
00120     
00121     for (i = 0; i < OCLENGTH; i ++) {
00122         c = *p++;
00123         switch(c) {
00124             case '\0':
00125             case ' ':
00126             case '\t':
00127             case '\n':
00128             case ',':
00129             case ';':
00130                 field_buf[i] = '\0';
00131                 return(p-1);
00132             default:
00133                 field_buf[i] = c;
00134         }
00135     }
00136     field_buf[OCLENGTH] = '\0';
00137     return(p);
00138 }
00139 
00140 /* Free a sequence of RIC instructions */
00141 void free_RIC(p)
00142 struct RIC_instr * p;
00143 {
00144     struct RIC_instr *current, *next;
00145 
00146     current = p;
00147     while (current != (struct RIC_instr *) 0) {
00148         next = current -> next_instr;
00149         free(current);
00150         current = next;
00151     }
00152 }
00153 
00154 /* Write out a sequence of RIC instructions onto stream f */
00155 put_RIC(seq, f)
00156 struct RIC_instr * seq;
00157 FILE * f;
00158 {
00159     struct RIC_instr *current;
00160 
00161     for (current = seq; current != (struct RIC_instr *) 0;
00162          current = current -> next_instr) {
00163         putc(current -> op_code, f); /* Must be non-zero */
00164         putc(current -> label_arg, f); putc(current -> n_args, f);
00165         if (current -> label_arg) {
00166             char * s = current -> label;
00167             for (; *s != '\0'; s++) {
00168                 putc(*s, f);
00169             }
00170             putc(0, f);
00171         } else {
00172             putw(current -> arg[0], f);
00173             putw(current -> arg[1], f);
00174             putw(current -> arg[2], f);
00175         }
00176     }
00177     /* Write a terminating null op code */
00178     putc(0,f);
00179 }
00180 
00181 extern long avail_loc;
00182 
00183 /* Read a sequence of RIC instructions written by put_RIC       */
00184 /* update avail_loc to be larger than any location encountered. */
00185 struct RIC_instr * get_RIC(f)
00186 FILE * f;
00187 {
00188     struct RIC_instr *current;
00189     struct RIC_instr *last;
00190     struct RIC_instr *result = (struct RIC_instr *)0;
00191     int opcode;
00192     int label_arg;
00193     int n_args;
00194     long arg0;
00195     char label_buf[MAXLABELSZ+1];
00196                
00197     while ((opcode = getc(f)) != 0) {
00198         label_arg = getc(f);
00199         n_args = getc(f);
00200         if (feof(f)) {
00201             dbgmsg("Unexpected end of file\n");
00202             abort();
00203         }
00204         if (label_arg) {
00205             char * s = label_buf;
00206             char * t;
00207 
00208             while((*s++ = getc(f)) != '\0');
00209             current = (struct RIC_instr *) gc_malloc(sizeof(struct RIC_instr)
00210                                                      + s - label_buf);
00211             /* Fill in the label field */
00212               s = current -> label;
00213               t = label_buf;
00214               while (*s++ = *t++);
00215         } else {
00216             current = (struct RIC_instr *) gc_malloc(sizeof(struct RIC_instr));
00217             current -> arg[0] = arg0 = getw(f);
00218             current -> arg[1] = getw(f);
00219             current -> arg[2] = getw(f);
00220             current -> label[0] = '\0';
00221         }
00222         /* update avail_loc */
00223           if (opcode == DCL && arg0 >= avail_loc) {
00224             if ((arg0 & ARG_BIT) || arg0 == RS) {
00225                 dbgmsg("get_RIC: Attempt to declare argument or result\n");
00226                 abort(arg0);
00227             }
00228 #           ifdef DEBUG
00229               if (((unsigned)arg0) > 10000000) {
00230                 dbgmsg("get_RIC: Bad declaration\n");
00231                 abort(arg0);
00232               }
00233 #           endif
00234             avail_loc = arg0+1;
00235           }
00236         current -> op_code = opcode; current -> n_args = n_args;
00237         current -> label_arg = label_arg;
00238         current -> next_instr = (struct RIC_instr *)0;
00239         /* Add current to the end of result sequence */
00240           if (result == (struct RIC_instr *)0) {
00241             result = last = current;
00242           } else {
00243             last -> next_instr = current;
00244             last = current;
00245           }
00246     }
00247     return(result);
00248 }
00249 
00250 
00251 /* Parse the text line *s, which is assumed to contain a mnemonic        */
00252 /* description of an RIC instruction.  Return a pointer to a newly       */
00253 /* allocated RIC_instr node.   A pointer to the ';', \n, or \0 character */
00254 /* trailing the line is returned in *s.                                  */
00255 struct RIC_instr * parse_RIC(s)
00256 char **s;
00257 {
00258 #   define skip_blanks while (*p == ' ' || *p == '\t' || *p == ',') { p++; }
00259 #   define AT_END (*p == '\0' || *p == '\n' || *p == ';')
00260     char *p = *s;
00261     int op_code;
00262     int i;
00263     struct RIC_instr * result;
00264 
00265     skip_blanks;
00266 #   ifdef DEBUG
00267         if (AT_END) {
00268             dbgmsg ("Empty RIC line\n");
00269             abort();
00270         }
00271 #   endif
00272     p = extract_field(p);
00273     op_code = find_RIC_table(field_buf);
00274 #   ifdef DEBUG
00275         if (op_code == MISSING) {
00276             dbgmsg ("Bad RIC opcode: %s\n", field_buf);
00277             abort();
00278         }
00279 #   endif
00280     skip_blanks;
00281     if (*p == '\"') {
00282         char * q;
00283         int i = 0;
00284 
00285         /* label */
00286 #       ifdef DEBUG
00287             if (i > MAX_LABEL_OP) {
00288                 dbgmsg("Label with big op code, oc = %d\n", i);
00289             }
00290 #       endif
00291         p++;
00292         result = (struct RIC_instr *) gc_malloc(sizeof(struct RIC_instr)
00293                                                 + ((char *)(index(p,'"'))) - p);
00294         result -> op_code = op_code;
00295         result -> n_args = 1;
00296         result -> next_instr = (struct RIC_instr *)0;
00297         q = result -> label;
00298         while ((*q = *p++) != '\"') {
00299             if (*q == '\\') {
00300                 /* Next 3 characters are octal escape */
00301                 int j,k;
00302 
00303                 k = 0;
00304                 for (j = 0; j < 3; j++) {
00305                     k = 8*k + (*p++) - '0';
00306                 }
00307                 *q = k;
00308             }
00309             q++;
00310         }
00311         *q = '\0';
00312         skip_blanks;
00313 #       ifdef DEBUG
00314             if (!(AT_END)) {
00315                 dbgmsg("Junk: %s following RIC label: %s\n", p, result -> label);
00316             }
00317 #       endif
00318         result -> label_arg = TRUE;
00319     } else {
00320         /* numeric arguments */
00321         result = (struct RIC_instr *) gc_malloc(sizeof(struct RIC_instr));
00322         result -> label_arg = FALSE;
00323         result -> op_code = op_code;
00324         result -> n_args = 0;
00325         result -> next_instr = (struct RIC_instr *)0;
00326         while (!(AT_END)) {
00327             if (isdigit(*p)) {
00328                 int v = 0;
00329                 while (isdigit(*p)) {
00330                     v = v * 10 + (*p++ - '0');
00331                 }
00332                 result -> arg[result -> n_args++] = v;
00333             } else if (*p == '$') {
00334                 int v = 0;
00335 
00336                 p++;
00337                 while (isdigit(*p)) {
00338                     v = v * 10 + (*p++ - '0');
00339                 }
00340 #               ifdef DEBUG
00341                     if (v <= 0) {
00342                         dbgmsg("There is no parameter 0\n");
00343                     }
00344 #               endif
00345                 result -> arg[result -> n_args++] = v + ARG_BIT;
00346             } else {
00347                 p = extract_field(p);
00348                 i = find_RIC_table(field_buf);
00349 #               ifdef DEBUG
00350                     if (i == MISSING) {
00351                         dbgmsg ("Bad RIC loc: %s\n", field_buf);
00352                         abort();
00353                     }
00354 #               endif
00355                 result -> arg[result -> n_args++] = i;
00356             }
00357             skip_blanks;
00358         }
00359     }
00360     *s = p;
00361     return(result);
00362 }
00363 
00364 /* Convert a string representing RIC code to internal form. The string */
00365 /* is assumed to contain a number of newline or ; separated            */
00366 /* instructions. The result is a linked list of RIC_instr nodes.       */
00367 /* The original string is freed unless it was statically allocated.    */
00368 struct RIC_instr * Ginline_cnvt(s)
00369 char *s;
00370 {
00371     char *p = s;
00372     struct RIC_instr *first = NIL;
00373     struct RIC_instr *last = NIL;
00374     struct RIC_instr *q = NIL;
00375     extern char end;
00376 
00377     while (*p != '\0') {
00378         q = parse_RIC(&p);
00379         if (first == NIL) {
00380             first = last = q;
00381         } else {
00382             last -> next_instr = q;
00383             last = q;
00384         }
00385         while (*p == '\n' || *p == ';') { p++; }
00386     }
00387     last -> next_instr = NIL;
00388     if (s > &end) {
00389       free(s);
00390     }
00391     return(first);
00392 }
00393 
00394 /* Write out the RIC instruction on stream f.  Add n-1 to each argument */
00395 /* number appearing in the instruction, except if n = 0.                */
00396 /* If n = 0, map the first argument to the top of the stack, the second */
00397 /* one to below the top of the stack, etc.  RS location by the value of */
00398 /* rs.                                                                  */
00399 void write_RIC(f, RIC_i, n, rs)
00400 FILE * f;
00401 struct RIC_instr * RIC_i;
00402 int n;
00403 int rs;
00404 {
00405     char * result;
00406 
00407     putw(RIC_i -> op_code, f);
00408     if (RIC_i -> label_arg) {
00409         fputs(RIC_i -> label,f);
00410         putc('\0',f);
00411     } else {
00412         int i;
00413         int is_ldn = ((RIC_i -> op_code == LDN) || (RIC_i -> op_code == IDT));
00414         for (i = 0; i < 3; i++) {
00415             if (i < RIC_i -> n_args) {
00416                 int arg = RIC_i -> arg[i];
00417 
00418                 if ((arg & ARG_BIT) && (!is_ldn || i != 0)) {
00419                     arg &= ~ARG_BIT;
00420                     arg = (n == 0? 1 - arg :  arg + n - 1);
00421                 } else if (arg == RS && 
00422                            (!is_ldn || i != 0)) {
00423                     /* Must be real result reference */
00424                     arg = rs;
00425                 }
00426                 ASSERT(arg < MAXLOC || is_ldn,
00427                        "Bad opnd in inline code\n");
00428                 putw(arg, f);
00429             } else {
00430                 putw(SK, f);
00431             }
00432         }
00433     }
00434 }
00435 
00436 /* Parse a sequence of RIC instructions, represented as above.      */
00437 /* Translate arguments and RS references as above.                  */
00438 void write_RIC_seq(f, RIC_seq, n, rs)
00439 FILE * f;
00440 struct RIC_instr * RIC_seq;
00441 int n;
00442 int rs;
00443 {
00444     struct RIC_instr * p = RIC_seq;
00445 
00446     while (p != NIL) {
00447         write_RIC(f, p, n, rs);
00448         p = p -> next_instr;
00449     }
00450 }
00451 
00452 /* Write out a label operand instruction onto file f */
00453 genl_RIC(f, op, label)
00454 FILE * f;
00455 int op;
00456 char * label;
00457 {
00458     putw(op, f);
00459     fputs(label, f);
00460     putc('\0', f);
00461 }
00462 
00463 
00464 /* Write out a location operand instruction onto file f */
00465 gen_RIC(f, op, arg1, arg2, arg3)
00466 FILE * f;
00467 int op;
00468 int arg1, arg2, arg3;
00469 {
00470     ASSERT((arg1 <= MAXLOC || op == LDN || op == IDT)
00471            && arg2 <= MAXLOC && arg3 <= MAXLOC,
00472            "Bad operand to gen_RIC\n");
00473     putw(op, f);
00474     putw(arg1, f);
00475     putw(arg2, f);
00476     putw(arg3, f);
00477 }
00478 
00479 /* Copy a sequence of RIC instructions */
00480 struct RIC_instr * copy_RIC(p)
00481 struct RIC_instr * p;
00482 {
00483     if (p == RIC_nil) {
00484         return (RIC_nil);
00485     } else {
00486         struct RIC_instr * result;
00487 
00488         if (!p -> label_arg) {
00489             result = (struct RIC_instr *) gc_malloc(sizeof (struct RIC_instr));
00490             *result = *p;
00491         } else {
00492             int sz = (sizeof (struct RIC_instr)) + strlen(p -> label);
00493             result = (struct RIC_instr *)gc_malloc(sz);
00494             result -> op_code = p -> op_code;
00495             result -> n_args = 0;
00496             result -> label_arg = TRUE;
00497             strcpy(result -> label, p -> label);
00498         }
00499         result -> next_instr = copy_RIC(p -> next_instr);
00500         return(result);
00501     }
00502 }
00503 
00504 /* Destructively concatenate two sequences of RIC instructions */
00505 struct RIC_instr * cat_RIC(p,q)
00506 struct RIC_instr * p;
00507 struct RIC_instr * q;
00508 {
00509     register struct RIC_instr * r;
00510 
00511     if (p == RIC_nil) {
00512         return(q);
00513     } else {
00514         for (r = p; r -> next_instr != RIC_nil; r = r -> next_instr);
00515         r -> next_instr = q;
00516     }
00517     return(p);
00518 }
00519 
00520 /* Replace arguments in RIC sequence by consecutively numbered locations */
00521 /* (virtual registers) starting with location n.                         */
00522 /* This is done destructively.                                           */
00523 struct RIC_instr * RIC_inst_args(p, n)
00524 struct RIC_instr * p;
00525 long n;
00526 {
00527     struct RIC_instr * r;
00528     int i;
00529     boolean is_ldn;     /* First argument to current instruction is a */
00530                         /* potentially huge integer constant. Ignore  */
00531                         /* its ARG_BIT.                               */
00532     int arg_no;
00533 
00534     for (r = p; r != RIC_nil; r = r -> next_instr) {
00535         is_ldn = (r -> op_code == LDN || r -> op_code == IDT);
00536         for (i = 0; i < r -> n_args && !(r -> label_arg); i++) {
00537             if (!is_ldn || i >= 1) {
00538                 if ((r -> arg[i]) & ARG_BIT) {
00539                     arg_no = (r -> arg[i]) & ~ ARG_BIT;
00540                     r -> arg[i] = arg_no + n - 1;
00541                 }
00542             }
00543         }
00544     }
00545     return(p);
00546 }
00547 
00548 
00549 /* Replace RS in RIC sequence by the location n. */
00550 /* This is done destructively.                   */
00551 struct RIC_instr * RIC_inst_rs(p, n)
00552 struct RIC_instr * p;
00553 long n;
00554 {
00555     struct RIC_instr * r;
00556     int i;
00557     boolean is_ldn;     /* First argument to current instruction is a */
00558                         /* potentially huge integer constant. Ignore. */
00559 
00560     for (r = p; r != RIC_nil; r = r -> next_instr) {
00561         is_ldn = (r -> op_code == LDN || r -> op_code == IDT);
00562         for (i = 0; i < r -> n_args && !(r -> label_arg); i++) {
00563             if (!is_ldn || i >= 1) {
00564                 if ((r -> arg[i]) == RS) {
00565                     r -> arg[i] = n;
00566                 }
00567             }
00568         }
00569     }
00570     return(p);
00571 }
00572 
00573 /* Return the length of an instruction sequence, discounting HINT */
00574 /* instructions and optional code.                                */
00575 long RIC_len(p)
00576 struct RIC_instr * p;
00577 {
00578     struct RIC_instr * r;
00579     int i = 0;
00580 
00581     for (r = p; r != RIC_nil; r = r -> next_instr) {
00582         i++;
00583         if (r -> op_code == HINT) {
00584             i--;
00585             if (r -> arg[1] == OPT) {
00586                 i -= r -> arg[2];
00587             }
00588         }
00589     }
00590     return(i);
00591 }

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