Exemplo n.º 1
0
void prtree(FILE *out, Node *n, int lvl)
{
	switch (n->what) {
		case nNUM: {
			indent(out, lvl), fprintf(out, "%lld", n->n);
			break;
		} case nFP: {
			indent(out, lvl), fprintf(out, "%g", n->fp);
			break;
		} case nSTR: {
			indent(out, lvl), fprintf(out, "\"%s\"", n->s);
			break;
		} case nVOID: {
			indent(out, lvl), fprintf(out, "void");
			break;
		} default: {
			if (n->s)
				indent(out, lvl), fprintf(out, "%s", n->s);
			else {
				indent(out, lvl), fprintf(out, "(%s\n", what_tab[n->what].name);
				if (n->l)
					prtree(out, n->l, lvl + 2);
				if (n->r)
					prtree(out, n->r, lvl + 2);
				indent(out, lvl), fprintf(out, ")");
			}
		}
	}
	fprintf(out, "\n");
}
Exemplo n.º 2
0
void
lcgen(Node *n, Node *nn)
{
	Prog *p1;
	Node nod;

	if(debug['g']) {
		prtree(nn, "lcgen lhs");
		prtree(n, "lcgen");
	}
	if(n == Z || n->type == T)
		return;
	if(nn == Z) {
		nn = &nod;
		regalloc(&nod, n, Z);
	}
	switch(n->op) {
	default:
		if(n->addable < INDEXED) {
			diag(n, "unknown op in lcgen: %O", n->op);
			break;
		}
		nod = *n;
		nod.op = OADDR;
		nod.left = n;
		nod.right = Z;
		nod.type = types[TIND];
		gopcode(OAS, &nod, Z, nn);
		break;

	case OCOMMA:
		cgen(n->left, n->left);
		lcgen(n->right, nn);
		break;

	case OIND:
		cgen(n->left, nn);
		break;

	case OCOND:
		bcgen(n->left, 1);
		p1 = p;
		lcgen(n->right->left, nn);
		gbranch(OGOTO);
		patch(p1, pc);
		p1 = p;
		lcgen(n->right->right, nn);
		patch(p1, pc);
		break;
	}
}
Exemplo n.º 3
0
static void prpc(struct imap_refmsgtable *mt)
{
	struct imap_refmsg *root=rfc822_threadgetroot(mt), *m;

	if (!root)
		return;

	for (m=root->firstchild; m; m=m->nextsib)
		prtree(m);

	printf("\n\n");
}
Exemplo n.º 4
0
Arquivo: mach.c Projeto: kahrs/cda
void
prsym(Sym *s)
{
	int i, n;
	if (s < wall && fflag)
		flatten(s->exp);
	if (n = s->inst) {
		if (n < 1)
			return;
		for (s++, i = 0; i < n; i++, s++)
			if (s->lval) {
				fprintf(stdout, "%s.%s = ", s->name, s->pin);
				prtree(s->exp);
				fprintf(stdout, "\n");
			}
	}
	if (!s->lval)
		return;
	fprintf(stdout,"%s = ",s->name);
	prtree(s->exp);
	fprintf(stdout,"\n");
}
Exemplo n.º 5
0
static void prtree(struct imap_refmsg *m)
{
	printf("<%s>", m->msgid ? m->msgid:"");

	if (m->isdummy)
	{
		printf(" (dummy)");
	}

	printf(".parent=");
	if (m->parent)
		printf("<%s>", m->parent->msgid ? m->parent->msgid:"");
	else
		printf("ROOT");

	printf("\n");

	for (m=m->firstchild; m; m=m->nextsib)
		prtree(m);
}
Exemplo n.º 6
0
int main(int argc, char** argv)
{
  int arg, i;
  char *mfile = NULL;

  for (arg = 1; arg < argc; ++arg)
  if (*argv[arg] == '-') {
    if ('f'==clower(argv[arg][1])) {
      if (++arg >= argc) {
  	fprintf(stderr, "-f needs filename argument.\n");
  	return 1;
      }
      mfile = argv[arg];
    }
    else 
      opt_char(argv[arg][1]);
  }
  else 
    if (modcount < MAXMODS) {
      if (argv[arg][0]) /* ignore trailing whitespace */
        modnames[modcount++] = argv[arg];
    }
    else {
      fprintf(stderr, "Too many module names.\n");
      return 1;
    }
  if (mfile != NULL) {
    arg = fmake(mfile);
    if (arg == -1)
      fprintf(stderr, "\nCannot open makefile\n");
  } 
  else {
    for (i = 0; *mfiles[i]; ++i)
       if ((arg=fmake(mfiles[i])) != -1) break;
    if (!*mfiles[i])
      fprintf(stderr, "\nCannot open makefile\n");
  }
  if (debug) prtree();
  return arg;
}
Exemplo n.º 7
0
void
cgen(Node *n, Node *nn)
{
	Node *l, *r;
	Prog *p1;
	Node nod, nod1, nod2, nod3, nod4;
	int o;
	long v, curs;

	if(debug['g']) {
		prtree(nn, "cgen lhs");
		prtree(n, "cgen");
	}
	if(n == Z || n->type == T)
		return;
	if(typesuv[n->type->etype]) {
		sugen(n, nn, n->type->width);
		return;
	}
	l = n->left;
	r = n->right;
	o = n->op;
	if(n->addable >= INDEXED) {
		if(nn == Z) {
			switch(o) {
			default:
				nullwarn(Z, Z);
				break;
			case OINDEX:
				nullwarn(l, r);
				break;
			}
			return;
		}
		gmove(n, nn);
		return;
	}
	curs = cursafe;

	if(n->complex >= FNX)
	if(l->complex >= FNX)
	if(r != Z && r->complex >= FNX)
	switch(o) {
	default:
		regret(&nod, r);
		cgen(r, &nod);

		regsalloc(&nod1, r);
		gopcode(OAS, &nod, Z, &nod1);

		regfree(&nod);
		nod = *n;
		nod.right = &nod1;
		cgen(&nod, nn);
		return;

	case OFUNC:
	case OCOMMA:
	case OANDAND:
	case OOROR:
	case OCOND:
	case ODOT:
		break;
	}

	switch(o) {
	default:
		diag(n, "unknown op in cgen: %O", o);
		break;

	case OAS:
		if(l->op == OBIT)
			goto bitas;
		if(l->addable >= INDEXED && l->complex < FNX) {
			if(nn != Z || r->addable < INDEXED) {
				if(r->complex >= FNX && nn == Z)
					regret(&nod, r);
				else
					regalloc(&nod, r, nn);
				cgen(r, &nod);
				gmove(&nod, l);
				if(nn != Z)
					gmove(&nod, nn);
				regfree(&nod);
			} else
				gmove(r, l);
			break;
		}
		if(l->complex >= r->complex) {
			reglcgen(&nod1, l, Z);
			if(r->addable >= INDEXED) {
				gmove(r, &nod1);
				if(nn != Z)
					gmove(r, nn);
				regfree(&nod1);
				break;
			}
			regalloc(&nod, r, nn);
			cgen(r, &nod);
		} else {
			regalloc(&nod, r, nn);
			cgen(r, &nod);
			reglcgen(&nod1, l, Z);
		}
		gmove(&nod, &nod1);
		regfree(&nod);
		regfree(&nod1);
		break;

	bitas:
		n = l->left;
		regalloc(&nod, r, nn);
		if(l->complex >= r->complex) {
			reglcgen(&nod1, n, Z);
			cgen(r, &nod);
		} else {
			cgen(r, &nod);
			reglcgen(&nod1, n, Z);
		}
		regalloc(&nod2, n, Z);
		gopcode(OAS, &nod1, Z, &nod2);
		bitstore(l, &nod, &nod1, &nod2, nn);
		break;

	case OBIT:
		if(nn == Z) {
			nullwarn(l, Z);
			break;
		}
		bitload(n, &nod, Z, Z, nn);
		gopcode(OAS, &nod, Z, nn);
		regfree(&nod);
		break;

	case OADD:
	case OSUB:
	case OAND:
	case OOR:
	case OXOR:
	case OLSHR:
	case OASHL:
	case OASHR:
		/*
		 * immediate operands
		 */
		if(nn != Z)
		if(r->op == OCONST)
		if(!typefd[n->type->etype]) {
			cgen(l, nn);
			if(r->vconst == 0)
			if(o != OAND)
				break;
			if(nn != Z)
				gopcode(o, r, Z, nn);
			break;
		}

	case OLMUL:
	case OLDIV:
	case OLMOD:
	case OMUL:
	case ODIV:
	case OMOD:
		if(nn == Z) {
			nullwarn(l, r);
			break;
		}
		if(o == OMUL || o == OLMUL) {
			if(mulcon(n, nn))
				break;
		}
		if(l->complex >= r->complex) {
			regalloc(&nod, l, nn);
			cgen(l, &nod);
			regalloc(&nod1, r, Z);
			cgen(r, &nod1);
			gopcode(o, &nod1, Z, &nod);
		} else {
			regalloc(&nod, r, nn);
			cgen(r, &nod);
			regalloc(&nod1, l, Z);
			cgen(l, &nod1);
			gopcode(o, &nod, &nod1, &nod);
		}
		gopcode(OAS, &nod, Z, nn);
		regfree(&nod);
		regfree(&nod1);
		break;

	case OASLSHR:
	case OASASHL:
	case OASASHR:
	case OASAND:
	case OASADD:
	case OASSUB:
	case OASXOR:
	case OASOR:
		if(l->op == OBIT)
			goto asbitop;
		if(r->op == OCONST)
		if(!typefd[r->type->etype])
		if(!typefd[n->type->etype]) {
			if(l->addable < INDEXED)
				reglcgen(&nod2, l, Z);
			else
				nod2 = *l;
			regalloc(&nod, r, nn);
			gopcode(OAS, &nod2, Z, &nod);
			gopcode(o, r, Z, &nod);
			gopcode(OAS, &nod, Z, &nod2);
	
			regfree(&nod);
			if(l->addable < INDEXED)
				regfree(&nod2);
			break;
		}

	case OASLMUL:
	case OASLDIV:
	case OASLMOD:
	case OASMUL:
	case OASDIV:
	case OASMOD:
		if(l->op == OBIT)
			goto asbitop;
		if(l->complex >= r->complex) {
			if(l->addable < INDEXED)
				reglcgen(&nod2, l, Z);
			else
				nod2 = *l;
			regalloc(&nod1, r, Z);
			cgen(r, &nod1);
		} else {
			regalloc(&nod1, r, Z);
			cgen(r, &nod1);
			if(l->addable < INDEXED)
				reglcgen(&nod2, l, Z);
			else
				nod2 = *l;
		}

		regalloc(&nod, n, nn);
		gmove(&nod2, &nod);
		gopcode(o, &nod1, Z, &nod);
		gmove(&nod, &nod2);
		if(nn != Z)
			gopcode(OAS, &nod, Z, nn);
		regfree(&nod);
		regfree(&nod1);
		if(l->addable < INDEXED)
			regfree(&nod2);
		break;

	asbitop:
		regalloc(&nod4, n, nn);
		if(l->complex >= r->complex) {
			bitload(l, &nod, &nod1, &nod2, &nod4);
			regalloc(&nod3, r, Z);
			cgen(r, &nod3);
		} else {
			regalloc(&nod3, r, Z);
			cgen(r, &nod3);
			bitload(l, &nod, &nod1, &nod2, &nod4);
		}
		gmove(&nod, &nod4);
		gopcode(o, &nod3, Z, &nod4);
		regfree(&nod3);
		gmove(&nod4, &nod);
		regfree(&nod4);
		bitstore(l, &nod, &nod1, &nod2, nn);
		break;

	case OADDR:
		if(nn == Z) {
			nullwarn(l, Z);
			break;
		}
		lcgen(l, nn);
		break;

	case OFUNC:
		if(l->complex >= FNX) {
			if(l->op != OIND)
				diag(n, "bad function call");

			regret(&nod, l->left);
			cgen(l->left, &nod);
			regsalloc(&nod1, l->left);
			gopcode(OAS, &nod, Z, &nod1);
			regfree(&nod);

			nod = *n;
			nod.left = &nod2;
			nod2 = *l;
			nod2.left = &nod1;
			nod2.complex = 1;
			cgen(&nod, nn);

			return;
		}
		o = reg[REGARG];
		gargs(r, &nod, &nod1);
		if(l->addable < INDEXED) {
			reglcgen(&nod, l, Z);
			gopcode(OFUNC, Z, Z, &nod);
			regfree(&nod);
		} else
			gopcode(OFUNC, Z, Z, l);
		if(REGARG)
			if(o != reg[REGARG])
				reg[REGARG]--;
		if(nn != Z) {
			regret(&nod, n);
			gopcode(OAS, &nod, Z, nn);
			regfree(&nod);
		}
		break;

	case OIND:
		if(nn == Z) {
			nullwarn(l, Z);
			break;
		}
		regialloc(&nod, n, nn);
		r = l;
		while(r->op == OADD)
			r = r->right;
		if(sconst(r)) {
			v = r->vconst;
			r->vconst = 0;
			cgen(l, &nod);
			nod.xoffset += v;
			r->vconst = v;
		} else
			cgen(l, &nod);
		regind(&nod, n);
		gopcode(OAS, &nod, Z, nn);
		regfree(&nod);
		break;

	case OEQ:
	case ONE:
	case OLE:
	case OLT:
	case OGE:
	case OGT:
	case OLO:
	case OLS:
	case OHI:
	case OHS:
		if(nn == Z) {
			nullwarn(l, r);
			break;
		}
		boolgen(n, 1, nn);
		break;

	case OANDAND:
	case OOROR:
		boolgen(n, 1, nn);
		if(nn == Z)
			patch(p, pc);
		break;

	case ONOT:
		if(nn == Z) {
			nullwarn(l, Z);
			break;
		}
		boolgen(n, 1, nn);
		break;

	case OCOMMA:
		cgen(l, Z);
		cgen(r, nn);
		break;

	case OCAST:
		if(nn == Z) {
			nullwarn(l, Z);
			break;
		}
		/*
		 * convert from types l->n->nn
		 */
		if(nocast(l->type, n->type)) {
			if(nocast(n->type, nn->type)) {
				cgen(l, nn);
				break;
			}
		}
		regalloc(&nod, l, nn);
		cgen(l, &nod);
		regalloc(&nod1, n, &nod);
		gopcode(OAS, &nod, Z, &nod1);
		gopcode(OAS, &nod1, Z, nn);
		regfree(&nod1);
		regfree(&nod);
		break;

	case ODOT:
		sugen(l, nodrat, l->type->width);
		if(nn != Z) {
			warn(n, "non-interruptable temporary");
			nod = *nodrat;
			if(!r || r->op != OCONST) {
				diag(n, "DOT and no offset");
				break;
			}
			nod.xoffset += (long)r->vconst;
			nod.type = n->type;
			cgen(&nod, nn);
		}
		break;

	case OCOND:
		bcgen(l, 1);
		p1 = p;
		cgen(r->left, nn);
		gbranch(OGOTO);
		patch(p1, pc);
		p1 = p;
		cgen(r->right, nn);
		patch(p1, pc);
		break;

	case OPOSTINC:
	case OPOSTDEC:
		v = 1;
		if(l->type->etype == TIND)
			v = l->type->link->width;
		if(o == OPOSTDEC)
			v = -v;
		if(l->op == OBIT)
			goto bitinc;
		if(nn == Z)
			goto pre;

		if(l->addable < INDEXED)
			reglcgen(&nod2, l, Z);
		else
			nod2 = *l;

		regalloc(&nod, l, nn);
		gopcode(OAS, &nod2, Z, &nod);
		regalloc(&nod1, l, Z);
		if(typefd[l->type->etype]) {
			regalloc(&nod3, l, Z);
			if(v < 0) {
				gopcode(OAS, nodfconst(-v), Z, &nod3);
				gopcode(OSUB, &nod3, &nod, &nod1);
			} else {
				gopcode(OAS, nodfconst(v), Z, &nod3);
				gopcode(OADD, &nod3, &nod, &nod1);
			}
			regfree(&nod3);
		} else
			gopcode(OADD, nodconst(v), &nod, &nod1);
		gopcode(OAS, &nod1, Z, &nod2);

		regfree(&nod);
		regfree(&nod1);
		if(l->addable < INDEXED)
			regfree(&nod2);
		break;

	case OPREINC:
	case OPREDEC:
		v = 1;
		if(l->type->etype == TIND)
			v = l->type->link->width;
		if(o == OPREDEC)
			v = -v;
		if(l->op == OBIT)
			goto bitinc;

	pre:
		if(l->addable < INDEXED)
			reglcgen(&nod2, l, Z);
		else
			nod2 = *l;

		regalloc(&nod, l, nn);
		gopcode(OAS, &nod2, Z, &nod);
		if(typefd[l->type->etype]) {
			regalloc(&nod3, l, Z);
			if(v < 0) {
				gopcode(OAS, nodfconst(-v), Z, &nod3);
				gopcode(OSUB, &nod3, Z, &nod);
			} else {
				gopcode(OAS, nodfconst(v), Z, &nod3);
				gopcode(OADD, &nod3, Z, &nod);
			}
			regfree(&nod3);
		} else
			gopcode(OADD, nodconst(v), Z, &nod);
		gopcode(OAS, &nod, Z, &nod2);
		if(nn && l->op == ONAME)	/* in x=++i, emit USED(i) */
			gins(ANOP, l, Z);

		regfree(&nod);
		if(l->addable < INDEXED)
			regfree(&nod2);
		break;

	bitinc:
		if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
			bitload(l, &nod, &nod1, &nod2, Z);
			gopcode(OAS, &nod, Z, nn);
			gopcode(OADD, nodconst(v), Z, &nod);
			bitstore(l, &nod, &nod1, &nod2, Z);
			break;
		}
		bitload(l, &nod, &nod1, &nod2, nn);
		gopcode(OADD, nodconst(v), Z, &nod);
		bitstore(l, &nod, &nod1, &nod2, nn);
		break;
	}
	cursafe = curs;
}
Exemplo n.º 8
0
void
cgen(Node *n, Node *nn)
{
	Node *l, *r, *t;
	Prog *p1;
	Node nod, nod1, nod2, nod3, nod4;
	int o, hardleft;
	int32 v, curs;
	vlong c;

	if(debug['g']) {
		prtree(nn, "cgen lhs");
		prtree(n, "cgen");
	}
	if(n == Z || n->type == T)
		return;
	if(typesu[n->type->etype]) {
		sugen(n, nn, n->type->width);
		return;
	}
	l = n->left;
	r = n->right;
	o = n->op;
	
	if(n->op == OEXREG || (nn != Z && nn->op == OEXREG)) {
		gmove(n, nn);
		return;
	}

	if(n->addable >= INDEXED) {
		if(nn == Z) {
			switch(o) {
			default:
				nullwarn(Z, Z);
				break;
			case OINDEX:
				nullwarn(l, r);
				break;
			}
			return;
		}
		gmove(n, nn);
		return;
	}
	curs = cursafe;

	if(l->complex >= FNX)
	if(r != Z && r->complex >= FNX)
	switch(o) {
	default:
		if(cond(o) && typesu[l->type->etype])
			break;

		regret(&nod, r);
		cgen(r, &nod);

		regsalloc(&nod1, r);
		gmove(&nod, &nod1);

		regfree(&nod);
		nod = *n;
		nod.right = &nod1;

		cgen(&nod, nn);
		return;

	case OFUNC:
	case OCOMMA:
	case OANDAND:
	case OOROR:
	case OCOND:
	case ODOT:
		break;
	}

	hardleft = l->addable < INDEXED || l->complex >= FNX;
	switch(o) {
	default:
		diag(n, "unknown op in cgen: %O", o);
		break;

	case ONEG:
	case OCOM:
		if(nn == Z) {
			nullwarn(l, Z);
			break;
		}
		regalloc(&nod, l, nn);
		cgen(l, &nod);
		gopcode(o, n->type, Z, &nod);
		gmove(&nod, nn);
		regfree(&nod);
		break;

	case OAS:
		if(l->op == OBIT)
			goto bitas;
		if(!hardleft) {
			if(nn != Z || r->addable < INDEXED || hardconst(r)) {
				if(r->complex >= FNX && nn == Z)
					regret(&nod, r);
				else
					regalloc(&nod, r, nn);
				cgen(r, &nod);
				gmove(&nod, l);
				if(nn != Z)
					gmove(&nod, nn);
				regfree(&nod);
			} else
				gmove(r, l);
			break;
		}
		if(l->complex >= r->complex) {
			if(l->op == OINDEX && immconst(r)) {
				gmove(r, l);
				break;
			}
			reglcgen(&nod1, l, Z);
			if(r->addable >= INDEXED && !hardconst(r)) {
				gmove(r, &nod1);
				if(nn != Z)
					gmove(r, nn);
				regfree(&nod1);
				break;
			}
			regalloc(&nod, r, nn);
			cgen(r, &nod);
		} else {
			regalloc(&nod, r, nn);
			cgen(r, &nod);
			reglcgen(&nod1, l, Z);
		}
		gmove(&nod, &nod1);
		regfree(&nod);
		regfree(&nod1);
		break;

	bitas:
		n = l->left;
		regalloc(&nod, r, nn);
		if(l->complex >= r->complex) {
			reglcgen(&nod1, n, Z);
			cgen(r, &nod);
		} else {
			cgen(r, &nod);
			reglcgen(&nod1, n, Z);
		}
		regalloc(&nod2, n, Z);
		gmove(&nod1, &nod2);
		bitstore(l, &nod, &nod1, &nod2, nn);
		break;

	case OBIT:
		if(nn == Z) {
			nullwarn(l, Z);
			break;
		}
		bitload(n, &nod, Z, Z, nn);
		gmove(&nod, nn);
		regfree(&nod);
		break;

	case OLSHR:
	case OASHL:
	case OASHR:
		if(nn == Z) {
			nullwarn(l, r);
			break;
		}
		if(r->op == OCONST) {
			if(r->vconst == 0) {
				cgen(l, nn);
				break;
			}
			regalloc(&nod, l, nn);
			cgen(l, &nod);
			if(o == OASHL && r->vconst == 1)
				gopcode(OADD, n->type, &nod, &nod);
			else
				gopcode(o, n->type, r, &nod);
			gmove(&nod, nn);
			regfree(&nod);
			break;
		}

		/*
		 * get nod to be D_CX
		 */
		if(nodreg(&nod, nn, D_CX)) {
			regsalloc(&nod1, n);
			gmove(&nod, &nod1);
			cgen(n, &nod);		/* probably a bug */
			gmove(&nod, nn);
			gmove(&nod1, &nod);
			break;
		}
		reg[D_CX]++;
		if(nn->op == OREGISTER && nn->reg == D_CX)
			regalloc(&nod1, l, Z);
		else
			regalloc(&nod1, l, nn);
		if(r->complex >= l->complex) {
			cgen(r, &nod);
			cgen(l, &nod1);
		} else {
			cgen(l, &nod1);
			cgen(r, &nod);
		}
		gopcode(o, n->type, &nod, &nod1);
		gmove(&nod1, nn);
		regfree(&nod);
		regfree(&nod1);
		break;

	case OADD:
	case OSUB:
	case OOR:
	case OXOR:
	case OAND:
		if(nn == Z) {
			nullwarn(l, r);
			break;
		}
		if(typefd[n->type->etype])
			goto fop;
		if(r->op == OCONST) {
			if(r->vconst == 0 && o != OAND) {
				cgen(l, nn);
				break;
			}
		}
		if(n->op == OADD && l->op == OASHL && l->right->op == OCONST
		&& (r->op != OCONST || r->vconst < -128 || r->vconst > 127)) {
			c = l->right->vconst;
			if(c > 0 && c <= 3) {
				if(l->left->complex >= r->complex) {
					regalloc(&nod, l->left, nn);
					cgen(l->left, &nod);
					if(r->addable < INDEXED) {
						regalloc(&nod1, r, Z);
						cgen(r, &nod1);
						genmuladd(&nod, &nod, 1 << c, &nod1);
						regfree(&nod1);
					}
					else
						genmuladd(&nod, &nod, 1 << c, r);
				}
				else {
					regalloc(&nod, r, nn);
					cgen(r, &nod);
					regalloc(&nod1, l->left, Z);
					cgen(l->left, &nod1);
					genmuladd(&nod, &nod1, 1 << c, &nod);
					regfree(&nod1);
				}
				gmove(&nod, nn);
				regfree(&nod);
				break;
			}
		}
		if(r->addable >= INDEXED && !hardconst(r)) {
			regalloc(&nod, l, nn);
			cgen(l, &nod);
			gopcode(o, n->type, r, &nod);
			gmove(&nod, nn);
			regfree(&nod);
			break;
		}
		if(l->complex >= r->complex) {
			regalloc(&nod, l, nn);
			cgen(l, &nod);
			regalloc(&nod1, r, Z);
			cgen(r, &nod1);
			gopcode(o, n->type, &nod1, &nod);
		} else {
			regalloc(&nod1, r, nn);
			cgen(r, &nod1);
			regalloc(&nod, l, Z);
			cgen(l, &nod);
			gopcode(o, n->type, &nod1, &nod);
		}
		gmove(&nod, nn);
		regfree(&nod);
		regfree(&nod1);
		break;

	case OLMOD:
	case OMOD:
	case OLMUL:
	case OLDIV:
	case OMUL:
	case ODIV:
		if(nn == Z) {
			nullwarn(l, r);
			break;
		}
		if(typefd[n->type->etype])
			goto fop;
		if(r->op == OCONST && typechl[n->type->etype]) {	/* TO DO */
			SET(v);
			switch(o) {
			case ODIV:
			case OMOD:
				c = r->vconst;
				if(c < 0)
					c = -c;
				v = xlog2(c);
				if(v < 0)
					break;
				/* fall thru */
			case OMUL:
			case OLMUL:
				regalloc(&nod, l, nn);
				cgen(l, &nod);
				switch(o) {
				case OMUL:
				case OLMUL:
					mulgen(n->type, r, &nod);
					break;
				case ODIV:
					sdiv2(r->vconst, v, l, &nod);
					break;
				case OMOD:
					smod2(r->vconst, v, l, &nod);
					break;
				}
				gmove(&nod, nn);
				regfree(&nod);
				goto done;
			case OLDIV:
				c = r->vconst;
				if((c & 0x80000000) == 0)
					break;
				regalloc(&nod1, l, Z);
				cgen(l, &nod1);
				regalloc(&nod, l, nn);
				zeroregm(&nod);
				gins(ACMPL, &nod1, nodconst(c));
				gins(ASBBL, nodconst(-1), &nod);
				regfree(&nod1);
				gmove(&nod, nn);
				regfree(&nod);
				goto done;
			}
		}

		if(o == OMUL) {
			if(l->addable >= INDEXED) {
				t = l;
				l = r;
				r = t;
			}
			/* should favour AX */
			regalloc(&nod, l, nn);
			cgen(l, &nod);
			if(r->addable < INDEXED || hardconst(r)) {
				regalloc(&nod1, r, Z);
				cgen(r, &nod1);
				gopcode(OMUL, n->type, &nod1, &nod);
				regfree(&nod1);
			}else
				gopcode(OMUL, n->type, r, &nod);	/* addressible */
			gmove(&nod, nn);
			regfree(&nod);
			break;
		}

		/*
		 * get nod to be D_AX
		 * get nod1 to be D_DX
		 */
		if(nodreg(&nod, nn, D_AX)) {
			regsalloc(&nod2, n);
			gmove(&nod, &nod2);
			v = reg[D_AX];
			reg[D_AX] = 0;

			if(isreg(l, D_AX)) {
				nod3 = *n;
				nod3.left = &nod2;
				cgen(&nod3, nn);
			} else
			if(isreg(r, D_AX)) {
				nod3 = *n;
				nod3.right = &nod2;
				cgen(&nod3, nn);
			} else
				cgen(n, nn);

			gmove(&nod2, &nod);
			reg[D_AX] = v;
			break;
		}
		if(nodreg(&nod1, nn, D_DX)) {
			regsalloc(&nod2, n);
			gmove(&nod1, &nod2);
			v = reg[D_DX];
			reg[D_DX] = 0;

			if(isreg(l, D_DX)) {
				nod3 = *n;
				nod3.left = &nod2;
				cgen(&nod3, nn);
			} else
			if(isreg(r, D_DX)) {
				nod3 = *n;
				nod3.right = &nod2;
				cgen(&nod3, nn);
			} else
				cgen(n, nn);

			gmove(&nod2, &nod1);
			reg[D_DX] = v;
			break;
		}
		reg[D_AX]++;

		if(r->op == OCONST && (o == ODIV || o == OLDIV) && immconst(r) && typechl[r->type->etype]) {
			reg[D_DX]++;
			if(l->addable < INDEXED) {
				regalloc(&nod2, l, Z);
				cgen(l, &nod2);
				l = &nod2;
			}
			if(o == ODIV)
				sdivgen(l, r, &nod, &nod1);
			else
				udivgen(l, r, &nod, &nod1);
			gmove(&nod1, nn);
			if(l == &nod2)
				regfree(l);
			goto freeaxdx;
		}

		if(l->complex >= r->complex) {
			cgen(l, &nod);
			reg[D_DX]++;
			if(o == ODIV || o == OMOD)
				gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z);
			if(o == OLDIV || o == OLMOD)
				zeroregm(&nod1);
			if(r->addable < INDEXED || r->op == OCONST) {
				regsalloc(&nod3, r);
				cgen(r, &nod3);
				gopcode(o, n->type, &nod3, Z);
			} else
				gopcode(o, n->type, r, Z);
		} else {
			regsalloc(&nod3, r);
			cgen(r, &nod3);
			cgen(l, &nod);
			reg[D_DX]++;
			if(o == ODIV || o == OMOD)
				gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z);
			if(o == OLDIV || o == OLMOD)
				zeroregm(&nod1);
			gopcode(o, n->type, &nod3, Z);
		}
		if(o == OMOD || o == OLMOD)
			gmove(&nod1, nn);
		else
			gmove(&nod, nn);
	freeaxdx:
		regfree(&nod);
		regfree(&nod1);
		break;

	case OASLSHR:
	case OASASHL:
	case OASASHR:
		if(r->op == OCONST)
			goto asand;
		if(l->op == OBIT)
			goto asbitop;
		if(typefd[n->type->etype])
			goto asand;	/* can this happen? */

		/*
		 * get nod to be D_CX
		 */
		if(nodreg(&nod, nn, D_CX)) {
			regsalloc(&nod1, n);
			gmove(&nod, &nod1);
			cgen(n, &nod);
			if(nn != Z)
				gmove(&nod, nn);
			gmove(&nod1, &nod);
			break;
		}
		reg[D_CX]++;

		if(r->complex >= l->complex) {
			cgen(r, &nod);
			if(hardleft)
				reglcgen(&nod1, l, Z);
			else
				nod1 = *l;
		} else {
			if(hardleft)
				reglcgen(&nod1, l, Z);
			else
				nod1 = *l;
			cgen(r, &nod);
		}

		gopcode(o, l->type, &nod, &nod1);
		regfree(&nod);
		if(nn != Z)
			gmove(&nod1, nn);
		if(hardleft)
			regfree(&nod1);
		break;

	case OASAND:
	case OASADD:
	case OASSUB:
	case OASXOR:
	case OASOR:
	asand:
		if(l->op == OBIT)
			goto asbitop;
		if(typefd[l->type->etype] || typefd[r->type->etype])
			goto asfop;
		if(l->complex >= r->complex) {
			if(hardleft)
				reglcgen(&nod, l, Z);
			else
				nod = *l;
			if(!immconst(r)) {
				regalloc(&nod1, r, nn);
				cgen(r, &nod1);
				gopcode(o, l->type, &nod1, &nod);
				regfree(&nod1);
			} else
				gopcode(o, l->type, r, &nod);
		} else {
			regalloc(&nod1, r, nn);
			cgen(r, &nod1);
			if(hardleft)
				reglcgen(&nod, l, Z);
			else
				nod = *l;
			gopcode(o, l->type, &nod1, &nod);
			regfree(&nod1);
		}
		if(nn != Z)
			gmove(&nod, nn);
		if(hardleft)
			regfree(&nod);
		break;

	asfop:
		if(l->complex >= r->complex) {
			if(hardleft)
				reglcgen(&nod, l, Z);
			else
				nod = *l;
			if(r->addable < INDEXED){
				regalloc(&nod1, r, nn);
				cgen(r, &nod1);
			}else
				nod1 = *r;
			regalloc(&nod2, r, Z);
			gmove(&nod, &nod2);
			gopcode(o, r->type, &nod1, &nod2);
			gmove(&nod2, &nod);
			regfree(&nod2);
			if(r->addable < INDEXED)
				regfree(&nod1);
		} else {
			regalloc(&nod1, r, nn);
			cgen(r, &nod1);
			if(hardleft)
				reglcgen(&nod, l, Z);
			else
				nod = *l;
			if(o != OASMUL && o != OASADD) {
				regalloc(&nod2, r, Z);
				gmove(&nod, &nod2);
				gopcode(o, r->type, &nod1, &nod2);
				regfree(&nod1);
				gmove(&nod2, &nod);
				regfree(&nod2);
			} else {
				gopcode(o, r->type, &nod, &nod1);
				gmove(&nod1, &nod);
				regfree(&nod1);
			}
		}
		if(nn != Z)
			gmove(&nod, nn);
		if(hardleft)
			regfree(&nod);
		break;

	case OASLMUL:
	case OASLDIV:
	case OASLMOD:
	case OASMUL:
	case OASDIV:
	case OASMOD:
		if(l->op == OBIT)
			goto asbitop;
		if(typefd[n->type->etype] || typefd[r->type->etype])
			goto asfop;
		if(r->op == OCONST && typechl[n->type->etype]) {
			SET(v);
			switch(o) {
			case OASDIV:
			case OASMOD:
				c = r->vconst;
				if(c < 0)
					c = -c;
				v = xlog2(c);
				if(v < 0)
					break;
				/* fall thru */
			case OASMUL:
			case OASLMUL:
				if(hardleft)
					reglcgen(&nod2, l, Z);
				else
					nod2 = *l;
				regalloc(&nod, l, nn);
				cgen(&nod2, &nod);
				switch(o) {
				case OASMUL:
				case OASLMUL:
					mulgen(n->type, r, &nod);
					break;
				case OASDIV:
					sdiv2(r->vconst, v, l, &nod);
					break;
				case OASMOD:
					smod2(r->vconst, v, l, &nod);
					break;
				}
			havev:
				gmove(&nod, &nod2);
				if(nn != Z)
					gmove(&nod, nn);
				if(hardleft)
					regfree(&nod2);
				regfree(&nod);
				goto done;
			case OASLDIV:
				c = r->vconst;
				if((c & 0x80000000) == 0)
					break;
				if(hardleft)
					reglcgen(&nod2, l, Z);
				else
					nod2 = *l;
				regalloc(&nod1, l, nn);
				cgen(&nod2, &nod1);
				regalloc(&nod, l, nn);
				zeroregm(&nod);
				gins(ACMPL, &nod1, nodconst(c));
				gins(ASBBL, nodconst(-1), &nod);
				regfree(&nod1);
				goto havev;
			}
		}

		if(o == OASMUL) {
			/* should favour AX */
			regalloc(&nod, l, nn);
			if(r->complex >= FNX) {
				regalloc(&nod1, r, Z);
				cgen(r, &nod1);
				r = &nod1;
			}
			if(hardleft)
				reglcgen(&nod2, l, Z);
			else
				nod2 = *l;
			cgen(&nod2, &nod);
			if(r->addable < INDEXED || hardconst(r)) {
				if(r->complex < FNX) {
					regalloc(&nod1, r, Z);
					cgen(r, &nod1);
				}
				gopcode(OASMUL, n->type, &nod1, &nod);
				regfree(&nod1);
			}
			else
				gopcode(OASMUL, n->type, r, &nod);
			if(r == &nod1)
				regfree(r);
			gmove(&nod, &nod2);
			if(nn != Z)
				gmove(&nod, nn);
			regfree(&nod);
			if(hardleft)
				regfree(&nod2);
			break;
		}

		/*
		 * get nod to be D_AX
		 * get nod1 to be D_DX
		 */
		if(nodreg(&nod, nn, D_AX)) {
			regsalloc(&nod2, n);
			gmove(&nod, &nod2);
			v = reg[D_AX];
			reg[D_AX] = 0;

			if(isreg(l, D_AX)) {
				nod3 = *n;
				nod3.left = &nod2;
				cgen(&nod3, nn);
			} else
			if(isreg(r, D_AX)) {
				nod3 = *n;
				nod3.right = &nod2;
				cgen(&nod3, nn);
			} else
				cgen(n, nn);

			gmove(&nod2, &nod);
			reg[D_AX] = v;
			break;
		}
		if(nodreg(&nod1, nn, D_DX)) {
			regsalloc(&nod2, n);
			gmove(&nod1, &nod2);
			v = reg[D_DX];
			reg[D_DX] = 0;

			if(isreg(l, D_DX)) {
				nod3 = *n;
				nod3.left = &nod2;
				cgen(&nod3, nn);
			} else
			if(isreg(r, D_DX)) {
				nod3 = *n;
				nod3.right = &nod2;
				cgen(&nod3, nn);
			} else
				cgen(n, nn);

			gmove(&nod2, &nod1);
			reg[D_DX] = v;
			break;
		}
		reg[D_AX]++;
		reg[D_DX]++;

		if(l->complex >= r->complex) {
			if(hardleft)
				reglcgen(&nod2, l, Z);
			else
				nod2 = *l;
			cgen(&nod2, &nod);
			if(r->op == OCONST && typechl[r->type->etype]) {
				switch(o) {
				case OASDIV:
					sdivgen(&nod2, r, &nod, &nod1);
					goto divdone;
				case OASLDIV:
					udivgen(&nod2, r, &nod, &nod1);
				divdone:
					gmove(&nod1, &nod2);
					if(nn != Z)
						gmove(&nod1, nn);
					goto freelxaxdx;
				}
			}
			if(o == OASDIV || o == OASMOD)
				gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z);
			if(o == OASLDIV || o == OASLMOD)
				zeroregm(&nod1);
			if(r->addable < INDEXED || r->op == OCONST ||
			   !typeil[r->type->etype]) {
				regalloc(&nod3, r, Z);
				cgen(r, &nod3);
				gopcode(o, l->type, &nod3, Z);
				regfree(&nod3);
			} else
				gopcode(o, n->type, r, Z);
		} else {
			regalloc(&nod3, r, Z);
			cgen(r, &nod3);
			if(hardleft)
				reglcgen(&nod2, l, Z);
			else
				nod2 = *l;
			cgen(&nod2, &nod);
			if(o == OASDIV || o == OASMOD)
				gins(typechl[l->type->etype]? ACDQ: ACQO, Z, Z);
			if(o == OASLDIV || o == OASLMOD)
				zeroregm(&nod1);
			gopcode(o, l->type, &nod3, Z);
			regfree(&nod3);
		}
		if(o == OASMOD || o == OASLMOD) {
			gmove(&nod1, &nod2);
			if(nn != Z)
				gmove(&nod1, nn);
		} else {
			gmove(&nod, &nod2);
			if(nn != Z)
				gmove(&nod, nn);
		}
	freelxaxdx:
		if(hardleft)
			regfree(&nod2);
		regfree(&nod);
		regfree(&nod1);
		break;

	fop:
		if(l->complex >= r->complex) {
			regalloc(&nod, l, nn);
			cgen(l, &nod);
			if(r->addable < INDEXED) {
				regalloc(&nod1, r, Z);
				cgen(r, &nod1);
				gopcode(o, n->type, &nod1, &nod);
				regfree(&nod1);
			} else
				gopcode(o, n->type, r, &nod);
		} else {
			/* TO DO: could do better with r->addable >= INDEXED */
			regalloc(&nod1, r, Z);
			cgen(r, &nod1);
			regalloc(&nod, l, nn);
			cgen(l, &nod);
			gopcode(o, n->type, &nod1, &nod);
			regfree(&nod1);
		}
		gmove(&nod, nn);
		regfree(&nod);
		break;

	asbitop:
		regalloc(&nod4, n, nn);
		if(l->complex >= r->complex) {
			bitload(l, &nod, &nod1, &nod2, &nod4);
			regalloc(&nod3, r, Z);
			cgen(r, &nod3);
		} else {
			regalloc(&nod3, r, Z);
			cgen(r, &nod3);
			bitload(l, &nod, &nod1, &nod2, &nod4);
		}
		gmove(&nod, &nod4);

		{	/* TO DO: check floating point source */
			Node onod;

			/* incredible grot ... */
			onod = nod3;
			onod.op = o;
			onod.complex = 2;
			onod.addable = 0;
			onod.type = tfield;
			onod.left = &nod4;
			onod.right = &nod3;
			cgen(&onod, Z);
		}
		regfree(&nod3);
		gmove(&nod4, &nod);
		regfree(&nod4);
		bitstore(l, &nod, &nod1, &nod2, nn);
		break;

	case OADDR:
		if(nn == Z) {
			nullwarn(l, Z);
			break;
		}
		lcgen(l, nn);
		break;

	case OFUNC:
		if(l->complex >= FNX) {
			if(l->op != OIND)
				diag(n, "bad function call");

			regret(&nod, l->left);
			cgen(l->left, &nod);
			regsalloc(&nod1, l->left);
			gmove(&nod, &nod1);
			regfree(&nod);

			nod = *n;
			nod.left = &nod2;
			nod2 = *l;
			nod2.left = &nod1;
			nod2.complex = 1;
			cgen(&nod, nn);

			return;
		}
		o = 0;
		if(REGARG >= 0)
			o = reg[REGARG];
		gargs(r, &nod, &nod1);
		if(l->addable < INDEXED) {
			reglcgen(&nod, l, nn);
			nod.op = OREGISTER;
			gopcode(OFUNC, n->type, Z, &nod);
			regfree(&nod);
		} else
			gopcode(OFUNC, n->type, Z, l);
		if(REGARG >= 0)
			if(o != reg[REGARG])
				reg[REGARG]--;
		if(nn != Z) {
			regret(&nod, n);
			gmove(&nod, nn);
			regfree(&nod);
		}
		break;

	case OIND:
		if(nn == Z) {
			nullwarn(l, Z);
			break;
		}
		regialloc(&nod, n, nn);
		r = l;
		while(r->op == OADD)
			r = r->right;
		if(sconst(r)) {
			v = r->vconst;
			r->vconst = 0;
			cgen(l, &nod);
			nod.xoffset += v;
			r->vconst = v;
		} else
			cgen(l, &nod);
		regind(&nod, n);
		gmove(&nod, nn);
		regfree(&nod);
		break;

	case OEQ:
	case ONE:
	case OLE:
	case OLT:
	case OGE:
	case OGT:
	case OLO:
	case OLS:
	case OHI:
	case OHS:
		if(nn == Z) {
			nullwarn(l, r);
			break;
		}
		boolgen(n, 1, nn);
		break;

	case OANDAND:
	case OOROR:
		boolgen(n, 1, nn);
		if(nn == Z)
			patch(p, pc);
		break;

	case ONOT:
		if(nn == Z) {
			nullwarn(l, Z);
			break;
		}
		boolgen(n, 1, nn);
		break;

	case OCOMMA:
		cgen(l, Z);
		cgen(r, nn);
		break;

	case OCAST:
		if(nn == Z) {
			nullwarn(l, Z);
			break;
		}
		/*
		 * convert from types l->n->nn
		 */
		if(nocast(l->type, n->type) && nocast(n->type, nn->type)) {
			/* both null, gen l->nn */
			cgen(l, nn);
			break;
		}
		if(ewidth[n->type->etype] < ewidth[l->type->etype]){
			if(l->type->etype == TIND && typechlp[n->type->etype])
				warn(n, "conversion of pointer to shorter integer");
		}else if(0){
			if(nocast(n->type, nn->type) || castup(n->type, nn->type)){
				if(typefd[l->type->etype] != typefd[nn->type->etype])
					regalloc(&nod, l, nn);
				else
					regalloc(&nod, nn, nn);
				cgen(l, &nod);
				gmove(&nod, nn);
				regfree(&nod);
				break;
			}
		}
		regalloc(&nod, l, nn);
		cgen(l, &nod);
		regalloc(&nod1, n, &nod);
		gmove(&nod, &nod1);
		gmove(&nod1, nn);
		regfree(&nod1);
		regfree(&nod);
		break;

	case ODOT:
		sugen(l, nodrat, l->type->width);
		if(nn == Z)
			break;
		warn(n, "non-interruptable temporary");
		nod = *nodrat;
		if(!r || r->op != OCONST) {
			diag(n, "DOT and no offset");
			break;
		}
		nod.xoffset += (int32)r->vconst;
		nod.type = n->type;
		cgen(&nod, nn);
		break;

	case OCOND:
		bcgen(l, 1);
		p1 = p;
		cgen(r->left, nn);
		gbranch(OGOTO);
		patch(p1, pc);
		p1 = p;
		cgen(r->right, nn);
		patch(p1, pc);
		break;

	case OPOSTINC:
	case OPOSTDEC:
		v = 1;
		if(l->type->etype == TIND)
			v = l->type->link->width;
		if(o == OPOSTDEC)
			v = -v;
		if(l->op == OBIT)
			goto bitinc;
		if(nn == Z)
			goto pre;

		if(hardleft)
			reglcgen(&nod, l, Z);
		else
			nod = *l;

		gmove(&nod, nn);
		if(typefd[n->type->etype]) {
			regalloc(&nod1, l, Z);
			gmove(&nod, &nod1);
			if(v < 0)
				gopcode(OSUB, n->type, nodfconst(-v), &nod1);
			else
				gopcode(OADD, n->type, nodfconst(v), &nod1);
			gmove(&nod1, &nod);
			regfree(&nod1);
		} else
			gopcode(OADD, n->type, nodconst(v), &nod);
		if(hardleft)
			regfree(&nod);
		break;

	case OPREINC:
	case OPREDEC:
		v = 1;
		if(l->type->etype == TIND)
			v = l->type->link->width;
		if(o == OPREDEC)
			v = -v;
		if(l->op == OBIT)
			goto bitinc;

	pre:
		if(hardleft)
			reglcgen(&nod, l, Z);
		else
			nod = *l;
		if(typefd[n->type->etype]) {
			regalloc(&nod1, l, Z);
			gmove(&nod, &nod1);
			if(v < 0)
				gopcode(OSUB, n->type, nodfconst(-v), &nod1);
			else
				gopcode(OADD, n->type, nodfconst(v), &nod1);
			gmove(&nod1, &nod);
			regfree(&nod1);
		} else
			gopcode(OADD, n->type, nodconst(v), &nod);
		if(nn != Z)
			gmove(&nod, nn);
		if(hardleft)
			regfree(&nod);
		break;

	bitinc:
		if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
			bitload(l, &nod, &nod1, &nod2, Z);
			gmove(&nod, nn);
			gopcode(OADD, tfield, nodconst(v), &nod);
			bitstore(l, &nod, &nod1, &nod2, Z);
			break;
		}
		bitload(l, &nod, &nod1, &nod2, nn);
		gopcode(OADD, tfield, nodconst(v), &nod);
		bitstore(l, &nod, &nod1, &nod2, nn);
		break;
	}
