⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gen.c

📁 window下的c编译器。
💻 C
📖 第 1 页 / 共 3 页
字号:
	oldbp = bp;
	isinstruction = IR->x._isinstruction[rulenum];
	genericOp = generic(p->op);
	if (p->x.intrinsic) {
		if (p->x.emitted) {
			outs(p->syms[RX]->x.name);
			return 0;
		}
		p->x.emitted = 1;
		Intrinsic(p);
		return 0;
	}
	if (isinstruction && p->x.emitted) {
		/* When an instruction has already been emitted, only the name of the
		register where the instruction left its result will be output
		*/
		outs(p->syms[RX]->x.name);
	}
	else if (*fmt == '#')
		/* This is an escape hatch to generate machine specific code like
		structure arguments
		*/
		(*IR->x.emit2)(p);
	else {
		if (*fmt == '?') {
			/* Omit redundant expressions */
			fmt++;
			/*assert(p->x.kids[0]);*/
			/* This was updated after my complaints about redundant expressions */
			if (p->x.kids[0] && p->syms[RX] == p->x.kids[0]->syms[RX])
				while (*fmt++ != '\n')
					;
			else if (p->x.kids[1] && p->syms[RX] == p->x.kids[1]->syms[RX]) {
				/*
				This happens mainly in the case of a return instruction, where
				the return expression assigns eax to one of its members,
				specifically to p->x.kids[1]. This is a bug in the register
				allocator that doesn't take into account the registers assigned
				with rtarget. This correction works, well I hope.
				*/
				int i;
				fmt = strchr(fmt,'\n');
				assert(fmt);
				fmt++;
				if (*fmt == '\t') 
					fmt++;
				i = 1;
				newfmt[0] = '\t';
				if (generic(p->op) == SUB || generic(p->op) == BXORU) {
					strcpy(newfmt,"\txchgl\t%0,%c\n\t");
					i = strlen(newfmt);
				}
				while (*fmt && *fmt != '\t') {
					newfmt[i++] = *fmt++;
				}
				newfmt[i++] = '\t';
				newfmt[i] = 0;
				strcat(newfmt,"%0,%c\n");
				fmt = newfmt;
//				printf("%s: (%d)\n",cfunc->name,src.y);
//				dumptree(p,0);
//				printf("\n");
			}
		}
		if (p->x.Flags && (p->op == LTI || p->op == GTI)) {
			while (*fmt++ != '\n')
				;
		}
		booleanAsgn = p->x.booleanAsgn;
		if (glevel > 2 && genericOp == CALL) {
			if (glevel == 3) {
				if (FunctionInfo.FnNrOfLines < 256)
					print("\tmovb\t$%d,-8(%%ebp)\n",src.y - cfunc->src.y);
				else
					print("\tmovw\t$%d,-8(%%ebp)\n",src.y - cfunc->src.y);
			}
			NeedsCallReset=1;
		}
		for ((*IR->x._kids)(p, rulenum, kids); *fmt; fmt++) {
			if (*fmt != '%')
				*bp++ = *fmt;
			else {
				++fmt;
				if (*fmt >= '0' && *fmt <= '9') {
				int n = *fmt - '0';
				/* Emit recursively the subtree corresponding to the 'digit'-th
				nonterminal for the pattern, counting from zero, left to
				right.
				*/
				emitasm(kids[n], nts[n]);
				if (genericOp == CALL) { /* call instruction */
					if (kids[n]->syms && kids[n]->syms[0] &&
						kids[n]->syms[0]->Flags) {
						*bp++ = '\n';
						goto exitEmit;
					}
					else if (oldbp[7] == 'a' && !strncmp(oldbp+6,"_alloca",7)) {
						int c = oldbp[13];
						if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'z') ||
								(c >= '0' && c <= '9'))) {
							hasAllocA = 1;
							*bp++ = '\n';
							goto exitEmit;
						}
					}
				}
			}
			else if (*fmt >= 'a' && *fmt < 'a' + NELEMS(p->syms)) {
				/* This evaluates to a register name */
				if (FunctionInfo.noFrame) {
					if (*fmt == 'a' && !strcmp(fmt+1,"(%%ebp)")) {
						char tmpbuf[20];
						int offset = atoi(p->syms[0]->x.name);
						offset -= 4;
						offset += FunctionInfo.pushedRegs;
						assert(offset > 0);
						sprintf(tmpbuf,"%d(%%esp)",offset);
						outs(tmpbuf);
						goto exitEmit;
					}
				}
				outs(p->syms[*fmt - 'a']->x.name);
			}
			else
				*bp++ = *fmt;
			}
			if (booleanAsgn && *fmt == '\n')
				break;
		}
	}
	if (OptimizeFlag && hasExceptions == 0 && genericOp == LABEL) {
		SendToOptimizer();
	}
