Esempio n. 1
0
/* setup a float param on the stack
 * used by bfcode() */
static void
param_float(struct symtab *sym, int *argofsp, int dotemps)
{
	NODE *p, *q, *t;
	int tmpnr;

	/*
	 * we have to dump the float from the general register
	 * into a temp, since the register allocator doesn't like
	 * floats to be in CLASSA.  This may not work for -xtemps.
	 */

	t = tempnode(0, INT, 0, 0);
	tmpnr = regno(t);
	q = block(REG, NIL, NIL, INT, 0, 0);
	q->n_rval = R0 + (*argofsp)++;
	p = buildtree(ASSIGN, t, q);
	ecomp(p);

	if (dotemps) {
		sym->soffset = tmpnr;
		sym->sflags |= STNODE;
	} else {
		q = tempnode(tmpnr, sym->stype, sym->sdf, sym->sap);
		p = nametree(sym);
		p = buildtree(ASSIGN, p, q);
		ecomp(p);
	}
}
Esempio n. 2
0
void
bfcode(struct symtab **sp, int cnt)
{
	int i, off;
	NODE *p, *q;
	struct symtab *sym;

	/* Process the first six arguments. */
	for (i=0; i < cnt && i < 6; i++) {
		sym = sp[i];
		q = block(REG, NIL, NIL, sym->stype, sym->sdf, sym->sap);
		q->n_rval = RETREG_PRE(sym->stype) + i;
		p = tempnode(0, sym->stype, sym->sdf, sym->sap);
		sym->soffset = regno(p);
		sym->sflags |= STNODE;
		p = buildtree(ASSIGN, p, q);
		ecomp(p);
	}

	/* Process the remaining arguments. */
	for (off = V9RESERVE; i < cnt; i++) {
		sym = sp[i];
		p = tempnode(0, sym->stype, sym->sdf, sym->sap);
		off = ALIGN(off, (tlen(p) - 1));
		sym->soffset = off * SZCHAR;
		off += tlen(p);
		p = buildtree(ASSIGN, p, nametree(sym));
		sym->soffset = regno(p->n_left);
		sym->sflags |= STNODE;
		ecomp(p);
	}
}
Esempio n. 3
0
/*
 * code for the beginning of a function; a is an array of
 * indices in symtab for the arguments; n is the number
 */
void
bfcode(struct symtab **sp, int cnt)
{
	struct symtab *sp2;
	NODE *n;
	int i;

	if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) {
		/* Function returns struct, adjust arg offset */
		for (i = 0; i < cnt; i++) 
			sp[i]->soffset += SZPOINT(INT);
	}

	if (xtemps == 0)
		return;

	/* put arguments in temporaries */
	for (i = 0; i < cnt; i++) {
		if (sp[i]->stype == STRTY || sp[i]->stype == UNIONTY ||
		    cisreg(sp[i]->stype) == 0)
			continue;
		sp2 = sp[i];
		n = tempnode(0, sp[i]->stype, sp[i]->sdf, sp[i]->sap);
		n = buildtree(ASSIGN, n, nametree(sp2));
		sp[i]->soffset = regno(n->n_left);
		sp[i]->sflags |= STNODE;
		ecomp(n);
	}
}
Esempio n. 4
0
/*
 * code for the beginning of a function; a is an array of
 * indices in stab for the arguments; n is the number
 */
