1011 lines · 17.6 KB · Brainfuck
RawDownload
	blocks:		int;			# nesting of blocks while generating code	zinst:		Inst;	firstinst:	ref Inst;	lastinst:	ref Inst; include "disoptab.m"; addrmode := array[int Rend] of{	int Rreg =>	Afp,	int Rmreg =>	Amp,	int Roff =>	Aoff,	int Rnoff =>	Anoff,	int Rdesc =>	Adesc,	int Rdescp =>	Adesc,	int Rconst =>	Aimm,	int Radr =>	Afpind,	int Rmadr =>	Ampind,	int Rpc =>	Apc,	int Rldt => Aldt,	* =>		Aerr,}; wtemp:		ref Decl;bigtemp:	ref Decl;ntemp:		int;retnode:	ref Node;nilnode:	ref Node; blockstack:	array of int;blockdep:	int;nblocks:	int;ntoz:	ref Node; #znode:		Node; genstart(){	d := mkdecl(nosrc, Dlocal, tint);	d.sym = enter(".ret", 0);	d.offset = IBY2WD * REGRET; 	retnode = ref 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 = ref zinst;	lastinst = firstinst; 	nilnode = ref znode;	nilnode.op = Oname;	nilnode.addable = Rmreg;	nilnode.decl = nildecl;	nilnode.ty = nildecl.ty; 	blocks = -1;	blockdep = 0;	nblocks = 0;} ## manage nested control flow blocks#pushblock(): int{	if(blockdep >= len blockstack){		bs := array[blockdep + 32] of int;		bs[0:] = blockstack;		blockstack = bs;	}	blockstack[blockdep++] = blocks;	return blocks = nblocks++;} repushblock(b: int){	blockstack[blockdep++] = blocks;	blocks = b;} popblock(){	blocks = blockstack[blockdep -= 1];} tinit(){	wtemp = nil;	bigtemp = nil;} tdecls(): ref Decl{	for(d := wtemp; d != nil; d = d.next){		if(d.tref != 1)			fatal("temporary "+d.sym.name+" has "+string(d.tref-1)+" references");	} 	for(d = bigtemp; d != nil; d = d.next){		if(d.tref != 1)			fatal("temporary "+d.sym.name+" has "+string(d.tref-1)+" references");	} 	return appdecls(wtemp, bigtemp);} talloc(t: ref Type, nok: ref Node): ref Node{	ok, d: ref Decl; 	ok = nil;	if(nok != nil)		ok = nok.decl;	if(ok == nil || ok.tref == 0 || tattr[ok.ty.kind].isbig != tattr[t.kind].isbig || ok.ty.align != t.align)		ok = nil;	n := ref znode;	n.op = Oname;	n.addable = Rreg;	n.ty = t;	if(tattr[t.kind].isbig){		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;		d.sym = enter(".b"+string ntemp++, 0);		d.next = bigtemp;		bigtemp = d;		n.decl = 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;	d.sym = enter(".t"+string ntemp++, 0);	d.next = wtemp;	wtemp = d;	n.decl = d;	return n;} tfree(n: ref Node){	if(n == nil || n.decl == nil)		return;	d := n.decl;	if(d.tref == 0)		return; 	if(d.tref == 1)		fatal("double free of temporary " + d.sym.name);	if (--d.tref == 1)		zcom1(n, nil); 	#	# nil out any pointers so we don't	# hang onto references	### costs ~7% in instruction count#	if(d.tref != 1)#		return;#	if(!tattr[d.ty.kind].isbig){#		if(tattr[d.ty.kind].isptr){	# or tmustzero()#			nilnode.decl.refs++;#			genmove(lastinst.src, Mas, d.ty, nilnode, n);#		}#	}else{#		if(d.desc.nmap != 0){		# tmustzero() is better#			zn := ref znode;#			zn.op = Oname;#			zn.addable = Rmreg;#			zn.decl = globalztup(d.ty);#			zn.ty = d.ty;#			genmove(lastinst.src, Mas, d.ty, zn, n);#		}#	}} tfreelater(n: ref Node){	if(n == nil || n.decl == nil)		return;	d := n.decl;	if(d.tref == 0)		return; 	if(d.tref == 1)		fatal("double free of temporary " + d.sym.name);	if (--d.tref == 1){		nn := mkn(Oname, nil, nil);		*nn = *n;		nn.left = ntoz;		ntoz = nn;		d.tref++;	}} tfreenow(){	nn: ref Node; 	for(n := ntoz; n != nil; n = nn){		nn = n.left;		n.left = nil;		if(n.decl.tref != 2)			fatal(sprint("bad free of temporary %s", n.decl.sym.name));		--n.decl.tref;		zcom1(n, nil);	}	ntoz = nil;} ## realloc a temporary after it's been released#tacquire(n: ref Node): ref Node{	if(n == nil || n.decl == nil)		return n;	d := n.decl;	if(d.tref == 0)		return n;	# if(d.tref != 1)	#	fatal("tacquire ref != 1: "+string d.tref);	d.tref++;	return n;} trelease(n: ref Node){	if(n == nil || n.decl == nil)		return;	d := n.decl;	if(d.tref == 0)		return;	if(d.tref == 1)		fatal("double release of temporary " + d.sym.name);	d.tref--;} mkinst(): ref Inst{	in := lastinst.next;	if(in == nil){		in = ref zinst;		lastinst.next = in;	}	lastinst = in;	in.block = blocks;	if(blocks < 0)		fatal("mkinst no block");	return in;} nextinst(): ref Inst{	in := lastinst.next;	if(in != nil)		return in;	in = ref zinst;	lastinst.next = in;	return in;} ## allocate a node for returning#retalloc(n, nn: ref Node): ref Node{	if(nn.ty == tnone)		return nil;	n = ref znode;	n.op = Oind;	n.addable = Radr;	n.left = dupn(1, n.src, retnode);	n.ty = nn.ty;	return n;} genrawop(src: Src, op: int, s, m, d: ref Node): ref Inst{	in := mkinst();	in.op = op;	in.src = src;	if(s != nil){		in.s = genaddr(s);		in.sm = addrmode[int s.addable];	}	if(m != nil){		in.m = genaddr(m);		in.mm = addrmode[int m.addable];		if(in.mm == Ampind || in.mm == Afpind)			fatal("illegal addressing mode in register "+nodeconv(m));	}	if(d != nil){		in.d = genaddr(d);		in.dm = addrmode[int d.addable];	}	return in;} genop(src: Src, op: int, s, m, d: ref Node): ref Inst{	iop := disoptab[op][opind[d.ty.kind]];	if(iop == 0)		fatal("can't deal with op "+opconv(op)+" on "+nodeconv(s)+" "+nodeconv(m)+" "+nodeconv(d)+" in genop");	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[int s.addable];	}	if(m != nil){		in.m = genaddr(m);		in.mm = addrmode[int m.addable];		if(in.mm == Ampind || in.mm == Afpind)			fatal("illegal addressing mode in register "+nodeconv(m));	}	if(d != nil){		in.d = genaddr(d);		in.dm = addrmode[int d.addable];	}	return in;} genbra(src: Src, op: int, s, m: ref Node): ref Inst{	t := s.ty;	if(t == tany)		t = m.ty;	iop := disoptab[op][opind[t.kind]];	if(iop == 0)		fatal("can't deal with op "+opconv(op)+" on "+nodeconv(s)+" "+nodeconv(m)+" in genbra");	in := mkinst();	in.op = iop;	in.src = src;	if(s != nil){		in.s = genaddr(s);		in.sm = addrmode[int s.addable];	}	if(m != nil){		in.m = genaddr(m);		in.mm = addrmode[int m.addable];		if(in.mm == Ampind || in.mm == Afpind)			fatal("illegal addressing mode in register "+nodeconv(m));	}	return in;} genchan(src: Src, sz: ref Node, mt: ref Type, d: ref Node): ref Inst{	reg: Addr; 	regm := Anone;	reg.decl = nil;	reg.reg = 0;	reg.offset = 0;	op := chantab[mt.kind];	if(op == 0)		fatal("can't deal with op "+string mt.kind+" in genchan"); 	case mt.kind{	Tadt or	Tadtpick or	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;		}	}	in := mkinst();	in.op = op;	in.src = src;	in.s = reg;	in.sm = regm;	if(sz != nil){		in.m = genaddr(sz);		in.mm = addrmode[int sz.addable];	}	if(d != nil){		in.d = genaddr(d);		in.dm = addrmode[int d.addable];	}	return in;} genmove(src: Src, how: int, mt: ref Type, s, d: ref Node): ref Inst{	reg: Addr; 	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 "+string how+" on "+nodeconv(s)+" "+nodeconv(d)+" in genmove"); 	case mt.kind{	Tadt or	Tadtpick or	Ttuple or	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;		}	}	in := mkinst();	in.op = op;	in.src = src;	if(s != nil){		in.s = genaddr(s);		in.sm = addrmode[int s.addable];	}	in.m = reg;	in.mm = regm;	if(d != nil){		in.d = genaddr(d);		in.dm = addrmode[int d.addable];	}	if(s.addable == Rpc)		in.op = IMOVPC;	return in;} patch(b, dst: ref Inst){	n: ref Inst; 	for(; b != nil; b = n){		n = b.branch;		b.branch = dst;	}} getpc(i: ref Inst): int{	if(i.pc == 0 && i != firstinst && (firstinst.op != INOOP || i != firstinst.next)){		do			i = i.next;		while(i != nil && i.pc == 0);		if(i == nil || i.pc == 0)			fatal("bad instruction in getpc");

Lines 1–500 of 1011.