File:  [Research Unix] / researchv10no / cmd / lcc / gen2 / gen.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: machine-independent back-end support routines */

#include "c.h"

unsigned freemask[3];
int savebase[3];
unsigned savemask[3];
unsigned tempmask[3];
unsigned usedmask[3];
unsigned eemask[3];
unsigned tmask[3];
unsigned vmask[3];

char **asmstr[MAXINTS];
int nregsets;
Node last;
int maxoffset;
int ncalls;
int offset;
int argoffset;
int argbuildsize;
int bflag, dflag, kflag, pflag, rflag;
char **opcodes;
Symbol regs;
Symbol regvars;
Symbol rmap[8];
int dalign, salign;
int genx = 2;

static int cseg;
static Node curhead;

dclproto(static Node *findxnext,(Node));
dclproto(static void freereg,(Symbol));
dclproto(static void genreload,(Node*, Symbol, int, Symbol));
dclproto(static void genreloads,(Node, Symbol, int, Symbol));
dclproto(static Symbol genspill,(Symbol, int, Node *));
dclproto(static Symbol getreg,(Symbol, Node, unsigned, int));
dclproto(static void linearize,(Node, Node *, Node));
dclproto(static Node *lin1,(Node, Node *));
dclproto(static Symbol mkreg,(char *, int, int, int, int, Symbol));
dclproto(static void mvregvar,(Symbol, unsigned));
dclproto(static int ntob,(Symbol));
dclproto(static int overlaps,(Symbol, Symbol));
dclproto(static void ralloc,(Node));
dclproto(static int rmember,(Regnode, Symbol));
dclproto(static Symbol spillee,(Symbol, Node, unsigned));
dclproto(static void spillr,(Symbol, Node));
dclproto(static int uses,(Node, Symbol));

/* aset - record that p and any right ADD+P descendants are address calculations */
int aset(p, n) Node p; {
	p = p->kids[n];
	p->x.loadaddr = 1;
	while (p->op == ADD+P) {
		p = p->kids[1];
		p->x.loadaddr = 1;
	}
	return 1;
}

/* bitcount - count number of 1 bits in mask */
int bitcount(mask) unsigned mask; {
	unsigned i, n = 0;

	for (i = 1; i; i <<= 1)
		if (mask&i)
			n++;
	return n;
}

/* blkcopy - emit code to copy size bytes from sreg+soff to dreg+doff using tmp regs */
void blkcopy(dreg, doff, sreg, soff, size, tmp) int tmp[]; {
	if (size <= 0)
		return;
	else if (size <= 1) {
		blkunroll(1, dreg, doff, sreg, soff, size, tmp);
	} else if (size <= 3) {
		blkunroll(2, dreg, doff, sreg, soff, 2, tmp);
		blkcopy(dreg, doff+(size&~(2-1)), sreg, soff+(size&~(2-1)), size&(2-1), tmp);
	} else if (size <= 16) {
		blkunroll(4, dreg, doff, sreg, soff, size&~(4-1), tmp);
		blkcopy(dreg, doff+(size&~(4-1)), sreg, soff+(size&~(4-1)), size&(4-1), tmp);
	} else
		(*IR->x.blkloop)(dreg, doff, sreg, soff, size, tmp);
}

/* blkunroll - blkcopy as an unrolled loop using k-byte chunks */
void blkunroll(k, dreg, doff, sreg, soff, size, tmp) int tmp[]; {
	int i;

	assert(IR->x.maxunalignedload);
	if ((salign < k || dalign < k) && k > IR->x.maxunalignedload)
		k = IR->x.maxunalignedload;
	(*IR->x.blkfetch)(k, soff, sreg, tmp[0]);
	for (i = k; i <= size - k; i += k) {
		(*IR->x.blkfetch)(k, i+soff,   sreg, tmp[(i&k)==k]);
		(*IR->x.blkstore)(k, i+doff-k, dreg, tmp[(i&k)!=k]); 
	}
	(*IR->x.blkstore)(k, i+doff-k, dreg, tmp[((i-k)&k)==k]);
}

