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

📄 cccode.c

📁 KCC , a good c compiler, write by Ken Harrenstien
💻 C
📖 第 1 页 / 共 5 页
字号:
/*	CCCODE.C - Emit pseudo-code into peephole buffer
**
**	(c) Copyright Ken Harrenstien 1989
**		All changes after v.315, 26-Apr-1988
**	(c) Copyright Ken Harrenstien, SRI International 1985, 1986
**		All changes after v.146, 8-Aug-1985
**
**	Original version (c) 1981 K. Chen
*/

#include "cc.h"
#include "ccgen.h"
#include <string.h>		/* For memcpy, memcmp */
#include <stdlib.h>		/* for calloc() */

/* Imported functions */
extern PCODE *findrset(PCODE *, int);				/* CCOPT */
extern int rincode(PCODE *, int), rinaddr(PCODE *, int),
	rrchg(PCODE *, int),
	findconst(PCODE *), localbyte(PCODE *, PCODE *);	/* CCOPT */
extern void foldbp(PCODE *), foldbyte(PCODE *),
	foldplus(PCODE *),
	foldboth(void), foldadjbp(PCODE *), optlsh(PCODE *);	/* CCOPT */
extern INT foldstack(INT), hackstack(SYMBOL *);			/* CCOPT */
extern void realcode(PCODE *), outlab(SYMBOL *);	/* CCOUT */

extern void reflabel(SYMBOL *, int), cleanlabs(void),
	freelabel(SYMBOL *);					/* CCSYM */
extern int changereg(int, int, PCODE *), ufcreg(int),
	pnegreg(int, PCODE *), pushneg(int, PCODE *);	/* CCCREG */
extern void foldmove(PCODE *);				/* CCCREG */
extern int sameaddr(PCODE *, PCODE *, INT),
	alias(PCODE *, PCODE *, INT);			/* CCCSE */
extern void foldidx(PCODE *);				/* CCCSE */
extern void foldskip(PCODE *, int),
	foldjump(PCODE *, SYMBOL *), optlab(SYMBOL *),
	inskip(PCODE *);				/* CCJSKP */
extern VREG *vrget(void);
extern void vrfree (VREG *);
extern int vrreal (VREG *);
extern int vrstoreal (VREG *, VREG *);
extern int vrtoreal(VREG *);
extern int rbinreg (PCODE *);
extern int rbinaddr (PCODE *);

/* Exported functions */
PCODE *before(PCODE *), *after(PCODE *);
void fixprev(void), flushcode(void), dropinstr(PCODE *),
    swappseudo(PCODE *, PCODE *);
int codcreg(VREG *, VREG *), immedop(int op);
void code0(int, VREG *, VREG *);
void codek0(int, VREG *, VREG *);
void code00(int, int, int);		/* Reg linkage, was static */
void code1(int, VREG *, INT);
void code3(int, VREG *, SYMBOL *);
void code4(int, VREG *, VREG *);
void code40(int op, int r, int s, INT bsiz);/* Reg linkage, was static */
void code4s(int, VREG *, VREG *, int, INT);
void code5(int, VREG *);
void code6(int, VREG *, SYMBOL *);
void code8(int, VREG *, INT);
void code9(int, VREG *, double, int);
void code10(int, VREG *, SYMBOL *, INT, INT);
void code12(int, VREG *, INT);
void code13(int, VREG *, INT);
void code15(int, SYMBOL *, INT, VREG *);
void code16(int, VREG *, SYMBOL *, VREG *);
void code17(INT);
void codebp(int, int, INT, int, SYMBOL *, INT);

void codek4(int, VREG *, VREG *);
void codemdx(int, int, SYMBOL *, INT, int);
void codestr(char *, int);
void codgolab(SYMBOL *);
void codlabel(SYMBOL *);
void codr1(int, int, INT);
void codr10(int, int, SYMBOL *, INT, INT);

void code4m(int op, VREG *reg, VREG *idx, char *mnem),
	code5m(int, VREG *, char *);

PCODE *chkmref(PCODE *begp, PCODE *endp, INT *aoff);

/* Internal functions */
static void codrmdx(int, int, int, SYMBOL *, INT, int);
static void codr8(int, int, INT);
static void flsprev(void);
static PCODE *newcode(int, int, int);
static void codrrx(PCODE *, PCODE *);
static int rrpre1(PCODE *), rrpre2(PCODE *, PCODE *);
static void rrpre3(PCODE *, PCODE *, int), rrpopt(PCODE *), rrpop2(PCODE *);
static PCODE *chkref(PCODE *, PCODE *, int);
static void foldxref(PCODE *);
static void optjrst(PCODE *p);

