Example #1
0
// Checks if the group is abelian
// Maybe incorrect?
bool CayleyGraph::is_abelian (void) {
	int gen[MAX_GENERATORS];
	for (int i = 0; i < MAX_GENERATORS; i++)
		gen[i] = out_edges[0][i];
	for (int i = 0; i < MAX_GENERATORS; i++) {
		if (gen[i] != order) {
			for (int j = i; j < MAX_GENERATORS; j++) {
				if (gen[j] != order && !commutes(gen[i],gen[j]))
					return false;
			}
		}
	}
	return true;
}
Example #2
0
void
cgen(Node *n, Node *nn)
{
	Node *l, *r;
	Prog *p1;
	Node nod, nod1, nod2, nod3, nod4;
	int o, t;
	long v, curs;

	if(debug['g'] && nn == Z) {
		// 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 ODIV:
	case OMOD:
		if(nn != Z)
		if((t = vlog(r)) >= 0 && t <= 8) {
			/* 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(OSUB, nn, nodconst(0), nn);
				regalloc(&nod, l, Z);
				gopcode(OAS, nodconst((1<<t)-1), Z, &nod);
				gopcode(OAND, &nod, Z, nn);
				regfree(&nod);
				// gopcode(OAND, nodconst((1<<t)-1), Z, nn);
				gopcode(OSUB, nn, nodconst(0), nn);
				gbranch(OGOTO);
				patch(p1, pc);
				p1 = p;
				regalloc(&nod, l, Z);
				gopcode(OAS, nodconst((1<<t)-1), Z, &nod);
				gopcode(OAND, &nod, Z, nn);
				regfree(&nod);
				// gopcode(OAND, nodconst((1<<t)-1), Z, nn);
				patch(p1, pc);
			}
			break;
		}
		goto muldiv;

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

	case OAND:
	case OOR:
	case OXOR:
	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, r, Z);
			cgen(r, &nod1);
			gopcode(o, &nod1, Z, &nod);
		} else {
			if(o == OADD || o == OSUB) {
				regalloc(&nod, r, nn);
				cgen(r, &nod);
				regalloc(&nod1, l, Z);
				cgen(l, &nod1);
				gopcode(o, &nod, &nod1, &nod);
			}
			else {
				if(commutes(o)){
					regalloc(&nod, r, nn);
					cgen(r, &nod);
					regalloc(&nod1, l, Z);
					cgen(l, &nod1);
					gopcode(o, &nod1, Z, &nod);
				}
				else{
					regalloc(&nod1, r, Z);
					cgen(r, &nod1);
					regalloc(&nod, l, nn);
					cgen(l, &nod);
					gopcode(o, &nod1, Z, &nod);
				}
			}
		}
		gopcode(OAS, &nod, Z, nn);
		regfree(&nod);
		regfree(&nod1);
		break;

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

	case OASLSHR:
	case OASASHL:
	case OASASHR:
	case OASADD:
	case OASSUB:
		if(l->op == OBIT)
			goto asbitop;
		if(sconst(r))
		if(o == OASADD || o == OASSUB || r->vconst < (vlong)32) {
		// if(r->op == OCONST)
		// 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 OASAND:
	case OASXOR:
	case OASOR:
	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;
		}
		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) >= 0 && v < 32*r->type->width/SZ_LONG) {
			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 {
			if (v > 0 && v < 8)
				gopcode(OADD, nodconst(v), &nod, &nod1);
			else if (v < 0 && v > -8)
				gopcode(OSUB, nodconst(-v), &nod, &nod1);
			else {
				regalloc(&nod3, l, Z);
				gopcode(OAS, nodconst(v), Z, &nod3);
				gopcode(OADD, &nod3, &nod, &nod1);
				regfree(&nod3);
			}
		}
		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 {
			if (v > 0 && v < 256)
				gopcode(OADD, nodconst(v), Z, &nod);
			else if (v < 0 && v > -256)
				gopcode(OSUB, nodconst(-v), Z, &nod);
			else {
				regalloc(&nod3, l, Z);
				gopcode(OAS, nodconst(v), Z, &nod3);
				gopcode(OADD, &nod3, &nod, &nod);
				regfree(&nod3);
			}
		}
		gopcode(OAS, &nod, Z, &nod2);

		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);
			if (v > 0 && v < 256)
				gopcode(OADD, nodconst(v), Z, &nod);
			else if (v < 0 && v > -256)
				gopcode(OSUB, nodconst(-v), Z, &nod);
			else {
				regalloc(&nod3, l, Z);
				gopcode(OAS, nodconst(v), Z, &nod3);
				gopcode(OADD, &nod3, &nod, &nod);
				regfree(&nod3);
			}
			bitstore(l, &nod, &nod1, &nod2, Z);
			break;
		}
		bitload(l, &nod, &nod1, &nod2, nn);
		if (v > 0 && v < 256)
			gopcode(OADD, nodconst(v), Z, &nod);
		else if (v < 0 && v > -256)
			gopcode(OSUB, nodconst(-v), Z, &nod);
		else {
			regalloc(&nod3, l, Z);
			gopcode(OAS, nodconst(v), Z, &nod3);
			gopcode(OADD, &nod3, &nod, &nod);
			regfree(&nod3);
		}
		bitstore(l, &nod, &nod1, &nod2, nn);
		break;
	}
	cursafe = curs;
	return;
}
Example #3
0
bool CayleyGraph::is_central (int a) {
	for (int i = 0; i < order; i++)
		if (!commutes(a,i))
			return false;
	return true;
}