exitEmit:
	if (glevel > 2) {
		if (NeedsCallReset)
			RestoreGlevelStack();
		if (glevel > 3 && genericOp == LABEL)
			NeedsLineReset = 1;
	}
	return 0;
}


void emit(Node p)
{
	if (IntermediateLanguageFile)
		fprintf(ilFile,"\n; Tree\n");
	for (; p; p = p->x.next) {
		assert(p->x.registered);
		if (p->x.equatable && requate(p) || moveself(p)) {
			;
		}
		else {
			char *oldbp = bp;
			(*emitter)(p, p->x.inst);
			if (IntermediateLanguageFile) {
				int rulenum;

				ildumptree(p,0);
				fprintf(ilFile,"\n");
				rulenum = getrule(p, p->x.inst);
				ildumprule(rulenum);
				fprintf(ilFile,"%s",oldbp);
			}
			oldbp = bp;
		}

		p->x.emitted = 1;
	}
}
int moveself(Node p)
{
	if (p->x.kids[0] == NULL) return 0;
	return p->x.copy
	&& p->syms[RX]->x.name == p->x.kids[0]->syms[RX]->x.name;
}
int move(Node p)
{
	p->x.copy = 1;
	return 1;
}
int requate(Node q)
{
	Symbol src = q->x.kids[0]->syms[RX];
	Symbol tmp = q->syms[RX];
	Node p;
	int n = 0;

#ifdef DODEBUG
	fprint(2, "(requate(%x): tmp=%s src=%s)\n", q, tmp->x.name, src->x.name);
#endif
	for (p = q->x.next; p; p = p->x.next)
		if (p->x.copy && p->syms[RX] == src
		&&  p->x.kids[0]->syms[RX] == tmp)
#ifdef DODEBUG
			fprint(2, "(requate arm 0 at %x)\n", p),
#endif
			p->syms[RX] = tmp;
		else if (setsrc(p->syms[RX]) && !moveself(p) && !readsreg(p))
			return 0;
#if OLD
		else if (generic(p->op) == ASGN && p->kids[0]->op == ADDRLP
		&& p->kids[0]->syms[0]->temporary
		&& p->kids[1]->syms[RX]->x.name == tmp->x.name)
			return 0;
#else
		else if (p->x.spills)
			return 0;

#endif
		else if (generic(p->op) == CALL && p->x.next)
			return 0;
		else if (p->op == LABEL+V && p->x.next)
			return 0;
		else if (p->syms[RX] == tmp && readsreg(p))
#ifdef DODEBUG
			fprint(2, "(requate arm 5 at %x)\n", p),
#endif
			n++;
		else if (p->syms[RX] == tmp)
			break;
#ifdef DODEBUG
	fprint(2, "(requate arm 7 at %x)\n", p);
#endif
	assert(n > 0);
	for (p = q->x.next; p; p = p->x.next)
		if (p->syms[RX] == tmp && readsreg(p)) {
			p->syms[RX] = src;
			if (--n <= 0)
				break;
		}
	return 1;
}

extern int clobbersWhich(Node);


static int DoesNotUse(Node tree,Symbol r)
{
	int clobberedMask;

	if (tree == NULL) return 1;
	clobberedMask = clobbersWhich(tree);
	if (r->x.regnode && (clobberedMask & r->x.regnode->mask))
		return 0;
	if (tree->syms[RX]->x.name == r->x.name) return 0;
	if (tree->syms[0] && tree->syms[0]->x.name == r->x.name) return 0;
	if (!DoesNotUse(tree->kids[0],r)) return 0;
	if (!DoesNotUse(tree->kids[1],r)) return 0;
	if (tree->syms[0] == NULL) return 1;
	return 1;
}

