henesyinit from p9fce6d0435 years agoHistory
1779 lines · 27.9 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <bio.h>#include <ctype.h>#define Extern extern#include "parl.h"#include "globl.h" voidgendata(Node *n){	Type *t;	Inst *i;	ulong s; 	if(n == ZeroN)		return; 	switch(n->type) {	default:		gendata(n->left);		gendata(n->right);		break; 	case OAGDECL:	case OUNDECL:	case OADTDECL:	case OSETDECL:	case OFUNC:		break; 	case ONAME:		switch(n->t->class) {		case Internal:		case Global:			iline = n->srcline;			t = n->t;			if(n->init)				doinit(n, t, n->init, 0); 			s = t->size;			if(s == 0)				break;			if(s & (Align_data-1))				s += Align_data-(s&(Align_data-1)); 			i = ai();			i->op = AGLOBL;			mkaddr(con(s), &i->dst, 0);			mkaddr(n, &i->src1, 0);			ilink(i);			break;		}		break;	}} /* Load/store instructions by type 		TXXX  	TINT	TUINT	TSINT	TSUINT	TCHAR  TFLOAT		TIND	TCHAN	TARY	TAGG	TUNI	TFUNC	TVOID*/int ostore[] ={ AGOK, 	AMOVL, 	AMOVL, 	AMOVW, 	AMOVW, 	AMOVB, 	AFMOVDP,		AMOVL,  AMOVL,  AGOK,  	AGOK,  	AGOK,  	AGOK,  	AGOK }; int oload[] = { AGOK, 	AMOVL, 	AMOVL, 	AMOVWLSX,AMOVWLZX,AMOVBLZX,AFMOVD,		AMOVL,	AMOVL,	AGOK,  	AGOK,  	AGOK,  	AGOK,  	AGOK }; voidload(Node *from, Node *to){	Node n1;	int op; 	op = from->t->type;	switch(op) {	case TFLOAT:		instruction(oload[op], from, to);		break;	default:		reg(&n1, from->t, to);		instruction(oload[op], from, &n1);		assign(&n1, to);		regfree(&n1);	}} voidstore(Node *from, Node *to){	Node n1, *tmp;	int op, t; 	op = ostore[to->t->type]; 	t = from->t->type;	switch(t) {	case TFLOAT:		if(to->t->type == TFLOAT) {			instruction(op, from, to);			break;		}		tmp = stknode(builtype[TINT]);		instruction(AFMOVLP, from, tmp);		assign(tmp, to);		break;	default:		if(vconst(from) == 0) {			instruction(op, from, to);			return;		}				if(t == to->t->type)			reg(&n1, to->t, from);		else			reg(&n1, to->t, ZeroN); 		assign(from, &n1);		instruction(op, &n1, to);		regfree(&n1);	}} /* * Compile code for moves */voidassign(Node *src, Node *dst){	Node *tmp;	int op, dt;	Inst *nofix; 	if(opt('a'))		print("assign: %N = %N\n", dst, src);  	if(dst == ZeroN)		return; 	switch(src->type) {	case ONAME:	case OINDREG:	case OIND:		load(src, dst);		return;	} 	switch(dst->type) {	case ONAME:	case OINDREG:	case OIND:		store(src, dst);		return;	} 	/* delete register/register nop moves */	if(src->type == OREGISTER)	if(dst->type == OREGISTER)	if(dst->reg == src->reg)	if(dst->type == src->type)		return; 	op = AGOK;	dt = dst->t->type;	switch(src->t->type) {	case TINT:	case TUINT:	case TIND:	case TCHANNEL:		switch(dt) {		case TINT:		case TUINT:		case TCHAR:		case TSUINT:		case TSINT:		case TIND:		case TCHANNEL:			op = AMOVL;			break; 		case TFLOAT:			tmp = stknode(builtype[TINT]);			assign(src, tmp);			instruction(AFMOVL, tmp, F0);			if(src->t->type != TUINT)				return;			instruction(ACMPL, src, con(0));			instruction(AJGE, ZeroN, ZeroN);			nofix = ipc;			instruction(AFADDD, conf(4294967296.), F0);			label(nofix, ipc->pc+1);			return;		}		break; 	case TSUINT:		switch(dt) {		case TINT:		case TUINT:		case TIND:			op = AMOVWLZX;			break; 		case TSUINT:		case TCHAR:		case TSINT:			op = AMOVL;			break; 		case TFLOAT:			tmp = stknode(builtype[TINT]);			assign(src, tmp);			instruction(AFMOVL, tmp, F0);			return;		}		break; 	case TSINT:		switch(dt) {		case TINT:		case TUINT:		case TIND:			op = AMOVW;			break; 		case TSUINT:		case TCHAR:		case TSINT:			op = AMOVL;			break; 		case TFLOAT:			tmp = stknode(builtype[TINT]);			assign(src, tmp);			instruction(AFMOVL, tmp, F0);			return;		}		break; 	case TFLOAT:		switch(dt) {		case TINT:		case TUINT:		case TIND:		case TCHAR:		case TSINT:		case TSUINT:			tmp = stknode(builtype[TINT]);			instruction(AFMOVLP, src, tmp);			assign(tmp, dst);			return; 		case TFLOAT:			op = AFMOVD;			break;		}		break;	case TCHAR:		switch(dt) {		case TINT:		case TUINT:		case TIND:			op = AMOVBLZX;			break; 		case TSUINT:		case TSINT:		case TCHAR:			op = AMOVL;			break; 		case TFLOAT:			tmp = stknode(builtype[TINT]);			assign(src, tmp);			instruction(AFMOVL, tmp, F0);			return;		}		break;	}	instruction(op, src, dst);} /* * This routine makes anything addressable */voidgenaddr(Node *expr, Node *dst){	Node n, *tmp; 	if(opt('g')) {		print("genaddr:\n");		ptree(expr, 0);	} 	switch(expr->type) {	case OIND:		genexp(expr->left, dst);		return;	default:		if(!isaddr(expr)) {			tmp = stknode(expr->t);			n.type = OASGN;			n.t = tmp->t;			n.left = tmp;			n.right = expr;			n.islval = 0;			genexp(&n, ZeroN);			expr = tmp;		}		switch(dst->type) {		case OINDREG:		case OREGISTER:			instruction(ALEAL, expr, dst);			break;		default:			reg(&n, builtype[TIND], ZeroN);			instruction(ALEAL, expr, &n);			assign(&n, dst);			regfree(&n);			break;		}	}} /*  * generate an l-value into a register */voidrgenaddr(Node *t, Node *rval, Node *lval){	Node *r;	ulong v; 	*t = *rval;	t->t = builtype[TIND];	reg(t, t->t, lval);	if(rval->type == OIND) {		r = rval->left;		while(r->type == OADD)			r = r->right;		if(immed(r)) {			v = r->ival;			r->ival = 0;			genaddr(rval, t);			t->ival += v;			r->ival = v;			t->type = OINDREG;			t->t = rval->t;			return;		}	}	genaddr(rval, t);	t->type = OINDREG;	t->t = rval->t;} voidtoaddr(Node *l, Node *dst){	if(isaddr(l)) {		*dst = *l;		return;	} 	rgenaddr(dst, l, ZeroN);} /* * pre and post increment generation */voidpostop(Node *rval, Node *lval){	Node *l, *nconst, n1, nop; 	l = rval->left;	nconst = con(1);	if(l->t->type == TIND)		nconst->ival = l->t->next->size; 	if(rval->type == OPDEC)		nconst->ival = -nconst->ival; 	toaddr(l, &n1);	nop.type = OADD;	nop.t = builtype[TINT];	assign(&n1, lval);	codmop(&nop, nconst, &n1, &n1);	if(!isaddr(l))		regfree(&n1);} voidpreop(Node *rval, Node *lval){	Node *l, *nconst, n1, nop; 	l = rval->left;	nconst = con(1);	if(l->t->type == TIND)		nconst->ival = l->t->next->size; 	if(rval->type == OEDEC)		nconst->ival = -nconst->ival; 	toaddr(l, &n1);	nop.type = OADD;	nop.t = builtype[TINT];	codmop(&nop, nconst, &n1, &n1);	assign(&n1, lval);	if(!isaddr(l))		regfree(&n1);} voiddocall(Node *n){	Node *rsp; 	if(atv == ZeroN) {		instruction(ACALL, ZeroN, n);		return;	} 	/*	 * if calling through an activation, link	 * to the new stack	 */	ratv.ival = atv->atvsafe;	rsp = regn(RegSP);	instruction(AMOVL, rsp, &ratv);	ratv.type = OREGISTER;	assign(&ratv, rsp);	instruction(ACALL, ZeroN, n);	rsp->type = OINDREG;	rsp->ival = atv->atvsafe;	instruction(AMOVL, rsp, regn(RegSP));	regfree(&ratv);} /* * make reg free so we can use it as an implied register for things * like IDIV and SALL */intneed(int reg, Node *rnod, Node *rval, Node *lval){	int ref;	Node *safe, *r, *l, n; 	l = rval->left;	r = rval->right; 	if(needreg(reg, rnod, lval) == 0)		return 0; 	safe = stknode(builtype[TINT]);	assign(rnod, safe);	ref = regsave(reg);	/*	 * If the destination is the safe register generate an	 * assign into the safe stack location and let the optimiser	 * figure the redundant moves	 */	if(l->type == OREGISTER && l->reg == reg) {		n = *rval;		n.left = safe;		genexp(&n, lval);	}	else	if(r->type == OREGISTER && r->reg == reg) {		n = *rval;		n.right = safe;		genexp(&n, lval);	}	else		genexp(rval, lval);	assign(safe, regn(reg));	regrest(reg, ref);	return 1;} voidbecome(Node *rval){	Node nl;	Node *l, *r, *ns, *tmp; 	tmp = rval->left;	r = tmp->right;	l = tmp->left; 	if(opt('b')) {		print("BECOME:\n");		ptree(rval, 0);	} 	tmp = ZeroN;	if(!isaddr(l)) {

Lines 1–500 of 1779.