File:  [Research Unix] / researchv10no / cmd / lcc / c / dag.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:21:35 2018 UTC (8 years, 1 month ago) by root
Branches: belllabs, MAIN
CVS tags: researchv10, HEAD
researchv10 Norman

/* C compiler: dag processing */

#include "c.h"
#define NBUCKETS 020

struct code codehead = { Start };
Code codelist = &codehead;	/* list of code nodes for current function */
int nodecount;			/* # of available nodes in hash table */

static struct dag {		/* dags: */
	struct node node;		/* the node itself */
	struct dag *hlink;		/* next dag on hash chain */
} *buckets[NBUCKETS];		/* hash table */
static Node nodelist;		/* node list */
dclproto(static struct dag *dagnode,(int, Node, Node, Symbol));
dclproto(static void fixup,(Node));
dclproto(static int haskid,(Node, Node));
dclproto(static Node labelnode,(int));
dclproto(static Node list,(Node));
dclproto(static void reset,(void));
dclproto(static void remove,(Node));
dclproto(static void trash,(Node));
dclproto(static void typestab,(Symbol, Generic));
dclproto(static Node undag,(Node));
dclproto(static Node undag1,(Node, Node));

/* addlocal - add local p to list of locals for the current block */
void addlocal(p) Symbol p; {
	if (!p->defined) {
		code(Local)->u.var = p;
		p->defined = 1;
		p->scope = level;
	}
}

/* btot - map operator op or suffix op into a representative type */
Type btot(op) int op; {
	switch (optype(op)) {
	case F: return floattype;
	case D: return doubletype;
	case C: return chartype;
	case S: return shorttype;
	case I: return inttype;
	case U: return unsignedtype;
	case P: return voidptype;
	default: assert(0);
	}
	return 0;
}

/* code - allocate a code node of kind and append to the code list */
Code code(kind) {
	Code cp;

	if (kind > Label) {
		for (cp = codelist; cp->kind < Label; )
			cp = cp->prev;
		if (cp->kind == Jump)
			warning("unreachable code\n");
	}
	cp = (Code)talloc(sizeof *cp);
	cp->kind = kind;
	cp->prev = codelist;
	cp->next = 0;
	codelist->next = cp;
	return codelist = cp;
}

/* dagnode - allocate a dag with the given fields */
static struct dag *dagnode(op, l, r, sym) Node l, r; Symbol sym; {
	register struct dag *p = (struct dag *) talloc(sizeof *p);

	BZERO(p, struct dag);
	p->node.op = op;
	if (p->node.kids[0] = l)
		++l->count;
	if (p->node.kids[1] = r)
		++r->count;
	p->node.syms[0] = sym;
	return p;
}

/* emitcode - emit code for the current function */
void emitcode() {
	Code bp, cp;
	Coordinate save;

	save = src;
	for (bp = 0, cp = &codehead; errcnt <= 0 && cp; cp = cp->next)
		switch (cp->kind) {
		case Blockbeg:
			cp->u.block.prev = bp;
			bp = cp;
			if (glevel && IR->stabblock) {
				(*IR->stabblock)('{',  bp->u.block.level - LOCAL, bp->u.block.locals);
				swtoseg(CODE);
			}
			break;
		case Blockend:
			if (glevel && IR->stabblock) {
				foreach(bp->u.block.identifiers, bp->u.block.level, typestab, (Generic)0);
				foreach(bp->u.block.types,       bp->u.block.level, typestab, (Generic)0);
				(*IR->stabblock)('}', bp->u.block.level - LOCAL, bp->u.block.locals);
				swtoseg(CODE);
			}
			bp = bp->u.block.prev;
			break;
		case Local:
			if (glevel && IR->stabsym) {
				(*IR->stabsym)(cp->u.var);
				swtoseg(CODE);
			}
			break;
		case Defpoint:
			src = cp->u.point.src;
			if (glevel && IR->stabline) {
				(*IR->stabline)(&cp->u.point.src);
				swtoseg(CODE);
			}
			break;
		case Jump:
			if (cp->u.node == 0)
				break;
			/* else fall thru */
		case Gen: case Label:
			(*IR->emit)(cp->u.node);
			break;
		case Switch: {
			int i, k = cp->u.swtch.values[0];
			for (i = 0; i < cp->u.swtch.size; i++) {
				while (k++ < cp->u.swtch.values[i])
					(*IR->defaddress)(cp->u.swtch.deflab->u.l.equatedto);
				(*IR->defaddress)(cp->u.swtch.labels[i]->u.l.equatedto);
			}
			break;
			}
		}
	src = save;
}

