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

Go to the documentation of this file.
00001 # define DEBUG
00002 
00003 # include "parm.h"
00004 # include <stdio.h>
00005 # include "stree/ststructs.mh"
00006 # include "codegen.h"
00007 # include "op_codes.h"
00008 # include "pass4/sigs.h"
00009 # include "pass3/is_local.h"
00010 # include <ctype.h>
00011 
00012 extern int yydebug;
00013 extern int yynerrs;
00014 
00015 extern FILE * unparse_file;
00016 
00017 extern FILE * Goutfile;
00018 
00019 extern char str_code_buf[];
00020 
00021 extern int avail_loc;
00022 
00023 extern int Glevel;
00024 
00025 extern NODE * Gcurrent;  /* Current function construction */
00026 
00027 extern boolean Vflag;
00028 
00029 extern boolean Nflag;
00030 
00031 extern boolean Oflag;
00032 
00033 extern boolean xflag;
00034 
00035 /* Check whether s is a valid C identifier */
00036 boolean valid_C_id(s)
00037 char * s;
00038 {
00039     register char * t = s;
00040 
00041     if (!isalpha(*t) && *t != '_') {
00042         return(FALSE);
00043     };
00044     for (t++; *t != '\0'; t++) {
00045         if (!isalnum(*t) && *t != '_') {
00046             return(FALSE);
00047         }
00048     };
00049     return(TRUE);
00050 }
00051       
00052 /* Generate a C callable stup for the i th type component with signature */
00053 /* sig and name nm of the type stored at location identified by lbl.     */
00054 /* Assumes that a pointer to the correct global a.r. is stored at ar_lbl.*/
00055 /* The code is largely a greatly simplified version of appl.c.           */
00056 void compile_stub(nm, sig, lbl, ar_lbl, i)
00057 char * nm;
00058 NODE * sig;
00059 char * lbl;
00060 char * ar_lbl;
00061 int i;
00062 {
00063     int size_loc = avail_loc++;
00064     int ar_loc = avail_loc++;
00065     NODE * params = sig -> fsig_param_list;
00066     int n_args = length(params) - n_vacuous_params(params);
00067     int first_arg_loc;
00068     int closure_loc, tp_loc;
00069     NODE * constr = sig -> fsig_construction;
00070     boolean need_closure = (constr == NIL
00071                             || (constr -> fc_complexity & SL_ACC));
00072     boolean discard_ar = (constr != NIL
00073                           && (constr -> fc_complexity & NO_AR_REFS));
00074 
00075     ASSERT(sig -> kind == FUNCSIGNATURE, "compile_stub: bad sig\n");
00076 
00077     sprintf(str_code_buf, "_%s", nm);
00078     genl(EXT, str_code_buf);
00079     genl(BSF, str_code_buf);
00080     
00081     /* Copy arguments to registers.  This is required by the ILOC */
00082     /* translator.  It doesn't hurt too much otherwise.           */
00083       first_arg_loc = avail_loc;
00084       avail_loc += n_args;
00085       {
00086         register int arg_count;
00087 
00088         for (arg_count = 0; arg_count < n_args; arg_count++) {
00089             gen2(DCL, first_arg_loc + arg_count, DCL_INT);
00090             gen2(GAR, arg_count+1, first_arg_loc + arg_count);
00091         }
00092       }
00093 
00094 
00095     /* Get closure, if necessary */
00096       if (need_closure) {
00097         tp_loc = avail_loc++;
00098         closure_loc = avail_loc++;
00099         gen2(DCL, tp_loc, DCL_ADDR);
00100         gen2(DCL, closure_loc, DCL_ADDR);
00101         genl(LBA, lbl);
00102         gen1(LDL, tp_loc);
00103         gen3(LDI, tp_loc, 0, tp_loc);
00104         gen3(LDI, tp_loc, i, closure_loc);
00105         gen1(UDC, tp_loc);
00106       }
00107     /* Load activation record size into size_loc */
00108       gen2(DCL, size_loc, DCL_INT);
00109       if (constr != NIL) {
00110         gen2(LDN, constr -> ar_size, size_loc);
00111       } else {
00112         gen3(LDI, closure_loc, FO_SIZE, size_loc);
00113       }
00114     /* Allocate activation record */
00115       gen2(DCL, ar_loc, DCL_ADDR);
00116       gen2(ALH, size_loc, ar_loc);
00117       gen1(UDC, size_loc);
00118 
00119     /* Copy arguments to activation record.  Ignore vacuous arguments */
00120       {
00121         register int arg_count;
00122 
00123         for (arg_count = 0; arg_count < n_args; arg_count++) {
00124             gen3(STI, ar_loc, arg_count+1, first_arg_loc + arg_count);
00125             gen1(UDC, first_arg_loc + arg_count);
00126         }
00127       }
00128 
00129     /* store environment ptr */
00130       if (need_closure) {
00131         gen3(LDI, closure_loc, FO_EP, T1);
00132         gen3(STI, ar_loc, 0, T1);
00133       }
00134 
00135     /* Load correct value of global frame pointer */
00136     /* This doesn't matter if we generate C code, since the */
00137     /* code will retrieve GF whenever it needs it, anyway.  */
00138 #     ifndef GEN_C
00139         genl(LBA, ar_lbl);
00140         gen1(LDL, T1);
00141         gen1(HINT, GFU);
00142         gen3(LDI, T1, 0, GF);
00143 #     endif
00144 
00145     if (!xflag) {
00146       /* Store global frame pointer in global_ar, so call_russell works */
00147         gen2(DCL, T2, DCL_ADDR);
00148         genl(LBA, "_global_ar");
00149         gen1(LDL, T2);
00150         gen3(STI, T2, 0, GF);
00151         gen1(UDC, T2);
00152     } else {
00153       /* This is useless and unnecessary in pcr world.  Whatever value */
00154       /* is already there will do fine.                                */
00155     }
00156 
00157     /* Pass activation record as the only argument */
00158       gen2(ARG, 1, ar_loc);
00159 
00160     /* Call the Russell function */
00161       if (need_closure) {
00162         gen2(CLI, closure_loc, FO_IP);
00163         gen1(UDC, closure_loc);
00164       } else {
00165         genl(CLL, constr -> fc_code_label);
00166       }
00167 
00168     /* Allow deallocation of activation record if appropriate */
00169       if (discard_ar) {
00170         gen3(HINT, DEA, ar_loc, constr -> ar_size);
00171       }
00172       gen1(UDC, ar_loc);
00173 
00174     gen0(RTN);
00175 }
00176 
00177 /* Generate C callable stubs for all the components of the type */
00178 /* signature tsig.  Assumes that the type value is stored in    */
00179 /* the location labelled by lbl.                                */
00180 /* Assumes that a pointer to the correct global a.r. is stored  */
00181 /* at ar_lbl.                                                   */
00182 void compile_stubs(tsig, lbl, ar_lbl)
00183 NODE * tsig;
00184 char * lbl;
00185 char * ar_lbl;
00186 {
00187     unsigned * s;
00188     int i;
00189     int component_count = 0;
00190     char * cname;
00191     NODE * csig;
00192 
00193     maplist(t, tsig -> ts_clist, {
00194         switch(t -> kind) {
00195             case DEFCHARSIGS:
00196                 s = &(t -> dcs_0);
00197                 for (i = 0; i < NVECTORS; i++) {
00198                     if (s[i] != 0) {
00199                         errmsg0(t, "Can't generate stub for quoted identifier");
00200                         break;
00201                     }
00202                 }
00203                 break;
00204             case TSCOMPONENT:
00205                 csig = sig_structure(t -> tsc_signature);
00206                 if (csig -> kind != FUNCSIGNATURE){
00207                     errmsg0(csig, "Can't generate stup for non-function");
00208                     break;
00209                 }
00210                 cname = (char *)getname(t -> tsc_id -> id_str_table_index);
00211                 if (!valid_C_id(cname)) {
00212                     errmsg1(csig, "Can't generate stub named %s", cname);
00213                     break;
00214                 }
00215                 compile_stub(cname, t -> tsc_signature,
00216                              lbl, ar_lbl, component_count++);
00217                 break;
00218         }
00219     });
00220 }

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