/* blockbeg - begin a compound statement */
void blockbeg(e) Env *e; {
	int i;

	e->off = offset;
	for (i = 0; i < nregsets; i++)
		e->freemask[i] = freemask[i];
}

/* blockend - end a compound statement */
void blockend(e) Env *e; {
	int i;

	if (offset > maxoffset)
		maxoffset = offset;
	offset = e->off;
	for (i = 0; i < nregsets; i++)
		freemask[i] = e->freemask[i];
}

/* docall - finalize a call */
void docall(p) Node p; {
	if (argoffset > argbuildsize)
		argbuildsize = argoffset;
	p->syms[0] = intconst(argoffset);
	argoffset = 0;
}

/* dumpregs - trace register allocation */
void dumpregs(msg, a, b) char *a, *b, *msg; {
	int i;

	fprint(2, msg, a, b);
	for (i = 0; i < nregsets; i++)
		fprint(2, "(free[%d]=%x)\n", i, freemask[i]);
}

/* dumptree1 - emit debugging image of dag p, indented n, with kid# k */
void dumptree1(p, op, k, n) Node p; {
	int i;
	char *s;
	extern char **opcodes;

	if (dflag == 0 || p == 0)
		return;
	for (i = 0; i < n; i++)
		fprint(2, " ");
	if (k < 0)
		fprint(2, "(root=%x ", p);
	else
		fprint(2, "(kid%d=%x ", k, p);
	s = opname(op);
	if (*s >= '0' && *s <= '9')
		s = opcodes[op];
	fprint(2, "op=%s ", s);
	for (i = 0; i < MAXINTS; i++)
		if (p->x.ints[i])
			fprint(2, "I%d=%s ", i, asmstr[i][p->x.ints[i]]);
	for (i = 0; i < MAXSYMS; i++)
		if (p->syms[i])
			fprint(2, "S%d=%s ", i, p->syms[i]->x.name);
	fprint(2, "count=%d)\n", p->count);
	if (p->x.registered == 0)
		for (i = 0; i < MAXKIDS; i++)
			if (p->kids[i])
				dumptree1(p->kids[i], p->kids[i]->op, i, n+1);
	if (k == -1)
		fprint(2, "\n");
}

void export(p) Symbol p; {
	if (!bflag)
		print(IR->x.exportfmt, p->x.name);
}

/* findxnext - return the address of the pointer to p in the linearized chain */
static Node *findxnext(p) Node p; {
	Node *q;

	for (q = &curhead; *q; q = &(*q)->x.next)
		if (*q == p)
			return q;
	assert(0);
	return 0;
}

/* freereg - free register p */
static void freereg(p) Symbol p; {
	assert(p->x.regnode);
	p->x.regnode->count = 0;
	freemask[p->x.regnode->regset] |= p->x.regnode->mask;
	debug(rflag, dumpregs("(freeing %s)\n", p->x.name, 0));
}

/* freeregvars - free register variables */
void freeregvars() {
	Symbol p;

	for (p = regvars; p; p = p->x.nextregvar) {
		Regnode r = p->x.regvar->x.regnode;
		usedmask[r->regset] |= r->mask;
		freereg(p->x.regvar);
	}
}

