1402 lines · 26.4 KB · Brainfuck
RawDownload
# back end breaks:		array of ref Inst;conts:		array of ref Inst;labels:		array of ref Decl;bcscps:		array of ref Node;labdep:		int;nocont:		ref Inst;nlabel:		int; scp:			int;scps:=		array[MaxScope] of ref Node; curfn:	ref Decl; pushscp(n : ref Node){	if (scp >= MaxScope)		fatal("scope too deep");	scps[scp++] = n;} popscp(){	scp--;} curscp() : ref Node{	if (scp == 0)		return nil;	return scps[scp-1];} zeroscopes(stop : ref Node){	i : int;	cs : ref Node; 	for (i = scp-1; i >= 0; i--) {		cs = scps[i];		if (cs == stop)			break;		zcom(cs.left, nil);	}} zeroallscopes(n: ref Node, nn: array of ref Node){	if(n == nil)		return;	for(; n != nil; n = n.right){		case(n.op){		Oscope =>			zeroallscopes(n.right, nn);			zcom(n.left, nn);			return;		Olabel or		Odo =>			zeroallscopes(n.right, nn);			return;		Oif or		Ofor =>			zeroallscopes(n.right.left, nn);			zeroallscopes(n.right.right, nn);			return;		Oalt or		Ocase or		Opick or		Oexcept =>			for(n = n.right; n != nil; n = n.right)				zeroallscopes(n.left.right, nn);			return;		Oseq =>			zeroallscopes(n.left, nn);			break;		Oexstmt =>			zeroallscopes(n.left, nn);			zeroallscopes(n.right, nn);			return;		* =>			return;		}	}} excs: ref Except; installexc(en: ref Node, p1: ref Inst, p2: ref Inst, zn: ref Node){	e := ref Except;	e.p1 = p1;	e.p2 = p2;	e.c = en.ty.cse;	e.d = en.left.decl;	e.zn = zn;	e.next = excs;	excs = e; 	ne := 0;	c := e.c;	for(i := 0; i < c.nlab; i++){		lab := c.labs[i];		if(lab.start.ty.kind == Texception)			ne++;	}	e.ne = ne;} inlist(d: ref Decl, dd: ref Decl): int{	for( ; dd != nil; dd = dd.next)		if(d == dd)			return 1;	return 0;} excdesc(){	dd, nd: ref Decl; 	for(e := excs; e != nil; e = e.next){		if(e.zn != nil){			dd = nil;			maxo := 0;			for(n := e.zn ; n != nil; n = n.right){				d := n.decl;				d.locals = d.next;				if(!inlist(d, dd)){					d.next = dd;					dd = d;					o := d.offset+d.ty.size;					if(o > maxo)						maxo = o;				}			}			e.desc = gendesc(e.d, align(maxo, MaxAlign), dd);			for(d := dd; d != nil; d = nd){				nd = d.next;				d.next = d.locals;				d.locals = nil;			}			e.zn = nil;		}	}} reve(e: ref Except): ref Except{	l, n: ref Except; 	l = nil;	for( ; e != nil; e = n){		n = e.next;		e.next = l;		l = e;	}	return l;} ckinline0(n: ref Node, d: ref Decl): int{	dd: ref Decl; 	if(n == nil)		return 1;	if(n.op == Oname){		dd = n.decl;		if(d == dd)			return 0;		if(int dd.inline == 1)			return ckinline0(dd.init.right, d);		return 1;	}	return ckinline0(n.left, d) && ckinline0(n.right, d);} ckinline(d: ref Decl){	d.inline = byte ckinline0(d.init.right, d);} modcom(entry: ref Decl){	d, m: ref Decl; 	if(errors)		return; 	if(emitcode != "" || emitstub || emittab != "" || emitsbl != ""){		emit(curscope());		popscope();		return;	} 	#	# scom introduces global variables for case statements	# and unaddressable constants, so it must be done before	# popping the global scope	#	gent = sys->millisec();	nlabel = 0;	maxstack = MaxTemp;	nocont = ref Inst;	genstart(); 	for(i := 0; i < nfns; i++)		if(int fns[i].inline == 1)			ckinline(fns[i]); 	ok := 0;	for(i = 0; i < nfns; i++){		d = fns[i];		if(d.refs > 1 && !(int d.inline == 1 && local(d) && d.iface == nil)){			fns[ok++] = d;			fncom(d);		}	}	fns = fns[:ok];	nfns = ok;	if(blocks != -1)		fatal("blocks not nested correctly");	firstinst = firstinst.next;	if(errors)		return; 	globals := popscope();	checkrefs(globals);	if(errors)		return;	globals = vars(globals);	moddataref(); 	nils := popscope();	m = nil;	for(d = nils; d != nil; d = d.next){		if(debug['n'])			print("nil '%s' ref %d\n", d.sym.name, d.refs);		if(d.refs && m == nil)			m = dupdecl(d);		d.offset = 0;	}	globals = appdecls(m, globals);	globals = namesort(globals);	globals = modglobals(impdecls.d, globals);	vcom(globals);	narrowmods();	ldts: ref Decl;	if(LDT)		(globals, ldts) = resolveldts(globals);	offset := idoffsets(globals, 0, IBY2WD);	if(LDT)		ldtoff := idindices(ldts);	# idoffsets(ldts, 0, IBY2WD);	for(d = nils; d != nil; d = d.next){		if(debug['n'])			print("nil '%s' ref %d\n", d.sym.name, d.refs);		if(d.refs)			d.offset = m.offset;	} 	if(debug['g']){		print("globals:\n");		printdecls(globals);	} 	ndata := 0;	for(d = globals; d != nil; d = d.next)		ndata++;	ndesc := resolvedesc(impdecls.d, offset, globals);	ninst := resolvepcs(firstinst);	modresolve();	if(impdecls.next != nil)		for(dl := impdecls; dl != nil; dl = dl.next)			resolvemod(dl.d);	nlink := resolvemod(impdecl);	gent = sys->millisec() - gent; 	maxstack *= 10;	if(fixss != 0)		maxstack = fixss; 	if(debug['s'])		print("%d instructions\n%d data elements\n%d type descriptors\n%d functions exported\n%d stack size\n",			ninst, ndata, ndesc, nlink, maxstack); 	excs = reve(excs); 	writet = sys->millisec();	if(gendis){		discon(XMAGIC);		hints := 0;		if(mustcompile)			hints |= MUSTCOMPILE;		if(dontcompile)			hints |= DONTCOMPILE;		if(LDT)			hints |= HASLDT;		if(excs != nil)			hints |= HASEXCEPT;		discon(hints);		# runtime hints		discon(maxstack);	# minimum stack extent size		discon(ninst);		discon(offset);		discon(ndesc);		discon(nlink);		disentry(entry);		disinst(firstinst);		disdesc(descriptors);		disvar(offset, globals);		dismod(impdecl);		if(LDT)			disldt(ldtoff, ldts);		if(excs != nil)			disexc(excs);		dispath();	}else{		asminst(firstinst);		asmentry(entry);		asmdesc(descriptors);		asmvar(offset, globals);		asmmod(impdecl);		if(LDT)			asmldt(ldtoff, ldts);		if(excs != nil)			asmexc(excs);		asmpath();	}	writet = sys->millisec() - writet; 	symt = sys->millisec();	if(bsym != nil){		sblmod(impdecl); 		sblfiles();		sblinst(firstinst, ninst);		sblty(adts, nadts);		sblfn(fns, nfns);		sblvar(globals);	}	symt = sys->millisec() - symt; 	firstinst = nil;	lastinst = nil; 	excs = nil;} fncom(decl: ref Decl){	curfn = decl;	if(ispoly(decl))		addfnptrs(decl, 1); 	#	# pick up the function body and compile it	# this code tries to clean up the parse nodes as fast as possible	# function is Ofunc(name, body)	#	decl.pc = nextinst();	tinit();	labdep = 0;	scp = 0;	breaks = array[maxlabdep] of ref Inst;	conts = array[maxlabdep] of ref Inst;	labels = array[maxlabdep] of ref Decl;	bcscps = array[maxlabdep] of ref Node;		n := decl.init;	if(int decl.inline == 1)		decl.init = dupn(0, nosrc, n);	else		decl.init = n.left;	src := n.right.src;	src.start = src.stop - 1;	for(n = n.right; n != nil; n = n.right){		if(n.op != Oseq){			if(n.op == Ocall && trcom(n, nil, 1))				break;			scom(n);			break;		}		if(n.left.op == Ocall && trcom(n.left, n.right, 1)){			n = n.right;			if(n == nil || n.op != Oseq)				break;		}		else			scom(n.left);	}	pushblock();	valued := decl.ty.tof != tnone;	if(valued)		in := genrawop(src, IRAISE, nil, nil, nil);	else		in = genrawop(src, IRET, nil, nil, nil);	popblock();	reach(decl.pc);	if(valued && in.reach != byte 0)		error(src.start, "no return at end of function " + dotconv(decl));	# decl.endpc = lastinst;	if(labdep != 0)		fatal("unbalanced label stack");	breaks = nil;	conts = nil;	labels = nil;	bcscps = nil; 	loc := declsort(appdecls(vars(decl.locals), tdecls())); 	decl.offset = idoffsets(loc, decl.offset, MaxAlign);	for(last := decl.ty.ids; last != nil && last.next != nil; last = last.next)		;	if(last != nil)		last.next = loc;	else		decl.ty.ids = loc; 	if(debug['f']){		print("fn: %s\n", decl.sym.name);		printdecls(decl.ty.ids);	} 	decl.desc = gendesc(decl, decl.offset, decl.ty.ids);	decl.locals = loc;	excdesc();	if(decl.offset > maxstack)		maxstack = decl.offset;	if(optims)		optim(decl.pc, decl);	if(last != nil)		last.next = nil;	else		decl.ty.ids = nil;} ## statement compiler#scom(n: ref Node){	b: int;	p, pp: ref Inst;	left: ref Node; 	for(; n != nil; n = n.right){		case n.op{		Ocondecl or		Otypedecl or		Ovardecl or		Oimport or		Oexdecl =>			return;		Ovardecli =>			break;		Oscope =>			pushscp(n);			scom(n.right);			popscp();			zcom(n.left, nil);			return;		Olabel =>			scom(n.right);			return;		Oif =>			pushblock();			left = simplify(n.left);			if(left.op == Oconst && left.ty == tint){				if(left.c.val != big 0)					scom(n.right.left);				else					scom(n.right.right);				popblock();				return;			}			sumark(left);			pushblock();			p = bcom(left, 1, nil);			tfreenow();			popblock();			scom(n.right.left);			if(n.right.right != nil){				pp = p;				p = genrawop(lastinst.src, IJMP, nil, nil, nil);				patch(pp, nextinst());				scom(n.right.right);			}			patch(p, nextinst());			popblock();			return;		Ofor =>			n.left = left = simplify(n.left);			if(left.op == Oconst && left.ty == tint){				if(left.c.val == big 0)					return;				left.op = Onothing;				left.ty = tnone;				left.decl = nil;			}			pp = nextinst();			b = pushblock();

Lines 1–500 of 1402.