done:
	cursafe = curs;
}
Exemplo n.º 9
0
/*-----------------*
 * Function getsam |
 *-----------------*
 | Generates a gene genealogy for a locus.
*/
int gensam(struct params *pparam, char **list, int **pnbvariant, int *pS) 
{
  int nsegs=0, k=0, seg=0, ns=0, start=0, end=0, len=0, segsit=0, nsites=0, nsam=0;
  /* The function returns ns, the number of sgregating sites.
   * nsegs is the gametes were broken into in tracing back the history of the gametes.
   * The histories of these segments are  passed back to the calling function in the array of structures seglst[]
   */
  struct segl *seglst=NULL;
  double nsinv=0.0, tseg=0.0, tt=0.0, theta=0.0;
  void make_gametes(int, struct node*, double, int, int, char**, int, int*, int**, int*, int*);

  void inititable(int, int, int*);
  void initimatrix(int, int, int, int**);
  void biggerimatrix(int, int**);
  void biggerlist(int, char**);
  void locate(int, double, double, double*);
  //// From make_gametes ////
  void prtree(struct node*, int);
  double ttime(struct node*, int);
  int poisso(double);
  //// From streec.c ////
  struct segl*segtre_mig(struct c_params*, int*);

  nsites=pparam->cp.nsites;                 // Locus lenght available for recombination
  nsinv=1./nsites;
  seglst=segtre_mig(&(pparam->cp), &nsegs); // Generate Xove and ARGr, record # segments
  nsam=pparam->cp.nsam;                     // # chromo in the sample
  theta=pparam->mp.theta;                   // mutation rate given by user
  ns=0;                                     // # seg sites
  if(pparam->mp.treeflag)                   // Case output tree.
    {
      theta=pparam->mp.theta;
      ns=0;
      for(seg=0, k=0;k<nsegs;seg=seglst[seg].next, k++)
        {
          if((pparam->cp.r>0.0)||(pparam->cp.f>0.0))
            {
              end=(k<nsegs-1 ? seglst[seglst[seg].next].beg-1:nsites-1);
              start=seglst[seg].beg;
              len=end-start+1;
              fprintf(stdout, "[%d]", len);
            }
          prtree(seglst[seg].ptree, nsam);
          if((theta==0.0)) 
            free(seglst[seg].ptree);
        }
    }
  //--- Loop along all segments ---//
  for(seg=0, k=0;k<nsegs; seg=seglst[seg].next, k++)
    {
      end=(k<nsegs-1 ? seglst[seglst[seg].next].beg-1:nsites-1); // End of segment
      start=seglst[seg].beg;                                     // beginning of segment
      len=end-start+1;                                           // Lengh of segment
      tseg=len*(theta/nsites);                                   // Mutation rate along the segment
      tt=ttime(seglst[seg].ptree, nsam);                         // Total time in the tree for this segment
      segsit=poisso(tseg*tt);                                    // get # segsites along genealogy for the segment

      //--- Realloc memory if # segsite bigger than max previously define ---//
      if((segsit+ns)>=maxsites)
        {
          maxsites=segsit+ns+SITESINC;                          // Bigger Max sites 
          biggerlist(nsam, list);                               // Increase list of haplotype
          typeseg=(int*)realloc(typeseg, maxsites*sizeof(int)); // Increase # seg sites in typeseg
          biggerimatrix(pparam->cp.npop+1, pnbvariant);         // Increase matrix of variant
        }

      //--- Initialize table of variant and segType ---//
      initimatrix(ns, ns+segsit, pparam->cp.npop+1, pnbvariant);
      inititable(ns, segsit+ns, typeseg);
      make_gametes(nsam, seglst[seg].ptree, tt, segsit, ns, list, pparam->cp.npop, pparam->cp.config, pnbvariant, typeseg, pS); // Make gametes (Put segsites on gene genealogy)
      free(seglst[seg].ptree);                                   // Free memory
      ns+=segsit;                                                // Total # seg sites
    }
  for(k=0;k<nsam;k++) list[k][ns]='\0';                          // End of haplotype strings
  return(ns);                                                    // Total # segsites
}// End Gensam
Exemplo n.º 10
0
Arquivo: ms.c Projeto: EdRice4/P2C2M
int
gensam( char **list, double *pprobss, double *ptmrca, double *pttot )
{
    int nsegs, h, i, k, j, seg, ns, start, end, len, segsit ;
    struct segl *seglst, *segtre_mig(struct c_params *p, int *nsegs ) ; /* used to be: [MAXSEG];  */
    double nsinv,  tseg, tt, ttime(struct node *, int nsam), ttimemf(struct node *, int nsam, int mfreq) ;
    double *pk;
    int *ss;
    int segsitesin,nsites;
    double theta, es ;
    int nsam, mfreq ;
    void prtree( struct node *ptree, int nsam);
    void make_gametes(int nsam, int mfreq,  struct node *ptree, double tt, int newsites, int ns, char **list );
    void ndes_setup( struct node *, int nsam );


    nsites = pars.cp.nsites ;
    nsinv = 1./nsites;
    seglst = segtre_mig(&(pars.cp),  &nsegs ) ;

    nsam = pars.cp.nsam;
    segsitesin = pars.mp.segsitesin ;
    theta = pars.mp.theta ;
    mfreq = pars.mp.mfreq ;

    if( pars.mp.treeflag ) {
        ns = 0 ;
        for( seg=0, k=0; k<nsegs; seg=seglst[seg].next, k++) {
            if( (pars.cp.r > 0.0 ) || (pars.cp.f > 0.0) ) {
                end = ( k<nsegs-1 ? seglst[seglst[seg].next].beg -1 : nsites-1 );
                start = seglst[seg].beg ;
                len = end - start + 1 ;
                fprintf(stdout,"[%d]", len);
            }
            prtree( seglst[seg].ptree, nsam ) ;
            if( (segsitesin == 0) && ( theta == 0.0 ) && ( pars.mp.timeflag == 0 ) )
                free(seglst[seg].ptree) ;
        }
    }

    if( pars.mp.timeflag ) {
        tt = 0.0 ;
        for( seg=0, k=0; k<nsegs; seg=seglst[seg].next, k++) {
            if( mfreq > 1 ) ndes_setup( seglst[seg].ptree, nsam );
            end = ( k<nsegs-1 ? seglst[seglst[seg].next].beg -1 : nsites-1 );
            start = seglst[seg].beg ;
            if( (nsegs==1) || ( ( start <= nsites/2) && ( end >= nsites/2 ) ) )
                *ptmrca = (seglst[seg].ptree + 2*nsam-2) -> time ;
            len = end - start + 1 ;
            tseg = len/(double)nsites ;
            if( mfreq == 1 ) tt += ttime(seglst[seg].ptree,nsam)*tseg ;
            else tt += ttimemf(seglst[seg].ptree,nsam, mfreq)*tseg ;
            if( (segsitesin == 0) && ( theta == 0.0 )  )
                free(seglst[seg].ptree) ;
        }
        *pttot = tt ;
    }

    if( (segsitesin == 0) && ( theta > 0.0)   ) {
        ns = 0 ;
        for( seg=0, k=0; k<nsegs; seg=seglst[seg].next, k++) {
            if( mfreq > 1 ) ndes_setup( seglst[seg].ptree, nsam );
            end = ( k<nsegs-1 ? seglst[seglst[seg].next].beg -1 : nsites-1 );
            start = seglst[seg].beg ;
            len = end - start + 1 ;
            tseg = len*(theta/nsites) ;
            if( mfreq == 1) tt = ttime(seglst[seg].ptree, nsam);
            else tt = ttimemf(seglst[seg].ptree, nsam, mfreq );
            segsit = poisso( tseg*tt );
            if( (segsit + ns) >= maxsites ) {
                maxsites = segsit + ns + SITESINC ;
                posit = (double *)realloc(posit, maxsites*sizeof(double) ) ;
                biggerlist(nsam, list) ;
            }
            make_gametes(nsam,mfreq,seglst[seg].ptree,tt, segsit, ns, list );
            free(seglst[seg].ptree) ;
            locate(segsit,start*nsinv, len*nsinv,posit+ns);
            ns += segsit;
        }
    }
    else if( segsitesin > 0 ) {

        pk = (double *)malloc((unsigned)(nsegs*sizeof(double)));
        ss = (int *)malloc((unsigned)(nsegs*sizeof(int)));
        if( (pk==NULL) || (ss==NULL) ) perror("malloc error. gensam.2");


        tt = 0.0 ;
        for( seg=0, k=0; k<nsegs; seg=seglst[seg].next, k++) {
            if( mfreq > 1 ) ndes_setup( seglst[seg].ptree, nsam );
            end = ( k<nsegs-1 ? seglst[seglst[seg].next].beg -1 : nsites-1 );
            start = seglst[seg].beg ;
            len = end - start + 1 ;
            tseg = len/(double)nsites ;
            if( mfreq == 1 ) pk[k] = ttime(seglst[seg].ptree,nsam)*tseg ;
            else pk[k] = ttimemf(seglst[seg].ptree,nsam, mfreq)*tseg ;
            tt += pk[k] ;
        }
        if( theta > 0.0 ) {
            es = theta * tt ;
            *pprobss = exp( -es )*pow( es, (double) segsitesin) / segfac ;
        }
        if( tt > 0.0 ) {
            for (k=0; k<nsegs; k++) pk[k] /= tt ;
            mnmial(segsitesin,nsegs,pk,ss);
        }
        else
            for( k=0; k<nsegs; k++) ss[k] = 0 ;
        ns = 0 ;
        for( seg=0, k=0; k<nsegs; seg=seglst[seg].next, k++) {
            end = ( k<nsegs-1 ? seglst[seglst[seg].next].beg -1 : nsites-1 );
            start = seglst[seg].beg ;
            len = end - start + 1 ;
            tseg = len/(double)nsites;
            make_gametes(nsam,mfreq,seglst[seg].ptree,tt*pk[k]/tseg, ss[k], ns, list);

            free(seglst[seg].ptree) ;
            locate(ss[k],start*nsinv, len*nsinv,posit+ns);
            ns += ss[k] ;
        }
        free(pk);
        free(ss);

    }
    for(i=0; i<nsam; i++) list[i][ns] = '\0' ;
    return( ns ) ;
}
Exemplo n.º 11
0
void
cgenrel(Node *n, Node *nn, int inrel)
{
	Node *l, *r;
	Prog *p1;
	Node nod, nod1, nod2, nod3, nod4;
	int o, t;
	long v, curs;

	if(debug['g']) {
		prtree(nn, "cgen lhs");
		prtree(n, "cgen");
	}
	if(n == Z || n->type == T)
		return;
	if(typesu[n->type->etype]) {
		sugen(n, nn, n->type->width);
		return;
	}
	l = n->left;
	r = n->right;
	o = n->op;
	if(n->addable >= INDEXED) {
		if(nn == Z) {
			switch(o) {
			default:
				nullwarn(Z, Z);
				break;
			case OINDEX:
				nullwarn(l, r);
				break;
			}
			return;
		}
		gmove(n, nn);
		return;
	}
	curs = cursafe;

	if(n->complex >= FNX)
	if(l->complex >= FNX)
	if(r != Z && r->complex >= FNX)
	switch(o) {
	default:
		if(cond(o) && typesu[l->type->etype])
			break;

		regret(&nod, r);
		cgen(r, &nod);

		regsalloc(&nod1, r);
		gopcode(OAS, &nod, Z, &nod1);

		regfree(&nod);
		nod = *n;
		nod.right = &nod1;
		cgen(&nod, nn);
		return;

	case OFUNC:
	case OCOMMA:
	case OANDAND:
	case OOROR:
	case OCOND:
	case ODOT:
		break;
	}

	switch(o) {
	default:
		diag(n, "unknown op in cgen: %O", o);
		break;

	case ONEG:
	case OCOM:
		if(nn == Z) {
			nullwarn(l, Z);
			break;
		}
		regalloc(&nod, l, nn);
		cgen(l, &nod);
		gopcode(o, &nod, Z, &nod);
		gmove(&nod, nn);
		regfree(&nod);
		break;

	case OAS:
		if(l->op == OBIT)
			goto bitas;
		if(l->addable >= INDEXED && l->complex < FNX) {
			if(nn != Z || r->addable < INDEXED) {	/* || hardconst(r) */
				if(r->complex >= FNX && nn == Z)
					regret(&nod, r);
				else
					regalloc(&nod, r, nn);
				cgen(r, &nod);
				gmove(&nod, l);
				if(nn != Z)
					gmove(&nod, nn);
				regfree(&nod);
			} else
				gmove(r, l);
			break;
		}
		if(l->complex >= r->complex) {
			/* TO DO: see 6c for OINDEX && immconst(r) */
			reglcgen(&nod1, l, Z);
			if(r->addable >= INDEXED) {	/* && !hardconst(r) */
				gmove(r, &nod1);
				if(nn != Z)
					gmove(r, nn);
				regfree(&nod1);
				break;
			}
			regalloc(&nod, r, nn);
			cgen(r, &nod);
		} else {
			regalloc(&nod, r, nn);
			cgen(r, &nod);
			reglcgen(&nod1, l, Z);
		}
		gmove(&nod, &nod1);
		regfree(&nod);
		regfree(&nod1);
		break;

	bitas:
		n = l->left;
		regalloc(&nod, r, nn);
		if(l->complex >= r->complex) {
			reglcgen(&nod1, n, Z);
			cgen(r, &nod);
		} else {
			cgen(r, &nod);
			reglcgen(&nod1, n, Z);
		}
		regalloc(&nod2, n, Z);
		gopcode(OAS, &nod1, Z, &nod2);
		bitstore(l, &nod, &nod1, &nod2, nn);
		break;

	case OBIT:
		if(nn == Z) {
			nullwarn(l, Z);
			break;
		}
		bitload(n, &nod, Z, Z, nn);
		gopcode(OAS, &nod, Z, nn);
		regfree(&nod);
		break;

	case ODIV:
	case OMOD:
		if(nn != Z)
		if((t = vlog(r)) >= 0) {
			/* signed div/mod by constant power of 2 */
			cgen(l, nn);
			gopcode(OGE, nodconst(0), nn, Z);
			p1 = p;
			if(o == ODIV) {
				gopcode(OADD, nodconst((1<<t)-1), Z, nn);
				patch(p1, pc);
				gopcode(OASHR, nodconst(t), Z, nn);
			} else {
				gopcode(ONEG, nn, Z, nn);
				gopcode(OAND, nodconst((1<<t)-1), Z, nn);
				gopcode(ONEG, nn, Z, nn);
				gbranch(OGOTO);
				patch(p1, pc);
				p1 = p;
				gopcode(OAND, nodconst((1<<t)-1), Z, nn);
				patch(p1, pc);
			}
			break;
		}
		goto muldiv;

	case OXOR:
#ifdef NOTYET
		if(nn != Z)
		if(r->op == OCONST && r->vconst == -1){
			cgen(l, nn);
			gopcode(OCOM, nn, Z, nn);
			break;
		}
#endif

	case OSUB:
	case OADD:
	case OAND:
	case OOR:
	case OLSHR:
	case OASHL:
	case OASHR:
		/*
		 * immediate operands
		 */
		if(nn != Z)
		if(r->op == OCONST)
		if(!typefd[n->type->etype]) {
			cgen(l, nn);
			if(r->vconst == 0)
			if(o != OAND)
				break;
			if(nn != Z)
				gopcode(o, r, Z, nn);
			break;
		}

	case OLMUL:
	case OLDIV:
	case OLMOD:
	case OMUL:
	muldiv:
		if(nn == Z) {
			nullwarn(l, r);
			break;
		}
		if(o == OMUL || o == OLMUL) {
			if(mulcon(n, nn))
				break;
		}
		if(l->complex >= r->complex) {
			regalloc(&nod, l, nn);
			cgen(l, &nod);
			regalloc(&nod1, l, Z);		/* note: l used for type, so shifts work! */
			cgen(r, &nod1);
			gopcode(o, &nod1, Z, &nod);
		} else {
			regalloc(&nod, l, nn);		/* note: l used for type, so shifts work! */
			cgen(r, &nod);
			regalloc(&nod1, l, Z);
			cgen(l, &nod1);
			gopcode(o, &nod, &nod1, &nod);
		}
		gopcode(OAS, &nod, Z, nn);
		regfree(&nod);
		regfree(&nod1);
		break;

	case OASLSHR:
	case OASASHL:
	case OASASHR:
	case OASAND:
	case OASADD:
	case OASSUB:
	case OASXOR:
	case OASOR:
		if(l->op == OBIT)
			goto asbitop;
		if(r->op == OCONST)
		if(!typefd[r->type->etype])
		if(!typefd[n->type->etype]) {
			if(l->addable < INDEXED)
				reglcgen(&nod2, l, Z);
			else
				nod2 = *l;
			regalloc(&nod, l, nn);		/* note: l used for type, so shifts work! */
			gopcode(OAS, &nod2, Z, &nod);
			gopcode(o, r, Z, &nod);
			gopcode(OAS, &nod, Z, &nod2);
	
			regfree(&nod);
			if(l->addable < INDEXED)
				regfree(&nod2);
			break;
		}

	case OASLMUL:
	case OASLDIV:
	case OASLMOD:
	case OASMUL:
	case OASDIV:
	case OASMOD:
		if(l->op == OBIT)
			goto asbitop;
		if(l->complex >= r->complex) {
			if(l->addable < INDEXED)
				reglcgen(&nod2, l, Z);
			else
				nod2 = *l;
			regalloc(&nod, n, nn);
			cgen(r, &nod);
		} else {
			regalloc(&nod, n, nn);
			cgen(r, &nod);
			if(l->addable < INDEXED)
				reglcgen(&nod2, l, Z);
			else
				nod2 = *l;
		}
		regalloc(&nod1, n, Z);
		gopcode(OAS, &nod2, Z, &nod1);
		if(nod1.type->etype != nod.type->etype){
			regalloc(&nod3, &nod, Z);
			gmove(&nod1, &nod3);
			regfree(&nod1);
			nod1 = nod3;
		}
		gopcode(o, &nod, &nod1, &nod);
		gmove(&nod, &nod2);
		if(nn != Z)
			gmove(&nod, nn);
		regfree(&nod);
		regfree(&nod1);
		if(l->addable < INDEXED)
			regfree(&nod2);
		break;

	asbitop:
		regalloc(&nod4, n, nn);
		regalloc(&nod3, r, Z);
		if(l->complex >= r->complex) {
			bitload(l, &nod, &nod1, &nod2, &nod4);
			cgen(r, &nod3);
		} else {
			cgen(r, &nod3);
			bitload(l, &nod, &nod1, &nod2, &nod4);
		}
		gmove(&nod, &nod4);
		gopcode(o, &nod3, Z, &nod4);
		regfree(&nod3);
		gmove(&nod4, &nod);
		regfree(&nod4);
		bitstore(l, &nod, &nod1, &nod2, nn);
		break;

	case OADDR:
		if(nn == Z) {
			nullwarn(l, Z);
			break;
		}
		lcgen(l, nn);
		break;

	case OFUNC:
		l = uncomma(l);
		if(l->complex >= FNX) {
			if(l->op != OIND)
				diag(n, "bad function call");

			regret(&nod, l->left);
			cgen(l->left, &nod);
			regsalloc(&nod1, l->left);
			gopcode(OAS, &nod, Z, &nod1);
			regfree(&nod);

			nod = *n;
			nod.left = &nod2;
			nod2 = *l;
			nod2.left = &nod1;
			nod2.complex = 1;
			cgen(&nod, nn);

			return;
		}
		if(REGARG >= 0)
			o = reg[REGARG];
		gargs(r, &nod, &nod1);
		if(l->addable < INDEXED) {
			reglcgen(&nod, l, Z);
			gopcode(OFUNC, Z, Z, &nod);
			regfree(&nod);
		} else
			gopcode(OFUNC, Z, Z, l);
		if(REGARG >= 0)
			if(o != reg[REGARG])
				reg[REGARG]--;
		if(nn != Z) {
			regret(&nod, n);
			gopcode(OAS, &nod, Z, nn);
			regfree(&nod);
		}
		break;

	case OIND:
		if(nn == Z) {
			nullwarn(l, Z);
			break;
		}
		regialloc(&nod, n, nn);
		r = l;
		while(r->op == OADD)
			r = r->right;
		if(sconst(r) && (v = r->vconst+nod.xoffset) >= -4096 && v < 4096) {
			v = r->vconst;
			r->vconst = 0;
			cgen(l, &nod);
			nod.xoffset += v;
			r->vconst = v;
		} else
			cgen(l, &nod);
		regind(&nod, n);
		gopcode(OAS, &nod, Z, nn);
		regfree(&nod);
		break;

	case OEQ:
	case ONE:
	case OLE:
	case OLT:
	case OGE:
	case OGT:
	case OLO:
	case OLS:
	case OHI:
	case OHS:
		if(nn == Z) {
			nullwarn(l, r);
			break;
		}
		boolgen(n, 1, nn);
		break;

	case OANDAND:
	case OOROR:
		boolgen(n, 1, nn);
		if(nn == Z)
			patch(p, pc);
		break;

	case ONOT:
		if(nn == Z) {
			nullwarn(l, Z);
			break;
		}
		boolgen(n, 1, nn);
		break;

	case OCOMMA:
		cgen(l, Z);
		cgen(r, nn);
		break;

	case OCAST:
		if(nn == Z) {
			nullwarn(l, Z);
			break;
		}
		/*
		 * convert from types l->n->nn
		 */
		if(nocast(l->type, n->type) && nocast(n->type, nn->type)) {
			/* both null, gen l->nn */
			cgen(l, nn);
			break;
		}
		if(ewidth[n->type->etype] < ewidth[l->type->etype]){
			if(l->type->etype == TIND && typechlp[n->type->etype])
				warn(n, "conversion of pointer to shorter integer");
		}else if(0){
			if(nocast(n->type, nn->type) || castup(n->type, nn->type)){
				if(typefd[l->type->etype] != typefd[nn->type->etype])
					regalloc(&nod, l, nn);
				else
					regalloc(&nod, nn, nn);
				cgen(l, &nod);
				gmove(&nod, nn);
				regfree(&nod);
				break;
			}
		}
		regalloc(&nod, l, nn);
		cgen(l, &nod);
		regalloc(&nod1, n, &nod);
		if(inrel)
			gmover(&nod, &nod1);
		else
			gopcode(OAS, &nod, Z, &nod1);
		gopcode(OAS, &nod1, Z, nn);
		regfree(&nod1);
		regfree(&nod);
		break;

	case ODOT:
		sugen(l, nodrat, l->type->width);
		if(nn != Z) {
			warn(n, "non-interruptable temporary");
			nod = *nodrat;
			if(!r || r->op != OCONST) {
				diag(n, "DOT and no offset");
				break;
			}
			nod.xoffset += (long)r->vconst;
			nod.type = n->type;
			cgen(&nod, nn);
		}
		break;

	case OCOND:
		bcgen(l, 1);
		p1 = p;
		cgen(r->left, nn);
		gbranch(OGOTO);
		patch(p1, pc);
		p1 = p;
		cgen(r->right, nn);
		patch(p1, pc);
		break;

	case OPOSTINC:
	case OPOSTDEC:
		v = 1;
		if(l->type->etype == TIND)
			v = l->type->link->width;
		if(o == OPOSTDEC)
			v = -v;
		if(l->op == OBIT)
			goto bitinc;
		if(nn == Z)
			goto pre;

		if(l->addable < INDEXED)
			reglcgen(&nod2, l, Z);
		else
			nod2 = *l;

		regalloc(&nod, l, nn);
		gopcode(OAS, &nod2, Z, &nod);
		regalloc(&nod1, l, Z);
		if(typefd[l->type->etype]) {
			regalloc(&nod3, l, Z);
			if(v < 0) {
				gopcode(OAS, nodfconst(-v), Z, &nod3);
				gopcode(OSUB, &nod3, &nod, &nod1);
			} else {
				gopcode(OAS, nodfconst(v), Z, &nod3);
				gopcode(OADD, &nod3, &nod, &nod1);
			}
			regfree(&nod3);
		} else
			gopcode(OADD, nodconst(v), &nod, &nod1);
		gopcode(OAS, &nod1, Z, &nod2);

		regfree(&nod);
		regfree(&nod1);
		if(l->addable < INDEXED)
			regfree(&nod2);
		break;

	case OPREINC:
	case OPREDEC:
		v = 1;
		if(l->type->etype == TIND)
			v = l->type->link->width;
		if(o == OPREDEC)
			v = -v;
		if(l->op == OBIT)
			goto bitinc;

	pre:
		if(l->addable < INDEXED)
			reglcgen(&nod2, l, Z);
		else
			nod2 = *l;

		regalloc(&nod, l, nn);
		gopcode(OAS, &nod2, Z, &nod);
		if(typefd[l->type->etype]) {
			regalloc(&nod3, l, Z);
			if(v < 0) {
				gopcode(OAS, nodfconst(-v), Z, &nod3);
				gopcode(OSUB, &nod3, Z, &nod);
			} else {
				gopcode(OAS, nodfconst(v), Z, &nod3);
				gopcode(OADD, &nod3, Z, &nod);
			}
			regfree(&nod3);
		} else
			gopcode(OADD, nodconst(v), Z, &nod);
		gopcode(OAS, &nod, Z, &nod2);
		if(nn && l->op == ONAME)	/* in x=++i, emit USED(i) */
			gins(ANOP, l, Z);

		regfree(&nod);
		if(l->addable < INDEXED)
			regfree(&nod2);
		break;

	bitinc:
		if(nn != Z && (o == OPOSTINC || o == OPOSTDEC)) {
			bitload(l, &nod, &nod1, &nod2, Z);
			gopcode(OAS, &nod, Z, nn);
			gopcode(OADD, nodconst(v), Z, &nod);
			bitstore(l, &nod, &nod1, &nod2, Z);
			break;
		}
		bitload(l, &nod, &nod1, &nod2, nn);
		gopcode(OADD, nodconst(v), Z, &nod);
		bitstore(l, &nod, &nod1, &nod2, nn);
		break;
	}
	cursafe = curs;
	return;
}
Exemplo n.º 12
0
Arquivo: cgen.c Projeto: 8l/inferno
void
lcgen(Node *n, int result, Node *nn)
{
	Node rn;
	Prog *p1;
	int lg;

	if(n == Z || n->type == T)
		return;
	if(debug['g']) {
		if(result == D_TREE)
			prtree(nn, "result");
		else
			print("result = %R\n", result);
		prtree(n, "lcgen");
	}
	if(nn == Z) {
		nn = &rn;
		nn->type = types[TIND];
	}
	switch(n->op) {
	case OCOMMA:
		cgen(n->left, D_NONE, n->left);
		doinc(n->left, POST);
		doinc(n->right, PRE);
		lcgen(n->right, result, nn);
		break;

	case OCOND:
		doinc(n->left, PRE);
		boolgen(n->left, 1, D_NONE, Z, n->left);
		p1 = p;

		inargs++;
		doinc(n->right->left, PRE);
		lcgen(n->right->left, result, nn);
		doinc(n->right->left, POST);
		gbranch(OGOTO);
		patch(p1, pc);
		p1 = p;

		doinc(n->right->right, PRE);
		lcgen(n->right->right, result, nn);
		doinc(n->right->right, POST);
		patch(p1, pc);
		inargs--;
		break;

	case OIND:
		if(n->addable >= INDEXED) {
			if(result >= D_A0 && result < D_A0+NREG) {
				gopcode(OADDR, types[TLONG], D_TREE, n, result, nn);
				break;
			}
			if(result == D_TOS) {
				gopcode(OADDR, types[TSHORT], D_NONE, nn, D_TREE, n);
				break;
			}
		}
		cgen(n->left, result, nn);
		break;

	default:
		if(n->addable < INDEXED) {
			diag(n, "unknown op in lcgen: %O", n->op);
			break;
		}
		if(result >= D_A0 && result < D_A0+NREG) {
			gopcode(OADDR, types[TLONG], D_TREE, n, result, nn);
			break;
		}
		if(result == D_TOS) {
			gopcode(OADDR, types[TSHORT], D_NONE, nn, D_TREE, n);
			break;
		}
		lg = regaddr(result);
		gopcode(OADDR, types[TLONG], D_TREE, n, lg, nn);
		gopcode(OAS, nn->type, lg, nn, result, nn);
		regfree(lg);
		break;
	}
}
Exemplo n.º 13
0
Arquivo: cgen.c Projeto: 8l/inferno
void
cgen(Node *n, int result, Node *nn)
{
	Node *l, *r, nod;
	int lg, rg, xg, yg, g, o;
	long v;
	Prog *p1;

	if(n == Z || n->type == T)
		return;
	if(typesuv[n->type->etype]) {
		sugen(n, result, nn, n->type->width);
		return;
	}
	if(debug['g']) {
		if(result == D_TREE)
			prtree(nn, "result");
		else
			print("result = %R\n", result);
		prtree(n, "cgen");
	}
	l = n->left;
	r = n->right;
	o = n->op;
	if(n->addable >= INDEXED) {
		if(result == D_NONE) {
			if(nn == Z)
				switch(o) {
				default:
					nullwarn(Z, Z);
					break;
				case OINDEX:
					nullwarn(l, r);
					break;
				}
			return;
		}
		gmove(n->type, nn->type, D_TREE, n, result, nn);
		return;
	}

	v = 0; /* set */
	switch(o) {
	default:
		diag(n, "unknown op in cgen: %O", o);
		break;

	case OAS:
		if(l->op == OBIT)
			goto bitas;
		/*
		 * recursive use of result
		 */
		if(result == D_NONE)
		if(l->addable > INDEXED)
		if(l->complex < FNX) {
			cgen(r, D_TREE, l);
			break;
		}

		/*
		 * function calls on both sides
		 */
		if(l->complex >= FNX && r->complex >= FNX) {
			cgen(r, D_TOS, r);
			v = argoff;
			lg = regaddr(result);
			lcgen(l, lg, Z);
			lg |= I_INDIR;
			adjsp(v - argoff);
			gmove(r->type, l->type, D_TOS, r, lg, l);
			if(result != D_NONE)
				gmove(l->type, nn->type, lg, l, result, nn);
			regfree(lg);
			break;
		}

		rg = D_TREE;
		lg = D_TREE;
		if(r->complex >= l->complex) {
			/*
			 * right side before left
			 */
			if(result != D_NONE) {
				rg = regalloc(n->type, result);
				cgen(r, rg, n);
			} else
			if(r->complex >= FNX || r->addable < INDEXED) {
				rg = regalloc(r->type, result);
				cgen(r, rg, r);
			}
			if(l->addable < INDEXED) {
				lg = regaddr(lg);
				lcgen(l, lg, Z);
				lg |= I_INDIR;
			}
		} else {
			/*
			 * left before right
			 */
			if(l->complex >= FNX || l->addable < INDEXED) {
				lg = regaddr(lg);
				lcgen(l, lg, Z);
				lg |= I_INDIR;
			}
			if(result != D_NONE) {
				rg = regalloc(n->type, result);
				cgen(r, rg, n);
			} else
			if(r->addable < INDEXED) {
				rg = regalloc(r->type, result);
				cgen(r, rg, r);
			}
		}
		if(result != D_NONE) {
			gmove(n->type, l->type, rg, r, lg, l);
			gmove(n->type, nn->type, rg, r, result, nn);
		} else
			gmove(r->type, l->type, rg, r, lg, l);
		regfree(lg);
		regfree(rg);
		break;

	bitas:
		n = l->left;
		rg = regalloc(tfield, result);
		if(l->complex >= r->complex) {
			lg = regaddr(D_NONE);
			lcgen(n, lg, Z);
			lg |= I_INDIR;
			cgen(r, rg, r);
		} else {
			cgen(r, rg, r);
			lg = regaddr(D_NONE);
			lcgen(n, lg, Z);
			lg |= I_INDIR;
		}
		g = regalloc(n->type, D_NONE);
		gmove(l->type, l->type, lg, l, g, l);
		bitstore(l, rg, lg, g, result, nn);
		break;

	case OBIT:
		if(result == D_NONE) {
			nullwarn(l, Z);
			break;
		}
		g = bitload(n, D_NONE, D_NONE, result, nn);
		gopcode(OAS, nn->type, g, n, result, nn);
		regfree(g);
		break;

	case ODOT:
		sugen(l, D_TREE, nodrat, l->type->width);
		if(result != D_NONE) {
			warn(n, "non-interruptable temporary");
			nod = *nodrat;
			if(!r || r->op != OCONST) {
				diag(n, "DOT and no offset");
				break;
			}
			nod.xoffset += r->vconst;
			nod.type = n->type;
			cgen(&nod, result, nn);
		}
		break;

	case OASLDIV:
	case OASLMOD:
	case OASDIV:
	case OASMOD:
		if(l->op == OBIT)
			goto asbitop;
		if(typefd[n->type->etype])
			goto asbinop;
		rg = D_TREE;
		if(l->complex >= FNX || r->complex >= FNX) {
			rg = D_TOS;
			cgen(r, rg, r);
			v = argoff;
		} else
		if(r->addable < INDEXED) {
			rg = regalloc(n->type, D_NONE);
			cgen(r, rg, r);
		}
		lg = D_TREE;
		if(!simplv(l)) {
			lg = regaddr(D_NONE);
			lcgen(l, lg, Z);	/* destroys register optimization */
			lg |= I_INDIR;
		}
		g = regpair(result);
		gmove(l->type, n->type, lg, l, g, n);
		if(rg == D_TOS)
			adjsp(v - argoff);
		gopcode(o, n->type, rg, r, g, n);
		if(o == OASLMOD || o == OASMOD)
			gmove(n->type, l->type, g+1, n, lg, l);
		else
			gmove(n->type, l->type, g, n, lg, l);
		if(result != D_NONE)
		if(o == OASLMOD || o == OASMOD)
			gmove(n->type, nn->type, g+1, n, result, nn);
		else
			gmove(n->type, nn->type, g, n, result, nn);
		regfree(g);
		regfree(g+1);
		regfree(lg);
		regfree(rg);
		break;

	case OASXOR:
	case OASAND:
	case OASOR:
		if(l->op == OBIT)
			goto asbitop;
		if(l->complex >= FNX ||
		   l->addable < INDEXED ||
		   result != D_NONE ||
		   typefd[n->type->etype])
			goto asbinop;
		rg = D_TREE;
		if(r->op != OCONST) {
			rg = regalloc(n->type, D_NONE);
			cgen(r, rg, r);
		}
		gopcode(o, l->type, rg, r, D_TREE, l);
		regfree(rg);
		break;

	case OASADD:
	case OASSUB:
		if(l->op == OBIT ||
		   l->complex >= FNX ||
		   l->addable < INDEXED ||
		   result != D_NONE ||
		   typefd[n->type->etype])
			goto asbinop;
		v = vconst(r);
		if(v > 0 && v <= 8) {
			gopcode(o, n->type, D_TREE, r, D_TREE, l);
			break;
		}
		rg = regalloc(n->type, D_NONE);
		cgen(r, rg, r);
		gopcode(o, n->type, rg, r, D_TREE, l);
		regfree(rg);
		break;

	case OASLSHR:
	case OASASHR:
	case OASASHL:
		if(l->op == OBIT ||
		   l->complex >= FNX ||
		   l->addable < INDEXED ||
		   result != D_NONE ||
		   typefd[n->type->etype])
			goto asbinop;
		rg = D_TREE;
		v = vconst(r);
		if(v <= 0 || v > 8) {
			rg = regalloc(n->type, D_NONE);
			cgen(r, rg, r);
		}
		lg = regalloc(n->type, D_NONE);
		cgen(l, lg, l);
		gopcode(o, n->type, rg, r, lg, l);
		gmove(n->type, n->type, lg, l, D_TREE, l);
		regfree(lg);
		regfree(rg);
		break;

	case OASLMUL:
	case OASMUL:
	asbinop:
		if(l->op == OBIT)
			goto asbitop;
		rg = D_TREE;
		if(l->complex >= FNX || r->complex >= FNX) {
			rg = D_TOS;
			cgen(r, rg, r);
			v = argoff;
		} else
		if(r->addable < INDEXED) {
			rg = regalloc(n->type, D_NONE);
			cgen(r, rg, r);
		} else {
			if(o == OASLSHR || o == OASASHR || o == OASASHL) {
				v = vconst(r);
				if(v <= 0 || v > 8) {
					rg = regalloc(n->type, D_NONE);
					cgen(r, rg, r);
				}
			}
		}
		lg = D_TREE;
		if(!simplv(l)) {
			lg = regaddr(D_NONE);
			lcgen(l, lg, Z);	/* destroys register optimization */
			lg |= I_INDIR;
		}
		g = regalloc(n->type, result);
		gmove(l->type, n->type, lg, l, g, n);
		if(rg == D_TOS)
			adjsp(v - argoff);
		if(o == OASXOR)
			if(rg == D_TREE) {
				rg = regalloc(n->type, D_NONE);
				cgen(r, rg, r);
			}
		if(o == OASXOR || o == OASLSHR || o == OASASHR || o == OASASHL)
			if(rg == D_TOS) {
				rg = regalloc(n->type, D_NONE);
				gmove(n->type, n->type, D_TOS, n, rg, n);
			}
		gopcode(o, n->type, rg, r, g, n);
		gmove(n->type, l->type, g, n, lg, l);
		if(result != D_NONE)
			gmove(n->type, nn->type, g, n, result, nn);
		regfree(g);
		regfree(lg);
		regfree(rg);
		break;

	asbitop:
		rg = regaddr(D_NONE);
		lg = regalloc(tfield, D_NONE);
		if(l->complex >= r->complex) {
			g = bitload(l, lg, rg, result, nn);
			xg = regalloc(r->type, D_NONE);
			cgen(r, xg, nn);
		} else {
			xg = regalloc(r->type, D_NONE);
			cgen(r, xg, nn);
			g = bitload(l, lg, rg, result, nn);
		}

		if(!typefd[n->type->etype]) {
			if(o == OASLDIV || o == OASDIV) {
				yg = regpair(result);
				gmove(tfield, n->type, g, l, yg, n);
				gopcode(o, n->type, xg, r, yg, n);
				gmove(n->type, tfield, yg, n, g, l);
				regfree(yg);
				regfree(yg+1);

				regfree(xg);
				bitstore(l, g, rg, lg, D_NONE, nn);
				break;
			}
			if(o == OASLMOD || o == OASMOD) {
				yg = regpair(result);
				gmove(tfield, n->type, g, l, yg, n);
				gopcode(o, n->type, xg, r, yg, n);
				gmove(n->type, tfield, yg+1, n, g, l);
				regfree(yg);
				regfree(yg+1);

				regfree(xg);
				bitstore(l, g, rg, lg, D_NONE, nn);
				break;
			}
		}

		yg = regalloc(n->type, result);
		gmove(tfield, n->type, g, l, yg, n);
		gopcode(o, n->type, xg, r, yg, n);
		gmove(n->type, tfield, yg, n, g, l);
		regfree(yg);

		regfree(xg);
		bitstore(l, g, rg, lg, D_NONE, nn);
		break;

	case OCAST:
		if(result == D_NONE) {
			nullwarn(l, Z);
			break;
		}
		lg = result;
		if(l->complex >= FNX)
			lg = regret(l->type);
		lg = eval(l, lg);
		if(nocast(l->type, n->type)) {
			gmove(n->type, nn->type, lg, l, result, nn);
			regfree(lg);
			break;
		}
		if(nocast(n->type, nn->type)) {
			gmove(l->type, n->type, lg, l, result, nn);
			regfree(lg);
			break;
		}
		rg = regalloc(n->type, result);
		gmove(l->type, n->type, lg, l, rg, n);
		gmove(n->type, nn->type, rg, n, result, nn);
		regfree(rg);
		regfree(lg);
		break;

	case OCOND:
		doinc(l, PRE);
		boolgen(l, 1, D_NONE, Z, l);
		p1 = p;

		inargs++;
		doinc(r->left, PRE);
		cgen(r->left, result, nn);
		doinc(r->left, POST);
		gbranch(OGOTO);
		patch(p1, pc);
		p1 = p;

		doinc(r->right, PRE);
		cgen(r->right, result, nn);
		doinc(r->right, POST);
		patch(p1, pc);
		inargs--;
		break;

	case OIND:
		if(result == D_NONE) {
			nullwarn(l, Z);
			break;
		}
		lg = nodalloc(types[TIND], result, &nod);
		nod.lineno = n->lineno;
		if(l->op == OADD) {
			if(l->left->op == OCONST) {
				nod.xoffset += l->left->vconst;
				l = l->right;
			} else
			if(l->right->op == OCONST) {
				nod.xoffset += l->right->vconst;
				l = l->left;
			}
		}
		cgen(l, lg, l);
		gmove(n->type, nn->type, D_TREE, &nod, result, nn);
		regfree(lg);
		break;

	case OFUNC:
		v = argoff;
		inargs++;
		gargs(r);
		lg = D_TREE;
		if(l->addable < INDEXED) {
			lg = regaddr(result);
			lcgen(l, lg, Z);
			lg |= I_INDIR;
		}
		inargs--;
		doinc(r, POST);
		doinc(l, POST);
		gopcode(OFUNC, types[TCHAR], D_NONE, Z, lg, l);
		regfree(lg);
		if(inargs)
			adjsp(v - argoff);
		if(result != D_NONE) {
			lg = regret(n->type);
			gmove(n->type, nn->type, lg, n, result, nn);
		}
		break;

	case OLDIV:
	case OLMOD:
	case ODIV:
	case OMOD:
		if(result == D_NONE) {
			nullwarn(l, r);
			break;
		}
		if(typefd[n->type->etype])
			goto binop;
		if(r->addable >= INDEXED && r->complex < FNX) {
			lg = regpair(result);
			cgen(l, lg, l);
			rg = D_TREE;
		} else {
			cgen(r, D_TOS, r);
			v = argoff;
			lg = regpair(result);
			cgen(l, lg, l);
			adjsp(v - argoff);
			rg = D_TOS;
		}
		gopcode(o, n->type, rg, r, lg, l);
		if(o == OMOD || o == OLMOD)
			gmove(l->type, nn->type, lg+1, l, result, nn);
		else
			gmove(l->type, nn->type, lg, l, result, nn);
		regfree(lg);
		regfree(lg+1);
		break;

	case OMUL:
	case OLMUL:
		if(l->op == OCONST)
			if(mulcon(r, l, result, nn))
				break;
		if(r->op == OCONST)
			if(mulcon(l, r, result, nn))
				break;
		if(debug['M'])
			print("%L multiply\n", n->lineno);
		goto binop;

	case OAND:
		if(r->op == OCONST)
		if(typeil[n->type->etype])
		if(l->op == OCAST) {
			if(typec[l->left->type->etype])
			if(!(r->vconst & ~0xff)) {
				l = l->left;
				goto binop;
			}
			if(typeh[l->left->type->etype])
			if(!(r->vconst & ~0xffff)) {
				l = l->left;
				goto binop;
			}
		}
		goto binop;

	case OADD:
		if(result == D_TOS)
		if(r->addable >= INDEXED)
		if(l->op == OCONST)
		if(typeil[l->type->etype]) {
			v = l->vconst;
			if(v > -32768 && v < 32768) {
				rg = regaddr(D_NONE);
				gmove(r->type, r->type, D_TREE, r, rg, r);
				gopcode(OADDR, types[TSHORT], D_NONE, Z, rg, r);
				p->to.offset = v;
				p->to.type |= I_INDIR;
				regfree(rg);
				break;
			}
		}

	case OSUB:
		if(result == D_TOS)
		if(l->addable >= INDEXED)
		if(r->op == OCONST)
		if(typeil[r->type->etype]) {
			v = r->vconst;
			if(v > -32768 && v < 32768) {
				if(n->op == OSUB)
					v = -v;
				lg = regaddr(D_NONE);
				gmove(l->type, l->type, D_TREE, l, lg, l);
				gopcode(OADDR, types[TSHORT], D_NONE, Z, lg, l);
				p->to.offset = v;
				p->to.type |= I_INDIR;
				regfree(lg);
				break;
			}
		}
		goto binop;

	case OOR:
	case OXOR:
	binop:
		if(result == D_NONE) {
			nullwarn(l, r);
			break;
		}
		if(l->complex >= FNX && r->complex >= FNX) {
			cgen(r, D_TOS, r);
			v = argoff;
			lg = regalloc(l->type, result);
			cgen(l, lg, l);
			adjsp(v - argoff);
			if(o == OXOR) {
				rg = regalloc(r->type, D_NONE);
				gmove(r->type, r->type, D_TOS, r, rg, r);
				gopcode(o, n->type, rg, r, lg, l);
				regfree(rg);
			} else
				gopcode(o, n->type, D_TOS, r, lg, l);
			gmove(n->type, nn->type, lg, l, result, nn);
			regfree(lg);
			break;
		}
		if(l->complex >= r->complex) {
			if(l->op == OADDR && (o == OADD || o == OSUB))
				lg = regaddr(result);
			else
				lg = regalloc(l->type, result);
			cgen(l, lg, l);
			rg = eval(r, D_NONE);
		} else {
			rg = regalloc(r->type, D_NONE);
			cgen(r, rg, r);
			lg = regalloc(l->type, result);
			cgen(l, lg, l);
		}
		if(o == OXOR) {
			if(rg == D_TREE) {
				rg = regalloc(r->type, D_NONE);
				cgen(r, rg, r);
			}
			if(rg == D_TOS) {
				rg = regalloc(r->type, D_NONE);
				gmove(r->type, r->type, D_TOS, r, rg, r);
			}
		}
		gopcode(o, n->type, rg, r, lg, l);
		gmove(n->type, nn->type, lg, l, result, nn);
		regfree(lg);
		regfree(rg);
		break;

	case OASHL:
		if(r->op == OCONST)
			if(shlcon(l, r, result, nn))
				break;
	case OLSHR:
	case OASHR:
		if(result == D_NONE) {
			nullwarn(l, r);
			break;
		}

		if(l->complex >= FNX && r->complex >= FNX) {
			cgen(r, D_TOS, r);
			v = argoff;
			lg = regalloc(l->type, result);
			cgen(l, lg, l);
			adjsp(v - argoff);
			rg = regalloc(r->type, D_NONE);
			gopcode(OAS, r->type, D_TOS, r, rg, r);
			gopcode(n->op, n->type, rg, r, lg, l);
			gmove(n->type, nn->type, lg, l, result, nn);
			regfree(lg);
			regfree(rg);
			break;
		}
		if(l->complex >= r->complex) {
			lg = regalloc(l->type, result);
			cgen(l, lg, l);
			v = vconst(r);
			if(v <= 0 || v > 8) {
				rg = regalloc(r->type, D_NONE);
				cgen(r, rg, r);
			} else
				rg = eval(r, D_NONE);
		} else {
			rg = regalloc(r->type, D_NONE);
			cgen(r, rg, r);
			lg = regalloc(l->type, result);
			cgen(l, lg, l);
		}
		gopcode(o, n->type, rg, r, lg, l);
		gmove(n->type, nn->type, lg, l, result, nn);
		regfree(lg);
		regfree(rg);
		break;

	case ONEG:
	case OCOM:
		if(result == D_NONE) {
			nullwarn(l, Z);
			break;
		}
		lg = regalloc(l->type, result);
		cgen(l, lg, l);
		gopcode(o, l->type, D_NONE, Z, lg, l);
		gmove(n->type, nn->type, lg, l, result, nn);
		regfree(lg);
		break;

	case OADDR:
		if(result == D_NONE) {
			nullwarn(l, Z);
			break;
		}
		lcgen(l, result, nn);
		break;

	case OEQ:
	case ONE:
	case OLE:
	case OLT:
	case OGE:
	case OGT:
	case OLO:
	case OLS:
	case OHI:
	case OHS:
		if(result == D_NONE) {
			nullwarn(l, r);
			break;
		}
		boolgen(n, 1, result, nn, Z);
		break;

	case OANDAND:
	case OOROR:
		boolgen(n, 1, result, nn, Z);
		if(result == D_NONE)
			patch(p, pc);
		break;

	case OCOMMA:
		cgen(l, D_NONE, l);
		doinc(l, POST);
		doinc(r, PRE);
		cgen(r, result, nn);
		break;

	case ONOT:
		if(result == D_NONE) {
			nullwarn(l, Z);
			break;
		}
		boolgen(n, 1, result, nn, Z);
		break;

	case OPOSTINC:
	case OPOSTDEC:
		v = 1;
		if(l->type->etype == TIND)
			v = l->type->link->width;
		if(o == OPOSTDEC)
			v = -v;
		if(l->op == OBIT)
			goto bitinc;
		if(nn == Z)
			goto pre;

		lg = D_TREE;
		if(l->addable < INDEXED) {
			lg = regaddr(D_NONE);
			lcgen(l, lg, Z);
			lg |= I_INDIR;
		}
		if(result != D_NONE)
			gmove(l->type, nn->type, lg, l, result, nn);
		if(typefd[n->type->etype]) {
			rg = regalloc(n->type, D_NONE);
			gmove(l->type, l->type, lg, l, rg, l);
			gopcode(o, n->type, D_CONST, nodconst(1), rg, l);
			gmove(l->type, l->type, rg, l, lg, l);
			regfree(rg);
		} else {
			if(v < 0)
				gopcode(o, n->type, D_CONST, nodconst(-v), lg, l);
			else
				gopcode(o, n->type, D_CONST, nodconst(v), lg, l);
		}
		regfree(lg);
		break;

	case OPREINC:
	case OPREDEC:
		v = 1;
		if(l->type->etype == TIND)
			v = l->type->link->width;
		if(o == OPREDEC)
			v = -v;
		if(l->op == OBIT)
			goto bitinc;

	pre:
		lg = D_TREE;
		if(l->addable < INDEXED) {
			lg = regaddr(D_NONE);
			lcgen(l, lg, Z);
			lg |= I_INDIR;
		}
		if(typefd[n->type->etype]) {
			rg = regalloc(n->type, D_NONE);
			gmove(l->type, l->type, lg, l, rg, l);
			gopcode(o, n->type, D_CONST, nodconst(1), rg, l);
			gmove(l->type, l->type, rg, l, lg, l);
			regfree(rg);
		} else {
			if(v < 0)
				gopcode(o, n->type, D_CONST, nodconst(-v), lg, l);
			else
				gopcode(o, n->type, D_CONST, nodconst(v), lg, l);
		}
		if(result != D_NONE)
			gmove(l->type, nn->type, lg, l, result, nn);
		regfree(lg);
		break;

	bitinc:
		rg = regaddr(D_NONE);
		lg = regalloc(tfield, D_NONE);
		if(result != D_NONE && (o == OPOSTINC || o == OPOSTDEC)) {
			g = bitload(l, lg, rg, D_NONE, nn);
			if(nn != Z)
				gmove(l->type, nn->type, g, l, result, nn);
			if(v < 0)
				gopcode(o, n->type, D_CONST, nodconst(-v), g, n);
			else
				gopcode(o, n->type, D_CONST, nodconst(v), g, n);
			bitstore(l, g, rg, lg, D_NONE, nn);
			break;
		}
		g = bitload(l, lg, rg, result, nn);
		if(v < 0)
			gopcode(o, n->type, D_CONST, nodconst(-v), g, n);
		else
			gopcode(o, n->type, D_CONST, nodconst(v), g, n);
		if(result != D_NONE)
			gmove(l->type, nn->type, g, l, result, nn);
		bitstore(l, g, rg, lg, D_NONE, nn);
		break;
	}
}