/* gen - drive nodelist from front end through all back-end phases */
Node gen(nodelist) Node nodelist; {
	int i;
	Node p, q = 0;

	curhead = nodelist;
	last = 0;
	for (p = nodelist; p; p = p->link) {
		switch (generic(p->op)) {
		case CALL:
			p->x.sideeffect = 1;
			p->x.iscall = 1;
			p->x.args = q;
			q = 0;
			(*IR->x.docall)(p);
			break;
		case ARG:
			p->x.isarg = 1;
			p->x.args = q;
			q = p;
			(*IR->x.doarg)(p);
			/* fall through */
		case ASGN: case JUMP: case LABEL: case RET:
		case EQ: case GE: case GT: case LE: case LT: case NE:
			assert(p->count == 0);
			p->x.sideeffect = 1;
			break;
		case INDIR:
			p->x.unavailable = 1;
			assert(p->count);
			break;
		case DIV: case MOD: case MUL:
			if (IR->mulops_are_calls && (optype(p->op) == I || optype(p->op) == U))
				break;
			/* else fall through */
		default:
			assert(0);
		}
		(*IR->x.rewrite)(p);
		last = p;
		debug(dflag, fprint(2, "(last=%x)\n", last));
	}
	last = 0;
	linearize(curhead, &curhead, 0);
	for (p = curhead; p; p = p->x.next) {
		assert(p->x.sideeffect || p->count);
		if (p->x.registered == 0) {
			if (p->x.iscall)
				for (q = p->x.args; q; q = q->x.args)
					if (q->syms[RX] && q->syms[RX]->x.regnode)
						freereg(q->syms[RX]);
			ralloc(p);
			if (p->x.isarg && p->syms[RX] && p->syms[RX]->x.regnode)
				p->syms[RX]->x.regnode->count = -1;
			else if (p->x.listed && p->count == 0 && p->syms[RX] && p->syms[RX]->x.regnode && p->syms[RX]->x.regnode->count >= 0)
				freereg(p->syms[RX]);
			last = p;
		} else
			last = 0;
	}
	for (i = 0; i < nregsets; i++) {
		freemask[i] |= tempmask[i];
		tempmask[i] = 0;
	}
	return curhead;
}

/* genascii - emit ascii string str */
void genascii(ascii, byte, len, str) char *ascii, *byte, *str; {
	char *s = str;
	int m, n;

	for (n = 5, m = 9; s < str + len; s++) {
		if (*s == '"' || *s == '\\')
			m += 2;
		else
			m += *s < ' ' || *s >= 0177 ? 4 : 1;
		n += *s < 10 ? 2 : *s < 100 ? 3 : 4;
	}
	s = str;
	if (ascii == 0 || n < m) {
		print("%s %d", byte, (*s++)&0xff);
		for (n = 0; s < str + len; n++)
			if (n > 10) {
				n = 0;
				print("\n%s %d", byte, (*s++)&0xff);
			} else
				print(",%d", (*s++)&0xff);
		outs("\n");
	} else {
		n = 0;
		print("%s \"", ascii);
		for (s = str; s < str + len; s++) {
			if (n >= 64) {
				print("\"\n%s \"", ascii);
				n = 0;
			}
			if (*s == '"' || *s == '\\') {
				print("\\%c", *s);
				n += 2;
			} else if (*s >= ' ' && *s < 0177) {
				*bp++ = *s;
				n += 1;
			} else {
				print("\\%d%d%d", (*s>>6)&3, (*s>>3)&7, *s&7);
				n += 4;
			}
		}
		outs("\"\n");
	}
}

/* genreload - make *pp use reloads instead of r */
static void genreload(pp, temp, ty, r) Node *pp; Symbol r, temp; {
	int i;
	Node p = *pp;

	for (i = 0; i < MAXKIDS; i++)
		if (p->kids[i] && p->kids[i]->syms[RX] == r && p->kids[i]->x.registered) {
			Symbol target = p->kids[i]->x.rtarget;
			p->kids[i] = newnode(INDIR + ty, newnode(ADDRL+P, 0, 0, temp), 0, 0);
			p->kids[i]->count = 1;
			(*IR->x.rewrite)(p->kids[i]);
			if (target)
				rtarget(p, i, target);
			(*IR->x.rewrite)(p);
			linearize(p->kids[i], pp, *pp);
			if (p->kids[i])
				pp = &p->kids[i]->x.next;
		}
}

/* genreloads - make the nodes after dot use reloads instead of r */
static void genreloads(dot, temp, ty, r) Node dot; Symbol r, temp; {
	Node p, *pp;

	if (IR->x.twoop && dot->x.zap0) {
		pp = findxnext(dot);
		genreload(pp, temp, ty, r);
		for (p = *pp; p != dot; p = p->x.next)
			ralloc(*pp);
	}
	for (pp = &dot->x.next; dot = *pp; pp = &dot->x.next)
		genreload(pp, temp, ty, r);
}

