page@swan.ulowell.edu (Bob Page) (03/08/89)
Submitted-by: monty@brahms.Berkeley.EDU (Joe Montgomery) Posting-number: Volume 89, Issue 29 Archive-name: languages/zc.2 # This is a shell archive. # Remove everything above and including the cut line. # Then run the rest of the file through sh. #----cut here-----cut here-----cut here-----cut here----# #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # d2.c # decl.c # expr.c # fix.c # fun.c # g2.c # This archive created: Tue Mar 7 21:49:30 1989 cat << \SHAR_EOF > d2.c /* Copyright (c) 1988 by Sozobon, Limited. Author: Johann Ruegg * * Permission is granted to anyone to use this software for any purpose * on any computer system, and to redistribute it freely, with the * following restrictions: * 1) No charge may be made other than reasonable charges for reproduction. * 2) Modified versions must be clearly marked as such. * 3) The authors are not responsible for any harmful consequences * of using this software, even if they result from defects in it. * * d2.c * * Declaration subroutines * * Mostly routines for initializations */ #include <stdio.h> #include "param.h" #include "tok.h" #include "nodes.h" #include "cookie.h" #if MMCC overlay "pass2" #endif extern NODEP cur; extern NODEP symtab[]; extern level; extern int oflags[]; #define debugi oflags['i'-'a'] su_size(lp, cp, xp, isunion) register long *lp; char *cp; register NODE *xp; { long sz; char al; sz = xp->n_tptr->t_size; al = xp->n_tptr->t_aln; if (isunion) { *lp = *lp > sz ? *lp : sz; } else { while (al & (*lp)) { /* align new field */ (*lp)++; xp->e_offs++; } *lp += sz; } *cp = *cp > al ? *cp : al; } lc_size(lp, rp, xp) register long *lp; int *rp; register NODE *xp; { long sz; char al; long arg_size(); if (level > 1 && xp->e_sc == K_REGISTER) { if (lc_reg(rp, xp)) return; else xp->e_sc = K_AUTO; } if (xp->e_sc == K_AUTO || level == 1) { sz = xp->n_tptr->t_size; al = xp->n_tptr->t_aln; while (al & (*lp)) { /* align new field */ (*lp)++; xp->e_offs++; } if (level == 1) { sz = arg_size(sz,xp); xp->e_offs += ARG_BASE + *lp; } *lp += sz; if (level != 1) xp->e_offs = LOC_BASE - *lp; } } su_fld(lp, alp, xp, fldw, fop) register long *lp; char *alp; register NODE *xp; int *fop; { if (*alp < ALN_I) *alp = ALN_I; if (fldw == 0) { afterfld(lp, fop); return; } if (fldw + *fop > 8*SIZE_I) afterfld(lp, fop); if (xp) { xp->e_fldw = fldw; xp->e_fldo = *fop; } *fop += fldw; } afterfld(szp, fop) long *szp; int *fop; { if (*fop) { *szp += SIZE_I; *fop = 0; } } ok_gsh(sc, np) NODE *np; { if (sc == K_REGISTER || sc == K_AUTO) { error("reg/auto outside fun"); return 0; } return ok_ty(np, NULL); } ok_gx(np, endp) NODEP np, endp; { if (np) return ok_ty(np->n_tptr, endp); return 0; } ok_lsh(sc, np) NODE *np; { return ok_ty(np, NULL); } arytoptr(np) NODEP np; { NODEP tp = np->n_tptr; NODEP copyone(); if (np->n_flags & N_COPYT) { /* cant change if a dupl. */ tp = copyone(tp); np->n_tptr = tp; np->n_flags &= ~N_COPYT; } tp->t_token = STAR; strcpy(tp->n_name, "Aptr to"); } ok_lx(np,endp) NODEP np, endp; { if (np) { if (level == 1 && np->n_tptr->t_token == '[') arytoptr(np); return ok_ty(np->n_tptr, endp); } return 0; } ok_suh(np) NODEP np; { return 1; } ok_sux(np, endp) NODEP np, endp; { if (np) return ok_ty(np->n_tptr, endp); return 0; } ok_enx(np, endp) NODEP np, endp; { if (np && np->n_tptr == endp) /* no modifiers */ return 1; return 0; } ok_cast(np, endp) NODEP np, endp; { if (np) return ok_ty(np, endp); return 0; } ok_ty(np, endp) register NODEP np, endp; { NODEP child; long csize; long conlval(); if (np == endp) return 1; child = np->n_tptr; if (child) { if (ok_ty(child, endp) == 0) return 0; csize = child->t_size; } switch (np->t_token) { case STAR: np->t_size = SIZE_P; np->t_aln = ALN_P; break; case '(': /* size 0 okay - fun ret void */ if (child->t_token == '[') { error("bad func"); return 0; } /* size 0 */ break; case '[': if (csize == 0) { error("bad array"); return 0; } if (np->n_right) { csize *= conlval(np->n_right); np->n_right = NULL; np->t_size = csize; } np->t_aln = child->t_aln; break; default: return 1; } return 1; } ok_revx(rv,forcast) NODEP rv; { if (rv == NULL) return 1; if (forcast == 0 && rv->e_token != ID) { error("need ID"); return 0; } if (forcast && rv->e_token == ID) { error("ID in cast"); return 0; } return 1; } opt_ginit(xp) NODEP xp; { if (xp->e_token != ID) return; if (xp->n_tptr->t_token == '(') return; switch (xp->e_sc) { case K_STATIC: case HERE_SC: if (cur->e_token == '=') { out_gv(xp, 0); /* place in data segment */ fadvnode(); g_init(xp->n_tptr); } else out_gv(xp, 1); /* place in BSS segment */ break; /* ? added external case ? */ case K_EXTERN: out_gv(xp,0); } } opt_linit(xp) NODEP xp; { if (xp->e_token != ID) return; if (xp->n_tptr->t_token == '(') return; switch (xp->e_sc) { case K_STATIC: if (cur->e_token == '=') { out_gv(xp, 0); fadvnode(); g_init(xp->n_tptr); } else out_gv(xp, 1); to_text(); break; case K_AUTO: case K_REGISTER: if (cur->e_token == '=') a_init(xp); break; } } a_init(op) NODEP op; { register NODEP np, xp; NODEP assignx(), copynode(); np = cur; advnode(); xp = assignx(); op = copynode(op); np->n_left = op; np->n_right = xp; np->e_type = E_BIN; do_expr(np, FORSIDE); return; } opt_enval(intp) int *intp; { NODEP np; NODEP questx(); if (cur->e_token == '=') { fadvnode(); np = questx(); *intp = conxval(np); return; } } opt_field(xp,wdp,isunion) NODE *xp; int *wdp; { NODEP np; NODEP questx(); int i; *wdp = -1; if (isunion) return; if (cur->e_token == ':') { fadvnode(); np = questx(); i = conxval(np); if (i > 8*SIZE_I) { error("field too big"); i = 8*SIZE_I; } if (xp) { if (i <= 0 || bad_fty(xp->n_tptr)) { error("bad field"); return; } } else if (i < 0) { error("neg field width"); return; } *wdp = i; return; } } bad_fty(tp) NODEP tp; { int tok; tok = tp->t_token; if (tok == K_INT || tok == K_UNSIGNED) return 0; return 1; } field(xp, wd, ofp) NODEP xp; int *ofp; { } NODEP def_type() { NODEP bas_type(); return bas_type(K_INT); } #define NSC LAST_SC-FIRST_SC+1 #define NBAS LAST_BAS-FIRST_BAS+1 NODE basics[NBAS]; NODE str_ptr, fun_int; struct bt { char *name; int size; char align; } btbl[] = { {"Uchar", SIZE_C, ALN_C}, {"Ulong", SIZE_L, ALN_L}, {"Long", SIZE_L, ALN_L}, {"Short", SIZE_S, ALN_S}, {"Uns", SIZE_U, ALN_U}, {"Int", SIZE_I, ALN_I}, {"Char", SIZE_C, ALN_C}, {"Float", SIZE_F, ALN_F}, {"Dbl", SIZE_D, ALN_D}, {"Void", 0}, }; NODEP bas_type(btype) { NODEP rv; static once = 0; if (once == 0) { once++; sprintf(str_ptr.n_name, "Ptr to"); str_ptr.t_token = STAR; str_ptr.n_tptr = bas_type(K_CHAR); str_ptr.n_flags = N_COPYT; str_ptr.t_size = SIZE_P; str_ptr.t_aln = ALN_P; sprintf(fun_int.n_name, "Fun ret"); fun_int.t_token = '('; fun_int.n_tptr = bas_type(K_INT); fun_int.n_flags = N_COPYT; } if (btype == SCON) return &str_ptr; else if (btype == '(') return &fun_int; rv = &basics[btype-FIRST_BAS]; if (rv->t_token == 0) { rv->t_token = btype; rv->t_size = btbl[btype-FIRST_BAS].size; rv->t_aln = btbl[btype-FIRST_BAS].align; sprintf(rv->n_name, btbl[btype-FIRST_BAS].name); } return rv; } /* new function name seen in expr */ NODEP new_fun(op) NODE *op; { NODEP np; NODEP copyone(); /* we know left, right and tptr are NULL */ np = copyone(op); /* ID node */ np->n_tptr = bas_type('('); np->n_flags = N_COPYT; np->e_sc = K_EXTERN; new_sym(symtab, np); return np; } /* declare arg name as int */ def_arg(listpp, op) NODE **listpp, *op; { register NODEP np; NODEP copyone(); np = copyone(op); np->n_tptr = bas_type(K_INT); np->n_flags = N_COPYT; np->e_sc = K_AUTO; new_sym(listpp, np); } /* initialize 0 or 1 thing of any type (tp) */ g_init(tp) register NODEP tp; { int nsee; long sz; int oldsize; int seebr = 0; if (cur->e_token == SCON && tp->t_token == '[' && tp->n_tptr->t_token == K_CHAR) { /* hack for SCON ary */ nsee = out_scon(cur); fadvnode(); a_fix(tp, nsee); return 1; } if (cur->e_token == '{') { fadvnode(); seebr = 1; } switch (tp->t_token) { case '[': if (tp->t_size) oldsize = tp->t_size / tp->n_tptr->t_size; else oldsize = 0; nsee = inita(tp->n_tptr, oldsize); if (nsee) a_fix(tp, nsee); break; case K_STRUCT: o_aln(tp->t_aln); nsee = inits(tp->n_right); break; case K_UNION: o_aln(tp->t_aln); nsee = g_init(tp->n_right->n_tptr); if (nsee) { sz = tp->t_size - tp->n_right->n_tptr->t_size; if (sz) o_nz(sz, 0); } break; default: nsee = init1(tp); break; } if (seebr) { if (cur->e_token == ',') fadvnode(); eat('}'); } return nsee ? 1 : 0; } /* initialize one (or 0) scalar to an expr */ init1(tp) register NODEP tp; { NODEP xp; NODEP assignx(); if (debugi) { printf("init1"); printnode(tp); } xp = assignx(); if (xp) { if (debugi) printnode(xp); o_vinit(tp, xp); return 1; } else return 0; } /* set array size or fill array with zeros */ a_fix(tp, nsee) register NODEP tp; { int oldsize; if (tp->t_size) { oldsize = tp->t_size / tp->n_tptr->t_size; if (oldsize > nsee) { o_nz(tp->n_tptr->t_size * (oldsize-nsee), tp->n_tptr->t_aln); } else if (oldsize < nsee) { error("too many init exprs"); } } else tp->t_size = nsee * tp->n_tptr->t_size; } /* initialize up to max items of type tp */ /* if max is 0, any number is okay */ inita(tp, maxi) NODEP tp; { int nsee; nsee = g_init(tp); if (nsee == 0) return 0; while (cur->e_token == ',') { if (nsee == maxi) break; fadvnode(); nsee += g_init(tp); } return nsee; } /* initialize (possible) structure */ inits(np) register NODEP np; { int see1; see1 = g_init(np->n_tptr); if (see1 == 0) return 0; while (np->n_next) { np = np->n_next; if (cur->e_token == ',') { fadvnode(); see1 = g_init(np->n_tptr); } else see1 = 0; if (see1 == 0) z_init(np->n_tptr); } return 1; } z_init(tp) register NODEP tp; { switch (tp->t_token) { case '[': case K_STRUCT: case K_UNION: o_nz(tp->t_size, tp->t_aln); break; default: out_zi(tp); } } SHAR_EOF cat << \SHAR_EOF > decl.c /* Copyright (c) 1988 by Sozobon, Limited. Author: Johann Ruegg * * Permission is granted to anyone to use this software for any purpose * on any computer system, and to redistribute it freely, with the * following restrictions: * 1) No charge may be made other than reasonable charges for reproduction. * 2) Modified versions must be clearly marked as such. * 3) The authors are not responsible for any harmful consequences * of using this software, even if they result from defects in it. * * decl.c * * Do all declarations * * Currently, * struct tags are local * struct members are tied to the struct * enum tags are ignored * enum members are local */ #include <stdio.h> #include "param.h" #include "tok.h" #include "nodes.h" extern NODE *cur; extern level; NODEP symtab[NHASH], tagtab; extern NODE *blktab; NODEP alltags(), allsyms(), llook(), hlook(); extern int oflags[]; #define debug oflags['v'-'a'] /* look for global data decls return when see something weird return last ID declared */ NODEP glb_decls() { register NODEP head, xp; NODEP d_type(), def_type(), d_declr(); int sclass; for(;;) { sclass = d_scl(HERE_SC); head = d_type(); if (head == NULL) head = def_type(); if (ok_gsh(sclass, head) == 0) continue; more: xp = d_declr(head,0); if (ok_gx(xp,head)) { xp->e_sc = sclass; opt_ginit(xp); new_sym(symtab,xp); if (xp->n_tptr->t_token == '(') { /* func */ if (cur->e_token == ',' || cur->e_token == ';') fix_fun(xp); else return xp; } } if (cur->e_token == ',') { fadvnode(); goto more; } if (cur->e_token == ';') { fadvnode(); } else return NULL; } } /* do local or arg decls return 1 if see something */ loc_decls() { register NODEP head, xp; NODEP d_type(), def_type(), d_declr(); int sclass; int regs; long size; int rv = 0; size = level > 2 ? blktab->n_next->b_size : 0; regs = level > 1 ? blktab->n_next->b_regs : 0; while (is_ty_start()) { rv++; sclass = d_scl(K_AUTO); head = d_type(); if (head == NULL) head = def_type(); if (ok_lsh(sclass, head) == 0) continue; more: xp = d_declr(head,0); if (ok_lx(xp,head)) { xp->e_sc = sclass; if (level > 1) /* not args */ lc_size(&size, ®s, xp); new_sym(&blktab->b_syms,xp); fix_fun(xp); opt_linit(xp,sclass); } if (cur->e_token == ',') { fadvnode(); goto more; } if (cur->e_token == ';') { fadvnode(); } else { error("expect ;"); return 1; } } while (STACKALN & size) size++; blktab->b_size = size; blktab->b_regs = regs; return rv; } /* Decls inside Struct/Union */ su_decls(listpp, isunion, sizep, alnp) NODEP *listpp; long *sizep; char *alnp; { register NODEP head, xp; NODEP d_type(), d_declr(); long size; char aln; int fldw, fldoff; aln = 0; size = 0; fldoff = 0; for(;;) { head = d_type(); if (head == NULL) goto out; if (ok_suh(head) == 0) continue; more: xp = d_declr(head,0); opt_field(xp,&fldw,isunion); if (ok_sux(xp,head)) { if (fldw > 0) { /* handle field */ su_fld(&size,&aln,xp,fldw,&fldoff); xp->e_offs = size; } else { /* handle non-field */ afterfld(&size,&fldoff); xp->e_offs = isunion ? 0 : size; su_size(&size,&aln,xp,isunion); } new_sym(listpp,xp); listpp = &xp->n_next; } else if (fldw == 0) { afterfld(&size, &fldoff); } if (cur->e_token == ',') { fadvnode(); goto more; } if (cur->e_token == ';') { fadvnode(); } else goto out; } out: afterfld(&size,&fldoff); while (aln & size) size++; *sizep = size; *alnp = aln; return; } /* Decls inside Enum */ en_decls() { register NODEP head, xp; NODEP bas_type(), d_declr(); int curval = 0; for(;;) { head = bas_type(K_INT); more: xp = d_declr(head,0); if (ok_enx(xp,head)) { opt_enval(&curval); xp->e_ival = curval++; xp->e_sc = ENUM_SC; new_sym(level ? blktab->b_syms : (NODE *)symtab, xp); } if (cur->e_token == ',') { fadvnode(); goto more; } return; } } /* * called from expr.c, make a cast * only called if is_ty_start(); */ NODE * makecast() { NODEP head, xp; register NODEP np; NODEP d_type(), d_declr(), def_type(); head = d_type(); /* we know this is not NULL */ xp = d_declr(head, 1); if (ok_cast(xp,head) == 0) { xp = def_type(); /* return cast to INT */ } np = allocnode(); np->e_token = TCONV; np->n_tptr = xp; if (xp == head) np->n_flags |= N_COPYT; if (debug) { printf("Make cast"); printnode(np); } return np; } is_ty_start() { NODEP rv; if (is_tykw(cur->e_token)) return 1; if (cur->e_token == ID) { rv = allsyms(cur); if (rv && rv->e_sc == K_TYPEDEF) return 1; } return 0; } /* assemble decl and put in listpp */ new_sym(listpp, xp) NODEP *listpp; NODEP xp; { NODEP old; if (xp == NULL) return 0; /* put in table */ if (debug) { printf("New sym sc %c", "EARTSCH"[xp->e_sc-K_EXTERN]); printnode(xp); } /* later look for previous definition */ if (listpp == (NODE **)symtab) { old = hlook(listpp, xp); if (old == NULL || def2nd(old, xp)) puthlist(listpp, xp); } else { old = llook(*listpp, xp); if (old == NULL || def2nd(old, xp)) putlist(listpp, xp); } return 1; } /* look for storage class */ d_scl(defau) { int rv; if (is_sclass(cur->e_token)) { rv = cur->e_token; fadvnode(); return rv; } /* no storage class specified */ return defau; } NODEP d_declr(head, forcast) NODEP head; { NODEP e1; NODEP declarator(), rev_decl(); NODEP xp, tailp; e1 = declarator(); xp = rev_decl(e1, &tailp, forcast); if (xp) { tailp->n_tptr = head; tailp->n_flags |= N_COPYT; return xp; } else if (forcast) return head; else return NULL; } NODEP rev_decl(np,tailpp,forcast) NODEP np, *tailpp; { NODEP rv, scan, nxt; rv = NULL; for (scan = np; scan != NULL; scan = nxt) { nxt = scan->n_next; scan->n_next = NULL; if (rv == NULL) { *tailpp = scan; scan->n_tptr = NULL; rv = scan; } else { scan->n_tptr = rv; rv = scan; } e_to_t(rv); switch (rv->t_token) { case UNARY '*': sprintf(rv->n_name, "Ptr to"); break; case '(': sprintf(rv->n_name, "Fun ret"); break; case '[': sprintf(rv->n_name, "Ary of"); break; case ID: break; default: error("bad type xpr"); return NULL; } } /* if normal decl and see something, must see id first */ if (!ok_revx(rv,forcast)) rv = NULL; return rv; } /* * Looking for type part of a decl */ NODEP d_type() { int btype, adj; NODEP rv; NODEP bas_type(), decl_su(), decl_enum(); /* look for 'struct', 'union', 'enum' or typedef ID */ switch (cur->e_token) { case ID: rv = allsyms(cur); if (rv && rv->e_sc == K_TYPEDEF) { fadvnode(); rv = rv->n_tptr; return rv; } return NULL; case K_STRUCT: return decl_su(0); case K_UNION: return decl_su(1); case K_ENUM: return decl_enum(); } /* look for modifiers 'long', 'short', 'unsigned' */ adj = 0; while (is_tadj(cur->e_token)) { switch (cur->e_token) { case K_SHORT: adj |= SAW_SHORT; break; case K_LONG: adj |= SAW_LONG; break; case K_UNSIGNED: adj |= SAW_UNS; break; } fadvnode(); } /* look for base type 'char', 'int', 'float', 'double', 'void'*/ if (is_btype(cur->e_token)) { btype = cur->e_token; fadvnode(); } else if (adj == 0) /* saw nothing */ return NULL; else btype = K_INT; if (adj) btype = adj_type(btype, adj); rv = bas_type(btype); return rv; } NODEP decl_enum() { NODEP bas_type(); fadvnode(); /* skip 'enum' */ if (cur->e_token == ID) { /* ignore tag */ fadvnode(); } if (cur->e_token == '{') { /* new declaration */ fadvnode(); /* skip '{' */ en_decls(); /* global scope */ if (cur->e_token != '}') error("expect }"); else fadvnode(); /* skip '}' */ } return bas_type(K_INT); } extern lineno; NODEP decl_su(isunion) { register NODEP rv, tagp; NODEP *attab; fadvnode(); /* skip 'struct' or 'union' */ attab = level ? &blktab->b_tags : &tagtab; tagp = NULL; if (cur->e_token == ID) { /* hold on to ID node */ tagp = cur; e_to_t(tagp); advnode(); nnmadd(tagp, isunion ? ".U" : ".S"); } if (cur->e_token == '{') { /* new declaration */ if (tagp == NULL) { /* make fake name */ tagp = allocnode(); sprintf(tagp->n_name, isunion ? "%dU" : "%dS", lineno); } fadvnode(); /* skip '{' */ if (rv = llook(*attab, tagp)) { freenode(tagp); if (rv->n_right) { errors("struct redefined", rv->n_name); freenode(rv->n_right); rv->n_right = NULL; } } else { /* new defn */ rv = tagp; rv->t_token = isunion ? K_UNION : K_STRUCT; rv->n_flags |= N_BRKPR; /* break print loops */ putlist(attab, rv); } su_decls(&rv->n_right, isunion, &rv->t_size, &rv->t_aln); if (cur->e_token != '}') error("expect }"); else fadvnode(); /* skip '}' */ } else { /* reference to old */ if (tagp == NULL) { error("nonsense struct"); goto out; } /* ANSI special decl struct <tag> ; for hiding old tag within block */ if (cur->e_token == ';' && level) rv = llook(*attab, tagp); else rv = alltags(tagp); if (rv == NULL) { /* delayed tag */ rv = tagp; rv->t_token = isunion ? K_UNION : K_STRUCT; rv->n_flags |= N_BRKPR; /* break print loops */ putlist(attab, rv); goto out; } else freenode(tagp); } out: return rv; } NODE * alltags(np) NODE *np; { register NODE *bp; NODE *rv; for (bp=blktab; bp != NULL; bp = bp->n_next) if ((rv = llook(bp->b_tags, np)) != NULL) return rv; return llook(tagtab, np); } NODE * allsyms(np) NODE *np; { register NODE *bp; NODE *rv; for (bp=blktab; bp != NULL; bp = bp->n_next) if ((rv = llook(bp->b_syms, np)) != NULL) return rv; return hlook(symtab, np); } sim_type(a,b) register NODE *a, *b; { more: if (a == b) return 1; if (a == NULL || b == NULL) return 0; if (a->t_token != b->t_token) return 0; if (a->t_size != b->t_size && a->t_size && b->t_size) return 0; a = a->n_tptr; b = b->n_tptr; goto more; } /* 2nd def of same name at same level */ /* OK if one extern and types the same */ def2nd(old,new) NODEP old, new; { int osc, nsc; if (sim_type(old->n_tptr, new->n_tptr) == 0) goto bad; osc = old->e_sc; nsc = new->e_sc; if (nsc == K_EXTERN) { /* works only if no further use allowed */ freenode(new); return 0; } if (osc == K_EXTERN) { /* replace old def with new one */ /* for now, just put new one on list too */ return 1; } bad: errorn("bad 2nd decl of ", new); /* use 2nd def so other stuff works */ return 1; } /* saw fun but no body */ fix_fun(np) NODE *np; { if (np == NULL) return; if (np->n_tptr->t_token == '(') { /* fix to extern */ if (np->e_sc != K_TYPEDEF) np->e_sc = K_EXTERN; } } e_to_t(np) NODE *np; { int token; token = np->e_token; np->t_token = token; np->t_size = 0; np->t_aln = 0; } SHAR_EOF cat << \SHAR_EOF > expr.c /* Copyright (c) 1988 by Sozobon, Limited. Author: Johann Ruegg * * Permission is granted to anyone to use this software for any purpose * on any computer system, and to redistribute it freely, with the * following restrictions: * 1) No charge may be made other than reasonable charges for reproduction. * 2) Modified versions must be clearly marked as such. * 3) The authors are not responsible for any harmful consequences * of using this software, even if they result from defects in it. * * expr.c * * Expression parse routines * * All routines return either NULL or a valid tree * binop nodes have non-null left and right * unop nodes have non-null left * * Special nodes: * '(' : function call. left:name-expr right:args * ',': if part of function arg list, ival:num. descendants * '?' : ?switch. left:test-expr right:':' part * ':' : left:true-expr right:false-expr * TCONV: left:convertee tptr:type-list * TSIZEOF: tptr:type-list * */ #include <stdio.h> #include "param.h" #include "nodes.h" #include "tok.h" extern NODEP cur; NODEP getnode(); NODEP opt_follow(); extern int oflags[]; #define debug oflags['x'-'a'] advnode() { cur = getnode(); } fadvnode() { freenode(cur); cur = getnode(); } NODEP gete_or_ty() { NODEP getexpr(), makecast(); NODEP rv; if (is_ty_start()) { rv = makecast(); if (debug) { printf("TY_X"); printnode(rv); } return rv; } else return getexpr(); } /* call this for any expr including comma's */ NODEP getexpr() { NODEP np, get_f_expr(); np = get_f_expr(0); return np; } NODEP get_f_expr(flg) int flg; { NODEP assignx(); register NODEP op, lpart, rpart; int i = 0; lpart = assignx(); if (lpart == NULL) { return NULL; } i++; more: if (cur->e_token != ',') return lpart; op = cur; advnode(); rpart = assignx(); if (rpart == NULL) { error("',' expr syntax"); return lpart; } i++; op->n_left = lpart; op->n_right = rpart; op->e_type = E_BIN; op->e_ival = flg ? i : 0; lpart = op; if (debug) { printf("COMMA"); printnode(op); } goto more; } /* call this if you want expr w/o comma's */ NODEP assignx() { NODEP questx(); register NODEP op, lpart, rpart; lpart = questx(); if (lpart == NULL) return NULL; if (!isassign(cur->e_token) && cur->e_token != '=') return lpart; op = cur; advnode(); rpart = assignx(); if (rpart == NULL) { error("'=op' expr syntax"); return lpart; } op->n_left = lpart; op->n_right = rpart; op->e_type = E_BIN; if (debug) { printf("ASSIGN"); printnode(op); } return op; } /* call this if you want expr w/o assign's or comma's */ /* i.e. constant-expression */ NODEP questx() { NODEP binary(); register NODEP holdq, holdc; NODEP qpart, tpart, fpart; qpart = binary(); if (qpart == NULL) return NULL; if (cur->e_token != '?') return qpart; holdq = cur; advnode(); tpart = questx(); if (tpart == NULL || cur->e_token != ':') { bad: error("'?:' expr syntax"); return qpart; } holdc = cur; advnode(); fpart = questx(); if (fpart == NULL) goto bad; holdc->n_left = tpart; holdc->n_right = fpart; holdc->e_type = E_BIN; holdq->n_left = qpart; holdq->n_right = holdc; holdq->e_type = E_BIN; if (debug) { printf("QUEST"); printnode(holdq); } return holdq; } NODEP binary() { NODEP unary(), buildbin(); register NODEP rv, op, e2; rv = unary(); if (rv == NULL) return NULL; rv->e_prec = 0; more: if (cur->e_prec == 0) /* not binary op */ return rv; op = cur; advnode(); e2 = unary(); if (e2 == NULL) { error("bin-op expr syntax"); return rv; } e2->e_prec = 0; rv = buildbin(rv, op, e2); if (debug) { printf("BINARY"); printnode(rv); } goto more; } NODEP buildbin(lpart, op, upart) NODEP lpart, op, upart; { register NODEP look, tail; NODEP rv; tail = NULL; look = lpart; for (look=lpart; op->e_prec < look->e_prec; look=look->n_right) tail = look; if (tail == NULL) { op->n_left = lpart; op->n_right = upart; rv = op; } else { tail->n_right = op; op->n_left = look; op->n_right = upart; rv = lpart; } op->e_type = E_BIN; return rv; } NODEP unary() { register NODEP tp,e1; NODEP primary(); if (cur->e_flags & CAN_U) { tp = cur; advnode(); if (tp->e_prec) { /* also have BINARY op */ tp->e_token = UNARY tp->e_token; strcat(tp->n_name, "U"); } tp->n_left = unary(); tp->e_type = E_UNARY; goto check; } else switch (cur->e_token) { case '(': fadvnode(); tp = gete_or_ty(); if (cur->e_token != ')') { error("missing )"); } else fadvnode(); if (tp == NULL) return NULL; if (tp->e_token == TCONV && tp->n_left == NULL) { sprintf(tp->n_name, "cast to"); tp->n_left = unary(); tp->e_type = E_UNARY; } else { tp = opt_follow(tp); goto out; } goto check; case K_SIZEOF: tp = cur; advnode(); if (cur->e_token == '(') { /* may be type expr */ fadvnode(); e1 = gete_or_ty(); if (cur->e_token != ')') { error("missing )"); } else fadvnode(); } else e1 = unary(); if (e1 == NULL) { error("sizeof expr syntax"); return NULL; } if (e1->e_token == TCONV) { freeunit(tp); e1->e_token = TSIZEOF; sprintf(e1->n_name, "T-sizeof"); tp = e1; tp->e_type = E_LEAF; goto out; } else { tp->e_type = E_UNARY; tp->n_left = e1; } goto check; default: tp = primary(); goto out; } check: if (tp == NULL) return NULL; if (tp->n_left == NULL) { error("u-op expr syntax"); return NULL; } out: if (debug) { printf("UNARY"); printnode(tp); } return tp; } NODEP primary() { register NODEP e1; switch (cur->e_token) { case ID: case ICON: case FCON: case SCON: e1 = cur; e1->e_type = E_LEAF; advnode(); break; case '(': fadvnode(); e1 = getexpr(); if (cur->e_token != ')') error("missing )"); else fadvnode(); break; default: e1 = NULL; } if (e1 == NULL) return NULL; return opt_follow(e1); } NODEP opt_follow(np) NODEP np; { register NODEP tp, e1, t2; switch (cur->e_token) { case '[': tp = cur; advnode(); e1 = getexpr(); if (cur->e_token != ']') { error("missing ]"); return np; } else { t2 = cur; advnode(); } if (e1 == NULL) { error("empty []"); return np; } t2->n_left = np; t2->n_right = e1; t2->e_type = E_BIN; t2->e_token = '+'; strcpy(t2->n_name, "+ ["); tp->n_left = t2; tp->e_type = E_UNARY; tp->e_token = STAR; strcpy(tp->n_name, "U*"); goto out; case '(': tp = cur; advnode(); e1 = get_f_expr(1); if (cur->e_token != ')') error("expect )"); else fadvnode(); tp->n_left = np; tp->n_right = e1; tp->e_type = E_SPEC; goto out; case '.': case ARROW: tp = cur; advnode(); if (cur->e_token != ID) { error("expect ID"); return np; } tp->n_left = np; tp->n_right = cur; tp->e_type = E_SPEC; if (tp->e_token == ARROW) { /* make into (*X).Y */ tp->e_token = '.'; strcpy(tp->n_name, "."); t2 = allocnode(); t2->e_token = STAR; t2->n_left = np; t2->e_type = E_UNARY; strcpy(t2->n_name, "U*"); tp->n_left = t2; } advnode(); goto out; case DOUBLE '+': case DOUBLE '-': tp = cur; advnode(); tp->e_token = (tp->e_token == DOUBLE '+') ? POSTINC : POSTDEC; strcat(tp->n_name, "post"); tp->n_left = np; tp->e_type = E_UNARY; goto out; default: return np; } out: return opt_follow(tp); } /* restricted version of unary for declarations or coertions */ /* allows NULL primary part */ NODEP declarator() { register NODEP tp,e1; NODEP ty_primary(), ty_follow(); if (cur->e_token == '*') { tp = cur; tp->e_token = UNARY tp->e_token; strcat(tp->n_name, "U"); advnode(); tp->n_left = declarator(); return tp; } else switch (cur->e_token) { case '(': tp = cur; advnode(); e1 = declarator(); if (cur->e_token != ')') { error("expect )"); } else fadvnode(); if (e1 == NULL) { /* special "fun of" */ /* left and right already NULL */ return ty_follow(tp); } else { freeunit(tp); return ty_follow(e1); } default: return ty_primary(); } } /* restricted version of primary for "declarator" */ NODEP ty_primary() { register NODEP e1; NODEP ty_follow(); switch (cur->e_token) { case ID: e1 = cur; advnode(); break; case '(': fadvnode(); e1 = declarator(); if (cur->e_token != ')') error("expect )"); else fadvnode(); break; default: e1 = NULL; } return ty_follow(e1); } /* restricted version of opt_follow for 'declarator' */ /* allow null [] */ NODEP ty_follow(np) NODEP np; { register NODEP tp, e1; NODEP ty_args(); switch (cur->e_token) { case '[': tp = cur; advnode(); e1 = questx(); if (cur->e_token != ']') error("expect ]"); else fadvnode(); tp->n_left = np; tp->n_right = e1; goto out; case '(': tp = cur; advnode(); e1 = ty_args(); /* allow args of fun to follow */ if (cur->e_token != ')') error("expect )"); else fadvnode(); tp->n_left = np; tp->n_right = e1; goto out; default: return np; } out: return ty_follow(tp); } /* called for args of function declaration or NULL */ NODEP ty_args() { NODEP opt_id(); register NODEP rv, tail, new; rv = opt_id(); if (rv == NULL) return NULL; tail = rv; more: if (cur->e_token != ',') return rv; fadvnode(); new = opt_id(); if (new == NULL) { error("expect as-op value"); return rv; } tail->n_left = new; tail = new; goto more; } NODEP opt_id() { NODEP rv; if (cur->e_token == ID) { rv = cur; advnode(); return rv; } else return NULL; } SHAR_EOF cat << \SHAR_EOF > fix.c /* Copyright (c) 1988 by Sozobon, Limited. Author: Johann Ruegg * * Permission is granted to anyone to use this software for any purpose * on any computer system, and to redistribute it freely, with the * following restrictions: * 1) No charge may be made other than reasonable charges for reproduction. * 2) Modified versions must be clearly marked as such. * 3) The authors are not responsible for any harmful consequences * of using this software, even if they result from defects in it. * * fix.c * * Motorola has is not consistent in what operations allow * which operands. This section compensates for that -- * tries to find the best way to do something. */ #include <stdio.h> #include "param.h" #include "nodes.h" #include "flags.h" #include "bstok.h" #include "gen.h" #include "ops.h" #define FAIL 0 #define OKAY 1 #define CL_IMM IOPD #define CL_AREG AOPD #define CL_DREG DOPD #define CL_ADR MOPD #define RETAREG 0x100 #define RETDREG 0x200 #define RETLEFT 0x400 #define RETRIGHT 0x800 #define LISTMP 1 #define RISTMP 2 #define NDASSOC 4 #define CANRL 8 #define CANLR 0x10 #define CANRD 0x20 #define CANDL 0x40 #define CANLD 0x80 #define CANDD 0x100 #define CANDR 0x200 struct mtbl { int restr; char *code; int needregs; } tbl2[] = { {LISTMP|CANRL, "\tN.S\t>A,<A\n", RETLEFT}, {RISTMP|CANLR|NDASSOC, "\tN.S\t<A,>A\n", RETRIGHT}, {CANRD, "\tmove.S\t<A,A\n\tN.S\t>A,A\n", RETDREG}, {CANLD|NDASSOC, "\tmove.S\t>A,A\n\tN.S\t<A,A\n", RETDREG}, /* only EOR and shifts get to here */ {CANDL|LISTMP, "\tmove.S\t>A,R1\n\tN.S\tR1,A\n", RETLEFT|1}, {CANDR|RISTMP|NDASSOC, "\tmove.S\t<A,R1\n\tN.S\tR1,A\n", RETRIGHT|1}, {CANDD, "\tmove.S\t<A,A\n\tmove.S\t>A,R1\n\tN.S\tR1,A\n", RETDREG|1}, {0} }; struct mtbl tblmul[] = { {CANRL|LISTMP, "\tmulU\t>A,<A\n", RETLEFT}, {CANLR|RISTMP, "\tmulU\t<A,>A\n", RETRIGHT}, {CANRD, "\tmove.w\t>A,A\n\tmulU\t<A,A\n", RETDREG}, {0} }; struct mtbl tbldiv[] = { {CANRL|LISTMP, "\text.l\t<A\n\tdivs\t>A,<A\n", RETLEFT}, {CANRD, "\tmove.w\t<A,A\n\text.l\tA\n\tdivs\t>A,A\n", RETDREG}, {0} }; struct mtbl tbludiv[] = { {CANRD, "\tclr.l\tA\n\tmove.w\t<A,A\n\tdivu\t>A,A\n", RETDREG}, {0} }; struct mtbl tblc[] = { {CANRL, "\tcmp.<S\t>A,<A\n", 0}, {CANRD, "\tmove.<S\t<A,R1\n\tcmp.<S\t>A,R1\n", 1}, /* shouldnt get to here! */ {CANDL, "\tmove.<S\t>A,R1\n\tcmp.<S\tR1,<A\n", 1}, {CANDD, "\tmove.<S\t>A,R1\n\tmove.<S\t<A,R2\n\tcmp.<S\tR1,R2\n", 2}, {0} }; struct mtbl tblas[] = { {CANRL, "\tN.S\t>A,<A\n", RETLEFT}, {CANDL, "\tmove.S\t>A,R1\n\tN.S\tR1,A\n", 1|RETLEFT}, /* only MUL, DIV and shifts should get to here */ {CANRD, "\tmove.S\t<A,A\n\tN.S\t>A,A\n\tmove.S\tA,<A\n", RETDREG}, {CANLD|NDASSOC, "\tmove.S\t>A,A\n\tN.S\t<A,A\n\tmove.S\tA,<A\n", RETDREG}, {CANDD, "\tmove.S\t<A,A\n\tmove.S\t>A,R1\n\tN.S\tR1,A\n\tmove.S\tA,<A\n", RETDREG|1}, {0} }; struct mtbl tblamul[] = { {CANRL, "\tmulU\t>A,<A\n", RETLEFT}, {CANLR|RISTMP, "\tmulU\t<A,>A\n\tmove.w\t>A,<A\n", RETRIGHT}, {CANRD, "\tmove.w\t<A,A\n\tmulU\t>A,A\n\tmove.w\tA,<A\n", RETDREG}, {0} }; struct mtbl tbladiv[] = { {CANRL, "\text.l\t<A\n\tdivs\t>A,<A\n", RETLEFT}, {CANRD, "\tmove.w\t<A,A\n\text.l\tA\n\tdivs\t>A,A\n\tmove.w\tA,<A\n", RETDREG}, {0} }; struct mtbl tbluadiv[] = { {CANRD, "\tclr.l\tA\n\tmove.w\t<A,A\n\tdivu\t>A,A\n\tmove.w\tA,<A\n", RETDREG}, {0} }; struct mtbl tblamod[] = { {CANRL, "\text.l\t<A\n\tdivs\t>A,<A\n\tswap\t<A\n", RETLEFT}, {CANRD, "\tmove.w\t<A,A\n\text.l\tA\n\tdivs\t>A,A\n\tswap\tA\n\tmove.w\tA,<A\n", RETDREG}, {0} }; struct mtbl tbluamod[] = { {CANRD, "\tclr.l\tA\n\tmove.w\t<A,A\n\tdivu\t>A,A\n\tswap\tA\n\tmove.w\tA,<A\n", RETDREG}, {0} }; class(np) NODEP np; { switch (np->g_token) { case ICON: return CL_IMM; case ONAME: return (np->g_flags & IMMEDID) ? CL_IMM : CL_ADR; case OREG: return (np->g_flags & IMMEDID) ? CL_IMM : CL_ADR; case PUSHER: return CL_ADR; case REGVAR: if (np->g_rno < AREG) return CL_DREG; else return CL_AREG; default: printf("Weird class "); return CL_IMM; } } int canswap; NODEP matchnp; fix_cmp(np, flags) NODEP np; { NODEP rp = np->n_right; /* special stuff for ICON 0 */ if (rp->g_token == ICON && rp->g_offs == 0 && (rp->g_flags & IMMEDID)) { addcode(np, "<Q"); return OKAY; } canswap = 0; return fix_sub(np, flags, tblc); } fix2ops(np, flags) NODEP np; { canswap = flags & ASSOC; return fix_sub(np, flags, tbl2); } fixmul(np, flags) NODEP np; { return fix_sub(np, flags, tblmul); } fixdiv(np, flags) NODEP np; { return fix_sub(np, flags, np->g_ty == ET_U ? tbludiv : tbldiv); } fixmod(np, flags) NODEP np; { int r; r = fixdiv(np, flags); addcode(np, "\tswap\tA\n"); return r; } fixamul(np, flags) NODEP np; { return fix_sub(np, flags, tblamul); } fixadiv(np, flags) NODEP np; { return fix_sub(np, flags, np->g_ty == ET_U ? tbluadiv : tbladiv); } fixamod(np, flags) NODEP np; { return fix_sub(np, flags, np->g_ty == ET_U ? tbluamod : tblamod); } fix_asn(np, flags) NODEP np; { canswap = 0; return fix_sub(np, flags, tblas); } fix_sub(np, flags, tbl) register NODEP np; struct mtbl *tbl; { NODEP lp = np->n_left, rp = np->n_right; int lclass, rclass; register struct mtbl *p; int rv; lclass = class(lp); rclass = class(rp); matchnp = np; for (p = tbl; p->restr; p++) if ((rv = cando(flags, p->restr, lclass, rclass))) { dotbl(p, np); return OKAY; } printf("no code table match! "); return FAIL; } dotbl(p, np) struct mtbl *p; NODEP np; { register int i, k; if (p->needregs) { i = p->needregs; if (i & RETLEFT) inherit(np); else if (i & RETRIGHT) rinherit(np); else if (i & RETAREG) retreg(np, ralloc(AREG)); else if (i & RETDREG) retreg(np, ralloc(0)); k = i & 7; while (k--) tempr(np, 0); k = (i/AREG) & 7; while (k--) tempr(np, AREG); } addcode(np, p->code); } #define canflag(l,r) (l << cansh[r]) short cansh[] = {0, 0, 4, 0, 8, 0, 0, 0, 12}; cando(flags, restr, lc, rc) register restr; { NODEP lp = matchnp->n_left, rp = matchnp->n_right; if (restr & RISTMP) { if ((rc & (CL_DREG|CL_AREG)) == 0 || istemp(rp->g_rno) == 0) return 0; } else if (restr & LISTMP) { if ((lc & (CL_DREG|CL_AREG)) == 0 || istemp(lp->g_rno) == 0) return 0; } if (restr & NDASSOC) { if (canswap == 0) return 0; } if (restr & (CANLR|CANLD)) { flags |= quickflag(lp, flags); } else if (restr & (CANRL|CANRD)) { flags |= quickflag(rp, flags); } flags &= 0xfff; if (restr & CANLR) { if ((flags & canflag(lc,rc)) == 0) return 0; } else if (restr & CANRL) { if ((flags & canflag(rc,lc)) == 0) return 0; } else if (restr & CANRD) { if ((flags & canflag(rc,CL_DREG)) == 0) return 0; } else if (restr & CANDL) { if ((flags & canflag(CL_DREG,lc)) == 0) return 0; } else if (restr & CANLD) { if ((flags & canflag(lc,CL_DREG)) == 0) return 0; } else if (restr & CANDR) { if ((flags & canflag(CL_DREG,rc)) == 0) return 0; } else if (restr & CANDD) { if ((flags & DOPD) == 0) return 0; } return 1; } quickflag(np, flags) NODEP np; { long offs; if (np->g_token != ICON) return 0; offs = np->g_offs; if ((flags & QOPD) && np->g_offs >= 1 && np->g_offs <= 8) return IOPD; if ((flags & ONEOPM) && np->g_offs == 1) return IOPM; return 0; } /* * stuff to do field extract and field assign * Yes, this stuff can be optimized a lot more ... feel free */ fldget(np, flags) register NODEP np; { int how; how = 1; if (np->g_fldo == 0) how = 0; /* no shift needed */ else if (np->g_fldo > 8) how = 2; /* shift too big for immediate */ np->n_left->g_offs += np->g_offs; /* major HACK, hope it works */ retreg(np, ralloc(0)); addcode(np, "\tmove\t<A,A\n"); /* get word */ if (how) /* shift to position */ addcode(np, how==1 ? "\tlsr\t#Y,A\n" : "\tlsr\t#8,A\n\tlsr\t#Z,A\n"); addcode(np, "\tand\t#W,A\n"); /* mask off top */ return OKAY; } fldasn(np, flags) register NODEP np; { int how; how = 1; if (np->g_fldo == 0) how = 0; /* no shift needed */ else if (np->g_fldo > 8) how = 2; /* shift too big for immediate */ retreg(np, ralloc(0)); tempr(np, 0); addcode(np, "\tmove\t>A,A\n"); /* value */ if (needmask(np)) /* mask off high bits */ addcode(np, "\tand\t#W,A\n"); if (how) /* shift into position */ addcode(np, how==1 ? "\tlsl\t#Y,A\n" : "\tlsl\t#8,A\n\tlsl\t#Z,A\n"); addcode(np, "\tmove\t<A,R1\n"); /* old value */ addcode(np, "\tand\t#X,R1\n"); /* mask out old value */ addcode(np, "\tor\tA,R1\n"); /* set new field */ addcode(np, "\tmove\tR1,<A\n"); /* store new word */ if (how && (flags & NOVAL_OK) == 0) /* return value */ addcode(np, how==1 ? "\tlsr\t#Y,A\n" : "\tlsr\t#8,A\n\tlsr\t#Z,A\n"); return OKAY; } needmask(np) register NODEP np; { NODEP lp = np->n_left; if (np->g_fldw + np->g_fldo >= 16) return 0; if (lp->g_token != ICON) return 1; if ((int)lp->g_offs & ~ones(np->g_fldw)) { warn("value too big for field"); return 1; } return 0; } SHAR_EOF cat << \SHAR_EOF > fun.c /* Copyright (c) 1988 by Sozobon, Limited. Author: Johann Ruegg * * Permission is granted to anyone to use this software for any purpose * on any computer system, and to redistribute it freely, with the * following restrictions: * 1) No charge may be made other than reasonable charges for reproduction. * 2) Modified versions must be clearly marked as such. * 3) The authors are not responsible for any harmful consequences * of using this software, even if they result from defects in it. * * fun.c * * Handle function entry, exit, etc. * Parse statements. * Also, general syntax error recovery strategy. */ #include <stdio.h> #include "param.h" #include "tok.h" #include "nodes.h" #include "cookie.h" #if MMCC overlay "pass2" #endif extern NODE *cur; int level; NODE *blktab; NODE *labels; struct swittbl { NODEP caselist; int deflbl; } *curswit; int curbrk, curcont; int funtopl, funbotl, funretl, funstrl; NODEP funtyp; int maxregs; long maxlocs; int skipon; NODEP glb_decls(); extern int oflags[]; #define debugl oflags['l'-'a'] #define debugs oflags['s'-'a'] #define debugv oflags['v'-'a'] findtok(x) { while (cur->e_token != EOFTOK && cur->e_token != x) fadvnode(); if (cur->e_token == EOFTOK) exit(1); } extern NODEP symtab[]; program() { NODEP last; skipon = 0; more: last = glb_decls(); if (cur->e_token == EOFTOK) return; if (last) skipon = 0; /* saw something valid */ if (last && last->n_tptr && last->n_tptr->t_token == '(') { /* possible function definition */ if (debugs) { printf("FUN "); put_nnm(last); } out_fstart(last); last->e_sc = K_EXTERN; fun_start(last->n_tptr); args_blk(last->n_tptr->n_right); sub_block(); fun_end(); clr_lvl(); /* for args block */ goto more; } /* error if get to here */ if (last) { error("missing ;"); goto more; } else { skip(); goto more; } } fun_start(np) NODEP np; { NODEP functy(); funtyp = functy(np); curbrk = curcont = -1; funtopl = new_lbl(); funbotl = new_lbl(); funretl = new_lbl(); switch (funtyp->t_token) { case K_STRUCT: case K_UNION: funstrl = new_lbl(); break; default: funstrl = 0; } maxregs = 0; maxlocs = 0; out_br(funbotl); def_lbl(funtopl); } fun_end() { NODEP np; if (labels) { for (np = labels; np; np = np->n_next) if (np->c_defined == 0) errorn("undefined label", np); freenode(labels); labels = NULL; } def_lbl(funretl); out_fret(maxregs, funstrl); def_lbl(funbotl); out_fend(maxregs, maxlocs); out_br(funtopl); if (funstrl) out_fs(funstrl, funtyp->t_size); } skip() { if (skipon == 0) { error("syntax (try skipping...)"); skipon = 1; } fadvnode(); } block() { int some; int sawsome; some = loc_decls(); if (cur->e_token == EOFTOK) return; if (some) skipon = 0; more: sawsome = stmts(); if (sawsome) skipon = 0; if (cur->e_token == '}') { if (blktab->b_regs > maxregs) maxregs = blktab->b_regs; if (blktab->b_size + blktab->b_tsize > maxlocs) maxlocs = blktab->b_size + blktab->b_tsize; return; } /* error if get to here */ if (cur->e_token == EOFTOK || is_tykw(cur->e_token)) /* get out of block */ return; else { skip(); goto more; } } clr_lvl() { NODE *bp; level--; bp = blktab; blktab = bp->n_next; bp->n_next = NULL; if (debugl && bp->b_syms) { printf("local syms %d", level); printlist(bp->b_syms); } freenode(bp->b_syms); if (debugl && bp->b_tags) { printf("local tags %d", level); printlist(bp->b_tags); } freenode(bp->b_tags); freenode(bp); } eat(c) { char *p = "assume X"; if (cur->e_token == c) fadvnode(); else { p[strlen(p) - 1] = c; error(p); } } sub_block() { register NODE *new; if (debugs) printf("{ "); eat('{'); level++; new = allocnode(); new->n_next = blktab; sprintf(new->n_name, "sub{"); blktab = new; block(); clr_lvl(); eat('}'); if (debugs) printf("}\n"); } args_blk(np) NODEP np; { register NODE *p; register NODE *new; NODE *tp; NODEP llook(); long size; int rmask; size = 0; rmask = 0; new = allocnode(); new->n_next = blktab; sprintf(new->n_name, "arg{"); blktab = new; level++; loc_decls(); /* make sure all decls were in arg list */ for (p=new->b_syms; p != NULL; p = p->n_next) if (llook(np, p) == NULL) errorn("ID not param", p); /* now make any names not mentioned INT */ /* and generate offsets and alloc regs */ for (p=np; p != NULL; p = p->n_next) { if ((tp=llook(new->b_syms, p)) == NULL) { def_arg(&new->b_syms, p); tp = new->b_syms; } lc_size(&size, &rmask, tp); if (tp->e_sc == K_REGISTER) reg_arg(&rmask, tp); if (debugv) { printf("final o%ld r%d ", tp->e_offs, tp->e_rno); put_nnm(tp); putchar('\n'); } } new->b_regs = rmask; } reg_arg(rp, xp) int *rp; NODEP xp; { if (lc_reg(rp, xp) == 0) { /* out of regs? */ xp->e_sc = K_AUTO; return; } out_argreg(xp); } stmts() { int didsome; didsome = 0; while (stmt()) didsome++; return didsome; } stmt_bc(brk,cont) { int svb, svc; svb = curbrk; svc = curcont; curbrk = brk; curcont = cont; stmt(); curbrk = svb; curcont = svc; } stmt_b(brk) { int svb; svb = curbrk; curbrk = brk; stmt(); curbrk = svb; } /* do a single statement */ stmt() { register tok; NODEP np; NODEP getexpr(); int i; more: tok = cur->e_token; if (is_stkw(tok)) { if (is_blkst(tok)) { i = blk_stmt(); } else if (is_brast(tok)) { i = bra_stmt(); } else if (is_lblst(tok)) { i = lbl_stmt(); } else i = asm_stmt(); if (i == 0) goto more; return 1; } else if (tok == '{') { sub_block(); return 1; } else if (tok == ';') { fadvnode(); return 1; } np = getexpr(); if (np) { if (cur->e_token == ':') { fadvnode(); label(np); goto more; } expr_stmt(np); if (cur->e_token != ';') error("missing ;"); else fadvnode(); return 1; } return 0; } expr_stmt(np) NODEP np; { if (debugs) { printf("E_STMT "); if (debugs > 1) printnode(np); } do_expr(np, FORSIDE); } label(np) NODEP np; { register NODEP tp; NODEP llook(); if (debugs) { printf("LABEL "); if (debugs > 1) printnode(np); } if (np->e_token != ID) { error("weird label"); return; } tp = llook(labels, np); if (tp) { freenode(np); if (tp->c_defined) { error("duplicate label"); return; } } else { putlist(&labels, np); tp = np; tp->c_casel = new_lbl(); } tp->c_defined = 1; def_lbl(tp->c_casel); } extern int lineno; blk_stmt() { register tok; int l1, l2, l3; NODEP e1, e2, e3; NODEP opt_expr(), paren_expr(), def_type(); struct swittbl locswit, *oldp; int svline, svline2; tok = cur->e_token; fadvnode(); switch (tok) { case K_IF: if (debugs) printf("IF "); l1 = new_lbl(); e1 = paren_expr(); gen_brf(e1, l1); eat(')'); stmt(); opt_else(l1); return 1; case K_WHILE: if (debugs) printf("WHILE "); e1 = paren_expr(); l1 = new_lbl(); l2 = new_lbl(); def_lbl(l1); gen_brf(e1,l2); eat(')'); stmt_bc(l2,l1); out_br(l1); def_lbl(l2); return 1; case K_DO: if (debugs) printf("DO "); l1 = new_lbl(); l2 = new_lbl(); l3 = new_lbl(); def_lbl(l1); stmt_bc(l3,l2); def_lbl(l2); eat(K_WHILE); e1 = paren_expr(); gen_brt(e1, l1); eat(')'); eat(';'); def_lbl(l3); return 1; case K_FOR: if (debugs) printf("FOR "); l1 = new_lbl(); l2 = new_lbl(); l3 = new_lbl(); eat('('); e1 = opt_expr(); expr_stmt(e1); eat(';'); def_lbl(l1); e2 = opt_expr(); if (e2) gen_brf(e2,l3); eat(';'); e3 = opt_expr(); /* save for later */ svline = lineno; eat(')'); stmt_bc(l3,l2); def_lbl(l2); svline2 = lineno; lineno = svline; expr_stmt(e3); lineno = svline2; out_br(l1); def_lbl(l3); return 1; case K_SWITCH: if (debugs) printf("SWITCH "); e1 = paren_expr(); l1 = new_lbl(); l2 = new_lbl(); to_d0(e1, def_type()); eat(')'); out_br(l2); oldp = curswit; curswit = &locswit; locswit.caselist = NULL; locswit.deflbl = -1; stmt_b(l1); out_br(l1); def_lbl(l2); gen_switch(locswit.caselist, locswit.deflbl); curswit = oldp; def_lbl(l1); return 1; case K_ELSE: error("unexpected 'else'"); fadvnode(); return 0; } } NODEP paren_expr() { NODEP np; NODEP need_expr(); eat('('); np = need_expr(); return np; } bra_stmt() { register tok; NODEP np, tp; NODEP opt_expr(), llook(); tok = cur->e_token; fadvnode(); switch (tok) { case K_BREAK: if (debugs) printf("BRK"); eat(';'); out_br(curbrk); return 1; case K_CONTINUE: if (debugs) printf("CONT "); eat(';'); out_br(curcont); return 1; case K_RETURN: if (debugs) printf("RETURN "); np = opt_expr(); if (np) { if (funstrl) ret_stru(np); else to_d0(np, funtyp); } out_br(funretl); eat(';'); return 1; case K_GOTO: if (debugs) printf("GOTO "); np = cur; advnode(); if (np->e_token != ID) error("bad goto"); else { tp = llook(labels, np); if (tp) { freenode(np); } else { tp = np; putlist(&labels, tp); tp->c_casel = new_lbl(); } out_br(tp->c_casel); } eat(';'); return 1; } } lbl_stmt() { register tok; NODEP need_expr(), np; int l1, i; l1 = new_lbl(); tok = cur->e_token; again: fadvnode(); switch (tok) { case K_CASE: if (debugs) printf("CASE "); np = need_expr(); i = conxval(np); add_case(i,l1); eat(':'); break; case K_DEFAULT: if (debugs) printf("DEFAULT "); if (curswit->deflbl >= 0) error("multiple 'default'"); curswit->deflbl = l1; eat(':'); } tok = cur->e_token; /* lookahead for more cases */ if (tok == K_CASE || tok == K_DEFAULT) goto again; def_lbl(l1); return 0; } asm_stmt() { NODEP np, getexpr(); fadvnode(); np = getexpr(); if (np == NULL || np->e_token != SCON) { error("bad asm() func"); } else { out_asm(np); freenode(np); } eat(';'); } NODEP opt_expr() { NODE *np, *getexpr(); np = getexpr(); if (np) { if (debugs) { printf("OXPR "); if (debugs > 1) printnode(np); } } return np; } NODEP need_expr() { NODE *np, *getexpr(); np = getexpr(); if (np) { if (debugs) { printf("NXPR "); if (debugs > 1) printnode(np); } } else error("need expr"); return np; } opt_else(l1) { int l2; if (cur->e_token == K_ELSE) { if (debugs) printf("ELSE "); fadvnode(); l2 = new_lbl(); out_br(l2); def_lbl(l1); stmt(); def_lbl(l2); } else def_lbl(l1); } add_case(val, lbl) { NODEP np, last, p; np = allocnode(); np->c_casev = val; np->c_casel = lbl; sprintf(np->n_name, "%d:%d", val, lbl); last = NULL; for (p = curswit->caselist; p; last=p, p=p->n_next) if (p->c_casev == val) { error("duplicate case"); return; } else if (p->c_casev > val) break; if (last) { last->n_next = np; np->n_next = p; } else { curswit->caselist = np; np->n_next = p; } if (debugs) { printf("CASELIST\n"); printnode(curswit->caselist); } } to_d0(np, typ) NODEP np, typ; { NODEP tp; tp = allocnode(); tp->e_token = TCONV; tp->n_tptr = typ; tp->n_flags |= N_COPYT; tp->n_left = np; tp->e_type = E_UNARY; strcpy(tp->n_name, "r cast"); do_expr(tp, IND0); } ret_stru(np) NODEP np; { p2_expr(&np); if (same_type(np->n_tptr, funtyp) == 0) { error("bad struct return type"); return; } genx(np, RETSTRU); } SHAR_EOF cat << \SHAR_EOF > g2.c /* Copyright (c) 1988 by Sozobon, Limited. Author: Johann Ruegg * * Permission is granted to anyone to use this software for any purpose * on any computer system, and to redistribute it freely, with the * following restrictions: * 1) No charge may be made other than reasonable charges for reproduction. * 2) Modified versions must be clearly marked as such. * 3) The authors are not responsible for any harmful consequences * of using this software, even if they result from defects in it. * * g2.c * * Generate code for binary nodes. */ #include <stdio.h> #include "param.h" #include "nodes.h" #include "flags.h" #include "bstok.h" #include "gen.h" #include "ops.h" #define FAIL 0 #define OKAY 1 extern int cookflags[]; #define isimmed(np) ((np)->g_flags & IMMEDID) #define isareg(np) ((np)->g_token == REGVAR && (np)->g_rno >= AREG) struct bop { char *s_op, *u_op; int opflags; } bops[] = { {"muls", "mulu", EOPD |ASSOC}, {"divs", "divu", EOPD}, {"divs", "divu", EOPD}, {"and", "and", EOPD|DOPE|IOPE |ASSOC}, {"or", "or", EOPD|DOPE|IOPE |ASSOC}, {"eor", "eor", DOPE|IOPE |ASSOC}, {"add", "add", EOPD|DOPE|EOPA|IOPE|AOPA|AOPD |ASSOC}, {"sub", "sub", EOPD|DOPE|EOPA|IOPE|AOPA|AOPD}, {"asl", "lsl", DOPD|QOPD|ONEOPM}, {"asr", "lsr", DOPD|QOPD|ONEOPM}, }; char *tstnm[] = { "lt", /* < */ "gt", /* > */ "le", /* <= */ "ge", /* >= */ "eq", /* == */ "ne", /* != */ }; int tstx[] = { B_LT, B_GT, B_LE, B_GE, B_EQ, B_NE }; char *utstnm[] = { "cs", /* < */ "hi", /* > */ "ls", /* <= */ "cc", /* >= */ "eq", /* == */ "ne", /* != */ }; int utstx[] = { B_ULT, B_UGT, B_ULE, B_UGE, B_EQ, B_NE }; b_eval(np, cookie) register NODEP np; { NODEP lp = np->n_left, rp = np->n_right; NODEP tp; int lcook = FORADR, rcook = FORADR; switch (np->g_token) { /* special cookies */ case DOUBLE '&': case DOUBLE '|': lcook = rcook = FORCC; break; case '?': lcook = FORCC; break; case '(': rcook = FORPUSH; break; case ',': if (np->g_offs) /* function args */ lcook = rcook = FORPUSH; else { lcook = FORSIDE; rcook = cookie; } break; case '=': rcook = FORIMA; break; case '+': case '-': tp = rp; while (tp->g_token == TCONV && tp->g_ty != ET_F) tp = tp->n_left; if (tp->g_token == ICON) lcook = FORIMA; break; } if (np->g_type == EV_LR) { if (eval(lp,lcook) == FAIL) return FAIL; freetmps(lp); if (eval(rp,rcook) == FAIL) return FAIL; freetmps(rp); } else if (np->g_type == EV_RL) { if (eval(rp,rcook) == FAIL) return FAIL; freetmps(rp); if (eval(lp,lcook) == FAIL) return FAIL; freetmps(lp); } else { /* EV_LRSEP */ if (eval(lp,lcook) == FAIL) return FAIL; freetmps(lp); free1(NULL, lp); if (eval(rp,rcook) == FAIL) return FAIL; freetmps(rp); } return b_sube(np, cookflags[cookie]); } b_sube(np, flags) register NODEP np; { NODEP lp = np->n_left, rp = np->n_right; register int i, r; int argsize; char buf[40]; if (isassign(np->g_token)) return as_eval(np); switch (np->g_token) { case '=': if (specasn(np, flags) || strasn(np)) return OKAY; inherit(np); addcode(np, "\tmove.S\t>A,<A\n"); return OKAY; case '(': argsize = argmod(rp); free1(NULL,rp); if (np->g_ty == ET_A) { /* struct returned */ frc_ral(AREG); indir(np, AREG); } else { frc_ral(0); retreg(np, 0); } externfuncref(np); sprintf(buf, "\tjsr\t<A\n\tadd.w\t#%d,sp\n", argsize); addcode(np, buf); return OKAY; case ',': if (np->g_offs == 0) /* normal ',' */ rinherit(np); return OKAY; case DOUBLE '&': free1(NULL, rp); r = ralloc(0); retreg(np, r); holdlbls(np); np->g_betw = iscc(lp) ? "<FL1\n" : "<Q\tbeq\tL1\n"; addcode(np, iscc(rp) ? ">FL1\n" : ">Q\tbeq\tL1\n"); addcode(np, "\tmoveq\t#1,A\n"); addcode(np, "\tbra\tL2\nL1:\tclr\tA\nL2:\n"); return OKAY; case DOUBLE '|': free1(NULL, rp); r = ralloc(0); retreg(np, r); holdlbls(np); np->g_betw = iscc(lp) ? "<TL1\n" : "<Q\tbne\tL1\n"; addcode(np, iscc(rp) ? ">TL1\n" : ">Q\tbne\tL1\n"); addcode(np, "\tclr\tA\n"); addcode(np, "\tbra\tL2\nL1:\tmoveq\t#1,A\nL2:\n"); return OKAY; case '?': rinherit(np); rinhlbls(np); np->g_betw = iscc(lp) ? "<FL1\n" : "<Q\tbeq\tL1\n"; return OKAY; case ':': free1(NULL, rp); r = ralloc(0); retreg(np, r); holdlbls(np); np->g_betw = same_a(np, lp) ? "\tbra\tL2\nL1:\n" : "\tmove.S\t<A,A\n\tbra\tL2\nL1:\n"; if (!same_a(np, rp)) addcode(np, "\tmove.S\t>A,A\n"); addcode(np, "L2:\n"); return OKAY; case '<': i = 0; goto dotst; case '>': i = 1; goto dotst; case LTEQ: i = 2; goto dotst; case GTEQ: i = 3; goto dotst; case DOUBLE '=': i = 4; goto dotst; case NOTEQ: i = 5; dotst: fix_cmp(np, EOPD|EOPA|IOPE|AOPA|AOPD); if (flags & CC_OK) { np->g_token = (lp->g_ty == ET_U ? utstx[i] : tstx[i]) + BR_TOK; } else { strcpy(np->n_name, lp->g_ty == ET_U ? utstnm[i] : tstnm[i]); r = ralloc(0); retreg(np, r); addcode(np, "\tsN\tA\n\tand.w\t#1,A\n"); } return OKAY; case '*': return fixmul(np, bops[0].opflags); case '/': return fixdiv(np, bops[1].opflags); case '%': return fixmod(np, bops[2].opflags); case '&': i = 3; goto doop; case '|': i = 4; goto doop; case '^': i = 5; goto doop; case '+': if (optadd(np, flags, 1)) return OKAY; i = 6; goto doop; case '-': if (optadd(np, flags, -1)) return OKAY; i = 7; goto doop; case DOUBLE '<':i = 8; goto doop; case DOUBLE '>':i = 9; doop: strcpy(np->n_name, np->g_ty == ET_U ? bops[i].u_op : bops[i].s_op); r = fix2ops(np, bops[i].opflags); cc_hack(np); return r; case FIELDAS: return fldasn(np, flags); default: printf("Weird b_eval %s ", np->n_name); return FAIL; } } as_eval(np) register NODEP np; { NODEP rp = np->n_right; register int op, i, r; rp = np->n_right; op = np->g_token; op -= ASSIGN 0; switch (op) { /* these get unfolded now */ case '*': return fixamul(np, bops[0].opflags); case '/': return fixadiv(np, bops[1].opflags); case '%': return fixamod(np, bops[2].opflags); case '&': i = 3; goto doop; case '|': i = 4; goto doop; case '^': i = 5; goto doop; case '+': i = 6; goto doop; case '-': i = 7; goto doop; case DOUBLE '<':i = 8; goto doop; case DOUBLE '>':i = 9; doop: strcpy(np->n_name, np->g_ty == ET_U ? bops[i].u_op : bops[i].s_op); r = fix_asn(np, bops[i].opflags); cc_hack(np); return r; default: printf("Weird as_eval %s ", np->n_name); return FAIL; } } rinherit(np) register NODEP np; { register NODEP rp = np->n_right; np->g_token = rp->g_token; np->g_offs = rp->g_offs; np->g_rno = rp->g_rno; np->g_flags |= RCHILDNM | (rp->g_flags & IMMEDID); } argmod(np) register NODEP np; { int size = 0; if (np->g_token == ',') { np->g_type = EV_RL; size += argmod(np->n_right); size += argmod(np->n_left); return size; } size += onearg(np); return size; } onearg(np) register NODEP np; { int rv; /* hack small ICON */ if (np->g_sz == 1 && np->g_token == ICON) np->g_sz = 2; /* hack push of 0 */ if (np->g_token == ICON && np->g_offs == 0 && isimmed(np)) { addcode(np, "\tclr.S\t-(sp)\n"); return (int)np->g_sz; } /* hack push of #OREG */ if (np->g_token == OREG && isimmed(np)) { np->g_flags &= ~IMMEDID; addcode(np, "\tpea\tA\n"); return 4; } if (np->g_ty == ET_A) { rv = np->g_bsize; strpush(np); freetmps(np); free1(NULL,np); return rv; } switch (np->g_sz) { case 1: addcode(np, "\tmove.b\tA,d0\n\text.w\td0\n\tmove.w\td0,-(sp)\n"); return 2; case 2: addcode(np, "\tmove.w\tA,-(sp)\n"); return 2; default: addcode(np, "\tmove.l\tA,-(sp)\n"); return 4; } } #define MAXD DRV_START #define MAXA (ARV_START-AREG) #define NEEDALL (MAXA*AREG + MAXD) order(np) register NODEP np; { int l, r; switch (np->g_type) { case E_BIN: order(np->n_right); r = np->n_right->g_needs; case E_UNARY: order(np->n_left); l = np->n_left->g_needs; break; default: /* leaf */ np->g_type = EV_NONE; np->g_needs = 0; return; } if (np->g_type == E_UNARY) { switch (np->g_token) { case STAR: np->g_needs = merge(l,AREG); break; case '(': np->g_needs = NEEDALL; break; case POSTINC: case POSTDEC: case '!': np->g_needs = merge(l,1); break; case '.': if (np->g_fldw) { np->g_needs = merge(l,1); break; } /* else fall through */ default: np->g_needs = l; } np->g_type = EV_LEFT; return; } /* at this point, have binary node */ switch (np->g_token) { case DOUBLE '&': case DOUBLE '|': case '?': case ':': /* always left-right, no extra regs */ np->g_type = EV_LRSEP; np->g_needs = merge(1, merge(l,r)); return; case ',': np->g_needs = merge(l, r); np->g_type = EV_LRSEP; return; case '(': np->g_needs = NEEDALL; break; case '^': case DOUBLE '<': case DOUBLE '>': case ASSIGN '/': case ASSIGN DOUBLE '<': case ASSIGN DOUBLE '>': np->g_needs = merge(bin(l,r), 2); break; default: np->g_needs = merge(bin(l,r), 1); } if (isassign(np->g_token) || np->g_token == '=') np->g_type = EV_RL; /* NO PUSHER's on L */ else np->g_type = worst_1st(l, r); flag_saves(np, l, r); } flag_saves(np, l, r) NODEP np; { NODEP *cpp; register int other; if (np->g_type == EV_LR) { cpp = &np->n_left; other = r; } else { cpp = &np->n_right; other = l; } if ((other & 7) >= MAXD || (other/AREG) >= MAXA) addtmp(np, cpp); } addtmp(np, cpp) NODEP np, *cpp; { NODEP cp, tp; NODEP copyone(); cp = *cpp; tp = copyone(cp); tp->n_left = cp; *cpp = tp; tp->g_token = PUSHER; strcpy(tp->n_name, "pusher"); tp->g_type = EV_LEFT; } worst_1st(l,r) { int ld, rd; ld = l & 7; rd = r & 7; if (rd > ld) return EV_RL; if (r > l) return EV_RL; return EV_LR; } bin(l,r) { int la, ra, na; int ld, rd, nd; la = l/AREG; ra = r/AREG; ld = l & 7; rd = r & 7; na = la > ra ? la : ra; if (ld == rd) nd = ld == MAXD ? MAXD : ld+1; else nd = ld > rd ? ld : rd; return na*AREG + nd; } merge(need, have) { int na, nd, ha, hd, xa, xd; na = need/AREG; ha = have/AREG; nd = need & 7; hd = have & 7; xa = na > ha ? na : ha; xd = nd > hd ? nd : hd; return xa*AREG + xd; } holdlbls(np) NODEP np; { np->g_bsize = new_lbl(); new_lbl(); } rinhlbls(np) NODEP np; { np->g_bsize = np->n_right->g_bsize; } /* limited version of same address check assume one of these is a temp register */ same_a(p1, p2) NODEP p1, p2; { if (p1->g_token != p2->g_token) return 0; if (p1->g_rno != p2->g_rno) return 0; return 1; } optadd(np, flags, sign) register NODEP np; { NODEP lp = np->n_left, rp = np->n_right; if (rp->g_token != ICON) return 0; if (isimmed(lp) && isimmed(rp)) { switch (lp->g_token) { case OREG: case ONAME: inherit(np); if (sign == -1) rp->g_offs = -rp->g_offs; np->g_offs += rp->g_offs; if ((flags & IMMA_OK) == 0) imm_oreg(np); return 1; default: return 0; } } return 0; } iscc(np) NODEP np; { return (np->g_token >= BR_TOK) || (np->g_flags & SIDE_CC); } cc_hack(np) NODEP np; { if (isareg(np)) return; np->g_flags |= SIDE_CC; } cctok(np) NODEP np; { if (np->g_token >= BR_TOK) return np->g_token - BR_TOK; if (np->g_flags & SIDE_CC) return B_NE; printf("cctok error "); return 0; } SHAR_EOF # End of shell archive exit 0 -- Bob Page, U of Lowell CS Dept. page@swan.ulowell.edu ulowell!page Have five nice days.