static int IsSafeOp(Node q)
{
	if (q == NULL) return 0;
	return (
		q->op == ADDI || q->op == SUBI || q->op == BANDU || q->op == BORU
		|| q->op == CVSI || q->op == CVSU  || q->op == NEGI) ? 1 : 0;
}

static void prelabel(Node p)
{
	if (p == NULL)
		return;
	prelabel(p->kids[0]);
	prelabel(p->kids[1]);
	if (NeedsReg[opindex(p->op)] || p->op == JUMPI)
		setreg(p, rmap[optype(p->op)]);
	switch (generic(p->op)) {
	case ADDRF: case ADDRL:
		if (p->syms[0]->sclass == REGISTER)
			p->op = VREG+P;
		return;
	case INDIR:
		if (p->kids[0]->op == VREG+P)
			setreg(p, p->kids[0]->syms[0]);
		return;
	case ASGN:
		if (p->kids[0]->op == VREG+P) {
			Node q = p->kids[1];
			Symbol r = p->kids[0]->syms[0];
#ifdef DODEBUG
			fprint(2, "(cse=%x)\n", p->kids[0]->syms[0]->u.t.cse);
#endif
			rtarget(p, 1, r);
			(IR->x.target)(p);
			if (OptimizeFlag && r->x.wildcard == NULL && IsSafeOp(q)) {
				if (q->kids[0]->syms[RX]->x.wildcard && IsSafeOp(q->kids[0])) {
					if (DoesNotUse(q->kids[0],r) &&
						DoesNotUse(q->kids[1],r))  {
						setreg(q->kids[0],r);
#if 0
						printf("%s: setting operation %d to %s. Line %d\n",
							src.file,q->kids[0]->op,r->x.name,src.y);
#endif
					}
				}
			}
			return;
		}
		break;
	}
	(IR->x.target)(p);
}
void setreg(Node p,Symbol r)
{
	p->syms[RX] = r;
}
void rtarget(Node p,int n,Symbol r)
{
	Node q = p->kids[n];

	assert(q);
	assert(r->sclass == REGISTER || !r->x.wildcard);
	assert(q->syms[RX]);
	if (r != q->syms[RX] && !q->syms[RX]->x.wildcard) {
lab1:
		q = newnode(LOAD + optype(q->op),
			q, NULL, q->syms[0]);
		if (r->u.t.cse == p->kids[n])
			r->u.t.cse = q;
		p->kids[n] = p->x.kids[n] = q;
		q->x.kids[0] = q->kids[0];
		setreg(q,r);
	}
	else if (q->kids[1] == NULL ||
		p->kids[0]->syms[0] == NULL ||
		p->kids[0]->syms[0]->u.t.cse ||
		!(/*q->kids[0]->syms[RX]->x.name[0] == '?' &&*/
		p->kids[0]->syms[0] == q->kids[1]->syms[RX]))
		setreg(q, r);
	else {
//		printf("not taken line %d\n",src.y);
		goto lab1;
	}
//	q->x.unsafe = 1;
#ifdef DODEBUG
	fprint(2, "(targeting %x->x.kids[%d]=%x to %s)\n", p, n, p->kids[n], r->x.name);
#endif
}
static void rewrite(Node p)
{
	assert(p->x.inst == 0);
	prelabel(p);
#ifdef DODEBUG
	dumptree(p,0);
	fprint(2, "\n");
#endif
	(*IR->x._label)(p);
#ifdef DODEBUG
	dumpcover(p, 1, 0);
#endif
	reduce(p, 1);
}