#if DEBUG_KCC		/* 5/91 KCC size */
/* PEEPHOLER DEBUGGING ROUTINES */

/*	SHOALL and SHOCURCOD are intended to be called directly by
**	IDDT during debugging, e.g. as in PUSHJ 17,SHOALL$X
*/
#if __STDC__
static void shoall(void), shocurcod(void), shopcod(FILE *, PCODE *, INT),
	shoop(FILE *, unsigned), shohdr(char *, int, int), shocum(void),
	shocmp(FILE *);
#else
static void shoall(), shocurcod(), shopcod(), shoop(),
		shohdr(), shocum(), shocmp();
#endif

static void
shoall()
{
    INT i;
    for (i = mincode; i < maxcode; i++)
	shopcod(outmsgs, &codes[i&(MAXCODE-1)], i&(MAXCODE-1));
}

static void
shocurcod()
{
    shopcod(outmsgs, previous, codes-previous);
}


/* SHOHDR - Called at start of each CODEnn function.
**	Ensures consistent trace of all calls from CCGEN2 to CCCODE.
*/
static void
shohdr(loc, op, r)
char *loc;
int op, r;
{
    fprintf(fpho, "%s: %o=", loc, op);
    shoop(fpho, op);
    if (r)
	fprintf(fpho, " %o,", r);
    else
	fputc(' ', fpho);
}

/* SHOPCOD - Show one pseudo-code entry
**	Used as auxiliary for other debug printing routines, never called
**	directly by IDDT.
*/
static void
shopcod(f,p,idx)
FILE *f;
PCODE *p;
INT idx;
{
    unsigned int i;

    fprintf(f,"codes[%d] %6lo/ %4o %5o %2o %6o %6lo %2o %lo+%lo\n\t",
		idx, p, p->Ptype, p->Pop, p->Preg, p->Pptr,
		p->Poffset, p->Pindex, p->Pdouble1, p->Pdouble2);

    /* Output value of Pop field */
    shoop(f, p->Pop);

    /* Output value of Ptype field */
    fputs(" <", f);
    if (p->Ptype&PTF_IMM)
	fputs("Imm,", f);
    if (p->Ptype&PTF_SKIPPED)
	fputs("Skipped,", f);
    if (p->Ptype&PTF_IND)
	fputs("Indirect", f);
    fputs("> ", f);

    /* Now interpret the rest of the instruction according to mode */
    switch (i = (p->Ptype&PTF_ADRMODE))
	{
	case PTA_ONEREG:		/* no address, just register */
	    fprintf(f, "ONEREG R=%o,", p->Preg);
	    break;
	case PTA_REGIS:			/* register to register */
	    fprintf(f, "REGIS R=%o, R=%o", p->Preg, p->Pr2);
	    break;
	case PTA_MINDEXED:		/* addr+offset(index) */
	    fprintf(f, "MINDEXED R=%o, Addr=%s+%o(%o) siz %o", p->Preg,
		(p->Pptr ? p->Pptr->Sname : ""),
		p->Poffset, p->Pindex, p->Pbsize);
	    break;
	case PTA_BYTEPOINT:		/* [bsize,,addr+offset(index)] */
	    fprintf(f, "BYTEPOINT R=%o, BP=[%o,,%s+%o(%o)]", p->Preg,
		p->Pbsize,
		(p->Pptr ? p->Pptr->Sname : ""),
		p->Poffset,
		p->Pindex);
	    break;
	case PTA_PCONST:		/* [<pointer of addr+offset+bsize>] */
	    if (p->Pbsize)
		fprintf(f, "PCONST R=%o, bptr%d=[%s+%o]", p->Preg,
			p->Pbsize,
			(p->Pptr ? p->Pptr->Sname : ""),
			p->Poffset);
	    else
		fprintf(f, "PCONST R=%o, Wptr=[%s+%o]", p->Preg,
			(p->Pptr ? p->Pptr->Sname : ""),
			p->Poffset);
	    break;
	case PTA_RCONST:		/* Simple integer in pvalue */
	    fprintf(f, "RCONST R=%o, Constant=%o", p->Preg, p->Pvalue);
	    break;
	case PTA_FCONST:		/* [single-prec float] */
	    fprintf(f, "FCONST R=%o, Fltcon=%g", p->Preg, p->Pfloat);
	    break;
	case PTA_DCONST:		/* [double-prec float] */
	    fprintf(f, "DCONST R=%o, Dblcon=%g", p->Preg, p->Pdouble);
	    break;
	case PTA_DCONST1:		/* [1st wd of double float] */
	    fprintf(f, "DCONST1 R=%o, 1st wd of dblcon=%g", p->Preg, p->Pdouble);
	    break;
	case PTA_DCONST2:		/* [2nd wd of double float] */
	    fprintf(f, "DCONST2 R=%o, 2nd wd of dblcon=%g", p->Preg, p->Pdouble);
	    break;
	default:
	    fprintf(f, "Illegal ADRMODE value = %o", i);
	}
    fputc('\n', f);
}