/* fixup - re-aim equated labels to the true label */
static void fixup(p) Node p; {
	for ( ; p; p = p->link)
		switch (generic(p->op)) {
		case JUMP:
			if (p->kids[0]->op == ADDRG+P)
				p->kids[0]->syms[0] = p->kids[0]->syms[0]->u.l.equatedto;
			break;
		case LABEL:
		case EQ: case GE: case GT: case LE: case LT: case NE:
			assert(p->syms[0]);
			p->syms[0] = p->syms[0]->u.l.equatedto;
		}
}

/* gencode - generate code for the current function */
void gencode(caller, callee) Symbol caller[], callee[]; {
	int i;
	Code bp, cp;
	Symbol p, q;
	Coordinate save;

	save = src;
	cp = codehead.next->next;
	codelist = codehead.next;
	for (i = 0; (p = callee[i]) && (q = caller[i]); i++)
		if (p->sclass != q->sclass || p->type != q->type) {
			walk(asgn(p, idnode(q)), 0, 0);
			if (glevel && IR->stabsym) {
				(*IR->stabsym)(p);
				(*IR->stabsym)(q);
				swtoseg(CODE);
			}
		} else if (glevel && IR->stabsym) {
			(*IR->stabsym)(p);
			swtoseg(CODE);
		}
	codelist->next = cp;
	cp->prev = codelist;
	for (bp = 0, cp = &codehead; errcnt <= 0 && cp; cp = cp->next)
		switch (cp->kind) {
		case Start: case Switch:
			break;
		case Defpoint: 
			src = cp->u.point.src;
			break;
		case Blockbeg: {
			Symbol *p = cp->u.block.locals;
			cp->u.block.prev = bp;
			bp = cp;
			(*IR->blockbeg)(&bp->u.block.x);
			for ( ; *p; p++)
				if ((*p)->ref || glevel)
					(*IR->local)(*p);
			break;
			}
		case Blockend:
			(*IR->blockend)(&bp->u.block.x);
			bp = bp->u.block.prev;
			break;
		case Local:
			assert(cp->u.var->scope == bp->u.block.level);
			(*IR->local)(cp->u.var);
			break;
		case Address:
			(*IR->address)(cp->u.addr.sym, cp->u.addr.base, cp->u.addr.offset);
			break;
		case Jump:
			if (cp->u.node == 0)
				break;
			/* else fall thru */
		case Gen: case Label:
			fixup(cp->u.node);
			if (IR->no_dag)
				cp->u.node = undag(cp->u.node);
			cp->u.node = (*IR->gen)(cp->u.node);
			break;
		default:assert(0);
		}
	src = save;
}

/* haskid - does p appear as an operand in t? */
static int haskid(p, t) Node p, t; {
	if (t == 0)
		return 0;
	else if (p == t)
		return 1;
	else
		return haskid(p, t->kids[0]) || haskid(p, t->kids[1]); 
}

/* labelnode - list and return a LABEL node for label lab */
static Node labelnode(lab) {
	assert(lab);
	if (islabel(nodelist)) {
		equatelab(findlabel(lab), nodelist->syms[0]);
		return nodelist;
	}
	return list(newnode(LABEL+V, 0, 0, findlabel(lab)));
}

/* list - list node p unless it's already listed; return p */
static Node list(p) Node p; {
	if (p && p->link == 0) {
		if (nodelist) {
			p->link = nodelist->link;
			nodelist->link = p;
		} else
			p->link = p;
		nodelist = p;
#ifdef DAGCHECK
		{ extern void type_checker(Node); type_checker(p); }
#endif
	}
	return p;
}