/* genspill - generate code to spill r and return the temp used */
static Symbol genspill(r, ty, last) Symbol r; Node *last; {
	Node p, q;
	Symbol s, tmp;
	static struct symbol z;
	unsigned i, savemask[(sizeof freemask)/(sizeof freemask[0])];

	for (i = 0; i < nregsets; i++) {
		savemask[i] = vmask[i];
		vmask[i] &= ~usedmask[i];
	}
	tmp = newtemp(REGISTER, ty);
	for (i = 0; i < nregsets; i++)
		vmask[i] = savemask[i];
	debug(rflag, fprint(2, "(spilling %s to symbol %s=%s)\n", r->x.name, tmp->name, tmp->x.name));
	s = (Symbol) talloc(sizeof *s);
	*s = z;
	s->sclass = REGISTER;
	s->x.name = r->x.name;
	symeaddr(s) = symeaddr(r);
	s->x.regvar = r;
	q = newnode(ADDRL+P, 0, 0, s);
	q = newnode(INDIR + ty, q, 0, 0);
	p = newnode(ADDRL+P, 0, 0, tmp);
	p = newnode(ASGN + ty, p, q, 0);
	p->x.sideeffect = 1;
	(*IR->x.rewrite)(p);
	q = *last;
	linearize(p, last, q);
	for (p = *last; p != q; p = p->x.next)
		ralloc(p);
	return tmp;
}

/* getint - return value of signed integer constant */
int getint(p) Symbol p; {
	switch (ttob(p->type)) {
	case C:		return p->u.c.v.sc;
	case S:		return p->u.c.v.ss;
	default:	return p->u.c.v.i;
	}
}

/* getreg - assign a register from set rs to node p */
static Symbol getreg(rs, p, rmask, count) Symbol rs; Node p; unsigned rmask; {
	Regnode rn;
	Symbol r;

	if (rs->x.regnode->link == 0)
		rmask = -1;
	for (r = rs; r; r = rn->link) {
		rn = r->x.regnode;
		assert(rn);
		if ((rn->mask&~(freemask[rn->regset]&rmask)) == 0) {
			freemask[rn->regset] &= ~rn->mask;
			r->x.regnode->node = p;
			r->x.regnode->count = count;
			return r;
		}
	}
	if (p == 0)  /* register variable */
		return 0;
	r = spillee(rs, p, rmask);
	spill(r->x.regnode->mask, r->x.regnode->regset, p);
	r = getreg(rs, p, rmask, count);
	assert(r);
	return r;
}

/* getregnode - return regnode for register variable or codegen temp */
Regnode getregnode(p) Symbol p; {
	assert(p);
	if (p->x.regvar) {
		assert(!p->x.regnode);
		assert(p->x.regvar->x.regnode);
		return p->x.regvar->x.regnode;
	} else {
		assert(p->x.regnode);
		return p->x.regnode;
	}
}

/* getregset - return index of the register set to which p's been allocated */
int getregset(p) Symbol p; {
	if (p->sclass == REGISTER) {
		assert(p->x.regvar);
		return getregnode(p)->regset;
	} else
		return -1;
}

/* getregvar - assign variable p to a register if possible */
int getregvar(p, reglist) Symbol p, reglist; {
	Symbol reg;

	assert(p && p->type);
	if (reglist && isscalar(p->type) && isregvar(p) && (reg = getreg(reglist, 0, vmask[reglist->x.regnode->regset], -1))) {
		p->x.regvar = reg;
		p->x.name = reg->x.name;
		symeaddr(p) = symeaddr(reg);
		p->x.nextregvar = regvars;
		regvars = p;
		debug(rflag, dumpregs("(allocating %s to symbol %s)\n", p->x.name, p->name));
		if (p->temporary)
			tempmask[reg->x.regnode->regset] |= reg->x.regnode->mask;
		return 1;
	} else {
		p->sclass = AUTO;
		return 0;
	}
}

