/* * Do the actual conversion of offstar-found OREGs into real OREGs. * For simple OREGs conversion should already be done. */ void myormake(NODE *q) { static int shtbl[] = { 1,2,4,8 }; NODE *p, *r; CONSZ c = 0; int r1, r2, sh; int mkconv = 0; char *n = ""; #define risreg(p) (p->n_op == REG) if (x2debug) { printf("myormake(%p)\n", q); fwalk(q, e2print, 0); } r1 = r2 = MAXREGS; sh = 1; r = p = q->n_left; if ((p->n_op == PLUS || p->n_op == MINUS) && p->n_left->n_op == ICON) { c = p->n_left->n_lval; n = p->n_left->n_name; p = p->n_right; } if (p->n_op == PLUS && risreg(p->n_left)) { r1 = regno(p->n_left); p = p->n_right; } if (findls(p, 1)) { if (p->n_op == SCONV) p = p->n_left; sh = shtbl[(int)p->n_right->n_lval]; r2 = regno(p->n_left); mkconv = 1; } else if (risreg(p)) { r2 = regno(p); mkconv = 1; } //else // comperr("bad myormake tree"); if (mkconv == 0) return; q->n_op = OREG; q->n_lval = c; q->n_rval = R2PACK(r1, r2, sh); q->n_name = n; tfree(r); if (x2debug) { printf("myormake converted %p\n", q); fwalk(q, e2print, 0); } }
void fwalk(NODE *t, void (*f)(NODE *, int, int *, int *), int down) { int down1, down2; more: down1 = down2 = 0; (*f)(t, down, &down1, &down2); switch (OPTYPE( t->n_op )) { case BITYPE: fwalk( t->n_left, f, down1 ); t = t->n_right; down = down2; goto more; case UTYPE: t = t->n_left; down = down1; goto more; } }
/* * Do the actual conversion of offstar-found OREGs into real OREGs. */ void myormake(NODE *p) { NODE *q = p->n_left; if (x2debug) { printf("myormake(%p)\n", p); fwalk(p, e2print, 0); } if (inctree(q)) { if (q->n_left->n_left->n_op == TEMP) return; p->n_op = OREG; p->n_lval = 0; /* Add support for index offset */ p->n_rval = R2PACK(regno(q->n_left->n_left), 0, 1); tfree(q); return; } if (q->n_op != OREG) return; p->n_op = OREG; p->n_lval = q->n_lval; p->n_rval = R2PACK(q->n_rval, 0, 0); nfree(q); }
T DoubleList<T>::add(int pos, T data) { if (pos > this->size()) { this->append(data); return data; } if (pos < 0) { this->prepend(data); return data; } Node<T> * tmp = fwalk(head, pos); Node<T> * new_node = new Node<T>(data, tmp->prev, tmp); tmp->prev = new_node; new_node->prev->next = new_node; return data; }
static void sendp2(NODE *p) { extern int thisline; p2tree(p); thisline = lineno; if (debugflag) fwalk(p, e2print, 0); pass2_compile(ipnode(p)); }
T DoubleList<T>::remove(int pos) { Node<T> * tmp = fwalk(head, pos); if (tmp != this->head) { tmp->prev->next = tmp->next; } else { this->head = tmp->next; } if (tmp != this->tail) { tmp->next->prev = tmp->prev; } else { this->tail = tmp->prev; } T data = tmp->data; delete tmp; return data; }
/* * Turn a UMUL-referenced node into OREG. * Be careful about register classes, this is a place where classes change. * * AMD64 (and i386) have a quite powerful addressing scheme: * : 4(%rax) 4 + %rax * : 4(%rbx,%rax,8) 4 + %rbx + %rax * 8 * : 4(,%rax) 4 + %rax * 8 * The 8 above can be 1,2,4 or 8. */ void offstar(NODE *p, int shape) { NODE *l; if (x2debug) { printf("offstar(%p)\n", p); fwalk(p, e2print, 0); } if (isreg(p)) return; /* Matched (%rax) */ if (findls(p, 0)) return; /* Matched (,%rax,8) */ if ((p->n_op == PLUS || p->n_op == MINUS) && p->n_left->n_op == ICON) { l = p->n_right; if (isreg(l)) return; /* Matched 4(%rax) */ if (findls(l, 0)) return; /* Matched 4(,%rax,8) */ if (l->n_op == PLUS && isreg(l->n_right)) { if (findls(l->n_left, 0)) return; /* Matched 4(%rbx,%rax,8) */ (void)geninsn(l->n_left, INAREG); return; /* Generate 4(%rbx,%rax) */ } (void)geninsn(l, INAREG); return; /* Generate 4(%rbx) */ } if (p->n_op == PLUS) { if (!isreg(p->n_left)) /* ensure right is REG */ (void)geninsn(p->n_left, INAREG); if (isreg(p->n_right)) return; /* Matched (%rax,%rbx) */ if (findls(p->n_right, 0)) return; /* Matched (%rax,%rbx,4) */ (void)geninsn(p->n_right, INAREG); return; /* Generate (%rbx,%rax) */ } (void)geninsn(p, INAREG); }
tcheck(){ /* ensure that all nodes have been freed */ register NODE *p; static NODE *first = node; /* SS. 25.feb.87 added */ if( !nerrors ) /* for( p=node; p<= &node[TREESZ-1]; ++p ) */ for( p=first; p != lastfree; p= TNEXT(p) ){ if( p->in.op != FREE ){ #ifndef BUG4 extern int e2print(); printf( "\ntree causing cerror <wasted space>:\n" ); fwalk( p, e2print, 0 ); #endif cerror( 209, p ); /* wasted space: %o */ } first = lastfree; /* SS. remember the location */ } else tinit(); /* SS. call the tinit() only if there were errors */ freetstr(); } /* tcheck */
/* * print out a constant node * mat be associated with a label */ int ninval(NODE *p) { struct symtab *q; TWORD t; p = p->n_left; t = p->n_type; if (t > BTMASK) t = p->n_type = INT; /* pointer */ switch (t) { case LONGLONG: case ULONGLONG: inval(p->n_lval & 0xffffffff); inval(p->n_lval >> 32); break; case LONG: case ULONG: case INT: case UNSIGNED: printf("\t.long 0x%x", (int)p->n_lval); if ((q = p->n_sp) != NULL) { if ((q->sclass == STATIC && q->slevel > 0)) { printf("+" LABFMT, q->soffset); } else printf("+%s", exname(q->soname)); } printf("\n"); break; default: fwalk(p, eprint, 0); return 0; } return 1; }
/* clocal() is called to do local transformations on * an expression tree preparitory to its being * written out in intermediate code. * * the major essential job is rewriting the * automatic variables and arguments in terms of * REG and OREG nodes * conversion ops which are not necessary are also clobbered here * in addition, any special features (such as rewriting * exclusive or) are easily handled here as well */ NODE * clocal(NODE *p) { register struct symtab *q; register NODE *r, *l; register int o; register int m; TWORD t; #ifdef PCC_DEBUG if (xdebug) { printf("clocal: %p\n", p); fwalk(p, eprint, 0); } #endif switch( o = p->n_op ){ case NAME: if ((q = p->n_sp) == NULL) return p; /* Nothing to care about */ switch (q->sclass) { case PARAM: case AUTO: /* fake up a structure reference */ r = block(REG, NIL, NIL, PTR+STRTY, 0, 0); slval(r, 0); r->n_rval = FPREG; p = stref(block(STREF, r, p, 0, 0, 0)); break; case USTATIC: if (kflag == 0) break; /* FALLTHROUGH */ case STATIC: #ifdef TLS if (q->sflags & STLS) { p = tlsref(p); break; } #endif break; case REGISTER: p->n_op = REG; slval(p, 0); p->n_rval = q->soffset; break; case EXTERN: case EXTDEF: if (q->sflags & STLS) { p = tlsref(p); break; } if (kflag == 0 || statinit) break; if (blevel > 0) p = picext(p); break; } break; case UCALL: case USTCALL: /* For now, always clear eax */ l = block(REG, NIL, NIL, INT, 0, 0); regno(l) = RAX; p->n_right = clocal(buildtree(ASSIGN, l, bcon(0))); p->n_op -= (UCALL-CALL); break; case SCONV: /* Special-case shifts */ if (p->n_type == LONG && (l = p->n_left)->n_op == LS && l->n_type == INT && l->n_right->n_op == ICON) { p->n_left = l->n_left; p = buildtree(LS, p, l->n_right); nfree(l); break; } l = p->n_left; /* Float conversions may need extra casts */ if (p->n_type == FLOAT || p->n_type == DOUBLE || p->n_type == LDOUBLE) { if (l->n_type < INT || l->n_type == BOOL) { p->n_left = block(SCONV, l, NIL, ISUNSIGNED(l->n_type) ? UNSIGNED : INT, l->n_df, l->n_ap); break; } } if (p->n_type == l->n_type) { nfree(p); return l; } if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 && tsize(p->n_type, p->n_df, p->n_ap) == tsize(l->n_type, l->n_df, l->n_ap)) { if (p->n_type != FLOAT && p->n_type != DOUBLE && l->n_type != FLOAT && l->n_type != DOUBLE && l->n_type != LDOUBLE && p->n_type != LDOUBLE) { if (l->n_op == NAME || l->n_op == UMUL || l->n_op == TEMP) { l->n_type = p->n_type; nfree(p); return l; } } } if (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == INT && coptype(l->n_op) == BITYPE && l->n_op != COMOP && l->n_op != QUEST && l->n_op != ASSIGN) { l->n_type = p->n_type; nfree(p); return l; } o = l->n_op; m = p->n_type; if (o == ICON) { CONSZ val = glval(l); /* if named constant and pointer, allow cast to long/ulong */ if (!nncon(l) && (l->n_type & TMASK) && (m == LONG || m == ULONG)) { l->n_type = m; l->n_ap = 0; return nfree(p); } if (ISPTR(l->n_type) && !nncon(l)) break; /* cannot convert named pointers */ if (!ISPTR(m)) /* Pointers don't need to be conv'd */ switch (m) { case BOOL: val = nncon(l) ? (val != 0) : 1; slval(l, val); l->n_sp = NULL; break; case CHAR: slval(l, (char)val); break; case UCHAR: slval(l, val & 0377); break; case SHORT: slval(l, (short)val); break; case USHORT: slval(l, val & 0177777); break; case UNSIGNED: slval(l, val & 0xffffffff); break; case INT: slval(l, (int)val); break; case LONG: case LONGLONG: slval(l, (long long)val); break; case ULONG: case ULONGLONG: slval(l, val); break; case VOID: break; case LDOUBLE: case DOUBLE: case FLOAT: l->n_op = FCON; l->n_dcon = fltallo(); FCAST(l->n_dcon)->fp = val; break; default: cerror("unknown type %d", m); } l->n_type = m; l->n_ap = NULL; nfree(p); return l; } else if (l->n_op == FCON) { CONSZ lv; if (p->n_type == BOOL) lv = !FLOAT_ISZERO(FCAST(l->n_dcon)); else { FLOAT_FP2INT(lv, FCAST(l->n_dcon), m); } slval(l, lv); l->n_sp = NULL; l->n_op = ICON; l->n_type = m; l->n_ap = NULL; nfree(p); return clocal(l); } if ((p->n_type == CHAR || p->n_type == UCHAR || p->n_type == SHORT || p->n_type == USHORT) && (l->n_type == FLOAT || l->n_type == DOUBLE || l->n_type == LDOUBLE)) { p = block(SCONV, p, NIL, p->n_type, p->n_df, p->n_ap); p->n_left->n_type = INT; return p; } break; case MOD: case DIV: if (o == DIV && p->n_type != CHAR && p->n_type != SHORT) break; if (o == MOD && p->n_type != CHAR && p->n_type != SHORT) break; /* make it an int division by inserting conversions */ p->n_left = makety(p->n_left, INT, 0, 0, 0); p->n_right = makety(p->n_right, INT, 0, 0, 0); p = makety(p, p->n_type, 0, 0, 0); p->n_left->n_type = INT; break; case FORCE: /* put return value in return reg */ p->n_op = ASSIGN; p->n_right = p->n_left; p->n_left = block(REG, NIL, NIL, p->n_type, 0, 0); t = p->n_type; if (ISITY(t)) t = t - (FIMAG-FLOAT); p->n_left->n_rval = p->n_left->n_type == BOOL ? RETREG(CHAR) : RETREG(t); break; case LS: case RS: /* shift count must be in a char */ if (p->n_right->n_type == CHAR || p->n_right->n_type == UCHAR) break; p->n_right = makety(p->n_right, CHAR, 0, 0, 0); break; } #ifdef PCC_DEBUG if (xdebug) { printf("clocal end: %p\n", p); fwalk(p, eprint, 0); } #endif return(p); }
NODE * clocal(NODE *p) { struct symtab *q; NODE *r, *l; TWORD t; int o; #ifdef PCC_DEBUG if (xdebug) { printf("clocal\n"); fwalk(p, eprint, 0); } #endif switch( o = p->n_op ){ case NAME: /* handle variables */ if ((q = p->n_sp) == NULL) return p; /* Nothing to care about */ switch (q->sclass) { case PARAM: case AUTO: if (0 && q->soffset < MAXZP * SZINT && q->sclass != PARAM) { p->n_lval = -(q->soffset/SZCHAR) + ZPOFF*2; p->n_sp = NULL; } else { /* fake up a structure reference */ r = block(REG, NIL, NIL, PTR+STRTY, 0, 0); r->n_lval = 0; r->n_rval = FPREG; p = stref(block(STREF, r, p, 0, 0, 0)); } break; default: break; } break; case PMCONV: case PVCONV: if( p->n_right->n_op != ICON ) cerror( "bad conversion", 0); nfree(p); p = (buildtree(o==PMCONV?MUL:DIV, p->n_left, p->n_right)); break; case PCONV: t = p->n_type; if (t == INCREF(CHAR) || t == INCREF(UCHAR) || t == INCREF(BOOL) || t == INCREF(VOID)) break; l = p->n_left; t = l->n_type; if (t == INCREF(CHAR) || t == INCREF(UCHAR) || t == INCREF(BOOL) || t == INCREF(VOID)) break; if (p->n_type <= UCHAR || l->n_type <= UCHAR) break; /* must do runtime ptr conv */ /* if conversion to another pointer type, just remove */ if (p->n_type > BTMASK && l->n_type > BTMASK) goto delp; if (l->n_op == ICON && l->n_sp == NULL) goto delp; break; delp: l->n_type = p->n_type; l->n_qual = p->n_qual; l->n_df = p->n_df; l->n_ap = p->n_ap; p = nfree(p); break; } #ifdef PCC_DEBUG if (xdebug) { printf("clocal end\n"); fwalk(p, eprint, 0); } #endif #if 0 register struct symtab *q; register NODE *r, *l; register int o; register int m; TWORD t; //printf("in:\n"); //fwalk(p, eprint, 0); switch( o = p->n_op ){ case NAME: if ((q = p->n_sp) == NULL) return p; /* Nothing to care about */ switch (q->sclass) { case PARAM: case AUTO: /* fake up a structure reference */ r = block(REG, NIL, NIL, PTR+STRTY, 0, 0); r->n_lval = 0; r->n_rval = FPREG; p = stref(block(STREF, r, p, 0, 0, 0)); break; case STATIC: if (q->slevel == 0) break; p->n_lval = 0; p->n_sp = q; break; case REGISTER: p->n_op = REG; p->n_lval = 0; p->n_rval = q->soffset; break; } break; case STCALL: case CALL: /* Fix function call arguments. On x86, just add funarg */ for (r = p->n_right; r->n_op == CM; r = r->n_left) { if (r->n_right->n_op != STARG && r->n_right->n_op != FUNARG) r->n_right = block(FUNARG, r->n_right, NIL, r->n_right->n_type, r->n_right->n_df, r->n_right->n_sue); } if (r->n_op != STARG && r->n_op != FUNARG) { l = talloc(); *l = *r; r->n_op = FUNARG; r->n_left = l; r->n_type = l->n_type; } break; case CBRANCH: l = p->n_left; /* * Remove unnecessary conversion ops. */ if (clogop(l->n_op) && l->n_left->n_op == SCONV) { if (coptype(l->n_op) != BITYPE) break; if (l->n_right->n_op == ICON) { r = l->n_left->n_left; if (r->n_type >= FLOAT && r->n_type <= LDOUBLE) break; /* Type must be correct */ t = r->n_type; nfree(l->n_left); l->n_left = r; l->n_type = t; l->n_right->n_type = t; } } break; case PCONV: /* Remove redundant PCONV's. Be careful */ l = p->n_left; if (l->n_op == ICON) { l->n_lval = (unsigned)l->n_lval; goto delp; } if (l->n_type < INT || l->n_type == LONGLONG || l->n_type == ULONGLONG) { /* float etc? */ p->n_left = block(SCONV, l, NIL, UNSIGNED, 0, 0); break; } /* if left is SCONV, cannot remove */ if (l->n_op == SCONV) break; /* if conversion to another pointer type, just remove */ if (p->n_type > BTMASK && l->n_type > BTMASK) goto delp; break; delp: l->n_type = p->n_type; l->n_qual = p->n_qual; l->n_df = p->n_df; l->n_sue = p->n_sue; nfree(p); p = l; break; case SCONV: l = p->n_left; if (p->n_type == l->n_type) { nfree(p); return l; } if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 && btdims[p->n_type].suesize == btdims[l->n_type].suesize) { if (p->n_type != FLOAT && p->n_type != DOUBLE && l->n_type != FLOAT && l->n_type != DOUBLE && l->n_type != LDOUBLE && p->n_type != LDOUBLE) { if (l->n_op == NAME || l->n_op == UMUL || l->n_op == TEMP) { l->n_type = p->n_type; nfree(p); return l; } } } if (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == INT && coptype(l->n_op) == BITYPE) { l->n_type = p->n_type; nfree(p); return l; } o = l->n_op; m = p->n_type; if (o == ICON) { CONSZ val = l->n_lval; if (!ISPTR(m)) /* Pointers don't need to be conv'd */ switch (m) { case CHAR: l->n_lval = (char)val; break; case UCHAR: l->n_lval = val & 0377; break; case SHORT: l->n_lval = (short)val; break; case USHORT: l->n_lval = val & 0177777; break; case ULONG: case UNSIGNED: l->n_lval = val & 0xffffffff; break; case LONG: case INT: l->n_lval = (int)val; break; case LONGLONG: l->n_lval = (long long)val; break; case ULONGLONG: l->n_lval = val; break; case VOID: break; case LDOUBLE: case DOUBLE: case FLOAT: l->n_op = FCON; l->n_dcon = val; break; default: cerror("unknown type %d", m); } l->n_type = m; l->n_sue = 0; nfree(p); return l; } if (DEUNSIGN(p->n_type) == SHORT && DEUNSIGN(l->n_type) == SHORT) { nfree(p); p = l; } if ((p->n_type == CHAR || p->n_type == UCHAR || p->n_type == SHORT || p->n_type == USHORT) && (l->n_type == FLOAT || l->n_type == DOUBLE || l->n_type == LDOUBLE)) { p = block(SCONV, p, NIL, p->n_type, p->n_df, p->n_sue); p->n_left->n_type = INT; return p; } break; case MOD: case DIV: if (o == DIV && p->n_type != CHAR && p->n_type != SHORT) break; if (o == MOD && p->n_type != CHAR && p->n_type != SHORT) break; /* make it an int division by inserting conversions */ p->n_left = block(SCONV, p->n_left, NIL, INT, 0, 0); p->n_right = block(SCONV, p->n_right, NIL, INT, 0, 0); p = block(SCONV, p, NIL, p->n_type, 0, 0); p->n_left->n_type = INT; break; case PMCONV: case PVCONV: if( p->n_right->n_op != ICON ) cerror( "bad conversion", 0); nfree(p); return(buildtree(o==PMCONV?MUL:DIV, p->n_left, p->n_right)); case FORCE: /* put return value in return reg */ p->n_op = ASSIGN; p->n_right = p->n_left; p->n_left = block(REG, NIL, NIL, p->n_type, 0, 0); p->n_left->n_rval = RETREG(p->n_type); break; case LS: case RS: /* shift count must be in a char * unless longlong, where it must be int */ if (p->n_right->n_op == ICON) break; /* do not do anything */ if (p->n_type == LONGLONG || p->n_type == ULONGLONG) { if (p->n_right->n_type != INT) p->n_right = block(SCONV, p->n_right, NIL, INT, 0, 0); break; } if (p->n_right->n_type == CHAR || p->n_right->n_type == UCHAR) break; p->n_right = block(SCONV, p->n_right, NIL, CHAR, 0, 0); break; } //printf("ut:\n"); //fwalk(p, eprint, 0); #endif return(p); }
/* this is called to do local transformations on * an expression tree preparitory to its being * written out in intermediate code. */ NODE * clocal(NODE *p) { struct symtab *q; NODE *r, *l; int o; int m; TWORD ty; int tmpnr, isptrvoid = 0; #ifdef PCC_DEBUG if (xdebug) { printf("clocal in: %p\n", p); fwalk(p, eprint, 0); } #endif switch (o = p->n_op) { case UCALL: case CALL: case STCALL: case USTCALL: if (p->n_type == VOID) break; /* * if the function returns void*, ecode() invokes * delvoid() to convert it to uchar*. * We just let this happen on the ASSIGN to the temp, * and cast the pointer back to void* on access * from the temp. */ if (p->n_type == PTR+VOID) isptrvoid = 1; r = tempnode(0, p->n_type, p->n_df, p->n_ap); tmpnr = regno(r); r = block(ASSIGN, r, p, p->n_type, p->n_df, p->n_ap); p = tempnode(tmpnr, r->n_type, r->n_df, r->n_ap); if (isptrvoid) { p = block(PCONV, p, NIL, PTR+VOID, p->n_df, 0); } p = buildtree(COMOP, r, p); break; case NAME: if ((q = p->n_sp) == NULL) return p; /* Nothing to care about */ switch (q->sclass) { case PARAM: case AUTO: /* fake up a structure reference */ r = block(REG, NIL, NIL, PTR+STRTY, 0, 0); r->n_lval = 0; r->n_rval = FP; p = stref(block(STREF, r, p, 0, 0, 0)); break; case STATIC: if (q->slevel == 0) break; p->n_lval = 0; p->n_sp = q; break; case REGISTER: p->n_op = REG; p->n_lval = 0; p->n_rval = q->soffset; break; } break; case FUNARG: /* Args smaller than int are given as int */ if (p->n_type != CHAR && p->n_type != UCHAR && p->n_type != SHORT && p->n_type != USHORT) break; p->n_left = block(SCONV, p->n_left, NIL, INT, 0, 0); p->n_type = INT; p->n_ap = 0; p->n_rval = SZINT; break; case CBRANCH: l = p->n_left; /* * Remove unnecessary conversion ops. */ if (clogop(l->n_op) && l->n_left->n_op == SCONV) { if (coptype(l->n_op) != BITYPE) break; if (l->n_right->n_op == ICON) { r = l->n_left->n_left; if (r->n_type >= FLOAT && r->n_type <= LDOUBLE) break; /* Type must be correct */ ty = r->n_type; nfree(l->n_left); l->n_left = r; l->n_type = ty; l->n_right->n_type = ty; } #if 0 else if (l->n_right->n_op == SCONV && l->n_left->n_type == l->n_right->n_type) { r = l->n_left->n_left; nfree(l->n_left); l->n_left = r; r = l->n_right->n_left; nfree(l->n_right); l->n_right = r; } #endif } break; case PCONV: /* Remove redundant PCONV's. Be careful */ l = p->n_left; if (l->n_op == ICON) { l->n_lval = (unsigned)l->n_lval; goto delp; } if (l->n_type < INT || DEUNSIGN(l->n_type) == LONGLONG) { /* float etc? */ p->n_left = block(SCONV, l, NIL, UNSIGNED, 0, 0); break; } /* if left is SCONV, cannot remove */ if (l->n_op == SCONV) break; /* avoid ADDROF TEMP */ if (l->n_op == ADDROF && l->n_left->n_op == TEMP) break; /* if conversion to another pointer type, just remove */ if (p->n_type > BTMASK && l->n_type > BTMASK) goto delp; break; delp: l->n_type = p->n_type; l->n_qual = p->n_qual; l->n_df = p->n_df; l->n_ap = p->n_ap; nfree(p); p = l; break; case SCONV: l = p->n_left; if (p->n_type == l->n_type) { nfree(p); p = l; break; } if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 && tsize(p->n_type, p->n_df, p->n_ap) == tsize(l->n_type, l->n_df, l->n_ap)) { if (p->n_type != FLOAT && p->n_type != DOUBLE && l->n_type != FLOAT && l->n_type != DOUBLE && l->n_type != LDOUBLE && p->n_type != LDOUBLE) { if (l->n_op == NAME || l->n_op == UMUL || l->n_op == TEMP) { l->n_type = p->n_type; nfree(p); p = l; break; } } } if (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == INT && coptype(l->n_op) == BITYPE) { l->n_type = p->n_type; nfree(p); p = l; } if (DEUNSIGN(p->n_type) == SHORT && DEUNSIGN(l->n_type) == SHORT) { nfree(p); p = l; } /* convert float/double to int before to (u)char/(u)short */ if ((DEUNSIGN(p->n_type) == CHAR || DEUNSIGN(p->n_type) == SHORT) && (l->n_type == FLOAT || l->n_type == DOUBLE || l->n_type == LDOUBLE)) { p = block(SCONV, p, NIL, p->n_type, p->n_df, p->n_ap); p->n_left->n_type = INT; break; } /* convert (u)char/(u)short to int before float/double */ if ((p->n_type == FLOAT || p->n_type == DOUBLE || p->n_type == LDOUBLE) && (DEUNSIGN(l->n_type) == CHAR || DEUNSIGN(l->n_type) == SHORT)) { p = block(SCONV, p, NIL, p->n_type, p->n_df, p->n_ap); p->n_left->n_type = INT; break; } o = l->n_op; m = p->n_type; if (o == ICON) { CONSZ val = l->n_lval; if (!ISPTR(m)) /* Pointers don't need to be conv'd */ switch (m) { case BOOL: l->n_lval = l->n_lval != 0; break; case CHAR: l->n_lval = (char)val; break; case UCHAR: l->n_lval = val & 0377; break; case SHORT: l->n_lval = (short)val; break; case USHORT: l->n_lval = val & 0177777; break; case ULONG: case UNSIGNED: l->n_lval = val & 0xffffffff; break; case LONG: case INT: l->n_lval = (int)val; break; case LONGLONG: l->n_lval = (long long)val; break; case ULONGLONG: l->n_lval = val; break; case VOID: break; case LDOUBLE: case DOUBLE: case FLOAT: l->n_op = FCON; l->n_dcon = val; break; default: cerror("unknown type %d", m); } l->n_type = m; nfree(p); p = l; } else if (o == FCON) { l->n_lval = l->n_dcon; l->n_sp = NULL; l->n_op = ICON; l->n_type = m; l->n_ap = 0; nfree(p); p = clocal(l); } break; case MOD: case DIV: if (o == DIV && p->n_type != CHAR && p->n_type != SHORT) break; if (o == MOD && p->n_type != CHAR && p->n_type != SHORT) break; /* make it an int division by inserting conversions */ p->n_left = block(SCONV, p->n_left, NIL, INT, 0, 0); p->n_right = block(SCONV, p->n_right, NIL, INT, 0, 0); p = block(SCONV, p, NIL, p->n_type, 0, 0); p->n_left->n_type = INT; break; case FORCE: /* put return value in return reg */ p->n_op = ASSIGN; p->n_right = p->n_left; p->n_left = block(REG, NIL, NIL, p->n_type, 0, 0); p->n_left->n_rval = RETREG(p->n_type); break; } #ifdef PCC_DEBUG if (xdebug) { printf("clocal out: %p\n", p); fwalk(p, eprint, 0); } #endif return(p); }
/* * generate code by interpreting table entry */ void expand(NODE *p, int cookie, char *cp) { CONSZ val; #if 0 printf("expand\n"); fwalk(p, e2print, 0); #endif for( ; *cp; ++cp ){ switch( *cp ){ default: putchar(*cp); continue; /* this is the usual case... */ case 'Z': /* special machine dependent operations */ zzzcode( p, *++cp ); continue; case 'F': /* this line deleted if FOREFF is active */ if (cookie & FOREFF) { while (*cp && *cp != '\n') cp++; if (*cp == 0) return; } continue; case 'S': /* field size */ if (fldexpand(p, cookie, &cp)) continue; printf("%d", FLDSZ(p->n_rval)); continue; case 'H': /* field shift */ if (fldexpand(p, cookie, &cp)) continue; printf("%d", FLDSHF(p->n_rval)); continue; case 'M': /* field mask */ case 'N': /* complement of field mask */ if (fldexpand(p, cookie, &cp)) continue; val = 1; val <<= FLDSZ(p->n_rval); --val; val <<= FLDSHF(p->n_rval); adrcon( *cp=='M' ? val : ~val ); continue; case 'L': /* output special label field */ if (*++cp == 'C') printf(LABFMT, p->n_label); else printf(LABFMT, (int)getlval(getlr(p,*cp))); continue; case 'O': /* opcode string */ #ifdef FINDMOPS if (p->n_op == ASSIGN) hopcode(*++cp, p->n_right->n_op); else #endif hopcode( *++cp, p->n_op ); continue; case 'B': /* byte offset in word */ val = getlval(getlr(p,*++cp)); val = BYTEOFF(val); printf( CONFMT, val ); continue; case 'C': /* for constant value only */ conput(stdout, getlr( p, *++cp ) ); continue; case 'I': /* in instruction */ insput( getlr( p, *++cp ) ); continue; case 'A': /* address of */ adrput(stdout, getlr( p, *++cp ) ); continue; case 'U': /* for upper half of address, only */ upput(getlr(p, *++cp), SZLONG); continue; } } }
/* clocal() is called to do local transformations on * an expression tree preparitory to its being * written out in intermediate code. * * the major essential job is rewriting the * automatic variables and arguments in terms of * REG and OREG nodes * conversion ops which are not necessary are also clobbered here * in addition, any special features (such as rewriting * exclusive or) are easily handled here as well */ NODE * clocal(NODE *p) { register struct symtab *q; register NODE *r, *l; register int o; TWORD t; #ifdef PCC_DEBUG if (xdebug) { printf("clocal: %p\n", p); fwalk(p, eprint, 0); } #endif switch( o = p->n_op ){ case NAME: if ((q = p->n_sp) == NULL) return p; /* Nothing to care about */ switch (q->sclass) { case PARAM: case AUTO: /* fake up a structure reference */ r = block(REG, NIL, NIL, PTR+STRTY, 0, 0); slval(r, 0); r->n_rval = FPREG; p = stref(block(STREF, r, p, 0, 0, 0)); break; case REGISTER: p->n_op = REG; slval(p, 0); p->n_rval = q->soffset; break; case USTATIC: case STATIC: if (kflag == 0) break; if (blevel > 0 && !statinit) p = picstatic(p); break; case EXTERN: case EXTDEF: if (kflag == 0) break; if (blevel > 0 && !statinit) p = picext(p); break; } break; case ADDROF: if (kflag == 0 || blevel == 0 || statinit) break; /* char arrays may end up here */ l = p->n_left; if (l->n_op != NAME || (l->n_type != ARY+CHAR && l->n_type != ARY+WCHAR_TYPE)) break; l = p; p = picstatic(p->n_left); nfree(l); if (p->n_op != UMUL) cerror("ADDROF error"); l = p; p = p->n_left; nfree(l); break; case STASG: /* convert struct assignment to call memcpy */ l = p->n_left; if (l->n_op == NAME && ISFTN(l->n_sp->stype)) break; /* struct return, do nothing */ /* first construct arg list */ p->n_left = buildtree(ADDROF, p->n_left, 0); r = bcon(tsize(STRTY, p->n_df, p->n_ap)/SZCHAR); p->n_left = buildtree(CM, p->n_left, p->n_right); p->n_right = r; p->n_op = CM; p->n_type = INT; r = block(NAME, NIL, NIL, INT, 0, 0); r->n_sp = lookup(addname("memcpy"), SNORMAL); if (r->n_sp->sclass == SNULL) { r->n_sp->sclass = EXTERN; r->n_sp->stype = INCREF(VOID+PTR)+(FTN-PTR); } r->n_type = r->n_sp->stype; p = buildtree(CALL, r, p); break; case SCONV: l = p->n_left; if (l->n_op == ICON && ISPTR(l->n_type)) { /* Do immediate cast here */ /* Should be common code */ q = l->n_sp; l->n_sp = NULL; l->n_type = UNSIGNED; if (concast(l, p->n_type) == 0) cerror("clocal"); p = nfree(p); p->n_sp = q; } break; case FORCE: /* put return value in return reg */ p->n_op = ASSIGN; p->n_right = p->n_left; p->n_left = block(REG, NIL, NIL, p->n_type, 0, 0); t = p->n_type; if (ISITY(t)) t = t - (FIMAG-FLOAT); p->n_left->n_rval = RETREG(t); break; } #ifdef PCC_DEBUG if (xdebug) { printf("clocal end: %p\n", p); fwalk(p, eprint, 0); } #endif return(p); }
T DoubleList<T>::set(int pos, T data) { Node<T> * tmp = fwalk(head, pos); tmp->data = data; return data; }
T DoubleList<T>::get(int pos) const { if (pos < 0) { return (T)(NULL); } return fwalk(head, pos)->data; }