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

Go to the documentation of this file.
00001 /* 
00002  *  This is the zeroth approximation to the Russell code generator.
00003  *  I have started with printastx.c from pass5a and have begun to hack.
00004  *      Jim Hook  27 March 1982 
00005  *  Trying to revive this code.  Switched from display to static chain.
00006  *  Adding stack based calls, in-line calls, and type modification.
00007  *      Hans Boehm 7 Feb 1984
00008  *  Adding type constructions, etc.
00009  *      Hans Boehm 15 June 1984
00010  *  Added jsb calls, etc.
00011  *      Hans Boehm 6 Oct 1984
00012  *  Adding stack based variable allocation.
00013  *      Hans Boehm 4 June 1986
00014  */
00015 # include "parm.h"
00016 # include <stdio.h>
00017 # include "stree/ststructs.mh"
00018 # include "codeutil.h"
00019 # include "pass4/sigs.h"
00020 # include "pass3/is_local.h"
00021 # include "../runtime/runtime.h"
00022 
00023 # define UNDEF (HEAPLIM+1)  /* runtime rep of undefined value */
00024 
00025 extern int yydebug;
00026 extern int yynerrs;
00027 
00028 extern boolean Pflag;  /* Generate profiling code */
00029 extern boolean Tflag;  /* Generate trace code */
00030 extern boolean Vflag;  /* Print optimization information */
00031 extern boolean hflag;  /* Put activation reords on heap */
00032 
00033 extern char * entry_name; /* "" for main compilation */
00034 
00035 boolean mentions_r11();
00036 
00037 void type_expr();  /* generate code for type in record element */
00038 
00039 char str_code_buf[MAXSTRCODELEN]; /* used for strings, "special" fns */
00040                   /* and by find_inline              */
00041                   /* and for object file names       */
00042 
00043 extern int Ventry_mask,Vgc_mask;
00044 extern int Vlevel;   /* current static nesting level */
00045  
00046 extern NODE * Vcurrent;    /* Function currently being compiled */
00047 extern FILE * Voutfile;
00048 
00049 void Vexpression();
00050 
00051 /* Generate code for the application p */
00052 Vappl(p)
00053 NODE *p;
00054 {
00055     register NODE *v;
00056     register int argcount;
00057     char * in_line;     /* in-line code, NIL if not known */
00058     boolean stack_call; /* use stack for activation rec.  */
00059     char * size_reg;    /* Name of register for a.r. size */
00060                         /* used only for stack based call */
00061     char * ar_reg;      /* Register with pointer to a.r.  */
00062                         /* used only in non-stack call    */
00063     boolean in_memory;  /* size_reg or ar_reg is not a reg*/
00064     NODE * construction  =  p -> ap_operator -> signature
00065                               -> fsig_construction;
00066     boolean slink_known; /* used only if construction is  */
00067                          /* known.  Indicates that static */
00068                          /* can be gotten by indirecting  */
00069                          /* through current static link.  */
00070     NODE * result_sig = p -> signature;
00071     NODE * op_sig = p -> ap_operator -> signature;
00072     int op_kind = p -> ap_operator -> kind;
00073     long op_special = op_sig -> fsig_special;
00074     extern boolean is_id(); /* defined in pass5d */
00075     boolean op_is_id = is_id(p -> ap_operator);
00076     boolean appl_impure = impure(op_sig);
00077     boolean op_impure = (appl_impure && !op_is_id)
00078                         || calls_put(p -> ap_operator);
00079     int i;
00080 
00081 
00082     /* Handle some special operations */
00083       switch (special_tp(op_special)) {
00084         case STD_VALUEOF:
00085           {
00086             NODE * arg = first(p -> ap_args);
00087 
00088             if (arg -> kind == LETTERID 
00089                 && arg -> id_last_definition -> kind == DECLARATION
00090                 && (arg -> id_last_definition -> decl_special & VAR_ON_STACK)) {
00091                 register NODE * v;
00092                 char * r10 = "r10";
00093                 char * display_reg; /* name of reg used for a.r. pointer */
00094 
00095                 v = arg -> id_last_definition;
00096                 putcomment1("\t\t\t# Value of Identifier %s",
00097                             getname(arg -> id_str_table_index));
00098                 DISPLAY ( display_reg, v -> level, r10,
00099                           "# display entry in place");
00100                 if (display_reg == r10) Ventry_mask |= R10;
00101                 PUSH_DISP (display_reg, v->displacement,
00102                                         "# referenced object");
00103                 return;
00104             } else {
00105                 break;
00106             }
00107           }
00108         case ARRAY_VALUEOF:
00109           if (Vflag) {
00110               printf("Using fast array ValueOf inside %s\n",
00111                      Vcurrent -> fc_code_label);
00112           }
00113           Vexpression(first(p -> ap_args));
00114           SET_GC_INFO;
00115           CODE("\t.globl\t_fast_Array_ValueOf");
00116           CODE("\tcalls\t$1,_fast_Array_ValueOf");
00117           CODE("\tpushl\tr0\n");
00118           return;
00119         case ARRAY_STD_NEW:
00120         case ARRAY_PTR_NEW:
00121           {
00122             long size_val = special_val(op_special);
00123             NODE * sel_type_sig;
00124             NODE * size_sig;
00125             NODE * size_appl;
00126             NODE * size_id;
00127             extern NODE * id_size;
00128             NODE * op = p -> ap_operator;
00129 
00130             if (size_val == 0) {
00131                 /* Try to put size of array rep on top of the stack */
00132                 /* using size function of the array type            */
00133                   if (op_kind != LETTERID || op -> sel_type == NIL) {
00134                       break;
00135                   }
00136                   sel_type_sig = op -> sel_type -> signature;
00137                   size_sig = getcomp(sel_type_sig, id_size, NIL, NIL,
00138                                      NIL, NIL, NIL, FALSE);
00139                   if (size_sig == NIL || special_tp(size_sig -> fsig_special)
00140                                          != ARRAY_SIZE) {
00141                       /* No appropriate size operation */
00142                       break;
00143                   }
00144                   /* Construct size application and generate code for it */
00145                     size_id = copynode(id_size);
00146                     initfld(&(size_id -> sel_type), op -> sel_type);
00147                     size_id -> id_def_found = TRUE;
00148                     size_appl = mknode(APPLICATION, size_id, emptylist());
00149                     tl_findsig(size_appl, FALSE);
00150                     Vappl(size_appl);
00151             } else {
00152               /* Push constant onto the stack */
00153                 fprintf(Voutfile, "\tpushl\t$%d\n", size_val);
00154             }
00155             SET_GC_INFO;
00156             switch(special_tp(op_special)) {
00157               case ARRAY_STD_NEW:
00158                 if (Vflag) {
00159                     printf("Using fast standard array allocation inside %s\n",
00160                            Vcurrent -> fc_code_label);
00161                 }
00162                 CODE("\t.globl\t_fast_Array_New");
00163                 CODE("\tcalls\t$1,_fast_Array_New");
00164                 break;
00165               case ARRAY_PTR_NEW:
00166                 if (Vflag) {
00167                     printf("Using fast pointer array allocation inside %s\n",
00168                            Vcurrent -> fc_code_label);
00169                 }
00170                 CODE("\t.globl\t_fast_ptr_Array_New");
00171                 CODE("\tcalls\t$1,_fast_ptr_Array_New");
00172                 break;
00173             }
00174             CODE("\tpushl\tr0");
00175             return;
00176           }
00177       }
00178     /* determine type of calling sequence */
00179       in_line = op_sig -> fsig_inline_code;
00180       /* if it's impure and not id, ignore in-line code */
00181         if (op_impure) {
00182 #         ifdef VERBOSE
00183             printf("Clearing inline code\n");
00184 #         endif
00185           in_line = NIL;
00186         }
00187       if (in_line == NIL) {
00188         switch(result_sig -> kind) {
00189           case TYPESIGNATURE:
00190             stack_call = FALSE;
00191             break;
00192           case FUNCSIGNATURE:
00193             stack_call = FALSE;
00194             break;
00195           case VALSIGNATURE:
00196 #                           ifdef DEBUG
00197             if (!has_sig(result_sig -> val_denotation)) {
00198               dbgmsg("codegen: Missing res. type signature\n");
00199               prtree(p);
00200               abort();
00201             }
00202 #                           endif
00203             stack_call = result_sig -> val_denotation
00204                          -> signature -> ts_simple_type;
00205             break;
00206           case VARSIGNATURE:
00207 #                           ifdef DEBUG
00208              if (!has_sig(result_sig -> val_denotation)) {
00209               dbgmsg("codegen: Missing res. type signature\n");
00210               prtree(p);
00211               abort();
00212              }
00213 #                           endif
00214             stack_call = result_sig -> var_denotation
00215                          -> signature -> ts_simple_type;
00216             break;
00217         }
00218         /* Check for an impure function */
00219             if (appl_impure) {
00220                 stack_call = FALSE;
00221             }
00222         /* Check for bad VAR parameters */
00223             maplist(q, p -> ap_args, {
00224                 NODE * sig = q -> signature;
00225                 if (sig -> kind == VARSIGNATURE) {
00226                     ASSERT (has_sig(sig -> var_denotation),
00227                       "Missing argument type signature");
00228                     if (!sig -> var_denotation -> signature
00229                              -> ts_simple_type) {
00230                         stack_call = FALSE;
00231                     }
00232                 }
00233             });
00234       }
00235       if (construction != NIL) {
00236         stack_call = stack_call
00237                      || (construction -> fc_complexity & NO_SL)
00238                      || (construction -> fc_complexity & NO_CONSTR);
00239       }
00240       if (hflag) {
00241         stack_call = FALSE;
00242       }
00243     if (in_line != NIL) {
00244       maprlist(p -> ap_args, Vexpression);
00245       /* add r11 to Ventry_mask if it is mentioned */
00246         if(mentions_r11(in_line)) {
00247             Ventry_mask |= R11;
00248         }
00249       fprintf(Voutfile,
00250               in_line,
00251               Vgc_mask << 16, Vgc_mask << 16);
00252       fprintf(Voutfile, "\n");
00253     } else /* not in-line */ {
00254       if (stack_call & Vflag) {
00255         printf("Function %s calls ", Vcurrent -> fc_code_label);
00256         if (construction == NIL) {
00257             extern FILE * unparse_file;
00258 
00259             unparse_file = stdout;
00260             unparse(p -> ap_operator);
00261         } else {
00262             printf("%s", construction -> fc_code_label);
00263         }
00264         printf(" with stack a.r.\n");
00265       }
00266       if (construction != NIL) {
00267           slink_known = p -> ap_operator -> signature
00268                           -> fsig_slink_known;
00269       }
00270       if (construction == NIL
00271           || (!slink_known && !(construction -> fc_complexity & NO_SL))) {
00272           Vexpression (p -> ap_operator);
00273       } else if (op_impure) {
00274           /* evaluate operator for side effects */
00275             Vexpression (p -> ap_operator);
00276             POP ("r0", "# clobber unneeded function value");
00277       } else {
00278           /* May contain needed function construction */
00279             Vtraverse (p -> ap_operator);
00280       }
00281       argcount = length(p -> ap_args);
00282       if (!stack_call) {
00283         /* allocate activation record */
00284           if (construction != NIL && slink_known) {
00285             FXD_NEWOBJ(construction -> ar_size);
00286           } else {
00287             fprintf(Voutfile,"\tmovl\t*(sp),r1");
00288             putcomment ("# Get Size of Activation Record");
00289             NEWOBJ;
00290           }
00291           ar_reg = Vnewreg();
00292           Vgc_mask |= Vreg_bit;
00293           in_memory = (Vreg_bit == 0);
00294           if (construction == NIL || !slink_known) {
00295             fprintf(Voutfile, "\tmovl\t(sp),r1");
00296             putcomment("# Function Value");
00297             fprintf (Voutfile,"\tmovl\t%d(r1),(r0)",
00298                      FO_EP);
00299           } else {
00300             char * display_reg;
00301                   /* name of reg used for a.r. pointer */
00302             char * r10 = "r10";
00303     
00304             DISPLAY ( display_reg, 
00305                       ((construction -> ar_static_level) - 1),
00306                       r10, "# display entry in place" );
00307             if (display_reg == r10) Ventry_mask |= R10;
00308             fprintf(Voutfile, "\tmovl\t%s,(r0)",
00309                     display_reg);
00310           }
00311           putcomment ("# initialize static link to ep");
00312           fprintf(Voutfile,"\tmovl\tr0,%s",ar_reg);
00313           putcomment("# Save Activation Record object");
00314           if (in_memory) {
00315             PUSH("r0", "# make sure it's accessible");
00316           }
00317       } else {
00318         /* clear space for local variables */
00319           if (construction == NIL) {
00320             size_reg = Vnewreg();
00321             in_memory = (Vreg_bit == 0);
00322             fprintf(Voutfile,"\tmovl\t*(sp),%s\n",size_reg);
00323             if (in_memory) {
00324               fprintf(Voutfile, "\tmovl\t%s,r10\n", size_reg);
00325               Ventry_mask |= R10;
00326             }
00327             Ventry_mask |= movc_regs;
00328             fprintf(Voutfile,"\tmoval\t%d[%s],r2",
00329                              -4*(argcount+1),
00330                              in_memory? "r10" : size_reg);
00331             putcomment("# size of local variable area");
00332             fprintf(Voutfile,"\tsubl2\tr2,sp");
00333             putcomment("# reserve space for local variables");
00334             fprintf(Voutfile,"\tmovc5\t$0,(sp),$0,r2,(sp)\n");
00335           } else { /* construction known */
00336             ASSERT(construction -> kind == FUNCCONSTR,
00337                    "codegen.c: fn construction expected");
00338             switch(i = (construction -> ar_size
00339                         - argcount - 1)) {
00340               case 0:
00341                 break;
00342               case 1:
00343                 fprintf(Voutfile,"\tclrl\t-(sp)");
00344                 putcomment("# 1 local variable");
00345                 break;
00346               case 2:
00347                 fprintf(Voutfile,"\tclrq\t-(sp)");
00348                 putcomment("# 2 local variables");
00349                 break;
00350               case 3:
00351                 fprintf(Voutfile,"\tclrq\t-(sp)");
00352                 putcomment("# 3 local variables");
00353                 fprintf(Voutfile,"\tclrl\t-(sp)\n");
00354                 break;
00355               case 4:
00356 #                               ifdef EXTENDED_RANGE
00357                   fprintf(Voutfile,"\tclro\t-(sp)");
00358 #                               else
00359                   fprintf(Voutfile,"\tclrq\t-(sp)\n");
00360                   fprintf(Voutfile,"\tclrq\t-(sp)");
00361 #                               endif
00362                 putcomment("# 4 local variables");
00363                 break;
00364               default: fprintf(Voutfile,
00365                            "\tsubl2\t$%d,sp", 4*i);
00366                        putcomment(
00367                            "# reserve space for locals");
00368                        fprintf(Voutfile,
00369                            "\tmovc5\t$0,(sp),$0,$%d,(sp)\n",
00370                            4*i);
00371                        Ventry_mask |= movc_regs;
00372             }
00373           }
00374       }
00375       maprlist (p-> ap_args, Vexpression);
00376       if (!stack_call) {
00377         char * treg = in_memory? "r10" : ar_reg;
00378 
00379         if (in_memory) {
00380           Vgc_mask |= R10;
00381           fprintf(Voutfile,"\tmovl\t%s,r10\n", ar_reg);
00382         }
00383         /* copy arguments to activation record */
00384           switch(argcount) {
00385             case 0:
00386               break;
00387             case 1:
00388               POP_DISP(treg, 1, "# copy argument");
00389               break;
00390             case 2:
00391               fprintf(Voutfile,"\tmovq\t(sp)+,4(%s)\n", treg);
00392               putcomment("# copy 2 arguments");
00393               break;
00394             case 3:
00395               POP_DISP(treg, 1, "# copy 3 args");
00396               fprintf(Voutfile,"\tmovq\t(sp)+,8(%s)\n", treg);
00397               break;
00398 #                         ifdef EXTENDED_RANGE
00399             case 4:
00400               fprintf(Voutfile,"\tmovo\t(sp)+,4(%s)\n", treg);
00401               putcomment("# copy 4 arguments");
00402               break;
00403 #                         endif
00404             default:
00405               Ventry_mask |= movc_regs;
00406               fprintf(Voutfile,"\tmovc3\t$%d,(sp),4(%s)\n",
00407                       4*argcount, treg);
00408               CODE("\tmovl\tr1,sp");
00409           }
00410         if (in_memory) {
00411           POP ("r0", "# clobber a.r. pointer");
00412         }
00413         if (construction == NIL || !slink_known) {
00414           POP ("r0","# Function Value");
00415         }
00416         SET_GC_INFO;
00417         if (construction != NIL) {
00418           fprintf(Voutfile,"\tcallg\t(%s),%s\n",
00419                   treg, construction -> fc_code_label);
00420         } else {
00421           fprintf(Voutfile,"\tcallg\t(%s),*%d(r0)\n",
00422                   treg, FO_IP);
00423         }
00424         Vretreg(ar_reg);
00425       } else /* stack call */ if (construction == NIL) {
00426         /* arguments are in place */
00427         if (in_memory) {
00428           Vgc_mask |= R10; /* entry_mask already set */
00429           fprintf(Voutfile, "\tmovl\t%s,r10\n", size_reg);
00430         }
00431         fprintf(Voutfile,"\tmovl\t-4(sp)[%s],r0",
00432                 in_memory? "r10" : size_reg);
00433         putcomment("# function value");
00434         PUSH_DISP("r0",(FO_EP/ObjSize),"# static link");
00435         SET_GC_INFO;
00436         fprintf(Voutfile,"\tcallg\t(sp),*%d(r0)\n",
00437                 FO_IP);
00438         fprintf(Voutfile,"\tmoval\t4(sp)[%s],sp",
00439                 in_memory? "r10" : size_reg);
00440         putcomment("# pop a.r. and function value");
00441         Vretreg(size_reg);
00442       } else /* stack call, construction known */ {
00443         if (construction -> fc_complexity & NO_SL) {
00444           fprintf(Voutfile,"\tjsb\tF%s\n",
00445                             construction -> fc_code_label);
00446           if(argcount > 0) {
00447             /* pop arguments */
00448               fprintf(Voutfile,"\taddl2\t$%d,sp\n",4*argcount);
00449           }
00450         } else /* need static link */ {
00451           if (slink_known) {
00452             char * display_reg; /* name of reg used for a.r. pointer */
00453             char * r10 = "r10";
00454     
00455             DISPLAY ( display_reg,
00456                       ((construction -> ar_static_level) - 1),
00457                       r10, "# display entry in place" );
00458             if (display_reg == r10) Ventry_mask |= R10;
00459             PUSH(display_reg, "# static link");
00460           } else {
00461             fprintf(Voutfile, "\tmovl\t%d(sp),r0\n",
00462                     4 * ((construction -> ar_size) - 1));
00463             PUSH_DISP("r0",(FO_EP/ObjSize),"# static link");
00464           }
00465           SET_GC_INFO;
00466           fprintf(Voutfile,"\tcallg\t(sp),%s\n",
00467                   construction -> fc_code_label);
00468           if (!slink_known) {
00469             fprintf(Voutfile,"\taddl2\t$%d,sp",
00470                     4 * ((construction -> ar_size) + 1));
00471             putcomment("# pop a.r. and function value");
00472           } else {
00473             fprintf(Voutfile,"\taddl2\t$%d,sp",
00474                     4 * (construction -> ar_size));
00475             putcomment("# pop a.r.");
00476           }
00477         }
00478       }
00479       PUSH ("r0","# push value returned by function");
00480     }  /* end not in-line */
00481 }

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