Charles.Forsyth20080201-190845629f718 years agoHistory
2558 lines · 51.5 KB · C
RawDownload
#include "limbo.h" static Node* putinline(Node*);static void fpcall(Src*, int, Node*, Node*); voidoptabinit(void){	int i; 	for(i = 0; setisbyteinst[i] >= 0; i++)		isbyteinst[setisbyteinst[i]] = 1; 	for(i = 0; setisused[i] >= 0; i++)		isused[setisused[i]] = 1; 	for(i = 0; setsideeffect[i] >= 0; i++)		sideeffect[setsideeffect[i]] = 1; 	opind[Tbyte] = 1;	opind[Tint] = 2;	opind[Tbig] = 3;	opind[Treal] = 4;	opind[Tstring] = 5;	opind[Tfix] = 6; 	opcommute[Oeq] = Oeq;	opcommute[Oneq] = Oneq;	opcommute[Olt] = Ogt;	opcommute[Ogt] = Olt;	opcommute[Ogeq] = Oleq;	opcommute[Oleq] = Ogeq;	opcommute[Oadd] = Oadd;	opcommute[Omul] = Omul;	opcommute[Oxor] = Oxor;	opcommute[Oor] = Oor;	opcommute[Oand] = Oand; 	oprelinvert[Oeq] = Oneq;	oprelinvert[Oneq] = Oeq;	oprelinvert[Olt] = Ogeq;	oprelinvert[Ogt] = Oleq;	oprelinvert[Ogeq] = Olt;	oprelinvert[Oleq] = Ogt; 	isrelop[Oeq] = 1;	isrelop[Oneq] = 1;	isrelop[Olt] = 1;	isrelop[Oleq] = 1;	isrelop[Ogt] = 1;	isrelop[Ogeq] = 1;	isrelop[Oandand] = 1;	isrelop[Ooror] = 1;	isrelop[Onot] = 1; 	precasttab[Tstring][Tbyte] = tint;	precasttab[Tbyte][Tstring] = tint;	precasttab[Treal][Tbyte] = tint;	precasttab[Tbyte][Treal] = tint;	precasttab[Tbig][Tbyte] = tint;	precasttab[Tbyte][Tbig] = tint;	precasttab[Tfix][Tbyte] = tint;	precasttab[Tbyte][Tfix] = tint;	precasttab[Tbig][Tfix] = treal;	precasttab[Tfix][Tbig] = treal;	precasttab[Tstring][Tfix] = treal;	precasttab[Tfix][Tstring] = treal; 	casttab[Tint][Tint] = IMOVW;	casttab[Tbig][Tbig] = IMOVL;	casttab[Treal][Treal] = IMOVF;	casttab[Tbyte][Tbyte] = IMOVB;	casttab[Tstring][Tstring] = IMOVP;	casttab[Tfix][Tfix] = ICVTXX;	/* never same type */ 	casttab[Tint][Tbyte] = ICVTWB;	casttab[Tint][Treal] = ICVTWF;	casttab[Tint][Tstring] = ICVTWC;	casttab[Tint][Tfix] = ICVTXX;	casttab[Tbyte][Tint] = ICVTBW;	casttab[Treal][Tint] = ICVTFW;	casttab[Tstring][Tint] = ICVTCW;	casttab[Tfix][Tint] = ICVTXX; 	casttab[Tint][Tbig] = ICVTWL;	casttab[Treal][Tbig] = ICVTFL;	casttab[Tstring][Tbig] = ICVTCL;	casttab[Tbig][Tint] = ICVTLW;	casttab[Tbig][Treal] = ICVTLF;	casttab[Tbig][Tstring] = ICVTLC; 	casttab[Treal][Tstring] = ICVTFC;	casttab[Tstring][Treal] = ICVTCF; 	casttab[Treal][Tfix] = ICVTFX;	casttab[Tfix][Treal] = ICVTXF; 	casttab[Tstring][Tarray] = ICVTCA;	casttab[Tarray][Tstring] = ICVTAC; 	/*	 * placeholders; fixed in precasttab	 */	casttab[Tbyte][Tstring] = 0xff;	casttab[Tstring][Tbyte] = 0xff;	casttab[Tbyte][Treal] = 0xff;	casttab[Treal][Tbyte] = 0xff;	casttab[Tbyte][Tbig] = 0xff;	casttab[Tbig][Tbyte] = 0xff;	casttab[Tfix][Tbyte] = 0xff;	casttab[Tbyte][Tfix] = 0xff;	casttab[Tfix][Tbig] = 0xff;	casttab[Tbig][Tfix] = 0xff;	casttab[Tfix][Tstring] = 0xff;	casttab[Tstring][Tfix] = 0xff;} /* * global variable and constant initialization checking */intvcom(Decl *ids){	Decl *v;	int ok; 	ok = 1;	for(v = ids; v != nil; v = v->next)		ok &= varcom(v);	for(v = ids; v != nil; v = v->next)		v->init = simplify(v->init);	return ok;} Node*simplify(Node *n){	if(n == nil)		return nil;	if(debug['F'])		print("simplify %n\n", n);	n = efold(rewrite(n));	if(debug['F'])		print("simplified %n\n", n);	return n;} static intisfix(Node *n){	if(n->ty->kind == Tint || n->ty->kind == Tfix){		if(n->op == Ocast)			return n->left->ty->kind == Tint || n->left->ty->kind == Tfix;		return 1;	}	return 0;} /* * rewrite an expression to make it easiser to compile, * or give the correct results */Node*rewrite(Node *n){	Long v;	Type *t;	Decl *d;	Node *nn, *left, *right; 	if(n == nil)		return nil; 	left = n->left;	right = n->right; 	/*	 * rewrites	 */	switch(n->op){	case Oname:		d = n->decl;		if(d->importid != nil){			left = mkbin(Omdot, dupn(1, &n->src, d->eimport), mkdeclname(&n->src, d->importid));			left->ty = n->ty;			return rewrite(left);		}		if((t = n->ty)->kind == Texception){			if(t->cons)				fatal("cons in rewrite Oname");			n = mkbin(Oadd, n, mkconst(&n->src, 2*IBY2WD));			n = mkunary(Oind, n);			n->ty = t;			n->left->ty = n->left->left->ty = tint;			return rewrite(n);		}		break;	case Odas:		n->op = Oas;		return rewrite(n);	case Oneg:		n->left = rewrite(left);		if(n->ty == treal)			break;		left = n->left;		n->right = left;		n->left = mkconst(&n->src, 0);		n->left->ty = n->ty;		n->op = Osub;		break;	case Ocomp:		v = 0;		v = ~v;		n->right = mkconst(&n->src, v);		n->right->ty = n->ty;		n->left = rewrite(left);		n->op = Oxor;		break;	case Oinc:	case Odec:	case Opreinc:	case Opredec:		n->left = rewrite(left);		switch(n->ty->kind){		case Treal:			n->right = mkrconst(&n->src, 1.0);			break;		case Tint:		case Tbig:		case Tbyte:		case Tfix:			n->right = mkconst(&n->src, 1);			n->right->ty = n->ty;			break;		default:			fatal("can't rewrite inc/dec %n", n);			break;		}		if(n->op == Opreinc)			n->op = Oaddas;		else if(n->op == Opredec)			n->op = Osubas;		break;	case Oslice:		if(right->left->op == Onothing)			right->left = mkconst(&right->left->src, 0);		n->left = rewrite(left);		n->right = rewrite(right);		break;	case Oindex:		n->op = Oindx;		n->left = rewrite(left);		n->right = rewrite(right);		n = mkunary(Oind, n);		n->ty = n->left->ty;		n->left->ty = tint;		break;	case Oload:		n->right = mkn(Oname, nil, nil);		n->right->src = n->left->src;		n->right->decl = n->ty->tof->decl;		n->right->ty = n->ty;		n->left = rewrite(left);		break;	case Ocast:		if(left->ty->kind == Texception){			n = rewrite(left);			break;		}		n->op = Ocast;		t = precasttab[left->ty->kind][n->ty->kind];		if(t != nil){			n->left = mkunary(Ocast, left);			n->left->ty = t;			return rewrite(n);		}		n->left = rewrite(left);		break;	case Oraise:		if(left->ty == tstring)			{}		else if(!left->ty->cons)			break;		else if(left->op != Ocall || left->left->ty->kind == Tfn){			left = mkunary(Ocall, left);			left->ty = left->left->ty;		}		n->left = rewrite(left);		break;	case Ocall:		t = left->ty;		if(t->kind == Tref)			t = t->tof;		if(t->kind == Tfn){if(debug['U']) print("call %n\n", left);			if(left->ty->kind == Tref){	/* call by function reference */				n->left = mkunary(Oind, left);				n->left->ty = t;				return rewrite(n);			}			d = nil;			if(left->op == Oname)				d = left->decl;			else if(left->op == Omdot && left->right->op == Odot)				d = left->right->right->decl;			else if(left->op == Omdot || left->op == Odot)				d = left->right->decl;			else if(left->op != Oind)				fatal("cannot deal with call %n in rewrite", n);			if(ispoly(d))				addfnptrs(d, 0);			n->left = rewrite(left);			if(right != nil)				n->right = rewrite(right);			if(d != nil && d->caninline == 1)				n = simplify(putinline(n));			break;		}		switch(n->ty->kind){		case Tref:			n = mkunary(Oref, n);			n->ty = n->left->ty;			n->left->ty = n->left->ty->tof;			n->left->left->ty = n->left->ty;			return rewrite(n);		case Tadt:			n->op = Otuple;			n->right = nil;			if(n->ty->tags != nil){				n->left = nn = mkunary(Oseq, mkconst(&n->src, left->right->decl->tag));				if(right != nil){					nn->right = right;					nn->src.stop = right->src.stop;				}				n->ty = left->right->decl->ty->tof;			}else				n->left = right;			return rewrite(n);		case Tadtpick:			n->op = Otuple;			n->right = nil;			n->left = nn = mkunary(Oseq, mkconst(&n->src, left->right->decl->tag));			if(right != nil){				nn->right = right;				nn->src.stop = right->src.stop;			}			n->ty = left->right->decl->ty->tof;			return rewrite(n);		case Texception:			if(!n->ty->cons)				return n->left;			if(left->op == Omdot){				left->right->ty = left->ty;				left = left->right;			}			n->op = Otuple;			n->right = nil;			n->left = nn = mkunary(Oseq, left->decl->init);			nn->right = mkunary(Oseq, mkconst(&n->src, 0));			nn->right->right = right;			n->ty = mkexbasetype(n->ty);			n = mkunary(Oref, n);			n->ty = internaltype(mktype(&n->src.start, &n->src.stop, Tref, t, nil));			return rewrite(n);		default:			fatal("can't deal with %n in rewrite/Ocall", n);			break;		}		break;	case Omdot:		/*		 * what about side effects from left?		 */		d = right->decl;		switch(d->store){		case Dfn:			n->left = rewrite(left);			if(right->op == Odot){				n->right = dupn(1, &left->src, right->right);				n->right->ty = d->ty;			}			break;		case Dconst:		case Dtag:		case Dtype:			/* handled by fold */			return n;		case Dglobal:			right->op = Oconst;			right->val = d->offset;			right->ty = tint; 			n->left = left = mkunary(Oind, left);			left->ty = tint;			n->op = Oadd;			n = mkunary(Oind, n);			n->ty = n->left->ty;			n->left->ty = tint;			n->left = rewrite(n->left);			return n;		case Darg:			return n;		default:			fatal("can't deal with %n in rewrite/Omdot", n);			break;		}		break;	case Odot:		/*		 * what about side effects from left?		 */		d = right->decl;		switch(d->store){		case Dfn:			if(right->left != nil){				n = mkbin(Omdot, dupn(1, &left->src, right->left), right);				right->left = nil;				n->ty = d->ty;				return rewrite(n);			}			if(left->ty->kind == Tpoly){				n = mkbin(Omdot, mkdeclname(&left->src, d->link), mkdeclname(&left->src, d->link->next));				n->ty = d->ty;				return rewrite(n);			}			n->op = Oname;			n->decl = d;			n->right = nil;			n->left = nil;			return n;		case Dconst:		case Dtag:		case Dtype:			/* handled by fold */			return n;		}		if(istuple(left))			return n;	/* handled by fold */		right->op = Oconst;		right->val = d->offset;		right->ty = tint; 		if(left->ty->kind != Tref){			n->left = mkunary(Oadr, left);			n->left->ty = tint;		}		n->op = Oadd;		n = mkunary(Oind, n);		n->ty = n->left->ty;		n->left->ty = tint;		n->left = rewrite(n->left);		return n;	case Oadr:		left = rewrite(left);		n->left = left;		if(left->op == Oind)			return left->left;		break;	case Otagof:		if(n->decl == nil){			n->op = Oind;			return rewrite(n);		}		return n;	case Omul:	case Odiv:		left = n->left = rewrite(left);		right = n->right = rewrite(right);		if(n->ty->kind == Tfix && isfix(left) && isfix(right)){			if(left->op == Ocast && tequal(left->ty, n->ty))				n->left = left->left;			if(right->op == Ocast && tequal(right->ty, n->ty))				n->right = right->left;		}		break;	case Oself:		if(newfnptr)			return n;		if(selfdecl == nil){			d = selfdecl = mkids(&n->src, enter(strdup(".self"), 5), tany, nil);			installids(Dglobal, d);			d->refs++;		}		nn = mkn(Oload, nil, nil);		nn->src = n->src;		nn->left = mksconst(&n->src, enterstring(strdup("$self"), 5));		nn->ty = impdecl->ty;		usetype(nn->ty);		usetype(nn->ty->tof);		nn = rewrite(nn);		nn->op = Oself;		return nn;	case Ofnptr:		if(n->flags == 0){			/* module */			if(left == nil)				left = mkn(Oself, nil, nil);			return rewrite(left);		}		right->flags = n->flags;

Lines 1–500 of 2558.