void
bfcode(struct symtab **sp, int cnt)
{
	NODE *p, *q;
	int i, n;

	if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) {
		uerror("no struct return yet");
	}
	/* recalculate the arg offset and create TEMP moves */
	for (n = 1, i = 0; i < cnt; i++) {
		if (n < 8) {
			p = tempnode(0, sp[i]->stype, sp[i]->sdf, sp[i]->ssue);
			q = block(REG, NIL, NIL,
			    sp[i]->stype, sp[i]->sdf, sp[i]->ssue);
			q->n_rval = n;
			p = buildtree(ASSIGN, p, q);
			sp[i]->soffset = regno(p->n_left);
			sp[i]->sflags |= STNODE;
			ecomp(p);
		} else {
			sp[i]->soffset += SZINT * n;
			if (xtemps) {
				/* put stack args in temps if optimizing */
				p = tempnode(0, sp[i]->stype,
				    sp[i]->sdf, sp[i]->ssue);
				p = buildtree(ASSIGN, p, nametree(sp[i]));
				sp[i]->soffset = regno(p->n_left);
				sp[i]->sflags |= STNODE;
				ecomp(p);
			}
		}
		n += szty(sp[i]->stype);
	}
}
Esempio n. 5
0
static P1ND *
tlsnonpic(P1ND *p)
{
	P1ND *q, *r;
	struct symtab *sp, *sp2;
	int ext = p->n_sp->sclass;
	char *name;

	name = getsoname(p->n_sp);
	sp = picsymtab("", name,
	    ext == EXTERN ? "@INDNTPOFF" : "@NTPOFF");
	q = xbcon(0, sp, INT);
	if (ext == EXTERN)
		q = block(UMUL, q, NIL, PTR|VOID, 0, 0);

	sp2 = lookup("%gs:0", 0);
	sp2->stype = EXTERN|INT;
	r = nametree(sp2);

	q = buildtree(PLUS, q, r);
	q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_ap);
	q->n_sp = p->n_sp; /* for init */

	p1nfree(p);
	return q;
}
Esempio n. 6
0
File: code.c Progetto: Sciumo/pcc
void
bfcode(struct symtab **sp, int n)
{
	struct symtab *sp2;
	NODE *p, *q;
	int i;

	if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) {
		/* Move return address into temporary */
		p = tempnode(0, INT, 0, 0);
		strtemp = regno(p);
		q = block(REG, 0, 0, INT, 0, 0);
		regno(q) = R1;
		ecomp(buildtree(ASSIGN, p, q));
	}
	if (xtemps == 0)
		return;

	/* put arguments in temporaries */
	for (i = 0; i < n; i++) {
		if (sp[i]->stype == STRTY || sp[i]->stype == UNIONTY ||
		    cisreg(sp[i]->stype) == 0)
			continue;
		if (cqual(sp[i]->stype, sp[i]->squal) & VOL)
			continue;
		sp2 = sp[i];
		p = tempnode(0, sp[i]->stype, sp[i]->sdf, sp[i]->sap);
		p = buildtree(ASSIGN, p, nametree(sp2));
		sp[i]->soffset = regno(p->n_left);
		sp[i]->sflags |= STNODE;
		ecomp(p);
	}

}
Esempio n. 7
0
/* Put a symbol in a temporary
 * used by bfcode() and its helpers */
static void
putintemp(struct symtab *sym)
{
	NODE *p;
	p = tempnode(0, sym->stype, sym->sdf, sym->sap);
	p = buildtree(ASSIGN, p, nametree(sym));
	sym->soffset = regno(p->n_left);
	sym->sflags |= STNODE;
	ecomp(p);
}
Esempio n. 8
0
/*
 * Check if we may have to do a cast to/from TI.
 */
NODE *
gcc_eval_ticast(int op, NODE *p1, NODE *p2)
{
	struct attr *a1, *a2;
	int t;

	a2 = NULL; /* XXX flow analysis */
	if ((a1 = isti(p1)) == NULL && (a2 = isti(p2)) == NULL)
		return NIL;

	if (op == RETURN)
		p1 = p1tcopy(p1);
	if (a1 == NULL) {
		if (a2 == NULL)
			cerror("gcc_eval_ticast error");
		switch (p1->n_type) {
		case LDOUBLE:
			p2 = doacall(floatuntixfsp,
			    nametree(floatuntixfsp), p2);
			tfree(p1);
			break;
		case ULONG:
		case LONG:
			p2 = cast(structref(p2, DOT, loti), p1->n_type, 0);
			tfree(p1);
			break;
		case VOID:
			return NIL;
		default:
			uerror("gcc_eval_ticast: %d", p1->n_type);
		}
		return p2;
	}
	/* p2 can be anything, but we must cast it to p1 */
	t = a1->iarg(1);

	if (p2->n_type == STRTY &&
	    (a2 = attr_find(p2->n_ap, GCC_ATYP_MODE)) &&
	    strcmp(a2->sarg(0), TISTR) == 0) {
		/* Already TI, just add extra mode bits */
		a2 = attr_new(GCC_ATYP_MODE, 3);
		a2->sarg(0) = TISTR;
		a2->iarg(1) = t;
		p2->n_ap = attr_add(p2->n_ap, a2);
	} else  {
		p2 = ticast(p2, t);
	}
	tfree(p1);
	return p2;
}
Esempio n. 9
0
/*
 * helper for bfcode() to put register arguments on stack.
 */
