Trailing-Edge
-
PDP-10 Archives
-
SRI_NIC_PERM_FS_1_19910112
-
c/old/kcc/cclab.c
There are 3 other files named cclab.c in the archive. Click here to see a list.
/*
** cclab - Manage internal labels for kcc assembly output
** David Eppstein / Stanford University / 29 May 1985
*/
#include "ccsym.h"
#include "ccgen.h"
typedef struct SYMBOL *label;
char *malloc();
/*
** Get a new label to play with.
**
** The argument should be nonzero if the label will be emitted after all
** uses of it, rather than before. If it is zero, the label is emitted.
*/
label newlabel (forward)
{
label lab;
/* find a free label */
if (fllist == NULL) lab = (label) malloc (sizeof (*lab)); /* make new */
else { /* else have something in freelist */
lab = fllist; /* so use head for this label */
fllist = fllist->snext; /* and remove it from freelist */
}
/* fill it out */
lab->sclass = SILABEL; /* this is an internal label */
sprintf (lab->sname, "$%d", ++maxlabel); /* give it a name */
lab->svalue = 0; /* no uses yet */
/* emit if necessary and return */
if (!forward) glabel (lab->sname);
return lab;
}
/*
** Reference or dereference a label.
**
** The second argument is how much to add to the reference count.
** The label may be NULL or not a SILABEL; in that case nothing happens.
*/
reflabel (lab, count)
label lab;
{
if (lab != NULL && lab->sclass == SILABEL) lab->svalue += count;
}
/*
** Release a label.
**
** This should be called after the last possible reference to the label.
** It will be called automatically on emission of forward labels.
** Note sprev must not be changed (see emitlabel).
*/
static
realfreelabel (lab)
label lab;
{
lab->snext = fllist; /* chain old freelist onto it */
fllist = lab; /* it is now head of freelist */
}
/*
** Unfortunately we can't know when the last instance in the peephole
** buffer has been emitted, at least until we flush the whole thing out.
** So we keep explicitly freed labels on another list and only transfer
** them after we have emitted a new label (and thus called flushcode()).
**
** This list chains through sprev rather than snext to keep things simple.
*/
freelabel (lab)
label lab;
{
lab->sprev = flprev; /* chain old freelist onto it */
flprev = lab; /* it is now head of freelist */
}
/*
** Emit a (forward) label.
**
** Optimizations are performed and if the label still has references
** to it, it is emitted. Then realfreelabel() is called on it, and
** if we emitted it and thus cleared the peephole buffer we also free
** the list of labels queued by freelabel().
*/
emitlabel (lab)
label lab;
{
int after = hackstack (lab); /* pull ADJSP across POPJ */
optlab (lab); /* call peephole optimizer */
if (lab->svalue > 0) {
glabel (lab->sname); /* emit if necessary */
while (flprev != NULL) { /* peephole buffer is now empty */
realfreelabel (flprev); /* so free the list of labels queued */
flprev = flprev->sprev; /* by freelabel() */
} /* (nb sprev unchanged by realfree) */
}
if (after) code8 (ADJSP, SP, after); /* fix up stack */
realfreelabel (lab);
}
/*
** Emit a GOTO label
** These are not as well behaved as loop and if labels so we can't do as much.
*/
emitgoto (lab)
label lab;
{
optlab (lab); /* optimize */
glabel (lab->sname); /* and unconditionally send out */
}