diff options
Diffstat (limited to 'src/iconc/codegen.c')
-rw-r--r-- | src/iconc/codegen.c | 1918 |
1 files changed, 0 insertions, 1918 deletions
diff --git a/src/iconc/codegen.c b/src/iconc/codegen.c deleted file mode 100644 index 8ca5bd1..0000000 --- a/src/iconc/codegen.c +++ /dev/null @@ -1,1918 +0,0 @@ -/* - * codegen.c - routines to write out C code. - */ -#include "../h/gsupport.h" -#include "ctrans.h" -#include "cglobals.h" -#include "csym.h" -#include "ccode.h" -#include "ctree.h" -#include "cproto.h" - -#ifndef LoopThreshold -#define LoopThreshold 7 -#endif /* LoopThreshold */ - -/* - * MinOne - arrays sizes must be at least 1. - */ -#define MinOne(n) ((n) > 0 ? (n) : 1) - -/* - * ChkSeqNum - make sure a label has been given a sequence number. - */ -#define ChkSeqNum(x) if ((x)->SeqNum == 0) (x)->SeqNum = ++lbl_seq_num - -/* - * ChkBound - for a given procedure, signals that transfer control to a - * bounding label all use the same signal number. - */ -#define ChkBound(x) (((x)->LabFlg & Bounding) ? bound_sig : (x)) - -/* - * When a switch statement for signal handling is optimized, there - * are three possible forms of default clauses. - */ -#define DfltNone 0 /* no default clause */ -#define DfltBrk 1 /* default is just a break */ -#define DfltRetSig 2 /* default is to return the signal from the call */ - -/* - * Prototypes for static functions. - */ -static int arg_nms (struct lentry *lptr, int prt); -static void bi_proc (char *name, struct implement *ip); -static void chkforgn (int outer); -static int dyn_nms (struct lentry *lptr, int prt); -static void fldnames (struct fldname *fields); -static void fnc_blk (struct gentry *gptr); -static void frame (int outer); -static void good_clsg (struct code *call, int outer); -static void initpblk (FILE *f, int c, char *prefix, char *name, - int nquals, int nparam, int ndynam, int nstatic, - int frststat); -static char *is_builtin (struct gentry *gptr); -static void proc_blk (struct gentry *gptr, int init_glbl); -static void prt_ary (struct code *cd, int outer); -static void prt_cond (struct code *cond); -static void prt_cont (struct c_fnc *cont); -static void prt_var (struct lentry *var, int outer); -static void prtcall (struct code *call, int outer); -static void prtcode (struct code *cd, int outer); -static void prtpccall (int outer); -static void rec_blk (struct gentry *gptr, int init_glbl); -static void smpl_clsg (struct code *call, int outer); -static void stat_nms (struct lentry *lptr, int prt); -static void val_loc (struct val_loc *rslt, int outer); - -static int n_stat = -1; /* number of static variables */ - -/* - * var_dcls - produce declarations necessary to implement variables - * and to initialize globals and statics: procedure blocks, procedure - * frames, record blocks, declarations for globals and statics, the - * C main program. - */ -void var_dcls() - { - register int i; - register struct gentry *gptr; - struct gentry *gbl_main; - struct pentry *prc_main; - int n_glob = 0; - int flag; - int init_glbl; - int first; - char *pfx; - - /* - * Output initialized array of descriptors for globals. - */ - fprintf(codefile, "\nstatic struct {word dword; union block *vword;}"); - fprintf(codefile, " init_globals[NGlobals] = {\n"); - prc_main = NULL; - for (i = 0; i < GHSize; i++) - for (gptr = ghash[i]; gptr != NULL; gptr = gptr->blink) { - flag = gptr->flag & ~(F_Global | F_StrInv); - if (strcmp(gptr->name, "main") == 0 && (gptr->flag & F_Proc)) { - /* - * Remember main procedure. - */ - gbl_main = gptr; - prc_main = gbl_main->val.proc; - } - if (flag == 0) { - /* - * Ordinary variable. - */ - gptr->index = n_glob++; - fprintf(codefile, " {D_Null},\n"); - } - else { - /* - * Procedure, function, or record constructor. If the variable - * has not been optimized away, initialize the it to reference - * the procedure block. - */ - if (flag & F_SmplInv) { - init_glbl = 0; - flag &= ~(uword)F_SmplInv; - } - else { - init_glbl = 1; - gptr->index = n_glob++; - fprintf(codefile, " {D_Proc, "); - } - switch (flag) { - case F_Proc: - proc_blk(gptr, init_glbl); - break; - case F_Builtin: - if (init_glbl) - fnc_blk(gptr); - break; - case F_Record: - rec_blk(gptr, init_glbl); - } - } - } - if (n_glob == 0) - fprintf(codefile, " {D_Null} /* place holder */\n"); - fprintf(codefile, " };\n"); - - if (prc_main == NULL) { - nfatal(NULL, "main procedure missing", NULL); - return; - } - - /* - * Output array of descriptors initialized to the names of the - * global variables that have not been optimized away. - */ - if (n_glob == 0) - fprintf(codefile, "\nstruct sdescrip init_gnames[1];\n"); - else { - fprintf(codefile, "\nstruct sdescrip init_gnames[NGlobals] = {\n"); - for (i = 0; i < GHSize; i++) - for (gptr = ghash[i]; gptr != NULL; gptr = gptr->blink) - if (!(gptr->flag & F_SmplInv)) - fprintf(codefile, " {%d, \"%s\"},\n", strlen(gptr->name), - gptr->name); - fprintf(codefile, " };\n"); - } - - /* - * Output array of pointers to builtin functions that correspond to - * names of the global variables. - */ - if (n_glob == 0) - fprintf(codefile, "\nstruct b_proc *builtins[1];\n"); - else { - fprintf(codefile, "\nstruct b_proc *builtins[NGlobals] = {\n"); - for (i = 0; i < GHSize; i++) - for (gptr = ghash[i]; gptr != NULL; gptr = gptr->blink) - if (!(gptr->flag & F_SmplInv)) { - /* - * Need to output *something* to stay in step with other arrays. - */ - if (pfx = is_builtin(gptr)) { - fprintf(codefile, " (struct b_proc *)&BF%c%c_%s,\n", - pfx[0], pfx[1], gptr->name); - } - else - fprintf(codefile, " 0,\n"); - } - fprintf(codefile, " };\n"); - } - - /* - * Output C main function that initializes the run-time system and - * calls the main procedure. - */ - fprintf(codefile, "\n"); - fprintf(codefile, "int main(argc, argv)\n"); - fprintf(codefile, "int argc;\n"); - fprintf(codefile, "char **argv;\n"); - fprintf(codefile, " {\n"); - - /* - * If the main procedure requires a command-line argument list, we - * need a place to construct the Icon argument list. - */ - if (prc_main->nargs != 0 || !(gbl_main->flag & F_SmplInv)) { - fprintf(codefile, " struct {\n"); - fprintf(codefile, " struct tend_desc *previous;\n"); - fprintf(codefile, " int num;\n"); - fprintf(codefile, " struct descrip arg_lst;\n"); - fprintf(codefile, " } t;\n"); - fprintf(codefile, "\n"); - } - - /* - * Produce code to initialize run-time system variables. Some depend - * on compiler options. - */ - fprintf(codefile, " op_tbl = (struct b_proc *)init_op_tbl;\n"); - fprintf(codefile, " globals = (dptr)init_globals;\n"); - fprintf(codefile, " eglobals = &globals[%d];\n", n_glob); - fprintf(codefile, " gnames = (dptr)init_gnames;\n"); - fprintf(codefile, " egnames = &gnames[%d];\n", n_glob); - fprintf(codefile, " estatics = &statics[%d];\n", n_stat + 1); - if (debug_info) - fprintf(codefile, " debug_info = 1;\n"); - else - fprintf(codefile, " debug_info = 0;\n"); - if (line_info) { - fprintf(codefile, " line_info = 1;\n"); - fprintf(codefile, " file_name = \"\";\n"); - fprintf(codefile, " line_num = 0;\n"); - } - else - fprintf(codefile, " line_info = 0;\n"); - if (err_conv) - fprintf(codefile, " err_conv = 1;\n"); - else - fprintf(codefile, " err_conv = 0;\n"); - if (largeints) - fprintf(codefile, " largeints = 1;\n"); - else - fprintf(codefile, " largeints = 0;\n"); - - /* - * Produce code to call the routine to initialize the runtime system. - */ - if (trace) - fprintf(codefile, " init(*argv, &argc, argv, -1);\n"); - else - fprintf(codefile, " init(*argv, &argc, argv, 0);\n"); - fprintf(codefile, "\n"); - - /* - * If the main procedure requires an argument list (perhaps because - * it uses standard, rather than tailored calling conventions), - * set up the argument list. - */ - if (prc_main->nargs != 0 || !(gbl_main->flag & F_SmplInv)) { - fprintf(codefile, " t.arg_lst = nulldesc;\n"); - fprintf(codefile, " t.num = 1;\n"); - fprintf(codefile, " t.previous = NULL;\n"); - fprintf(codefile, " tend = (struct tend_desc *)&t;\n"); - if (prc_main->nargs == 0) - fprintf(codefile, - " /* main() takes no arguments: construct no list */\n"); - else - fprintf(codefile, " cmd_line(argc, argv, &t.arg_lst);\n"); - fprintf(codefile, "\n"); - } - else - fprintf(codefile, " tend = NULL;\n"); - - if (gbl_main->flag & F_SmplInv) { - /* - * procedure main only has a simplified implementation if it - * takes either 0 or 1 argument. - */ - first = 1; - if (prc_main->nargs == 0) - fprintf(codefile, " P%s_main(", prc_main->prefix); - else { - fprintf(codefile, " P%s_main(&t.arg_lst", prc_main->prefix); - first = 0; - } - if (prc_main->ret_flag & (DoesRet | DoesSusp)) { - if (!first) - fprintf(codefile, ", "); - fprintf(codefile, "&trashcan"); - first = 0; - } - if (prc_main->ret_flag & DoesSusp) - fprintf(codefile, ", (continuation)NULL"); - fprintf(codefile, ");\n"); - } - else /* the main procedure uses standard calling conventions */ - fprintf(codefile, - " P%s_main(1, &t.arg_lst, &trashcan, (continuation)NULL);\n", - prc_main->prefix); - fprintf(codefile, " \n"); - fprintf(codefile, " c_exit(EXIT_SUCCESS);\n"); - fprintf(codefile, " }\n"); - - /* - * Output to header file definitions related to global and static - * variables. - */ - fprintf(inclfile, "\n"); - if (n_glob == 0) { - fprintf(inclfile, "#define NGlobals 1\n"); - fprintf(inclfile, "int n_globals = 0;\n"); - } - else { - fprintf(inclfile, "#define NGlobals %d\n", n_glob); - fprintf(inclfile, "int n_globals = NGlobals;\n"); - } - ++n_stat; - fprintf(inclfile, "\n"); - fprintf(inclfile, "int n_statics = %d;\n", n_stat); - fprintf(inclfile, "struct descrip statics[%d]", MinOne(n_stat)); - if (n_stat > 0) { - fprintf(inclfile, " = {\n"); - for (i = 0; i < n_stat; ++i) - fprintf(inclfile, " {D_Null},\n"); - fprintf(inclfile, " };\n"); - } - else - fprintf(inclfile, ";\n"); - } - -/* - * proc_blk - create procedure block and initialize global variable, also - * compute offsets for local procedure variables. - */ -static void proc_blk(gptr, init_glbl) -struct gentry *gptr; -int init_glbl; - { - struct pentry *p; - register char *name; - int nquals; - - name = gptr->name; - p = gptr->val.proc; - - /* - * If we don't initialize a global variable for this procedure, we - * need only compute offsets for variables. - */ - if (init_glbl) { - fprintf(codefile, "(union block *)&BP%s_%s},\n", p->prefix, name); - nquals = 1 + Abs(p->nargs) + p->ndynam + p->nstatic; - fprintf(inclfile, "\n"); - fprintf(inclfile, "static int P%s_%s (int r_nargs, dptr r_args,", - p->prefix, name); - fprintf(inclfile, "dptr r_rslt, continuation r_s_cont);\n"); - initpblk(inclfile, 'P', p->prefix, name, nquals, p->nargs, p->ndynam, - p->nstatic, n_stat + 1); - fprintf(inclfile, "\n {%d, \"%s\"},\n", strlen(name), name); - } - arg_nms(p->args, init_glbl); - p->tnd_loc = dyn_nms(p->dynams, init_glbl); - stat_nms(p->statics, init_glbl); - if (init_glbl) - fprintf(inclfile, " }};\n"); - } - -/* - * arg_nms - compute offsets of arguments and, if needed, output the - * initializer for a descriptor for the argument name. - */ -static int arg_nms(lptr, prt) -struct lentry *lptr; -int prt; - { - register int n; - - if (lptr == NULL) - return 0; - n = arg_nms(lptr->next, prt); - lptr->val.index = n; - if (prt) - fprintf(inclfile, " {%d, \"%s\"},\n", strlen(lptr->name), lptr->name); - return n + 1; - } - -/* - * dyn_nms - compute offsets of dynamic locals and, if needed, output the - * initializer for a descriptor for the variable name. - */ -static int dyn_nms(lptr, prt) -struct lentry *lptr; -int prt; - { - register int n; - - if (lptr == NULL) - return 0; - n = dyn_nms(lptr->next, prt); - lptr->val.index = n; - if (prt) - fprintf(inclfile, " {%d, \"%s\"},\n", strlen(lptr->name), lptr->name); - return n + 1; - } - -/* - * stat_nams - compute offsets of static locals and, if needed, output the - * initializer for a descriptor for the variable name. - */ -static void stat_nms(lptr, prt) -struct lentry *lptr; -int prt; - { - if (lptr == NULL) - return; - stat_nms(lptr->next, prt); - lptr->val.index = ++n_stat; - if (prt) - fprintf(inclfile, " {%d, \"%s\"},\n", strlen(lptr->name), lptr->name); - } - -/* - * is_builtin - check if a global names or hides a builtin, returning prefix. - * If it hides one, we must also generate the prototype and block here. - */ -static char *is_builtin(gptr) -struct gentry *gptr; - { - struct implement *iptr; - - if (!(gptr->flag & F_StrInv)) /* if not eligible for string invoc */ - return 0; - if (gptr->flag & F_Builtin) /* if global *is* a builtin */ - return gptr->val.builtin->prefix; - iptr = db_ilkup(gptr->name, bhash); - if (iptr == NULL) /* if no builtin by this name */ - return NULL; - bi_proc(gptr->name, iptr); /* output prototype and proc block */ - return iptr->prefix; - } - -/* - * fnc_blk - output vword of descriptor for a built-in function and its - * procedure block. - */ -static void fnc_blk(gptr) -struct gentry *gptr; - { - struct implement *iptr; - char *name, *pfx; - - name = gptr->name; - iptr = gptr->val.builtin; - pfx = iptr->prefix; - /* - * output prototype and procedure block to inclfile. - */ - bi_proc(name, iptr); - /* - * vword of descriptor references the procedure block. - */ - fprintf(codefile, "(union block *)&BF%c%c_%s}, \n", pfx[0], pfx[1], name); - } - -/* - * bi_proc - output prototype and procedure block for builtin function. - */ -static void bi_proc(name, ip) -char *name; - struct implement *ip; - { - int nargs; - char prefix[3]; - - prefix[0] = ip->prefix[0]; - prefix[1] = ip->prefix[1]; - prefix[2] = '\0'; - nargs = ip->nargs; - if (nargs > 0 && ip->arg_flgs[nargs - 1] & VarPrm) - nargs = -nargs; - fprintf(inclfile, "\n"); - implproto(ip); - initpblk(inclfile, 'F', prefix, name, 1, nargs, -1, 0, 0); - fprintf(inclfile, "{%d, \"%s\"}}};\n", strlen(name), name); - } - -/* - * rec_blk - if needed, output vword of descriptor for a record - * constructor and output its procedure block. - */ -static void rec_blk(gptr, init_glbl) -struct gentry *gptr; -int init_glbl; - { - struct rentry *r; - register char *name; - int nfields; - - name = gptr->name; - r = gptr->val.rec; - nfields = r->nfields; - - /* - * If the variable is not optimized away, output vword of descriptor. - */ - if (init_glbl) - fprintf(codefile, "(union block *)&BR%s_%s},\n", r->prefix, name); - - fprintf(inclfile, "\n"); - /* - * Prototype for C function implementing constructor. If no optimizations - * have been performed on the variable, the standard calling conventions - * are used and we need a continuation parameter. - */ - fprintf(inclfile, - "static int R%s_%s (int r_nargs, dptr r_args, dptr r_rslt", - r->prefix, name); - if (init_glbl) - fprintf(inclfile, ", continuation r_s_cont"); - fprintf(inclfile, ");\n"); - - /* - * Procedure block, including record name and field names. - */ - initpblk(inclfile, 'R', r->prefix, name, nfields + 1, nfields, -2, - r->rec_num, 1); - fprintf(inclfile, "\n {%d, \"%s\"},\n", strlen(name), name); - fldnames(r->fields); - fprintf(inclfile, " }};\n"); - } - - -/* - * fldnames - output the initializer for a descriptor for the field name. - */ -static void fldnames(fields) -struct fldname *fields; - { - register char *name; - - if (fields == NULL) - return; - fldnames(fields->next); - name = fields->name; - fprintf(inclfile, " {%d, \"%s\"},\n", strlen(name), name); - } - -/* - * implproto - print prototype for function implementing a run-time operation. - */ -void implproto(ip) -struct implement *ip; - { - if (ip->iconc_flgs & ProtoPrint) - return; /* only print prototype once */ - fprintf(inclfile, "int %c%c%c_%s ", ip->oper_typ, ip->prefix[0], - ip->prefix[1], ip->name); - fprintf(inclfile, "(int r_nargs, dptr r_args, dptr r_rslt, "); - fprintf(inclfile,"continuation r_s_cont);\n"); - ip->iconc_flgs |= ProtoPrint; - } - -/* - * const_blks - output blocks for cset and real constants. - */ -void const_blks() - { - register int i; - register struct centry *cptr; - - fprintf(inclfile, "\n"); - for (i = 0; i < CHSize; i++) - for (cptr = chash[i]; cptr != NULL; cptr = cptr->blink) { - switch (cptr->flag) { - case F_CsetLit: - nxt_pre(cptr->prefix, pre, PrfxSz); - cptr->prefix[PrfxSz] = '\0'; - fprintf(inclfile, "struct b_cset BDC%s = ", cptr->prefix); - cset_init(inclfile, cptr->u.cset); - break; - case F_RealLit: - nxt_pre(cptr->prefix, pre, PrfxSz); - cptr->prefix[PrfxSz] = '\0'; - fprintf(inclfile, "struct b_real BDR%s = {T_Real, %s};\n", - cptr->prefix, cptr->image); - break; - } - } - } - -/* - * reccnstr - output record constructors. - */ -void recconstr(r) -struct rentry *r; - { - register char *name; - int optim; - int nfields; - - if (r == NULL) - return; - recconstr(r->next); - - name = r->name; - nfields = r->nfields; - - /* - * Does this record constructor use optimized calling conventions? - */ - optim = glookup(name)->flag & F_SmplInv; - - fprintf(codefile, "\n"); - fprintf(codefile, "static int R%s_%s(r_nargs, r_args, r_rslt", r->prefix, - name); - if (!optim) - fprintf(codefile, ", r_s_cont"); /* continuation is passed */ - fprintf(codefile, ")\n"); - fprintf(codefile, "int r_nargs;\n"); - fprintf(codefile, "dptr r_args;\n"); - fprintf(codefile, "dptr r_rslt;\n"); - if (!optim) - fprintf(codefile, "continuation r_s_cont;\n"); - fprintf(codefile, " {\n"); - fprintf(codefile, " register int i;\n"); - fprintf(codefile, " register struct b_record *rp;\n"); - fprintf(codefile, "\n"); - fprintf(codefile, " rp = alcrecd(%d, (union block *)&BR%s_%s);\n", - nfields, r->prefix, name); - fprintf(codefile, " if (rp == NULL) {\n"); - fprintf(codefile, " err_msg(307, NULL);\n"); - if (err_conv) - fprintf(codefile, " return A_Resume;\n"); - fprintf(codefile, " }\n"); - fprintf(codefile, " for (i = %d; i >= 0; i--)\n", nfields - 1); - fprintf(codefile, " if (i < r_nargs)\n"); - fprintf(codefile, " deref(&r_args[i], &rp->fields[i]);\n"); - fprintf(codefile, " else\n"); - fprintf(codefile, " rp->fields[i] = nulldesc;\n"); - fprintf(codefile, " r_rslt->vword.bptr = (union block *)rp;\n"); - fprintf(codefile, " r_rslt->dword = D_Record;\n"); - fprintf(codefile, " return A_Continue;\n"); - fprintf(codefile, " }\n"); - } - -/* - * outerfnc - output code for the outer function implementing a procedure. - */ -void outerfnc(fnc) -struct c_fnc *fnc; - { - char *prefix; - char *name; - char *cnt_var; - char *sep; - int ntend; - int first_arg; - int nparms; - int optim; /* optimized interface: no arg list adjustment */ - int ret_flag; -#ifdef OptimizeLoop - int i; -#endif /* OptimizeLoop */ - - prefix = cur_proc->prefix; - name = cur_proc->name; - ntend = cur_proc->tnd_loc + num_tmp; - ChkPrefix(fnc->prefix); - optim = glookup(name)->flag & F_SmplInv; - nparms = Abs(cur_proc->nargs); - ret_flag = cur_proc->ret_flag; - - fprintf(codefile, "\n"); - if (optim) { - /* - * Arg list adjustment and dereferencing are done at call site. - * Use simplified interface. Output both function header and - * prototype. - */ - sep = ""; - fprintf(inclfile, "static int P%s_%s (", prefix, name); - fprintf(codefile, "static int P%s_%s(", prefix, name); - if (nparms != 0) { - fprintf(inclfile, "dptr r_args"); - fprintf(codefile, "r_args"); - sep = ", "; - } - if (ret_flag & (DoesRet | DoesSusp)) { - fprintf(inclfile, "%sdptr r_rslt", sep); - fprintf(codefile, "%sr_rslt", sep); - sep = ", "; - } - if (ret_flag & DoesSusp) { - fprintf(inclfile, "%scontinuation r_s_cont", sep); - fprintf(codefile, "%sr_s_cont", sep); - sep = ", "; - } - if (*sep == '\0') - fprintf(inclfile, "void"); - fprintf(inclfile, ");\n"); - fprintf(codefile, ")\n"); - if (nparms != 0) - fprintf(codefile, "dptr r_args;\n"); - if (ret_flag & (DoesRet | DoesSusp)) - fprintf(codefile, "dptr r_rslt;\n"); - if (ret_flag & DoesSusp) - fprintf(codefile, "continuation r_s_cont;\n"); - } - else { - /* - * General invocation interface. Output function header; prototype has - * already been produced. - */ - fprintf(codefile, - "static int P%s_%s(r_nargs, r_args, r_rslt, r_s_cont)\n", prefix, - name); - fprintf(codefile, "int r_nargs;\n"); - fprintf(codefile, "dptr r_args;\n"); - fprintf(codefile, "dptr r_rslt;\n"); - fprintf(codefile, "continuation r_s_cont;\n"); - } - - fprintf(codefile, "{\n"); - fprintf(codefile, " struct PF%s_%s r_frame;\n", prefix, name); - fprintf(codefile, " register int r_signal;\n"); - fprintf(codefile, " int i;\n"); - if (Type(Tree1(cur_proc->tree)) != N_Empty) - fprintf(codefile, " static int first_time = 1;"); - fprintf(codefile, "\n"); - fprintf(codefile, " r_frame.old_pfp = pfp;\n"); - fprintf(codefile, " pfp = (struct p_frame *)&r_frame;\n"); - fprintf(codefile, " r_frame.old_argp = glbl_argp;\n"); - if (!optim || ret_flag & (DoesRet | DoesSusp)) - fprintf(codefile, " r_frame.rslt = r_rslt;\n"); - else - fprintf(codefile, " r_frame.rslt = NULL;\n"); - if (!optim || ret_flag & DoesSusp) - fprintf(codefile, " r_frame.succ_cont = r_s_cont;\n"); - else - fprintf(codefile, " r_frame.succ_cont = NULL;\n"); - fprintf(codefile, "\n"); -#ifdef OptimizeLoop - if (ntend > 0) { - if (ntend < LoopThreshold) - for (i=0; i < ntend ;i++) - fprintf(codefile, " r_frame.tend.d[%d] = nulldesc;\n", i); - else { - fprintf(codefile, " for (i = 0; i < %d; ++i)\n", ntend); - fprintf(codefile, " r_frame.tend.d[i] = nulldesc;\n"); - } - } -#else /* OptimizeLoop */ - fprintf(codefile, " for (i = 0; i < %d; ++i)\n", ntend); - fprintf(codefile, " r_frame.tend.d[i] = nulldesc;\n"); -#endif /* OptimizeLoop */ - if (optim) { - /* - * Dereferencing and argument list adjustment is done at the call - * site. There is not much to do here. - */ - if (nparms == 0) - fprintf(codefile, " glbl_argp = NULL;\n"); - else - fprintf(codefile, " glbl_argp = r_args;\n"); - } - else { - /* - * Dereferencing and argument list adjustment must be done by - * the procedure itself. - */ - first_arg = ntend; - ntend += nparms; - if (cur_proc->nargs < 0) { - /* - * varargs - construct a list into the last argument. - */ - nparms -= 1; - if (nparms == 0) - cnt_var = "r_nargs"; - else { - fprintf(codefile, " i = r_nargs - %d;\n", nparms); - cnt_var = "i"; - } - fprintf(codefile," if (%s <= 0)\n", cnt_var); - fprintf(codefile," varargs(NULL, 0, &r_frame.tend.d[%d]);\n", - first_arg + nparms); - fprintf(codefile," else\n"); - fprintf(codefile, - " varargs(&r_args[%d], %s, &r_frame.tend.d[%d]);\n", nparms, - cnt_var, first_arg + nparms); - } - if (nparms > 0) { - /* - * Output code to dereference argument or supply default null - * value. - */ -#ifdef OptimizeLoop - fprintf(codefile, " for (i = 0; i < r_nargs ; ++i)\n"); - fprintf(codefile, " deref(&r_args[i], &r_frame.tend.d[i + %d]);\n", first_arg); - fprintf(codefile, " for(i = r_nargs; i < %d ; ++i)\n", nparms); - fprintf(codefile, " r_frame.tend.d[i + %d] = nulldesc;\n", - first_arg); -#else /* OptimizeLoop */ - fprintf(codefile, " for (i = 0; i < %d; ++i)\n", nparms); - fprintf(codefile, " if (i < r_nargs)\n"); - fprintf(codefile, - " deref(&r_args[i], &r_frame.tend.d[i + %d]);\n", - first_arg); - fprintf(codefile, " else\n"); - fprintf(codefile, " r_frame.tend.d[i + %d] = nulldesc;\n", - first_arg); -#endif /* OptimizeLoop */ - } - fprintf(codefile, " glbl_argp = &r_frame.tend.d[%d];\n", first_arg); - } - fprintf(codefile, " r_frame.tend.num = %d;\n", ntend); - fprintf(codefile, " r_frame.tend.previous = tend;\n"); - fprintf(codefile, " tend = (struct tend_desc *)&r_frame.tend;\n"); - if (line_info) { - fprintf(codefile, " r_frame.debug.old_line = line_num;\n"); - fprintf(codefile, " r_frame.debug.old_fname = file_name;\n"); - } - if (debug_info) { - fprintf(codefile, " r_frame.debug.proc = (struct b_proc *)&BP%s_%s;\n", - prefix, name); - fprintf(codefile, " if (k_trace) ctrace();\n"); - fprintf(codefile, " ++k_level;\n\n"); - } - fprintf(codefile, "\n"); - - /* - * Output definition for procedure frame. - */ - prt_frame(prefix, ntend, num_itmp, num_dtmp, num_sbuf, num_cbuf); - - /* - * Output code to implement procedure body. - */ - prtcode(&(fnc->cd), 1); - fprintf(codefile, " }\n"); - } - -/* - * prt_fnc - output C function that implements a continuation. - */ -void prt_fnc(fnc) -struct c_fnc *fnc; - { - struct code *sig; - char *name; - char *prefix; - - if (fnc->flag & CF_SigOnly) { - /* - * This function only returns a signal. A shared function is used in - * its place. Make sure that function has been printed. - */ - sig = fnc->cd.next->SigRef->sig; - if (sig->cd_id != C_Resume) { - sig = ChkBound(sig); - if (!(sig->LabFlg & FncPrtd)) { - ChkSeqNum(sig); - fprintf(inclfile, "static int sig_%d (void);\n", - sig->SeqNum); - - fprintf(codefile, "\n"); - fprintf(codefile, "static int sig_%d()\n", sig->SeqNum); - fprintf(codefile, " {\n"); - fprintf(codefile, " return %d; /* %s */\n", sig->SeqNum, - sig->Desc); - fprintf(codefile, " }\n"); - sig->LabFlg |= FncPrtd; - } - } - } - else { - ChkPrefix(fnc->prefix); - prefix = fnc->prefix; - name = cur_proc->name; - - fprintf(inclfile, "static int P%s_%s (void);\n", prefix, name); - - fprintf(codefile, "\n"); - fprintf(codefile, "static int P%s_%s()\n", prefix, name); - fprintf(codefile, " {\n"); - if (fnc->flag & CF_Coexpr) - fprintf(codefile, "#ifdef Coexpr\n"); - - prefix = fnc->frm_prfx; - - fprintf(codefile, " register int r_signal;\n"); - fprintf(codefile, " register struct PF%s_%s *r_pfp;\n", prefix, name); - fprintf(codefile, "\n"); - fprintf(codefile, " r_pfp = (struct PF%s_%s *)pfp;\n", prefix, name); - prtcode(&(fnc->cd), 0); - if (fnc->flag & CF_Coexpr) { - fprintf(codefile, "#else\t\t\t\t\t/* Coexpr */\n"); - fprintf(codefile, " fatalerr(401, NULL);\n"); - fprintf(codefile, "#endif\t\t\t\t\t/* Coexpr */\n"); - } - fprintf(codefile, " }\n"); - } - } - -/* - * prt_frame - output the definition for a procedure frame. - */ -void prt_frame(prefix, ntend, n_itmp, n_dtmp, n_sbuf, n_cbuf) -char *prefix; -int ntend; -int n_itmp; -int n_dtmp; -int n_sbuf; -int n_cbuf; - { - int i; - - /* - * Output standard part of procedure frame including tended - * descriptors. - */ - fprintf(inclfile, "\n"); - fprintf(inclfile, "struct PF%s_%s {\n", prefix, cur_proc->name); - fprintf(inclfile, " struct p_frame *old_pfp;\n"); - fprintf(inclfile, " dptr old_argp;\n"); - fprintf(inclfile, " dptr rslt;\n"); - fprintf(inclfile, " continuation succ_cont;\n"); - fprintf(inclfile, " struct {\n"); - fprintf(inclfile, " struct tend_desc *previous;\n"); - fprintf(inclfile, " int num;\n"); - fprintf(inclfile, " struct descrip d[%d];\n", MinOne(ntend)); - fprintf(inclfile, " } tend;\n"); - - if (line_info) { /* must be true if debug_info is true */ - fprintf(inclfile, " struct debug debug;\n"); - } - - /* - * Output declarations for the integer, double, string buffer, - * and cset buffer work areas of the frame. - */ - for (i = 0; i < n_itmp; ++i) - fprintf(inclfile, " word i%d;\n", i); - for (i = 0; i < n_dtmp; ++i) - fprintf(inclfile, " double d%d;\n", i); - if (n_sbuf > 0) - fprintf(inclfile, " char sbuf[%d][MaxCvtLen];", n_sbuf); - if (n_cbuf > 0) - fprintf(inclfile, " struct b_cset cbuf[%d];", n_cbuf); - fprintf(inclfile, " };\n"); - } - -/* - * prtcode - print a list of C code. - */ -static void prtcode(cd, outer) -struct code *cd; -int outer; - { - struct lentry *var; - struct centry *lit; - struct code *sig; - int n; - - for ( ; cd != NULL; cd = cd->next) { - switch (cd->cd_id) { - case C_Null: - break; - - case C_NamedVar: - /* - * Construct a reference to a named variable in a result - * location. - */ - var = cd->NamedVar; - fprintf(codefile, " "); - val_loc(cd->Rslt, outer); - fprintf(codefile, ".dword = D_Var;\n"); - fprintf(codefile, " "); - val_loc(cd->Rslt, outer); - fprintf(codefile, ".vword.descptr = &"); - prt_var(var, outer); - fprintf(codefile, ";\n"); - break; - - case C_CallSig: - /* - * Call to C function that returns a signal along with signal - * handling code. - */ - if (opt_sgnl) - good_clsg(cd, outer); - else - smpl_clsg(cd, outer); - break; - - case C_RetSig: - /* - * Return a signal. - */ - sig = cd->SigRef->sig; - if (sig->cd_id == C_Resume) - fprintf(codefile, " return A_Resume;\n"); - else { - sig = ChkBound(sig); - ChkSeqNum(sig); - fprintf(codefile, " return %d; /* %s */\n", sig->SeqNum, - sig->Desc); - } - break; - - case C_Goto: - /* - * goto label. - */ - ChkSeqNum(cd->Lbl); - fprintf(codefile, " goto L%d /* %s */;\n", cd->Lbl->SeqNum, - cd->Lbl->Desc); - break; - - case C_Label: - /* - * numbered label. - */ - if (cd->RefCnt > 0) { - ChkSeqNum(cd); - fprintf(codefile, "L%d: ; /* %s */\n", cd->SeqNum, cd->Desc); - } - break; - - case C_Lit: - /* - * Assign literal value to a result location. - */ - lit = cd->Literal; - fprintf(codefile, " "); - val_loc(cd->Rslt, outer); - switch (lit->flag) { - case F_CsetLit: - fprintf(codefile, ".dword = D_Cset;\n"); - fprintf(codefile, " "); - val_loc(cd->Rslt, outer); - fprintf(codefile, ".vword.bptr = (union block *)&BDC%s;\n", - lit->prefix); - break; - case F_IntLit: - if (lit->u.intgr == -1) { - /* - * Large integer literal - output string and convert - * to integer. - */ - fprintf(codefile, ".vword.sptr = \"%s\";\n", lit->image); - fprintf(codefile, " "); - val_loc(cd->Rslt, outer); - fprintf(codefile, ".dword = %d;\n", strlen(lit->image)); - fprintf(codefile, " cnv_int(&"); - val_loc(cd->Rslt, outer); - fprintf(codefile, ", &"); - val_loc(cd->Rslt, outer); - fprintf(codefile, ");\n"); - } - else { - /* - * Ordinary integer literal. - */ - fprintf(codefile, ".dword = D_Integer;\n"); - fprintf(codefile, " "); - val_loc(cd->Rslt, outer); - fprintf(codefile, ".vword.integr = %ld;\n", lit->u.intgr); - } - break; - case F_RealLit: - fprintf(codefile, ".dword = D_Real;\n"); - fprintf(codefile, " "); - val_loc(cd->Rslt, outer); - fprintf(codefile, ".vword.bptr = (union block *)&BDR%s;\n", - lit->prefix); - break; - case F_StrLit: - fprintf(codefile, ".vword.sptr = "); - if (lit->length == 0) { - /* - * Placing an empty string at the end of the string region - * allows some concatenation optimizations at run time. - */ - fprintf(codefile, "strfree;\n"); - n = 0; - } - else { - fprintf(codefile, "\""); - n = prt_i_str(codefile, lit->image, lit->length); - fprintf(codefile, "\";\n"); - } - fprintf(codefile, " "); - val_loc(cd->Rslt, outer); - fprintf(codefile, ".dword = %d;\n", n); - break; - } - break; - - case C_PFail: - /* - * Procedure failure - this code occurs once near the end of - * the procedure. - */ - if (debug_info) { - fprintf(codefile, " --k_level;\n"); - fprintf(codefile, " if (k_trace) failtrace();\n"); - } - fprintf(codefile, " tend = r_frame.tend.previous;\n"); - fprintf(codefile, " pfp = r_frame.old_pfp;\n"); - fprintf(codefile, " glbl_argp = r_frame.old_argp;\n"); - if (line_info) { - fprintf(codefile, " line_num = r_frame.debug.old_line;\n"); - fprintf(codefile, " file_name = r_frame.debug.old_fname;\n"); - } - fprintf(codefile, " return A_Resume;\n"); - break; - - case C_PRet: - /* - * Procedure return - this code occurs once near the end of - * the procedure. - */ - if (debug_info) { - fprintf(codefile, " --k_level;\n"); - fprintf(codefile, " if (k_trace) rtrace();\n"); - } - fprintf(codefile, " tend = r_frame.tend.previous;\n"); - fprintf(codefile, " pfp = r_frame.old_pfp;\n"); - fprintf(codefile, " glbl_argp = r_frame.old_argp;\n"); - if (line_info) { - fprintf(codefile, " line_num = r_frame.debug.old_line;\n"); - fprintf(codefile, " file_name = r_frame.debug.old_fname;\n"); - } - fprintf(codefile, " return A_Continue;\n"); - break; - - case C_PSusp: - /* - * Procedure suspend - call success continuation. - */ - prtpccall(outer); - break; - - case C_Break: - fprintf(codefile, " break;\n"); - break; - - case C_If: - /* - * C if statement. - */ - fprintf(codefile, " if ("); - prt_ary(cd->Cond, outer); - fprintf(codefile, ")\n "); - prtcode(cd->ThenStmt, outer); - break; - - case C_CdAry: - /* - * Array of code fragments. - */ - fprintf(codefile, " "); - prt_ary(cd, outer); - fprintf(codefile, "\n"); - break; - - case C_LBrack: - fprintf(codefile, " {\n"); - break; - - case C_RBrack: - fprintf(codefile, " }\n"); - break; - - case C_Create: - /* - * Code to create a co-expression and assign it to a result - * location. - */ - fprintf(codefile, " "); - val_loc(cd->Rslt, outer); - fprintf(codefile , ".vword.bptr = (union block *)create("); - prt_cont(cd->Cont); - fprintf(codefile, - ", (struct b_proc *)&BP%s_%s, %d, sizeof(word) * %d);\n", - cur_proc->prefix, cur_proc->name, cd->NTemps, cd->WrkSize); - fprintf(codefile, " "); - val_loc(cd->Rslt, outer); - fprintf(codefile, ".dword = D_Coexpr;\n"); - break; - - case C_SrcLoc: - /* - * Update file name and line number information. - */ - if (cd->FileName != NULL) { - fprintf(codefile, " file_name = \""); - prt_i_str(codefile, cd->FileName, strlen(cd->FileName)); - fprintf(codefile, "\";\n"); - } - if (cd->LineNum != 0) - fprintf(codefile, " line_num = %d;\n", cd->LineNum); - break; - } - } - } - -/* - * prt_var - output C code to reference an Icon named variable. - */ -static void prt_var(var, outer) -struct lentry *var; -int outer; - { - switch (var->flag) { - case F_Global: - fprintf(codefile, "globals[%d]", var->val.global->index); - break; - case F_Static: - fprintf(codefile, "statics[%d]", var->val.index); - break; - case F_Dynamic: - frame(outer); - fprintf(codefile, ".tend.d[%d]", var->val.index); - break; - case F_Argument: - fprintf(codefile, "glbl_argp[%d]", var->val.index); - } - - /* - * Include an identifying comment. - */ - fprintf(codefile, " /* %s */", var->name); - } - -/* - * prt_ary - print an array of code fragments. - */ -static void prt_ary(cd, outer) -struct code *cd; -int outer; - { - int i; - - for (i = 0; cd->ElemTyp(i) != A_End; ++i) - switch (cd->ElemTyp(i)) { - case A_Str: - /* - * Simple C code in a string. - */ - fprintf(codefile, "%s", cd->Str(i)); - break; - case A_ValLoc: - /* - * Value location (usually variable of some sort). - */ - val_loc(cd->ValLoc(i), outer); - break; - case A_Intgr: - /* - * Integer. - */ - fprintf(codefile, "%d", cd->Intgr(i)); - break; - case A_ProcCont: - /* - * Current procedure call's success continuation. - */ - if (outer) - fprintf(codefile, "r_s_cont"); - else - fprintf(codefile, "r_pfp->succ_cont"); - break; - case A_SBuf: - /* - * One of the string buffers. - */ - frame(outer); - fprintf(codefile, ".sbuf[%d]", cd->Intgr(i)); - break; - case A_CBuf: - /* - * One of the cset buffers. - */ - fprintf(codefile, "&("); - frame(outer); - fprintf(codefile, ".cbuf[%d])", cd->Intgr(i)); - break; - case A_Ary: - /* - * A subarray of code fragments. - */ - prt_ary(cd->Array(i), outer); - break; - } - } - -/* - * frame - access to the procedure frame. Access directly from outer function, - * but access through r_pfp from a continuation. - */ -static void frame(outer) -int outer; - { - if (outer) - fprintf(codefile, "r_frame"); - else - fprintf(codefile, "(*r_pfp)"); - } - -/* - * prtpccall - print procedure continuation call. - */ -static void prtpccall(outer) -int outer; - { - int first_arg; - int optim; /* optimized interface: no arg list adjustment */ - - first_arg = cur_proc->tnd_loc + num_tmp; - optim = glookup(cur_proc->name)->flag & F_SmplInv; - - /* - * The only signal to be handled in this procedure is - * resumption, the rest must be passed on. - */ - if (cur_proc->nargs != 0 && optim && !outer) { - fprintf(codefile, " {\n"); - fprintf(codefile, " dptr r_argp_sav;\n"); - fprintf(codefile, "\n"); - fprintf(codefile, " r_argp_sav = glbl_argp;\n"); - } - if (debug_info) { - fprintf(codefile, " --k_level;\n"); - fprintf(codefile, " if (k_trace) strace();\n"); - } - fprintf(codefile, " pfp = "); - frame(outer); - fprintf(codefile, ".old_pfp;\n"); - fprintf(codefile, " glbl_argp = "); - frame(outer); - fprintf(codefile, ".old_argp;\n"); - if (line_info) { - fprintf(codefile, " line_num = "); - frame(outer); - fprintf(codefile, ".debug.old_line;\n"); - fprintf(codefile, " file_name = "); - frame(outer); - fprintf(codefile , ".debug.old_fname;\n"); - } - fprintf(codefile, " r_signal = (*"); - if (outer) - fprintf(codefile, "r_s_cont)();\n"); - else - fprintf(codefile, "r_pfp->succ_cont)();\n"); - fprintf(codefile, " if (r_signal != A_Resume) {\n"); - if (outer) - fprintf(codefile, " tend = r_frame.tend.previous;\n"); - fprintf(codefile, " return r_signal;\n"); - fprintf(codefile, " }\n"); - fprintf(codefile, " pfp = (struct p_frame *)&"); - frame(outer); - fprintf(codefile, ";\n"); - if (cur_proc->nargs == 0) - fprintf(codefile, " glbl_argp = NULL;\n"); - else { - if (optim) { - if (outer) - fprintf(codefile, " glbl_argp = r_args;\n"); - else - fprintf(codefile, " glbl_argp = r_argp_sav;\n"); - } - else { - fprintf(codefile, " glbl_argp = &"); - if (outer) - fprintf(codefile, "r_frame."); - else - fprintf(codefile, "r_pfp->"); - fprintf(codefile, "tend.d[%d];\n", first_arg); - } - } - if (debug_info) { - fprintf(codefile, " if (k_trace) atrace();\n"); - fprintf(codefile, " ++k_level;\n"); - } - if (cur_proc->nargs != 0 && optim && !outer) - fprintf(codefile, " }\n"); - } - -/* - * smpl_clsg - print call and signal handling code, but nothing fancy. - */ -static void smpl_clsg(call, outer) -struct code *call; -int outer; - { - struct sig_act *sa; - - fprintf(codefile, " r_signal = "); - prtcall(call, outer); - fprintf(codefile, ";\n"); - if (call->Flags & ForeignSig) - chkforgn(outer); - fprintf(codefile, " switch (r_signal) {\n"); - for (sa = call->SigActs; sa != NULL; sa = sa->next) { - fprintf(codefile, " case "); - prt_cond(sa->sig); - fprintf(codefile, ":\n "); - prtcode(sa->cd, outer); - } - fprintf(codefile, " }\n"); - } - -/* - * chkforgn - produce code to see if the current signal belongs to a - * procedure higher up the call chain and pass it along if it does. - */ -static void chkforgn(outer) -int outer; - { - fprintf(codefile, " if (pfp != (struct p_frame *)"); - if (outer) { - fprintf(codefile, "&r_frame) {\n"); - fprintf(codefile, " tend = r_frame.tend.previous;\n"); - } - else - fprintf(codefile, "r_pfp) {\n"); - fprintf(codefile, " return r_signal;\n"); - fprintf(codefile, " }\n"); - } - -/* - * good_clsg - print call and signal handling code and do a good job. - */ -static void good_clsg(call, outer) -struct code *call; -int outer; - { - struct sig_act *sa, *sa1, *nxt_sa; - int ncases; /* the number of cases - each may have multiple case labels */ - int ncaselbl; /* the number of case labels */ - int nbreak; /* the number of cases that just break out of the switch */ - int nretsig; /* the number of cases that just pass along signal */ - int sig_var; - int dflt; - struct code *cond; - struct code *then_cd; - - /* - * Decide whether to use "break;", "return r_signal;", or nothing as - * the default case. - */ - nretsig = 0; - nbreak = 0; - for (sa = call->SigActs; sa != NULL; sa = sa->next) { - if (sa->cd->cd_id == C_RetSig && sa->sig == sa->cd->SigRef->sig) { - /* - * The action returns the same signal detected by this case. - */ - ++nretsig; - } - else if (sa->cd->cd_id == C_Break) { - cond = sa->sig; /* if there is only one break, we may want this */ - ++nbreak; - } - } - dflt = DfltNone; - ncases = 0; - if (nbreak > 0 && nbreak >= nretsig) { - /* - * There are at least as many "break;"s as "return r_signal;"s, so - * use "break;" for default clause. - */ - dflt = DfltBrk; - ncases = 1; - } - else if (nretsig > 1) { - /* - * There is more than one case that returns the same signal it - * detects and there are more of them than "break;"s, to make - * "return r_signal;" the default clause. - */ - dflt = DfltRetSig; - ncases = 1; - } - - /* - * Gather case labels together for each case, ignoring cases that - * fall under the default. This involves constructing a new - * improved call->SigActs list. - */ - ncaselbl = ncases; - sa = call->SigActs; - call->SigActs = NULL; - for ( ; sa != NULL; sa = nxt_sa) { - nxt_sa = sa->next; - /* - * See if we have already found a case with the same action. - */ - sa1 = call->SigActs; - switch (sa->cd->cd_id) { - case C_Break: - if (dflt == DfltBrk) - continue; - while (sa1 != NULL && sa1->cd->cd_id != C_Break) - sa1 = sa1->next; - break; - case C_RetSig: - if (dflt == DfltRetSig && sa->cd->SigRef->sig == sa->sig) - continue; - while (sa1 != NULL && (sa1->cd->cd_id != C_RetSig || - sa1->cd->SigRef->sig != sa->cd->SigRef->sig)) - sa1 = sa1->next; - break; - default: /* C_Goto */ - while (sa1 != NULL && (sa1->cd->cd_id != C_Goto || - sa1->cd->Lbl != sa->cd->Lbl)) - sa1 = sa1->next; - break; - } - ++ncaselbl; - if (sa1 == NULL) { - /* - * First time we have seen this action, create a new case. - */ - ++ncases; - sa->next = call->SigActs; - call->SigActs = sa; - } - else { - /* - * We can share the action of another case label. - */ - sa->shar_act = sa1->shar_act; - sa1->shar_act = sa; - } - } - - /* - * If we might receive a "foreign" signal that belongs to a procedure - * further down the call chain, put the signal in "r_signal" then - * check for this condition. - */ - sig_var = 0; - if (call->Flags & ForeignSig) { - fprintf(codefile, " r_signal = "); - prtcall(call, outer); - fprintf(codefile, ";\n"); - chkforgn(outer); - sig_var = 1; - } - - /* - * Determine the best way to handle the signal returned from the call. - */ - if (ncases == 0) { - /* - * Any further signal checking has been optimized away. Execution - * just falls through to subsequent code. If the call has not - * been done, do it. - */ - if (!sig_var) { - fprintf(codefile, " "); - prtcall(call, outer); - fprintf(codefile, ";\n"); - } - } - else if (ncases == 1) { - if (dflt == DfltRetSig || ncaselbl == nretsig) { - /* - * All this call does is pass the signal on. See if we have - * done the call yet. - */ - if (sig_var) - fprintf(codefile, " return r_signal;"); - else { - fprintf(codefile, " return "); - prtcall(call, outer); - fprintf(codefile, ";\n"); - } - } - else { - /* - * We know what to do without looking at the signal. Make sure - * we have done the call. If the action is not simply "break" - * out signal checking, execute it. - */ - if (!sig_var) { - fprintf(codefile, " "); - prtcall(call, outer); - fprintf(codefile, ";\n"); - } - if (dflt != DfltBrk) - prtcode(call->SigActs->cd, outer); - } - } - else { - /* - * We have at least two cases. If we have a default action of returning - * the signal without looking at it, make sure it is in "r_signal". - */ - if (!sig_var && dflt == DfltRetSig) { - fprintf(codefile, " r_signal = "); - prtcall(call, outer); - fprintf(codefile, ";\n"); - sig_var = 1; - } - - if (ncaselbl == 2) { - /* - * We can use an if statement. If we need the signal in "r_signal", - * it is already there. - */ - fprintf(codefile, " if ("); - if (sig_var) - fprintf(codefile, "r_signal"); - else - prtcall(call, outer); - - cond = call->SigActs->sig; - then_cd = call->SigActs->cd; - - /* - * If the "then" clause is a no-op ("break;" from a switch), - * prepare to eliminate it by reversing the test in the - * condition. - */ - if (then_cd->cd_id == C_Break) - fprintf(codefile, " != "); - else - fprintf(codefile, " == "); - - prt_cond(cond); - fprintf(codefile, ")\n "); - - if (then_cd->cd_id == C_Break) { - /* - * We have reversed the test, so we need to use the default - * code. However, because a "break;" exists and it is not - * default, "return r_signal;" must be the default. - */ - fprintf(codefile, " return r_signal;\n"); - } - else { - /* - * Print the "then" clause and determine what the "else" clause - * is. - */ - prtcode(then_cd, outer); - if (call->SigActs->next != NULL) { - fprintf(codefile, " else\n "); - prtcode(call->SigActs->next->cd, outer); - } - else if (dflt == DfltRetSig) { - fprintf(codefile, " else\n"); - fprintf(codefile, " return r_signal;\n"); - } - } - } - else if (ncases == 2 && nbreak == 1) { - /* - * We can use an if-then statement with a negated test. Note, - * the non-break case is not "return r_signal" or we would have - * ncaselbl = 2, making the last test true. This also means that - * break is the default (the break condition was saved). - */ - fprintf(codefile, " if ("); - if (sig_var) - fprintf(codefile, "r_signal"); - else - prtcall(call, outer); - fprintf(codefile, " != "); - prt_cond(cond); - fprintf(codefile, ") {\n "); - prtcode(call->SigActs->cd, outer); - fprintf(codefile, " }\n"); - } - else { - /* - * We must use a full case statement. If we need the signal in - * "r_signal", it is already there. - */ - fprintf(codefile, " switch ("); - if (sig_var) - fprintf(codefile, "r_signal"); - else - prtcall(call, outer); - fprintf(codefile, ") {\n"); - - /* - * Print the cases - */ - for (sa = call->SigActs; sa != NULL; sa = sa->next) { - for (sa1 = sa; sa1 != NULL; sa1 = sa1->shar_act) { - fprintf(codefile, " case "); - prt_cond(sa1->sig); - fprintf(codefile, ":\n"); - } - fprintf(codefile, " "); - prtcode(sa->cd, outer); - } - - /* - * If we have a default action and it is not break, print it. - */ - if (dflt == DfltRetSig) { - fprintf(codefile, " default:\n"); - fprintf(codefile, " return r_signal;\n"); - } - - fprintf(codefile, " }\n"); - } - } - } - -/* - * prtcall - print call. - */ -static void prtcall(call, outer) -struct code *call; -int outer; - { - /* - * Either the operation or the continuation may be missing, but not - * both. - */ - if (call->OperName == NULL) { - prt_cont(call->Cont); - fprintf(codefile, "()"); - } - else { - fprintf(codefile, "%s(", call->OperName); - if (call->ArgLst != NULL) - prt_ary(call->ArgLst, outer); - if (call->Cont == NULL) { - if (call->Flags & NeedCont) { - /* - * The operation requires a continuation argument even though - * this call does not include one, pass the NULL pointer. - */ - if (call->ArgLst != NULL) - fprintf(codefile, ", "); - fprintf(codefile, "(continuation)NULL"); - } - } - else { - /* - * Pass the success continuation. - */ - if (call->ArgLst != NULL) - fprintf(codefile, ", "); - prt_cont(call->Cont); - } - fprintf(codefile, ")"); - } - } - -/* - * prt_cont - print the name of a continuation. - */ -static void prt_cont(cont) -struct c_fnc *cont; - { - struct code *sig; - - if (cont->flag & CF_SigOnly) { - /* - * This continuation only returns a signal. All continuations - * returning the same signal are implemented by the same C function. - */ - sig = cont->cd.next->SigRef->sig; - if (sig->cd_id == C_Resume) - fprintf(codefile, "sig_rsm"); - else { - sig = ChkBound(sig); - ChkSeqNum(sig); - fprintf(codefile, "sig_%d", sig->SeqNum); - } - } - else { - /* - * Regular continuation. - */ - ChkPrefix(cont->prefix); - fprintf(codefile, "P%s_%s", cont->prefix, cur_proc->name); - } - } - -/* - * val_loc - output code referencing a value location (usually variable of - * some sort). - */ -static void val_loc(loc, outer) -struct val_loc *loc; -int outer; - { - /* - * See if we need to cast a block pointer to a specific block type - * or if we need to take the address of a location. - */ - if (loc->mod_access == M_BlkPtr && loc->blk_name != NULL) - fprintf(codefile, "(*(struct %s **)&", loc->blk_name); - if (loc->mod_access == M_Addr) - fprintf(codefile, "(&"); - - switch (loc->loc_type) { - case V_Ignore: - fprintf(codefile, "trashcan"); - break; - case V_Temp: - /* - * Temporary descriptor variable. - */ - frame(outer); - fprintf(codefile, ".tend.d[%d]", cur_proc->tnd_loc + loc->u.tmp); - break; - case V_ITemp: - /* - * Temporary C integer variable. - */ - frame(outer); - fprintf(codefile, ".i%d", loc->u.tmp); - break; - case V_DTemp: - /* - * Temporary C double variable. - */ - frame(outer); - fprintf(codefile, ".d%d", loc->u.tmp); - break; - case V_Const: - /* - * Integer constant (used for size of variable part of arg list). - */ - fprintf(codefile, "%d", loc->u.int_const); - break; - case V_NamedVar: - /* - * Icon named variable. - */ - prt_var(loc->u.nvar, outer); - break; - case V_CVar: - /* - * C variable from in-line code. - */ - fprintf(codefile, "%s", loc->u.name); - break; - case V_PRslt: - /* - * Procedure result location. - */ - if (!outer) - fprintf(codefile, "(*r_pfp->rslt)"); - else - fprintf(codefile, "(*r_rslt)"); - break; - } - - /* - * See if we are accessing the vword of a descriptor. - */ - switch (loc->mod_access) { - case M_CharPtr: - fprintf(codefile, ".vword.sptr"); - break; - case M_BlkPtr: - fprintf(codefile, ".vword.bptr"); - if (loc->blk_name != NULL) - fprintf(codefile, ")"); - break; - case M_CInt: - fprintf(codefile, ".vword.integr"); - break; - case M_Addr: - fprintf(codefile, ")"); - break; - } - } - -/* - * prt_cond - print a condition (signal number). - */ -static void prt_cond(cond) -struct code *cond; - { - if (cond == &resume) - fprintf(codefile, "A_Resume"); - else if (cond == &contin) - fprintf(codefile, "A_Continue"); - else if (cond == &fallthru) - fprintf(codefile, "A_FallThru"); - else { - cond = ChkBound(cond); - ChkSeqNum(cond); - fprintf(codefile, "%d /* %s */", cond->SeqNum, cond->Desc); - } - } - -/* - * initpblk - write a procedure block along with initialization up to the - * the array of qualifiers. - */ -static void initpblk(f, c, prefix, name, nquals, nparam, ndynam, nstatic, - frststat) -FILE *f; /* output file */ -int c; /* distinguishes procedures, functions, record constructors */ -char* prefix; /* prefix for name */ -char *name; /* name of routine */ -int nquals; /* number of qualifiers at end of block */ -int nparam; /* number of parameters */ -int ndynam; /* number of dynamic locals or function/record indicator */ -int nstatic; /* number of static locals or record number */ -int frststat; /* index into static array of first static local */ - { - fprintf(f, "B_IProc(%d) B%c%s_%s = ", nquals, c, prefix, name); - fprintf(f, "{T_Proc, %d, %c%s_%s, %d, %d, %d, %d, {", 9 + 2 * nquals, c, - prefix, name, nparam, ndynam, nstatic, frststat); - } - |