static void
argmove(struct symtab *s, int regno)
{
	NODE *p, *r;

	s->sclass = AUTO;
	s->soffset = NOOFFSET;
	oalloc(s, &autooff);
	p = nametree(s);
	r = bcon(0);
	r->n_op = REG;
	r->n_rval = regno;
	r->n_type = p->n_type;
	r->n_sue = p->n_sue;
	r->n_df = p->n_df;
	ecode(buildtree(ASSIGN, p, r));
}
Esempio n. 10
0
void
bfcode(struct symtab **sp, int n)
{
	struct symtab *sp2;
	NODE *p, *q;
	int i, argbase, sz;

	if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) {
		/* Move return address into temporary */
		p = tempnode(0, INT, 0, 0);
		strtemp = regno(p);
		q = block(REG, 0, 0, INT, 0, 0);
		regno(q) = R1;
		ecomp(buildtree(ASSIGN, p, q));
	}

	/* correct arg alignment XXX should be done somewhere else */
	argbase = ARGINIT;
	for (i = 0; i < n; i++) {
		sp2 = sp[i];
		sz = tsize(sp2->stype, sp2->sdf, sp2->sap);

		SETOFF(sz, SZINT);
		sp2->soffset = argbase;
		argbase += sz;
	}

	if (xtemps == 0)
		return;

	/* put arguments in temporaries */
	for (i = 0; i < n; i++) {
		if (sp[i]->stype == STRTY || sp[i]->stype == UNIONTY ||
		    cisreg(sp[i]->stype) == 0)
			continue;
		if (cqual(sp[i]->stype, sp[i]->squal) & VOL)
			continue;
		sp2 = sp[i];
		p = tempnode(0, sp[i]->stype, sp[i]->sdf, sp[i]->sap);
		p = buildtree(ASSIGN, p, nametree(sp2));
		sp[i]->soffset = regno(p->n_left);
		sp[i]->sflags |= STNODE;
		ecomp(p);
	}

}
Esempio n. 11
0
/* setup a 32-bit param on the stack
 * used by bfcode() */
static void
param_32bit(struct symtab *sym, int *argofsp, int dotemps)
{
	NODE *p, *q;

	q = block(REG, NIL, NIL, sym->stype, sym->sdf, sym->sap);
	regno(q) = R0 + (*argofsp)++;
	if (dotemps) {
		p = tempnode(0, sym->stype, sym->sdf, sym->sap);
		sym->soffset = regno(p);
		sym->sflags |= STNODE;
	} else {
		p = nametree(sym);
	}
	p = buildtree(ASSIGN, p, q);
	ecomp(p);
}
Esempio n. 12
0
/*
 * XXX This is a hack.  We cannot have (l)doubles in more than one
 * register class.  So we bounce them in and out of temps to
 * move them in and out of the right registers.
 */
static void
param_double(struct symtab *sym, int *regp, int dotemps)
{
	int reg = *regp;
	NODE *p, *q, *t;
	int navail;
	int tmpnr;

	/* alignment */
	++reg;
	reg &= ~1;

	navail = nargregs - (reg - A0);

	if (navail < 2) {
		/* would have appeared half in registers/half
		 * on the stack, but alignment ensures it
		 * appears on the stack */
		if (dotemps)
			putintemp(sym);
		*regp = reg;
		return;
	}

	t = tempnode(0, LONGLONG, 0, 0);
	tmpnr = regno(t);
	q = block(REG, NIL, NIL, LONGLONG, 0, 0);
	q->n_rval = A0A1 + (reg - A0);
	p = buildtree(ASSIGN, t, q);
	ecomp(p);

	if (dotemps) {
		sym->soffset = tmpnr;
		sym->sflags |= STNODE;
	} else {
		q = tempnode(tmpnr, sym->stype, sym->sdf, sym->sap);
		p = nametree(sym);
		p = buildtree(ASSIGN, p, q);
		ecomp(p);
	}
	*regp = reg + 2;
}
Esempio n. 13
0
/*
 * Watch out for references to static members.
 */