/* SHOOP - Auxiliary for above two routines, just outputs string for opcode.
*/
static void
shoop(f, op)
FILE *f;
unsigned op;
{
    /* Test conditions, indexed by POF_OPSKIP field */
    static char *shoskt[] = { "", "A", "E", "N", "L", "GE", "G", "LE" };

    fputs(popostr[op&POF_OPCODE], f);
    if (op&(~POF_OPCODE))
	{
	if (op&POF_ISSKIP)
	    fputs("+skp", f);
	if (op&POF_OPSKIP)
	    {
	    fputc('+', f);
	    fputs(shoskt[(op&POF_OPSKIP)>>POF_OPSKIP_SHF], f);
	    }
	if (op&POF_BOTH)
	    fputs("+B", f);
	}
}

/* More debug stuff.  Pcode buffer compare, to show what's changed. */

static INT cmpcnt = 0;		/* Count of times compare done */
static PCODE *oldcodes = NULL;
static INT omaxcode = 0, omincode = 0;

static void
shocum()
{
    fprintf(fpho, "----------- Update %3d -----------------\n", cmpcnt++);
    shocmp(fpho);
    fprintf(fpho, "----------------------------------------\n");
}

/* SHOCMP - Output a buffer comparison */
static void
shocmp(f)
FILE *f;
{
    PCODE *p, *q;
    INT i, lim;

    if (oldcodes == NULL)	/* Ensure old buffer copy exists */
	if ((oldcodes = (PCODE *)calloc(sizeof(codes), 1)) == NULL)
	    {
	    error("No memory for pcode buffer");
	    return;
	    }

    /* First check for new code prior to last stuff */
    if (mincode < omincode)
	{
	fprintf(f,"    NEW---- stuff prior to start of last check:\n");
	for (i = mincode; i < omincode; ++i)
	    {
	    fprintf(f, "    NEW ");
	    shopcod(f, &codes[i&(MAXCODE-1)], i&(MAXCODE-1));
	    }
	}
    /* Then check for old code prior to current new start */
    else if (omincode < mincode)
	{
	fprintf(f,"    OLD---- stuff flushed from start of current code:\n");
	for (i = omincode; i < mincode; ++i)
	    {
	    fprintf(f, "    OLD ");
	    shopcod(f, &oldcodes[i&(MAXCODE-1)], i&(MAXCODE-1));
	    }
	}

    /* Now compare stuff that's in both buffers */
    lim = (maxcode < omaxcode) ? maxcode : omaxcode;	/* Find smallest */
    for (i = mincode; i < lim; ++i)
	{
	p = &codes[i&(MAXCODE-1)];
	q = &oldcodes[i&(MAXCODE-1)];
	if (memcmp((char *)p, (char *)q, sizeof(PCODE)) == 0)
	    continue;			/* Compared OK, keep going */
	fprintf(f, "    ----Changed\n    OLD ");
	shopcod(f, q, i&(MAXCODE-1));
	fprintf(f, "    ----to\n    NEW ");
	shopcod(f, p, i&(MAXCODE-1));
	fprintf(f, "    -----------\n");
	}

    /* Now check for new code added after last stuff */
    if (maxcode > omaxcode)
	{
	fprintf(f,"    ADD---- New stuff:\n");
	for (i = omaxcode; i < maxcode; ++i)
	    {
	    fprintf(f, "    ADD ");
	    shopcod(f, &codes[i&(MAXCODE-1)], i&(MAXCODE-1));
	    }
	}
    /* Then check for old code still existing at end */
    else if (maxcode < omaxcode)
	{
	fprintf(f,"    OLD---- stuff flushed from end:\n");
	for (i = maxcode; i < omaxcode; ++i)
	    {
	    fprintf(f, "    OLD ");
	    shopcod(f, &oldcodes[i&(MAXCODE-1)], i&(MAXCODE-1));
	    }
	}

    /* Now update our copy in preparation for next check */
#if __STDC__
    memcpy((void *)oldcodes, (void *)codes, sizeof(codes));
#else
    memcpy((char *)oldcodes, (char *)codes, sizeof(codes));
#endif
    omincode = mincode;
    omaxcode = maxcode;
}
#endif

