Charles.Forsyth20080201-1852e3244db18 years agoHistory
1495 lines · 27.9 KB · C
RawDownload
#include "limbo.h" static	Inst	**breaks;static	Inst	**conts;static	Decl	**labels;static	Node **bcscps;static	int	labdep;static	Inst	nocont; static	int scp;static	Node *scps[MaxScope]; static	int trcom(Node*, Node*, int); static voidpushscp(Node *n){	if (scp >= MaxScope)		fatal("scope too deep");	scps[scp++] = n;} static voidpopscp(void){	scp--;} static Node *curscp(void){	if (scp == 0)		return nil;	return scps[scp-1];} static voidzeroscopes(Node *stop){	int i;	Node *cs; 	for (i = scp-1; i >= 0; i--) {		cs = scps[i];		if (cs == stop)			break;		zcom(cs->left, nil);	}} static voidzeroallscopes(Node *n, Node **nn){	if(n == nil)		return;	for(; n != nil; n = n->right){		switch(n->op){		case Oscope:			zeroallscopes(n->right, nn);			zcom(n->left, nn);			return;		case Olabel:		case Odo:			zeroallscopes(n->right, nn);			return;		case Oif:		case Ofor:			zeroallscopes(n->right->left, nn);			zeroallscopes(n->right->right, nn);			return;		case Oalt:		case Ocase:		case Opick:		case Oexcept:			for(n = n->right; n != nil; n = n->right)				zeroallscopes(n->left->right, nn);			return;		case Oseq:			zeroallscopes(n->left, nn);			break;		case Oexstmt:			zeroallscopes(n->left, nn);			zeroallscopes(n->right, nn);			return;		default:			return;		}	}} static Except *excs; static voidinstallexc(Node *en, Inst *p1, Inst *p2, Node *zn){	int i, ne;	Except *e;	Case *c;	Label *lab; 	e = allocmem(sizeof(Except));	e->p1 = p1;	e->p2 = p2;	e->c = en->ty->cse;	e->d = en->left->decl;	e->zn = zn;	e->desc = nil;	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;} static intinlist(Decl *d, Decl *dd){	for( ; dd != nil; dd = dd->next)		if(d == dd)			return 1;	return 0;} static voidexcdesc(void){	ulong o, maxo;	Except *e;	Node *n;	Decl *d, *dd, *nd; 	for(e = excs; e != nil; e = e->next){		if(e->zn != nil){			/* set up a decl list for gendesc */			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;		}	}} static Except*reve(Except *e){	Except *l, *n; 	l = nil;	for( ; e != nil; e = n){		n = e->next;		e->next = l;		l = e;	}	return l;} static intckinline0(Node *n, Decl *d){	Decl *dd; 	if(n == nil)		return 1;	if(n->op == Oname){		dd = n->decl;		if(d == dd)			return 0;		if(dd->caninline == 1)			return ckinline0(dd->init->right, d);		return 1;	}	return ckinline0(n->left, d) && ckinline0(n->right, d);} static voidckinline(Decl *d){	d->caninline = ckinline0(d->init->right, d);}		voidmodcom(Decl *entry){	Decl *globals, *m, *nils, *d, *ldts;	long ninst, ndata, ndesc, nlink, offset, ldtoff;	int ok, i, hints;	Dlist *dl; 	if(errors)		return; 	if(emitcode || emitstub || emittab != nil){		emit(curscope());		popscope();		return;	} 	/*	 * scom introduces global variables for case statements	 * and unaddressable constants, so it must be done before	 * popping the global scope	 */	nlabel = 0;	maxstack = MaxTemp;	genstart(); 	for(i = 0; i < nfns; i++)		if(fns[i]->caninline == 1)			ckinline(fns[i]); 	ok = 0;	for(i = 0; i < nfns; i++){		d = fns[i];if(debug['v']) print("fncom: %s %d %p\n", d->sym->name, d->refs, d);		if(d->refs > 1 && !(d->caninline == 1 && local(d) && d->iface == nil)){			fns[ok++] = d;			fncom(d);		}	}	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 = nil;	if(LDT)		globals = resolveldts(globals, &ldts);	offset = idoffsets(globals, 0, IBY2WD);	if(LDT)		ldtoff = idindices(ldts);	/* ldtoff = 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); 	maxstack *= 10;	if(fixss != 0)		maxstack = fixss; 	if(debug['s'])		print("%ld instructions\n%ld data elements\n%ld type descriptors\n%ld functions exported\n%ld stack size\n",			ninst, ndata, ndesc, nlink, maxstack); 	excs = reve(excs); 	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();	}	if(bsym != nil){		sblmod(impdecl); 		sblfiles();		sblinst(firstinst, ninst);		sblty(adts, nadts);		sblfn(fns, nfns);		sblvar(globals);	} 	firstinst = nil;	lastinst = nil; 	excs = nil;} voidfncom(Decl *decl){	Src src;	Node *n;	Decl *loc, *last;	Inst *in;	int valued; 	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 = allocmem(maxlabdep * sizeof breaks[0]);	conts = allocmem(maxlabdep * sizeof conts[0]);	labels = allocmem(maxlabdep * sizeof labels[0]);	bcscps = allocmem(maxlabdep * sizeof bcscps[0]);	n = decl->init;	if(decl->caninline == 1)		decl->init = dupn(0, nil, n);	else		decl->init = n->left;	src = n->right->src;	src.start.line = src.stop.line;	src.start.pos = src.stop.pos - 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;	in = genrawop(&src, valued? IRAISE: IRET, nil, nil, nil);	popblock();	reach(decl->pc);	if(valued && in->reach)		error(src.start, "no return at end of function %D", decl);	/* decl->endpc = lastinst; */	if(labdep != 0)		fatal("unbalanced label stack");	free(breaks);	free(conts);	free(labels);	free(bcscps); 	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 */voidscom(Node *n){	Inst *p, *pp, *p1, *p2, *p3;	Node tret, *left, *zn; 	for(; n != nil; n = n->right){		switch(n->op){		case Ocondecl:		case Otypedecl:		case Ovardecl:		case Oimport:		case Oexdecl:			return;		case Ovardecli:			break;		case Oscope:			pushscp(n);			scom(n->right);			popscp();			zcom(n->left, nil);			return;		case Olabel:			scom(n->right);			return;		case Oif:			pushblock();			left = simplify(n->left);			if(left->op == Oconst && left->ty == tint){				if(left->val != 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){

Lines 1–500 of 1495.