/* listnodes - walk tree tp, building and listing dag nodes in execution order */
Node listnodes(tp, tlab, flab) Tree tp; {
	Opcode op;
	Node p, l, r;

	if (tp == 0)
		return 0;
	if (tp->node)
		return tp->node;
	op = generic(tp->op);
	switch (op) {
	case AND:
		if (flab) {
			listnodes(tp->kids[0], 0, flab);
			r = listnodes(tp->kids[1], 0, flab);
		} else {
			listnodes(tp->kids[0], 0, flab = genlabel(1));
			listnodes(tp->kids[1], tlab, 0);
			r = labelnode(flab);
		}
		trash(0);
		return r;
	case NOT:
		return listnodes(tp->kids[0], flab, tlab);
	case OR:
		if (tlab) {
			listnodes(tp->kids[0], tlab, 0);
			r = listnodes(tp->kids[1], tlab, 0);
		} else {
			listnodes(tp->kids[0], tlab = genlabel(1), 0);
			listnodes(tp->kids[1], 0, flab);
			r = labelnode(tlab);
		}
		trash(0);
		return r;
	case COND: {
		Tree q;
		assert(tlab == 0 && flab == 0);
		if (tp->u.sym)
			addlocal(tp->u.sym);
		trash(0);
		listnodes(tp->kids[0], 0, flab = genlabel(2));
		trash(0);
		if (q = tp->kids[1]) {
			assert(q->op == RIGHT);
			listnodes(q->kids[0], 0, 0);
			if (islabel(nodelist)) {
				equatelab(nodelist->syms[0], findlabel(flab + 1));
				remove(nodelist);
			}
			trash(0);
		}
		if (q && q->kids[1]) {
			list(jump(flab + 1));
			labelnode(flab);
			listnodes(q->kids[1], 0, 0);
			if (islabel(nodelist)) {
				equatelab(nodelist->syms[0], findlabel(flab + 1));
				remove(nodelist);
			}
		} else
			labelnode(flab);
		p = labelnode(flab + 1);
		trash(0);
		if (tp->u.sym) {
			Tree t = idnode(tp->u.sym);
			tp->u.sym->ref = 0;	/* undo idnode's setting ref */
			p = listnodes(t, 0, 0);
		}
		break;
		}
	case CNST: {
		Type ty = unqual(tp->type);
		assert(op == CNST+S || ty->u.sym);
		if (op == CNST+S || ty->u.sym->addressed)
			p = listnodes(cvtconst(tp), tlab, flab);
		else if (tlab == 0 && flab == 0)
			p = node(tp->op, 0, 0, constant(ty, tp->u.v));
		else {
			assert(ty == inttype);
			if (tlab && tp->u.v.i != 0)
				p = list(jump(tlab));
			else if (flab && tp->u.v.i == 0)
				p = list(jump(flab));
			else
				p = 0;
		}
		break;
		}
	case RIGHT:
		if (tp->kids[0] && generic(tp->kids[0]->op) == INDIR
		&&  tp->kids[1] && generic(tp->kids[1]->op) == ASGN
		&&  tp->kids[0]->kids[0] == tp->kids[1]->kids[0]) {	/* e++ */
			p = listnodes(tp->kids[0], 0, 0);
			if (nodelist) {
				Node t;
				for (t = nodelist; ; t = t->link)
					if (haskid(p, t->link)) {
						p->link = t->link;
						t->link = p;
						break;
					} else if (t->link == nodelist) {
						list(p);
						break;
					}
			} else
				list(p);
			listnodes(tp->kids[1], 0, 0);
		} else if (tp->kids[1]) {
			if (tp->kids[0] && generic(tp->kids[0]->op) == CNST)
				tp->kids[0] = 0;
			listnodes(tp->kids[0], 0, 0);
			p = listnodes(tp->kids[1], tlab, flab);
		} else
			p = listnodes(tp->kids[0], tlab, flab);
		break;
	case JUMP:
		assert(tlab == 0 && flab == 0);
		assert(tp->u.sym == 0);
		assert(tp->kids[0]);
		l = listnodes(tp->kids[0], 0, 0);
		p = newnode(JUMP+V, l, 0, 0);
		trash(0);
		list(p);
		break;
	case CALL:
		assert(tlab == 0 && flab == 0);
		l = listnodes(tp->kids[0], 0, 0);	/* arguments, function name */
		r = listnodes(tp->kids[1], 0, 0);
		p = newnode(tp->op, l, r, 0);
		p->syms[0] = (Symbol)talloc(sizeof *p->syms[0]);
		BZERO(p->syms[0], struct symbol);
		if (isptr(tp->kids[0]->type) && isfunc(tp->kids[0]->type->type))
			p->syms[0]->type = tp->kids[0]->type->type;
		else
			p->syms[0]->type = func(voidtype, 0, 1);
		trash(0);
		list(p);
		cfunc->u.f.ncalls++;
		break;
	case ARG:
		assert(tlab == 0 && flab == 0);
		if (IR->left_to_right)
			listnodes(tp->kids[1], 0, 0);
		l = listnodes(tp->kids[0], 0, 0);
		p = newnode(tp->op, l, 0, 0);
		p->syms[0] = intconst(tp->type->size);
		p->syms[1] = intconst(tp->type->align);
		list(p);
		if (!IR->left_to_right)
			listnodes(tp->kids[1], 0, 0);
		return 0;
	case EQ: case NE: case GT: case GE: case LE: case LT: {
		int lab;
		assert(tp->u.sym == 0);
		assert(errcnt || tlab || flab);
		if (lab = flab) {
			assert(tlab == 0);
			switch (op) {
			case EQ: op = NE + optype(tp->op); break;
			case NE: op = EQ + optype(tp->op); break;
			case GT: op = LE + optype(tp->op); break;
			case LT: op = GE + optype(tp->op); break;
			case GE: op = LT + optype(tp->op); break;
			case LE: op = GT + optype(tp->op); break;
			}
		} else if (lab = tlab)
			op = tp->op;
		l = listnodes(tp->kids[0], 0, 0);
		r = listnodes(tp->kids[1], 0, 0);
		p = newnode(op, l, r, findlabel(lab));
		p->syms[0]->ref++;
		list(p);
		break;
		}
	case ASGN:
		assert(tlab == 0 && flab == 0);
		if (tp->kids[0]->op == FIELD) {
			Tree x = tp->kids[0]->kids[0];
			Field p = tp->kids[0]->u.field;
			assert(generic(x->op) == INDIR);
			trash(0);
			l = listnodes(lvalue(x), 0, 0);
			if (fieldsize(p) < 8*p->type->size) {
				unsigned int fmask = fieldmask(p);
				unsigned int mask = fmask<<fieldright(p);
				Tree q = tp->kids[1];
				if (q->op == CNST+I && q->u.v.i == 0
				||  q->op == CNST+U && q->u.v.u == 0)
					q = bitnode(BAND, x, constnode(~mask, unsignedtype));
				else if (q->op == CNST+I && (q->u.v.i&fmask) == fmask
				||       q->op == CNST+U && (q->u.v.u&fmask) == fmask)
					q = bitnode(BOR, x, constnode(mask, unsignedtype));
				else
					q = bitnode(BOR,
						bitnode(BAND, x, constnode(~mask, unsignedtype)),
						bitnode(BAND, shnode(LSH, cast(q, unsignedtype),
							constnode(fieldright(p), inttype)),
							constnode(mask, unsignedtype)));
				r = listnodes(q, 0, 0);
			} else
				r = listnodes(tp->kids[1], 0, 0);
		} else {
			l = listnodes(tp->kids[0], 0, 0);
			r = listnodes(tp->kids[1], 0, 0);
		}
		trash(isaddrop(tp->kids[0]->op) && !tp->kids[0]->u.sym->computed ? l : 0);
		p = newnode(tp->op, l, r, 0);
		p->syms[0] = intconst(tp->kids[1]->type->size);
		p->syms[1] = intconst(tp->kids[1]->type->align);
		list(p);
		p = listnodes(tp->kids[1], 0, 0);
		break;
	case BAND:
		assert(tlab == 0 && flab == 0);
		l = listnodes(tp->kids[0], 0, 0);
		if (IR->compl_band)
			r = listnodes(cast(
				simplify(BCOM+U, unsignedtype,
					cast(tp->kids[1], unsignedtype), 0),
				tp->kids[1]->type), 0, 0);
		else
			r = listnodes(tp->kids[1], 0, 0);
		p = node(tp->op, l, r, 0);
		break;
	case RSH:
		assert(tlab == 0 && flab == 0);
		l = listnodes(tp->kids[0], 0, 0);
		if (IR->compl_band && tp->op == RSH+I)
			r = listnodes(simplify(NEG+I, inttype, tp->kids[1], 0), 0, 0);
		else
			r = listnodes(tp->kids[1], 0, 0);
		p = node(tp->op, l, r, 0);
		break;
	case ADD: case SUB:  case DIV: case MUL: case MOD:
	case BOR: case BXOR: case LSH:
		assert(tlab == 0 && flab == 0);
		l = listnodes(tp->kids[0], 0, 0);
		r = listnodes(tp->kids[1], 0, 0);
		p = node(tp->op, l, r, 0);
		if (IR->mulops_are_calls &&
		   (p->op == DIV+I || p->op == MOD+I || p->op == MUL+I
		||  p->op == DIV+U || p->op == MOD+U || p->op == MUL+U))
			list(p);
		break;
	case RET:
		assert(tlab == 0 && flab == 0);
		l = listnodes(tp->kids[0], 0, 0);
		p = newnode(tp->op, l, 0, 0);
		list(p);
		break;
	case CVC: case CVD: case CVF: case CVI:
	case CVP: case CVS: case CVU: case NEG: case BCOM:
		assert(tlab == 0 && flab == 0);
		l = listnodes(tp->kids[0], 0, 0);
		p = node(tp->op, l, 0, 0);
		break;
	case INDIR: {
		Type ty = tp->kids[0]->type;
		if (isptr(ty))
			ty = unqual(ty)->type;
		assert(tlab == 0 && flab == 0);
		l = listnodes(tp->kids[0], 0, 0);
		if (isvolatile(ty) || (isstruct(ty) && unqual(ty)->u.sym->u.s.vfields))
			p = newnode(tp->op, l, 0, 0);
		else
			p = node(tp->op, l, 0, 0);
		break;
		}
	case FIELD: {
		Tree q;
		assert(tlab == 0 && flab == 0);
		q = shnode(RSH,
			shnode(LSH, tp->kids[0],
				constnode(fieldleft(tp->u.field), inttype)),
			constnode(8*tp->type->size - fieldsize(tp->u.field), inttype));
		p = listnodes(q, 0, 0);
		break;
		}
	case ADDRL:
		assert(tlab == 0 && flab == 0);
		if (tp->u.sym->temporary) {
			addlocal(tp->u.sym);
			release(tp->u.sym);
		}
		p = node(tp->op, 0, 0, tp->u.sym);
		break;
	case ADDRG: case ADDRF:
		assert(tlab == 0 && flab == 0);
		if (tp->u.sym->scope == LABELS)
			tp->u.sym->ref++;
		p = node(tp->op, 0, 0, tp->u.sym);
		break;
	default:assert(0);
	}
	return tp->node = p;
}

