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

📄 ccreg.c

📁 KCC , a good c compiler, write by Ken Harrenstien
💻 C
📖 第 1 页 / 共 2 页
字号:
    if (vr->Vrflags & VRF_SPILLED)	/* Nope, so ensure 1st reg active */
	(void) vrtoreal(vr);
    vr->Vrflags |= VRF_LOCK;		/* Lock it to that phys reg, */
    (void) vrtoreal(vr2);		/* while we ensure 2nd active too! */
    vr->Vrflags &= ~VRF_LOCK;		/* OK, can unlock 1st now */
    return vr->Vrloc;
}

/* VRISPAIR - Return true if virtual register is a doubleword pair
*/
int
vrispair(VREG *reg)
{
#if	DEBUG_KCC
    printf ("vrispair (%%%o)\n", reg);
#endif

    return (reg->Vrflags & VRF_REGPAIR) != 0;
}

/* VRUFCREG - Vreg version of ufcreg().
**	If changereg() fails to change a reg (S) to the desired # (R), it
** emits a MOVE R,S.  Often the code generator later realizes the exact
** # didn't matter and so the MOVE to R can be flushed; this routine does
** exactly that for a virtual reg by updating it to reflect the new
** real reg it's associated with (S)  once the MOVE is flushed.
**
** Currently only used by switch case jump generation to avoid
** lossage that would ensue from CCCODE's calls to ufcreg.
*/

void
vrufcreg(VREG *vr)
{
#if	DEBUG_KCC
    printf ("vrufcreg (%%%o)\n", vr);
#endif

    regis[vrtoreal(vr)] = NULL;			/* Swap in, deassign it */
    regis[vr->Vrloc = ufcreg(vr->Vrloc)] = vr;	/*Maybe flush MOVE; reassign*/
}

/* RFREE - True if real register is NOT assigned to a virtual reg.
**	A function is necessary because the outside world can't see regis[]
*/
int
rfree(int rr)
{
#if	DEBUG_KCC
    printf ("rfree (%%%o)\n", rr);
#endif

    return regis[rr] == NULL;
}

#if 0
/* RHASVAL - True if real reg is still assigned and VRF_HASVAL is set
**	indicating it contains a needed value.
**
** This isn't actually used by anything yet.
*/
int
rhasval(rr)
{
    return (regis[rr] ? regis[rr]->Vrflags&VRF_HASVAL : 0);
}
#endif




/* From this point, all routines are internal auxiliaries */

/* RRFIND - Find or create an unused real register.
**	If none exist, we spill what is likely to be the
**	earliest allocated register (since our register allocation
**	will tend to act like a stack this is a win).
*/
static int
rrfind (void)
{
    VREG *vr;
    int r;


#if	DEBUG_KCC
    puts ("rrfind ()");
#endif

    if (r_preserve)
	{
	r = r_preserve;
	r_preserve = 0;
	return r;
	}

    updrfree();			/* update regfree[] to pbuf contents */

    for (r = r_minnopreserve; r <= r_maxnopreserve; r++) /* FW 2A(47) */
	if (regfree[r])
	    return r;

    for (r = r_minnopreserve; r <= r_maxnopreserve; r++) /* FW 2A(47) */
	if (regis[r] == NULL)
	    return r;

    /* All registers in use, have to decide which one to spill to stack.
    ** The heuristic for this is to use the "oldest" thing on the register
    ** list (this is the least recently created -- not necessary the least
    ** recently used -- register)
    ** This is where VRF_LOCK has its effect of DELAYING regs from being
    ** spilled. Also, for time being, don't spill 2nd reg of a pair.
    */

    for (vr = reglist.Vrprev; vr != &reglist; vr = vr->Vrprev)
	{
	if (!(vr->Vrflags & (VRF_LOCK | VRF_REG2ND)))
	    {
	    r = vr->Vrloc;		/* Remember phys reg # */
	    vrspill(vr);		/* Spill this reg to stack! */
	    return r;
	    }
	}

    /*extremely rare to fall thru here (never happens in KCC & LIBC sources)*/

    efatal("rrfind: no regs, use keyword [register] or simplify expr");
    return -1;	/* should never get here */
}

/* UPDRFIND - auxiliary for rrfind() and rrdfind().
**	Sees which registers are in use in the peephole buffer.
** We try to avoid assigning these so that common subexpression
** elimination will have the greatest opportunity to work.
**
** Since this is merely a heuristic and since it is called intensively,
** we care more about speed than accuracy.
** In particular, we don't even bother looking at the opcode or
** addressing mode of each instruction.
*/
static void
updrfree()
{
    int r;
    PCODE *p;

#if	DEBUG_KCC
    puts ("updrfree ()");
#endif

    for (r = r_minnopreserve; r <= r_maxnopreserve; r++) /* FW 2A(47) */
	regfree[r] = (regis[r] == NULL);
    for (p = previous; p != NULL && p->Pop != P_PUSHJ; p = before(p))
	regfree[p->Preg] = 0;
}