/* BASIC PSEUDO-CODE AUXILIARIES */

/* NEWCODE - Get a new pseudo-code record.
**	Sets "previous" to the returned pointer, for global access.
*/
static int prvskip = 0;	/* Used by newcode/flushcode to remember if skipping */

#define OVERINC	20		/* Number of ops to force out on overflow */

static PCODE *
newcode(type, op, reg)
{
    PCODE *p;
    int i;
    int skipped;

    /* fixprev(); */		/* Don't need if all other code is careful */
    if (previous)
	skipped = isskip(previous->Pop)		/* If prev was skip, */
			? PTF_SKIPPED : 0;	/* say new instr is skipped! */
    else
	skipped = prvskip;			/* No prev, ask flushcode */

    p = &codes[maxcode++ & (MAXCODE - 1)];	/* Get ptr to new instr */
    if (maxcode >= mincode + MAXCODE - 1)	/* Overflow?  If so, */
	for (i = 0; i < OVERINC; i++)		/* force some instrs out */
	    realcode(&codes[(mincode++)&(MAXCODE-1)]);

    p->Ptype = type | skipped;
    p->Pop = op;
    p->Preg = reg;
    return previous = p;		/* Set "previous" to new instr */
}

/* BEFORE(p) - Return live instruction preceding this one.
** AFTER(p)  - Return live instruction succeeding this one.
*/
PCODE *
before(p)
PCODE *p;
{
    PCODE *b;

    if (p == NULL)
	return NULL;		/* make sure we have a real pseudo */
    b = &codes[mincode&(MAXCODE-1)];
    while (1)
	{
	if (p == b)
	    break;	/* start of buffer, can't back up */
	--p;				/* back before here */
	if (p < &codes[0])
	    p = &codes[MAXCODE-1]; /* wrap in circular buffer */
	if (p->Pop != P_NOP)
	    return p;	/* got a real op, return with it */
	}
    return NULL;
}

PCODE *
after(p)
PCODE *p;
{
    PCODE *b = &codes[maxcode&(MAXCODE-1)];

    if (p == NULL)
	return NULL;		/* make sure we have a real pseudo */
    while (1)
	{
	if (++p > &codes[MAXCODE-1])
	    p = &codes[0]; /* wrap */
	if (p == b)
	    break;	/* end of buffer, no more code */
	if (p->Pop != P_NOP)
	    return p;	/* got a real op, return with it */
	}
    return NULL;
}

/* SWAPPSEUDO(a,b) - swap two pseudo code locations
*/

void
swappseudo(a,b)
PCODE *a, *b;
{
    PCODE temp;

    temp = *b;		/* Copy the structure to temp place */
    *b = *a;
    *a = temp;
}

/* FIXPREV() - Make sure "previous" points to something.
**
** This should be called after a pseudo-code which might be the last
** in the buffer is P_NOPed out.  It sets previous to the new last
** instruction in the peephole buffer.
**
** Someday this might also change maxcode to save buffer space.
*/
void
fixprev(void)
{
    if (previous && previous->Pop == P_NOP)
	{
	previous = before(previous);
	--maxcode;	/* We know at least one flushed, but */
			/* not sure how far back.  1 is better than nothing. */
	}
}

/* DROPINSTR(p) - Flush pseudo-code instruction (make it a NOP)
** FLSPREV() - Flush instruction that "previous" points to.
*/
void
dropinstr(p)
PCODE *p;
{
    if (p)
	{
	p->Pop = P_NOP;
	fixprev();	/* Fix up in case "previous" is now (or was) a NOP */
	}
}
static void
flsprev(void)
{
    dropinstr(previous);
}

/* FLUSHCODE() - Flush peephole buffer (emit everything)
*/
void
flushcode(void)
{
    if (mincode < maxcode)
	{
	prvskip = (previous && isskip(previous->Pop))	/* If prev was skip, */
			? PTF_SKIPPED : 0;	/* remember fact for newcode */

	do
	    realcode(&codes[(mincode++)&(MAXCODE-1)]);
	while (mincode < maxcode)
	    ;

#if DEBUG_KCC		/* 5/91 KCC size */
	if (debpho)
	    {
	    fprintf(fpho,"FLUSHCODE:\n");
	    shocum();		/* Show stuff forced out. */
	    }
#endif
	}
    previous = NULL;
}

/* CODCREG - Change register.

⌨️ 快捷键说明

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