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

📄 ccgen1.c

📁 KCC , a good c compiler, write by Ken Harrenstien
💻 C
📖 第 1 页 / 共 2 页
字号:
	    break;
	case Q_CONTINUE:
	    false = looplabel;
	    nelse = NULL;
	    break;
	case Q_BREAK:
	    false = brklabel;
	    nelse = NULL;
	    break;
	default:
	    false = newlabel();
	}
	switch(nthen->Nop) {		/* we could invert the boolean here, */
	case Q_GOTO:			/* but instead we merely set label */
	case N_LABEL:			/* at the end of the condition. */
	case Q_CASE:			/* fixes gotos in both clauses. */
	    l->Nendlab = nthen->Nxfsym;
	    break;
	case Q_CONTINUE:
	    l->Nendlab = looplabel;
	    break;
	case Q_BREAK:
	    l->Nendlab = brklabel;
	default:
	    ;	/* do nothing */
	}
	gboolean(l, false, 0);
	nthen->Nendlab = true;
	genstmt(nthen);
	if (nelse) {
	    code6(P_JRST, NULL, true);
	    codlabel(false);
	    nelse->Nendlab = true;
	    genstmt(nelse);
	}
    } else if (nelse) {
	gboolean(l, true, 1);
	nelse->Nendlab = true;
	genstmt(nelse);
    }

    /* then emit exit label */
    if (!n->Nendlab) codlabel(true);	/* emit exit label */
}

/* LABCHK - returns true if parse tree contains any labels.
*/
static int
labchk(n)
NODE *n;
{
    if (n == NULL) return 0;
    switch (n->Nop) {
	case Q_CASE:		/* These three are all labels */
	case N_LABEL:
	case Q_DEFAULT:
	    return 1;

	case N_STATEMENT:		/* Compound statement, scan it. */
	    if (n->Nleft && n->Nleft->Nop == N_DATA)	/* Skip auto inits */
		n = n->Nright;		/* move on to real statements */
	    for(; n != NULL; n = n->Nright) {
		if(n->Nop != N_STATEMENT)
		    int_error("labchk: bad stmt %N", n);
		if(n->Nleft && labchk(n->Nleft))
		    return 1;
	    }
	    return 0;

	case Q_IF:		/* Has two substatements */
	    return labchk(n->Nright->Nleft) || labchk(n->Nright->Nright);

	case Q_DO:		/* Standard substatements */
	case Q_FOR:
	case Q_SWITCH:
	case Q_WHILE:
	    return labchk(n->Nright);

	case Q_BREAK:		/* Not labels and no substatements */
	case Q_GOTO:
	case Q_CONTINUE:
	case Q_RETURN:
	case N_EXPRLIST:	/* Same as expression stmt */
	default:		/* None of above, assume expression stmt */
	    return 0;
    }
}

/* ------------------------- */
/*	while statement      */
/* ------------------------- */
static void
gwhile(n)
NODE *n;
{
    SYMBOL *saveb, *savel;

    /* ok, we do, so we need to make a label for the top */
    savel = looplabel;
    looplabel = gtoplab();		/* Get new label and emit */

    /* now, see if there is a body or just the test */
    if (n->Nright == NULL) {
	n->Nleft->Nendlab = n->Nendlab;	/* propagate exit point */
	gboolean(n->Nleft, looplabel, 1); /* no body, just test */
    } else {
	saveb = brklabel;		/* full body, need another label */
	brklabel = (n->Nendlab != NULL)? n->Nendlab : newlabel();
	n->Nright->Nendlab = looplabel;	/* exit from body is to loop top */
	gboolean(n->Nleft, brklabel, 0);	/* first the test, if any */
	genstmt(n->Nright);		/* then the actual body */
	code6(P_JRST, NULL, looplabel);	/* body jumps back to test */
	if (n->Nendlab == NULL) codlabel(brklabel); /* emit end label */
	brklabel = saveb;		/* restore label for outer loop */
    }

    /* in either case we need to restore the outer loop top label */
    freelabel (looplabel);
    looplabel = savel;			/* fix the label */
}

/* GTOPLAB - auxiliary for loops which need to generate a label at top.
*/
static SYMBOL *
gtoplab()
{
    SYMBOL *lab;
    flushcode();		/* Ensure all previous code forced out */
    lab = newlabel();		/* Get new label */
    outlab(lab);		/* and emit it directly */
    return lab;
}

/* ---------------------- */
/*	do statement      */
/* ---------------------- */
static void
gdo(n)
NODE *n;
{
    SYMBOL *saveb, *savel, *toplabel;

    toplabel = gtoplab();		/* Get new label and emit */
    saveb = brklabel;
    brklabel = (n->Nendlab != NULL) ? n->Nendlab : newlabel();

    if (n->Nright) {
	savel = looplabel;
	n->Nright->Nendlab = looplabel = newlabel();
	genstmt(n->Nright);
	codlabel(looplabel);
	looplabel = savel;		/* restore outer loop label */
    }

    if ((n->Nleft->Nop) != N_ICONST) {
	n->Nleft->Nendlab = brklabel;
	gboolean(n->Nleft, toplabel, 1);
    } else if (n->Nleft->Niconst) code6(P_JRST, NULL, toplabel);

    if (n->Nendlab == NULL) codlabel(brklabel);
    brklabel = saveb;			/* restore for outer breaks */
    freelabel (toplabel);		/* no more use for this one */
}

