Sigrid Solveig Haflínudóttirmake it build first94efa043 years agoHistory
323 lines · 5.7 KB · C
RawDownload
#include "all.h" enum Imm {	Iother,	Iplo12,	Iphi12,	Iplo24,	Inlo12,	Inhi12,	Inlo24}; static enum Immimm(Con *c, int k, int64_t *pn){	int64_t n;	int i; 	if (c->type != CBits)		return Iother;	n = c->bits.i;	if (k == Kw)		n = (int32_t)n;	i = Iplo12;	if (n < 0) {		i = Inlo12;		n = -n;	}	*pn = n;	if ((n & 0x000fff) == n)		return i;	if ((n & 0xfff000) == n)		return i + 1;	if ((n & 0xffffff) == n)		return i + 2;	return Iother;} intarm64_logimm(uint64_t x, int k){	uint64_t n; 	if (k == Kw)		x = (x & 0xffffffff) | x << 32;	if (x & 1)		x = ~x;	if (x == 0)		return 0;	if (x == 0xaaaaaaaaaaaaaaaa)		return 1;	n = x & 0xf;	if (0x1111111111111111 * n == x)		goto Check;	n = x & 0xff;	if (0x0101010101010101 * n == x)		goto Check;	n = x & 0xffff;	if (0x0001000100010001 * n == x)		goto Check;	n = x & 0xffffffff;	if (0x0000000100000001 * n == x)		goto Check;	n = x;Check:	return (n & (n + (n & -n))) == 0;} static voidfixarg(Ref *pr, int k, int phi, Fn *fn){	char buf[32];	Con *c, cc;	Ref r0, r1, r2, r3;	int s, n; 	r0 = *pr;	switch (rtype(r0)) {	case RCon:		c = &fn->con[r0.val];		if (T.apple		&& c->type == CAddr		&& c->sym.type == SThr) {			r1 = newtmp("isel", Kl, fn);			*pr = r1;			if (c->bits.i) {				r2 = newtmp("isel", Kl, fn);				memset(&cc, 0, sizeof(cc));				cc.type = CBits;				cc.bits.i = c->bits.i;				r3 = newcon(&cc, fn);				emit(Oadd, Kl, r1, r2, r3);				r1 = r2;			}			emit(Ocopy, Kl, r1, TMP(R0), R);			r1 = newtmp("isel", Kl, fn);			r2 = newtmp("isel", Kl, fn);			emit(Ocall, 0, R, r1, CALL(33));			emit(Ocopy, Kl, TMP(R0), r2, R);			emit(Oload, Kl, r1, r2, R);			cc = *c;			cc.bits.i = 0;			r3 = newcon(&cc, fn);			emit(Ocopy, Kl, r2, r3, R);			break;		}		if (KBASE(k) == 0 && phi)			return;		r1 = newtmp("isel", k, fn);		if (KBASE(k) == 0) {			emit(Ocopy, k, r1, r0, R);		} else {			n = stashbits(&c->bits, KWIDE(k) ? 8 : 4);			vgrow(&fn->con, ++fn->ncon);			c = &fn->con[fn->ncon-1];			sprintf(buf, "\"%sfp%d\"", T.asloc, n);			memset(c, 0, sizeof(*c));			c->type = CAddr;			c->sym.id = intern(buf);			r2 = newtmp("isel", Kl, fn);			emit(Oload, k, r1, r2, R);			emit(Ocopy, Kl, r2, CON(c-fn->con), R);		}		*pr = r1;		break;	case RTmp:		s = fn->tmp[r0.val].slot;		if (s == -1)			break;		r1 = newtmp("isel", Kl, fn);		emit(Oaddr, Kl, r1, SLOT(s), R);		*pr = r1;		break;	}} static intselcmp(Ref arg[2], int k, Fn *fn){	Ref r, *iarg;	Con *c;	int swap, cmp, fix;	int64_t n; 	if (KBASE(k) == 1) {		emit(Oafcmp, k, R, arg[0], arg[1]);		iarg = curi->arg;		fixarg(&iarg[0], k, 0, fn);		fixarg(&iarg[1], k, 0, fn);		return 0;	}	swap = rtype(arg[0]) == RCon;	if (swap) {		r = arg[1];		arg[1] = arg[0];		arg[0] = r;	}	fix = 1;	cmp = Oacmp;	r = arg[1];	if (rtype(r) == RCon) {		c = &fn->con[r.val];		switch (imm(c, k, &n)) {		default:			break;		case Iplo12:		case Iphi12:			fix = 0;			break;		case Inlo12:		case Inhi12:			cmp = Oacmn;			r = getcon(n, fn);			fix = 0;			break;		}	}	emit(cmp, k, R, arg[0], r);	iarg = curi->arg;	fixarg(&iarg[0], k, 0, fn);	if (fix)		fixarg(&iarg[1], k, 0, fn);	return swap;} static intcallable(Ref r, Fn *fn){	Con *c; 	if (rtype(r) == RTmp)		return 1;	if (rtype(r) == RCon) {		c = &fn->con[r.val];		if (c->type == CAddr)		if (c->bits.i == 0)			return 1;	}	return 0;} static voidsel(Ins i, Fn *fn){	Ref *iarg;	Ins *i0;	int ck, cc; 	if (INRANGE(i.op, Oalloc, Oalloc1)) {		i0 = curi - 1;		salloc(i.to, i.arg[0], fn);		fixarg(&i0->arg[0], Kl, 0, fn);		return;	}	if (iscmp(i.op, &ck, &cc)) {		emit(Oflag, i.cls, i.to, R, R);		i0 = curi;		if (selcmp(i.arg, ck, fn))			i0->op += cmpop(cc);		else			i0->op += cc;		return;	}	if (i.op == Ocall)	if (callable(i.arg[0], fn)) {		emiti(i);		return;	}	if (i.op != Onop) {		emiti(i);		iarg = curi->arg; /* fixarg() can change curi */		fixarg(&iarg[0], argcls(&i, 0), 0, fn);		fixarg(&iarg[1], argcls(&i, 1), 0, fn);	}} static voidseljmp(Blk *b, Fn *fn){	Ref r;	Ins *i, *ir;	int ck, cc, use; 	if (b->jmp.type == Jret0	|| b->jmp.type == Jjmp	|| b->jmp.type == Jhlt)		return;	assert(b->jmp.type == Jjnz);	r = b->jmp.arg;	use = -1;	b->jmp.arg = R;	ir = 0;	i = &b->ins[b->nins];	while (i > b->ins)		if (req((--i)->to, r)) {			use = fn->tmp[r.val].nuse;			ir = i;			break;		}	if (ir && use == 1	&& iscmp(ir->op, &ck, &cc)) {		if (selcmp(ir->arg, ck, fn))			cc = cmpop(cc);		b->jmp.type = Jjf + cc;		memset(ir, 0, sizeof(*ir));		ir->op = Onop;	}	else {		Ref ref[] = {r, CON_Z};		selcmp(ref, Kw, fn);		b->jmp.type = Jjfine;	}} voidarm64_isel(Fn *fn){	Blk *b, **sb;	Ins *i;	Phi *p;	uint n, al;	int64_t sz; 	/* assign slots to fast allocs */	b = fn->start;	/* specific to NAlign == 3 */ /* or change n=4 and sz /= 4 below */	for (al=Oalloc, n=4; al<=Oalloc1; al++, n*=2)		for (i=b->ins; i<&b->ins[b->nins]; i++)			if (i->op == al) {				if (rtype(i->arg[0]) != RCon)					break;				sz = fn->con[i->arg[0].val].bits.i;				if (sz < 0 || sz >= INT_MAX-15)					err("invalid alloc size %"PRId64, sz);				sz = (sz + n-1) & -n;				sz /= 4;				fn->tmp[i->to.val].slot = fn->slot;				fn->slot += sz;				memset(i, 0, sizeof(*i));				i->op = Onop;			} 	for (b=fn->start; b; b=b->link) {		curi = &insb[NIns];		Blk *blk[3] = {b->s1, b->s2, 0};		for (sb=blk; *sb; sb++)			for (p=(*sb)->phi; p; p=p->link) {				for (n=0; p->blk[n] != b; n++)					assert(n+1 < p->narg);				fixarg(&p->arg[n], p->cls, 1, fn);			}		seljmp(b, fn);		for (i=&b->ins[b->nins]; i!=b->ins;)			sel(*--i, fn);		b->nins = &insb[NIns] - curi;		idup(&b->ins, curi, b->nins);	} 	if (debug['I']) {		fprintf(stderr, "\n> After instruction selection:\n");		printfn(fn, stderr);	}}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t