static void SetClobberedRegs(Node p,int clobbered)
{
	if (p == NULL) return;
	p->x.clobbersWhich = clobbered;
	SetClobberedRegs(p->kids[0],clobbered);
	SetClobberedRegs(p->kids[1],clobbered);
}
/*
The interface function gen receives a forest from the front end and makes
several passes over the trees.
*/
Node gen(Node forest)
{
	int i;
	struct node sentinel;
	Node dummy, p;

	head = forest;
	if (OptimizeFlag)
		unsafe = head->x.unsafe;
	else
		unsafe = 1;
	/*
	The first pass calls rewrite to select instructions, and the second
	prunes the subinstructions out of the tree.
	*/
	for (p = forest; p; p = p->link) {
		assert(p->count == 0);
		if (generic(p->op) == CALL)
			docall(p);
		else /* If the call returns no value, or if the returned
				value is ignored, then the call itself appears in the forst.
				This statement recognizes this pattern */
		if (generic(p->op) == ASGN
		&& generic(p->kids[1]->op) == CALL)
			docall(p->kids[1]);
		else if (generic(p->op) == ARG)
			(*IR->x.doarg)(p);
		rewrite(p);
		p->x.listed = 1;
	}
	for (p = forest; p; p = p->link)
		prune(p, &dummy);
	relink(&sentinel, &sentinel);
	for (p = forest; p; p = p->link)
		linearize(p, &sentinel);
	forest = sentinel.x.next;
	assert(forest);
	sentinel.x.next->x.prev = NULL;
	sentinel.x.prev->x.next = NULL;
	for (p = forest; p; p = p->x.next)
		for (i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++) {
			assert(p->x.kids[i]->syms[RX]);
			if (p->x.kids[i]->syms[RX]->temporary) {
				p->x.kids[i]->x.prevuse =
					p->x.kids[i]->syms[RX]->x.lastuse;
				p->x.kids[i]->syms[RX]->x.lastuse = p->x.kids[i];
			}
		}
#if 0 // This is the patch proposed by Chris Fraser end of April 97.
	for (p = forest; p; p = p->x.next)
		if (p->x.copy && p->x.kids[0] && p->x.kids[0]->syms[RX]->u.t.cse) {
			Symbol dst = p->syms[RX];
			Symbol temp = p->x.kids[0]->syms[RX];
			Node q;

			assert(temp->x.lastuse);
			for (q = temp->u.t.cse; q; q = q->x.next)
				if (p != q && dst == q->syms[RX]
				|| (q->op == LABELV || q->op == JUMPV || generic(q->op)==RET ||
					generic(q->op)==EQ || generic(q->op)==NE ||
					generic(q->op)==LE || generic(q->op)==LT ||
					generic(q->op)==GE || generic(q->op)==GT ||
					q->op == ASGNB || /* This costed me a week */
					(generic(q->op) == CALL && dst->sclass != REGISTER)))
					break;
			if (!q)
				for (q = temp->x.lastuse; q; q = q->x.prevuse)
					q->syms[RX] = dst;
		}
#endif
	if (OptimizeFlag) {
		int clobberswhich = 0;
        for (p = forest; p ; p = p->x.next) {
			if (p->op != JUMPI)
				clobberswhich = clobbersWhich(p);
			else
				clobberswhich = (1 << 6)|(1<< 7);
			if (clobberswhich) {
				SetClobberedRegs(p,clobberswhich);
			}
			if (p->op == DIVI && p != forest && p->x.prev)
				p->x.prev->x.clobbersWhich |= (1 << 2)|1;
		}
	}
	for (p = forest; p; p = p->x.next) {
		if (p->x.unsafe || (p->x.next && p->x.next->x.unsafe))
			unsafe = 1;
		ralloc(p);
		if (p->x.listed && (NeedsReg[opindex(p->op)] || p->op == JUMPI)
		&& rmap[optype(p->op)]) {
			assert(generic(p->op) == CALL || p->op == JUMPI ||
				generic(p->op) == LOAD);
			putreg(p->syms[RX]);
		}
	}
	unsafe = 1;
	return forest;
}
int notarget(Node p)
{
	return p->syms[RX]->x.wildcard ? 0 : LBURG_MAX;
}
static void putreg(Symbol r)
{
	assert(r && r->x.regnode);
	freemask[r->x.regnode->set] |= r->x.regnode->mask;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -