Exemplo n.º 1
0
static int
getlit(Node *lit)
{
	if(smallintconst(lit))
		return mpgetfix(lit->val.u.xval);
	return -1;
}
Exemplo n.º 2
0
int
Bconv(Fmt *fp)
{
	char buf[500], *p;
	Mpint *xval, q, r, ten;
	int f;

	xval = va_arg(fp->args, Mpint*);
	mpmovefixfix(&q, xval);
	f = 0;
	if(mptestfix(&q) < 0) {
		f = 1;
		mpnegfix(&q);
	}
	mpmovecfix(&ten, 10);

	p = &buf[sizeof(buf)];
	*--p = 0;
	for(;;) {
		mpdivmodfixfix(&q, &r, &q, &ten);
		*--p = mpgetfix(&r) + '0';
		if(mptestfix(&q) <= 0)
			break;
	}
	if(f)
		*--p = '-';
	return fmtstrcpy(fp, p);
}
Exemplo n.º 3
0
void
gdata(Node *nam, Node *nr, int wid)
{
	Prog *p;
	vlong v;

	if(nr->op == OLITERAL) {
		switch(nr->val.ctype) {
		case CTCPLX:
			gdatacomplex(nam, nr->val.u.cval);
			return;
		case CTSTR:
			gdatastring(nam, nr->val.u.sval);
			return;
		}
	}

	if(wid == 8 && is64(nr->type)) {
		v = mpgetfix(nr->val.u.xval);
		p = gins(ADATA, nam, nodintconst(v));
		p->reg = 4;
		p = gins(ADATA, nam, nodintconst(v>>32));
		p->reg = 4;
		p->from.offset += 4;
		return;
	}
Exemplo n.º 4
0
int
Bconv(Fmt *fp)
{
	char buf[500], *p;
	Mpint *xval, q, r, ten, sixteen;
	int f, digit;

	xval = va_arg(fp->args, Mpint*);
	mpmovefixfix(&q, xval);
	f = 0;
	if(mptestfix(&q) < 0) {
		f = 1;
		mpnegfix(&q);
	}

	p = &buf[sizeof(buf)];
	*--p = 0;
	if(fp->flags & FmtSharp) {
		// Hexadecimal
		mpmovecfix(&sixteen, 16);
		for(;;) {
			mpdivmodfixfix(&q, &r, &q, &sixteen);
			digit = mpgetfix(&r);
			if(digit < 10)
				*--p = digit + '0';
			else
				*--p = digit - 10 + 'A';
			if(mptestfix(&q) <= 0)
				break;
		}
		*--p = 'x';
		*--p = '0';
	} else {
		// Decimal
		mpmovecfix(&ten, 10);
		for(;;) {
			mpdivmodfixfix(&q, &r, &q, &ten);
			*--p = mpgetfix(&r) + '0';
			if(mptestfix(&q) <= 0)
				break;
		}
	}
	if(f)
		*--p = '-';
	return fmtstrcpy(fp, p);
}
Exemplo n.º 5
0
void
gdata(Node *nam, Node *nr, int wid)
{
	Prog *p;
	vlong v;

	if(wid == 8 && is64(nr->type)) {
		v = mpgetfix(nr->val.u.xval);
		p = gins(ADATA, nam, nodintconst(v));
		p->reg = 4;
		p = gins(ADATA, nam, nodintconst(v>>32));
		p->reg = 4;
		p->from.offset += 4;
		return;
	}
Exemplo n.º 6
0
void
mplshfixfix(Mpint *a, Mpint *b)
{
	vlong s;

	if(a->ovf || b->ovf) {
		yyerror("ovf in mporfixfix");
		mpmovecfix(a, 0);
		a->ovf = 1;
		return;
	}
	s = mpgetfix(b);
	if(s < 0 || s >= Mpprec*Mpscale) {
		yyerror("stupid shift: %lld", s);
		mpmovecfix(a, 0);
		return;
	}

	mpshiftfix(a, s);
}
Exemplo n.º 7
0
static void
slicelit(int ctxt, Node *n, Node *var, NodeList **init)
{
	Node *r, *a;
	NodeList *l;
	Type *t;
	Node *vstat, *vauto;
	Node *index, *value;
	int mode;

	// make an array type
	t = shallow(n->type);
	t->bound = mpgetfix(n->right->val.u.xval);
	t->width = 0;
	t->sym = nil;
	dowidth(t);

	if(ctxt != 0) {

		// put everything into static array
		vstat = staticname(t, ctxt);
		arraylit(ctxt, 1, n, vstat, init);
		arraylit(ctxt, 2, n, vstat, init);

		// copy static to slice
		a = nod(OSLICE, vstat, nod(OKEY, N, N));
		a = nod(OAS, var, a);
		typecheck(&a, Etop);
		a->dodata = 2;
		*init = list(*init, a);
		return;
	}

	// recipe for var = []t{...}
	// 1. make a static array
	//	var vstat [...]t
	// 2. assign (data statements) the constant part
	//	vstat = constpart{}
	// 3. make an auto pointer to array and allocate heap to it
	//	var vauto *[...]t = new([...]t)
	// 4. copy the static array to the auto array
	//	*vauto = vstat
	// 5. assign slice of allocated heap to var
	//	var = [0:]*auto
	// 6. for each dynamic part assign to the slice
	//	var[i] = dynamic part
	//
	// an optimization is done if there is no constant part
	//	3. var vauto *[...]t = new([...]t)
	//	5. var = [0:]*auto
	//	6. var[i] = dynamic part

	// if the literal contains constants,
	// make static initialized array (1),(2)
	vstat = N;
	mode = getdyn(n, 1);
	if(mode & MODECONST) {
		vstat = staticname(t, ctxt);
		arraylit(ctxt, 1, n, vstat, init);
	}

	// make new auto *array (3 declare)
	vauto = nod(OXXX, N, N);
	tempname(vauto, ptrto(t));

	// set auto to point at new heap (3 assign)
	a = nod(ONEW, N, N);
	a->list = list1(typenod(t));
	a = nod(OAS, vauto, a);
	typecheck(&a, Etop);
	walkexpr(&a, init);
	*init = list(*init, a);

	if(vstat != N) {
		// copy static to heap (4)
		a = nod(OIND, vauto, N);
		a = nod(OAS, a, vstat);
		typecheck(&a, Etop);
		walkexpr(&a, init);
		*init = list(*init, a);
	}

	// make slice out of heap (5)
	a = nod(OAS, var, nod(OSLICE, vauto, nod(OKEY, N, N)));
	typecheck(&a, Etop);
	walkexpr(&a, init);
	*init = list(*init, a);

	// put dynamics into slice (6)
	for(l=n->list; l; l=l->next) {
		r = l->n;
		if(r->op != OKEY)
			fatal("slicelit: rhs not OKEY: %N", r);
		index = r->left;
		value = r->right;
		a = nod(OINDEX, var, index);
		a->etype = 1;	// no bounds checking
		// TODO need to check bounds?

		switch(value->op) {
		case OARRAYLIT:
			if(value->type->bound < 0)
				break;
			arraylit(ctxt, 2, value, a, init);
			continue;

		case OSTRUCTLIT:
			structlit(ctxt, 2, value, a, init);
			continue;
		}

		if(isliteral(index) && isliteral(value))
			continue;

		// build list of var[c] = expr
		a = nod(OAS, a, value);
		typecheck(&a, Etop);
		walkexpr(&a, init);
		*init = list(*init, a);
	}
}
Exemplo n.º 8
0
Arquivo: cgen64.c Projeto: 8l/go-learn
/*
 * attempt to generate 64-bit
 *	res = n
 * return 1 on success, 0 if op not handled.
 */
void
cgen64(Node *n, Node *res)
{
	Node t1, t2, *l, *r;
	Node lo1, lo2, hi1, hi2;
	Node al, ah, bl, bh, cl, ch, s, n1, creg;
	Prog *p1, *p2, *p3, *p4, *p5, *p6;

	uint64 v;

	if(res->op != OINDREG && res->op != ONAME) {
		dump("n", n);
		dump("res", res);
		fatal("cgen64 %O of %O", n->op, res->op);
	}

	l = n->left;
	if(!l->addable) {
		tempname(&t1, l->type);
		cgen(l, &t1);
		l = &t1;
	}

	split64(l, &lo1, &hi1);
	switch(n->op) {
	default:
		fatal("cgen64 %O", n->op);

	case OMINUS:
		split64(res, &lo2, &hi2);

		regalloc(&t1, lo1.type, N);
		regalloc(&al, lo1.type, N);
		regalloc(&ah, hi1.type, N);

		gins(AMOVW, &lo1, &al);
		gins(AMOVW, &hi1, &ah);

		gmove(ncon(0), &t1);
		p1 = gins(ASUB, &al, &t1);
		p1->scond |= C_SBIT;
		gins(AMOVW, &t1, &lo2);

		gmove(ncon(0), &t1);
		gins(ASBC, &ah, &t1);
		gins(AMOVW, &t1, &hi2);

		regfree(&t1);
		regfree(&al);
		regfree(&ah);
		splitclean();
		splitclean();
		return;

	case OCOM:
		split64(res, &lo2, &hi2);
		regalloc(&n1, lo1.type, N);

		gins(AMOVW, &lo1, &n1);
		gins(AMVN, &n1, &n1);
		gins(AMOVW, &n1, &lo2);

		gins(AMOVW, &hi1, &n1);
		gins(AMVN, &n1, &n1);
		gins(AMOVW, &n1, &hi2);

		regfree(&n1);
		splitclean();
		splitclean();
		return;

	case OADD:
	case OSUB:
	case OMUL:
	case OLSH:
	case ORSH:
	case OAND:
	case OOR:
	case OXOR:
		// binary operators.
		// common setup below.
		break;
	}

	// setup for binary operators
	r = n->right;
	if(r != N && !r->addable) {
		tempname(&t2, r->type);
		cgen(r, &t2);
		r = &t2;
	}
	if(is64(r->type))
		split64(r, &lo2, &hi2);

	regalloc(&al, lo1.type, N);
	regalloc(&ah, hi1.type, N);

	// Do op.  Leave result in ah:al.
	switch(n->op) {
	default:
		fatal("cgen64: not implemented: %N\n", n);

	case OADD:
		// TODO: Constants
		regalloc(&bl, types[TPTR32], N);
		regalloc(&bh, types[TPTR32], N);
		gins(AMOVW, &hi1, &ah);
		gins(AMOVW, &lo1, &al);
		gins(AMOVW, &hi2, &bh);
		gins(AMOVW, &lo2, &bl);
		p1 = gins(AADD, &bl, &al);
		p1->scond |= C_SBIT;
		gins(AADC, &bh, &ah);
		regfree(&bl);
		regfree(&bh);
		break;

	case OSUB:
		// TODO: Constants.
		regalloc(&bl, types[TPTR32], N);
		regalloc(&bh, types[TPTR32], N);
		gins(AMOVW, &lo1, &al);
		gins(AMOVW, &hi1, &ah);
		gins(AMOVW, &lo2, &bl);
		gins(AMOVW, &hi2, &bh);
		p1 = gins(ASUB, &bl, &al);
		p1->scond |= C_SBIT;
		gins(ASBC, &bh, &ah);
		regfree(&bl);
		regfree(&bh);
		break;

	case OMUL:
		// TODO(kaib): this can be done with 4 regs and does not need 6
		regalloc(&bl, types[TPTR32], N);
		regalloc(&bh, types[TPTR32], N);
		regalloc(&cl, types[TPTR32], N);
		regalloc(&ch, types[TPTR32], N);

		// load args into bh:bl and bh:bl.
		gins(AMOVW, &hi1, &bh);
		gins(AMOVW, &lo1, &bl);
		gins(AMOVW, &hi2, &ch);
		gins(AMOVW, &lo2, &cl);

		// bl * cl
		p1 = gins(AMULLU, N, N);
		p1->from.type = D_REG;
		p1->from.reg = bl.val.u.reg;
		p1->reg = cl.val.u.reg;
		p1->to.type = D_REGREG;
		p1->to.reg = ah.val.u.reg;
		p1->to.offset = al.val.u.reg;
//print("%P\n", p1);

		// bl * ch
		p1 = gins(AMULA, N, N);
		p1->from.type = D_REG;
		p1->from.reg = bl.val.u.reg;
		p1->reg = ch.val.u.reg;
		p1->to.type = D_REGREG;
		p1->to.reg = ah.val.u.reg;
		p1->to.offset = ah.val.u.reg;
//print("%P\n", p1);

		// bh * cl
		p1 = gins(AMULA, N, N);
		p1->from.type = D_REG;
		p1->from.reg = bh.val.u.reg;
		p1->reg = cl.val.u.reg;
		p1->to.type = D_REGREG;
		p1->to.reg = ah.val.u.reg;
		p1->to.offset = ah.val.u.reg;
//print("%P\n", p1);

		regfree(&bh);
		regfree(&bl);
		regfree(&ch);
		regfree(&cl);

		break;

	case OLSH:
		regalloc(&bl, lo1.type, N);
		regalloc(&bh, hi1.type, N);
		gins(AMOVW, &hi1, &bh);
		gins(AMOVW, &lo1, &bl);

		if(r->op == OLITERAL) {
			v = mpgetfix(r->val.u.xval);
			if(v >= 64) {
				// TODO(kaib): replace with gins(AMOVW, nodintconst(0), &al)
				// here and below (verify it optimizes to EOR)
				gins(AEOR, &al, &al);
				gins(AEOR, &ah, &ah);
			} else if(v > 32) {
				gins(AEOR, &al, &al);
				//	MOVW	bl<<(v-32), ah
				gshift(AMOVW, &bl, SHIFT_LL, (v-32), &ah);
			} else if(v == 32) {
				gins(AEOR, &al, &al);
				gins(AMOVW, &bl, &ah);
			} else if(v > 0) {
				//	MOVW	bl<<v, al
				gshift(AMOVW, &bl, SHIFT_LL, v, &al);

				//	MOVW	bh<<v, ah
				gshift(AMOVW, &bh, SHIFT_LL, v, &ah);

				//	OR		bl>>(32-v), ah
				gshift(AORR, &bl, SHIFT_LR, 32-v, &ah);
			} else {
				gins(AMOVW, &bl, &al);
				gins(AMOVW, &bh, &ah);
			}
			goto olsh_break;
		}

		regalloc(&s, types[TUINT32], N);
		regalloc(&creg, types[TUINT32], N);
		if (is64(r->type)) {
			// shift is >= 1<<32
			split64(r, &cl, &ch);
			gmove(&ch, &s);
			p1 = gins(AMOVW, &s, &s);
			p1->scond |= C_SBIT;
			p6 = gbranch(ABNE, T);
			gmove(&cl, &s);
			splitclean();
		} else {
			gmove(r, &s);
			p6 = P;
		}
		p1 = gins(AMOVW, &s, &s);
		p1->scond |= C_SBIT;

		// shift == 0
		p1 = gins(AMOVW, &bl, &al);
		p1->scond = C_SCOND_EQ;
		p1 = gins(AMOVW, &bh, &ah);
		p1->scond = C_SCOND_EQ;
		p2 = gbranch(ABEQ, T);

		// shift is < 32
		nodconst(&n1, types[TUINT32], 32);
		gmove(&n1, &creg);
		gcmp(ACMP, &s, &creg);

		//	MOVW.LO		bl<<s, al
		p1 = gregshift(AMOVW, &bl, SHIFT_LL, &s, &al);
		p1->scond = C_SCOND_LO;

		//	MOVW.LO		bh<<s, ah
		p1 = gregshift(AMOVW, &bh, SHIFT_LL, &s, &ah);
		p1->scond = C_SCOND_LO;

		//	SUB.LO		s, creg
		p1 = gins(ASUB, &s, &creg);
		p1->scond = C_SCOND_LO;

		//	OR.LO		bl>>creg, ah
		p1 = gregshift(AORR, &bl, SHIFT_LR, &creg, &ah);
		p1->scond = C_SCOND_LO;

		//	BLO	end
		p3 = gbranch(ABLO, T);

		// shift == 32
		p1 = gins(AEOR, &al, &al);
		p1->scond = C_SCOND_EQ;
		p1 = gins(AMOVW, &bl, &ah);
		p1->scond = C_SCOND_EQ;
		p4 = gbranch(ABEQ, T);

		// shift is < 64
		nodconst(&n1, types[TUINT32], 64);
		gmove(&n1, &creg);
		gcmp(ACMP, &s, &creg);

		//	EOR.LO	al, al
		p1 = gins(AEOR, &al, &al);
		p1->scond = C_SCOND_LO;

		//	MOVW.LO		creg>>1, creg
		p1 = gshift(AMOVW, &creg, SHIFT_LR, 1, &creg);
		p1->scond = C_SCOND_LO;

		//	SUB.LO		creg, s
		p1 = gins(ASUB, &creg, &s);
		p1->scond = C_SCOND_LO;

		//	MOVW	bl<<s, ah
		p1 = gregshift(AMOVW, &bl, SHIFT_LL, &s, &ah);
		p1->scond = C_SCOND_LO;

		p5 = gbranch(ABLO, T);

		// shift >= 64
		if (p6 != P) patch(p6, pc);
		gins(AEOR, &al, &al);
		gins(AEOR, &ah, &ah);

		patch(p2, pc);
		patch(p3, pc);
		patch(p4, pc);
		patch(p5, pc);
		regfree(&s);
		regfree(&creg);

olsh_break:
		regfree(&bl);
		regfree(&bh);
		break;


	case ORSH:
		regalloc(&bl, lo1.type, N);
		regalloc(&bh, hi1.type, N);
		gins(AMOVW, &hi1, &bh);
		gins(AMOVW, &lo1, &bl);

		if(r->op == OLITERAL) {
			v = mpgetfix(r->val.u.xval);
			if(v >= 64) {
				if(bh.type->etype == TINT32) {
					//	MOVW	bh->31, al
					gshift(AMOVW, &bh, SHIFT_AR, 31, &al);

					//	MOVW	bh->31, ah
					gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
				} else {
					gins(AEOR, &al, &al);
					gins(AEOR, &ah, &ah);
				}
			} else if(v > 32) {
				if(bh.type->etype == TINT32) {
					//	MOVW	bh->(v-32), al
					gshift(AMOVW, &bh, SHIFT_AR, v-32, &al);

					//	MOVW	bh->31, ah
					gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
				} else {
					//	MOVW	bh>>(v-32), al
					gshift(AMOVW, &bh, SHIFT_LR, v-32, &al);
					gins(AEOR, &ah, &ah);
				}
			} else if(v == 32) {
				gins(AMOVW, &bh, &al);
				if(bh.type->etype == TINT32) {
					//	MOVW	bh->31, ah
					gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
				} else {
					gins(AEOR, &ah, &ah);
				}
			} else if( v > 0) {
				//	MOVW	bl>>v, al
				gshift(AMOVW, &bl, SHIFT_LR, v, &al);
	
				//	OR		bh<<(32-v), al
				gshift(AORR, &bh, SHIFT_LL, 32-v, &al);

				if(bh.type->etype == TINT32) {
					//	MOVW	bh->v, ah
					gshift(AMOVW, &bh, SHIFT_AR, v, &ah);
				} else {
					//	MOVW	bh>>v, ah
					gshift(AMOVW, &bh, SHIFT_LR, v, &ah);
				}
			} else {
				gins(AMOVW, &bl, &al);
				gins(AMOVW, &bh, &ah);
			}
			goto orsh_break;
		}

		regalloc(&s, types[TUINT32], N);
		regalloc(&creg, types[TUINT32], N);
		if (is64(r->type)) {
			// shift is >= 1<<32
			split64(r, &cl, &ch);
			gmove(&ch, &s);
			p1 = gins(AMOVW, &s, &s);
			p1->scond |= C_SBIT;
			p6 = gbranch(ABNE, T);
			gmove(&cl, &s);
			splitclean();
		} else {
			gmove(r, &s);
			p6 = P;
		}
		p1 = gins(AMOVW, &s, &s);
		p1->scond |= C_SBIT;

		// shift == 0
		p1 = gins(AMOVW, &bl, &al);
		p1->scond = C_SCOND_EQ;
		p1 = gins(AMOVW, &bh, &ah);
		p1->scond = C_SCOND_EQ;
		p2 = gbranch(ABEQ, T);

		// check if shift is < 32
		nodconst(&n1, types[TUINT32], 32);
		gmove(&n1, &creg);
		gcmp(ACMP, &s, &creg);

		//	MOVW.LO		bl>>s, al
		p1 = gregshift(AMOVW, &bl, SHIFT_LR, &s, &al);
		p1->scond = C_SCOND_LO;

		//	SUB.LO		s,creg
		p1 = gins(ASUB, &s, &creg);
		p1->scond = C_SCOND_LO;

		//	OR.LO		bh<<(32-s), al
		p1 = gregshift(AORR, &bh, SHIFT_LL, &creg, &al);
		p1->scond = C_SCOND_LO;

		if(bh.type->etype == TINT32) {
			//	MOVW	bh->s, ah
			p1 = gregshift(AMOVW, &bh, SHIFT_AR, &s, &ah);
		} else {
			//	MOVW	bh>>s, ah
			p1 = gregshift(AMOVW, &bh, SHIFT_LR, &s, &ah);
		}
		p1->scond = C_SCOND_LO;

		//	BLO	end
		p3 = gbranch(ABLO, T);

		// shift == 32
		if(bh.type->etype == TINT32)
			p1 = gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
		else
			p1 = gins(AEOR, &al, &al);
		p1->scond = C_SCOND_EQ;
		p1 = gins(AMOVW, &bh, &al);
		p1->scond = C_SCOND_EQ;
		p4 = gbranch(ABEQ, T);

		// check if shift is < 64
		nodconst(&n1, types[TUINT32], 64);
		gmove(&n1, &creg);
		gcmp(ACMP, &s, &creg);

		//	MOVW.LO		creg>>1, creg
		p1 = gshift(AMOVW, &creg, SHIFT_LR, 1, &creg);
		p1->scond = C_SCOND_LO;

		//	SUB.LO		creg, s
		p1 = gins(ASUB, &creg, &s);
		p1->scond = C_SCOND_LO;

		if(bh.type->etype == TINT32) {
			//	MOVW	bh->(s-32), al
			p1 = gregshift(AMOVW, &bh, SHIFT_AR, &s, &al);
			p1->scond = C_SCOND_LO;

			//	MOVW	bh->31, ah
			p1 = gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
			p1->scond = C_SCOND_LO;
		} else {
			//	MOVW	bh>>(v-32), al
			p1 = gregshift(AMOVW, &bh, SHIFT_LR, &s, &al);
			p1->scond = C_SCOND_LO;

			p1 = gins(AEOR, &ah, &ah);
			p1->scond = C_SCOND_LO;
		}

		//	BLO	end
		p5 = gbranch(ABLO, T);

		// s >= 64
		if (p6 != P) patch(p6, pc);
		if(bh.type->etype == TINT32) {
			//	MOVW	bh->31, al
			gshift(AMOVW, &bh, SHIFT_AR, 31, &al);

			//	MOVW	bh->31, ah
			gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
		} else {
			gins(AEOR, &al, &al);
			gins(AEOR, &ah, &ah);
		}

		patch(p2, pc);
		patch(p3, pc);
		patch(p4, pc);
		patch(p5, pc);
		regfree(&s);
		regfree(&creg);


orsh_break:
		regfree(&bl);
		regfree(&bh);
		break;

	case OXOR:
	case OAND:
	case OOR:
		// TODO(kaib): literal optimizations
		// make constant the right side (it usually is anyway).
//		if(lo1.op == OLITERAL) {
//			nswap(&lo1, &lo2);
//			nswap(&hi1, &hi2);
//		}
//		if(lo2.op == OLITERAL) {
//			// special cases for constants.
//			lv = mpgetfix(lo2.val.u.xval);
//			hv = mpgetfix(hi2.val.u.xval);
//			splitclean();	// right side
//			split64(res, &lo2, &hi2);
//			switch(n->op) {
//			case OXOR:
//				gmove(&lo1, &lo2);
//				gmove(&hi1, &hi2);
//				switch(lv) {
//				case 0:
//					break;
//				case 0xffffffffu:
//					gins(ANOTL, N, &lo2);
//					break;
//				default:
//					gins(AXORL, ncon(lv), &lo2);
//					break;
//				}
//				switch(hv) {
//				case 0:
//					break;
//				case 0xffffffffu:
//					gins(ANOTL, N, &hi2);
//					break;
//				default:
//					gins(AXORL, ncon(hv), &hi2);
//					break;
//				}
//				break;

//			case OAND:
//				switch(lv) {
//				case 0:
//					gins(AMOVL, ncon(0), &lo2);
//					break;
//				default:
//					gmove(&lo1, &lo2);
//					if(lv != 0xffffffffu)
//						gins(AANDL, ncon(lv), &lo2);
//					break;
//				}
//				switch(hv) {
//				case 0:
//					gins(AMOVL, ncon(0), &hi2);
//					break;
//				default:
//					gmove(&hi1, &hi2);
//					if(hv != 0xffffffffu)
//						gins(AANDL, ncon(hv), &hi2);
//					break;
//				}
//				break;

//			case OOR:
//				switch(lv) {
//				case 0:
//					gmove(&lo1, &lo2);
//					break;
//				case 0xffffffffu:
//					gins(AMOVL, ncon(0xffffffffu), &lo2);
//					break;
//				default:
//					gmove(&lo1, &lo2);
//					gins(AORL, ncon(lv), &lo2);
//					break;
//				}
//				switch(hv) {
//				case 0:
//					gmove(&hi1, &hi2);
//					break;
//				case 0xffffffffu:
//					gins(AMOVL, ncon(0xffffffffu), &hi2);
//					break;
//				default:
//					gmove(&hi1, &hi2);
//					gins(AORL, ncon(hv), &hi2);
//					break;
//				}
//				break;
//			}
//			splitclean();
//			splitclean();
//			goto out;
//		}
		regalloc(&n1, lo1.type, N);
		gins(AMOVW, &lo1, &al);
		gins(AMOVW, &hi1, &ah);
		gins(AMOVW, &lo2, &n1);
		gins(optoas(n->op, lo1.type), &n1, &al);
		gins(AMOVW, &hi2, &n1);
		gins(optoas(n->op, lo1.type), &n1, &ah);
		regfree(&n1);
		break;
	}
	if(is64(r->type))
		splitclean();
	splitclean();

	split64(res, &lo1, &hi1);
	gins(AMOVW, &al, &lo1);
	gins(AMOVW, &ah, &hi1);
	splitclean();

//out:
	regfree(&al);
	regfree(&ah);
}
Exemplo n.º 9
0
/*
 * generate:
 *	res = &n;
 */
void
agen(Node *n, Node *res)
{
	Node *nl, *nr;
	Node n1, n2, n3, tmp, n4;
	Prog *p1;
	uint32 w;
	uint64 v;
	Type *t;

	if(debug['g']) {
		dump("\nagen-res", res);
		dump("agen-r", n);
	}
	if(n == N || n->type == T)
		return;

	if(!isptr[res->type->etype])
		fatal("agen: not tptr: %T", res->type);

	while(n->op == OCONVNOP)
		n = n->left;

	if(n->addable) {
		regalloc(&n1, types[tptr], res);
		gins(ALEAQ, n, &n1);
		gmove(&n1, res);
		regfree(&n1);
		goto ret;
	}

	nl = n->left;
	nr = n->right;

	switch(n->op) {
	default:
		fatal("agen: unknown op %N", n);
		break;

	case OCALLMETH:
		cgen_callmeth(n, 0);
		cgen_aret(n, res);
		break;

	case OCALLINTER:
		cgen_callinter(n, res, 0);
		cgen_aret(n, res);
		break;

	case OCALLFUNC:
		cgen_call(n, 0);
		cgen_aret(n, res);
		break;

	case OINDEX:
		w = n->type->width;
		if(nr->addable)
			goto irad;
		if(nl->addable) {
			if(!isconst(nr, CTINT)) {
				regalloc(&n1, nr->type, N);
				cgen(nr, &n1);
			}
			regalloc(&n3, types[tptr], res);
			agen(nl, &n3);
			goto index;
		}
		tempname(&tmp, nr->type);
		cgen(nr, &tmp);
		nr = &tmp;

	irad:
		regalloc(&n3, types[tptr], res);
		agen(nl, &n3);
		if(!isconst(nr, CTINT)) {
			regalloc(&n1, nr->type, N);
			cgen(nr, &n1);
		}
		goto index;

	index:
		// &a is in &n3 (allocated in res)
		// i is in &n1 (if not constant)
		// w is width

		// explicit check for nil if array is large enough
		// that we might derive too big a pointer.
		if(!isslice(nl->type) && nl->type->width >= unmappedzero) {
			regalloc(&n4, types[tptr], &n3);
			gmove(&n3, &n4);
			n4.op = OINDREG;
			n4.type = types[TUINT8];
			n4.xoffset = 0;
			gins(ATESTB, nodintconst(0), &n4);
			regfree(&n4);
		}

		if(w == 0)
			fatal("index is zero width");

		// constant index
		if(isconst(nr, CTINT)) {
			v = mpgetfix(nr->val.u.xval);
			if(isslice(nl->type)) {

				if(!debug['B'] && !n->etype) {
					n1 = n3;
					n1.op = OINDREG;
					n1.type = types[tptr];
					n1.xoffset = Array_nel;
					nodconst(&n2, types[TUINT64], v);
					gins(optoas(OCMP, types[TUINT32]), &n1, &n2);
					p1 = gbranch(optoas(OGT, types[TUINT32]), T);
					ginscall(throwindex, 0);
					patch(p1, pc);
				}

				n1 = n3;
				n1.op = OINDREG;
				n1.type = types[tptr];
				n1.xoffset = Array_array;
				gmove(&n1, &n3);
			} else
			if(!debug['B'] && !n->etype) {
				if(v < 0)
					yyerror("out of bounds on array");
				else
				if(v >= nl->type->bound)
					yyerror("out of bounds on array");
			}

			nodconst(&n2, types[tptr], v*w);
			gins(optoas(OADD, types[tptr]), &n2, &n3);

			gmove(&n3, res);
			regfree(&n3);
			break;
		}

		// type of the index
		t = types[TUINT64];
		if(issigned[n1.type->etype])
			t = types[TINT64];

		regalloc(&n2, t, &n1);			// i
		gmove(&n1, &n2);
		regfree(&n1);

		if(!debug['B'] && !n->etype) {
			// check bounds
			if(isslice(nl->type)) {
				n1 = n3;
				n1.op = OINDREG;
				n1.type = types[tptr];
				n1.xoffset = Array_nel;
			} else
				nodconst(&n1, types[TUINT64], nl->type->bound);
			gins(optoas(OCMP, types[TUINT32]), &n2, &n1);
			p1 = gbranch(optoas(OLT, types[TUINT32]), T);
			ginscall(throwindex, 0);
			patch(p1, pc);
		}

		if(isslice(nl->type)) {
			n1 = n3;
			n1.op = OINDREG;
			n1.type = types[tptr];
			n1.xoffset = Array_array;
			gmove(&n1, &n3);
		}

		if(w == 1 || w == 2 || w == 4 || w == 8) {
			p1 = gins(ALEAQ, &n2, &n3);
			p1->from.scale = w;
			p1->from.index = p1->from.type;
			p1->from.type = p1->to.type + D_INDIR;
		} else {
			nodconst(&n1, t, w);
			gins(optoas(OMUL, t), &n1, &n2);
			gins(optoas(OADD, types[tptr]), &n2, &n3);
			gmove(&n3, res);
		}

		gmove(&n3, res);
		regfree(&n2);
		regfree(&n3);
		break;

	case ONAME:
		// should only get here with names in this func.
		if(n->funcdepth > 0 && n->funcdepth != funcdepth) {
			dump("bad agen", n);
			fatal("agen: bad ONAME funcdepth %d != %d",
				n->funcdepth, funcdepth);
		}

		// should only get here for heap vars or paramref
		if(!(n->class & PHEAP) && n->class != PPARAMREF) {
			dump("bad agen", n);
			fatal("agen: bad ONAME class %#x", n->class);
		}
		cgen(n->heapaddr, res);
		if(n->xoffset != 0) {
			nodconst(&n1, types[TINT64], n->xoffset);
			gins(optoas(OADD, types[tptr]), &n1, res);
		}
		break;

	case OIND:
		cgen(nl, res);
		break;

	case ODOT:
		agen(nl, res);
		if(n->xoffset != 0) {
			nodconst(&n1, types[TINT64], n->xoffset);
			gins(optoas(OADD, types[tptr]), &n1, res);
		}
		break;

	case ODOTPTR:
		cgen(nl, res);
		if(n->xoffset != 0) {
			// explicit check for nil if struct is large enough
			// that we might derive too big a pointer.
			if(nl->type->type->width >= unmappedzero) {
				regalloc(&n1, types[tptr], res);
				gmove(res, &n1);
				n1.op = OINDREG;
				n1.type = types[TUINT8];
				n1.xoffset = 0;
				gins(ATESTB, nodintconst(0), &n1);
				regfree(&n1);
			}
			nodconst(&n1, types[TINT64], n->xoffset);
			gins(optoas(OADD, types[tptr]), &n1, res);
		}
		break;
	}

ret:
	;
}