henesyinit from p9fce6d0435 years agoHistory
1543 lines · 24.2 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, AMOVW, AMOVW, AMOVH, AMOVH, AMOVB, AMOVD, AMOVW, 		AMOVW, AGOK,  AGOK,  AGOK,  AGOK,  AGOK }; int oload[] = { AGOK, AMOVW, AMOVW, AMOVH, AMOVHU,AMOVBU,AMOVD, AMOVW,		AMOVW,AGOK,  AGOK,  AGOK,  AGOK,  AGOK }; voidload(Node *from, Node *to){	Node n1;	int op; 	op = oload[from->t->type];	reg(&n1, from->t, to);	instruction(op, from, ZeroN, &n1);	assign(&n1, to);	regfree(&n1);} voidstore(Node *from, Node *to){	Node n1;	int op, t; 	op = ostore[to->t->type]; 	t = from->t->type; 	if(t != TFLOAT)	if(vconst(from) == 0) {		instruction(op, from, ZeroN, to);		return;	}			if(t == to->t->type)		reg(&n1, to->t, from);	else		reg(&n1, to->t, ZeroN); 	assign(from, &n1);	instruction(op, &n1, ZeroN, to);	regfree(&n1);} /* * Compile code for moves */voidassign(Node *src, Node *dst){	Node n1;	int op, dt; 	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 = AMOVW;			break; 		case TFLOAT:			instruction(AMOVW, src, ZeroN, dst);			instruction(AMOVWD, dst, ZeroN, dst);			return;		}		break; 	case TSUINT:		switch(dt) {		case TINT:		case TUINT:		case TIND:			op = AMOVHU;			break; 		case TSUINT:		case TCHAR:		case TSINT:			op = AMOVW;			break; 		case TFLOAT:			reg(&n1, src->t, ZeroN);			instruction(AMOVHU, src, ZeroN, &n1);			instruction(AMOVW, &n1, ZeroN, dst);			instruction(AMOVWD, dst, ZeroN, dst);			regfree(&n1);			return;		}		break; 	case TSINT:		switch(dt) {		case TINT:		case TUINT:		case TIND:			op = AMOVH;			break; 		case TSUINT:		case TCHAR:		case TSINT:			op = AMOVW;			break; 		case TFLOAT:			reg(&n1, src->t, ZeroN);			instruction(AMOVH, src, ZeroN, &n1);			instruction(AMOVW, &n1, ZeroN, dst);			instruction(AMOVWD, dst, ZeroN, dst);			regfree(&n1);			return;		}		break; 	case TFLOAT:		switch(dt) {		case TINT:		case TUINT:		case TIND:			instruction(AMOVDW, src, ZeroN, src);			instruction(AMOVW, src, ZeroN, dst);			return; 		case TCHAR:			reg(&n1, dst->t, ZeroN);			instruction(AMOVDW, src, ZeroN, src);			instruction(AMOVW, src, ZeroN, &n1);			instruction(AMOVBU, &n1, ZeroN, dst);			regfree(&n1);			return; 		case TSINT:			reg(&n1, dst->t, ZeroN);			instruction(AMOVDW, src, ZeroN, src);			instruction(AMOVW, src, ZeroN, &n1);			instruction(AMOVH, &n1, ZeroN, dst);			regfree(&n1);			return; 		case TSUINT:			reg(&n1, dst->t, ZeroN);			instruction(AMOVDW, src, ZeroN, src);			instruction(AMOVW, src, ZeroN, &n1);			instruction(AMOVHU, &n1, ZeroN, dst);			regfree(&n1);			return; 		case TFLOAT:			op = AMOVD;			break;		}		break;	case TCHAR:		switch(dt) {		case TINT:		case TUINT:		case TIND:			op = AMOVBU;			break; 		case TSUINT:		case TSINT:		case TCHAR:			op = AMOVW;			break; 		case TFLOAT:			reg(&n1, src->t, ZeroN);			instruction(AMOVBU, src, ZeroN, &n1);			instruction(AMOVW, &n1, ZeroN, dst);			instruction(AMOVWD, dst, ZeroN, dst);			regfree(&n1);			return;		}		break;	}	instruction(op, src, ZeroN, dst);} /* * Generate the address of an expression */voidgenaddr(Node *expr, Node *dst){	Node n, *tmp; 	if(opt('g'))		print("genaddr: %N\n", expr); 	if(expr->type == OIND) {		genexp(expr->left, dst);		return;	} 	n.srcline = expr->srcline; 	if(isaddr(expr) == 0) {		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;	}	n = *expr;	reg(&n, builtype[TIND], dst);	n.type = OADDR;	n.left = expr;	n.right = ZeroN;	n.t = builtype[TIND];	assign(&n, dst);	regfree(&n);} /*  * 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;} /* * pre and post increment generation */voidpostop(Node *rval, Node *lval){	Node *l, *nconst;	Node n1, n2, n3, n4; 	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; 	if(l->islval < Sucompute)		rgenaddr(&n2, l, ZeroN);	else		n2 = *l; 	n3.type = OADD;	n3.t = builtype[TINT]; 	/* Easy if we dont need the value after the inc */	if(lval == ZeroN) {		reg(&n1, l->t, lval);		assign(&n2, &n1); 		codmop(&n3, nconst, &n1, &n1); 		assign(&n1, &n2);		goto out;	} 	reg(&n4, l->t, lval);	assign(&n2, &n4);	reg(&n1, l->t, ZeroN);	/* Thank RISC for three address ! */	codmop(&n3, nconst, &n4, &n1);	assign(&n1, &n2); 	regfree(&n4);out:	regfree(&n1);	if(l->islval < Sucompute)		regfree(&n2);} voidpreop(Node *rval, Node *lval){	Node n1, n2, n3;	Node *l, *nconst; 	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; 	if(l->islval < Sucompute)		rgenaddr(&n2, l, ZeroN);	else		n2 = *l; 	reg(&n1, l->t, lval);	assign(&n2, &n1); 	n3.type = OADD;	n3.t = builtype[TINT];	codmop(&n3, nconst, &n1, &n1); 	assign(&n1, &n2); 	regfree(&n1);	if(l->islval < Sucompute)		regfree(&n2);} voiddocall(Node *n){	Node *rsp; 	if(atv == ZeroN) {		instruction(AJAL, ZeroN, ZeroN, n);		return;	} 	/*	 * if calling through an activation, link	 * to the new stack	 */	ratv.ival = atv->atvsafe;	rsp = regn(RegSP);	instruction(AMOVW, rsp, ZeroN, &ratv);	ratv.type = OREGISTER;	assign(&ratv, rsp);	instruction(AJAL, ZeroN, ZeroN, n);	rsp->type = OINDREG;	rsp->ival = atv->atvsafe;	instruction(AMOVW, rsp, ZeroN, regn(RegSP));	regfree(&ratv);} 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)) {		tmp = stknode(builtype[TIND]);		genaddr(l, tmp);	} 	/* Generate the alias saves */	genelist(rval->right); 	evalarg(r, 0); 	/*	 * Write out tail recursion	 */	if(l->type == ONAME && curfunc->sym == l->sym) {		tip = block[Scope];		evalarg(r, 4);		instruction(AJMP, ZeroN, ZeroN, ZeroN);		label(ipc, becomentry->pc+1);		return;	} 	ns = an(ONAME, ZeroN, ZeroN);

Lines 1–500 of 1543.