/* getunsigned - return value of unsigned integer constant */
unsigned getunsigned(p) Symbol p; {
	switch (ttob(p->type)) {
	case C:		return p->u.c.v.uc;
	case S:		return p->u.c.v.us;
	default:	return p->u.c.v.u;
	}
}

/* initfunc - common function initialization */
void initfunc(a, b, c) {
	int i;

	offset = b;
	maxoffset = 0;
	argbuildsize = c;
	ncalls = a;
	regvars = 0;
	for (i = 0; i < nregsets; i++) {
		usedmask[i] = 0;
		freemask[i] = -1;
	}
}

/* linearize - linearize nodelist p */
static void linearize(p, last, next) Node *last, next, p; {
	for (; p; p = p->link)
		if (p->x.sideeffect || p->count > 0) {
			last = lin1(p, last);
			p->x.listed = 1;
		}
	*last = next;
}

/* lin1 - linearize dag p */
static Node *lin1(p, last) Node p, *last; {
	int i;

	if (p->x.linearized)
		return last;
	for (i = 0; i < MAXKIDS; i++)
		if (p->kids[i])
			last = lin1(p->kids[i], last);
	p->x.linearized = 1;
	*last = p;
	debug(rflag, fprint(2, "(listing %x)\n", p));
	return &p->x.next;
}

/* lop - p->syms[i] &= mask */
int lop(p, i, size) Node p; {
	unsigned before = getunsigned(p->syms[i]);
	unsigned after = before&((1<<size) - 1);

	if (before == after)
		return 0;
	else {
		Value v;
		v.u = after;
		p->syms[i] = constant(p->syms[i]->type, v);
		return 1;
	}
}

/* mkactual - make next frame offset */
int mkactual(prealign, size, postalign) {
	int n = roundup(argoffset, prealign);
	argoffset = roundup(n + size, postalign);
	return n;
}

/* mkauto - make next local */
int mkauto(p, align) Symbol p; {
	offset = roundup(offset + p->type->size, align);
	p->x.offset = -offset;
	return -offset;
}

/* mkreg - create register s with given mask, regset, and link */
static Symbol mkreg(s, n, mask, regset, regtype, link) char *s; Symbol link; {
	static struct symbol zs;
	static struct regnode zr;
	Symbol q = (Symbol)alloc(sizeof *q);

	*q = zs;
	q->x.name = string(s);
	symeaddr(q) = atoi(s);
	q->x.regnode = (Regnode)alloc(sizeof *q->x.regnode);
	*q->x.regnode = zr;
	q->x.regnode->regnum = n;
	q->x.regnode->mask = mask;
	q->x.regnode->link = link;
	q->x.regnode->regset = regset;
	q->x.regnode->regtype = regtype;
	q->x.regnode->next = regs;
	regs = q;
	return q;
}

/* mkregs - create registers lo to hi by inc with given mask and type */
Symbol mkregs(fmt, lo, hi, inc, mask, regset, regtype, p) char *fmt; Symbol p; {
	for (; lo*inc <= hi*inc; lo += inc)
		p = mkreg(stringf(fmt, lo), lo, mask << lo, regset, regtype, p);
	return p;
}

/* mvregvar - move register variable */
static void mvregvar(p, mask) Symbol p; unsigned mask; {
	Symbol reg;

	if (reg = getreg(rmap[ttob(p->type)], 0, ~mask, -1)) {
		freereg(p->x.regvar);
		p->x.regvar = reg;
		p->x.name = reg->x.name;
		symeaddr(p) = symeaddr(reg);
		debug(rflag, dumpregs("(moving register variable %s to %s)\n", p->name, p->x.name));
	}
}