NODE *
cxxstructref(NODE *p, int f, char *n)
{
	struct symtab *sp = strmemb(p->n_ap);

	if (sp == NULL)
		cerror("ref to unknown struct");
	sp = sfind(n, sp);
	while (sp != NULL) {
		if (ISFTN(sp->stype) == 0) {
			if (sp->sclass == STATIC || sp->sclass == USTATIC) {
				tfree(p);
				return nametree(sp);
			}
			break;
		}
		sp = sfind(n, sp->snext);
	}
	return structref(p, f, n);
}
Esempio n. 14
0
/*
 * Create a reference for a TLS variable.
 */
static P1ND *
tlspic(P1ND *p)
{
	P1ND *q, *r;
	struct symtab *sp, *sp2;
	char *name;

	/*
	 * creates:
	 *   leal var@TLSGD(%ebx),%eax
	 *   call ___tls_get_addr@PLT
	 */

	/* calc address of var@TLSGD */
	q = tempnode(gotnr, PTR|VOID, 0, 0);
	name = getsoname(p->n_sp);
	sp = picsymtab("", name, "@TLSGD");
	r = xbcon(0, sp, INT);
	q = buildtree(PLUS, q, r);

	/* assign to %eax */
	r = block(REG, NIL, NIL, PTR|VOID, 0, 0);
	r->n_rval = EAX;
	q = buildtree(ASSIGN, r, q);

	/* call ___tls_get_addr */
	sp2 = lookup("___tls_get_addr@PLT", 0);
	sp2->stype = EXTERN|INT|FTN;
	r = nametree(sp2);
	r = buildtree(ADDROF, r, NIL);
	r = block(UCALL, r, NIL, INT, 0, 0);

	/* fusion both parts together */
	q = buildtree(COMOP, q, r);
	q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_ap);
	q->n_sp = p->n_sp; /* for init */

	p1nfree(p);
	return q;
}
Esempio n. 15
0
/*
 * Generate a call tree to function named n.
 */
static NODE *
callftn(char *n, ...)
{
	struct symtab *sp = getsymtab(n, 0);
	NODE *p, *a, *b;
	va_list ap;

	sp->stype = (FTN|VOID) | (PTR << TSHIFT);
	va_start(ap, n);

	a = va_arg(ap, NODE *);
	if (a != NULL) {
		do {
			b = va_arg(ap, NODE *);
			if (b != NULL)
				a = buildtree(CM, a, b);
		} while (b != NULL);
	}
	
	p = doacall(sp, nametree(sp), a, 0);
	va_end(ap);
	return p;
}
Esempio n. 16
0
/*
 * XXX This is a hack.  We cannot have floats in more than one
 * register class.  So we bounce them in and out of temps to
 * move them in and out of the right registers.
 */
static void
param_float(struct symtab *sym, int *regp, int dotemps)
{
	NODE *p, *q, *t;
	int tmpnr;

	t = tempnode(0, INT, 0, 0);
	tmpnr = regno(t);
	q = block(REG, NIL, NIL, INT, 0, 0);
	q->n_rval = (*regp)++;
	p = buildtree(ASSIGN, t, q);
	ecomp(p);

	if (dotemps) {
		sym->soffset = tmpnr;
		sym->sflags |= STNODE;
	} else {
		q = tempnode(tmpnr, sym->stype, sym->sdf, sym->sap);
		p = nametree(sym);
		p = buildtree(ASSIGN, p, q);
		ecomp(p);
	}
}
Esempio n. 17
0
/*
 * Search for correct matching function in a struct depending on 
 * argument list a.  Return a call node for this function.
 * Do not touch neither f nor a.
 * return a name tree suitable for a function call.
 * We know here that f is a struct reference.
 */