/* RRDFIND - Find (or create) a real double-register pair, returning the
**	# of the first real reg of the pair.
**	We have to be careful not to return the very last register.
*/

static int
rrdfind (void)
{
    VREG	*vr;
    VREG	*vrok[NREGS];
    int		i;
    int		nvrs;
    int		r;


#if	DEBUG_KCC
    puts ("rrdfind ()");
#endif

    if (r_preserve)
	{
	r = r_preserve;
	r_preserve = 0;
	return r;
	}

    updrfree();			/* update regfree[] to pbuf contents */

    for (r = r_minnopreserve; r < r_maxnopreserve; r++) /* FW 2A(47) */
	{
	if (regfree[r] && regfree[r + 1])
	    return r;
#if	DEBUG_KCC
	else
	    printf ("unable to use %d and %d (not free in regfree[])\n",
		    r, r + 1);
#endif
	}

    for (r = r_minnopreserve; r < r_maxnopreserve; r++) /* FW 2A(47) */
        {
	if ((regis[r] == NULL) && (regis[r + 1] == NULL))
	    return r;
#if	DEBUG_KCC
	else
	    printf ("unable to use %d and %d (not free in regis[])\n",
		    r, r + 1);
#endif
	}

    /* None free, scan the reglist in the same way as for rrfind.  But
    ** since we need a pair, we must look for the first virtual reg or
    ** combination thereof that forms a pair.
    ** Note that for time being, we avoid spilling just the 2nd reg of a pair.
    */

    nvrs = 0;

    for (vr = reglist.Vrprev; vr != &reglist; vr = vr->Vrprev)
	{
	if (vr->Vrflags & (VRF_LOCK | VRF_REG2ND))	/* If locked, */
	    {
#if	DEBUG_KCC
	    printf ("rejecting %d because flags = %%%o\n",
		    vr->Vrloc, vr->Vrflags);
#endif
	    continue;				/* don't consider it */
	    }

	if (vr->Vrflags & VRF_REGPAIR)
	    {
	    r = vr->Vrloc;		/* Remember phys reg # */
	    vrspill(vr);		/* Spill this reg to stack! */
	    return r;
	    }

	/* Not a pair, see if forms pair with anything already seen. */

	for (i = 0; i < nvrs; ++i)
	    {
	    if (((r = vrok[i]->Vrloc) == (vr->Vrloc + 1))
		    || (r == (vr->Vrloc - 1)))
		{
		if (r > vr->Vrloc)	/* get low phys reg # */
		    r = vr->Vrloc;

		vrspill(vr);		/* Spill both to stack */
		vrspill(vrok[i]);
		return r;
		}
	    }

	/* Nope, add to array and keep looking.  Should never have more
	** than NREGS active registers, so array bounds ought to be safe.
	*/

	vrok[nvrs++] = vr;
	}

    /* extremely rare to fall thru here (never in KCC & LIBC sources)*/

#if	DEBUG_KCC
    puts ("entering last-ditch code");
#endif

    for (vr = reglist.Vrprev; vr != &reglist; vr = vr->Vrprev)
	{
	if (!vr->Vrflags)
            {
	    if (((vr->Vrloc + 1) <= r_maxnopreserve) /* FW 2A(47) */
		    && (regis[vr->Vrloc + 1] == NULL))
		{
		vrspill(vr);
		return r;
		}
	    else if (((vr->Vrloc - 1) >= r_minnopreserve)
		    && (regis[vr->Vrloc - 1] == NULL))
		{
		vrspill(vr);
		return (r - 1);
		}
	    }
	}

#if DEBUG_KCC	/* Only turn on if int_error message below gets printed */
    vrdumplists ();
#endif

    efatal("rrdfind: no regs, use keyword [register] or simplify expr");
    return -1;
}

/* VRSETRR -  Set a virtual register's location(s) to be some real reg(s).
**	If the vreg is a pair, both are set.
*/
static VREG *
vrsetrr(VREG *vr, int rr)
{
#if	DEBUG_KCC
    printf ("vrsetrr (%%%o, %%%o)\n", vr, rr);
#endif

    if (vr->Vrflags & VRF_REGPAIR)
	vr1setrr(vr->Vrmate, rr+1);
    return vr1setrr(vr, rr);
}

/* VR1SETRR -  Set a virtual register's location to be some real reg
*/
static VREG *
vr1setrr(vr, rr)
VREG *vr;
{
#if	DEBUG_KCC
    printf ("vr1setrr (%%%o, %%%o)\n", vr, rr);
#endif

    return regis[vr->Vrloc = rr] = vr;
}

/* VRUNLINK - Unlink a virtual reg from whatever list it's on.
**	If the vreg is a pair, both are unlinked.
*/
static void
vrunlink(vr)
VREG *vr;
{
#if	DEBUG_KCC
    printf ("vrunlink (%%%o)\n", vr);
#endif

    if (vr->Vrflags & VRF_REGPAIR)
	vr1unlink(vr->Vrmate);
    vr1unlink(vr);
}