/* mvregvars - move register variables to reduce callee saves */
void mvregvars() {
	Symbol p;

	if (ncalls == 0) {
		unsigned i, mask[(sizeof usedmask)/(sizeof usedmask[0])];
		for (i = 0; i < nregsets; i++)
			mask[i] = usedmask[i] | eemask[i];
		for (p = regvars; p; p = p->x.nextregvar) {
			Regnode r = p->x.regvar->x.regnode;
			mask[r->regset] |= r->mask;
		}
		for (p = regvars; p; p = p->x.nextregvar) {
			Regnode r = p->x.regvar->x.regnode;
			if (r->mask&eemask[r->regset])
				mvregvar(p, mask[r->regset]);
		}
	}
	freeregvars();
}

/* ntob - infer type suffix from register set for register p */
static int ntob(p) Symbol p; {
	Regnode r = getregnode(p);
	assert(r->regtype);
	return r->regtype;
}

/* overlaps - do registers x and y overlap? */
static int overlaps(x, y) Symbol x, y; {
	Regnode rx = getregnode(x), ry = getregnode(y);
	return rx->regset == ry->regset && rx->mask&ry->mask;
}

/* parseflags - parse back end flags */
void parseflags(argc, argv) char *argv[]; {
	for (++argv; --argc > 0; ++argv)
		if (strcmp(*argv, "-d") == 0)
			dflag++;
		else if (strcmp(*argv, "-p") == 0 || strcmp(*argv, "-pg") == 0)
			pflag++;
		else if (strcmp(*argv, "-r") == 0)
			rflag++;
		else if (strcmp(*argv, "-k") == 0)
			kflag++;
}

void progend() {}

/* ralloc - assign registers for p */
static void ralloc(p) Node p; {
	Symbol s;
	int i, n;

	assert(p && p->x.registered == 0);
	n = IR->x.twoop && p->x.zap0 ? 1 : MAXKIDS;
	for (i = 0; i < n; i++)
		if (p->kids[i]) {
			assert(p->kids[i]->x.registered);
			s = p->kids[i]->syms[RX];
			if (s == 0) {
				debug(rflag, fprint(2, "(%x->kids[%d]=%x has no register allocated)\n", p, i, p->kids[i]));
				assert(s);
			}
			if (s->x.regnode && s->x.regnode->count >= 0 && --s->x.regnode->count == 0)
				freereg(s);
		}
	s = p->syms[RX];
	if (s && s->x.regnode) {
		p->syms[RX] = getreg(s, p, tmask[s->x.regnode->regset], p->count);
		usedmask[p->syms[RX]->x.regnode->regset] |= p->syms[RX]->x.regnode->mask;
		debug(rflag, dumpregs("(allocating %s to node %x)\n", p->syms[RX]->x.name, (char *) p));
	}
	for (i = n; i < MAXKIDS; i++)
		if (p->kids[i]) {
			assert(p->kids[i]->x.registered);
			s = p->kids[i]->syms[RX];
			assert(s);
			if (s->x.regnode && s->x.regnode->count >= 0 && --s->x.regnode->count == 0)
				freereg(s);
		}
	p->x.registered = 1;
	(*IR->x.final)(p);
}

/* range - does signed k fit in n bits? */
int range(k, n) {
	return k >= -(1<<(n - 1)) && k < (1<<(n - 1));
}

/* regchain - does this binary instruction overwrite its left operand? */
regchain(a) Node a; {
	return a->kids[0] == 0 || a->kids[0]->syms[RX] == a->syms[RX];
}

/* regloc - return "id" for p's register */
unsigned regloc(p) Symbol p; {
	assert(p && p->sclass == REGISTER && p->x.regvar && p->x.regvar->x.regnode);
	return p->x.regvar->x.regnode->regset<<8 | p->x.regvar->x.regnode->regnum;
}
	
/* rmcopy - remove the register-to-register copy in node a? */
int rmcopy(a) Node a; {
	return !isregvar(a->syms[RX]) && !a->x.unavailable;
}