/* ----------------------- */
/*	for statement      */
/* ----------------------- */
static void
gfor(n)
NODE *n;
{
    NODE *cond, *body, *incr, *init;
    SYMBOL *saveb, *savel, *toplabel;
    int endtest;			/* safe to move test to end of loop */

    cond = n->Nleft;
    body = n->Nright;
    incr = cond->Nright->Nleft;
    cond = cond->Nleft;
    init = cond->Nleft;
    cond = cond->Nright;

    /* See if conditional test can be put at the end of the loop, which is
    ** usually more efficient.  endtest is true if so.  Note that it
    ** will not be true if no test exists.
    */
    endtest = optgen &&			/* Never, if not optimizing. */
	cond &&				/* And only if have a condition. */
	((body == NULL && incr == NULL)	/* OK if no body or increment */
	 || istrue(cond, init));	/* or if test exists & is TRUE */

    if (init) genxrelease(init);

    toplabel = gtoplab();	/* Generate top-of-loop label and emit */
    saveb = brklabel;
    brklabel = (n->Nendlab != NULL) ? n->Nendlab : newlabel();

    savel = looplabel;			/* remember prev outer label */
    looplabel = (body == NULL || (incr == NULL && !endtest)) ?
		toplabel : newlabel();

     /* Normally generate test at start of loop */
    if (cond && !endtest)		/* If have condition, and at beg, */
	gboolean(cond, brklabel, 0);	/* generate test at start of loop */

    /* Now generate body */
    if (body != NULL) {			/* If we have one, of course */
	body->Nendlab = looplabel;
	genstmt(body);
	if (looplabel != toplabel) codlabel(looplabel);
    }

    /* Now generate increment */
    if (incr != NULL) {
	if (!endtest) incr->Nendlab = toplabel;
	genxrelease(incr);
    }

    /* Finally generate loop back to condition test at top, unless actually
    ** doing the test here.
    */
    if (endtest) {			/* If test comes at end of loop */
	cond->Nendlab = brklabel;	/* set end label for it */
	gboolean(cond,toplabel,1);	/* and gen the conditional jump */
    }
    else code6(P_JRST, NULL, toplabel);	/* Otherwise just loop */

    if (n->Nendlab == NULL)
	codlabel(brklabel);
    brklabel = saveb;			/* restore old break label */
    looplabel = savel;			/* restore outer loop continuation */
    freelabel(toplabel);		/* don't need top label any more */
}

/*
 * greturn ()
 */

static
void
greturn (NODE *n)
    {
    INT		siz;
    VREG*	r;
    VREG*	r2;
    int		i = n->Nreg;


    if (optobj && deadjump ())		/* If in dead code, do nothing */
	return;

    if ((n = n->Nright) != NULL)
	{				/* If returning a value, set it */
	if (n->Ntype->Tspec == TS_ARRAY)
	    {				/* Just in case */
	    int_error("greturn: returning array");
	    return;
	    }

	siz = sizetype(n->Ntype);	/* Remember size */
	n->Nflag |= NF_RETEXPR;		/* Tell genexpr this is return value */

	if ((r = genexpr(n)) == NULL)
	    {				/* Make return expression */
	    if (!deadjump())		/* If no expr, must be in dead code */
		int_error("greturn: null vreg");

	    return;			/* Assume tail-recursed, so win! */
	    }

	if (siz == 1) 			/* Return 1-word value */
	    code0 (P_MOVE, VR_RETVAL, r);
	else if (siz == 2)		/* Return 2-word value */
	    code0 (P_DMOVE, VR_RETVAL, r);
	else
	    {				/* Return N-word value */
	    r2 = vrget();
	    code13(P_MOVE, r2, -1 - stackoffset); /* Get addr of arg 0 */
	    code4(P_MOVE, r2, r2);	/* Get ptr to place to return block */
	    code4s(P_SMOVE, r2, r, 0, siz);	/* Copy the block */
	    vrfree(r2);
	    }
	}

    if (optobj)
	killstack ();			/* Flush spurious MOVEMs */

#if 0	/* qq Reg linkage */
    if (!fn_main && R_PRESERVE_COUNT >= i && i > 0)	/* Reg linkage */
	stackoffset -= i;

    printf ("stackoffset=%d i=%d\n", stackoffset, i);
#endif

    code8 (P_ADJSP, VR_SP, -stackoffset); /* flush local vars from stk */

    if (profbliss)
	{				/* for BLISS profiler */
	flushcode ();
	outepilog (curfn);		/* added 09/15/89 by MVS */
	}

    /*
     * Restore any preserved registers that were used for
     * register variables.
     */    

    if (!fn_main && R_PRESERVE_COUNT >= i) /* Reg linkage */
	{
        while (i-- > 0)
            {
	    code00 (P_POP, R_SP, i + r_maxnopreserve + 1); /* FW 2A(52) */
 	    oline++;
	    }
	}

    if (isr)				/* FW 2A(52) */
	{
	flushcode ();			
	outiepilog ();
	}
    else
	code5 (P_POPJ, VR_SP);		/* emit the return */
    }

⌨️ 快捷键说明

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