/* VR1UNLINK - Remove a register from whatever list it's on.
**	This is the first half of changing from one list to another
*/
static void
vr1unlink(reg)
VREG *reg;
{
#if	DEBUG_KCC
    printf ("vr1unlink (%%%o)\n", reg);
#endif

    if (reg->Vrnext == reg)
	efatal("vr1unlink: list head");

    reg->Vrnext->Vrprev = reg->Vrprev;
    reg->Vrprev->Vrnext = reg->Vrnext;

#if DEBUG_KCC
    vrdumplists ();
#endif
}


/* VRLINK - Link a register that may be the 1st of a pair; if so, link
**	the 2nd reg as well.
*/
static VREG *
vrlink(reg, list)
VREG *reg, *list;
{
#if	DEBUG_KCC
    printf ("vrlink (%%%o, %%%o)\n", reg, list);
#endif

    if (reg->Vrflags & VRF_REGPAIR)
	vr1link(reg->Vrmate, list);	/* Is pair, link 2nd first */
    return vr1link(reg, list);
}

/* VR1LINK -  Add a register to a list
**	Used when a new vreg is created and when moving between lists
*/
static VREG *
vr1link(reg, list)
VREG *reg, *list;
{
#if	DEBUG_KCC
    printf ("vr1link (%%%o, %%%o)\n", reg, list);
#endif

    reg->Vrnext = list->Vrnext;
    list->Vrnext->Vrprev = reg;
    reg->Vrprev = list;
    list->Vrnext = reg;

#if DEBUG_KCC
    vrdumplists ();
#endif

    return reg;
}




/* VRALLOC - Allocate a new virtual register structure
** VRDALLOC - Same, but returns 1st of a double register pair, linked together.
*/
static VREG *
vralloc()
{
    VREG *rp;

#if	DEBUG_KCC
    puts ("vralloc ()");
#endif

    if (empty(&freelist))
	{
	rp = (VREG *)calloc(1, sizeof (VREG));
	if (rp == NULL)
	    efatal("Out of memory for virtual registers");
	}
    else
	{
	rp = freelist.Vrnext;
	vr1unlink(rp);
	}

    rp->Vrflags = 0;
    rp->Vrloc = 0;			/* FW 2A(41) */
    rp->Vrtype = NULL;			/* FW 2A(41) */
    rp->Vroldstk = 0;			/* FW 2A(41) */
    rp->Vrnext = NULL;			/* FW 2A(41) */
    rp->Vrprev = NULL;			/* FW 2A(41) */
    rp->Vrmate = NULL;			/* FW 2A(41) */

    return rp;
}

static VREG *
vrdalloc()
{
    VREG *vr1 = vralloc();
    VREG *vr2 = vralloc();

#if	DEBUG_KCC
    puts ("vrdalloc ()");
#endif

    vr1->Vrflags |= VRF_REGPAIR;
    vr2->Vrflags |= VRF_REG2ND;
    vr1->Vrmate = vr2;
    vr2->Vrmate = vr1;
    return vr1;
}

#if	DEBUG_KCC
static void
vrdumplists (void)
    {
    VREG	*vr;
    int		r;
    

    puts ("\nreglist:");

    for (vr = reglist.Vrprev; vr != &reglist; vr = vr->Vrprev)
	{
	printf ("@%%%o, flags: %s, loc: %%%o, typespec: %%%o, mate: %%%o\n",
		vr, vrdumpflags (vr->Vrflags), vr->Vrloc,
		vr->Vrtype->Tspec, vr->Vrmate);
	}
    
    puts ("spillist:");

    for (vr = spillist.Vrprev; vr != &spillist; vr = vr->Vrprev)
	{
	printf ("@%%%o, flags: %s, loc: %%%o, typespec: %%%o, mate: %%%o\n",
		vr, vrdumpflags (vr->Vrflags), vr->Vrloc,
		vr->Vrtype->Tspec, vr->Vrmate);
	}
    
    puts ("freelist:");

    for (vr = freelist.Vrprev; vr != &freelist; vr = vr->Vrprev)
	{
	printf ("@%%%o\n", vr);		/* the rest is silence */
	}
    
    for (r = r_minnopreserve; r <= r_maxnopreserve; r++) /* FW 2A(47) */
	{
	printf ("regfree[%d] = %s\tregis[%d] = %%%o\n",
		r, (regfree[r] ? "free" : "used"), r, regis[r]);
	}
    }

static char *
vrdumpflags (int flags)
{
    static
    char	fchars[6];

    fchars[0] = flags & VRF_SPILLED ? 'S' : ' ';
    fchars[1] = flags & VRF_REGPAIR ? '1' : ' ';
    fchars[2] = flags & VRF_REG2ND  ? '2' : ' ';
    fchars[3] = flags & VRF_LOCK    ? 'L' : ' ';
    fchars[4] = flags & VRF_SPECIAL ? 'D' : ' ';
    fchars[5] = '\0';

    return fchars;
}
#endif

⌨️ 快捷键说明

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