C:/Users/Dennis/src/lang/russell.orig/src/RIC_to_C/main.c

Go to the documentation of this file.
00001 /* A simple Russell intermediate code (RIC) to C translator     */
00002 /* Stdin is assumed to be an RIC file.  We write to stdout.     */
00003 /*   We translate a function at a time.  We build up the code   */
00004 /* for the current function in the variable "code".  Note that  */
00005 /* we use a string representation allowing O(1) concatenation.  */
00006 /* Thus this is reasonably efficient.                           */
00007 /*   Also note that we read from in_file using stdio, but we    */
00008 /* write using plain UNIX system calls.                         */
00009 /*   General Russell functions expect a single argument namely  */
00010 /* a pointer to their activation record.  We expect a pointer   */
00011 /* to the global activation record to be in a local variable    */
00012 /* called GF.  Every function that needs to initializes this    */
00013 /* to the value of the global variable passed on the command    */
00014 /* line.                                                        */
00015 /*   We store expressions evaluating to virtual register        */
00016 /* contents in the virtual register table only if the virtual   */
00017 /* register is one of the two last                              */
00018 /* modified virtual registers, or if the the only registers     */
00019 /* mentioned in the expression are AR and GF.  (Arguments may   */
00020 /* also be mentioned, since they are never changed.)            */
00021 /* Expressions stored for the two last modified virtual regs    */
00022 /* are not guaranteed to be valid unless they are eventually    */
00023 /* generated in the correct order.                              */
00024 /*   All expressions stored in the virtual register table are   */
00025 /* fully parenthesized and evaluate to an integer or pointer    */
00026 /* value.  The same is true of most expressions manipulated     */
00027 /* elsewhere.                                                   */
00028 
00029 # include <fcntl.h>
00030 # include <stdio.h>
00031 # include "strings.h"
00032 # include "op_codes.h"
00033 # include "../parm.h"
00034 # include "../pass5d/codegen.h"
00035 # include "tables.h"
00036 # define GCC
00037 # undef GCC
00038 
00039 
00040 # define STDOUT_FD 1
00041 # define DELAB strcat(RROOT, "/src/delab/delab")
00042 # ifdef GCC
00043 #   define CC "/usr/local/gcc"
00044 # else
00045 #   define CC "/bin/cc"
00046 # endif
00047 
00048 char * C_name();
00049 
00050 FILE * in_file;
00051 
00052 # define STANDARD_PREFIX \
00053 concat("typedef long word;\n",  \
00054 concat("typedef word (*word_func_ptr)();\n",    \
00055 concat("extern word * GC_malloc();\n",   \
00056 concat("extern void GC_free();\n",   \
00057 concat("extern word * GC_malloc_atomic();\n",   \
00058 concat("#define alloc(sz,result) *(word **)(&result) = GC_malloc((sz)<<2)\n", \
00059 concat("#define alloc_nc(sz,result) result = GC_malloc((sz)<<2)\n", \
00060 concat("#define alloc_cw(sz,result) result = (word)GC_malloc((sz)<<2)\n", \
00061 concat("#define alloc_a(sz,result) *(word **)(&result) = GC_malloc_atomic((sz)<<2)\n", \
00062 concat("#define alloc_a_nc(sz,result) result = GC_malloc_atomic((sz)<<2)\n", \
00063 concat("#define alloc_a_cw(sz,result) result = (word)GC_malloc_atomic((sz)<<2)\n", \
00064 concat("#define abs(x) ((x) > 0? (x) : -(x))\n",    \
00065 "#define shift(x, n) ((n) < 0? (x) >> (-(n)) : (x) << (n))\n"    \
00066 ))))))))))))
00067 
00068 
00069 boolean profile = FALSE;    /* Profiling was requested.  This is ascertained */
00070                             /* from the intermediate code.                   */
00071 
00072 
00073 # define SAFE 0x40000000 /* This bit in lm or slm values indicates that it */
00074                          /* is safe to delay the update until we encounter */
00075                          /* a store to memory, an assignment to AR or GF,  */
00076                          /* or the end of a basic block.                   */
00077 # define NONE ((-1) | SAFE)
00078 
00079 long lm = NONE;     /* Last modified virtual register           */
00080 char * lm_expr;     /* The expression for the val. of virtual   */
00081                     /* reg. lm.  A "strings.h" string.          */
00082                     /* The expression is not entered in the v.  */
00083                     /* register table, since it may contain a   */
00084                     /* placeholder.                             */
00085 char * slm_ph;      /* A placeholder for the expression for slm */
00086                     /* in lm_expr.  CS_NIL if slm is not        */
00087                     /* referenced.  This will be replaced by    */
00088                     /* either a temporary name for, or an       */
00089                     /* expression for, slm, depending on        */
00090                     /* whether the assignment to slm is         */
00091                     /* explicitly generated.                    */
00092                     /* Slm_ph is always CS_NIL if slm is either */
00093                     /* NONE or MEMORY.                          */
00094                     /* Both lm_expr and slm_ph are invalid if   */
00095                     /* lm is NONE.                              */
00096 
00097 long slm = NONE;    /* Second to last modified virtual register */
00098                     /* An expression for its value is entered   */
00099                     /* in the virtual register table.  It is    */
00100                     /* not yet appended to code, since slm is   */
00101                     /* likely to be declared dead before the    */
00102                     /* next real instruction.                   */
00103 
00104 # define MEMORY ((-2) & ~SAFE)
00105                       /* Either of the above, and only one may be MEMORY, */
00106                       /* indicating that a store to memory has been       */
00107                       /* suppressed.  Such a store will always be         */
00108                       /* generated, but other code can possibly precede   */
00109                       /* it.  In particular, it is still advantagous to   */
00110                       /* delay generation of previous register stores     */
00111                       /* until we know whether the register will be live. */
00112 
00113 char * store_code;  /* Code for a pending store. If lm is MEMORY, then */
00114                     /* slm_ph may be used inside store_code.           */
00115 
00116 char * code = "";   /* Code generated so far for the body of the current function */
00117 
00118 char * extern_decls = ""; /* Collected external declarations for the current */
00119                           /* function.                                       */
00120 
00121 char * fn_name;     /* Name of current function. */
00122 
00123 int n_params = 0;   /* number of parameter refs to current fn seen so far */
00124 
00125 int n_args = 0;     /* Number of arguments to current call seen so far */
00126 
00127 boolean is_simple;  /* Current function started with a BSF */
00128 
00129 boolean gf_refd = FALSE;    /* GF is referenced in current function */
00130 
00131 boolean ar_refd = FALSE;    /* AR could conceivably have been used.  */
00132                             /* of interest only for BSF functions.   */
00133 
00134 boolean saw_ons = FALSE;    /* A HINT ONS is still pending. */
00135 
00136 int ons_depth;          /* Current number of nested active ONS allocations */
00137 
00138 char * global_ar_name;  /* Name of global activation record pointer */
00139 
00140 # define ONS_MAX 50
00141 
00142 boolean ons_stack[ONS_MAX];  /* ons_stack[i] holds if the i'th nested */
00143                              /* ONS marked allocation was implemented */
00144                              /* as a stack allocation.                */
00145 
00146 boolean suppress = FALSE;
00147                     /* Suppress code currently being scanned.  We have */
00148                     /* seen an unconditional branch and no subseqent   */
00149                     /* label.                                          */
00150 
00151 int extern_type = NONE;  /* Type of next EXT as supplied by HINT ET */
00152 
00153 boolean idt_in_progress;
00154                     /* We are translating a sequence of IDT instructions */
00155                     /* These must be translated to a single array, since */
00156                     /* the compiler assumes that adjacent data is        */
00157                     /* generated, and C compilers are known to shuffle   */
00158                     /* global declarations.                              */
00159 
00160 void finish_idt()
00161 {
00162     if (idt_in_progress) {
00163         extern_decls = concat(extern_decls,"};\n");
00164         idt_in_progress = FALSE;
00165     }
00166 }
00167 
00168 void add_idt(lbl, item)
00169 long item;
00170 char * lbl;
00171 {
00172     if (lbl != CS_NIL) {
00173         finish_idt();
00174     }
00175     if (!idt_in_progress) {
00176         if (lbl == CS_NIL) {
00177             fprintf(stderr, "Unreachable integer data: %d\n", item);
00178             lbl = "???";
00179         }
00180         idt_in_progress = TRUE;
00181         if (lbl[0] == 'L') {
00182             /* Local label that may conflict with labels in other files */
00183             extern_decls = concat(extern_decls, "static ");
00184         }
00185         extern_decls = concat(concat(extern_decls, "word "),
00186                               concat(C_name(lbl), "[] = {"));
00187     }
00188     extern_decls = concat(extern_decls, concat(itos(item), ","));
00189 }
00190 
00191 /* Convert the assembly language label s to its C form.  Currently we    */
00192 /* interpret this to mean deleting its leading underscore, if there is   */
00193 /* one, replacing embedded periods by underscores, and doubling embedded */
00194 /* underscores after the first nondeleted sequence of underscores.       */
00195 /* The last underscore is not doubled.                                   */
00196 char * C_name(s)
00197 char *s;
00198 {
00199     char * result;
00200     register char *p, *q;
00201     boolean saw_us;  /* Saw an underscore */
00202     int n_us;        /* total number of underscores in string */
00203     int n_us_so_far; /* number seen so far. */
00204     boolean saw_non_us; /* Saw a nonunderscore character after the first u.s. */
00205 
00206     n_us = 0;
00207     for (p = s; *p != '\0'; p++) {
00208         if (*p == '_') n_us++;
00209     }
00210 
00211     result = (char *) GC_malloc_atomic(strlen(s) + n_us + 1);
00212 
00213     if (*s == '_') {
00214         p = s+1;
00215         n_us_so_far = 1;
00216     } else {
00217         p = s;
00218         n_us_so_far = 0;
00219     }
00220     saw_us = FALSE;
00221     saw_non_us = FALSE;
00222     q = result;
00223     while (*p != '\0') {
00224         switch(*p) {
00225             case '.':
00226                 *q++ = '_';
00227                 break;
00228             case '_':
00229                 *q++ = '_';
00230                 n_us_so_far++;
00231                 saw_us = TRUE;
00232                 if (saw_non_us && n_us_so_far != n_us) {
00233                   *q++ = '_';
00234                 }
00235                 break;
00236             default:
00237                 *q++ = *p;
00238                 if (saw_us) {
00239                   saw_non_us = TRUE;
00240                 }
00241         }
00242         p++;
00243     }
00244     *q = '\0';
00245     return(result);
00246 }
00247 
00248 char * lbr_label = CS_NIL;   /* Label of preceding LBR instruction  */
00249 char * lba_label = CS_NIL;   /* Label of preceding LBA instruction  */
00250 
00251 char label_buf[MAXLABELSZ+1];
00252 
00253 /* Different kinds of type coercions on C expressions: */
00254 # define WORD_PTR 1
00255 # define WORD     2
00256 # define CHAR_PTR 3
00257 # define FLOAT 4
00258 /* or NONE */
00259 
00260 /* Return expr coerced to the type idicated by coercion.  Assumes expr */
00261 /* is an identifier or enclosed in parentheses.                        */
00262 /* Result is again enclosed in parentheses.                            */
00263 /* The coercion involving float expect an identifier, and works on     */
00264 /* either lhs or rhs of an assignment.                                 */
00265 char * coerce(expr, coercion)
00266 char * expr;
00267 int coercion;
00268 {
00269     char * result;
00270 
00271     switch(coercion) {
00272         case NONE:
00273             return(expr);
00274         case WORD_PTR:
00275             return(concat(concat("((word *)", expr), ")"));
00276         case WORD:
00277             return(concat(concat("((word)", expr), ")"));
00278         case CHAR_PTR:
00279             return(concat(concat("((char *)", expr), ")"));
00280         case FLOAT:
00281             return(concat(concat("(*(float *)&", expr), ")"));
00282     }
00283 }
00284 
00285 /* Generate code to store the value of slm in its assigned temporary. */
00286 /* Do the same for lm, if it refers to a store to memory.             */
00287 /* The resulting code is appended to "code".                          */
00288 /* Promote the old information related to lm to slm.                  */
00289 /* Two calls will generate all pending code for slm and lm.           */
00290 void flush_slm()
00291 {
00292     if (slm != NONE) {
00293         if (slm == MEMORY) {
00294             /* Store may invalidate stored expressions; flush */
00295             if (lm != NONE) {
00296                 code = concat(code, flush_all_non_const_except(lm & ~SAFE));
00297             } else {
00298                 code = concat(code, flush_all_non_const());
00299             }
00300             code = concat(code, store_code);
00301         } else {
00302             if (!(slm & SAFE)) {
00303                 code = concat(code, flush_vr(slm));
00304             }
00305             if (slm_ph != CS_NIL) {
00306                 set_ph(slm_ph, get_expr(slm & ~SAFE));
00307                 slm_ph = CS_NIL;
00308             }
00309         }
00310     }
00311     if (lm == MEMORY) {
00312         code = concat(code, concat(flush_all_non_const(), store_code));
00313         slm = NONE;
00314         /* Recycle dead temporaries while we know that the can't be */
00315         /* referenced.                                              */
00316             rem_tmps();
00317     } else if (lm == NONE) {
00318         slm = NONE;
00319         rem_tmps();
00320     } else {
00321         add_vr_def(lm & ~SAFE, lm_expr);
00322         slm = lm;
00323     }
00324     lm = NONE;
00325 }
00326 
00327 
00328 /* Add a virtual register as the last modified one          */
00329 /* Assumes that lm is NONE, e.g. flush_slm has been called. */
00330 /* Slm_ph is expected to be set by the invoker.             */
00331 # define add_modified_vr(result, expr, safe) \
00332         if ((slm & ~SAFE) != ((result) & ~SAFE)) {     \
00333           rem_vr_def(lm & ~SAFE);  \
00334         }  \
00335         lm = (result);  lm_expr = (expr); \
00336         if (safe) { \
00337           lm |= SAFE;   \
00338         }
00339 
00340 /* Add code for the binary operation with C prefix operator symbol "prefix"*/
00341 /* and the indicated infix and suffic operator strings.                    */
00342 /* The result is reflected in code.                                        */
00343 /* Each operand may optionally be coerced to the indicated type.  Is_float */
00344 /* indicates whether the resulting expression has type "float".            */
00345 /* Safe indicates that the constructed expression may be moved to anywhere */
00346 /* within the basic block, so long as there are no intervening updates to  */
00347 /* AR or GF.                                                               */
00348 void binary_op(result, is_float, op1, coercion1, op2, coercion2,
00349                prefix, infix, suffix, safe)
00350 long result;
00351 boolean is_float;
00352 long op1;
00353 int coercion1;
00354 long op2;
00355 int coercion2;
00356 char * prefix;
00357 char * infix;
00358 char * suffix;
00359 boolean safe;
00360 {
00361     register char * expr;
00362     char * op1_expr;
00363     char * op2_expr;
00364     char * ph = CS_NIL;
00365     boolean is_ar_ptr = (result == AR || result == GF);
00366 
00367     if (result == SK) return;
00368     /* Operands to stored expressions may get modified.   */
00369     /* Flush if  moves are still pending.                 */
00370         flush_slm();
00371     /* We claim that it is now safe to do as many flushes as we like, in */
00372     /* any order.                                                        */
00373     if (is_ar_ptr) {
00374         code = concat(code, flush_all_non_const());
00375         /* This also gets the old lm, if it was not a constant */
00376     }
00377     if (coercion1 == FLOAT) {
00378         /* Flush, so that coercion will work. */
00379         code = concat(code, flush_vr(op1));
00380         op1_expr = get_name(op1);
00381     } else if (op1 == (slm & ~SAFE)) {
00382         ph = placeholder();
00383         op1_expr = ph;
00384     } else {
00385         op1_expr = get_expr(op1);
00386     }
00387     if (coercion2 == FLOAT) {
00388         code = concat(code, flush_vr(op2));
00389         op2_expr = get_name(op2);
00390     } else if (op2 == (slm & ~SAFE)) {
00391         if (ph == CS_NIL) {
00392             ph = placeholder();
00393         } 
00394         op2_expr = ph;
00395     } else {
00396         op2_expr = get_expr(op2);
00397     }
00398     expr = concat(concat(concat("(", prefix),
00399                                 coerce(op1_expr, coercion1)),
00400                   concat(concat(infix, coerce(op2_expr, coercion2)),
00401                          concat(suffix, ")")));
00402     if (is_float) {
00403         flush_slm();        /* Flushes what was lm at entry */
00404         code = concat(code, coerce(get_name(result), FLOAT));
00405         code = concat(code, " = ");
00406         code = concat(code, expr);
00407         code = concat(code, ";\n");
00408     } else {
00409         add_modified_vr(result, expr, safe && !is_ar_ptr);
00410         slm_ph = ph;
00411     }
00412     if (is_ar_ptr) {
00413         flush_slm();
00414         code = concat(code, flush_vr(result));
00415     }
00416 }
00417 
00418 /* Add code for the unary operation with C prefix operator symbol prefix   */
00419 /* and suffix operator symbol suffix.                                      */
00420 /* The result is reflected in code.                                        */
00421 /* The operand may optionally be coerced to the indicated type.  Is_float  */
00422 /* indicates whether the resulting expression has type "float".            */
00423 void unary_op(result, is_float, op, coercion, prefix, suffix, safe)
00424 long result;
00425 boolean is_float;
00426 long op;
00427 int coercion;
00428 char * prefix;
00429 char * suffix;
00430 boolean safe;
00431 {
00432     register char * expr;
00433     char * op_expr;
00434     char * ph = CS_NIL;
00435     boolean is_ar_ptr = (result == AR || result == GF);
00436 
00437     if (result == SK) return;
00438     /* Operands to stored expressions may get modified.   */
00439     /* Flush if  moves are still pending.                 */
00440         flush_slm();
00441     /* We claim that it is now safe to do as many flushes as we like, in */
00442     /* any order.                                                        */
00443     if (is_ar_ptr) {
00444       code = concat(code, flush_all_non_const());
00445     }
00446     if (coercion == FLOAT) {
00447         /* Flush, so that coercion will work. */
00448         code = concat(code, flush_vr(op));
00449         op_expr = get_name(op);
00450     } else if (op == (slm & ~SAFE)) {
00451         ph = placeholder();
00452         op_expr = ph;
00453     } else {
00454         op_expr = get_expr(op);
00455     }
00456     expr = concat(concat(prefix, coerce(op_expr, coercion)), suffix);
00457     if (!is_empty(prefix) || ! is_empty(suffix)) {
00458         expr = concat("(", concat(expr, ")"));
00459     }
00460     if (is_float) {
00461         flush_slm();
00462         code = concat(code, coerce(get_name(result), FLOAT));
00463         code = concat(code, " = ");
00464         code = concat(code, expr);
00465         code = concat(code, ";\n");
00466     } else {
00467         add_modified_vr(result, expr, safe && !is_ar_ptr);
00468         slm_ph = ph;
00469     }
00470     if (is_ar_ptr) {
00471         flush_slm();
00472         code = concat(code, flush_vr(result));
00473     }
00474 }
00475 
00476 /* Add code for the nilary operation rhs.             */
00477 /* We assume that rhs is parenthesized or a constant. */
00478 void nilary_op(result, is_float, rhs, safe)
00479 long result;
00480 boolean is_float;
00481 char * rhs;
00482 boolean safe;
00483 {
00484     boolean is_ar_ptr = (result == AR || result == GF);
00485 
00486     if (result == SK) return;
00487     flush_slm();
00488     if (is_ar_ptr) {
00489       code = concat(code, flush_all_non_const());
00490     }
00491     if (is_float) {
00492         flush_slm();
00493         code = concat(code, coerce(get_name(result), FLOAT));
00494         code = concat(code, " = ");
00495         code = concat(code, rhs);
00496         code = concat(code, ";\n");
00497     } else {
00498         add_modified_vr(result, rhs, safe && !is_ar_ptr);
00499         slm_ph = CS_NIL;
00500     }
00501     if (is_ar_ptr) {
00502         flush_slm();
00503         code = concat(code, flush_vr(result));
00504     }
00505 }
00506 
00507 /* Write out a string s to stdout using direct write system calls. */
00508 /* The argument string is represented as in strings.[hc]           */
00509 void emit(s)
00510 char *s;  /* Not really a C string */
00511 {
00512     char * flattened;
00513     long len;
00514 
00515     flattened = flatten(s, &len);
00516     if (write(STDOUT_FD, flattened, len) < len) {
00517         fprintf(stderr, "Write to stdout failed\n");
00518         exit(1);
00519     }
00520     GC_free(flattened);
00521 }
00522 
00523 main(argc, argv)
00524 int argc;
00525 char **argv;
00526 {
00527     int opc = RTN;
00528     long arg1, arg2, arg3;
00529     char * label;   /* Label in either this instruction or preceding LBA */
00530     char * cmd;
00531     boolean has_flags;
00532     boolean bad_flag = FALSE;
00533     boolean xflag = FALSE;
00534     boolean Oflag = FALSE;
00535     char *Cfile;
00536     char *Gfile;
00537     char *sfile;
00538     int len;
00539 
00540     GC_init();
00541     /* Set up input and out files */
00542         has_flags = (argc == 5);
00543         if (has_flags) {
00544             char *s = &(argv[1][1]);
00545             
00546             while (*s) {
00547                 switch(*s) {
00548                     case 'O':
00549                         Oflag = TRUE;
00550                         break;
00551                     case 'x':
00552                         xflag = TRUE;
00553                         break;
00554                     default:
00555                         bad_flag = TRUE;
00556                 }
00557                 s++;
00558             }
00559         }
00560         if (argc < 4 || argc > 5 || bad_flag) {
00561           fprintf(stderr,
00562                   "Usage: %s [-[O][x]] file.G file.s global_ar_name\n",
00563                   argv[0]);
00564           exit(1);
00565         }
00566         if (has_flags) {
00567           Gfile = argv[2];
00568           sfile = argv[3];
00569           global_ar_name = C_name(argv[4]);
00570         } else {
00571           Gfile = argv[1];
00572           sfile = argv[2];
00573           global_ar_name = C_name(argv[3]);
00574         }
00575         len = strlen(sfile);
00576         if (len < 3 || sfile[len-2] != '.' || sfile[len-1] != 's') {
00577           fprintf(stderr, "Output file %s name should end in .s\n", sfile);
00578           exit(1);
00579         }
00580         Cfile = (char *)GC_malloc_atomic(len+1);
00581         strcpy(Cfile,sfile);
00582         Cfile[len-1] = 'c';
00583         cmd = concat(concat(DELAB, " "), Gfile);
00584         cmd = flatten(cmd, 0);
00585         in_file = popen(cmd, "r");
00586         /* Change stdout to be Cfile */
00587           (void) close(STDOUT_FD);
00588           if (open(Cfile, O_WRONLY | O_CREAT | O_TRUNC, 0644) != STDOUT_FD) {
00589             fprintf(stderr, "Can't open %s\n", Cfile);
00590             exit(1);
00591           }
00592 
00593     init_tmps();
00594     /* Emit standard prolog */
00595         emit(STANDARD_PREFIX);
00596     /* Emit declaration for global a.r. ptr.  Declare it as word array, */
00597     /* so it doesn't conflict with possible IDT generated decl.         */
00598       emit (concat("extern word ", concat(global_ar_name, "[];\n")));
00599 
00600     while (!feof(in_file)) {
00601         if (opc != LBA) {
00602             label = CS_NIL;
00603         }
00604         opc = getw(in_file);
00605         if (feof(in_file)) {
00606             /* compensate for strange feof semantics */
00607             break;
00608         }
00609         if (opc < 0 && opc > N_OP_CODES) {
00610             fprintf(stderr, "Bad op code\n");
00611             exit(1);
00612         }
00613         if (opc <= MAX_LABEL_OP) {
00614             char *p = label_buf;
00615             int c;
00616             int i = 0;
00617             
00618             while ((c = getc(in_file)) != '\0' && c != EOF) {
00619                 *p++ = c;
00620                 if (++i >= MAXLABELSZ) {
00621                     fprintf(stderr, "Label too long\n");
00622                     p = label_buf;
00623                 }
00624             }
00625             *p = '\0';
00626             label = (char *) GC_malloc_atomic(i+1);
00627             strcpy(label, label_buf);
00628         } else {
00629             arg1 = getw(in_file);
00630             arg2 = getw(in_file);
00631             arg3 = getw(in_file);
00632             if (!gf_refd) {
00633                 if (arg1 == GF && opc != LDN && opc != UDC
00634                     && opc != CLC && opc != HINT && opc != ARG
00635                     && opc != GAR) {
00636                     gf_refd = TRUE;
00637                 }
00638                 if (arg2 == GF && opc != LDI && opc != STI
00639                     && opc != LDC && opc != HINT && opc != CLI
00640                     && opc != DCL) {
00641                     gf_refd = TRUE;
00642                 }
00643                 if (arg3 == GF && opc != HINT) {
00644                     gf_refd = TRUE;
00645                 }
00646             }
00647         }
00648 
00649         if (suppress) {
00650             if (opc != LBL && opc != DCL && opc != UDC) {
00651                 /* Don't generate dead code. */
00652                 continue;
00653             }
00654         }
00655 
00656         switch(opc) {
00657             case BR:
00658                 flush_slm();
00659                 code = concat(code, flush_all_exprs());
00660                 rem_tmps();
00661                 code = concat(concat(code, "goto "), concat(C_name(label), ";\n"));
00662                 suppress = TRUE;
00663                 break;
00664 
00665             case BRT:
00666                 flush_slm();
00667                 code = concat(code, flush_all_except(TL));
00668                 code = concat(concat(concat(code, "if ("),
00669                                      concat(get_expr(TL),") goto ")),
00670                               concat(C_name(label), ";\n"));
00671                 /* TL is now known to be dead */
00672                 rem_vr_def(TL);
00673                 rem_tmps();
00674                 break;
00675 
00676             case BRF:
00677                 flush_slm();
00678                 code = concat(code, flush_all_except(TL));
00679                 code = concat(concat(concat(code, "if (!"),
00680                                      concat(get_expr(TL),") goto ")),
00681                               concat(C_name(label), ";\n"));
00682                 /* TL is now known to be dead */
00683                 rem_vr_def(TL);
00684                 rem_tmps();
00685                 break;
00686 
00687             case CLL:
00688             case ERR:
00689             case CLC:
00690                 {
00691                     char * expr;
00692                     char * args;
00693                     boolean lm_is_arg = ((lm & ARG_FLAG) &&
00694                                          lm != MEMORY && lm != NONE);
00695                     boolean slm_is_arg = ((slm & ARG_FLAG) &&
00696                                          slm != MEMORY && slm != NONE);
00697                 
00698                     /* Make sure that only "safe" expressions are in v.r. */
00699                     /* table.  Anything else will interact badly with     */
00700                     /* Call/cc.  Avoid flushing arguments, by delaying    */
00701                     /* such flushes until after the argument list is      */
00702                     /* built, and the death of the argument v. regs has   */
00703                     /* been recorded.                                     */
00704                       if (!lm_is_arg) {
00705                         flush_slm();
00706                         flush_slm();
00707                         args = arg_list(n_args);
00708                       } else if (!slm_is_arg) {
00709                         flush_slm();
00710                         args = arg_list(n_args);
00711                         flush_slm();
00712                       } else {
00713                         if (slm_ph != CS_NIL) {
00714                             fprintf(stderr, "Bad slm_ph value\n");
00715                             abort();
00716                         }
00717                         /* Add last arg def to table, so arg_list can */
00718                         /* find it.                                   */
00719                         /* This is safe, since the order of the two   */
00720                         /* argument loads is irrelevant.              */
00721                         /* The definition will be removed by arg_list */
00722                             add_vr_def(lm & ~SAFE, lm_expr);
00723                             lm = NONE;
00724                         args = arg_list(n_args);
00725                         flush_slm();
00726                       }
00727                     if (opc == CLL && n_args != 1) {
00728                       fprintf(stderr, "Wrong number of args (%d) to CLL\n",
00729                               n_args);
00730                     }
00731                     if (opc == CLC) {
00732                       if (n_args != arg1) {
00733                         fprintf(stderr,
00734                                 "Wrong number of args (%d vs %d) to CLC\n",
00735                                 n_args, arg1);
00736                       }
00737                       label = lba_label;
00738                     }
00739                     /* label already has function type in the C program */
00740                     expr = concat(C_name(label), "(");
00741                     /* Add arguments to call */
00742                       expr = concat(expr, args);
00743                     expr = concat(expr, ")");
00744                     rem_vr_def(RL);  /* Remove old definition */
00745                     code = concat(concat(code, "RL = (word)"),
00746                                   concat(expr, ";\n"));
00747                     n_args = 0;
00748                 }
00749                 break;
00750 
00751             case LBL:
00752                 suppress = FALSE;
00753                 flush_slm();
00754                 code = concat(code, flush_all_exprs());
00755                 code = concat(concat(code, C_name(label)), ":\n");
00756                 break;
00757 
00758             case EXT:
00759                 finish_idt();
00760                 switch(extern_type) {
00761                   case DCL_INT:
00762                     extern_decls = concat(concat(extern_decls, "extern word "),
00763                                           concat(C_name(label), "[];\n"));
00764                     break;
00765                   case DCL_ADDR:
00766                     extern_decls = concat(concat(extern_decls, "extern word *"),
00767                                           concat(C_name(label), "[];\n"));
00768                     break;
00769                   case DCL_FLOAT:
00770                     extern_decls = concat(concat(extern_decls, "extern float "),
00771                                           concat(C_name(label), "[];\n"));
00772                   case DCL_DBL_FLOAT:
00773                     extern_decls = concat(concat(extern_decls, "extern double "),
00774                                           concat(C_name(label), "[];\n"));
00775                     break;
00776                   case NONE:
00777                     /* It is a function */
00778                     extern_decls = concat(concat(extern_decls, "extern word "),
00779                                           concat(C_name(label), "();\n"));
00780                     break;
00781                   default:
00782                     fprintf(stderr, "Bad type for EXT\n");
00783                     break;
00784                 }
00785                 extern_type = NONE;
00786                 break;
00787 
00788             case LBA:
00789                 /* Simply remember label for next instruction */
00790                   lba_label = label;
00791                 break;
00792 
00793             case BFN:
00794                 /* Defer generating the header until we have seen */
00795                 /* all of the function.                           */
00796                 fn_name = C_name(label);
00797                 n_params = 0;
00798                 is_simple = FALSE;
00799                 gf_refd = FALSE;
00800                 ar_refd = FALSE;
00801                 break;
00802 
00803             case TFB:
00804             case TFE:
00805                 fprintf(stderr, "Tracing not yet implemented\n");
00806                 break;
00807 
00808             case PRO:
00809                 /* Profiling is handled by the C compiler */
00810                 profile = TRUE;
00811                 break;
00812 
00813             case ADT:
00814                 fprintf(stderr, "Obsolete ADT instruction encountered\n");
00815                 exit(1);
00816 
00817             case BSF:
00818                 finish_idt();
00819                 fn_name = C_name(label);
00820                 n_params = 0;
00821                 is_simple = TRUE;
00822                 gf_refd = FALSE;
00823                 ar_refd = FALSE;
00824                 break;
00825 
00826             case LBR:
00827                 lbr_label = label;
00828                 break;
00829 
00830             case DDT:
00831                 finish_idt();
00832                 if (lba_label == CS_NIL) {
00833                   fprintf(stderr, "Unlabelled double data\n");
00834                 } else {
00835                   if (lba_label[0] == 'L') {
00836                      extern_decls = concat(extern_decls, "static ");
00837                   }
00838                   extern_decls = concat(concat(extern_decls, "double "),
00839                                         concat(concat(C_name(lba_label), "[] = {"),
00840                                                concat(label, "};\n")));
00841                 }
00842                 break;
00843 
00844             case FDT:
00845                 finish_idt();
00846                 if (lba_label == CS_NIL) {
00847                   fprintf(stderr, "Unlabelled float data\n");
00848                 } else {
00849                   if (lba_label[0] == 'L') {
00850                      extern_decls = concat(extern_decls, "static ");
00851                   }
00852                   extern_decls = concat(concat(extern_decls, "float "),
00853                                         concat(concat(C_name(lba_label), "[] = {"),
00854                                                concat(label, "};\n")));
00855                 }
00856                 break;
00857 
00858             /* Instructions with numeric or v. register args: */
00859 
00860             case DCL:
00861                 add_undef_vr(arg1);
00862                 if (lbr_label != CS_NIL) {
00863                     code = concat(concat("/* ", lbr_label),
00864                                   concat(concat(" ~ ", get_name(arg1)),
00865                                          concat(" */\n", code)));
00866                     lbr_label = CS_NIL;
00867                 }
00868                 break;
00869 
00870             case UDC:
00871                 if (arg1 == (lm & ~SAFE)) {
00872                     lm = NONE;
00873                 }
00874                 if (arg1 == (slm & ~SAFE)) {
00875                     if (lm != NONE && slm_ph != CS_NIL) {
00876                         /* Still need the expression. Substitute now, */
00877                         /* since we know slm is otherwise dead.       */
00878                             set_ph(slm_ph, get_expr(arg1));
00879                             slm_ph = CS_NIL;
00880                     }
00881                     slm = NONE;
00882                 }
00883                 rem_vr(arg1);
00884                 break;
00885 
00886             case ALH:
00887                 if (arg2 == SK) break;
00888                 flush_slm();
00889                 if (arg1 != arg2) rem_vr_def(arg2);
00890                 flush_slm();
00891                 {
00892                   char * sz = get_expr(arg1);
00893                   char first_c;
00894                   boolean is_number;
00895 
00896                   GET_FIRST(sz, first_c);
00897                   is_number = (first_c >= '0' && first_c <= '9');
00898                   if (!is_number) {
00899                     /* Make sure that sz doesn't involve arg2's location */
00900                     /* unless arg1 = arg2                                */
00901                       code = concat(code, flush_vr(arg1));
00902                       sz = get_expr(arg1);
00903                   }
00904                   if ( saw_ons && is_number ) {
00905                     ons_stack[ons_depth++] = TRUE;
00906                     code = concat(concat(code, "{ word NS["),
00907                                   concat(concat(sz,"];\n"),
00908                                          concat(get_name(arg2), " = (word) NS;\n")));
00909                   } else {
00910                     if (saw_ons) {
00911                         ons_stack[ons_depth++] = FALSE;
00912                     }
00913                     {
00914                       char * ac;
00915                       char * sz_expr;
00916 
00917                       if (!is_number && arg1 == arg2) {
00918                         sz_expr = "sz";
00919                       } else {
00920                         sz_expr = sz;
00921                       }
00922                       if (arg2 == RL) {
00923                         /* Not all C compilers allow l-value casts. */
00924                         /* Generate allocation code that knows that */
00925                         /* RL has type word.                        */
00926                         ac = "alloc_cw(";
00927                       } else if (arg2 == AR || arg2 == GF) {
00928                         ac = "alloc_nc(";
00929                       } else {
00930                         ac = "alloc(";
00931                       }
00932                       ac = concat(ac,
00933                                   concat(concat(sz_expr, ","),
00934                                          concat(get_name(arg2), ");")));
00935                       if (!is_number && arg1 == arg2) {
00936                         ac = concat(concat("{ word sz = (word)", sz),
00937                                     concat(";", concat(ac, "}")));
00938                       }
00939                       code = concat(code, concat(ac, "\n"));
00940                     }
00941                   }
00942                   if (ons_depth >= ONS_MAX - 2) {
00943                       fprintf(stderr, "Too many nested allocations\n");
00944                       exit(1);
00945                   }
00946                 }
00947                 if (arg1 == arg2) rem_vr_def(arg2);
00948                 saw_ons = FALSE;
00949                 break;
00950 
00951             case GAR:
00952                 if (arg2 != SK) {
00953                   nilary_op(arg2, FALSE, par_name(arg1), TRUE);
00954                 }
00955                 if (arg1 > n_params) n_params = arg1;
00956                 break;
00957 
00958             case ALS:
00959                 fprintf(stderr, "Encountered ALS instruction\n");
00960                 exit(1);
00961 
00962             case LDI:
00963                 unary_op(arg3, FALSE, arg1, WORD_PTR,
00964                          "", concat("[", concat(itos(arg2), "]")),
00965                          (arg1 == AR || arg1 == GF));
00966                 break;
00967 
00968             case STI:
00969                 if (arg1 != SK) {
00970                     char * arg1_expr;
00971                     char * arg3_expr;
00972                     char * ph = CS_NIL;
00973 
00974                     flush_slm();
00975                     if (arg1 == (slm & ~SAFE)) {
00976                         ph = placeholder();
00977                         arg1_expr = ph;
00978                     } else {
00979                         arg1_expr = get_expr(arg1);
00980                     }
00981                     if (arg3 == (slm & ~SAFE)) {
00982                         if (ph == CS_NIL) {
00983                             ph = placeholder();
00984                         }
00985                         arg3_expr = ph;
00986                     } else {
00987                         arg3_expr = get_expr(arg3);
00988                     }
00989                     lm = MEMORY;
00990                     slm_ph = ph;
00991                     store_code = concat(concat("((word *)", arg1_expr),
00992                                         concat(")[(word)",
00993                                                concat(itos(arg2), "] = (word)")));
00994                     store_code = concat(store_code,
00995                                         concat(arg3_expr, ";\n"));
00996                 }
00997                 break;
00998 
00999             case CLI:
01000                 {
01001                     char * expr;
01002                     char * fn;
01003                     char * args;
01004                     boolean lm_is_arg = ((lm & ARG_FLAG) &&
01005                                          lm != MEMORY && lm != NONE);
01006                 
01007                     /* Make sure that only "safe" expressions are in v.r. */
01008                     /* table.  Anything else will interact badly with     */
01009                     /* Call/cc.  Avoid flushing arguments, by delaying    */
01010                     /* such flushes until after the argument list is      */
01011                     /* built, and the death of the argument v. regs has   */
01012                     /* been recorded.                                     */
01013                       flush_slm();
01014                       if (!lm_is_arg) {
01015                         flush_slm();
01016                         args = arg_list(n_args);
01017                       } else {
01018                         args = arg_list(n_args);
01019                         flush_slm();
01020                       }
01021                     if (n_args != 1) {
01022                       fprintf(stderr, "Wrong number of args (%d) to CLI\n",
01023                               n_args);
01024                     }
01025                     fn = concat(concat("((word_func_ptr *)", get_expr(arg1)),
01026                                 concat(")[(word)",
01027                                        concat(itos(arg2), "]")));
01028                     expr = concat(fn, "(");
01029                     /* Add arguments to call */
01030                       expr = concat(expr, args);
01031                     expr = concat(expr, ")");
01032                     rem_vr_def(RL);  /* Remove old definition */
01033                     code = concat(concat(code, "RL = (word)"),
01034                                   concat(expr, ";\n"));
01035                     n_args = 0;
01036                 }
01037                 break;
01038 
01039             case LDN:
01040                 nilary_op(arg2, FALSE, itos(arg1), TRUE);
01041                 break;
01042 
01043             case RTN:
01044                 {
01045                     char * header;
01046                     char * par_list;
01047 
01048                     if (fn_name == CS_NIL) {
01049                         fprintf(stderr, "Anonymous function\n");
01050                         fn_name = "?anonymous?";
01051                     }
01052                     if (ons_depth != 0) {
01053                         fprintf(stderr,
01054                                 "Nonmatching stack (de)allocations %d\n",
01055                                 ons_depth);
01056                         exit(1);
01057                     }
01058                     /* Make sure that there are no pending stores, */
01059                     /* UDCs, or incomplete declarations.           */
01060                       flush_slm();
01061                       rem_tmps();
01062                       finish_idt();
01063                     /* Complete and then emit code for the function */
01064                       code = concat(concat(code, "return((word)"),
01065                                     concat(get_expr(RL), ");\n}\n\n"));
01066                       code = concat(tmp_decls(max_tmp), code);
01067                       lm = NONE;
01068                       if (gf_refd) {
01069                         code = concat(concat(
01070                                         "register word * GF = ((word *)(",
01071                                         global_ar_name),
01072                                       concat("[0]));\n", code));
01073                       }
01074                       if (ar_refd && is_simple) {
01075                         code = concat("register word * AR;\n", code);
01076                       }
01077                       code = concat("word TL;\n", code);
01078                       code = concat("register word RL;\n", code);
01079                       header = concat ("\nword ", concat(fn_name, "("));
01080                       if (is_simple) {
01081                         header = concat(header,
01082                                         (par_list = par_names(n_params)));
01083                       } else {
01084                         header = concat(header, "AR");
01085                       }
01086                       header = concat(header, ")\n");
01087                       if (is_simple) {
01088                         if (n_params > 0) {
01089                           header = concat(concat(header, "word "),
01090                                           concat(par_list, ";\n{\n"));
01091                         } else {
01092                           header = concat(header, "{\n");
01093                         }
01094                       } else {
01095                         header = concat(header, "register word * AR;\n{\n");
01096                       }
01097                       code = concat(extern_decls, concat(header, code));
01098                       emit(code);
01099 
01100                     /* Get things set up for the next function. */
01101                       rem_vr_def(RL);
01102                       rem_vr_def(TL);
01103                       reset_tmps();
01104                       fn_name = CS_NIL;
01105                       n_params = 0;
01106                       gf_refd = FALSE;
01107                       code = "";
01108                       extern_decls = "";
01109                 }
01110                 break;
01111 
01112             case LDL:
01113                 finish_idt();
01114                 /* Labels are attached to either functions or arrays */
01115                 /* Thus C semantics imply that we implicitly get an  */
01116                 /* address.                                          */
01117                 if (lba_label == CS_NIL) {
01118                     fprintf(stderr, "No LBA preceding LDL\n");
01119                     exit(1);
01120                 }
01121                 nilary_op(arg1, FALSE, coerce(C_name(lba_label), WORD_PTR), TRUE);
01122                 break;
01123 
01124             case MOV:
01125                 unary_op(arg2, FALSE, arg1, NONE, "", "",
01126                          (arg1 == AR || arg1 == GF));
01127                 break;
01128 
01129             case TAR:
01130                 fprintf(stderr, "Tracing not yet implemented\n");
01131                 break;
01132 
01133             case PSH:
01134                 fprintf(stderr, "Encountered PSH instruction\n");
01135                 exit(1);
01136 
01137             case ADP:
01138                 { 
01139                   char * displ;
01140                   boolean is_number;
01141                   char first_c;
01142                   boolean is_ar_ptr = (arg1 == AR || arg1 == GF);
01143 
01144                   if (is_ar_ptr) {
01145                     displ = get_expr(arg2);
01146                     /* Determine whether displ is a numeric constant.  */
01147                     /* Note that a more complex expression starting    */
01148                     /* with a number would be enclosed in parentheses. */
01149                       GET_FIRST(displ, first_c);
01150                       is_number = (first_c == '-'
01151                                    || first_c >= '0' && first_c <= '9');
01152                   }
01153                   binary_op(arg3, FALSE, arg1, WORD_PTR, arg2, WORD,
01154                            "", "+", "",
01155                            is_ar_ptr && is_number);
01156                 }
01157                 break;
01158 
01159             /* case CLC:  handled above */
01160 
01161             case ALA:
01162                 if (arg2 == SK) break;
01163                 flush_slm();
01164                 if (arg1 != arg2) rem_vr_def(arg2);
01165                 flush_slm();
01166                 {
01167                   char * sz = get_expr(arg1);
01168                   char first_c;
01169                   boolean is_number;
01170 
01171                   GET_FIRST(sz, first_c);
01172                   is_number = (first_c >= '0' && first_c <= '9');
01173                   if (!is_number) {
01174                     /* Make sure that sz doesn't involve arg2's location */
01175                     /* unless arg1 = arg2                                */
01176                       code = concat(code, flush_vr(arg1));
01177                       sz = get_expr(arg1);
01178                   }
01179                   if ( saw_ons && is_number ) {
01180                     ons_stack[ons_depth++] = TRUE;
01181                     code = concat(concat(code, "{ word NS["),
01182                                   concat(concat(sz,"];\n"),
01183                                          concat(get_name(arg2), " = (word) NS;\n")));
01184                   } else {
01185                     if (saw_ons) {
01186                         ons_stack[ons_depth++] = FALSE;
01187                     }
01188                     {
01189                       char * ac;
01190                       char * sz_expr;
01191 
01192                       if (!is_number && arg1 == arg2) {
01193                         sz_expr = "sz";
01194                       } else {
01195                         sz_expr = sz;
01196                       }
01197                       if (arg2 == RL) {
01198                         /* Not all C compilers allow l-value casts. */
01199                         /* Generate allocation code that knows that */
01200                         /* RL has type word.                        */
01201                         ac = "alloc_a_cw(";
01202                       } else if (arg2 == AR || arg2 == GF) {
01203                         ac = "alloc_a_nc(";
01204                       } else {
01205                         ac = "alloc_a(";
01206                       }
01207                       ac = concat(ac,
01208                                   concat(concat(sz_expr, ","),
01209                                          concat(get_name(arg2), ");")));
01210                       if (!is_number && arg1 == arg2) {
01211                         ac = concat(concat("{ word sz = (word)", sz),
01212                                     concat(";", concat(ac, "}")));
01213                       }
01214                       code = concat(code, concat(ac, "\n"));
01215                     }
01216                   }
01217                   if (ons_depth >= ONS_MAX - 2) {
01218                       fprintf(stderr, "Too many nested allocations\n");
01219                       exit(1);
01220                   }
01221                 }
01222                 if (arg1 == arg2) rem_vr_def(arg2);
01223                 saw_ons = FALSE;
01224                 break;
01225 
01226             case HINT:
01227                 switch(arg1) {
01228                     case OPT:
01229                         /* We assume that this was taken care of in an */
01230                         /* earlier pass, namely RICfilter.             */
01231                         break;
01232                     case NP:
01233                     case AL:
01234                         /* Not relevant */
01235                         break;
01236                     case DEA:
01237                         /* Make sure no stores or references through arg2 */
01238                         /* are pending                                    */
01239                           flush_slm();
01240                           if (arg2 == AR || arg2 == GF) {
01241                               code = concat(code, flush_all_non_const());
01242                           } else {
01243                               flush_slm();
01244                           }
01245                         if (saw_ons) {
01246                           saw_ons = FALSE;
01247                           if (ons_stack[--ons_depth]) {
01248                             code = concat(code, "}\n");
01249                             break;
01250                           }
01251                         }
01252                         code = concat(concat(code, "GC_free("),
01253                                       concat(get_expr(arg2), ");\n"));
01254                         break;
01255                     case NSC:
01256                     case STSZ:
01257                     case PT:
01258                         /* Not relevant */
01259                         break;
01260                     case DEAD:
01261                         if (arg2 == (lm & ~SAFE)) {
01262                             lm = NONE;
01263                         }
01264                         if (arg2 == (slm & ~SAFE)) {
01265                             if (lm != NONE && slm_ph != CS_NIL) {
01266                               /* Still need the expression. Substitute now, */
01267                               /* since we know slm is otherwise dead.       */
01268                                 set_ph(slm_ph, get_expr(arg2));
01269                                 slm_ph = CS_NIL;
01270                             }
01271                             slm = NONE;
01272                         }
01273                         rem_vr_def(arg2);
01274                         break;
01275                     case GFU:
01276                         if (is_simple) {
01277                           /* Make sure AR gets declared.       */
01278                           /* We figure the rest out ourselves. */
01279                           ar_refd = TRUE;
01280                         }
01281                         break;
01282                     case LIVE:
01283                         /* We assert that there are no suppressed      */
01284                         /* procedure calls or allocations.  Thus it is */
01285                         /* safe to move up the effect of the hint to   */
01286                         /* the end of the code generated so far.       */
01287 #                       ifdef GCC
01288                           /* generate a bogus machine instruction requiring  */
01289                           /* the value of interest. This forces the compiler */
01290                           /* to see it as live, we hope.                     */
01291                           code = concat(code, "# ifdef __GNUC__\n");
01292                           code = concat(code, "asm volatile(\" \": : \"g\" (");
01293                           code = concat(code, get_expr(arg2));
01294                           code = concat(code, "));\n");
01295                           code = concat(code, "# endif\n");
01296 #                       else
01297                           /* Should really be passed to the C compiler, */
01298                           /* but there is no good way to do that, in    */
01299                           /* general.                                   */
01300 #                       endif
01301                         break;
01302                     case ET:
01303                         extern_type = arg2;
01304                         break;
01305                     case ONS:
01306                         saw_ons = TRUE;
01307                         break;
01308                 }
01309                 break;
01310 
01311             case ARG:
01312                 {
01313                   char * rhs;
01314                   boolean is_const;
01315                   char first_c;
01316 
01317                   if (arg2 == (lm & ~ SAFE)) {
01318                       rhs = lm_expr;
01319                   } else {
01320                       rhs = get_expr(arg2);
01321                   }
01322                   GET_FIRST(rhs, first_c);
01323                   is_const = (first_c == '-' || first_c == '"'
01324                                || first_c >= '0' && first_c <= '9');
01325                   add_undef_vr(ARGLOC(arg1));
01326                   unary_op(ARGLOC(arg1), FALSE, arg2, WORD, "", "",
01327                             (is_const || arg2 == AR || arg2 == GF
01328                              || is_param(first_c)));
01329                   if (n_args < arg1) n_args = arg1;
01330                 }
01331                 break;
01332 
01333             case ADI:
01334                 binary_op(arg3, FALSE, arg1, WORD, arg2, WORD, "", "+", "", FALSE);
01335                 break;
01336 
01337             case SBI:
01338                 binary_op(arg3, FALSE, arg1, WORD, arg2, WORD, "", "-", "", FALSE);
01339                 break;
01340 
01341             case MLI:
01342                 binary_op(arg3, FALSE, arg1, WORD, arg2, WORD, "", "*", "", FALSE);
01343                 break;
01344 
01345             case DVI:
01346                 binary_op(arg3, FALSE, arg1, WORD, arg2, WORD, "", "/", "", FALSE);
01347                 break;
01348 
01349             case NGI:
01350                 unary_op(arg2, FALSE, arg1, WORD, "-", "", FALSE);
01351                 break;
01352 
01353             case IDT:
01354                 add_idt(lba_label, arg1);
01355                 break;
01356 
01357             case EQI:
01358                 binary_op(arg3, FALSE, arg1, WORD, arg2, WORD, "", "==", "", FALSE);
01359                 break;
01360 
01361             case LTI:
01362                 binary_op(arg3, FALSE, arg1, WORD, arg2, WORD, "", "<", "", FALSE);
01363                 break;
01364 
01365             case GTI:
01366                 binary_op(arg3, FALSE, arg1, WORD, arg2, WORD, "", ">", "", FALSE);
01367                 break;
01368 
01369             case NEI:
01370                 binary_op(arg3, FALSE, arg1, WORD, arg2, WORD, "", "!=", "", FALSE);
01371                 break;
01372 
01373             case LEI:
01374                 binary_op(arg3, FALSE, arg1, WORD, arg2, WORD, "", "<=", "", FALSE);
01375                 break;
01376 
01377             case GEI:
01378                 binary_op(arg3, FALSE, arg1, WORD, arg2, WORD, "", ">=", "", FALSE);
01379                 break;
01380 
01381             case SHI:
01382                 binary_op(arg3, FALSE, arg1, WORD, arg2, WORD, "shift(", ",", ")", FALSE);
01383                 break;
01384 
01385             case ABI:
01386                 unary_op(arg2, FALSE, arg1, WORD, "abs(", ")", FALSE);
01387                 break;
01388 
01389             case TRU:
01390                 nilary_op(arg1, FALSE, "1", TRUE);
01391                 break;
01392 
01393             case FLS:
01394                 nilary_op(arg1, FALSE, "0", TRUE);
01395                 break;
01396 
01397             case LDS:
01398                 {
01399                     char * string;
01400                     if (lba_label == CS_NIL) {
01401                         fprintf(stderr, "LDS: missing label\n");
01402                         lba_label = "???";
01403                     }
01404                     string = concat("\"", concat(rmcntrl(lba_label), "\""));
01405                     nilary_op(arg1, FALSE, string, TRUE);
01406                 }
01407                 break;
01408 
01409             case LDC:
01410                 binary_op(arg3, FALSE, arg1, CHAR_PTR, arg2, WORD,
01411                           "", "[", "]", FALSE);
01412                 break;
01413 
01414             case AND:
01415                 binary_op(arg3, FALSE, arg1, WORD, arg2, WORD, "", "&", "", FALSE);
01416                 break;
01417 
01418             case OR:
01419                 binary_op(arg3, FALSE, arg1, WORD, arg2, WORD, "", "|", "", FALSE);
01420                 break;
01421 
01422             case NOT:
01423                 unary_op(arg2, FALSE, arg1, WORD, "!", "", FALSE);
01424                 break;
01425 
01426             case ADF:
01427 
01428             case SBF:
01429 
01430             case MLF:
01431 
01432             case DVF:
01433 
01434             case NGF:
01435 
01436             case EXF:
01437 
01438             default:
01439                 fprintf(stderr, "Unrecognized op code: %d\n", opc);
01440                 exit(1);
01441         }
01442         if (opc != LBA) {
01443             lba_label = CS_NIL;
01444         }
01445     }
01446     /* Emit any declarations that are still pending */
01447       finish_idt();
01448       if (!is_empty(extern_decls)) {
01449         emit(extern_decls);
01450       }
01451     /* Compile the result */
01452     {
01453         (void) close(STDOUT_FD);
01454         if (open("/dev/tty", O_WRONLY | O_CREAT | O_TRUNC, 0644) != STDOUT_FD) {
01455             fprintf(stderr, "/dev/tty reopen failed - continuing\n");
01456         }
01457         pclose(in_file);
01458         /* Replace ourselves with a cc process.  It is important that */
01459         /* all subprocesses have been waited for at this point, since */
01460         /* cc neglects to pay attention to values returned by the     */
01461         /* wait system call.                                          */
01462             if (profile) {
01463                 execl(CC, "cc", "-S", Oflag? "-O" : "-g" , "-p", "-o", sfile, Cfile, 0);
01464             } else {
01465                 execl(CC, "cc", "-S", Oflag? "-O" : "-g" , "-o", sfile, Cfile, 0);
01466             }
01467             fprintf(stderr, "Couldn't exec %s\n", CC);
01468             exit(1);
01469     }
01470 }

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