/* jump - return tree for a jump to lab */
Node jump(lab) {
	Symbol p = findlabel(lab);

	p->ref++;
	return newnode(JUMP+V, node(ADDRG+P, 0, 0, p), 0, 0);
}

/* newnode - allocate a node with the given fields */
Node newnode(op, l, r, sym) Node l, r; Symbol sym; {
	return &dagnode(op, l, r, sym)->node;
}

/* node - search for a node with the given fields, or allocate it */
Node node(op, l, r, sym) Node l, r; Symbol sym; {
	int i = (opindex(op)^((unsigned)sym>>2))&(NBUCKETS-1);
	register struct dag *p;

	for (p = buckets[i]; p; p = p->hlink)
		if (p->node.op == op && p->node.syms[0] == sym
		&& p->node.kids[0] == l && p->node.kids[1] == r)
			return &p->node;
	p = dagnode(op, l, r, sym);
	p->hlink = buckets[i];
	buckets[i] = p;
	++nodecount;
	return &p->node;
}

dclproto(static void printdag1,(Node, int, int));
dclproto(static void printnode,(Node, int, int));

/* printdag - print dag p on fd, or the node list if p == 0 */
void printdag(p, fd) Node p; {
	printed(0);
	if (p == 0) {
		if (p = nodelist)
			do {
				p = p->link;
				printdag1(p, fd, 0);
			} while (p != nodelist);
	} else if (*printed(nodeid((Tree)p)))
		fprint(fd, "node'%d printed above\n", nodeid((Tree)p));
	else
		printdag1(p, fd, 0);
}