NODE *
cxxmatchftn(NODE *f, NODE *a)
{
	struct attr *ap;
	struct symtab *sp;
	char *n = (char *)f->n_right->n_sp;

	f = f->n_left;

	if ((ap = attr_find(f->n_ap, ATTR_STRUCT)) == NULL) {
		uerror("undefined class");
		sp = getsymtab(n, 0);
	} else
		sp = ap->amlist;
	sp = sfind(n, sp);
	while (sp != NULL) {
		if (ISFTN(sp->stype) && cxxptreecmp(sp, a) == 0)
			break;
		sp = sfind(n, sp->snext);
	}
	if (sp == NULL)
		uerror("undefined class member");
	return nametree(sp);
}
Esempio n. 18
0
/*
 * Apply a unary op on a TI value.
 */
NODE *
gcc_eval_tiuni(int op, NODE *p1)
{
	struct attr *a1;
	NODE *p;

	if ((a1 = isti(p1)) == NULL)
		return NULL;

	switch (op) {
	case UMINUS:
		p = ticast(bcon(0), 0);
		p = buildtree(CM, p, p1);
		p = doacall(subvti3sp, nametree(subvti3sp), p);
		break;

	case UMUL:
		p = NULL;
	default:
		uerror("unsupported unary TI mode op %d", op);
		p = NULL;
	}
	return p;
}
Esempio n. 19
0
/*
 * Evaluate 128-bit operands.
 */
NODE *
gcc_eval_timode(int op, NODE *p1, NODE *p2)
{
	struct attr *a1, *a2;
	struct symtab *sp;
	NODE *p;
	int isu = 0, gotti, isaop;

	if (op == CM)
		return buildtree(op, p1, p2);

	a1 = isti(p1);
	a2 = isti(p2);

	if (a1 == NULL && a2 == NULL)
		return NULL;

	if (op == ASSIGN)
		return timodeassign(p1, p2);

	gotti = (a1 != NULL);
	gotti += (a2 != NULL);

	if (gotti == 0)
		return NULL;

	if (a1 != NULL)
		isu = a1->iarg(1);
	if (a2 != NULL && !isu)
		isu = a2->iarg(1);

	if (a1 == NULL) {
		p1 = ticast(p1, isu);
		a1 = attr_find(p1->n_ap, GCC_ATYP_MODE);
	}
	if (a2 == NULL && (cdope(op) & SHFFLG) == 0) {
		p2 = ticast(p2, isu);
		a2 = attr_find(p2->n_ap, GCC_ATYP_MODE);
	}

	switch (op) {
	case GT:
	case GE:
	case LT:
	case LE:
	case EQ:
	case NE:
		/* change to call */
		sp = isu ? ucmpti2sp : cmpti2sp;
		p = doacall(sp, nametree(sp), buildtree(CM, p1, p2));
		p = buildtree(op, p, bcon(1));
		break;

	case AND:
	case ER:
	case OR:
		if (!ISPTR(p1->n_type))
			p1 = buildtree(ADDROF, p1, NIL);
		if (!ISPTR(p2->n_type))
			p2 = buildtree(ADDROF, p2, NIL);
		p = gcc_andorer(op, p1, p2);
		break;

	case LSEQ:
	case RSEQ:
	case LS:
	case RS:
		sp = op == LS || op == LSEQ ? ashldi3sp :
		    isu ? lshrdi3sp : ashrdi3sp;
		p2 = cast(p2, INT, 0);
		/* XXX p1 ccopy may have side effects */
		p = doacall(sp, nametree(sp), buildtree(CM, ccopy(p1), p2));
		if (op == LSEQ || op == RSEQ) {
			p = buildtree(ASSIGN, p1, p);
		} else
			tfree(p1);
		break;

	case PLUSEQ:
	case MINUSEQ:
	case MULEQ:
	case DIVEQ:
	case MODEQ:
	case PLUS:
	case MINUS:
	case MUL:
	case DIV:
	case MOD:
		isaop = (cdope(op)&ASGOPFLG);
		if (isaop)
			op = UNASG op;
		sp = op == PLUS ? addvti3sp :
		    op == MINUS ? subvti3sp :
		    op == MUL ? mulvti3sp :
		    op == DIV ? (isu ? udivti3sp : divti3sp) :
		    op == MOD ? (isu ? umodti3sp : modti3sp) : 0;
		/* XXX p1 ccopy may have side effects */
		p = doacall(sp, nametree(sp), buildtree(CM, ccopy(p1), p2));
		if (isaop)
			p = buildtree(ASSIGN, p1, p);
		else
			tfree(p1);
		break;

	default:
		uerror("unsupported TImode op %d", op);
		p = bcon(0);
	}
	return p;
}
Esempio n. 20
0
/*
 * code for the beginning of a function; a is an array of
 * indices in symtab for the arguments; n is the number
 */
