diff options
author | Søren Sandmann Pedersen <ssp@redhat.com> | 2012-11-26 04:58:25 -0500 |
---|---|---|
committer | Søren Sandmann Pedersen <ssp@redhat.com> | 2012-11-26 04:58:25 -0500 |
commit | b479afb4103e81b2bcfc987aa5ea5ad2506e4988 (patch) | |
tree | 0e9789b314a05d2f303b40cc8314cd79e76857a7 /simple-reg.c | |
parent | 634e04a96a468e03b77f8fe833aaabd9552fc06d (diff) |
zombie registers
Diffstat (limited to 'simple-reg.c')
-rw-r--r-- | simple-reg.c | 84 |
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; |