summaryrefslogtreecommitdiff
path: root/simple-reg.c
diff options
context:
space:
mode:
authorSøren Sandmann Pedersen <ssp@redhat.com>2012-11-26 04:58:25 -0500
committerSøren Sandmann Pedersen <ssp@redhat.com>2012-11-26 04:58:25 -0500
commitb479afb4103e81b2bcfc987aa5ea5ad2506e4988 (patch)
tree0e9789b314a05d2f303b40cc8314cd79e76857a7 /simple-reg.c
parent634e04a96a468e03b77f8fe833aaabd9552fc06d (diff)
zombie registers
Diffstat (limited to 'simple-reg.c')
-rw-r--r--simple-reg.c84
1 files changed, 56 insertions, 28 deletions
diff --git a/simple-reg.c b/simple-reg.c
index 129b5ba..f8e657d 100644
--- a/simple-reg.c
+++ b/simple-reg.c
@@ -51,6 +51,11 @@ reg_context_init_internal (reg_context_t *ctx,
case SPILLABLE:
if (preserved[i])
{
+ /* Preserving a SPILLABLE register is nonsensical
+ * because SPILLABLE means the register _never_
+ * were in use by the parent, and therefore
+ * can't have a meaningful value.
+ */
fprintf (stderr,
"Asking to preserve a register that "
"was previously spilled");
@@ -69,7 +74,20 @@ reg_context_init_internal (reg_context_t *ctx,
case CLOBBERED:
case UNUSED:
- ctx->info[i].state = UNUSED;
+ if (preserved[i])
+ {
+ /* Preserving an UNUSED or CLOBBERED
+ * register is not necessarily nonsensical.
+ * The user may know that the register in
+ * question was recently freed and not
+ * overwritten since.
+ */
+ ctx->info[i].state = IN_USE;
+ }
+ else
+ {
+ ctx->info[i].state = UNUSED;
+ }
break;
}
}
@@ -77,6 +95,18 @@ reg_context_init_internal (reg_context_t *ctx,
}
void
+reg_alloc_init (reg_alloc_t * allocator,
+ const reg_pool_t *registers,
+ stack_man_t * stack_man,
+ reg_context_t * initial_context)
+{
+ allocator->registers = registers;
+ allocator->stack_man = stack_man;
+
+ reg_context_init_internal (initial_context, NULL, allocator, NULL);
+}
+
+void
reg_context_init (reg_context_t *ctx, reg_context_t *parent,
int n_preserved, ...)
{
@@ -98,18 +128,6 @@ reg_context_init (reg_context_t *ctx, reg_context_t *parent,
reg_context_init_internal (ctx, parent, parent->allocator, preserved);
}
-void
-reg_alloc_init (reg_alloc_t * allocator,
- const reg_pool_t *registers,
- stack_man_t * stack_man,
- reg_context_t * initial_context)
-{
- allocator->registers = registers;
- allocator->stack_man = stack_man;
-
- reg_context_init_internal (initial_context, NULL, allocator, NULL);
-}
-
op_t
reg_context_alloc (reg_context_t *ctx, fragment_t *frag)
{
@@ -168,6 +186,11 @@ reg_context_alloc (reg_context_t *ctx, fragment_t *frag)
return (op_t)-1;
}
+/* When a register is freed, it doesn't become invalid
+ * until next time a register is allocated. A register
+ * known to be free-but-valid can be resurrected by
+ * listing it in a call to reg_context_init().
+ */
void
reg_context_free (reg_context_t *ctx, op_t op)
{
@@ -181,22 +204,24 @@ reg_context_free (reg_context_t *ctx, op_t op)
info->state = CLOBBERED;
break;
+ case IN_USE:
+ info->state = UNUSED;
+ break;
+
case SPILLABLE:
case CLOBBERED:
case UNUSED:
abort();
break;
-
- case IN_USE:
- info->state = UNUSED;
- break;
}
}
/* Frees all registers allocated, except those listed, which
- * become allocated in the parent allocator.
+ * are reallocated in the parent allocator. Note that the
+ * list is of pointers to op_t's. That's because the reallocation
+ * may case the variables to move to other registers
*
- * If it is not possible to allocate all preserved registers,
+ * If it is not possible to reallocate all preserved registers,
* FALSE is returned.
*/
bool_t
@@ -240,7 +265,8 @@ reg_context_fini (reg_context_t *ctx, fragment_t *frag,
case CLOBBERED:
if (preserved[i])
{
- fprintf (stderr, "Trying to preserve an unallocated register\n");
+ fprintf (
+ stderr, "Attempted to preserve an unallocated register\n");
abort();
}
if (info->state == CLOBBERED)
@@ -268,7 +294,7 @@ reg_context_fini (reg_context_t *ctx, fragment_t *frag,
if (preserved[i])
{
/* This is the complicated case. We have to preserve the
- * register, but our parent needs it too. That means
+ * register, but the parent needs it too. That means
* it must be allocated somewhere else.
*
* We will deal with this in a separate pass.
@@ -278,9 +304,10 @@ reg_context_fini (reg_context_t *ctx, fragment_t *frag,
{
restore:
/* Restore parent's value */
- fragment_assemble (frag,
- "mov", info->reg, BASE (RSP, info->spill_offset),
- NULL);
+ fragment_assemble (
+ frag,
+ "mov", info->reg, BASE (RSP, info->spill_offset),
+ NULL);
stack_manager_free (stack_man, info->spill_offset);
}
@@ -301,10 +328,11 @@ reg_context_fini (reg_context_t *ctx, fragment_t *frag,
if (new_location == (op_t)-1)
return FALSE;
- fragment_assemble (frag,
- "mov", new_location, info->reg,
- "mov", info->reg, BASE (RSP, info->spill_offset),
- NULL);
+ fragment_assemble (
+ frag,
+ "mov", new_location, info->reg,
+ "mov", info->reg, BASE (RSP, info->spill_offset),
+ NULL);
*(locations[i]) = new_location;