/* * Create a tree that can later be converted to an OREG. */ static NODE * oregtree(int off, int reg, int type) { NODE *p, *q; p = mklnode(REG, 0, reg, INCREF(type)); q = mklnode(ICON, off, 0, INT); return mkunode(UMUL, mkbinode(PLUS, p, q, INCREF(type)), 0, type); }
struct lnode* mklist(int fd) { int nr, i; char buf[BUFSIZE]; struct lnode *root = 0; struct lnode *result = 0; while ((nr = read(fd, buf, BUFSIZE)) != -1 && nr != 0) { /* count characters */ printf("Read %d bytes.\n", nr); for(i = 0; i < nr; i++) { if (i == 0) root = mklnode(buf[i], 1); else if ((result = findlnode(root, buf[i]))) incfreq(result); else applnode(buf[i], 1, root); } } return root; }
/* * Push a structure on stack as argument. * the scratch registers are already free here */ static void starg(NODE *p) { #if defined(MACHOABI) printf(" subl $%d,%%esp\n", p->n_stsize); printf(" subl $4,%%esp\n"); printf(" pushl $%d\n", p->n_stsize); expand(p, 0, " pushl AL\n"); expand(p, 0, " leal 12(%esp),A1\n"); expand(p, 0, " pushl A1\n"); if (kflag) { printf(" call L%s$stub\n", EXPREFIX "memcpy"); addstub(&stublist, EXPREFIX "memcpy"); } else { printf(" call %s\n", EXPREFIX "memcpy"); } printf(" addl $16,%%esp\n"); #else NODE *q = p->n_left; printf(" subl $%d,%%esp\n", (p->n_stsize + 3) & ~3); p->n_left = mklnode(OREG, 0, ESP, INT); zzzcode(p, 'Q'); tfree(p->n_left); p->n_left = q; #endif }
/* put out code for goto l */ void putgoto(int label) { NODE *p; p = mkunode(GOTO, mklnode(ICON, label, 0, INT), 0, INT); sendp2(p); }
/* * Push a structure on stack as argument. * the scratch registers are already free here */ static void starg(NODE *p) { NODE *q = p->n_left; printf(" subl $%d,%%esp\n", (p->n_stsize + 3) & ~3); p->n_left = mklnode(OREG, 0, ESP, INT); zzzcode(p, 'Q'); tfree(p->n_left); p->n_left = q; }
/* * Push a structure on stack as argument. * the scratch registers are already free here */ static void starg(NODE *p) { struct attr *ap; NODE *q = p->n_left; ap = attr_find(p->n_ap, ATTR_P2STRUCT); printf(" subl $%d,%%esp\n", (ap->iarg(0) + 3) & ~3); p->n_left = mklnode(OREG, 0, ESP, INT); zzzcode(p, 'Q'); tfree(p->n_left); p->n_left = q; }
/* put out code for if( ! p) goto l */ void putif(bigptr p, int l) { NODE *p1; int k; if( ( k = (p = fixtype(p))->vtype) != TYLOGICAL) { if(k != TYERROR) err("non-logical expression in IF statement"); frexpr(p); } else { p1 = putex1(p); if (p1->n_op == EQ && p1->n_right->n_op == ICON && p1->n_right->n_lval == 0 && logop(p1->n_left->n_op)) { /* created by OPOR */ NODE *q = p1->n_left; q->n_op = negrel[q->n_op - EQ]; nfree(p1->n_right); nfree(p1); p1 = q; } if (logop(p1->n_op) == 0) p1 = mkbinode(NE, p1, mklnode(ICON, 0, 0, INT), INT); if (p1->n_left->n_op == ICON) { /* change constants to right */ NODE *p2 = p1->n_left; p1->n_left = p1->n_right; p1->n_right = p2; if (p1->n_op != EQ && p1->n_op != NE) p1->n_op = negrel[p1->n_op - EQ]; } p1->n_op = negrel[p1->n_op - EQ]; p1 = mkbinode(CBRANCH, p1, mklnode(ICON, l, 0, INT), INT); sendp2(p1); } }
/* * Push a structure on stack as argument. * the scratch registers are already free here */ static void starg(NODE *p) { NODE *q = p->n_left; int s = (attr_find(p->n_ap, ATTR_P2STRUCT)->iarg(0) + 1) & ~1; if (s == 2) printf(" dec sp\n dec sp\n"); else printf(" sub sp,#%d\n", s); p->n_left = mklnode(OREG, 0, SP, INT); zzzcode(p, 'Q'); tfree(p->n_left); p->n_left = q; }
/* * Convert a f77 tree statement to something that looks like a * pcc expression tree. */ NODE * putx(bigptr q) { struct bigblock *x1; NODE *p = NULL; /* XXX */ int opc; int type, k; #ifdef PCC_DEBUG if (tflag) { printf("putx %p\n", q); fprint(q, 0); } #endif switch(q->tag) { case TERROR: ckfree(q); break; case TCONST: switch(type = q->vtype) { case TYLOGICAL: type = tyint; case TYLONG: case TYSHORT: p = mklnode(ICON, q->b_const.fconst.ci, 0, types2[type]); ckfree(q); break; case TYADDR: p = mklnode(ICON, 0, 0, types2[type]); p->n_name = copys(memname(STGCONST, (int)q->b_const.fconst.ci)); ckfree(q); break; default: p = putx(putconst(q)); break; } break; case TEXPR: switch(opc = q->b_expr.opcode) { case OPCALL: case OPCCALL: if( ISCOMPLEX(q->vtype) ) p = putcxop(q); else { putcall(q); p = callval; } break; case OPMIN: case OPMAX: p = putmnmx(q); break; case OPASSIGN: if (ISCOMPLEX(q->b_expr.leftp->vtype) || ISCOMPLEX(q->b_expr.rightp->vtype)) { frexpr(putcxeq(q)); } else if (ISCHAR(q)) p = putcheq(q); else goto putopp; break; case OPEQ: case OPNE: if (ISCOMPLEX(q->b_expr.leftp->vtype) || ISCOMPLEX(q->b_expr.rightp->vtype) ) { p = putcxcmp(q); break; } case OPLT: case OPLE: case OPGT: case OPGE: if(ISCHAR(q->b_expr.leftp)) p = putchcmp(q); else goto putopp; break; case OPPOWER: p = putpower(q); break; case OPSTAR: /* m * (2**k) -> m<<k */ if (XINT(q->b_expr.leftp->vtype) && ISICON(q->b_expr.rightp) && ((k = flog2(q->b_expr.rightp->b_const.fconst.ci))>0) ) { q->b_expr.opcode = OPLSHIFT; frexpr(q->b_expr.rightp); q->b_expr.rightp = MKICON(k); goto putopp; } case OPMOD: goto putopp; case OPPLUS: case OPMINUS: case OPSLASH: case OPNEG: if( ISCOMPLEX(q->vtype) ) p = putcxop(q); else goto putopp; break; case OPCONV: if( ISCOMPLEX(q->vtype) ) p = putcxop(q); else if (ISCOMPLEX(q->b_expr.leftp->vtype)) { p = putx(mkconv(q->vtype, realpart(putcx1(q->b_expr.leftp)))); ckfree(q); } else goto putopp; break; case OPAND: /* Create logical AND */ x1 = fmktemp(TYLOGICAL, NULL); putexpr(mkexpr(OPASSIGN, cpexpr(x1), mklogcon(0))); k = newlabel(); putif(q->b_expr.leftp, k); putif(q->b_expr.rightp, k); putexpr(mkexpr(OPASSIGN, cpexpr(x1), mklogcon(1))); putlabel(k); p = putx(x1); break; case OPNOT: /* Logical NOT */ x1 = fmktemp(TYLOGICAL, NULL); putexpr(mkexpr(OPASSIGN, cpexpr(x1), mklogcon(1))); k = newlabel(); putif(q->b_expr.leftp, k); putexpr(mkexpr(OPASSIGN, cpexpr(x1), mklogcon(0))); putlabel(k); p = putx(x1); break; case OPOR: /* Create logical OR */ x1 = fmktemp(TYLOGICAL, NULL); putexpr(mkexpr(OPASSIGN, cpexpr(x1), mklogcon(1))); k = newlabel(); putif(mkexpr(OPEQ, q->b_expr.leftp, mklogcon(0)), k); putif(mkexpr(OPEQ, q->b_expr.rightp, mklogcon(0)), k); putexpr(mkexpr(OPASSIGN, cpexpr(x1), mklogcon(0))); putlabel(k); p = putx(x1); break; case OPCOMMA: for (x1 = q; x1->b_expr.opcode == OPCOMMA; x1 = x1->b_expr.leftp) putexpr(x1->b_expr.rightp); p = putx(x1); break; case OPEQV: case OPNEQV: case OPADDR: case OPBITOR: case OPBITAND: case OPBITXOR: case OPBITNOT: case OPLSHIFT: case OPRSHIFT: putopp: p = putop(q); break; default: fatal1("putx: invalid opcode %d", opc); } break; case TADDR: p = putaddr(q, YES); break; default: fatal1("putx: impossible tag %d", q->tag); } return p; }
static NODE * putaddr(bigptr q, int indir) { int type, type2, funct; NODE *p, *p1, *p2; ftnint offset; bigptr offp; p = p1 = p2 = NULL; /* XXX */ type = q->vtype; type2 = types2[type]; funct = (q->vclass==CLPROC ? FTN<<TSHIFT : 0); offp = (q->b_addr.memoffset ? cpexpr(q->b_addr.memoffset) : NULL); offset = simoffset(&offp); if(offp) offp = mkconv(TYINT, offp); switch(q->vstg) { case STGAUTO: if(indir && !offp) { p = oregtree(offset, AUTOREG, type2); break; } if(!indir && !offp && !offset) { p = mklnode(REG, 0, AUTOREG, INCREF(type2)); break; } p = mklnode(REG, 0, AUTOREG, INCREF(type2)); if(offp) { p1 = putx(offp); if(offset) p2 = mklnode(ICON, offset, 0, INT); } else p1 = mklnode(ICON, offset, 0, INT); if (offp && offset) p1 = mkbinode(PLUS, p1, p2, INCREF(type2)); p = mkbinode(PLUS, p, p1, INCREF(type2)); if (indir) p = mkunode(UMUL, p, 0, type2); break; case STGARG: p = oregtree(ARGOFFSET + (ftnint)(q->b_addr.memno), ARGREG, INCREF(type2)|funct); if (offp) p1 = putx(offp); if (offset) p2 = mklnode(ICON, offset, 0, INT); if (offp && offset) p1 = mkbinode(PLUS, p1, p2, INCREF(type2)); else if (offset) p1 = p2; if (offp || offset) p = mkbinode(PLUS, p, p1, INCREF(type2)); if (indir) p = mkunode(UMUL, p, 0, type2); break; case STGLENG: if(indir) { p = oregtree(ARGOFFSET + (ftnint)(q->b_addr.memno), ARGREG, INCREF(type2)|funct); } else { fatal1("faddrnode: STGLENG: fixme!"); #if 0 p2op(P2PLUS, types2[TYLENG] | P2PTR ); p2reg(ARGREG, types2[TYLENG] | P2PTR ); p2icon( ARGOFFSET + (ftnint) (FUDGEOFFSET*p->b_addr.memno), P2INT); #endif } break; case STGBSS: case STGINIT: case STGEXT: case STGCOMMON: case STGEQUIV: case STGCONST: if(offp) { p1 = putx(offp); p2 = putmem(q, ICON, offset); p = mkbinode(PLUS, p1, p2, INCREF(type2)); if(indir) p = mkunode(UMUL, p, 0, type2); } else p = putmem(q, (indir ? NAME : ICON), offset); break; case STGREG: if(indir) p = mklnode(REG, 0, q->b_addr.memno, type2); else fatal("attempt to take address of a register"); break; default: fatal1("putaddr: invalid vstg %d", q->vstg); } frexpr(q); return p; }
void zzzcode(NODE *p, int c) { NODE *l, *r; TWORD t; int m; char *ch; switch (c) { case 'N': /* logical ops, turned into 0-1 */ /* use register given by register 1 */ cbgen( 0, m=getlab2()); deflab( p->n_label ); printf( " clrl %s\n", rnames[getlr( p, '1' )->n_rval] ); deflab( m ); return; case 'A': /* Assign a constant directly to a memory position */ printf("\t"); if (p->n_type < LONG || ISPTR(p->n_type)) casg(p); else casg64(p); printf("\n"); break; case 'B': /* long long compare */ twollcomp(p); break; case 'C': /* num words pushed on arg stack */ printf("$%d", p->n_qual); break; case 'D': /* INCR and DECR */ zzzcode(p->n_left, 'A'); printf("\n "); #if 0 case 'E': /* INCR and DECR, FOREFF */ if (p->n_right->n_lval == 1) { printf("%s", (p->n_op == INCR ? "inc" : "dec") ); prtype(p->n_left); printf(" "); adrput(stdout, p->n_left); return; } printf("%s", (p->n_op == INCR ? "add" : "sub") ); prtype(p->n_left); printf("2 "); adrput(stdout, p->n_right); printf(","); adrput(p->n_left); return; #endif case 'F': /* register type of right operand */ { register NODE *n; register int ty; n = getlr( p, 'R' ); ty = n->n_type; if (x2debug) printf("->%d<-", ty); if ( ty==DOUBLE) printf("d"); else if ( ty==FLOAT ) printf("f"); else printf("l"); return; } case 'G': /* emit conversion instructions */ sconv(p); break; case 'J': /* jump or ret? */ { struct interpass *ip = DLIST_PREV((struct interpass *)p2env.epp, qelem); if (ip->type != IP_DEFLAB || ip->ip_lbl != getlr(p, 'L')->n_lval) expand(p, FOREFF, "jbr LL"); else printf("ret"); } break; case 'L': /* type of left operand */ case 'R': /* type of right operand */ { register NODE *n; n = getlr ( p, c); if (x2debug) printf("->%d<-", n->n_type); prtype(n); return; } case 'O': /* print out emulated ops */ expand(p, FOREFF, "\tmovq AR,-(%sp)\n"); expand(p, FOREFF, "\tmovq AL,-(%sp)\n"); if (p->n_op == DIV && p->n_type == ULONGLONG) ch = "udiv"; else if (p->n_op == DIV) ch = "div"; else if (p->n_op == MOD && p->n_type == ULONGLONG) ch = "umod"; else if (p->n_op == MOD) ch = "mod"; else if (p->n_op == MUL) ch = "mul"; else ch = 0, comperr("ZO %d", p->n_op); printf("\tcalls $4,__%sdi3\n", ch); break; case 'Z': /* complement mask for bit instr */ printf("$%Ld", ~p->n_right->n_lval); return; case 'U': /* 32 - n, for unsigned right shifts */ t = DEUNSIGN(p->n_left->n_type); m = t == CHAR ? 8 : t == SHORT ? 16 : 32; printf("$" CONFMT, m - p->n_right->n_lval); return; case 'T': /* rounded structure length for arguments */ { int size; size = p->n_stsize; SETOFF( size, 4); printf("$%d", size); return; } case 'S': /* structure assignment */ { register int size; size = p->n_stsize; l = r = NULL; /* XXX gcc */ if( p->n_op == STASG ){ l = p->n_left; r = p->n_right; } else if( p->n_op == STARG ){ /* store an arg into a temporary */ printf("\tsubl2 $%d,%%sp\n", size < 4 ? 4 : size); l = mklnode(OREG, 0, SP, INT); r = p->n_left; } else cerror( "STASG bad" ); if( r->n_op == ICON ) r->n_op = NAME; else if( r->n_op == REG ) r->n_op = OREG; else if( r->n_op != OREG ) cerror( "STASG-r" ); if (size != 0) { if( size <= 0 || size > 65535 ) cerror("structure size <0=0 or >65535"); switch(size) { case 1: printf(" movb "); break; case 2: printf(" movw "); break; case 4: printf(" movl "); break; case 8: printf(" movq "); break; default: printf(" movc3 $%d,", size); break; } adrput(stdout, r); printf(","); adrput(stdout, l); printf("\n"); } if( r->n_op == NAME ) r->n_op = ICON; else if( r->n_op == OREG ) r->n_op = REG; if (p->n_op == STARG) tfree(l); } break; default: comperr("illegal zzzcode '%c'", c); } }