void
bfcode(struct symtab **s, int cnt)
{
	union arglist *al;
	struct symtab *sp;
	NODE *p, *r;
	TWORD t;
	int i, rno, typ;

	/* recalculate the arg offset and create TEMP moves */
	/* Always do this for reg, even if not optimizing, to free arg regs */
	nsse = ngpr = 0;
	nrsp = ARGINIT;
	if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) {
		sp = cftnsp;
		if (argtyp(DECREF(sp->stype), sp->sdf, sp->sap) == STRMEM) {
			r = block(REG, NIL, NIL, LONG, 0, MKAP(LONG));
			regno(r) = argregsi[ngpr++];
			p = tempnode(0, r->n_type, r->n_df, r->n_ap);
			stroffset = regno(p);
			ecomp(buildtree(ASSIGN, p, r));
		}
	}

	for (i = 0; i < cnt; i++) {
		sp = s[i];

		if (sp == NULL)
			continue; /* XXX when happens this? */

		switch (typ = argtyp(sp->stype, sp->sdf, sp->sap)) {
		case INTEGER:
		case SSE:
			if (typ == SSE)
				rno = XMM0 + nsse++;
			else
				rno = argregsi[ngpr++];
			r = block(REG, NIL, NIL, sp->stype, sp->sdf, sp->sap);
			regno(r) = rno;
			p = tempnode(0, sp->stype, sp->sdf, sp->sap);
			sp->soffset = regno(p);
			sp->sflags |= STNODE;
			ecomp(buildtree(ASSIGN, p, r));
			break;

		case SSEMEM:
			sp->soffset = nrsp;
			nrsp += SZDOUBLE;
			if (xtemps) {
				p = tempnode(0, sp->stype, sp->sdf, sp->sap);
				p = buildtree(ASSIGN, p, nametree(sp));
				sp->soffset = regno(p->n_left);
				sp->sflags |= STNODE;
				ecomp(p);
			}
			break;

		case INTMEM:
			sp->soffset = nrsp;
			nrsp += SZLONG;
			if (xtemps) {
				p = tempnode(0, sp->stype, sp->sdf, sp->sap);
				p = buildtree(ASSIGN, p, nametree(sp));
				sp->soffset = regno(p->n_left);
				sp->sflags |= STNODE;
				ecomp(p);
			}
			break;

		case STRMEM: /* Struct in memory */
			sp->soffset = nrsp;
			nrsp += tsize(sp->stype, sp->sdf, sp->sap);
			break;

		case X87: /* long double args */
			sp->soffset = nrsp;
			nrsp += SZLDOUBLE;
			break;

		case STRCPX:
		case STRREG: /* Struct in register */
			/* Allocate space on stack for the struct */
			/* For simplicity always fetch two longwords */
			autooff += (2*SZLONG);

			if (typ == STRCPX) {
				t = DOUBLE;
				rno = XMM0 + nsse++;
			} else {
				t = LONG;
				rno = argregsi[ngpr++];
			}
			r = block(REG, NIL, NIL, t, 0, MKAP(t));
			regno(r) = rno;
			ecomp(movtomem(r, -autooff, FPREG));

			if (tsize(sp->stype, sp->sdf, sp->sap) > SZLONG) {
				r = block(REG, NIL, NIL, t, 0, MKAP(t));
				regno(r) = (typ == STRCPX ?
				    XMM0 + nsse++ : argregsi[ngpr++]);
				ecomp(movtomem(r, -autooff+SZLONG, FPREG));
			}

			sp->soffset = -autooff;
			break;

		default:
			cerror("bfcode: %d", typ);
		}
	}

	/* Check if there are varargs */
	if (cftnsp->sdf == NULL || cftnsp->sdf->dfun == NULL)
		return; /* no prototype */
	al = cftnsp->sdf->dfun;

	for (; al->type != TELLIPSIS; al++) {
		t = al->type;
		if (t == TNULL)
			return;
		if (BTYPE(t) == STRTY || BTYPE(t) == UNIONTY)
			al++;
		for (; t > BTMASK; t = DECREF(t))
			if (ISARY(t) || ISFTN(t))
				al++;
	}

	/* fix stack offset */
	SETOFF(autooff, ALMAX);

	/* Save reg arguments in the reg save area */
	p = NIL;
	for (i = ngpr; i < 6; i++) {
		r = block(REG, NIL, NIL, LONG, 0, MKAP(LONG));
		regno(r) = argregsi[i];
		r = movtomem(r, -RSALONGOFF(i)-autooff, FPREG);
		p = (p == NIL ? r : block(COMOP, p, r, INT, 0, MKAP(INT)));
	}
	for (i = nsse; i < 8; i++) {
		r = block(REG, NIL, NIL, DOUBLE, 0, MKAP(DOUBLE));
		regno(r) = i + XMM0;
		r = movtomem(r, -RSADBLOFF(i)-autooff, FPREG);
		p = (p == NIL ? r : block(COMOP, p, r, INT, 0, MKAP(INT)));
	}
	autooff += RSASZ;
	rsaoff = autooff;
	thissse = nsse;
	thisgpr = ngpr;
	thisrsp = nrsp;

	ecomp(p);
}
Esempio n. 21
0
/* setup a 64-bit parameter (double/ldouble/longlong)
 * used by bfcode() */
