Exemple #1
0
/*
 * 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);
	}
}
Exemple #2
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;

	}
}
Exemple #3
0
/*
 * 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);
}
Exemple #4
0
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;
}
Exemple #5
0
static void
sendp2(NODE *p)
{
	extern int thisline;

	p2tree(p);
	thisline = lineno;
	if (debugflag)
		fwalk(p, e2print, 0);
	pass2_compile(ipnode(p));
}
Exemple #6
0
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;
}
Exemple #7
0
/*
 * 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);
}
Exemple #8
0
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 */
Exemple #9
0
/*
 * 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;
}
Exemple #10
0
/* 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);
}
Exemple #11
0
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);
}
Exemple #12
0
/* 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);
}
Exemple #13
0
/*
 * 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;

			}

		}

	}
Exemple #14
0
/* 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);
}
Exemple #15
0
T DoubleList<T>::set(int pos, T data) {
  Node<T> * tmp = fwalk(head, pos);
  tmp->data = data;
  return data;
}
Exemple #16
0
T DoubleList<T>::get(int pos) const {
  if (pos < 0) { return (T)(NULL); }
  return fwalk(head, pos)->data;
}