forsyth20121205-174063a80cc13 years agoHistory
1096 lines · 19.1 KB · C
RawDownload
#include "limbo.h" static	int	addrmode[Rend] ={	/* Rreg */	Afp,	/* Rmreg */	Amp,	/* Roff */	Aoff,	/* Rnoff */	Anoff,	/* Rdesc */	Adesc,	/* Rdescp */	Adesc,	/* Rconst */	Aimm,	/* Ralways */	Aerr,	/* Radr */	Afpind,	/* Rmadr */	Ampind,	/* Rcant */	Aerr,	/* Rpc */	Apc,	/* Rmpc */	Aerr,	/* Rareg */	Aerr,	/* Ramreg */	Aerr,	/* Raadr */	Aerr,	/* Ramadr */	Aerr,	/* Rldt */	Aldt,}; static	Decl	*wtemp;static	Decl	*bigtemp;static	int	ntemp;static	Node	retnode;static	Inst	zinst; 	int	*blockstack;	int	blockdep;	int	nblocks;static	int	lenblockstack;static	Node	*ntoz; static Inst* genfixop(Src *src, int op, Node *s, Node *m, Node *d); voidgenstart(void){	Decl *d; 	d = mkdecl(&nosrc, Dlocal, tint);	d->sym = enter(".ret", 0);	d->offset = IBY2WD * REGRET; 	retnode = znode;	retnode.op = Oname;	retnode.addable = Rreg;	retnode.decl = d;	retnode.ty = tint; 	zinst.op = INOP;	zinst.sm = Anone;	zinst.dm = Anone;	zinst.mm = Anone; 	firstinst = allocmem(sizeof *firstinst);	*firstinst = zinst;	lastinst = firstinst; 	blocks = -1;	blockdep = 0;	nblocks = 0;} /* * manage nested control flow blocks */intpushblock(void){	if(blockdep >= lenblockstack){		lenblockstack = blockdep + 32;		blockstack = reallocmem(blockstack, lenblockstack * sizeof *blockstack);	}	blockstack[blockdep++] = blocks;	return blocks = nblocks++;} voidrepushblock(int b){	blockstack[blockdep++] = blocks;	blocks = b;} voidpopblock(void){	blocks = blockstack[blockdep -= 1];} voidtinit(void){	wtemp = nil;	bigtemp = nil;} Decl*tdecls(void){	Decl *d; 	for(d = wtemp; d != nil; d = d->next){		if(d->tref != 1)			fatal("temporary %s has %d references", d->sym->name, d->tref-1);	} 	for(d = bigtemp; d != nil; d = d->next){		if(d->tref != 1)			fatal("temporary %s has %d references", d->sym->name, d->tref-1);	} 	return appdecls(wtemp, bigtemp);} Node*talloc(Node *n, Type *t, Node *nok){	Decl *d, *ok;	Desc *desc;	char buf[StrSize]; 	ok = nil;	if(nok != nil)		ok = nok->decl;	if(ok == nil || ok->tref == 0 || tattr[ok->ty->kind].big != tattr[t->kind].big || ok->ty->align != t->align)		ok = nil;	*n = znode;	n->op = Oname;	n->addable = Rreg;	n->ty = t;	if(tattr[t->kind].big){		desc = mktdesc(t);		if(ok != nil && ok->desc == desc){			ok->tref++;			ok->refs++;			n->decl = ok;			return n;		}		for(d = bigtemp; d != nil; d = d->next){			if(d->tref == 1 && d->desc == desc && d->ty->align == t->align){				d->tref++;				d->refs++;				n->decl = d;				return n;			}		}		d = mkdecl(&nosrc, Dlocal, t);		d->desc = desc;		d->tref = 2;		d->refs = 1;		n->decl = d;		seprint(buf, buf+sizeof(buf), ".b%d", ntemp++);		d->sym = enter(buf, 0);		d->next = bigtemp;		bigtemp = d;		return n;	}	if(ok != nil	&& tattr[ok->ty->kind].isptr == tattr[t->kind].isptr	&& ok->ty->size == t->size){		ok->tref++;		n->decl = ok;		return n;	}	for(d = wtemp; d != nil; d = d->next){		if(d->tref == 1		&& tattr[d->ty->kind].isptr == tattr[t->kind].isptr		&& d->ty->size == t->size		&& d->ty->align == t->align){			d->tref++;			n->decl = d;			return n;		}	}	d = mkdecl(&nosrc, Dlocal, t);	d->tref = 2;	d->refs = 1;	n->decl = d;	seprint(buf, buf+sizeof(buf), ".t%d", ntemp++);	d->sym = enter(buf, 0);	d->next = wtemp;	wtemp = d;	return n;} voidtfree(Node *n){	if(n == nil || n->decl == nil || n->decl->tref == 0)		return;	if(n->decl->tref == 1)		fatal("double free of temporary %s", n->decl->sym->name);	if (--n->decl->tref == 1)		zcom1(n, nil);} voidtfreelater(Node *n){	if(n == nil || n->decl == nil || n->decl->tref == 0)		return;	if(n->decl->tref == 1)		fatal("double free of temporary %s", n->decl->sym->name);	if(--n->decl->tref == 1){		Node *nn = mkn(Oname, nil, nil); 		*nn = *n;		nn->left = ntoz;		ntoz = nn;		n->decl->tref++;	}} voidtfreenow(){	Node *n, *nn; 	for(n = ntoz; n != nil; n = nn){		nn = n->left;		n->left = nil;		if(n->decl->tref != 2)			fatal("bad free of temporary %s", n->decl->sym->name);		--n->decl->tref;		zcom1(n, nil);	}	ntoz = nil;} /* * realloc a temporary after it's been freed */Node*tacquire(Node *n){	if(n == nil || n->decl == nil || n->decl->tref == 0)		return n;/*	if(n->decl->tref != 1)		fatal("tacquire ref != 1: %d", n->decl->tref);*/	n->decl->tref++;	return n;} voidtrelease(Node *n){	if(n == nil || n->decl == nil || n->decl->tref == 0)		return;	if(n->decl->tref == 1)		fatal("double release of temporary %s", n->decl->sym->name);	n->decl->tref--;} Inst*mkinst(void){	Inst *in; 	in = lastinst->next;	if(in == nil){		in = allocmem(sizeof *in);		*in = zinst;		lastinst->next = in;	}	lastinst = in;	in->block = blocks;	if(blocks < 0)		fatal("mkinst no block");	return in;} Inst*nextinst(void){	Inst *in; 	in = lastinst->next;	if(in != nil)		return in;	in = allocmem(sizeof(*in));	*in = zinst;	lastinst->next = in;	return in;} /* * allocate a node for returning */Node*retalloc(Node *n, Node *nn){	if(nn->ty == tnone)		return nil;	*n = znode;	n->op = Oind;	n->addable = Radr;	n->left = dupn(1, &n->src, &retnode);	n->ty = nn->ty;	return n;} Inst*genrawop(Src *src, int op, Node *s, Node *m, Node *d){	Inst *in; 	in = mkinst();	in->op = op;	in->src = *src;if(in->sm != Anone || in->mm != Anone || in->dm != Anone)fatal("bogus mkinst in genrawop: %I\n", in);	if(s != nil){		in->s = genaddr(s);		in->sm = addrmode[s->addable];	}	if(m != nil){		in->m = genaddr(m);		in->mm = addrmode[m->addable];		if(in->mm == Ampind || in->mm == Afpind)			fatal("illegal addressing mode in register %n", m);	}	if(d != nil){		in->d = genaddr(d);		in->dm = addrmode[d->addable];	}	return in;} Inst*genop(Src *src, int op, Node *s, Node *m, Node *d){	Inst *in;	int iop; 	iop = disoptab[op][opind[d->ty->kind]];	if(iop == 0)		fatal("can't deal with op %s on %n %n %n in genop", opname[op], s, m, d);	if(iop == IMULX || iop == IDIVX)		return genfixop(src, iop, s, m, d);	in = mkinst();	in->op = iop;	in->src = *src;	if(s != nil){		in->s = genaddr(s);		in->sm = addrmode[s->addable];	}	if(m != nil){		in->m = genaddr(m);		in->mm = addrmode[m->addable];		if(in->mm == Ampind || in->mm == Afpind)			fatal("illegal addressing mode in register %n", m);	}	if(d != nil){		in->d = genaddr(d);		in->dm = addrmode[d->addable];	}	return in;} Inst*genbra(Src *src, int op, Node *s, Node *m){	Type *t;	Inst *in;	int iop; 	t = s->ty;	if(t == tany)		t = m->ty;	iop = disoptab[op][opind[t->kind]];	if(iop == 0)		fatal("can't deal with op %s on %n %n in genbra", opname[op], s, m);	in = mkinst();	in->op = iop;	in->src = *src;	if(s != nil){		in->s = genaddr(s);		in->sm = addrmode[s->addable];	}	if(m != nil){		in->m = genaddr(m);		in->mm = addrmode[m->addable];		if(in->mm == Ampind || in->mm == Afpind)			fatal("illegal addressing mode in register %n", m);	}	return in;} Inst*genchan(Src *src, Node *sz, Type *mt, Node *d){	Inst *in;	Desc *td;	Addr reg;	int op, regm; 	regm = Anone;	reg.decl = nil;	reg.reg = 0;	reg.offset = 0;	op = chantab[mt->kind];	if(op == 0)		fatal("can't deal with op %d in genchan", mt->kind); 	switch(mt->kind){	case Tadt:	case Tadtpick:	case Ttuple:		td = mktdesc(mt);		if(td->nmap != 0){			op++;		/* sleazy */			usedesc(td);			regm = Adesc;			reg.decl = mt->decl;		}else{			regm = Aimm;			reg.offset = mt->size;		}		break;	}	in = mkinst();	in->op = op;	in->src = *src;	in->s = reg;	in->sm = regm;	if(sz != nil){		in->m = genaddr(sz);		in->mm = addrmode[sz->addable];	}	if(d != nil){		in->d = genaddr(d);		in->dm = addrmode[d->addable];	}	return in;} Inst*genmove(Src *src, int how, Type *mt, Node *s, Node *d){	Inst *in;	Desc *td;	Addr reg;	int op, regm; 	regm = Anone;	reg.decl = nil;	reg.reg = 0;	reg.offset = 0;	op = movetab[how][mt->kind];	if(op == 0)		fatal("can't deal with op %d on %n %n in genmove", how, s, d); 	switch(mt->kind){	case Tadt:	case Tadtpick:	case Ttuple:	case Texception:		if(mt->size == 0 && how == Mas)			return nil;		td = mktdesc(mt);		if(td->nmap != 0){			op++;		/* sleazy */			usedesc(td);			regm = Adesc;			reg.decl = mt->decl;		}else{			regm = Aimm;			reg.offset = mt->size;		}		break;	}	in = mkinst();	in->op = op;	in->src = *src;	if(s != nil){		in->s = genaddr(s);		in->sm = addrmode[s->addable];	}	in->m = reg;	in->mm = regm;	if(d != nil){		in->d = genaddr(d);		in->dm = addrmode[d->addable];	}	if(s->addable == Rpc)		in->op = IMOVPC;	return in;} voidpatch(Inst *b, Inst *dst){	Inst *n;

Lines 1–500 of 1096.