static void
param_64bit(struct symtab *sym, int *argofsp, int dotemps)
{
	int argofs = *argofsp;
	NODE *p, *q;
	int navail;

#if ALLONGLONG == 64
	/* alignment */
	++argofs;
	argofs &= ~1;
	*argofsp = argofs;
#endif

	navail = NARGREGS - argofs;

	if (navail < 2) {
		/* half in and half out of the registers */
		if (features(FEATURE_BIGENDIAN)) {
			cerror("param_64bit");
			p = q = NULL;
		} else {
			q = block(REG, NIL, NIL, INT, 0, 0);
			regno(q) = R0 + argofs;
			if (dotemps) {
				q = block(SCONV, q, NIL,
				    ULONGLONG, 0, 0);
				p = nametree(sym);
				p->n_type = ULONGLONG;
				p->n_df = 0;
				p->n_ap = NULL;
				p = block(LS, p, bcon(32), ULONGLONG, 0, 0);
				q = block(PLUS, p, q, ULONGLONG, 0, 0);
				p = tempnode(0, ULONGLONG, 0, 0);
				sym->soffset = regno(p);
				sym->sflags |= STNODE;
			} else {
				p = nametree(sym);
				regno(p) = sym->soffset;
				p->n_type = INT;
				p->n_df = 0;
				p->n_ap = NULL;
			}
		}
		p = buildtree(ASSIGN, p, q);
		ecomp(p);
		*argofsp = argofs + 2;
		return;
	}

	q = block(REG, NIL, NIL, sym->stype, sym->sdf, sym->sap);
	regno(q) = R0R1 + argofs;
	if (dotemps) {
		p = tempnode(0, sym->stype, sym->sdf, sym->sap);
		sym->soffset = regno(p);
		sym->sflags |= STNODE;
	} else {
		p = nametree(sym);
	}
	p = buildtree(ASSIGN, p, q);
	ecomp(p);
	*argofsp = argofs + 2;
}