Code:
int alu_block( struct alu_block *mem, size_t want, int_t dir )
{
int ret = EINVAL;
uchar_t *block = NULL;
if ( mem->block )
{
if ( dir > 0 && mem->bytes.upto >= want )
return 0;
if ( dir < 0 && want > mem->bytes.upto )
return ret;
if ( !want )
{
free( mem->block );
(void)memset( mem, 0, sizeof(alu_block_t) );
return 0;
}
errno = 0;
block = realloc( mem->block, want );
ret = errno;
}
else
{
memset( mem, 0, sizeof(alu_block_t) );
if ( !want )
return 0;
if ( dir < 0 )
return ret;
errno = 0;
block = malloc( want );
ret = errno;
}
if ( block )
{
mem->block = block;
mem->bytes.upto = want;
mem->bytes.last = want - 1;
memset( &(block[mem->bytes.used]), 0, want - mem->bytes.used );
return 0;
}
return ret;
}
int alu_vec( alu_vec_t *vec, uint_t want, size_t perN, int dir )
{
int ret = 0, used = vec->qty.used;
void *dst, *src, *block;
size_t diff = 0;
if ( perN > vec->perN )
goto expand;
if ( perN < vec->perN )
goto shrink;
expand:
ret = alu_block( &(vec->mem), want * perN, dir );
if ( ret == 0 )
{
diff = perN - (vec->perN);
if ( !diff )
goto done;
/* Align nodes and initialise extra bytes */
block = vec->mem.block;
while ( used )
{
--used;
dst = block + (used * perN) + diff;
src = block + (used * vec->perN);
memmove( dst, src, vec->perN );
memset( dst - diff, 0, diff );
}
goto done;
}
goto fail;
shrink:
diff = (vec->perN) - perN;
/* Crop nodes */
block = vec->mem.block;
while ( used )
{
--used;
dst = block + (used * perN);
src = block + (used * vec->perN);
memset( src, 0, diff );
memmove( dst, src + diff, perN );
}
ret = alu_block( &(vec->mem), want * perN, dir );
if ( ret != 0 )
goto fail;
done:
vec->perN = perN;
vec->qty.upto = want;
vec->qty.last = want ? want - 1 : 0;
if ( vec->qty.used < want )
vec->qty.used = want;
vec->mem.bytes.used = vec->qty.used * perN;
fail:
return ret;
}
int alu_setup_reg( alu_t *alu, uint_t want, size_t perN )
{
int ret;
uint_t i;
alu_register_t *REG;
want = HIGHEST( want, ALU_REG_ID_NEED );
/* Needed for alu_mov() to support both register numbers and
* arbitrary addresses */
if ( want > ALU_REG_ID_LIMIT )
return ERANGE;
perN =
(sizeof(size_t) * !perN)
| (perN * !(perN % sizeof(size_t)))
| ((perN / sizeof(size_t))+1) * !!(perN % sizeof(size_t))
;
ret = alu_vec_expand( &(alu->buff), want, perN );
if ( ret != 0 )
return ret;
ret = alu_vec_expand( &(alu->_regv), want, sizeof(alu_reg_t) );
if ( ret != 0 )
return ret;
alu->regv = alu->_regv.mem.block;
for ( i = 0; i < ALU_REG_ID_NEED; ++i )
{
REG = alu->regv + i;
REG->node = i;
REG->info = ALU_INFO_VALID;
alu_set_bounds( *alu, i, 0, -1 );
}
alu_set_constants( *alu );
return 0;
}
int alu_get_reg( alu_t *alu, alu_register_t *dst, size_t size )
{
int ret;
size_t perN;
uint_t count = 0, r = count;
alu_register_t *REG;
if ( !dst )
{
nodst:
ret = EDESTADDRREQ;
alu_error( ret );
return ret;
}
(void)memset( dst, 0, sizeof(alu_register_t) );
if ( !alu )
goto nodst;
perN = HIGHEST( size, alu->buff.perN );
count = HIGHEST( ALU_REG_ID_NEED, ALU_USED( *alu ) );
if ( perN > alu->buff.perN || count > ALU_UPTO( *alu ) )
{
ret = alu_setup_reg( alu, count, perN );
if ( ret != 0 )
{
alu_error( ret );
return ret;
}
alu->buff.qty.used = count;
alu->_regv.qty.used = count;
alu->buff.mem.bytes.used = count * perN;
alu->_regv.mem.bytes.used = count * sizeof(alu_register_t);
}
for ( r = ALU_REG_ID_NEED; r < count; ++r )
{
REG = alu->regv + r;
count *= !!( REG->info & ALU_INFO_VALID );
}
count = alu->buff.qty.used;
if ( r == ALU_UPTO( *alu ) )
{
count = r + 1;
ret = alu_setup_reg( alu, count, perN );
if ( ret != 0 )
{
alu_error( ret );
return ret;
}
}
else if ( r == count )
{
++count;
}
alu->buff.qty.used = count;
alu->_regv.qty.used = count;
alu->buff.mem.bytes.used = count * perN;
alu->_regv.mem.bytes.used = count * sizeof(alu_register_t);
REG = alu->regv + r;
REG->node = r;
REG->info = ALU_INFO_VALID;
alu_set_bounds( *alu, r, 0, -1 );
(void)memset( ALU_PART( *alu, REG->node ), 0, perN );
(void)memcpy( dst, REG, sizeof( alu_register_t ) );
return 0;
}
void alu_rem_regv( alu_t alu, alu_register_t *regv, int count )
{
for ( --count; count >= 0; --count )
{
alu_rem_reg( alu, regv[count] );
}
}
int alu_get_regv( alu_t *alu, alu_register_t *regv, int count, size_t need )
{
int ret = 0, r;
for ( r = 0; r < count; ++r )
{
ret = alu_get_reg( alu, regv + r, need );
if ( ret != 0 )
{
alu_error( ret );
alu_rem_regv( *alu, regv, r );
break;
}
}
return ret;
}
From my digging I've found that somehow the register information is being wiped between attempts to allocate a register index, any ideas on what might be causing it to happen?