/* * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * See the copyright notice in the ACK home directory, in the file "Copyright". * * Author: Hans van Staveren */ #include #include #include "param.h" #include "types.h" #include "tes.h" #include "line.h" #include "lookup.h" #include "alloc.h" #include "proinf.h" #include #include #include #include #include "ext.h" #include "reg.h" #include "getline.h" #include "util.h" static short tabval; /* temp store for shorts */ static offset tabval2; /* temp store for offsets */ static char string[IDL + 1]; /* temp store for names */ /* * The next constants are close to sp_cend for fast switches */ #define INST 256 /* instruction: number in tabval */ #define PSEU 257 /* pseudo: number in tabval */ #define ILBX 258 /* label: number in tabval */ #define DLBX 259 /* symbol: name in string[] */ #define CSTX1 260 /* short constant: stored in tabval */ #define CSTX2 261 /* offset: value in tabval2 */ #define VALX1 262 /* symbol+short: in string[] and tabval */ #define VALX2 263 /* symbol+offset: in string[] and tabval2 */ #define ATEOF 264 /* bumped into end of file */ #define readbyte getchar /* Other external declarations */ extern void process(void); /* Forward declarations */ static int table2(void); static void tstinpro(void) { if (prodepth == 0) error("This is not allowed outside a procedure"); } short readshort(void) { register int l_byte, h_byte; l_byte = readbyte(); h_byte = readbyte(); if (h_byte >= 128) h_byte -= 256; return l_byte | (h_byte * 256); } #ifdef LONGOFF static offset readoffset(void) { register long l; register int h_byte; l = readbyte(); l |= ((unsigned) readbyte()) * 256; l |= readbyte() * 256L * 256L; h_byte = readbyte(); if (h_byte >= 128) h_byte -= 256; return l | (h_byte * 256L * 256 * 256L); } #endif static void draininput(void) { /* * called when MES ERR is encountered. * Drain input in case it is a pipe. */ while (getchar() != EOF) ; } static short getint(void) { switch (table2()) { default: error("int expected"); case CSTX1: return (tabval); } } static sym_p getsym(int status) { switch (table2()) { default: error("symbol expected"); case DLBX: return (symlookup(string, status, 0)); case sp_pnam: return (symlookup(string, status, SYMPRO)); } } static offset getoff(void) { switch (table2()) { default: error("offset expected"); case CSTX1: return ((offset) tabval); #ifdef LONGOFF case CSTX2: return (tabval2); #endif } } static void make_string(int n) { sprintf(string, ".%u", n); } static void inident(void) { register int n; register char *p = string; register int c; n = getint(); while (n--) { c = readbyte(); if (p < &string[IDL]) *p++ = c; } *p++ = 0; } static int table3(int n) { switch (n) { case sp_ilb1: tabval = readbyte(); return (ILBX); case sp_ilb2: tabval = readshort(); return (ILBX); case sp_dlb1: make_string(readbyte()); return (DLBX); case sp_dlb2: make_string(readshort()); return (DLBX); case sp_dnam: inident(); return (DLBX); case sp_pnam: inident(); return (n); case sp_cst2: tabval = readshort(); return (CSTX1); #ifdef LONGOFF case sp_cst4: tabval2 = readoffset(); return (CSTX2); #endif case sp_doff: if (table2() != DLBX) error("symbol expected"); switch (table2()) { default: error("offset expected"); case CSTX1: return (VALX1); #ifdef LONGOFF case CSTX2: return (VALX2); #endif } default: return (n); } } static int table1(void) { register int n; n = readbyte(); if (n == EOF) return (ATEOF); if ((n <= sp_lmnem) && (n >= sp_fmnem)) { tabval = n; return (INST); } if ((n <= sp_lpseu) && (n >= sp_fpseu)) { tabval = n; return (PSEU); } if ((n < sp_filb0 + sp_nilb0) && (n >= sp_filb0)) { tabval = n - sp_filb0; return (ILBX); } return (table3(n)); } static int table2(void) { register int n; n = readbyte(); if ((n < sp_fcst0 + sp_ncst0) && (n >= sp_fcst0)) { tabval = n - sp_zcst0; return (CSTX1); } return (table3(n)); } static void argstring(offset length, register argb_p abp) { while (length--) { if (abp->ab_index == NARGBYTES) abp = abp->ab_next = newargb(); abp->ab_contents[abp->ab_index++] = readbyte(); } } static line_p arglist(int n) { line_p lnp; register arg_p ap, *app; bool moretocome; offset length; /* * creates an arglist with n elements * if n == 0 the arglist is variable and terminated by sp_cend */ lnp = newline(OPLIST); app = &lnp->l_a.la_arg; moretocome = TRUE; do { switch (table2()) { default: error("unknown byte in arglist"); case CSTX1: tabval2 = (offset) tabval; case CSTX2: *app = ap = newarg(ARGOFF); ap->a_a.a_offset = tabval2; app = &ap->a_next; break; case ILBX: tstinpro(); *app = ap = newarg(ARGNUM); ap->a_a.a_np = numlookup((unsigned) tabval); ap->a_a.a_np->n_flags |= NUMDATA; app = &ap->a_next; break; case DLBX: *app = ap = newarg(ARGSYM); ap->a_a.a_sp = symlookup(string, OCCURRING, 0); app = &ap->a_next; break; case sp_pnam: *app = ap = newarg(ARGSYM); ap->a_a.a_sp = symlookup(string, OCCURRING, SYMPRO); app = &ap->a_next; break; case VALX1: tabval2 = (offset) tabval; case VALX2: *app = ap = newarg(ARGVAL); ap->a_a.a_val.av_sp = symlookup(string, OCCURRING, 0); ap->a_a.a_val.av_offset = tabval2; app = &ap->a_next; break; case sp_scon: *app = ap = newarg(ARGSTR); length = getoff(); argstring(length, &ap->a_a.a_string); app = &ap->a_next; break; case sp_icon: *app = ap = newarg(ARGICN); goto casecon; case sp_ucon: *app = ap = newarg(ARGUCN); goto casecon; case sp_fcon: *app = ap = newarg(ARGFCN); casecon: length = getint(); ap->a_a.a_con.ac_length = (short) length; argstring(getoff(), &ap->a_a.a_con.ac_con); app = &ap->a_next; break; case sp_cend: moretocome = FALSE; } if (n && (--n) == 0) moretocome = FALSE; } while (moretocome); return (lnp); } offset aoff(register arg_p ap, int n) { while (n > 0) { if (ap != (arg_p) 0) ap = ap->a_next; n--; } if (ap == (arg_p) 0) error("too few parameters"); if (ap->a_typ != ARGOFF) error("offset expected"); return (ap->a_a.a_offset); } static int inpseudo(short n) { register line_p lnp, head, tail; short n1, n2; proinf savearea; #ifdef PSEUBETWEEN static int pcount = 0; if (pcount++ >= PSEUBETWEEN && prodepth == 0) { process(); pcount = 0; } #endif switch (n) { default: error("unknown pseudo"); case ps_bss: case ps_hol: lnp = arglist(3); break; case ps_rom: case ps_con: lnp = arglist(0); break; case ps_ina: case ps_inp: case ps_exa: case ps_exp: lnp = newline(OPSYMBOL); lnp->l_a.la_sp = getsym(NOTHING); break; case ps_exc: n1 = getint(); n2 = getint(); if (n1 != 0 && n2 != 0) { tail = curpro.lastline; while (--n2) tail = tail->l_next; head = tail; while (n1--) head = head->l_next; lnp = tail->l_next; tail->l_next = head->l_next; head->l_next = curpro.lastline; curpro.lastline = lnp; } lnp = newline(OPNO); break; case ps_mes: lnp = arglist(0); switch ((int) aoff(lnp->l_a.la_arg, 0)) { case ms_err: draininput(); exit(-1); case ms_opt: nflag = TRUE; break; case ms_emx: wordsize = aoff(lnp->l_a.la_arg, 1); pointersize = aoff(lnp->l_a.la_arg, 2); #ifndef LONGOFF if (wordsize>2) error("This optimizer cannot handle wordsize>2"); #endif break; case ms_gto: curpro.gtoproc = 1; /* Treat as empty mes ms_reg */ case ms_reg: tstinpro(); regvar(lnp->l_a.la_arg->a_next); oldline(lnp); lnp = newline(OPNO); n = ps_exc; /* kludge to force out this line */ break; case ms_tes: tstinpro(); oldline(lnp); lnp = newline(OPNO); n = ps_exc; /* kludge to force out this line */ break; } break; case ps_pro: if (prodepth > 0) savearea = curpro; else process(); curpro.symbol = getsym(DEFINING); switch (table2()) { case sp_cend: curpro.localbytes = (offset) -1; break; case CSTX1: tabval2 = (offset) tabval; case CSTX2: curpro.localbytes = tabval2; break; default: error("bad second arg of PRO"); } prodepth++; curpro.gtoproc = 0; if (prodepth > 1) { register int i; curpro.lastline = (line_p) 0; curpro.freg = (reg_p) 0; for (i = 0; i < NNUMHASH; i++) curpro.numhash[i] = (num_p) 0; getlines(); curpro = savearea; prodepth--; } return (0); case ps_end: if (prodepth == 0) error("END misplaced"); switch (table2()) { case sp_cend: if (curpro.localbytes == (offset) -1) error("bytes for locals still unknown"); break; case CSTX1: tabval2 = (offset) tabval; case CSTX2: if (curpro.localbytes != (offset) -1 && curpro.localbytes != tabval2) error("inconsistency in number of bytes for locals"); curpro.localbytes = tabval2; break; } process(); curpro.symbol = (sym_p) 0; if (prodepth == 1) { prodepth = 0; #ifdef PSEUBETWEEN pcount = 0; #endif return (0); } else return (1); } lnp->l_instr = n; lnp->l_next = curpro.lastline; curpro.lastline = lnp; return (0); } void getlines(void) { register line_p lnp; register int instr; for (;;) { linecount++; switch (table1()) { default: error("unknown instruction byte"); /* NOTREACHED */ case ATEOF: if (prodepth != 0) error("procedure unterminated at eof"); process(); return; case INST: tstinpro(); instr = tabval; break; case DLBX: lnp = newline(OPSYMBOL); lnp->l_instr = ps_sym; lnp->l_a.la_sp = symlookup(string, DEFINING, 0); lnp->l_next = curpro.lastline; curpro.lastline = lnp; continue; case ILBX: tstinpro(); lnp = newline(OPNUMLAB); lnp->l_instr = op_lab; lnp->l_a.la_np = numlookup((unsigned) tabval); if (lnp->l_a.la_np->n_line != (line_p) 0) error("label %u multiple defined", (unsigned) tabval); lnp->l_a.la_np->n_line = lnp; lnp->l_next = curpro.lastline; curpro.lastline = lnp; continue; case PSEU: if (inpseudo(tabval)) return; continue; } /* * Now we have an instruction number in instr * There might be an operand, look for it */ if ((em_flag[instr - sp_fmnem] & EM_PAR) == PAR_NO) { lnp = newline(OPNO); } else switch (table2()) { default: error("unknown offset byte"); case sp_cend: lnp = newline(OPNO); break; case CSTX1: if ((em_flag[instr - sp_fmnem] & EM_PAR) != PAR_B) { if (CANMINI(tabval)) lnp = newline(tabval + Z_OPMINI); else { lnp = newline(OPSHORT); lnp->l_a.la_short = tabval; } } else { lnp = newline(OPNUMLAB); lnp->l_a.la_np = numlookup((unsigned) tabval); } break; #ifdef LONGOFF case CSTX2: lnp = newline(OPOFFSET); lnp->l_a.la_offset = tabval2; break; #endif case ILBX: tstinpro(); lnp = newline(OPNUMLAB); lnp->l_a.la_np = numlookup((unsigned) tabval); break; case DLBX: lnp = newline(OPSYMBOL); lnp->l_a.la_sp = symlookup(string, OCCURRING, 0); break; case sp_pnam: lnp = newline(OPSYMBOL); lnp->l_a.la_sp = symlookup(string, OCCURRING, SYMPRO); break; case VALX1: lnp = newline(OPSVAL); lnp->l_a.la_sval.lasv_sp = symlookup(string, OCCURRING, 0); lnp->l_a.la_sval.lasv_short = tabval; break; #ifdef LONGOFF case VALX2: lnp = newline(OPLVAL); lnp->l_a.la_lval.lalv_sp = symlookup(string, OCCURRING, 0); lnp->l_a.la_lval.lalv_offset = tabval2; break; #endif } lnp->l_instr = instr; lnp->l_next = curpro.lastline; curpro.lastline = lnp; } }