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

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