/* printdag1 - recursively print dag p */
static void printdag1(p, fd, lev) Node p; {
	int id, i;

	if (p == 0 || *printed(id = nodeid((Tree)p)))
		return;
	*printed(id) = 1;
	for (i = 0; i < MAXKIDS; i++)
		printdag1(p->kids[i], fd, lev + 1);
	printnode(p, fd, lev);
}

/* printnode - print fields of dag p */
static void printnode(p, fd, lev) Node p; {
	if (p) {
		int i, id = nodeid((Tree)p);
		fprint(fd, "%c%d%s", lev == 0 ? '\'' : '#', id,
			&"   "[id < 10 ? 0 : id < 100 ? 1 : 2]);
		fprint(fd, "%s count=%d", opname(p->op), p->count);
		for (i = 0; i < MAXKIDS && p->kids[i]; i++)
			fprint(fd, " #%d", nodeid((Tree)p->kids[i]));
		for (i = 0; i < MAXSYMS && p->syms[i]; i++)
			fprint(fd, " %s", p->syms[i]->name);
		fprint(fd, "\n");
	}
}

/* remove - remove node p from the node list */
static void remove(p) Node p; {
	if (nodelist) {
		Node q = nodelist;
		for ( ; q->link != p && q->link != nodelist; q = q->link)
			;
		assert(q->link == p);
		q->link = p->link;
		if (p == nodelist)
			nodelist = q;
	}
}