/* rmember - is regnode r in register class s? */
static int rmember(r, s) Regnode r; Symbol s; {
	assert(r && s->x.regnode);
	for (; s; s = s->x.regnode->link)
		if (r->regset == s->x.regnode->regset && r->mask == s->x.regnode->mask)
			return 1;
	return 0;
}

/* rtarget - evaluate p->kids[n] into register r */
void rtarget(p, n, r) Node p; Symbol r; {
	Node q;
	Regnode regnode;
	Symbol s;

	assert(p && r);
	q = p->kids[n];
	assert(q && r);
	regnode = getregnode(r);
	assert(r->x.regvar || regnode->link == 0);
	s = q->syms[RX];
	assert(s);
	if (!isregvar(s) && rmember(regnode, s)) {
		debug(rflag, fprint(2, "(targeting %x to %s)\n", q, r->x.name));
		q->syms[RX] = q->x.rtarget = r;
	} else {
		debug(rflag, fprint(2, "(moving %x to %s)\n", q, r->x.name));
		q->count--;
		p->kids[n] = q = newnode(LOAD + ntob(q->syms[RX]), q, 0, q->syms[0]?q->syms[0]:p->syms[0]);
		q->count++;
		q->syms[RX] = q->x.rtarget = r;
		(*IR->x.rewrite)(q);
	}
}

/* setseg - switch to logical segment n (1..5) */
void setseg(n) {
	assert(n >= 0 && n < sizeof IR->x.segnames/sizeof IR->x.segnames[0]);
	cseg = n;  
	if (IR->x.segnames[n-1])
		print("%s\n", IR->x.segnames[n-1]); 
}

/* spacen - allocate n bytes of space in the current segment */
void spacen(n, prefix) char *prefix; {
	if (cseg != BSS)
		print("%s ", prefix);
	print("%d\n", n);
}

/* spill - spill all busy registers in regset n that overlap mask */
void spill(mask, n, dot) unsigned mask; Node dot; {
	Symbol r;

	if (mask&~freemask[n])
		for (r = regs; r; r = r->x.regnode->next)
			if (n == r->x.regnode->regset && mask&r->x.regnode->mask && r->x.regnode->count)
				spillr(r, dot);
	usedmask[n] |= mask;
}

/* spillee - identify most-distantly-used register in register class r */
static Symbol spillee(r, dot, rmask) Node dot; Symbol r; unsigned rmask; {
	int bestdist = -1;
	Symbol bestreg = 0;

	for (; r; r = r->x.regnode->link)
		if ((r->x.regnode->mask&~rmask) == 0 && r->x.regnode->count >= 0) {
			Node q;
			int dist = 0;
			for (q = dot; q && !uses(q, r); q = q->x.next)
				dist++;
			if (q && dist > bestdist) {  /* no local use => reg vbl */
				bestdist = dist;
				bestreg = r;
			}
		}
	assert(bestreg);
	return bestreg;
}

/* spillr - spill register r */
static void spillr(r, dot) Symbol r; Node dot; {
	int ty = ntob(r);
	if (r->x.regnode->count < 0) {
		Node p = newnode(LOAD+ty,
			newnode(INDIR+ty,
			newnode(ADDRL+P, 0, 0,
			genspill(r, ty, findxnext(dot))), 0, 0), 0, 0);
		p->syms[RX] = r;
		p->x.sideeffect = 1;
		(*IR->x.rewrite)(p);
		linearize(p, &dot->x.next, dot->x.next);
		p->x.registered = 1;
	} else if (dot->x.registered && r == dot->syms[RX]) {
		/* dot can't have set it yet, so no spill is needed */
	} else {
		genreloads(dot, genspill(r, ty, &r->x.regnode->node->x.next), ty, r);
		freereg(r);
	}
}

/* uses - does node p read register r? */
static int uses(p, r) Node p; Symbol r; {
	int i;

	for (i = 0; i < MAXKIDS; i++)
		if (
			p->kids[i] &&
			p->kids[i]->x.registered && 
			overlaps(r, p->kids[i]->syms[RX])
		)
			return 1;
	return 0;
}

unix.superglobalmegacorp.com

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