/* reset - clear the dag */
static void reset() {
	BZERO(buckets, struct dag *[NBUCKETS]);
	nodecount = 0;
}

/* trash - preclude future links to rvalue of p or all values */
static void trash(p) Node p; {
	if (p) {
		register int i;
		register struct dag *q, **r;
		for (i = 0; i < NBUCKETS; i++)
			for (r = &buckets[i]; q = *r; )
				if (generic(q->node.op) == INDIR && (!isaddrop(q->node.kids[0]->op)
				|| q->node.kids[0]->syms[0] == p->syms[0])) {
					*r = q->hlink;
					--nodecount;
				} else
					r = &q->hlink;
	} else if (nodecount > 0)
		reset();
}

/* typestab - emit stab entries for p */
static void typestab(p, cl) Symbol p; Generic cl; {
	if (!isfunc(p->type) && (p->sclass == EXTERN || p->sclass == STATIC) && IR->stabsym)
		(*IR->stabsym)(p);
	else if ((p->sclass == TYPEDEF || p->sclass == 0) && IR->stabtype)
		(*IR->stabtype)(p);
}

#define iscall(p) (generic((p)->op) == CALL || IR->mulops_are_calls \
	&& ((p)->op == DIV+I || (p)->op == MOD+I || (p)->op == MUL+I \
	||  (p)->op == DIV+U || (p)->op == MOD+U || (p)->op == MUL+U))

/* undag - replace multiply-referenced nodes in nodelist by temporaries, return new nodelist */
static Node undag(nodelist) Node nodelist; {
	Node p, pred;
	struct node head;

	head.link = nodelist;
	for (pred = &head; p = pred->link; ) {
		/*
		 * succ is p's successor,
		 * pred is p's predecessor, and
		 * p->link == pred;
		 * undag1(x, p) adds predecessors and maintains p->link == p->link->link.
		 */
		Node succ = p->link;
		p->link = pred;
		if (generic(p->op) == INDIR) {
			assert(p->count >= 1);
			undag1(p, p);
			/*
			 * remove p from the node list,
			 * setting pred to the last node inserted (if any).
			 */
			pred = p->link;
			pred->link = succ;
			p->link = 0;
		} else if (iscall(p) && p->count >= 1) {
			Node q;
			undag1(p, p);
			/*
			 * p->link is p's predecessor,
			 * which is the ASGN of p to a temporary.
			 */
			assert(p->link && generic(p->link->op) == ASGN && p->link->kids[1] == p);
			/*
			 * remove p from the node list,
			 * setting pred to the ASGN node.
			 */
			pred = p->link;
			pred->link = succ;
			/*
			 * re-insert p into the node list
			 * immediately before its predecessor;
			 * this places the CALL node before the ASGN node.
			 * / 
			for (q = &head; q && q->link != pred; q = q->link)
				;
			assert(q);
			q->link = p;
			p->link = pred; */
			p->link = 0;
		} else {
			assert(p->count == 0);
			undag1(p, p);
			/*
			 * reestablish p's successor, and
			 * advance pred so that pred->link == succ
			 */
			p->link = succ;
			pred = p;
		}
	}
	rmtemps(0, LOCAL);
	return head.link;
}

/* undag1 - return a reference to the temporary holding value of p, or p */
static Node undag1(p, root) Node p, root; {
	Node e;

	if (p == 0)
		;
	else if (p->syms[2]) {
		e = newnode(INDIR + (isunsigned(p->syms[2]->type) ? I : ttob(p->syms[2]->type)),
			newnode(ADDRL+P, 0, 0, p->syms[2]), 0, 0);
		e->count = 1;
		if (--p->count == 1) {
			/* fprint(2, "releasing %s from ", p->syms[2]->name); printnode(p, 2, 1);
			release(p->syms[2]); */
			p->syms[2] = 0;
		}
		p = e;
	} else if (p->count <= 1 && !iscall(p)
	||         p->count == 0 &&  iscall(p)) {
		p->kids[0] = undag1(p->kids[0], root);
		p->kids[1] = undag1(p->kids[1], root);
	} else if (p->op == ADDRL+P || p->op == ADDRF+P) {
		assert(p != root);
		p = newnode(p->op, 0, 0, p->syms[0]);
		p->count = 1;
	} else if (generic(p->op) == INDIR
	&& (p->kids[0]->op == ADDRL+P || p->kids[0]->op == ADDRF+P)
	&& p->kids[0]->syms[0]->sclass == REGISTER && p != root) {
		p = newnode(p->op, 
			newnode(p->kids[0]->op, 0, 0, p->kids[0]->syms[0]), 0, 0);
		p->count = 1;
	} else if (p->op == INDIR+B) {
		--p->count;
		p = newnode(p->op, p->kids[0], 0, 0);
		p->count = 1;
		p->kids[0] = undag1(p->kids[0], root);
	} else {
		p->syms[2] = temporary(REGISTER, btot(p->op));
		/* fprint(2, "allocating %s to ", p->syms[2]->name); printnode(p, 2, 1); */
		if (!p->syms[2]->defined) {
			p->syms[2]->scope = LOCAL;
			p->syms[2]->ref = 1;
			(*IR->local)(p->syms[2]);
			p->syms[2]->defined = 1;
		}
		p->kids[0] = undag1(p->kids[0], root);
		p->kids[1] = undag1(p->kids[1], root);
		e = newnode(ASGN + (isunsigned(p->syms[2]->type) ? I : ttob(p->syms[2]->type)),
			newnode(ADDRL+P, 0, 0, p->syms[2]), p, 0);
		e->syms[0] = intconst(p->syms[2]->type->size);
		e->syms[1] = intconst(p->syms[2]->type->align);
		/*
		 * root->link is the root's predecessor;
		 * point the root's predecessor to the ASGN,
		 * make the ASGN the root's new predecessor,
		 * and make root the ASGN's successor.
		 */
		root->link = root->link->link = e;
		e->link = root;
		if (p != root)
			p = undag1(p, root);	/* returns reference to the temporary */
	}
	return p;
}

/* walk - list tree tp, generate code for current node list, reset node list */
void walk(tp, tlab, flab) Tree tp; {
	listnodes(tp, tlab, flab);
	if (nodelist) {
		trash(0);
		code(Gen);
		codelist->u.node = nodelist->link;
		nodelist->link = 0;
		nodelist = 0;
		rmtemps(REGISTER, 0);
	}
	reset();
	ntree = 0;
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.